]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - dfg/DFGOperations.cpp
JavaScriptCore-903.tar.gz
[apple/javascriptcore.git] / dfg / DFGOperations.cpp
diff --git a/dfg/DFGOperations.cpp b/dfg/DFGOperations.cpp
new file mode 100644 (file)
index 0000000..a310d22
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "DFGOperations.h"
+
+#if ENABLE(DFG_JIT)
+
+#include "CodeBlock.h"
+#include "Interpreter.h"
+#include "JSByteArray.h"
+#include "JSGlobalData.h"
+#include "Operations.h"
+
+namespace JSC { namespace DFG {
+
+EncodedJSValue operationConvertThis(ExecState* exec, EncodedJSValue encodedOp)
+{
+    return JSValue::encode(JSValue::decode(encodedOp).toThisObject(exec));
+}
+
+EncodedJSValue operationValueAdd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
+{
+    JSValue op1 = JSValue::decode(encodedOp1);
+    JSValue op2 = JSValue::decode(encodedOp2);
+
+    if (op1.isInt32() && op2.isInt32()) {
+        int64_t result64 = static_cast<int64_t>(op1.asInt32()) + static_cast<int64_t>(op2.asInt32());
+        int32_t result32 = static_cast<int32_t>(result64);
+        if (LIKELY(result32 == result64))
+            return JSValue::encode(jsNumber(result32));
+        return JSValue::encode(jsNumber((double)result64));
+    }
+    
+    double number1;
+    double number2;
+    if (op1.getNumber(number1) && op2.getNumber(number2))
+        return JSValue::encode(jsNumber(number1 + number2));
+
+    return JSValue::encode(jsAddSlowCase(exec, op1, op2));
+}
+
+EncodedJSValue operationGetByVal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty)
+{
+    JSValue baseValue = JSValue::decode(encodedBase);
+    JSValue property = JSValue::decode(encodedProperty);
+
+    if (LIKELY(baseValue.isCell())) {
+        JSCell* base = baseValue.asCell();
+
+        if (property.isUInt32()) {
+            JSGlobalData* globalData = &exec->globalData();
+            uint32_t i = property.asUInt32();
+
+            // FIXME: the JIT used to handle these in compiled code!
+            if (isJSArray(globalData, base) && asArray(base)->canGetIndex(i))
+                return JSValue::encode(asArray(base)->getIndex(i));
+
+            // FIXME: the JITstub used to relink this to an optimized form!
+            if (isJSString(globalData, base) && asString(base)->canGetIndex(i))
+                return JSValue::encode(asString(base)->getIndex(exec, i));
+
+            // FIXME: the JITstub used to relink this to an optimized form!
+            if (isJSByteArray(globalData, base) && asByteArray(base)->canAccessIndex(i))
+                return JSValue::encode(asByteArray(base)->getIndex(exec, i));
+
+            return JSValue::encode(baseValue.get(exec, i));
+        }
+
+        if (property.isString()) {
+            Identifier propertyName(exec, asString(property)->value(exec));
+            PropertySlot slot(base);
+            if (base->fastGetOwnPropertySlot(exec, propertyName, slot))
+                return JSValue::encode(slot.getValue(exec, propertyName));
+        }
+    }
+
+    Identifier ident(exec, property.toString(exec));
+    return JSValue::encode(baseValue.get(exec, ident));
+}
+
+EncodedJSValue operationGetById(ExecState* exec, EncodedJSValue encodedBase, Identifier* identifier)
+{
+    JSValue baseValue = JSValue::decode(encodedBase);
+    PropertySlot slot(baseValue);
+    return JSValue::encode(baseValue.get(exec, *identifier, slot));
+}
+
+template<bool strict>
+ALWAYS_INLINE static void operationPutByValInternal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
+{
+    JSGlobalData* globalData = &exec->globalData();
+
+    JSValue baseValue = JSValue::decode(encodedBase);
+    JSValue property = JSValue::decode(encodedProperty);
+    JSValue value = JSValue::decode(encodedValue);
+
+    if (LIKELY(property.isUInt32())) {
+        uint32_t i = property.asUInt32();
+
+        if (isJSArray(globalData, baseValue)) {
+            JSArray* jsArray = asArray(baseValue);
+            if (jsArray->canSetIndex(i)) {
+                jsArray->setIndex(*globalData, i, value);
+                return;
+            }
+
+            jsArray->JSArray::put(exec, i, value);
+            return;
+        }
+
+        if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
+            JSByteArray* jsByteArray = asByteArray(baseValue);
+            // FIXME: the JITstub used to relink this to an optimized form!
+            if (value.isInt32()) {
+                jsByteArray->setIndex(i, value.asInt32());
+                return;
+            }
+
+            double dValue = 0;
+            if (value.getNumber(dValue)) {
+                jsByteArray->setIndex(i, dValue);
+                return;
+            }
+        }
+
+        baseValue.put(exec, i, value);
+        return;
+    }
+
+    // Don't put to an object if toString throws an exception.
+    Identifier ident(exec, property.toString(exec));
+    if (!globalData->exception) {
+        PutPropertySlot slot(strict);
+        baseValue.put(exec, ident, value, slot);
+    }
+}
+
+void operationPutByValStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
+{
+    operationPutByValInternal<true>(exec, encodedBase, encodedProperty, encodedValue);
+}
+
+void operationPutByValNonStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
+{
+    operationPutByValInternal<false>(exec, encodedBase, encodedProperty, encodedValue);
+}
+
+void operationPutByIdStrict(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* identifier)
+{
+    PutPropertySlot slot(true);
+    JSValue::decode(encodedBase).put(exec, *identifier, JSValue::decode(encodedValue), slot);
+}
+
+void operationPutByIdNonStrict(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* identifier)
+{
+    PutPropertySlot slot(false);
+    JSValue::decode(encodedBase).put(exec, *identifier, JSValue::decode(encodedValue), slot);
+}
+
+void operationPutByIdDirectStrict(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* identifier)
+{
+    PutPropertySlot slot(true);
+    JSValue::decode(encodedBase).putDirect(exec, *identifier, JSValue::decode(encodedValue), slot);
+}
+
+void operationPutByIdDirectNonStrict(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* identifier)
+{
+    PutPropertySlot slot(false);
+    JSValue::decode(encodedBase).putDirect(exec, *identifier, JSValue::decode(encodedValue), slot);
+}
+
+bool operationCompareLess(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
+{
+    return jsLess(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
+}
+
+bool operationCompareLessEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
+{
+    return jsLessEq(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
+}
+
+bool operationCompareEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
+{
+    return JSValue::equal(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
+}
+
+bool operationCompareStrictEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
+{
+    return JSValue::strictEqual(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
+}
+
+DFGHandler lookupExceptionHandler(ExecState* exec, ReturnAddressPtr faultLocation)
+{
+    JSValue exceptionValue = exec->exception();
+    ASSERT(exceptionValue);
+
+    unsigned vPCIndex = exec->codeBlock()->bytecodeOffset(faultLocation);
+    HandlerInfo* handler = exec->globalData().interpreter->throwException(exec, exceptionValue, vPCIndex);
+
+    void* catchRoutine = handler ? handler->nativeCode.executableAddress() : (void*)ctiOpThrowNotCaught;
+    ASSERT(catchRoutine);
+    return DFGHandler(exec, catchRoutine);
+}
+
+double dfgConvertJSValueToNumber(ExecState* exec, EncodedJSValue value)
+{
+    return JSValue::decode(value).toNumber(exec);
+}
+
+int32_t dfgConvertJSValueToInt32(ExecState* exec, EncodedJSValue value)
+{
+    return JSValue::decode(value).toInt32(exec);
+}
+
+bool dfgConvertJSValueToBoolean(ExecState* exec, EncodedJSValue encodedOp)
+{
+    return JSValue::decode(encodedOp).toBoolean(exec);
+}
+
+} } // namespace JSC::DFG
+
+#endif