We should use different stack limits for stack checks from JS and host code.
authormark.lam@apple.com <mark.lam@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 13 Jul 2016 00:19:15 +0000 (00:19 +0000)
committermark.lam@apple.com <mark.lam@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 13 Jul 2016 00:19:15 +0000 (00:19 +0000)
commitfbfaf6b96201925882c038e0875bb6528dfa4956
treee5195e466ff25fc27ce199564cf154fd2814b66d
parenta33ebe7128fe28d8d0043e26b093ebe076c561a0
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/JavaScriptCore:

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.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@203142 268f45cc-cd09-0410-ab3c-d52691b4dbfc
24 files changed:
LayoutTests/ChangeLog
LayoutTests/js/regress-141098-expected.txt
LayoutTests/js/script-tests/regress-141098.js
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
Source/JavaScriptCore/interpreter/CLoopStack.cpp
Source/JavaScriptCore/interpreter/CLoopStack.h
Source/JavaScriptCore/interpreter/CLoopStackInlines.h
Source/JavaScriptCore/interpreter/CachedCall.h
Source/JavaScriptCore/interpreter/Interpreter.cpp
Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
Source/JavaScriptCore/parser/Parser.cpp
Source/JavaScriptCore/runtime/Options.h
Source/JavaScriptCore/runtime/ProxyObject.cpp
Source/JavaScriptCore/runtime/RegExp.cpp
Source/JavaScriptCore/runtime/StringRecursionChecker.h
Source/JavaScriptCore/runtime/VM.cpp
Source/JavaScriptCore/runtime/VM.h
Source/JavaScriptCore/runtime/VMInlines.h
Source/JavaScriptCore/tests/stress/promise-infinite-recursion-should-not-crash.js [new file with mode: 0644]
Source/JavaScriptCore/yarr/YarrPattern.cpp
Tools/ChangeLog
Tools/LayoutTestRelay/LayoutTestRelay/LTRelayController.m
Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py