Title: [203142] trunk
Revision
203142
Author
[email protected]
Date
2016-07-12 17:19:15 -0700 (Tue, 12 Jul 2016)

Log Message

We should use different stack limits for stack checks from JS and host code.
https://bugs.webkit.org/show_bug.cgi?id=159442
<rdar://problem/26889188>

Reviewed by Geoffrey Garen.

Source/_javascript_Core:

We have 2 stack reservedZoneSizes:
1. Options::softReservedZoneSize()
2. Options::reservedZoneSize()

Respectively, there are used to define 2 stack limits based on these reserved
zone sizes:
1. VM::m_softStackLimit
2. VM::m_stackLimit

Options::reservedZoneSize() is the amount of the stack space that JSC guarantees
to the VM and client host code for it's use.  Host code that has well known
stack usage characteristics (i.e. doesn't call arbitrary code) may do stack
checks against the VM::m_stackLimit limit (which is computed using
Options::reservedZoneSize()).

Options::softReservedZoneSize() is a more conservative amount of reserved stack
space.  This is used to compute the VM::m_softStackLimit limit.  Any code that
is difficult to have its stack usage characterized (i.e. may call arbitrary code)
may need more stack space for its work.  Hence, these should do stack checks
against the VM::m_softStackLimit limit.

JS code and host code that may call into JS code falls into the category of code
that may call arbitrary code.  Hence, they should do stack checks against the
VM::m_softStackLimit limit.

Accordingly, the VM now provides 2 recursion check functions:

1. VM::isSafeToRecurseSoft() will do a stack check against VM::m_softStackLimit.
   In addition, for C Loop builds, VM::isSafeToRecurseSoft() will also
   check the CLoopStack against VM::m_cloopStackLimit.

2. VM::isSafeToRecurse() will do a stack check against VM::m_stackLimit.

Also added a promise-infinite-recursion-should-not-crash.js test.

* bytecompiler/BytecodeGenerator.h:
(JSC::BytecodeGenerator::emitNodeInTailPosition):
(JSC::BytecodeGenerator::emitNodeInConditionContext):
* interpreter/CLoopStack.cpp:
(JSC::CLoopStack::grow):
* interpreter/CLoopStack.h:
(JSC::CLoopStack::size):
* interpreter/CLoopStackInlines.h:
(JSC::CLoopStack::ensureCapacityFor):
(JSC::CLoopStack::isSafeToRecurse):
(JSC::CLoopStack::topOfFrameFor):
* interpreter/CachedCall.h:
(JSC::CachedCall::CachedCall):
* interpreter/Interpreter.cpp:
(JSC::Interpreter::execute):
(JSC::Interpreter::executeCall):
(JSC::Interpreter::executeConstruct):
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* parser/Parser.cpp:
* runtime/Options.h:
* runtime/ProxyObject.cpp:
(JSC::performProxyGet):
(JSC::ProxyObject::performInternalMethodGetOwnProperty):
(JSC::ProxyObject::performHasProperty):
(JSC::ProxyObject::getOwnPropertySlotCommon):
(JSC::ProxyObject::performPut):
(JSC::performProxyCall):
(JSC::performProxyConstruct):
(JSC::ProxyObject::performDelete):
(JSC::ProxyObject::performPreventExtensions):
(JSC::ProxyObject::performIsExtensible):
(JSC::ProxyObject::performDefineOwnProperty):
(JSC::ProxyObject::performGetOwnPropertyNames):
(JSC::ProxyObject::performSetPrototype):
(JSC::ProxyObject::performGetPrototype):
* runtime/RegExp.cpp:
(JSC::RegExp::finishCreation):
(JSC::RegExp::compile):
(JSC::RegExp::compileMatchOnly):
* runtime/StringRecursionChecker.h:
(JSC::StringRecursionChecker::performCheck):
* runtime/VM.cpp:
(JSC::VM::setStackPointerAtVMEntry):
(JSC::VM::updateSoftReservedZoneSize):
(JSC::preCommitStackMemory):
(JSC::VM::updateStackLimits):
(JSC::VM::updateStackLimit): Deleted.
* runtime/VM.h:
(JSC::VM::stackLimit):
(JSC::VM::softStackLimit):
(JSC::VM::addressOfSoftStackLimit):
(JSC::VM::setCLoopStackLimit):
(JSC::VM::isSafeToRecurse):
(JSC::VM::lastStackTop):
(JSC::VM::setException):
* runtime/VMInlines.h:
(JSC::VM::ensureStackCapacityFor):
(JSC::VM::isSafeToRecurseSoft):
(JSC::VM::shouldTriggerTermination):
* tests/stress/promise-infinite-recursion-should-not-crash.js: Added.
(testPromise):
(promiseFunc):
* yarr/YarrPattern.cpp:

Tools:

In http://trac.webkit.org/r203067, we limited the amount of stack that tests will
run with to keep stack overflow tests sane.  Turns out, we also need to teach the
LayoutTestRelay to pass env vars over to the iOS simulator.  This is needed in
order to keep the js/regress-139548.html test happy with this patch.

Also fixed up run_webkit_tests.py to explicitly pass an int size value for the
JSC_maxPerThreadStackUsage option.  Otherwise, it will pass a float value.

* LayoutTestRelay/LayoutTestRelay/LTRelayController.m:
(-[LTRelayController _environmentVariables]):
* Scripts/webkitpy/layout_tests/run_webkit_tests.py:
(main):

LayoutTests:

* js/regress-141098-expected.txt:
* js/script-tests/regress-141098.js:
(testEval):
(probeAndRecurse):
- Gave all the test constants names.
- Tweaked the constants to allow the test to run in the least amount of time, and
  also to behave consistently across all test configurations.
- Re-enable eager tests now that the test should finish quickly.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (203141 => 203142)


--- trunk/LayoutTests/ChangeLog	2016-07-13 00:05:25 UTC (rev 203141)
+++ trunk/LayoutTests/ChangeLog	2016-07-13 00:19:15 UTC (rev 203142)
@@ -1,3 +1,20 @@
+2016-07-12  Mark Lam  <[email protected]>
+
+        We should use different stack limits for stack checks from JS and host code.
+        https://bugs.webkit.org/show_bug.cgi?id=159442
+        <rdar://problem/26889188>
+
+        Reviewed by Geoffrey Garen.
+
+        * js/regress-141098-expected.txt:
+        * js/script-tests/regress-141098.js:
+        (testEval):
+        (probeAndRecurse):
+        - Gave all the test constants names.
+        - Tweaked the constants to allow the test to run in the least amount of time, and
+          also to behave consistently across all test configurations.
+        - Re-enable eager tests now that the test should finish quickly.
+
 2016-07-12  Dean Jackson  <[email protected]>
 
         REGRESSION (202694): Audio and Video playback controls: Cannot find a position slider to adjust playback position using VO.

Modified: trunk/LayoutTests/js/regress-141098-expected.txt (203141 => 203142)


--- trunk/LayoutTests/js/regress-141098-expected.txt	2016-07-13 00:05:25 UTC (rev 203141)
+++ trunk/LayoutTests/js/regress-141098-expected.txt	2016-07-13 00:19:15 UTC (rev 203142)
@@ -4,7 +4,9 @@
 
 
 PASS Initial setup
+Starting 1st probeAndRecurse
 PASS Exception: RangeError: Maximum call stack size exceeded.
+Starting 2nd probeAndRecurse
 PASS Exception: RangeError: Maximum call stack size exceeded.
 PASS successfullyParsed is true
 

Modified: trunk/LayoutTests/js/script-tests/regress-141098.js (203141 => 203142)


--- trunk/LayoutTests/js/script-tests/regress-141098.js	2016-07-13 00:05:25 UTC (rev 203141)
+++ trunk/LayoutTests/js/script-tests/regress-141098.js	2016-07-13 00:19:15 UTC (rev 203142)
@@ -1,4 +1,4 @@
-//@ noEagerNoNoLLIntTestsRunLayoutTest
+//@ noNoLLIntRunLayoutTest
 
 description("Regression test for https://webkit.org/b/141098. Make sure eval() properly handles running out of stack space. This test should run without crashing.");
 
@@ -5,17 +5,32 @@
 // The tiering up to test higher levels of optimization will only test the DFG
 // if run in run-jsc-stress-tests with the eager settings.
 
+// countStart, countIncrement, and numberOfFramesToBackoffFromStackOverflowPoint were
+// empirically determined to be the values that will cause StackOverflowErrors to be
+// thrown where the tests expects them. If stack frame layouts change sufficiently (e.g.
+// due to JIT changes) such that this test starts failing (due to text output
+// differences), then these values will need to be rebased.
+// Under no circumstance should this test ever crash.
+let countStart = 2;
+let countIncrement = 8;
+let numberOfFramesToBackoffFromStackOverflowPoint = 50;
+
+// backoffEverything is chosen to be -1 because a negative number will never be
+// decremented to 0, and hence, will cause probeAndRecurse() to return out of every
+// frame instead of retrying the eval test.
+let backoffEverything = -1;
+
 var lastEvalString = "";
 
 function testEval(maxIterations)
 {
     var result;
-    var count = 1;
+    var count = countStart;
 
     if (!maxIterations)
         var result = eval(lastEvalString);
     else {
-        for (var iter = 0; iter < maxIterations; count *= 4, iter++) {
+        for (var iter = 0; iter < maxIterations; count *= countIncrement, iter++) {
             var evalString = "\"dummy\".valueOf(";
 
             for (var i = 0; i < count; i++) {
@@ -35,26 +50,29 @@
     return result;
 }
 
-function probeAndRecurse(depth, reuseEvalString)
+function probeAndRecurse(reuseEvalString)
 {
-    var result;
+    var framesToBackOffFromStackOverflowPoint;
 
     // Probe stack depth
     try {
-        result = probeAndRecurse(depth+1, reuseEvalString);
+        remainingFramesToBackOff = probeAndRecurse(reuseEvalString);
 
-        if (!result) {
+        if (!remainingFramesToBackOff) {
+            // We've backed off a number of frames. Now retry the eval test to see if we
+            // still overflow.
             try {
                 testEval(1);
             } catch (e) {
-                return -49;
+                // Yikes. We still overflow. Back off some more.
+                return numberOfFramesToBackoffFromStackOverflowPoint;
             }
         } else
-            return result + 1
+            return remainingFramesToBackOff - 1
     } catch (e) {
         // We exceeded stack space, now return up the stack until we can execute a simple eval.
         // Then run an eval test to exceed stack.
-        return -49;
+        return numberOfFramesToBackoffFromStackOverflowPoint;
     }
 
     try {
@@ -63,15 +81,16 @@
         testPassed("Exception: " + e);
     }
 
-    return 1;
+    return backoffEverything;
 }
 
-// Because this test intentionlly exhausts the stack, we call testPassed() to ensure
+// Because this test intentionally exhausts the stack, we call testPassed() to ensure
 // everything we need in that path has been compiled and is available.  Otherwise we
 // might properly handle an out of stack, but run out of stack calling testPassed().
 testPassed("Initial setup");
 
-var depth = probeAndRecurse(0, false);
+debug("Starting 1st probeAndRecurse");
+probeAndRecurse(false);
 
 // Tier up the eval'ed code.
 // When run with run-jsc-stress-tests and it's agressive options, this low of a count will
@@ -79,4 +98,5 @@
 for (var i = 0; i < 200; i++)
     testEval(0);
 
-probeAndRecurse(0, true);
+debug("Starting 2nd probeAndRecurse");
+probeAndRecurse(true);

Modified: trunk/Source/_javascript_Core/ChangeLog (203141 => 203142)


--- trunk/Source/_javascript_Core/ChangeLog	2016-07-13 00:05:25 UTC (rev 203141)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-07-13 00:19:15 UTC (rev 203142)
@@ -1,3 +1,111 @@
+2016-07-12  Mark Lam  <[email protected]>
+
+        We should use different stack limits for stack checks from JS and host code.
+        https://bugs.webkit.org/show_bug.cgi?id=159442
+        <rdar://problem/26889188>
+
+        Reviewed by Geoffrey Garen.
+
+        We have 2 stack reservedZoneSizes:
+        1. Options::softReservedZoneSize()
+        2. Options::reservedZoneSize()
+
+        Respectively, there are used to define 2 stack limits based on these reserved
+        zone sizes:
+        1. VM::m_softStackLimit
+        2. VM::m_stackLimit
+
+        Options::reservedZoneSize() is the amount of the stack space that JSC guarantees
+        to the VM and client host code for it's use.  Host code that has well known
+        stack usage characteristics (i.e. doesn't call arbitrary code) may do stack
+        checks against the VM::m_stackLimit limit (which is computed using
+        Options::reservedZoneSize()).
+
+        Options::softReservedZoneSize() is a more conservative amount of reserved stack
+        space.  This is used to compute the VM::m_softStackLimit limit.  Any code that
+        is difficult to have its stack usage characterized (i.e. may call arbitrary code)
+        may need more stack space for its work.  Hence, these should do stack checks
+        against the VM::m_softStackLimit limit.
+
+        JS code and host code that may call into JS code falls into the category of code
+        that may call arbitrary code.  Hence, they should do stack checks against the
+        VM::m_softStackLimit limit.
+
+        Accordingly, the VM now provides 2 recursion check functions:
+
+        1. VM::isSafeToRecurseSoft() will do a stack check against VM::m_softStackLimit.
+           In addition, for C Loop builds, VM::isSafeToRecurseSoft() will also
+           check the CLoopStack against VM::m_cloopStackLimit.
+
+        2. VM::isSafeToRecurse() will do a stack check against VM::m_stackLimit.
+
+        Also added a promise-infinite-recursion-should-not-crash.js test.
+
+        * bytecompiler/BytecodeGenerator.h:
+        (JSC::BytecodeGenerator::emitNodeInTailPosition):
+        (JSC::BytecodeGenerator::emitNodeInConditionContext):
+        * interpreter/CLoopStack.cpp:
+        (JSC::CLoopStack::grow):
+        * interpreter/CLoopStack.h:
+        (JSC::CLoopStack::size):
+        * interpreter/CLoopStackInlines.h:
+        (JSC::CLoopStack::ensureCapacityFor):
+        (JSC::CLoopStack::isSafeToRecurse):
+        (JSC::CLoopStack::topOfFrameFor):
+        * interpreter/CachedCall.h:
+        (JSC::CachedCall::CachedCall):
+        * interpreter/Interpreter.cpp:
+        (JSC::Interpreter::execute):
+        (JSC::Interpreter::executeCall):
+        (JSC::Interpreter::executeConstruct):
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+        * parser/Parser.cpp:
+        * runtime/Options.h:
+        * runtime/ProxyObject.cpp:
+        (JSC::performProxyGet):
+        (JSC::ProxyObject::performInternalMethodGetOwnProperty):
+        (JSC::ProxyObject::performHasProperty):
+        (JSC::ProxyObject::getOwnPropertySlotCommon):
+        (JSC::ProxyObject::performPut):
+        (JSC::performProxyCall):
+        (JSC::performProxyConstruct):
+        (JSC::ProxyObject::performDelete):
+        (JSC::ProxyObject::performPreventExtensions):
+        (JSC::ProxyObject::performIsExtensible):
+        (JSC::ProxyObject::performDefineOwnProperty):
+        (JSC::ProxyObject::performGetOwnPropertyNames):
+        (JSC::ProxyObject::performSetPrototype):
+        (JSC::ProxyObject::performGetPrototype):
+        * runtime/RegExp.cpp:
+        (JSC::RegExp::finishCreation):
+        (JSC::RegExp::compile):
+        (JSC::RegExp::compileMatchOnly):
+        * runtime/StringRecursionChecker.h:
+        (JSC::StringRecursionChecker::performCheck):
+        * runtime/VM.cpp:
+        (JSC::VM::setStackPointerAtVMEntry):
+        (JSC::VM::updateSoftReservedZoneSize):
+        (JSC::preCommitStackMemory):
+        (JSC::VM::updateStackLimits):
+        (JSC::VM::updateStackLimit): Deleted.
+        * runtime/VM.h:
+        (JSC::VM::stackLimit):
+        (JSC::VM::softStackLimit):
+        (JSC::VM::addressOfSoftStackLimit):
+        (JSC::VM::setCLoopStackLimit):
+        (JSC::VM::isSafeToRecurse):
+        (JSC::VM::lastStackTop):
+        (JSC::VM::setException):
+        * runtime/VMInlines.h:
+        (JSC::VM::ensureStackCapacityFor):
+        (JSC::VM::isSafeToRecurseSoft):
+        (JSC::VM::shouldTriggerTermination):
+        * tests/stress/promise-infinite-recursion-should-not-crash.js: Added.
+        (testPromise):
+        (promiseFunc):
+        * yarr/YarrPattern.cpp:
+
 2016-07-12  Per Arne Vollan  <[email protected]>
 
         [Win] Fix for build error when trying to version stamp dll.

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (203141 => 203142)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2016-07-13 00:05:25 UTC (rev 203141)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2016-07-13 00:19:15 UTC (rev 203142)
@@ -384,7 +384,7 @@
         {
             // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary.
             ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount());
-            if (!m_vm->isSafeToRecurse()) {
+            if (UNLIKELY(!m_vm->isSafeToRecurse())) {
                 emitThrowExpressionTooDeepException();
                 return;
             }
@@ -411,7 +411,7 @@
         {
             // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary.
             ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount());
-            if (!m_vm->isSafeToRecurse())
+            if (UNLIKELY(!m_vm->isSafeToRecurse()))
                 return emitThrowExpressionTooDeepException();
             return n->emitBytecode(*this, dst);
         }
@@ -428,7 +428,7 @@
 
         void emitNodeInConditionContext(ExpressionNode* n, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
         {
-            if (!m_vm->isSafeToRecurse()) {
+            if (UNLIKELY(!m_vm->isSafeToRecurse())) {
                 emitThrowExpressionTooDeepException();
                 return;
             }

Modified: trunk/Source/_javascript_Core/interpreter/CLoopStack.cpp (203141 => 203142)


--- trunk/Source/_javascript_Core/interpreter/CLoopStack.cpp	2016-07-13 00:05:25 UTC (rev 203141)
+++ trunk/Source/_javascript_Core/interpreter/CLoopStack.cpp	2016-07-13 00:19:15 UTC (rev 203142)
@@ -88,7 +88,7 @@
     }
 
     // Compute the chunk size of additional memory to commit, and see if we
-    // have it is still within our budget. If not, we'll fail to grow and
+    // have it still within our budget. If not, we'll fail to grow and
     // return false.
     ptrdiff_t delta = reinterpret_cast<char*>(m_commitTop) - reinterpret_cast<char*>(newTopOfStackWithReservedZone);
     delta = WTF::roundUpToMultipleOf(commitSize(), delta);

Modified: trunk/Source/_javascript_Core/interpreter/CLoopStack.h (203141 => 203142)


--- trunk/Source/_javascript_Core/interpreter/CLoopStack.h	2016-07-13 00:05:25 UTC (rev 203141)
+++ trunk/Source/_javascript_Core/interpreter/CLoopStack.h	2016-07-13 00:19:15 UTC (rev 203142)
@@ -68,6 +68,7 @@
         size_t size() const { return highAddress() - lowAddress(); }
 
         void setSoftReservedZoneSize(size_t);
+        bool isSafeToRecurse() const;
 
         inline Register* topOfStack();
 

Modified: trunk/Source/_javascript_Core/interpreter/CLoopStackInlines.h (203141 => 203142)


--- trunk/Source/_javascript_Core/interpreter/CLoopStackInlines.h	2016-07-13 00:05:25 UTC (rev 203141)
+++ trunk/Source/_javascript_Core/interpreter/CLoopStackInlines.h	2016-07-13 00:19:15 UTC (rev 203142)
@@ -42,6 +42,12 @@
     return grow(newTopOfStack);
 }
 
+bool CLoopStack::isSafeToRecurse() const
+{
+    void* reservationLimit = reinterpret_cast<int8_t*>(reservationTop() + m_reservedZoneSizeInRegisters);
+    return !m_topCallFrame || (m_topCallFrame->topOfFrame() > reservationLimit);
+}
+
 inline Register* CLoopStack::topOfFrameFor(CallFrame* frame)
 {
     if (UNLIKELY(!frame))

Modified: trunk/Source/_javascript_Core/interpreter/CachedCall.h (203141 => 203142)


--- trunk/Source/_javascript_Core/interpreter/CachedCall.h	2016-07-13 00:05:25 UTC (rev 203141)
+++ trunk/Source/_javascript_Core/interpreter/CachedCall.h	2016-07-13 00:19:15 UTC (rev 203142)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2013, 2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -33,6 +33,7 @@
 #include "Interpreter.h"
 #include "ProtoCallFrame.h"
 #include "VMEntryScope.h"
+#include "VMInlines.h"
 
 namespace JSC {
     class CachedCall {
@@ -44,7 +45,7 @@
             , m_entryScope(callFrame->vm(), function->scope()->globalObject())
         {
             ASSERT(!function->isHostFunctionNonInline());
-            if (callFrame->vm().isSafeToRecurse()) {
+            if (UNLIKELY(callFrame->vm().isSafeToRecurseSoft())) {
                 m_arguments.resize(argumentCount);
                 m_closure = m_interpreter->prepareForRepeatCall(function->jsExecutable(), callFrame, &m_protoCallFrame, function, argumentCount + 1, function->scope(), m_arguments.data());
             } else

Modified: trunk/Source/_javascript_Core/interpreter/Interpreter.cpp (203141 => 203142)


--- trunk/Source/_javascript_Core/interpreter/Interpreter.cpp	2016-07-13 00:05:25 UTC (rev 203141)
+++ trunk/Source/_javascript_Core/interpreter/Interpreter.cpp	2016-07-13 00:19:15 UTC (rev 203142)
@@ -828,7 +828,7 @@
     if (vm.isCollectorBusy())
         return jsNull();
 
-    if (!vm.isSafeToRecurse())
+    if (UNLIKELY(!vm.isSafeToRecurseSoft()))
         return checkedReturn(throwStackOverflowError(callFrame));
 
     // First check if the "program" is actually just a JSON object. If so,
@@ -988,7 +988,7 @@
     }
 
     VMEntryScope entryScope(vm, globalObject);
-    if (!vm.isSafeToRecurse())
+    if (UNLIKELY(!vm.isSafeToRecurseSoft()))
         return checkedReturn(throwStackOverflowError(callFrame));
 
     if (isJSCall) {
@@ -1050,7 +1050,7 @@
     }
 
     VMEntryScope entryScope(vm, globalObject);
-    if (!vm.isSafeToRecurse())
+    if (UNLIKELY(!vm.isSafeToRecurseSoft()))
         return checkedReturn(throwStackOverflowError(callFrame));
 
     if (isJSConstruct) {
@@ -1147,7 +1147,7 @@
         return jsNull();
 
     VMEntryScope entryScope(vm, scope->globalObject());
-    if (!vm.isSafeToRecurse())
+    if (UNLIKELY(!vm.isSafeToRecurseSoft()))
         return checkedReturn(throwStackOverflowError(callFrame));        
 
     unsigned numVariables = eval->numVariables();
@@ -1248,7 +1248,7 @@
         return jsNull();
 
     VMEntryScope entryScope(vm, scope->globalObject());
-    if (!vm.isSafeToRecurse())
+    if (UNLIKELY(!vm.isSafeToRecurseSoft()))
         return checkedReturn(throwStackOverflowError(callFrame));
 
     JSObject* compileError = executable->prepareForExecution(callFrame, nullptr, scope, CodeForCall);

Modified: trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp (203141 => 203142)


--- trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2016-07-13 00:05:25 UTC (rev 203141)
+++ trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2016-07-13 00:19:15 UTC (rev 203142)
@@ -482,10 +482,9 @@
     dataLogF("Num callee registers = %u.\n", exec->codeBlock()->m_numCalleeLocals);
     dataLogF("Num vars = %u.\n", exec->codeBlock()->m_numVars);
 
-#if ENABLE(JIT)
-    dataLogF("Current end is at %p.\n", exec->vm().softStackLimit());
-#else
-    dataLogF("Current end is at %p.\n", exec->vm().cloopStackLimit());
+    dataLogF("Current OS stack end is at %p.\n", exec->vm().softStackLimit());
+#if !ENABLE(JIT)
+    dataLogF("Current C Loop stack end is at %p.\n", exec->vm().cloopStackLimit());
 #endif
 
 #endif

Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (203141 => 203142)


--- trunk/Source/_javascript_Core/parser/Parser.cpp	2016-07-13 00:05:25 UTC (rev 203141)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp	2016-07-13 00:19:15 UTC (rev 203142)
@@ -55,7 +55,7 @@
 #define consumeOrFail(tokenType, ...) do { if (!consume(tokenType)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
 #define consumeOrFailWithFlags(tokenType, flags, ...) do { if (!consume(tokenType, flags)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
 #define matchOrFail(tokenType, ...) do { if (!match(tokenType)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
-#define failIfStackOverflow() do { if (!canRecurse()) failWithStackOverflow(); } while (0)
+#define failIfStackOverflow() do { if (UNLIKELY(!canRecurse())) failWithStackOverflow(); } while (0)
 #define semanticFail(...) do { internalFailWithMessage(false, __VA_ARGS__); } while (0)
 #define semanticFailIfTrue(cond, ...) do { if (cond) internalFailWithMessage(false, __VA_ARGS__); } while (0)
 #define semanticFailIfFalse(cond, ...) do { if (!(cond)) internalFailWithMessage(false, __VA_ARGS__); } while (0)

Modified: trunk/Source/_javascript_Core/runtime/Options.h (203141 => 203142)


--- trunk/Source/_javascript_Core/runtime/Options.h	2016-07-13 00:05:25 UTC (rev 203141)
+++ trunk/Source/_javascript_Core/runtime/Options.h	2016-07-13 00:19:15 UTC (rev 203142)
@@ -113,8 +113,8 @@
     v(bool, reportMustSucceedExecutableAllocations, false, Normal, nullptr) \
     \
     v(unsigned, maxPerThreadStackUsage, 4 * MB, Normal, "Max allowed stack usage by the VM") \
-    v(unsigned, softReservedZoneSize, 128 * KB, Normal, "The amount of stack JSC usually reserves for host code.") \
-    v(unsigned, reservedZoneSize, 64 * KB, Normal, "This is the amount of stack JSC guarantees for client and VM code.") \
+    v(unsigned, softReservedZoneSize, 128 * KB, Normal, "A buffer greater than reservedZoneSize that reserves space for stringifying exceptions.") \
+    v(unsigned, reservedZoneSize, 64 * KB, Normal, "The amount of stack space we guarantee to our clients (and to interal VM code that does not call out to clients).") \
     \
     v(bool, crashIfCantAllocateJITMemory, false, Normal, nullptr) \
     v(unsigned, jitMemoryReservationSize, 0, Normal, "Set this number to change the executable allocation size in ExecutableAllocatorFixedVMPool. (In bytes.)") \

Modified: trunk/Source/_javascript_Core/runtime/ProxyObject.cpp (203141 => 203142)


--- trunk/Source/_javascript_Core/runtime/ProxyObject.cpp	2016-07-13 00:05:25 UTC (rev 203141)
+++ trunk/Source/_javascript_Core/runtime/ProxyObject.cpp	2016-07-13 00:19:15 UTC (rev 203142)
@@ -33,6 +33,7 @@
 #include "ObjectConstructor.h"
 #include "SlotVisitorInlines.h"
 #include "StructureInlines.h"
+#include "VMInlines.h"
 
 // Note that this file is compile with -fno-optimize-sibling-calls because we rely on the machine stack
 // growing larger for throwing OOM errors for when we have an effectively cyclic prototype chain.
@@ -98,7 +99,7 @@
 static JSValue performProxyGet(ExecState* exec, ProxyObject* proxyObject, JSValue receiver, PropertyName propertyName)
 {
     VM& vm = exec->vm();
-    if (UNLIKELY(!vm.isSafeToRecurse())) {
+    if (UNLIKELY(!vm.isSafeToRecurseSoft())) {
         throwStackOverflowError(exec);
         return JSValue();
     }
@@ -167,7 +168,7 @@
 bool ProxyObject::performInternalMethodGetOwnProperty(ExecState* exec, PropertyName propertyName, PropertySlot& slot)
 {
     VM& vm = exec->vm();
-    if (UNLIKELY(!vm.isSafeToRecurse())) {
+    if (UNLIKELY(!vm.isSafeToRecurseSoft())) {
         throwStackOverflowError(exec);
         return false;
     }
@@ -273,7 +274,7 @@
 bool ProxyObject::performHasProperty(ExecState* exec, PropertyName propertyName, PropertySlot& slot)
 {
     VM& vm = exec->vm();
-    if (UNLIKELY(!vm.isSafeToRecurse())) {
+    if (UNLIKELY(!vm.isSafeToRecurseSoft())) {
         throwStackOverflowError(exec);
         return false;
     }
@@ -338,7 +339,7 @@
 
 bool ProxyObject::getOwnPropertySlotCommon(ExecState* exec, PropertyName propertyName, PropertySlot& slot)
 {
-    if (UNLIKELY(!exec->vm().isSafeToRecurse())) {
+    if (UNLIKELY(!exec->vm().isSafeToRecurseSoft())) {
         throwStackOverflowError(exec);
         return false;
     }
@@ -376,7 +377,7 @@
 bool ProxyObject::performPut(ExecState* exec, JSValue putValue, JSValue thisValue, PropertyName propertyName, PerformDefaultPutFunction performDefaultPut)
 {
     VM& vm = exec->vm();
-    if (UNLIKELY(!vm.isSafeToRecurse())) {
+    if (UNLIKELY(!vm.isSafeToRecurseSoft())) {
         throwStackOverflowError(exec);
         return false;
     }
@@ -468,7 +469,7 @@
 static EncodedJSValue JSC_HOST_CALL performProxyCall(ExecState* exec)
 {
     VM& vm = exec->vm();
-    if (UNLIKELY(!vm.isSafeToRecurse())) {
+    if (UNLIKELY(!vm.isSafeToRecurseSoft())) {
         throwStackOverflowError(exec);
         return JSValue::encode(JSValue());
     }
@@ -517,7 +518,7 @@
 static EncodedJSValue JSC_HOST_CALL performProxyConstruct(ExecState* exec)
 {
     VM& vm = exec->vm();
-    if (UNLIKELY(!vm.isSafeToRecurse())) {
+    if (UNLIKELY(!vm.isSafeToRecurseSoft())) {
         throwStackOverflowError(exec);
         return JSValue::encode(JSValue());
     }
@@ -572,7 +573,7 @@
 bool ProxyObject::performDelete(ExecState* exec, PropertyName propertyName, DefaultDeleteFunction performDefaultDelete)
 {
     VM& vm = exec->vm();
-    if (UNLIKELY(!vm.isSafeToRecurse())) {
+    if (UNLIKELY(!vm.isSafeToRecurseSoft())) {
         throwStackOverflowError(exec);
         return false;
     }
@@ -648,7 +649,7 @@
 bool ProxyObject::performPreventExtensions(ExecState* exec)
 {
     VM& vm = exec->vm();
-    if (UNLIKELY(!vm.isSafeToRecurse())) {
+    if (UNLIKELY(!vm.isSafeToRecurseSoft())) {
         throwStackOverflowError(exec);
         return false;
     }
@@ -700,7 +701,7 @@
 bool ProxyObject::performIsExtensible(ExecState* exec)
 {
     VM& vm = exec->vm();
-    if (UNLIKELY(!vm.isSafeToRecurse())) {
+    if (UNLIKELY(!vm.isSafeToRecurseSoft())) {
         throwStackOverflowError(exec);
         return false;
     }
@@ -758,7 +759,7 @@
 bool ProxyObject::performDefineOwnProperty(ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool shouldThrow)
 {
     VM& vm = exec->vm();
-    if (UNLIKELY(!vm.isSafeToRecurse())) {
+    if (UNLIKELY(!vm.isSafeToRecurseSoft())) {
         throwStackOverflowError(exec);
         return false;
     }
@@ -855,7 +856,7 @@
 void ProxyObject::performGetOwnPropertyNames(ExecState* exec, PropertyNameArray& trapResult, EnumerationMode enumerationMode)
 {
     VM& vm = exec->vm();
-    if (UNLIKELY(!vm.isSafeToRecurse())) {
+    if (UNLIKELY(!vm.isSafeToRecurseSoft())) {
         throwStackOverflowError(exec);
         return;
     }
@@ -1004,7 +1005,7 @@
     ASSERT(prototype.isObject() || prototype.isNull());
 
     VM& vm = exec->vm();
-    if (UNLIKELY(!vm.isSafeToRecurse())) {
+    if (UNLIKELY(!vm.isSafeToRecurseSoft())) {
         throwStackOverflowError(exec);
         return false;
     }
@@ -1068,7 +1069,7 @@
 JSValue ProxyObject::performGetPrototype(ExecState* exec)
 {
     VM& vm = exec->vm();
-    if (UNLIKELY(!vm.isSafeToRecurse())) {
+    if (UNLIKELY(!vm.isSafeToRecurseSoft())) {
         throwStackOverflowError(exec);
         return JSValue();
     }

Modified: trunk/Source/_javascript_Core/runtime/RegExp.cpp (203141 => 203142)


--- trunk/Source/_javascript_Core/runtime/RegExp.cpp	2016-07-13 00:05:25 UTC (rev 203141)
+++ trunk/Source/_javascript_Core/runtime/RegExp.cpp	2016-07-13 00:19:15 UTC (rev 203142)
@@ -222,7 +222,7 @@
 void RegExp::finishCreation(VM& vm)
 {
     Base::finishCreation(vm);
-    Yarr::YarrPattern pattern(m_patternString, m_flags, &m_constructionError, vm.softStackLimit());
+    Yarr::YarrPattern pattern(m_patternString, m_flags, &m_constructionError, vm.stackLimit());
     if (m_constructionError)
         m_state = ParseError;
     else
@@ -264,7 +264,7 @@
 {
     ConcurrentJITLocker locker(m_lock);
     
-    Yarr::YarrPattern pattern(m_patternString, m_flags, &m_constructionError, vm->softStackLimit());
+    Yarr::YarrPattern pattern(m_patternString, m_flags, &m_constructionError, vm->stackLimit());
     if (m_constructionError) {
         RELEASE_ASSERT_NOT_REACHED();
 #if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE)
@@ -317,7 +317,7 @@
 {
     ConcurrentJITLocker locker(m_lock);
     
-    Yarr::YarrPattern pattern(m_patternString, m_flags, &m_constructionError, vm->softStackLimit());
+    Yarr::YarrPattern pattern(m_patternString, m_flags, &m_constructionError, vm->stackLimit());
     if (m_constructionError) {
         RELEASE_ASSERT_NOT_REACHED();
 #if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE)

Modified: trunk/Source/_javascript_Core/runtime/StringRecursionChecker.h (203141 => 203142)


--- trunk/Source/_javascript_Core/runtime/StringRecursionChecker.h	2016-07-13 00:05:25 UTC (rev 203141)
+++ trunk/Source/_javascript_Core/runtime/StringRecursionChecker.h	2016-07-13 00:19:15 UTC (rev 203142)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2011 Apple Inc. All rights reserved.
+ *  Copyright (C) 2011, 2016 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -21,6 +21,7 @@
 #define StringRecursionChecker_h
 
 #include "Interpreter.h"
+#include "VMInlines.h"
 #include <wtf/StackStats.h>
 #include <wtf/WTFThreadData.h>
 
@@ -50,7 +51,7 @@
 inline JSValue StringRecursionChecker::performCheck()
 {
     VM& vm = m_exec->vm();
-    if (!vm.isSafeToRecurse())
+    if (UNLIKELY(!vm.isSafeToRecurseSoft()))
         return throwStackOverflowError();
 
     bool alreadyVisited = false;

Modified: trunk/Source/_javascript_Core/runtime/VM.cpp (203141 => 203142)


--- trunk/Source/_javascript_Core/runtime/VM.cpp	2016-07-13 00:05:25 UTC (rev 203141)
+++ trunk/Source/_javascript_Core/runtime/VM.cpp	2016-07-13 00:19:15 UTC (rev 203142)
@@ -610,7 +610,7 @@
 void VM::setStackPointerAtVMEntry(void* sp)
 {
     m_stackPointerAtVMEntry = sp;
-    updateStackLimit();
+    updateStackLimits();
 }
 
 size_t VM::updateSoftReservedZoneSize(size_t softReservedZoneSize)
@@ -621,7 +621,7 @@
     interpreter->cloopStack().setSoftReservedZoneSize(softReservedZoneSize);
 #endif
 
-    updateStackLimit();
+    updateStackLimits();
 
     return oldSoftReservedZoneSize;
 }
@@ -651,21 +651,32 @@
 }
 #endif
 
-inline void VM::updateStackLimit()
+inline void VM::updateStackLimits()
 {
 #if PLATFORM(WIN)
     void* lastSoftStackLimit = m_softStackLimit;
 #endif
 
+    size_t reservedZoneSize = Options::reservedZoneSize();
     if (m_stackPointerAtVMEntry) {
         ASSERT(wtfThreadData().stack().isGrowingDownward());
         char* startOfStack = reinterpret_cast<char*>(m_stackPointerAtVMEntry);
         m_softStackLimit = wtfThreadData().stack().recursionLimit(startOfStack, Options::maxPerThreadStackUsage(), m_currentSoftReservedZoneSize);
+        m_stackLimit = wtfThreadData().stack().recursionLimit(startOfStack, Options::maxPerThreadStackUsage(), reservedZoneSize);
     } else {
         m_softStackLimit = wtfThreadData().stack().recursionLimit(m_currentSoftReservedZoneSize);
+        m_stackLimit = wtfThreadData().stack().recursionLimit(reservedZoneSize);
     }
 
 #if PLATFORM(WIN)
+    // We only need to precommit stack memory dictated by the VM::m_softStackLimit limit.
+    // This is because VM::m_softStackLimit applies to stack usage by LLINT asm or JIT
+    // generated code which can allocate stack space that the C++ compiler does not know
+    // about. As such, we have to precommit that stack memory manually.
+    //
+    // In contrast, we do not need to worry about VM::m_stackLimit because that limit is
+    // used exclusively by C++ code, and the C++ compiler will automatically commit the
+    // needed stack pages.
     if (lastSoftStackLimit != m_softStackLimit)
         preCommitStackMemory(m_softStackLimit);
 #endif

Modified: trunk/Source/_javascript_Core/runtime/VM.h (203141 => 203142)


--- trunk/Source/_javascript_Core/runtime/VM.h	2016-07-13 00:05:25 UTC (rev 203141)
+++ trunk/Source/_javascript_Core/runtime/VM.h	2016-07-13 00:19:15 UTC (rev 203142)
@@ -465,6 +465,7 @@
     static size_t committedStackByteCount();
     inline bool ensureStackCapacityFor(Register* newTopOfStack);
 
+    void* stackLimit() { return m_stackLimit; }
     void* softStackLimit() { return m_softStackLimit; }
     void** addressOfSoftStackLimit() { return &m_softStackLimit; }
 #if !ENABLE(JIT)
@@ -472,12 +473,10 @@
     void setCLoopStackLimit(void* limit) { m_cloopStackLimit = limit; }
 #endif
 
-    bool isSafeToRecurse(size_t neededStackInBytes = 0) const
+    inline bool isSafeToRecurseSoft() const;
+    bool isSafeToRecurse() const
     {
-        ASSERT(wtfThreadData().stack().isGrowingDownward());
-        int8_t* curr = reinterpret_cast<int8_t*>(&curr);
-        int8_t* limit = reinterpret_cast<int8_t*>(m_softStackLimit);
-        return curr >= limit && static_cast<size_t>(curr - limit) >= neededStackInBytes;
+        return isSafeToRecurse(m_stackLimit);
     }
 
     void* lastStackTop() { return m_lastStackTop; }
@@ -626,8 +625,15 @@
     static VM*& sharedInstanceInternal();
     void createNativeThunk();
 
-    void updateStackLimit();
+    void updateStackLimits();
 
+    bool isSafeToRecurse(void* stackLimit) const
+    {
+        ASSERT(wtfThreadData().stack().isGrowingDownward());
+        void* curr = reinterpret_cast<void*>(&curr);
+        return curr >= stackLimit;
+    }
+
     void setException(Exception* exception)
     {
         m_exception = exception;
@@ -649,6 +655,7 @@
 
     void* m_stackPointerAtVMEntry;
     size_t m_currentSoftReservedZoneSize;
+    void* m_stackLimit { nullptr };
     void* m_softStackLimit { nullptr };
 #if !ENABLE(JIT)
     void* m_cloopStackLimit { nullptr };

Modified: trunk/Source/_javascript_Core/runtime/VMInlines.h (203141 => 203142)


--- trunk/Source/_javascript_Core/runtime/VMInlines.h	2016-07-13 00:05:25 UTC (rev 203141)
+++ trunk/Source/_javascript_Core/runtime/VMInlines.h	2016-07-13 00:19:15 UTC (rev 203142)
@@ -47,6 +47,15 @@
     
 }
 
+bool VM::isSafeToRecurseSoft() const
+{
+    bool safe = isSafeToRecurse(m_softStackLimit);
+#if !ENABLE(JIT)
+    safe = safe && interpreter->cloopStack().isSafeToRecurse();
+#endif
+    return safe;
+}
+
 bool VM::shouldTriggerTermination(ExecState* exec)
 {
     if (!watchdog())

Added: trunk/Source/_javascript_Core/tests/stress/promise-infinite-recursion-should-not-crash.js (0 => 203142)


--- trunk/Source/_javascript_Core/tests/stress/promise-infinite-recursion-should-not-crash.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/promise-infinite-recursion-should-not-crash.js	2016-07-13 00:19:15 UTC (rev 203142)
@@ -0,0 +1,14 @@
+//@ defaultNoSamplingProfilerRun
+
+// This should not crash
+var boundFunc;
+
+function testPromise(func) {
+    var p1 = new Promise(func);
+}
+function promiseFunc(resolve, reject) {
+    boundFunc();
+}
+
+boundFunc = testPromise.bind(null, promiseFunc);
+boundFunc();

Modified: trunk/Source/_javascript_Core/yarr/YarrPattern.cpp (203141 => 203142)


--- trunk/Source/_javascript_Core/yarr/YarrPattern.cpp	2016-07-13 00:05:25 UTC (rev 203141)
+++ trunk/Source/_javascript_Core/yarr/YarrPattern.cpp	2016-07-13 00:19:15 UTC (rev 203142)
@@ -580,7 +580,7 @@
 
     bool setupAlternativeOffsets(PatternAlternative* alternative, unsigned currentCallFrameSize, unsigned initialInputPosition, unsigned& newCallFrameSize) WARN_UNUSED_RETURN
     {
-        if (!isSafeToRecurse())
+        if (UNLIKELY(!isSafeToRecurse()))
             return false;
 
         alternative->m_hasFixedSize = true;
@@ -682,7 +682,7 @@
 
     bool setupDisjunctionOffsets(PatternDisjunction* disjunction, unsigned initialCallFrameSize, unsigned initialInputPosition, unsigned& callFrameSize) WARN_UNUSED_RETURN
     {
-        if (!isSafeToRecurse())
+        if (UNLIKELY(!isSafeToRecurse()))
             return false;
 
         if ((disjunction != m_pattern.m_body) && (disjunction->m_alternatives.size() > 1))

Modified: trunk/Tools/ChangeLog (203141 => 203142)


--- trunk/Tools/ChangeLog	2016-07-13 00:05:25 UTC (rev 203141)
+++ trunk/Tools/ChangeLog	2016-07-13 00:19:15 UTC (rev 203142)
@@ -1,3 +1,24 @@
+2016-07-12  Mark Lam  <[email protected]>
+
+        We should use different stack limits for stack checks from JS and host code.
+        https://bugs.webkit.org/show_bug.cgi?id=159442
+        <rdar://problem/26889188>
+
+        Reviewed by Geoffrey Garen.
+
+        In http://trac.webkit.org/r203067, we limited the amount of stack that tests will
+        run with to keep stack overflow tests sane.  Turns out, we also need to teach the
+        LayoutTestRelay to pass env vars over to the iOS simulator.  This is needed in
+        order to keep the js/regress-139548.html test happy with this patch.
+
+        Also fixed up run_webkit_tests.py to explicitly pass an int size value for the
+        JSC_maxPerThreadStackUsage option.  Otherwise, it will pass a float value.
+
+        * LayoutTestRelay/LayoutTestRelay/LTRelayController.m:
+        (-[LTRelayController _environmentVariables]):
+        * Scripts/webkitpy/layout_tests/run_webkit_tests.py:
+        (main):
+
 2016-07-12  Filip Pizlo  <[email protected]>
 
         platformUserPreferredLanguages on Mac should not try to put the region into the language

Modified: trunk/Tools/LayoutTestRelay/LayoutTestRelay/LTRelayController.m (203141 => 203142)


--- trunk/Tools/LayoutTestRelay/LayoutTestRelay/LTRelayController.m	2016-07-13 00:05:25 UTC (rev 203141)
+++ trunk/Tools/LayoutTestRelay/LayoutTestRelay/LTRelayController.m	2016-07-13 00:19:15 UTC (rev 203142)
@@ -28,6 +28,7 @@
 #import "CoreSimulatorSPI.h"
 #import "LTPipeRelay.h"
 #import <AppKit/AppKit.h>
+#import <crt_externs.h>
 
 @interface LTRelayController ()
 @property (readonly, strong) dispatch_source_t standardInputDispatchSource;
@@ -193,6 +194,33 @@
             }
         }
 
+        for (char** envp = *_NSGetEnviron(); *envp; envp++) {
+            const char* env = *envp;
+            if (!strncmp("JSC_", env, 4) || !strncmp("__XPC_JSC_", env, 10)) {
+                const char* equal = strchr(env, '=');
+                if (!equal) {
+                    NSLog(@"Missing '=' in env var '%s'", env);
+                    continue;
+                }
+
+                static const size_t maxKeyLength = 256;
+                size_t keyLength = equal - env;
+                if (keyLength >= maxKeyLength) {
+                    NSLog(@"Env var '%s' is too long", env);
+                    continue;
+                }
+
+                char key[maxKeyLength];
+                strncpy(key, env, keyLength);
+                key[keyLength] = '\0';
+                const char* value = equal + 1;
+
+                NSString *nsKey = [NSString stringWithUTF8String:key];
+                NSString *nsValue = [NSString stringWithUTF8String:value];
+                [dictionary setObject:nsValue forKey:nsKey];
+            }
+        }
+
         environmentVariables = [dictionary copy];
     });
 

Modified: trunk/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py (203141 => 203142)


--- trunk/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py	2016-07-13 00:05:25 UTC (rev 203141)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py	2016-07-13 00:19:15 UTC (rev 203142)
@@ -75,7 +75,7 @@
 
     try:
         # Force all tests to use a smaller stack so that stack overflow tests can run faster.
-        stackSizeInBytes = 1.5 * 1024 * 1024
+        stackSizeInBytes = int(1.5 * 1024 * 1024)
         options.additional_env_var.append('JSC_maxPerThreadStackUsage=' + str(stackSizeInBytes))
         options.additional_env_var.append('__XPC_JSC_maxPerThreadStackUsage=' + str(stackSizeInBytes))
         run_details = run(port, options, args, stderr)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to