Changeset 160967 in webkit


Ignore:
Timestamp:
Dec 21, 2013, 11:25:09 AM (11 years ago)
Author:
mark.lam@apple.com
Message:

CStack: Update the VMEntryScope's stack limit when the VM enters/exits ErrorMode.
https://bugs.webkit.org/show_bug.cgi?id=126009.

Not yet reviewed.

  1. Renamed JSStack::updateStackLimit() to setStackLimit() because that is what it actually does. We're going to repurpose the updateStackLimit name for another function.
  1. Fixed a bug in setStackLimit() where setJSStackLimit() was called with the value of newEnd which points past the end of the stack. The fix is to add 1 to point at the last slot at top of the stack. This is what is the users of the jsStackLimit value expects.
  1. Introduce the new JSStack::updateStackLimit() which is responsible for re-setting the current stack limit. updateStackLimit() will handle both cases of the JS stack being on the C stack or a separate stack.

For the C stack case, JStack::updateStackLimit() will check if a
VMEntryScope has been installed in the VM. If so, it will tell the
VMEntryScope to do the real work of updating the stack limit. The
VMEntryScope will take into account whether the VM's Interpreter is
in an error handling mode or not when determining the amount of host
zone space to reserve on the stack for computing the stack limit value.

  1. Interpreter::ErrorHandlingMode now calls JSStack::updateStackLimit whenever it enters / exit error handling mode. This allows the stack limit to change with the error mode change.
  1. A lot of places in the code were throwing StackOverflowErrors by creating and throwing the error themselves instead of using the throwStackOverflowError() helper function. As a result, the VM never got the chance to enter error mode. This is a bug and is now fixed by making all these sites use throwStackOverflowError() instead.

For sites that can't use throwStackOverflowError(), I updated them to
instantiate Interpreter::ErrorHandlingMode to set the error mode
appropriately.

  1. Made JSStack::enableErrorStackReserve() and disableErrorStackReserve() private. They are no longer called from outside of JSStack.
  • interpreter/Interpreter.cpp:

(JSC::Interpreter::ErrorHandlingMode::ErrorHandlingMode):
(JSC::Interpreter::ErrorHandlingMode::~ErrorHandlingMode):
(JSC::sizeFrameForVarargs):

  • interpreter/JSStack.cpp:

(JSC::JSStack::JSStack):
(JSC::JSStack::growSlowCase):
(JSC::JSStack::updateStackLimit):

  • interpreter/JSStack.h:
  • interpreter/JSStackInlines.h:

(JSC::JSStack::shrink):
(JSC::JSStack::setStackLimit):

  • jit/JITOperations.cpp:
  • llint/LLIntSlowPaths.cpp:

(JSC::LLInt::LLINT_SLOW_PATH_DECL):

  • parser/ParserError.h:

(JSC::ParserError::toErrorObject):

  • runtime/CommonSlowPaths.cpp:

(JSC::SLOW_PATH_DECL):

  • runtime/JSONObject.cpp:

(JSC::Walker::walk):

  • runtime/StringRecursionChecker.cpp:

(JSC::StringRecursionChecker::throwStackOverflowError):

  • runtime/VMEntryScope.cpp:

(JSC::VMEntryScope::VMEntryScope):
(JSC::VMEntryScope::updateStackLimit):

  • runtime/VMEntryScope.h:
Location:
branches/jsCStack/Source/JavaScriptCore
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • branches/jsCStack/Source/JavaScriptCore/ChangeLog

    r160963 r160967  
     12013-12-21  Mark Lam  <mark.lam@apple.com>
     2
     3        CStack: Update the VMEntryScope's stack limit when the VM enters/exits ErrorMode.
     4        https://bugs.webkit.org/show_bug.cgi?id=126009.
     5
     6        Not yet reviewed.
     7
     8        1. Renamed JSStack::updateStackLimit() to setStackLimit() because that
     9           is what it actually does. We're going to repurpose the updateStackLimit
     10           name for another function.
     11
     12        2. Fixed a bug in setStackLimit() where setJSStackLimit() was called with
     13           the value of newEnd which points past the end of the stack. The fix is
     14           to add 1 to point at the last slot at top of the stack. This is what is
     15           the users of the jsStackLimit value expects.
     16
     17        3. Introduce the new JSStack::updateStackLimit() which is responsible for
     18           re-setting the current stack limit. updateStackLimit() will handle both
     19           cases of the JS stack being on the C stack or a separate stack.
     20
     21           For the C stack case, JStack::updateStackLimit() will check if a
     22           VMEntryScope has been installed in the VM. If so, it will tell the
     23           VMEntryScope to do the real work of updating the stack limit. The
     24           VMEntryScope will take into account whether the VM's Interpreter is
     25           in an error handling mode or not when determining the amount of host
     26           zone space to reserve on the stack for computing the stack limit value.
     27
     28        4. Interpreter::ErrorHandlingMode now calls JSStack::updateStackLimit
     29           whenever it enters / exit error handling mode. This allows the stack
     30           limit to change with the error mode change.
     31
     32        5. A lot of places in the code were throwing StackOverflowErrors by
     33           creating and throwing the error themselves instead of using the
     34           throwStackOverflowError() helper function. As a result, the VM never
     35           got the chance to enter error mode. This is a bug and is now fixed by
     36           making all these sites use throwStackOverflowError() instead.
     37
     38           For sites that can't use throwStackOverflowError(), I updated them to
     39           instantiate Interpreter::ErrorHandlingMode to set the error mode
     40           appropriately.
     41
     42        6. Made JSStack::enableErrorStackReserve() and disableErrorStackReserve()
     43           private. They are no longer called from outside of JSStack.
     44
     45        * interpreter/Interpreter.cpp:
     46        (JSC::Interpreter::ErrorHandlingMode::ErrorHandlingMode):
     47        (JSC::Interpreter::ErrorHandlingMode::~ErrorHandlingMode):
     48        (JSC::sizeFrameForVarargs):
     49        * interpreter/JSStack.cpp:
     50        (JSC::JSStack::JSStack):
     51        (JSC::JSStack::growSlowCase):
     52        (JSC::JSStack::updateStackLimit):
     53        * interpreter/JSStack.h:
     54        * interpreter/JSStackInlines.h:
     55        (JSC::JSStack::shrink):
     56        (JSC::JSStack::setStackLimit):
     57        * jit/JITOperations.cpp:
     58        * llint/LLIntSlowPaths.cpp:
     59        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
     60        * parser/ParserError.h:
     61        (JSC::ParserError::toErrorObject):
     62        * runtime/CommonSlowPaths.cpp:
     63        (JSC::SLOW_PATH_DECL):
     64        * runtime/JSONObject.cpp:
     65        (JSC::Walker::walk):
     66        * runtime/StringRecursionChecker.cpp:
     67        (JSC::StringRecursionChecker::throwStackOverflowError):
     68        * runtime/VMEntryScope.cpp:
     69        (JSC::VMEntryScope::VMEntryScope):
     70        (JSC::VMEntryScope::updateStackLimit):
     71        * runtime/VMEntryScope.h:
     72
    1732013-12-21  Filip Pizlo  <fpizlo@apple.com>
    274
  • branches/jsCStack/Source/JavaScriptCore/interpreter/Interpreter.cpp

    r160960 r160967  
    9595    : m_interpreter(*exec->interpreter())
    9696{
    97     if (!m_interpreter.m_errorHandlingModeReentry)
    98         m_interpreter.stack().enableErrorStackReserve();
    9997    m_interpreter.m_errorHandlingModeReentry++;
     98    m_interpreter.stack().updateStackLimit();
    10099}
    101100
     
    105104    ASSERT(m_interpreter.m_errorHandlingModeReentry >= 0);
    106105    if (!m_interpreter.m_errorHandlingModeReentry)
    107         m_interpreter.stack().disableErrorStackReserve();
     106        m_interpreter.stack().updateStackLimit();
    108107}
    109108
     
    162161        CallFrame* newCallFrame = CallFrame::create(callFrame->registers() - paddedCalleeFrameOffset);
    163162        if (argumentCountIncludingThis > Arguments::MaxArguments + 1 || !stack->ensureCapacityFor(newCallFrame->registers())) {
    164             callFrame->vm().throwException(callFrame, createStackOverflowError(callFrame));
     163            throwStackOverflowError(callFrame);
    165164            return 0;
    166165        }
     
    173172        CallFrame* newCallFrame = CallFrame::create(callFrame->registers() - paddedCalleeFrameOffset);
    174173        if (!stack->ensureCapacityFor(newCallFrame->registers())) {
    175             callFrame->vm().throwException(callFrame, createStackOverflowError(callFrame));
     174            throwStackOverflowError(callFrame);
    176175            return 0;
    177176        }
     
    190189        CallFrame* newCallFrame = CallFrame::create(callFrame->registers() - paddedCalleeFrameOffset);
    191190        if (argCount > Arguments::MaxArguments || !stack->ensureCapacityFor(newCallFrame->registers())) {
    192             callFrame->vm().throwException(callFrame, createStackOverflowError(callFrame));
     191            throwStackOverflowError(callFrame);
    193192            return 0;
    194193        }
     
    202201        CallFrame* newCallFrame = CallFrame::create(callFrame->registers() - paddedCalleeFrameOffset);
    203202        if (argCount > Arguments::MaxArguments || !stack->ensureCapacityFor(newCallFrame->registers())) {
    204             callFrame->vm().throwException(callFrame, createStackOverflowError(callFrame));
     203            throwStackOverflowError(callFrame);
    205204            return 0;
    206205        }
     
    213212    CallFrame* newCallFrame = CallFrame::create(callFrame->registers() - paddedCalleeFrameOffset);
    214213    if (argCount > Arguments::MaxArguments || !stack->ensureCapacityFor(newCallFrame->registers())) {
    215         callFrame->vm().throwException(callFrame,  createStackOverflowError(callFrame));
     214        throwStackOverflowError(callFrame);
    216215        return 0;
    217216    }
  • branches/jsCStack/Source/JavaScriptCore/interpreter/JSStack.cpp

    r160824 r160967  
    3232#include "ConservativeRoots.h"
    3333#include "Interpreter.h"
     34#include "VMEntryScope.h"
    3435
    3536namespace JSC {
     
    5152
    5253    m_reservation = PageReservation::reserve(roundUpAllocationSize(capacity * sizeof(Register), commitSize), OSAllocator::JSVMStackPages);
    53     updateStackLimit(highAddress());
     54    setStackLimit(highAddress());
    5455    m_commitEnd = highAddress();
    5556   
     
    7475    // just update the end pointer and return.
    7576    if (newEnd >= m_commitEnd) {
    76         updateStackLimit(newEnd);
     77        setStackLimit(newEnd);
    7778        return true;
    7879    }
     
    9091    addToCommittedByteCount(delta);
    9192    m_commitEnd = reinterpret_cast_ptr<Register*>(reinterpret_cast<char*>(m_commitEnd) - delta);
    92     updateStackLimit(newEnd);
     93    setStackLimit(newEnd);
    9394    return true;
    9495}
     
    176177}
    177178
     179void JSStack::updateStackLimit()
     180{
     181#if ENABLE(LLINT_C_LOOP)
     182    if (m_vm.interpreter->isInErrorHandlingMode())
     183        enableErrorStackReserve();
     184    else
     185        disableErrorStackReserve();
     186#endif
     187    if (m_vm.entryScope)
     188        m_vm.entryScope->updateStackLimit();
     189}
     190
    178191} // namespace JSC
  • branches/jsCStack/Source/JavaScriptCore/interpreter/JSStack.h

    r160960 r160967  
    8484        bool ensureCapacityFor(Register* newTopOfStack);
    8585
     86        void updateStackLimit();
     87
    8688        void gatherConservativeRoots(ConservativeRoots&);
    8789        void gatherConservativeRoots(ConservativeRoots&, JITStubRoutineSet&, CodeBlockSet&);
     
    105107
    106108        bool containsAddress(Register* address) { return (lowAddress() <= address && address <= highAddress()); }
    107 
    108         void enableErrorStackReserve();
    109         void disableErrorStackReserve();
    110109
    111110#if ENABLE(DEBUG_JSSTACK)
     
    153152        void addToCommittedByteCount(long);
    154153
    155         void updateStackLimit(Register* newEnd);
     154        void setStackLimit(Register* newEnd);
     155
     156        void enableErrorStackReserve();
     157        void disableErrorStackReserve();
    156158
    157159        VM& m_vm;
  • branches/jsCStack/Source/JavaScriptCore/interpreter/JSStackInlines.h

    r160960 r160967  
    170170    if (newEnd >= m_end)
    171171        return;
    172     updateStackLimit(newEnd);
     172    setStackLimit(newEnd);
    173173    if (m_end == baseOfStack() && (m_commitEnd - baseOfStack()) >= maxExcessCapacity)
    174174        releaseExcessCapacity();
     
    183183}
    184184
    185 inline void JSStack::updateStackLimit(Register* newEnd)
     185inline void JSStack::setStackLimit(Register* newEnd)
    186186{
    187187    m_end = newEnd;
    188188#if ENABLE(LLINT_C_LOOP)
    189     m_vm.setJSStackLimit(newEnd);
     189    m_vm.setJSStackLimit(newEnd + 1);
    190190#endif
    191191}
  • branches/jsCStack/Source/JavaScriptCore/jit/JITOperations.cpp

    r160893 r160967  
    8080
    8181    NativeCallFrameTracer tracer(vm, callerFrame);
     82    Interpreter::ErrorHandlingMode mode(callerFrame);
    8283    vm->throwException(callerFrame, createStackOverflowError(callerFrame));
    8384}
     
    9394    int32_t missingArgCount = CommonSlowPaths::arityCheckFor(exec, &stack, CodeForCall);
    9495    if (missingArgCount < 0)
    95         vm->throwException(callerFrame, createStackOverflowError(callerFrame));
     96        throwStackOverflowError(callerFrame);
    9697
    9798    return missingArgCount;
     
    108109    int32_t missingArgCount = CommonSlowPaths::arityCheckFor(exec, &stack, CodeForConstruct);
    109110    if (missingArgCount < 0)
    110         vm->throwException(callerFrame, createStackOverflowError(callerFrame));
     111        throwStackOverflowError(callerFrame);
    111112
    112113    return missingArgCount;
     
    704705        JSObject* error = functionExecutable->prepareForExecution(execCallee, callee->scope(), kind);
    705706        if (error) {
    706             vm->throwException(exec, createStackOverflowError(exec));
     707            throwStackOverflowError(exec);
    707708            return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
    708709        }
  • branches/jsCStack/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp

    r160960 r160967  
    452452    {
    453453        exec = exec->callerFrame();
     454        Interpreter::ErrorHandlingMode mode(exec);
    454455        CommonSlowPaths::interpreterThrowInCaller(exec, createStackOverflowError(exec));
    455456        pc = returnToThrowForThrownException(exec);
  • branches/jsCStack/Source/JavaScriptCore/parser/ParserError.h

    r149014 r160967  
    9595        case EvalError:
    9696            return createSyntaxError(globalObject, m_message);
    97         case StackOverflow:
     97        case StackOverflow: {
     98            Interpreter::ErrorHandlingMode mode(globalObject->globalExec());
    9899            return createStackOverflowError(globalObject);
     100        }
    99101        case OutOfMemory:
    100102            return createOutOfMemoryError(globalObject);
  • branches/jsCStack/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp

    r160936 r160967  
    191191    if (slotsToAdd < 0) {
    192192        exec = exec->callerFrame();
     193        Interpreter::ErrorHandlingMode mode(exec);
    193194        CommonSlowPaths::interpreterThrowInCaller(exec, createStackOverflowError(exec));
    194195        RETURN_TWO(bitwise_cast<void*>(static_cast<uintptr_t>(1)), exec);
     
    203204    if (slotsToAdd < 0) {
    204205        exec = exec->callerFrame();
     206        Interpreter::ErrorHandlingMode mode(exec);
    205207        CommonSlowPaths::interpreterThrowInCaller(exec, createStackOverflowError(exec));
    206208        RETURN_TWO(bitwise_cast<void*>(static_cast<uintptr_t>(1)), exec);
  • branches/jsCStack/Source/JavaScriptCore/runtime/JSONObject.cpp

    r157614 r160967  
    655655                ASSERT(isJSArray(asObject(inValue)) || asObject(inValue)->inherits(JSArray::info()));
    656656                if (objectStack.size() + arrayStack.size() > maximumFilterRecursion)
    657                     return m_exec->vm().throwException(m_exec, createStackOverflowError(m_exec));
     657                    return throwStackOverflowError(m_exec);
    658658
    659659                JSArray* array = asArray(inValue);
     
    706706                ASSERT(!isJSArray(asObject(inValue)) && !asObject(inValue)->inherits(JSArray::info()));
    707707                if (objectStack.size() + arrayStack.size() > maximumFilterRecursion)
    708                     return m_exec->vm().throwException(m_exec, createStackOverflowError(m_exec));
     708                    return throwStackOverflowError(m_exec);
    709709
    710710                JSObject* object = asObject(inValue);
  • branches/jsCStack/Source/JavaScriptCore/runtime/StringRecursionChecker.cpp

    r154797 r160967  
    2929JSValue StringRecursionChecker::throwStackOverflowError()
    3030{
    31     return m_exec->vm().throwException(m_exec, createStackOverflowError(m_exec));
     31    return JSC::throwStackOverflowError(m_exec);
    3232}
    3333
  • branches/jsCStack/Source/JavaScriptCore/runtime/VMEntryScope.cpp

    r160694 r160967  
    5454    vm.clearExceptionStack();
    5555
    56     void* limit = m_stack.recursionLimit(requiredCapacity());
    57     vm.setStackLimit(limit);
     56    updateStackLimit();
    5857    vm.setLastStackTop(m_stack.origin());
    5958}
     
    6463    m_vm.setStackLimit(m_prevStackLimit);
    6564    m_vm.setLastStackTop(m_prevLastStackTop);
     65}
     66
     67void VMEntryScope::updateStackLimit()
     68{
     69    void* limit = m_stack.recursionLimit(requiredCapacity());
     70    m_vm.setStackLimit(limit);
    6671}
    6772
  • branches/jsCStack/Source/JavaScriptCore/runtime/VMEntryScope.h

    r160694 r160967  
    4141    JS_EXPORT_PRIVATE ~VMEntryScope();
    4242
     43    void updateStackLimit();
    4344    JSGlobalObject* globalObject() const { return m_globalObject; }
    4445
Note: See TracChangeset for help on using the changeset viewer.