Title: [169139] trunk/Source
Revision
169139
Author
[email protected]
Date
2014-05-20 15:55:49 -0700 (Tue, 20 May 2014)

Log Message

Watchdog timer should be lazily allocated
https://bugs.webkit.org/show_bug.cgi?id=133135

Reviewed by Geoffrey Garen.

Source/_javascript_Core:
We incur a noticeable amount of overhead on some benchmarks due to checking if the Watchdog ever fired.
There is no reason to do this checking if we never activated the Watchdog, which can only be done through
JSContextGroupSetExecutionTimeLimit or JSContextGroupClearExecutionTimeLimit.

By allocating the Watchdog lazily on the VM we can avoid all of the associated overhead when we don't use
these two API functions (which is true of most clients).

* API/JSContextRef.cpp:
(JSContextGroupSetExecutionTimeLimit):
(JSContextGroupClearExecutionTimeLimit):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* interpreter/Interpreter.cpp:
(JSC::Interpreter::execute):
(JSC::Interpreter::executeCall):
(JSC::Interpreter::executeConstruct):
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_loop_hint):
(JSC::JIT::emitSlow_op_loop_hint):
* jit/JITOperations.cpp:
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* runtime/VM.h:
* runtime/Watchdog.cpp:
(JSC::Watchdog::Scope::Scope): Deleted.
(JSC::Watchdog::Scope::~Scope): Deleted.
* runtime/Watchdog.h:
(JSC::Watchdog::Scope::Scope):
(JSC::Watchdog::Scope::~Scope):

Source/WebCore:
No new tests.

We incur a noticeable amount of overhead on some benchmarks due to checking if the Watchdog ever fired.
There is no reason to do this checking if we never activated the Watchdog, which can only be done through
JSContextGroupSetExecutionTimeLimit or JSContextGroupClearExecutionTimeLimit.

By allocating the Watchdog lazily on the VM we can avoid all of the associated overhead when we don't use
these two API functions (which is true of most clients).

* bindings/js/JSEventListener.cpp:
(WebCore::JSEventListener::handleEvent):
* bindings/js/WorkerScriptController.cpp:
(WebCore::WorkerScriptController::evaluate):
(WebCore::WorkerScriptController::scheduleExecutionTermination):
(WebCore::WorkerScriptController::isExecutionTerminating):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/API/JSContextRef.cpp (169138 => 169139)


--- trunk/Source/_javascript_Core/API/JSContextRef.cpp	2014-05-20 22:54:34 UTC (rev 169138)
+++ trunk/Source/_javascript_Core/API/JSContextRef.cpp	2014-05-20 22:55:49 UTC (rev 169139)
@@ -89,7 +89,9 @@
 {
     VM& vm = *toJS(group);
     JSLockHolder locker(&vm);
-    Watchdog& watchdog = vm.watchdog;
+    if (!vm.watchdog)
+        vm.watchdog = std::make_unique<Watchdog>();
+    Watchdog& watchdog = *vm.watchdog;
     if (callback) {
         void* callbackPtr = reinterpret_cast<void*>(callback);
         watchdog.setTimeLimit(vm, limit, internalScriptTimeoutCallback, callbackPtr, callbackData);
@@ -101,7 +103,9 @@
 {
     VM& vm = *toJS(group);
     JSLockHolder locker(&vm);
-    Watchdog& watchdog = vm.watchdog;
+    if (!vm.watchdog)
+        vm.watchdog = std::make_unique<Watchdog>();
+    Watchdog& watchdog = *vm.watchdog;
     watchdog.setTimeLimit(vm, std::numeric_limits<double>::infinity());
 }
 

Modified: trunk/Source/_javascript_Core/ChangeLog (169138 => 169139)


--- trunk/Source/_javascript_Core/ChangeLog	2014-05-20 22:54:34 UTC (rev 169138)
+++ trunk/Source/_javascript_Core/ChangeLog	2014-05-20 22:55:49 UTC (rev 169139)
@@ -1,3 +1,44 @@
+2014-05-20  Mark Hahnenberg  <[email protected]>
+
+        Watchdog timer should be lazily allocated
+        https://bugs.webkit.org/show_bug.cgi?id=133135
+
+        Reviewed by Geoffrey Garen.
+
+        We incur a noticeable amount of overhead on some benchmarks due to checking if the Watchdog ever fired. 
+        There is no reason to do this checking if we never activated the Watchdog, which can only be done through 
+        JSContextGroupSetExecutionTimeLimit or JSContextGroupClearExecutionTimeLimit. 
+
+        By allocating the Watchdog lazily on the VM we can avoid all of the associated overhead when we don't use 
+        these two API functions (which is true of most clients).
+
+        * API/JSContextRef.cpp:
+        (JSContextGroupSetExecutionTimeLimit):
+        (JSContextGroupClearExecutionTimeLimit):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * interpreter/Interpreter.cpp:
+        (JSC::Interpreter::execute):
+        (JSC::Interpreter::executeCall):
+        (JSC::Interpreter::executeConstruct):
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_loop_hint):
+        (JSC::JIT::emitSlow_op_loop_hint):
+        * jit/JITOperations.cpp:
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+        * runtime/VM.h:
+        * runtime/Watchdog.cpp:
+        (JSC::Watchdog::Scope::Scope): Deleted.
+        (JSC::Watchdog::Scope::~Scope): Deleted.
+        * runtime/Watchdog.h:
+        (JSC::Watchdog::Scope::Scope):
+        (JSC::Watchdog::Scope::~Scope):
+
 2014-05-19  Mark Hahnenberg  <[email protected]>
 
         JSArray::shiftCountWith* could be more efficient

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (169138 => 169139)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2014-05-20 22:54:34 UTC (rev 169138)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2014-05-20 22:55:49 UTC (rev 169139)
@@ -3192,7 +3192,7 @@
 
             addToGraph(LoopHint);
             
-            if (m_vm->watchdog.isEnabled())
+            if (m_vm->watchdog && m_vm->watchdog->isEnabled())
                 addToGraph(CheckWatchdogTimer);
             
             NEXT_OPCODE(op_loop_hint);

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (169138 => 169139)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2014-05-20 22:54:34 UTC (rev 169138)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2014-05-20 22:55:49 UTC (rev 169139)
@@ -4551,11 +4551,12 @@
         break;
 
     case CheckWatchdogTimer:
+        ASSERT(m_jit.vm()->watchdog);
         speculationCheck(
             WatchdogTimerFired, JSValueRegs(), 0,
             m_jit.branchTest8(
                 JITCompiler::NonZero,
-                JITCompiler::AbsoluteAddress(m_jit.vm()->watchdog.timerDidFireAddress())));
+                JITCompiler::AbsoluteAddress(m_jit.vm()->watchdog->timerDidFireAddress())));
         break;
 
     case CountExecution:

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (169138 => 169139)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2014-05-20 22:54:34 UTC (rev 169138)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2014-05-20 22:55:49 UTC (rev 169139)
@@ -4575,11 +4575,12 @@
         break;
 
     case CheckWatchdogTimer:
+        ASSERT(m_jit.vm()->watchdog);
         speculationCheck(
             WatchdogTimerFired, JSValueRegs(), 0,
             m_jit.branchTest8(
                 JITCompiler::NonZero,
-                JITCompiler::AbsoluteAddress(m_jit.vm()->watchdog.timerDidFireAddress())));
+                JITCompiler::AbsoluteAddress(m_jit.vm()->watchdog->timerDidFireAddress())));
         break;
 
     case Phantom:

Modified: trunk/Source/_javascript_Core/interpreter/Interpreter.cpp (169138 => 169139)


--- trunk/Source/_javascript_Core/interpreter/Interpreter.cpp	2014-05-20 22:54:34 UTC (rev 169138)
+++ trunk/Source/_javascript_Core/interpreter/Interpreter.cpp	2014-05-20 22:55:49 UTC (rev 169139)
@@ -913,7 +913,7 @@
 
     ProgramCodeBlock* codeBlock = program->codeBlock();
 
-    if (UNLIKELY(vm.watchdog.didFire(callFrame)))
+    if (UNLIKELY(vm.watchdog && vm.watchdog->didFire(callFrame)))
         return throwTerminatedExecutionException(callFrame);
 
     ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
@@ -928,7 +928,7 @@
     JSValue result;
     {
         SamplingTool::CallRecord callRecord(m_sampler.get());
-        Watchdog::Scope watchdogScope(vm.watchdog);
+        Watchdog::Scope watchdogScope(vm.watchdog.get());
 
         result = program->generatedJITCode()->execute(&vm, &protoCallFrame);
     }
@@ -975,7 +975,7 @@
     } else
         newCodeBlock = 0;
 
-    if (UNLIKELY(vm.watchdog.didFire(callFrame)))
+    if (UNLIKELY(vm.watchdog && vm.watchdog->didFire(callFrame)))
         return throwTerminatedExecutionException(callFrame);
 
     ProtoCallFrame protoCallFrame;
@@ -987,7 +987,7 @@
     JSValue result;
     {
         SamplingTool::CallRecord callRecord(m_sampler.get(), !isJSCall);
-        Watchdog::Scope watchdogScope(vm.watchdog);
+        Watchdog::Scope watchdogScope(vm.watchdog.get());
 
         // Execute the code:
         if (isJSCall)
@@ -1043,7 +1043,7 @@
     } else
         newCodeBlock = 0;
 
-    if (UNLIKELY(vm.watchdog.didFire(callFrame)))
+    if (UNLIKELY(vm.watchdog && vm.watchdog->didFire(callFrame)))
         return throwTerminatedExecutionException(callFrame);
 
     ProtoCallFrame protoCallFrame;
@@ -1055,7 +1055,7 @@
     JSValue result;
     {
         SamplingTool::CallRecord callRecord(m_sampler.get(), !isJSConstruct);
-        Watchdog::Scope watchdogScope(vm.watchdog);
+        Watchdog::Scope watchdogScope(vm.watchdog.get());
 
         // Execute the code.
         if (isJSConstruct)
@@ -1118,14 +1118,14 @@
     if (LegacyProfiler* profiler = vm.enabledProfiler())
         profiler->willExecute(closure.oldCallFrame, closure.function);
 
-    if (UNLIKELY(vm.watchdog.didFire(closure.oldCallFrame)))
+    if (UNLIKELY(vm.watchdog && vm.watchdog->didFire(closure.oldCallFrame)))
         return throwTerminatedExecutionException(closure.oldCallFrame);
 
     // Execute the code:
     JSValue result;
     {
         SamplingTool::CallRecord callRecord(m_sampler.get());
-        Watchdog::Scope watchdogScope(vm.watchdog);
+        Watchdog::Scope watchdogScope(vm.watchdog.get());
 
         result = closure.functionExecutable->generatedJITCodeForCall()->execute(&vm, closure.protoCallFrame);
     }
@@ -1194,7 +1194,7 @@
         }
     }
 
-    if (UNLIKELY(vm.watchdog.didFire(callFrame)))
+    if (UNLIKELY(vm.watchdog && vm.watchdog->didFire(callFrame)))
         return throwTerminatedExecutionException(callFrame);
 
     ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
@@ -1209,7 +1209,7 @@
     JSValue result;
     {
         SamplingTool::CallRecord callRecord(m_sampler.get());
-        Watchdog::Scope watchdogScope(vm.watchdog);
+        Watchdog::Scope watchdogScope(vm.watchdog.get());
 
         result = eval->generatedJITCode()->execute(&vm, &protoCallFrame);
     }

Modified: trunk/Source/_javascript_Core/jit/JITOpcodes.cpp (169138 => 169139)


--- trunk/Source/_javascript_Core/jit/JITOpcodes.cpp	2014-05-20 22:54:34 UTC (rev 169138)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes.cpp	2014-05-20 22:55:49 UTC (rev 169139)
@@ -1091,8 +1091,8 @@
     }
 
     // Emit the watchdog timer check:
-    if (m_vm->watchdog.isEnabled())
-        addSlowCase(branchTest8(NonZero, AbsoluteAddress(m_vm->watchdog.timerDidFireAddress())));
+    if (m_vm->watchdog && m_vm->watchdog->isEnabled())
+        addSlowCase(branchTest8(NonZero, AbsoluteAddress(m_vm->watchdog->timerDidFireAddress())));
 }
 
 void JIT::emitSlow_op_loop_hint(Instruction*, Vector<SlowCaseEntry>::iterator& iter)
@@ -1117,7 +1117,7 @@
 #endif
 
     // Emit the slow path of the watchdog timer check:
-    if (m_vm->watchdog.isEnabled()) {
+    if (m_vm->watchdog && m_vm->watchdog->isEnabled()) {
         linkSlowCase(iter);
         callOperation(operationHandleWatchdogTimer);
 

Modified: trunk/Source/_javascript_Core/jit/JITOperations.cpp (169138 => 169139)


--- trunk/Source/_javascript_Core/jit/JITOperations.cpp	2014-05-20 22:54:34 UTC (rev 169138)
+++ trunk/Source/_javascript_Core/jit/JITOperations.cpp	2014-05-20 22:55:49 UTC (rev 169139)
@@ -983,7 +983,7 @@
     VM& vm = exec->vm();
     NativeCallFrameTracer tracer(&vm, exec);
 
-    if (UNLIKELY(vm.watchdog.didFire(exec)))
+    if (UNLIKELY(vm.watchdog && vm.watchdog->didFire(exec)))
         vm.throwException(exec, createTerminatedExecutionException(&vm));
 }
 

Modified: trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp (169138 => 169139)


--- trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2014-05-20 22:54:34 UTC (rev 169138)
+++ trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2014-05-20 22:55:49 UTC (rev 169139)
@@ -1354,7 +1354,8 @@
 LLINT_SLOW_PATH_DECL(slow_path_handle_watchdog_timer)
 {
     LLINT_BEGIN_NO_SET_PC();
-    if (UNLIKELY(vm.watchdog.didFire(exec)))
+    ASSERT(vm.watchdog);
+    if (UNLIKELY(vm.watchdog->didFire(exec)))
         LLINT_THROW(createTerminatedExecutionException(&vm));
     LLINT_RETURN_TWO(0, exec);
 }

Modified: trunk/Source/_javascript_Core/runtime/VM.h (169138 => 169139)


--- trunk/Source/_javascript_Core/runtime/VM.h	2014-05-20 22:54:34 UTC (rev 169138)
+++ trunk/Source/_javascript_Core/runtime/VM.h	2014-05-20 22:55:49 UTC (rev 169139)
@@ -230,7 +230,7 @@
         VMType vmType;
         ClientData* clientData;
         ExecState* topCallFrame;
-        Watchdog watchdog;
+        std::unique_ptr<Watchdog> watchdog;
 
         const OwnPtr<const HashTable> arrayConstructorTable;
         const OwnPtr<const HashTable> arrayPrototypeTable;

Modified: trunk/Source/_javascript_Core/runtime/Watchdog.cpp (169138 => 169139)


--- trunk/Source/_javascript_Core/runtime/Watchdog.cpp	2014-05-20 22:54:34 UTC (rev 169138)
+++ trunk/Source/_javascript_Core/runtime/Watchdog.cpp	2014-05-20 22:55:49 UTC (rev 169139)
@@ -185,15 +185,4 @@
     m_isStopped = true;
 }
 
-Watchdog::Scope::Scope(Watchdog& watchdog)
-    : m_watchdog(watchdog)
-{
-    m_watchdog.arm();
-}
-
-Watchdog::Scope::~Scope()
-{
-    m_watchdog.disarm();
-}
-
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/Watchdog.h (169138 => 169139)


--- trunk/Source/_javascript_Core/runtime/Watchdog.h	2014-05-20 22:54:34 UTC (rev 169138)
+++ trunk/Source/_javascript_Core/runtime/Watchdog.h	2014-05-20 22:55:49 UTC (rev 169139)
@@ -104,11 +104,23 @@
 
 class Watchdog::Scope {
 public:
-    Scope(Watchdog&);
-    ~Scope();
+    Scope(Watchdog* watchdog)
+        : m_watchdog(watchdog)
+    {
+        if (!watchdog)
+            return;
+        m_watchdog->arm();
+    }
+    
+    ~Scope()
+    {
+        if (!m_watchdog)
+            return;
+        m_watchdog->disarm();
+    }
 
 private:
-    Watchdog& m_watchdog;
+    Watchdog* m_watchdog;
 };
 
 } // namespace JSC

Modified: trunk/Source/WebCore/ChangeLog (169138 => 169139)


--- trunk/Source/WebCore/ChangeLog	2014-05-20 22:54:34 UTC (rev 169138)
+++ trunk/Source/WebCore/ChangeLog	2014-05-20 22:55:49 UTC (rev 169139)
@@ -1,3 +1,26 @@
+2014-05-20  Mark Hahnenberg  <[email protected]>
+
+        Watchdog timer should be lazily allocated
+        https://bugs.webkit.org/show_bug.cgi?id=133135
+
+        Reviewed by Geoffrey Garen.
+
+        No new tests.
+
+        We incur a noticeable amount of overhead on some benchmarks due to checking if the Watchdog ever fired. 
+        There is no reason to do this checking if we never activated the Watchdog, which can only be done through 
+        JSContextGroupSetExecutionTimeLimit or JSContextGroupClearExecutionTimeLimit. 
+
+        By allocating the Watchdog lazily on the VM we can avoid all of the associated overhead when we don't use 
+        these two API functions (which is true of most clients).
+
+        * bindings/js/JSEventListener.cpp:
+        (WebCore::JSEventListener::handleEvent):
+        * bindings/js/WorkerScriptController.cpp:
+        (WebCore::WorkerScriptController::evaluate):
+        (WebCore::WorkerScriptController::scheduleExecutionTermination):
+        (WebCore::WorkerScriptController::isExecutionTerminating):
+
 2014-05-20  Dean Jackson  <[email protected]>
 
         [Mac] Allow popup menus to override default appearance

Modified: trunk/Source/WebCore/bindings/js/JSEventListener.cpp (169138 => 169139)


--- trunk/Source/WebCore/bindings/js/JSEventListener.cpp	2014-05-20 22:54:34 UTC (rev 169138)
+++ trunk/Source/WebCore/bindings/js/JSEventListener.cpp	2014-05-20 22:55:49 UTC (rev 169139)
@@ -133,7 +133,7 @@
 
         if (scriptExecutionContext->isWorkerGlobalScope()) {
             bool terminatorCausedException = (exec->hadException() && isTerminatedExecutionException(exec->exception()));
-            if (terminatorCausedException || vm.watchdog.didFire())
+            if (terminatorCausedException || (vm.watchdog && vm.watchdog->didFire()))
                 toWorkerGlobalScope(scriptExecutionContext)->script()->forbidExecution();
         }
 

Modified: trunk/Source/WebCore/bindings/js/WorkerScriptController.cpp (169138 => 169139)


--- trunk/Source/WebCore/bindings/js/WorkerScriptController.cpp	2014-05-20 22:54:34 UTC (rev 169138)
+++ trunk/Source/WebCore/bindings/js/WorkerScriptController.cpp	2014-05-20 22:55:49 UTC (rev 169139)
@@ -134,7 +134,9 @@
     JSValue evaluationException;
     JSC::evaluate(exec, sourceCode.jsSourceCode(), m_workerGlobalScopeWrapper->globalThis(), &evaluationException);
 
-    if ((evaluationException && isTerminatedExecutionException(evaluationException)) ||  m_workerGlobalScopeWrapper->vm().watchdog.didFire()) {
+    VM& vm = exec->vm();
+    if ((evaluationException && isTerminatedExecutionException(evaluationException)) 
+        || (vm.watchdog && vm.watchdog->didFire())) {
         forbidExecution();
         return;
     }
@@ -162,14 +164,17 @@
     // termination is scheduled, isExecutionTerminating will
     // accurately reflect that state when called from another thread.
     MutexLocker locker(m_scheduledTerminationMutex);
-    m_vm->watchdog.fire();
+    if (m_vm->watchdog)
+        m_vm->watchdog->fire();
 }
 
 bool WorkerScriptController::isExecutionTerminating() const
 {
     // See comments in scheduleExecutionTermination regarding mutex usage.
     MutexLocker locker(m_scheduledTerminationMutex);
-    return m_vm->watchdog.didFire();
+    if (m_vm->watchdog)
+        return m_vm->watchdog->didFire();
+    return false;
 }
 
 void WorkerScriptController::forbidExecution()
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to