[JSC] DFG should respect node's strict flag
authorysuzuki@apple.com <ysuzuki@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 9 Apr 2019 03:23:15 +0000 (03:23 +0000)
committerysuzuki@apple.com <ysuzuki@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 9 Apr 2019 03:23:15 +0000 (03:23 +0000)
https://bugs.webkit.org/show_bug.cgi?id=196617

Reviewed by Saam Barati.

JSTests:

* stress/put-by-val-direct-should-respect-strict-mode-of-inlining-codeblock.js: Added.
(shouldEqual):
(makeUnwriteableUnconfigurableObject):
(runTest):
* stress/put-dynamic-var-strict-and-sloppy.js: Added.
(shouldBe):
(shouldThrow):
(with.result):
(with.putValueStrict):
(with.putValueSloppy):

Source/JavaScriptCore:

We accidentally use codeBlock->isStrictMode() directly in DFG and FTL. But this is wrong since this CodeBlock is the top level DFG/FTL CodeBlock,
and this code does not respect the isStrictMode flag for the inlined CodeBlocks. In this patch, we start using isStrictModeFor(CodeOrigin) consistently
in DFG and FTL to get the right isStrictMode flag for the DFG node.
And we also split compilePutDynamicVar into compilePutDynamicVarStrict and compilePutDynamicVarNonStrict since (1) it is cleaner than accessing inlined
callframe in the operation function, and (2) it is aligned to the other functions like operationPutByValDirectNonStrict etc.
This bug is discovered by RandomizingFuzzerAgent by expanding the DFG coverage.

* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGConstantFoldingPhase.cpp:
(JSC::DFG::ConstantFoldingPhase::foldConstants):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupToThis):
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGPredictionPropagationPhase.cpp:
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileDoublePutByVal):
(JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray):
(JSC::DFG::SpeculativeJIT::compilePutDynamicVar):
(JSC::DFG::SpeculativeJIT::compileToThis):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compileContiguousPutByVal):
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compilePutByVal):
(JSC::FTL::DFG::LowerDFGToB3::compilePutDynamicVar):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@244067 268f45cc-cd09-0410-ab3c-d52691b4dbfc

14 files changed:
JSTests/ChangeLog
JSTests/stress/put-by-val-direct-should-respect-strict-mode-of-inlining-codeblock.js [new file with mode: 0644]
JSTests/stress/put-dynamic-var-strict-and-sloppy.js [new file with mode: 0644]
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
Source/JavaScriptCore/dfg/DFGOperations.cpp
Source/JavaScriptCore/dfg/DFGOperations.h
Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

index 0b4d69f..c653cd2 100644 (file)
@@ -1,5 +1,23 @@
 2019-04-08  Yusuke Suzuki  <ysuzuki@apple.com>
 
+        [JSC] DFG should respect node's strict flag
+        https://bugs.webkit.org/show_bug.cgi?id=196617
+
+        Reviewed by Saam Barati.
+
+        * stress/put-by-val-direct-should-respect-strict-mode-of-inlining-codeblock.js: Added.
+        (shouldEqual):
+        (makeUnwriteableUnconfigurableObject):
+        (runTest):
+        * stress/put-dynamic-var-strict-and-sloppy.js: Added.
+        (shouldBe):
+        (shouldThrow):
+        (with.result):
+        (with.putValueStrict):
+        (with.putValueSloppy):
+
+2019-04-08  Yusuke Suzuki  <ysuzuki@apple.com>
+
         [JSC] isRope jump in StringSlice should not jump over register allocations
         https://bugs.webkit.org/show_bug.cgi?id=196716
 
diff --git a/JSTests/stress/put-by-val-direct-should-respect-strict-mode-of-inlining-codeblock.js b/JSTests/stress/put-by-val-direct-should-respect-strict-mode-of-inlining-codeblock.js
new file mode 100644 (file)
index 0000000..d563215
--- /dev/null
@@ -0,0 +1,40 @@
+//@ runDefault("--useRandomizingFuzzerAgent=1", "--useConcurrentJIT=0")
+
+let totalFailed = 0;
+
+function shouldEqual(testId, iteration, actual, expected) {
+    if (actual != expected) {
+        throw new Error("Test #" + testId + ", iteration " + iteration + ", ERROR: expected \"" + expected + "\", got \"" + actual + "\"");
+    }
+}
+
+function makeUnwriteableUnconfigurableObject()
+{
+    return Object.defineProperty([], 0, {value: "frozen", writable: false, configurable: false});
+}
+
+function testArrayOf(obj)
+{
+    Array.of.call(function() { return obj; }, "no longer frozen");
+}
+
+noInline(testArrayOf);
+
+let numIterations = 10000;
+
+function runTest(testId, test, sourceMaker, expectedException) {
+    for (var i = 0; i < numIterations; i++) {
+        var exception = "No exception";
+        var obj = sourceMaker();
+
+        try {
+            test(obj);
+        } catch (e) {
+            exception = "" + e;
+            exception = exception.substr(0, 10); // Search for "TypeError:".
+        }
+        shouldEqual(testId, i, exception, expectedException);
+    }
+}
+
+runTest(1, testArrayOf, makeUnwriteableUnconfigurableObject, "TypeError:");
diff --git a/JSTests/stress/put-dynamic-var-strict-and-sloppy.js b/JSTests/stress/put-dynamic-var-strict-and-sloppy.js
new file mode 100644 (file)
index 0000000..f8f8c1b
--- /dev/null
@@ -0,0 +1,70 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function shouldThrow(func, errorMessage) {
+    var errorThrown = false;
+    var error = null;
+    try {
+        func();
+    } catch (e) {
+        errorThrown = true;
+        error = e;
+    }
+    if (!errorThrown)
+        throw new Error('not thrown');
+    if (String(error) !== errorMessage)
+        throw new Error(`bad error: ${String(error)}`);
+}
+
+(function () {
+    var flag = true;
+    var scope = {
+        resolveStrict: 20,
+        resolveSloppy: 20,
+    };
+
+    with (scope) {
+        var putValueStrict = function (text, value)
+        {
+            if (flag)
+                eval(text); // Make resolution Dynamic.
+            var result = (function () {
+                "use strict";
+                resolveStrict = value;
+            }());
+            return result;
+        };
+        noInline(putValueStrict);
+
+        var resolveSloppy = 20;
+        var putValueSloppy = function (text, value)
+        {
+            if (flag)
+                eval(text); // Make resolution Dynamic.
+            var result = (function () {
+                resolveSloppy = value;
+            }());
+            return result;
+        }
+        noInline(putValueSloppy);
+    }
+
+    putValueStrict(`var resolveStrict = 20`, i);
+    putValueSloppy(`var resolveSloppy = 20`, i);
+    flag = false;
+
+    for (var i = 0; i < 4e3; ++i) {
+        putValueStrict(``, i);
+        shouldBe(scope.resolveStrict, i);
+        putValueSloppy(``, i);
+        shouldBe(scope.resolveSloppy, i);
+    }
+    Object.freeze(scope);
+    shouldThrow(() => {
+        putValueStrict(``, 0);
+    }, `TypeError: Attempted to assign to readonly property.`);
+    putValueSloppy(``, 0);
+    shouldBe(scope.resolveSloppy, 4e3 - 1);
+}());
index d323380..b66e484 100644 (file)
@@ -1,3 +1,40 @@
+2019-04-08  Yusuke Suzuki  <ysuzuki@apple.com>
+
+        [JSC] DFG should respect node's strict flag
+        https://bugs.webkit.org/show_bug.cgi?id=196617
+
+        Reviewed by Saam Barati.
+
+        We accidentally use codeBlock->isStrictMode() directly in DFG and FTL. But this is wrong since this CodeBlock is the top level DFG/FTL CodeBlock,
+        and this code does not respect the isStrictMode flag for the inlined CodeBlocks. In this patch, we start using isStrictModeFor(CodeOrigin) consistently
+        in DFG and FTL to get the right isStrictMode flag for the DFG node.
+        And we also split compilePutDynamicVar into compilePutDynamicVarStrict and compilePutDynamicVarNonStrict since (1) it is cleaner than accessing inlined
+        callframe in the operation function, and (2) it is aligned to the other functions like operationPutByValDirectNonStrict etc.
+        This bug is discovered by RandomizingFuzzerAgent by expanding the DFG coverage.
+
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+        * dfg/DFGConstantFoldingPhase.cpp:
+        (JSC::DFG::ConstantFoldingPhase::foldConstants):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupToThis):
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGOperations.h:
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileDoublePutByVal):
+        (JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray):
+        (JSC::DFG::SpeculativeJIT::compilePutDynamicVar):
+        (JSC::DFG::SpeculativeJIT::compileToThis):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compileContiguousPutByVal):
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compilePutByVal):
+        (JSC::FTL::DFG::LowerDFGToB3::compilePutDynamicVar):
+
 2019-04-08  Don Olmstead  <don.olmstead@sony.com>
 
         [CMake][WinCairo] Separate copied headers into different directories
index e5b91bd..7ad450f 100644 (file)
@@ -2531,7 +2531,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     case ToThis: {
         AbstractValue& source = forNode(node->child1());
         AbstractValue& destination = forNode(node);
-        bool strictMode = m_graph.executableFor(node->origin.semantic)->isStrictMode();
+        bool strictMode = m_graph.isStrictModeFor(node->origin.semantic);
 
         ToThisResult result = isToThisAnIdentity(m_vm, strictMode, source);
         switch (result) {
index 452cf72..5e7e481 100644 (file)
@@ -695,7 +695,7 @@ private:
             }
 
             case ToThis: {
-                ToThisResult result = isToThisAnIdentity(m_graph.m_vm, m_graph.executableFor(node->origin.semantic)->isStrictMode(), m_state.forNode(node->child1()));
+                ToThisResult result = isToThisAnIdentity(m_graph.m_vm, m_graph.isStrictModeFor(node->origin.semantic), m_state.forNode(node->child1()));
                 if (result == ToThisResult::Identity) {
                     node->convertToIdentity();
                     changed = true;
index e62b002..c81a0cf 100644 (file)
@@ -2655,9 +2655,9 @@ private:
 
     void fixupToThis(Node* node)
     {
-        ECMAMode ecmaMode = m_graph.executableFor(node->origin.semantic)->isStrictMode() ? StrictMode : NotStrictMode;
+        bool isStrictMode = m_graph.isStrictModeFor(node->origin.semantic);
 
-        if (ecmaMode == StrictMode) {
+        if (isStrictMode) {
             if (node->child1()->shouldSpeculateBoolean()) {
                 fixEdge<BooleanUse>(node->child1());
                 node->convertToIdentity();
@@ -2710,7 +2710,7 @@ private:
         }
 
         if (node->child1()->shouldSpeculateOther()) {
-            if (ecmaMode == StrictMode) {
+            if (isStrictMode) {
                 fixEdge<OtherUse>(node->child1());
                 node->convertToIdentity();
                 return;
index dd2854b..036db07 100644 (file)
@@ -2875,10 +2875,8 @@ EncodedJSValue JIT_OPERATION operationGetDynamicVar(ExecState* exec, JSObject* s
     })));
 }
 
-void JIT_OPERATION operationPutDynamicVar(ExecState* exec, JSObject* scope, EncodedJSValue value, UniquedStringImpl* impl, unsigned getPutInfoBits)
+ALWAYS_INLINE static void putDynamicVar(ExecState* exec, VM& vm, JSObject* scope, EncodedJSValue value, UniquedStringImpl* impl, unsigned getPutInfoBits, bool isStrictMode)
 {
-    VM& vm = exec->vm();
-    NativeCallFrameTracer tracer(&vm, exec);
     auto throwScope = DECLARE_THROW_SCOPE(vm);
 
     const Identifier& ident = Identifier::fromUid(exec, impl);
@@ -2902,18 +2900,27 @@ void JIT_OPERATION operationPutDynamicVar(ExecState* exec, JSObject* scope, Enco
         return;
     }
 
-    CodeOrigin origin = exec->codeOrigin();
-    auto* inlineCallFrame = origin.inlineCallFrame();
-    bool strictMode;
-    if (inlineCallFrame)
-        strictMode = inlineCallFrame->baselineCodeBlock->isStrictMode();
-    else
-        strictMode = exec->codeBlock()->isStrictMode();
-    PutPropertySlot slot(scope, strictMode, PutPropertySlot::UnknownContext, isInitialization(getPutInfo.initializationMode()));
+    PutPropertySlot slot(scope, isStrictMode, PutPropertySlot::UnknownContext, isInitialization(getPutInfo.initializationMode()));
     throwScope.release();
     scope->methodTable(vm)->put(scope, exec, ident, JSValue::decode(value), slot);
 }
 
+void JIT_OPERATION operationPutDynamicVarStrict(ExecState* exec, JSObject* scope, EncodedJSValue value, UniquedStringImpl* impl, unsigned getPutInfoBits)
+{
+    VM& vm = exec->vm();
+    NativeCallFrameTracer tracer(&vm, exec);
+    constexpr bool isStrictMode = true;
+    return putDynamicVar(exec, vm, scope, value, impl, getPutInfoBits, isStrictMode);
+}
+
+void JIT_OPERATION operationPutDynamicVarNonStrict(ExecState* exec, JSObject* scope, EncodedJSValue value, UniquedStringImpl* impl, unsigned getPutInfoBits)
+{
+    VM& vm = exec->vm();
+    NativeCallFrameTracer tracer(&vm, exec);
+    constexpr bool isStrictMode = false;
+    return putDynamicVar(exec, vm, scope, value, impl, getPutInfoBits, isStrictMode);
+}
+
 int32_t JIT_OPERATION operationMapHash(ExecState* exec, EncodedJSValue input)
 {
     VM& vm = exec->vm();
index e76d445..949e39a 100644 (file)
@@ -268,7 +268,8 @@ JSCell* JIT_OPERATION operationCreateFixedArray(ExecState*, unsigned length);
 JSCell* JIT_OPERATION operationResolveScope(ExecState*, JSScope*, UniquedStringImpl*);
 EncodedJSValue JIT_OPERATION operationResolveScopeForHoistingFuncDeclInEval(ExecState*, JSScope*, UniquedStringImpl*);
 EncodedJSValue JIT_OPERATION operationGetDynamicVar(ExecState*, JSObject* scope, UniquedStringImpl*, unsigned);
-void JIT_OPERATION operationPutDynamicVar(ExecState*, JSObject* scope, EncodedJSValue, UniquedStringImpl*, unsigned);
+void JIT_OPERATION operationPutDynamicVarStrict(ExecState*, JSObject* scope, EncodedJSValue, UniquedStringImpl*, unsigned);
+void JIT_OPERATION operationPutDynamicVarNonStrict(ExecState*, JSObject* scope, EncodedJSValue, UniquedStringImpl*, unsigned);
 
 int64_t JIT_OPERATION operationConvertBoxedDoubleToInt52(EncodedJSValue);
 int64_t JIT_OPERATION operationConvertDoubleToInt52(double);
index 206d424..ef8d1af 100644 (file)
@@ -447,8 +447,8 @@ private:
             
         case ToThis: {
             // ToThis in methods for primitive types should speculate primitive types in strict mode.
-            ECMAMode ecmaMode = m_graph.executableFor(node->origin.semantic)->isStrictMode() ? StrictMode : NotStrictMode;
-            if (ecmaMode == StrictMode) {
+            bool isStrictMode = m_graph.isStrictModeFor(node->origin.semantic);
+            if (isStrictMode) {
                 if (node->child1()->shouldSpeculateBoolean()) {
                     changed |= mergePrediction(SpecBoolean);
                     break;
@@ -496,7 +496,7 @@ private:
             }
 
             SpeculatedType prediction = node->child1()->prediction();
-            if (ecmaMode == StrictMode)
+            if (isStrictMode)
                 changed |= mergePrediction(node->getHeapPrediction());
             else if (prediction) {
                 if (prediction & ~SpecObject) {
index 15ab44b..d6da198 100644 (file)
@@ -2122,7 +2122,7 @@ void SpeculativeJIT::compileDoublePutByVal(Node* node, SpeculateCellOperand& bas
         addSlowPathGenerator(
             slowPathCall(
                 slowCase, this,
-                m_jit.codeBlock()->isStrictMode()
+                m_jit.isStrictModeFor(node->origin.semantic)
                     ? (node->op() == PutByValDirect ? operationPutDoubleByValDirectBeyondArrayBoundsStrict : operationPutDoubleByValBeyondArrayBoundsStrict)
                     : (node->op() == PutByValDirect ? operationPutDoubleByValDirectBeyondArrayBoundsNonStrict : operationPutDoubleByValBeyondArrayBoundsNonStrict),
                 NoResult, baseReg, propertyReg, valueReg));
@@ -3153,12 +3153,12 @@ void SpeculativeJIT::compilePutByValForIntTypedArray(GPRReg base, GPRReg propert
         if (node->op() == PutByValDirect) {
             addSlowPathGenerator(slowPathCall(
                 slowPathCases, this,
-                m_jit.codeBlock()->isStrictMode() ? operationPutByValDirectCellStrict : operationPutByValDirectCellNonStrict,
+                m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValDirectCellStrict : operationPutByValDirectCellNonStrict,
                 NoResult, base, JSValueRegs(propertyTagGPR, property), JSValueRegs(valueTagGPR, valueGPR)));
         } else {
             addSlowPathGenerator(slowPathCall(
                 slowPathCases, this,
-                m_jit.codeBlock()->isStrictMode() ? operationPutByValCellStrict : operationPutByValCellNonStrict,
+                m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValCellStrict : operationPutByValCellNonStrict,
                 NoResult, base, JSValueRegs(propertyTagGPR, property), JSValueRegs(valueTagGPR, valueGPR)));
         }
 #endif
@@ -11060,7 +11060,7 @@ void SpeculativeJIT::compilePutDynamicVar(Node* node)
     JSValueRegs valueRegs = value.jsValueRegs();
 
     flushRegisters();
-    callOperation(operationPutDynamicVar, NoResult, scopeGPR, valueRegs, identifierUID(node->identifierNumber()), node->getPutInfo());
+    callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutDynamicVarStrict : operationPutDynamicVarNonStrict, NoResult, scopeGPR, valueRegs, identifierUID(node->identifierNumber()), node->getPutInfo());
     m_jit.exceptionCheck();
     noResult(node);
 }
@@ -12329,7 +12329,7 @@ void SpeculativeJIT::compileToThis(Node* node)
     m_jit.moveValueRegs(thisValueRegs, tempRegs);
 
     J_JITOperation_EJ function;
-    if (m_jit.graph().executableFor(node->origin.semantic)->isStrictMode())
+    if (m_jit.isStrictModeFor(node->origin.semantic))
         function = operationToThisStrict;
     else
         function = operationToThis;
index b585979..06f5b60 100644 (file)
@@ -1785,12 +1785,12 @@ void SpeculativeJIT::compileContiguousPutByVal(Node* node, BaseOperandType& base
         if (node->op() == PutByValDirect) {
             addSlowPathGenerator(slowPathCall(
                 slowCase, this,
-                m_jit.codeBlock()->isStrictMode() ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValDirectBeyondArrayBoundsNonStrict,
+                m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValDirectBeyondArrayBoundsNonStrict,
                 NoResult, baseReg, propertyReg, JSValueRegs(valueTag, valuePayloadReg)));
         } else {
             addSlowPathGenerator(slowPathCall(
                 slowCase, this,
-                m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
+                m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
                 NoResult, baseReg, propertyReg, JSValueRegs(valueTag, valuePayloadReg)));
         }
     }
@@ -2554,9 +2554,9 @@ void SpeculativeJIT::compile(Node* node)
             
             flushRegisters();
             if (node->op() == PutByValDirect)
-                callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByValDirectCellStrict : operationPutByValDirectCellNonStrict, baseGPR, propertyRegs, valueRegs);
+                callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValDirectCellStrict : operationPutByValDirectCellNonStrict, baseGPR, propertyRegs, valueRegs);
             else
-                callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByValCellStrict : operationPutByValCellNonStrict, baseGPR, propertyRegs, valueRegs);
+                callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValCellStrict : operationPutByValCellNonStrict, baseGPR, propertyRegs, valueRegs);
             m_jit.exceptionCheck();
             
             noResult(node);
@@ -2667,12 +2667,12 @@ void SpeculativeJIT::compile(Node* node)
                 if (node->op() == PutByValDirect) {
                     addSlowPathGenerator(slowPathCall(
                         slowCases, this,
-                        m_jit.codeBlock()->isStrictMode() ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValDirectBeyondArrayBoundsNonStrict,
+                        m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValDirectBeyondArrayBoundsNonStrict,
                         NoResult, baseReg, propertyReg, JSValueRegs(valueTagReg, valuePayloadReg)));
                 } else {
                     addSlowPathGenerator(slowPathCall(
                         slowCases, this,
-                        m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
+                        m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
                         NoResult, baseReg, propertyReg, JSValueRegs(valueTagReg, valuePayloadReg)));
                 }
             }
index 3afcc74..5dab08c 100644 (file)
@@ -2726,7 +2726,7 @@ void SpeculativeJIT::compile(Node* node)
             if (arrayMode.isOutOfBounds()) {
                 addSlowPathGenerator(slowPathCall(
                     slowCase, this,
-                    m_jit.codeBlock()->isStrictMode()
+                    m_jit.isStrictModeFor(node->origin.semantic)
                         ? (node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsStrict)
                         : (node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsNonStrict : operationPutByValBeyondArrayBoundsNonStrict),
                     NoResult, baseReg, propertyReg, valueReg));
@@ -2810,7 +2810,7 @@ void SpeculativeJIT::compile(Node* node)
             if (!slowCases.empty()) {
                 addSlowPathGenerator(slowPathCall(
                     slowCases, this,
-                    m_jit.codeBlock()->isStrictMode()
+                    m_jit.isStrictModeFor(node->origin.semantic)
                         ? (node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsStrict)
                         : (node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsNonStrict : operationPutByValBeyondArrayBoundsNonStrict),
                     NoResult, baseReg, propertyReg, valueReg));
index bc0d675..e2a4f52 100644 (file)
@@ -4565,7 +4565,7 @@ private:
                 }
                 
                 contiguousPutByValOutOfBounds(
-                    codeBlock()->isStrictMode()
+                    m_graph.isStrictModeFor(m_node->origin.semantic)
                         ? (m_node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsStrict)
                         : (m_node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsNonStrict : operationPutByValBeyondArrayBoundsNonStrict),
                     base, storage, index, value, continuation);
@@ -4591,7 +4591,7 @@ private:
                 }
                 
                 contiguousPutByValOutOfBounds(
-                    codeBlock()->isStrictMode()
+                    m_graph.isStrictModeFor(m_node->origin.semantic)
                         ? (m_node->op() == PutByValDirect ? operationPutDoubleByValDirectBeyondArrayBoundsStrict : operationPutDoubleByValBeyondArrayBoundsStrict)
                         : (m_node->op() == PutByValDirect ? operationPutDoubleByValDirectBeyondArrayBoundsNonStrict : operationPutDoubleByValBeyondArrayBoundsNonStrict),
                     base, storage, index, value, continuation);
@@ -4631,7 +4631,7 @@ private:
             LValue isOutOfBounds = m_out.aboveOrEqual(
                 index, m_out.load32NonNegative(storage, m_heaps.ArrayStorage_vectorLength));
 
-            auto slowPathFunction = codeBlock()->isStrictMode()
+            auto slowPathFunction = m_graph.isStrictModeFor(m_node->origin.semantic)
                 ? (m_node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsStrict)
                 : (m_node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsNonStrict : operationPutByValBeyondArrayBoundsNonStrict);
             if (!arrayMode.isOutOfBounds()) {
@@ -12355,7 +12355,7 @@ private:
     void compilePutDynamicVar()
     {
         UniquedStringImpl* uid = m_graph.identifiers()[m_node->identifierNumber()];
-        setJSValue(vmCall(Void, m_out.operation(operationPutDynamicVar),
+        setJSValue(vmCall(Void, m_out.operation(m_graph.isStrictModeFor(m_node->origin.semantic) ? operationPutDynamicVarStrict : operationPutDynamicVarNonStrict),
             m_callFrame, lowCell(m_node->child1()), lowJSValue(m_node->child2()), m_out.constIntPtr(uid), m_out.constInt32(m_node->getPutInfo())));
     }