Ignore:
Timestamp:
Nov 20, 2013, 9:29:42 PM (12 years ago)
Author:
[email protected]
Message:

Introducing VMEntryScope to update the VM stack limit.
https://bugs.webkit.org/show_bug.cgi?id=124634.

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

  1. Introduced USE(SEPARATE_C_AND_JS_STACK) (defined in Platform.h). Currently, it is hardcoded to use separate C and JS stacks. Once we switch to using the C stack for JS frames, we'll need to fix this to only be enabled when ENABLE(LLINT_C_LOOP).
  1. Stack limits are now tracked in the VM.

Logically, there are 2 stack limits:

  1. m_stackLimit for the native C stack, and
  2. m_jsStackLimit for the JS stack.

If USE(SEPARATE_C_AND_JS_STACK), then the 2 limits are the same
value, and are implemented as 2 fields in a union.

  1. The VM native stackLimit is set as follows:
    1. Initially, the VM sets it to the limit of the stack of the thread that instantiated the VM. This allows the parser and bytecode generator to run before we enter the VM to execute JS code.
  1. Upon entry into the VM to execute JS code (via one of the Interpreter::execute...() functions), we instantiate a VMEntryScope that sets the VM's stackLimit to the limit of the current thread's stack. The VMEntryScope will automatically restore the previous entryScope and stack limit upon destruction.

If USE(SEPARATE_C_AND_JS_STACK), the JSStack's methods will set the VM's
jsStackLimit whenever it grows or shrinks.

  1. The VM now provides a isSafeToRecurse() function that compares the current stack pointer against its native stackLimit. This subsumes and obsoletes the VMStackBounds class.
  1. The VMEntryScope class also subsumes DynamicGlobalObjectScope for tracking the JSGlobalObject that we last entered the VM with.
  1. Renamed dynamicGlobalObject() to vmEntryGlobalObject() since that is the value that the function retrieves.
  1. Changed JIT and LLINT code to do stack checks against the jsStackLimit in the VM class instead of the JSStack.
  • API/JSBase.cpp:

(JSEvaluateScript):
(JSCheckScriptSyntax):

  • API/JSContextRef.cpp:

(JSGlobalContextRetain):
(JSGlobalContextRelease):

  • CMakeLists.txt:
  • GNUmakefile.list.am:
  • JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
  • JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::BytecodeGenerator):

  • bytecompiler/BytecodeGenerator.h:

(JSC::BytecodeGenerator::emitNode):
(JSC::BytecodeGenerator::emitNodeInConditionContext):

  • debugger/Debugger.cpp:

(JSC::Debugger::detach):
(JSC::Debugger::recompileAllJSFunctions):
(JSC::Debugger::pauseIfNeeded):

  • debugger/DebuggerCallFrame.cpp:

(JSC::DebuggerCallFrame::vmEntryGlobalObject):

  • debugger/DebuggerCallFrame.h:
  • dfg/DFGJITCompiler.cpp:

(JSC::DFG::JITCompiler::compileFunction):

  • dfg/DFGOSREntry.cpp:
  • ftl/FTLLink.cpp:

(JSC::FTL::link):

  • ftl/FTLOSREntry.cpp:
  • heap/Heap.cpp:

(JSC::Heap::lastChanceToFinalize):
(JSC::Heap::deleteAllCompiledCode):

  • interpreter/CachedCall.h:

(JSC::CachedCall::CachedCall):

  • interpreter/CallFrame.cpp:

(JSC::CallFrame::vmEntryGlobalObject):

  • interpreter/CallFrame.h:
  • interpreter/Interpreter.cpp:

(JSC::unwindCallFrame):
(JSC::Interpreter::unwind):
(JSC::Interpreter::execute):
(JSC::Interpreter::executeCall):
(JSC::Interpreter::executeConstruct):
(JSC::Interpreter::prepareForRepeatCall):
(JSC::Interpreter::debug):

  • interpreter/JSStack.cpp:

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

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

(JSC::JSStack::shrink):
(JSC::JSStack::grow):

  • Moved these inlined functions here from JSStack.h. It reduces some #include dependencies of JSSTack.h which had previously resulted in some EWS bots' unhappiness with this patch.

(JSC::JSStack::updateStackLimit):

  • jit/JIT.cpp:

(JSC::JIT::privateCompile):

  • jit/JITCall.cpp:

(JSC::JIT::compileLoadVarargs):

  • jit/JITCall32_64.cpp:

(JSC::JIT::compileLoadVarargs):

  • jit/JITOperations.cpp:
  • llint/LLIntSlowPaths.cpp:
  • llint/LowLevelInterpreter.asm:
  • parser/Parser.cpp:

(JSC::::Parser):

  • parser/Parser.h:

(JSC::Parser::canRecurse):

  • runtime/CommonSlowPaths.h:
  • runtime/Completion.cpp:

(JSC::evaluate):

  • runtime/FunctionConstructor.cpp:

(JSC::constructFunctionSkippingEvalEnabledCheck):

  • runtime/JSGlobalObject.cpp:
  • runtime/JSGlobalObject.h:
  • runtime/StringRecursionChecker.h:

(JSC::StringRecursionChecker::performCheck):

  • runtime/VM.cpp:

(JSC::VM::VM):
(JSC::VM::releaseExecutableMemory):
(JSC::VM::throwException):

  • runtime/VM.h:

(JSC::VM::addressOfJSStackLimit):
(JSC::VM::jsStackLimit):
(JSC::VM::setJSStackLimit):
(JSC::VM::stackLimit):
(JSC::VM::setStackLimit):
(JSC::VM::isSafeToRecurse):

  • runtime/VMEntryScope.cpp: Added.

(JSC::VMEntryScope::VMEntryScope):
(JSC::VMEntryScope::~VMEntryScope):
(JSC::VMEntryScope::requiredCapacity):

  • runtime/VMEntryScope.h: Added.

(JSC::VMEntryScope::globalObject):

  • runtime/VMStackBounds.h: Removed.

Source/WebCore:

No new tests.

Renamed dynamicGlobalObject() to vmEntryGlobalObject().
Replaced uses of DynamicGlobalObjectScope with VMEntryScope.

  • ForwardingHeaders/runtime/VMEntryScope.h: Added.
  • WebCore.vcxproj/WebCore.vcxproj:
  • WebCore.vcxproj/WebCore.vcxproj.filters:
  • bindings/js/JSCryptoAlgorithmBuilder.cpp:

(WebCore::JSCryptoAlgorithmBuilder::add):

  • bindings/js/JSCustomXPathNSResolver.cpp:

(WebCore::JSCustomXPathNSResolver::create):

  • bindings/js/JSDOMBinding.cpp:

(WebCore::firstDOMWindow):

  • bindings/js/JSErrorHandler.cpp:

(WebCore::JSErrorHandler::handleEvent):

  • bindings/js/JSEventListener.cpp:

(WebCore::JSEventListener::handleEvent):

  • bindings/js/JavaScriptCallFrame.h:

(WebCore::JavaScriptCallFrame::vmEntryGlobalObject):

  • bindings/js/PageScriptDebugServer.cpp:

(WebCore::PageScriptDebugServer::recompileAllJSFunctions):

  • bindings/js/ScriptDebugServer.cpp:

(WebCore::ScriptDebugServer::evaluateBreakpointAction):
(WebCore::ScriptDebugServer::handlePause):

  • bindings/js/WorkerScriptDebugServer.cpp:

(WebCore::WorkerScriptDebugServer::recompileAllJSFunctions):

  • bindings/objc/WebScriptObject.mm:

(WebCore::addExceptionToConsole):

  • bridge/c/c_utility.cpp:

(JSC::Bindings::convertValueToNPVariant):

  • bridge/objc/objc_instance.mm:

(ObjcInstance::moveGlobalExceptionToExecState):

  • bridge/objc/objc_runtime.mm:

(JSC::Bindings::convertValueToObjcObject):

  • bridge/objc/objc_utility.mm:

(JSC::Bindings::convertValueToObjcValue):

Source/WebKit/mac:

  • WebView/WebScriptDebugger.mm:

(WebScriptDebugger::sourceParsed):

Source/WTF:

  • wtf/Platform.h:
  • wtf/StackBounds.h:

(WTF::StackBounds::StackBounds):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp

    r159528 r159605  
    6767#include "StrictEvalActivation.h"
    6868#include "StrongInlines.h"
    69 #include "VMStackBounds.h"
     69#include "VMEntryScope.h"
    7070#include "VirtualRegister.h"
    7171
     
    396396    JSScope* scope = callFrame->scope();
    397397
    398     if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {
     398    if (Debugger* debugger = callFrame->vmEntryGlobalObject()->debugger()) {
    399399        if (callFrame->callee())
    400400            debugger->returnEvent(callFrame);
     
    651651    ASSERT(!exceptionValue.isObject() || asObject(exceptionValue)->hasProperty(callFrame, callFrame->vm().propertyNames->stack));
    652652
    653     Debugger* debugger = callFrame->dynamicGlobalObject()->debugger();
     653    Debugger* debugger = callFrame->vmEntryGlobalObject()->debugger();
    654654    if (debugger && debugger->needsExceptionCallbacks()) {
    655655        // We need to clear the exception and the exception stack here in order to see if a new exception happens.
     
    740740        return jsNull();
    741741
    742     StackStats::CheckPoint stackCheckPoint;
    743     const VMStackBounds vmStackBounds(vm, wtfThreadData().stack());
    744     if (!vmStackBounds.isSafeToRecurse())
     742    VMEntryScope entryScope(vm, scope->globalObject());
     743    if (!vm.isSafeToRecurse())
    745744        return checkedReturn(throwStackOverflowError(callFrame));
    746745
     
    748747    // we'll handle the JSON object here. Else, we'll handle real JS code
    749748    // below at failedJSONP.
    750     DynamicGlobalObjectScope globalObjectScope(vm, scope->globalObject());
     749
    751750    Vector<JSONPData> JSONPData;
    752751    bool parseResult;
     
    901900        return jsNull();
    902901
    903     StackStats::CheckPoint stackCheckPoint;
    904     const VMStackBounds vmStackBounds(vm, wtfThreadData().stack());
    905     if (!vmStackBounds.isSafeToRecurse())
    906         return checkedReturn(throwStackOverflowError(callFrame));
    907 
    908902    bool isJSCall = (callType == CallTypeJS);
    909903    JSScope* scope;
     
    917911        scope = callFrame->scope();
    918912    }
    919     DynamicGlobalObjectScope globalObjectScope(vm, scope->globalObject());
     913
     914    VMEntryScope entryScope(vm, scope->globalObject());
     915    if (!vm.isSafeToRecurse())
     916        return checkedReturn(throwStackOverflowError(callFrame));
    920917
    921918    if (isJSCall) {
     
    979976        return checkedReturn(throwStackOverflowError(callFrame));
    980977
    981     StackStats::CheckPoint stackCheckPoint;
    982     const VMStackBounds vmStackBounds(vm, wtfThreadData().stack());
    983     if (!vmStackBounds.isSafeToRecurse())
    984         return checkedReturn(throwStackOverflowError(callFrame));
    985 
    986978    bool isJSConstruct = (constructType == ConstructTypeJS);
    987979    JSScope* scope;
     
    996988    }
    997989
    998     DynamicGlobalObjectScope globalObjectScope(vm, scope->globalObject());
     990    VMEntryScope entryScope(vm, scope->globalObject());
     991    if (!vm.isSafeToRecurse())
     992        return checkedReturn(throwStackOverflowError(callFrame));
    999993
    1000994    if (isJSConstruct) {
     
    10661060        return CallFrameClosure();
    10671061
    1068     StackStats::CheckPoint stackCheckPoint;
    1069     const VMStackBounds vmStackBounds(vm, wtfThreadData().stack());
    1070     if (!vmStackBounds.isSafeToRecurse()) {
    1071         throwStackOverflowError(callFrame);
    1072         return CallFrameClosure();
    1073     }
    1074 
    10751062    // Compile the callee:
    10761063    JSObject* error = functionExecutable->prepareForExecution(callFrame, scope, CodeForCall);
     
    11661153        return jsNull();
    11671154
    1168     DynamicGlobalObjectScope globalObjectScope(vm, scope->globalObject());
    1169 
    1170     StackStats::CheckPoint stackCheckPoint;
    1171     const VMStackBounds vmStackBounds(vm, wtfThreadData().stack());
    1172     if (!vmStackBounds.isSafeToRecurse())
    1173         return checkedReturn(throwStackOverflowError(callFrame));
     1155    VMEntryScope entryScope(vm, scope->globalObject());
     1156    if (!vm.isSafeToRecurse())
     1157        return checkedReturn(throwStackOverflowError(callFrame));       
    11741158
    11751159    unsigned numVariables = eval->numVariables();
     
    12521236NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHookID)
    12531237{
    1254     Debugger* debugger = callFrame->dynamicGlobalObject()->debugger();
     1238    Debugger* debugger = callFrame->vmEntryGlobalObject()->debugger();
    12551239    if (!debugger || !debugger->needsOpDebugCallbacks())
    12561240        return;
Note: See TracChangeset for help on using the changeset viewer.