Ignore:
Timestamp:
Apr 17, 2013, 3:37:45 PM (12 years ago)
Author:
[email protected]
Message:

Source/JavaScriptCore: Add LLINT and baseline JIT support for timing out scripts.
https://bugs.webkit.org/show_bug.cgi?id=114577.

Reviewed by Geoffrey Garen.

Introduces the new Watchdog class which is used to track script
execution time, and initiate script termination if needed.

  • API/JSContextRef.cpp:

(internalScriptTimeoutCallback):
(JSContextGroupSetExecutionTimeLimit):
(JSContextGroupClearExecutionTimeLimit):

  • API/JSContextRefPrivate.h:
  • Added new script execution time limit APIs.
  • API/tests/testapi.c:

(currentCPUTime):
(shouldTerminateCallback):
(cancelTerminateCallback):
(extendTerminateCallback):
(main):

  • Added new API tests for script execution time limit.
  • CMakeLists.txt:
  • GNUmakefile.list.am:
  • JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
  • JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
  • JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • Target.pri:
  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::emitLoopHint):

  • loop hints are needed for the llint as well. Hence, it will be emitted unconditionally.
  • interpreter/Interpreter.cpp:

(JSC::Interpreter::addStackTraceIfNecessary):
(JSC::Interpreter::throwException):
(JSC::Interpreter::execute):
(JSC::Interpreter::executeCall):
(JSC::Interpreter::executeConstruct):

  • Added checks for script termination before entering script code.
  • jit/JIT.cpp:

(JSC::JIT::emitWatchdogTimerCheck):

  • jit/JIT.h:

(JSC::JIT::emit_op_loop_hint):

  • jit/JITStubs.cpp:

(JSC::DEFINE_STUB_FUNCTION(void, handle_watchdog_timer)):

  • jit/JITStubs.h:
  • llint/LLIntExceptions.cpp:

(JSC::LLInt::doThrow):

  • Factored out some common code from returnToThrow() and callToThrow().

(JSC::LLInt::returnToThrow):
(JSC::LLInt::callToThrow):

  • llint/LLIntSlowPaths.cpp:

(JSC::LLInt::LLINT_SLOW_PATH_DECL(slow_path_handle_watchdog_timer)):

  • llint/LLIntSlowPaths.h:
  • llint/LowLevelInterpreter.asm:
  • llint/LowLevelInterpreter32_64.asm:
  • llint/LowLevelInterpreter64.asm:
  • runtime/ExceptionHelpers.cpp:

(JSC::throwTerminatedExecutionException):

  • Also removed the now unused InterruptedExecutionException.
  • runtime/ExceptionHelpers.h:
  • runtime/JSGlobalData.cpp:

(JSC::JSGlobalData::JSGlobalData):

  • runtime/JSGlobalData.h:
  • Added watchdog, and removed the now obsolete Terminator.
  • runtime/Terminator.h: Removed.
  • runtime/Watchdog.cpp: Added.

(JSC::Watchdog::Watchdog):
(JSC::Watchdog::~Watchdog):
(JSC::Watchdog::setTimeLimit):
(JSC::Watchdog::didFire):
(JSC::Watchdog::isEnabled):
(JSC::Watchdog::fire):
(JSC::Watchdog::arm):
(JSC::Watchdog::disarm):
(JSC::Watchdog::startCountdownIfNeeded):
(JSC::Watchdog::startCountdown):
(JSC::Watchdog::stopCountdown):
(JSC::Watchdog::Scope::Scope):
(JSC::Watchdog::Scope::~Scope):

  • runtime/Watchdog.h: Added.

(Watchdog):
(JSC::Watchdog::didFire):
(JSC::Watchdog::timerDidFireAddress):
(JSC::Watchdog::isArmed):
(Watchdog::Scope):

  • runtime/WatchdogMac.cpp: Added.

(JSC::Watchdog::initTimer):
(JSC::Watchdog::destroyTimer):
(JSC::Watchdog::startTimer):
(JSC::Watchdog::stopTimer):

  • runtime/WatchdogNone.cpp: Added.

(JSC::Watchdog::initTimer):
(JSC::Watchdog::destroyTimer):
(JSC::Watchdog::startTimer):
(JSC::Watchdog::stopTimer):

Source/WebCore: Add LLINT and baseline JIT support for timing out scripts.
https://bugs.webkit.org/show_bug.cgi?id=114577.

Reviewed by Geoffrey Garen.

Replaced use of the obsolete JSGlobalData.terminator methods with the
JSGlobalData.watchdog equivalents.

  • bindings/js/JSEventListener.cpp:

(WebCore::JSEventListener::handleEvent):

  • bindings/js/SerializedScriptValue.cpp:

(WebCore::SerializedScriptValue::maybeThrowExceptionIfSerializationFailed):

  • bindings/js/WorkerScriptController.cpp:

(WebCore::WorkerScriptController::evaluate):
(WebCore::WorkerScriptController::scheduleExecutionTermination):
(WebCore::WorkerScriptController::isExecutionTerminating):

Source/WTF: Added currentCPUTime() and currentCPUTimeMS().
https://bugs.webkit.org/show_bug.cgi?id=114577.

Reviewed by Geoffrey Garen.

The currentCPUTime() implementation came from the old TimeoutChecker.cpp.

  • wtf/CurrentTime.cpp:

(WTF::currentCPUTime):
(WTF::currentCPUTimeMS):

  • wtf/CurrentTime.h:
File:
1 edited

Legend:

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

    r147872 r148639  
    768768    JSObject* errorObject = asObject(error);
    769769    JSGlobalObject* globalObject = 0;
    770     if (isTerminatedExecutionException(error) || isInterruptedExecutionException(error))
     770    if (isTerminatedExecutionException(error))
    771771        globalObject = globalData->dynamicGlobalObject;
    772772    else
     
    789789{
    790790    CodeBlock* codeBlock = callFrame->codeBlock();
    791     bool isInterrupt = false;
     791    bool isTermination = false;
    792792
    793793    ASSERT(!exceptionValue.isEmpty());
     
    811811        }
    812812
    813         isInterrupt = isInterruptedExecutionException(exception) || isTerminatedExecutionException(exception);
     813        isTermination = isTerminatedExecutionException(exception);
    814814    } else {
    815815        if (!callFrame->globalData().exceptionStack.size()) {
     
    828828    // Calculate an exception handler vPC, unwinding call frames as necessary.
    829829    HandlerInfo* handler = 0;
    830     while (isInterrupt || !(handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset))) {
     830    while (isTermination || !(handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset))) {
    831831        if (!unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock)) {
    832832            if (LegacyProfiler* profiler = callFrame->globalData().enabledProfiler())
     
    10311031    // Execute the code:
    10321032    JSValue result;
    1033     {
     1033    if (LIKELY(!globalData.watchdog.didFire(newCallFrame))) {
    10341034        SamplingTool::CallRecord callRecord(m_sampler.get());
     1035        Watchdog::Scope watchdogScope(globalData.watchdog);
    10351036
    10361037#if ENABLE(LLINT_C_LOOP)
     
    10391040        result = program->generatedJITCode().execute(&m_stack, newCallFrame, &globalData);
    10401041#endif // ENABLE(JIT)
    1041     }
     1042    } else
     1043        result = throwTerminatedExecutionException(newCallFrame);
    10421044
    10431045    if (LegacyProfiler* profiler = globalData.enabledProfiler())
     
    11011103
    11021104    JSValue result;
    1103     {
     1105    if (LIKELY(!globalData.watchdog.didFire(newCallFrame))) {
    11041106        SamplingTool::CallRecord callRecord(m_sampler.get(), !isJSCall);
     1107        Watchdog::Scope watchdogScope(globalData.watchdog);
    11051108
    11061109        // Execute the code:
     
    11131116        } else
    11141117            result = JSValue::decode(callData.native.function(newCallFrame));
    1115     }
     1118    } else
     1119        result = throwTerminatedExecutionException(newCallFrame);
    11161120
    11171121    if (LegacyProfiler* profiler = globalData.enabledProfiler())
     
    11761180
    11771181    JSValue result;
    1178     {
     1182    if (LIKELY(!globalData.watchdog.didFire(newCallFrame))) {
    11791183        SamplingTool::CallRecord callRecord(m_sampler.get(), !isJSConstruct);
     1184        Watchdog::Scope watchdogScope(globalData.watchdog);
    11801185
    11811186        // Execute the code.
     
    11861191            result = constructData.js.functionExecutable->generatedJITCodeForConstruct().execute(&m_stack, newCallFrame, &globalData);
    11871192#endif // ENABLE(JIT)
    1188         } else {
     1193        } else
    11891194            result = JSValue::decode(constructData.native.function(newCallFrame));
    1190         }
    1191     }
     1195    } else
     1196        result = throwTerminatedExecutionException(newCallFrame);
    11921197
    11931198    if (LegacyProfiler* profiler = globalData.enabledProfiler())
     
    12731278    // Execute the code:
    12741279    JSValue result;
    1275     {
     1280    if (LIKELY(!globalData.watchdog.didFire(closure.newCallFrame))) {
    12761281        SamplingTool::CallRecord callRecord(m_sampler.get());
    1277        
     1282        Watchdog::Scope watchdogScope(globalData.watchdog);
     1283
    12781284#if ENABLE(LLINT_C_LOOP)
    12791285        result = LLInt::CLoop::execute(closure.newCallFrame, llint_function_for_call_prologue);
     
    12811287        result = closure.functionExecutable->generatedJITCodeForCall().execute(&m_stack, closure.newCallFrame, &globalData);
    12821288#endif // ENABLE(JIT)
    1283     }
     1289    } else
     1290        result = throwTerminatedExecutionException(closure.newCallFrame);
    12841291
    12851292    if (LegacyProfiler* profiler = globalData.enabledProfiler())
     
    13691376    // Execute the code:
    13701377    JSValue result;
    1371     {
     1378    if (LIKELY(!globalData.watchdog.didFire(newCallFrame))) {
    13721379        SamplingTool::CallRecord callRecord(m_sampler.get());
    1373        
     1380        Watchdog::Scope watchdogScope(globalData.watchdog);
     1381
    13741382#if ENABLE(LLINT_C_LOOP)
    13751383        result = LLInt::CLoop::execute(newCallFrame, llint_eval_prologue);
     
    13771385        result = eval->generatedJITCode().execute(&m_stack, newCallFrame, &globalData);
    13781386#endif // ENABLE(JIT)
    1379     }
     1387    } else
     1388        result = throwTerminatedExecutionException(newCallFrame);
    13801389
    13811390    if (LegacyProfiler* profiler = globalData.enabledProfiler())
Note: See TracChangeset for help on using the changeset viewer.