Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add support for CheckWatchdogTimer as slow path in DFG and FTL.
https://bugs.webkit.org/show_bug.cgi?id=147968

Reviewed by Michael Saboff.

Re-implement the DFG's CheckWatchdogTimer as a slow path instead of a speculation
check.  Since the watchdog timer can fire spuriously, this allows the code to
stay optimized if all we have are spurious fires.

Implement the equivalent slow path for CheckWatchdogTimer in the FTL.

The watchdog tests in ExecutionTimeLimitTest.cpp has already been updated in
https://bugs.webkit.org/show_bug.cgi?id=148125 to test for the FTL's watchdog
implementation.

* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::DFG::LowerDFGToLLVM::compileNode):
(JSC::FTL::DFG::LowerDFGToLLVM::compileMaterializeCreateActivation):
(JSC::FTL::DFG::LowerDFGToLLVM::compileCheckWatchdogTimer):
(JSC::FTL::DFG::LowerDFGToLLVM::isInlinableSize):

* jit/JIT.h:
* jit/JITInlines.h:
(JSC::JIT::callOperation):
* jit/JITOperations.cpp:
* jit/JITOperations.h:
- Changed operationHandleWatchdogTimer() to return an unused nullptr.  This
  allows me to reuse the existing DFG slow path generator mechanism.  I didn't
  think that operationHandleWatchdogTimer() was worth introducing a whole new set
  of machinery just so we can have a slow path that returns void.



Canonical link: https://commits.webkit.org/166307@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@188649 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
Mark Lam committed Aug 19, 2015
1 parent bed5234 commit 8af25a5
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 14 deletions.
39 changes: 39 additions & 0 deletions Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,42 @@
2015-08-19 Mark Lam <mark.lam@apple.com>

Add support for CheckWatchdogTimer as slow path in DFG and FTL.
https://bugs.webkit.org/show_bug.cgi?id=147968

Reviewed by Michael Saboff.

Re-implement the DFG's CheckWatchdogTimer as a slow path instead of a speculation
check. Since the watchdog timer can fire spuriously, this allows the code to
stay optimized if all we have are spurious fires.

Implement the equivalent slow path for CheckWatchdogTimer in the FTL.

The watchdog tests in ExecutionTimeLimitTest.cpp has already been updated in
https://bugs.webkit.org/show_bug.cgi?id=148125 to test for the FTL's watchdog
implementation.

* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::DFG::LowerDFGToLLVM::compileNode):
(JSC::FTL::DFG::LowerDFGToLLVM::compileMaterializeCreateActivation):
(JSC::FTL::DFG::LowerDFGToLLVM::compileCheckWatchdogTimer):
(JSC::FTL::DFG::LowerDFGToLLVM::isInlinableSize):

* jit/JIT.h:
* jit/JITInlines.h:
(JSC::JIT::callOperation):
* jit/JITOperations.cpp:
* jit/JITOperations.h:
- Changed operationHandleWatchdogTimer() to return an unused nullptr. This
allows me to reuse the existing DFG slow path generator mechanism. I didn't
think that operationHandleWatchdogTimer() was worth introducing a whole new set
of machinery just so we can have a slow path that returns void.

2015-08-19 Mark Lam <mark.lam@apple.com>

Add ability to save and restore JSC options.
Expand Down
15 changes: 9 additions & 6 deletions Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
Expand Up @@ -4640,14 +4640,17 @@ void SpeculativeJIT::compile(Node* node)
emitInvalidationPoint(node);
break;

case CheckWatchdogTimer:
case CheckWatchdogTimer: {
ASSERT(m_jit.vm()->watchdog);
speculationCheck(
WatchdogTimerFired, JSValueRegs(), 0,
m_jit.branchTest8(
JITCompiler::NonZero,
JITCompiler::AbsoluteAddress(m_jit.vm()->watchdog->timerDidFireAddress())));
GPRTemporary unused(this);
GPRReg unusedGPR = unused.gpr();

JITCompiler::Jump timerDidFire = m_jit.branchTest8(JITCompiler::NonZero,
JITCompiler::AbsoluteAddress(m_jit.vm()->watchdog->timerDidFireAddress()));

addSlowPathGenerator(slowPathCall(timerDidFire, this, operationHandleWatchdogTimer, unusedGPR));
break;
}

case CountExecution:
m_jit.add64(TrustedImm32(1), MacroAssembler::AbsoluteAddress(node->executionCounter()->address()));
Expand Down
15 changes: 9 additions & 6 deletions Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
Expand Up @@ -4329,14 +4329,17 @@ void SpeculativeJIT::compile(Node* node)
emitInvalidationPoint(node);
break;

case CheckWatchdogTimer:
case CheckWatchdogTimer: {
ASSERT(m_jit.vm()->watchdog);
speculationCheck(
WatchdogTimerFired, JSValueRegs(), 0,
m_jit.branchTest8(
JITCompiler::NonZero,
JITCompiler::AbsoluteAddress(m_jit.vm()->watchdog->timerDidFireAddress())));
GPRTemporary unused(this);
GPRReg unusedGPR = unused.gpr();

JITCompiler::Jump timerDidFire = m_jit.branchTest8(JITCompiler::NonZero,
JITCompiler::AbsoluteAddress(m_jit.vm()->watchdog->timerDidFireAddress()));

addSlowPathGenerator(slowPathCall(timerDidFire, this, operationHandleWatchdogTimer, unusedGPR));
break;
}

case Phantom:
case Check:
Expand Down
1 change: 1 addition & 0 deletions Source/JavaScriptCore/ftl/FTLCapabilities.cpp
Expand Up @@ -119,6 +119,7 @@ inline CapabilityLevel canCompile(Node* node)
case CheckBadCell:
case CheckNotEmpty:
case CheckIdent:
case CheckWatchdogTimer:
case StringCharCodeAt:
case AllocatePropertyStorage:
case ReallocatePropertyStorage:
Expand Down
21 changes: 21 additions & 0 deletions Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
Expand Up @@ -51,6 +51,7 @@
#include "ScopedArguments.h"
#include "ScopedArgumentsTable.h"
#include "VirtualRegister.h"
#include "Watchdog.h"
#include <atomic>
#include <dlfcn.h>
#include <llvm/InitializeLLVM.h>
Expand Down Expand Up @@ -829,6 +830,9 @@ class LowerDFGToLLVM {
case MaterializeCreateActivation:
compileMaterializeCreateActivation();
break;
case CheckWatchdogTimer:
compileCheckWatchdogTimer();
break;

case PhantomLocal:
case LoopHint:
Expand Down Expand Up @@ -5428,6 +5432,23 @@ class LowerDFGToLLVM {
setJSValue(activation);
}

void compileCheckWatchdogTimer()
{
LBasicBlock timerDidFire = FTL_NEW_BLOCK(m_out, ("CheckWatchdogTimer timer did fire"));
LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("CheckWatchdogTimer continuation"));

LValue state = m_out.load8(m_out.absolute(vm().watchdog->timerDidFireAddress()));
m_out.branch(m_out.equal(state, m_out.constInt8(0)),
usually(continuation), rarely(timerDidFire));

LBasicBlock lastNext = m_out.appendTo(timerDidFire, continuation);

vmCall(m_out.operation(operationHandleWatchdogTimer), m_callFrame);
m_out.jump(continuation);

m_out.appendTo(continuation, lastNext);
}

bool isInlinableSize(LValue function)
{
size_t instructionCount = 0;
Expand Down
1 change: 1 addition & 0 deletions Source/JavaScriptCore/jit/JIT.h
Expand Up @@ -739,6 +739,7 @@ namespace JSC {
MacroAssembler::Call callOperation(J_JITOperation_EPc, int, Instruction*);
MacroAssembler::Call callOperation(J_JITOperation_EZ, int, int32_t);
MacroAssembler::Call callOperation(J_JITOperation_EZZ, int, int32_t, int32_t);
MacroAssembler::Call callOperation(P_JITOperation_E);
MacroAssembler::Call callOperation(P_JITOperation_EJS, GPRReg, size_t);
MacroAssembler::Call callOperation(S_JITOperation_ECC, RegisterID, RegisterID);
MacroAssembler::Call callOperation(S_JITOperation_EJ, RegisterID);
Expand Down
6 changes: 6 additions & 0 deletions Source/JavaScriptCore/jit/JITInlines.h
Expand Up @@ -187,6 +187,12 @@ ALWAYS_INLINE MacroAssembler::Call JIT::appendCallWithExceptionCheckSetJSValueRe
return call;
}

ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(P_JITOperation_E operation)
{
setupArgumentsExecState();
return appendCallWithExceptionCheck(operation);
}

ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(C_JITOperation_E operation)
{
setupArgumentsExecState();
Expand Down
8 changes: 7 additions & 1 deletion Source/JavaScriptCore/jit/JITOperations.cpp
Expand Up @@ -988,13 +988,19 @@ EncodedJSValue JIT_OPERATION operationNewRegexp(ExecState* exec, void* regexpPtr
return JSValue::encode(RegExpObject::create(vm, exec->lexicalGlobalObject()->regExpStructure(), regexp));
}

void JIT_OPERATION operationHandleWatchdogTimer(ExecState* exec)
// The only reason for returning an UnusedPtr (instead of void) is so that we can reuse the
// existing DFG slow path generator machinery when creating the slow path for CheckWatchdogTimer
// in the DFG. If a DFG slow path generator that supports a void return type is added in the
// future, we can switch to using that then.
UnusedPtr JIT_OPERATION operationHandleWatchdogTimer(ExecState* exec)
{
VM& vm = exec->vm();
NativeCallFrameTracer tracer(&vm, exec);

if (UNLIKELY(vm.watchdog && vm.watchdog->didFire(exec)))
vm.throwException(exec, createTerminatedExecutionException(&vm));

return nullptr;
}

void JIT_OPERATION operationThrowStaticError(ExecState* exec, EncodedJSValue encodedValue, int32_t referenceErrorFlag)
Expand Down
4 changes: 3 additions & 1 deletion Source/JavaScriptCore/jit/JITOperations.h
Expand Up @@ -51,6 +51,8 @@ class ArrayAllocationProfile;

extern "C" {

typedef char* UnusedPtr;

// These typedefs provide typechecking when generating calls out to helper routines;
// this helps prevent calling a helper routine with the wrong arguments!
/*
Expand Down Expand Up @@ -293,7 +295,7 @@ EncodedJSValue JIT_OPERATION operationNewArrowFunction(ExecState*, JSScope*, JSC
EncodedJSValue JIT_OPERATION operationNewArrowFunctionWithInvalidatedReallocationWatchpoint(ExecState*, JSScope*, JSCell*, EncodedJSValue) WTF_INTERNAL;
JSCell* JIT_OPERATION operationNewObject(ExecState*, Structure*) WTF_INTERNAL;
EncodedJSValue JIT_OPERATION operationNewRegexp(ExecState*, void*) WTF_INTERNAL;
void JIT_OPERATION operationHandleWatchdogTimer(ExecState*) WTF_INTERNAL;
UnusedPtr JIT_OPERATION operationHandleWatchdogTimer(ExecState*) WTF_INTERNAL;
void JIT_OPERATION operationThrowStaticError(ExecState*, EncodedJSValue, int32_t) WTF_INTERNAL;
void JIT_OPERATION operationThrow(ExecState*, EncodedJSValue) WTF_INTERNAL;
void JIT_OPERATION operationDebug(ExecState*, int32_t) WTF_INTERNAL;
Expand Down

0 comments on commit 8af25a5

Please sign in to comment.