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()