Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (188648 => 188649)
--- trunk/Source/_javascript_Core/ChangeLog 2015-08-19 20:41:30 UTC (rev 188648)
+++ trunk/Source/_javascript_Core/ChangeLog 2015-08-19 21:18:15 UTC (rev 188649)
@@ -1,5 +1,44 @@
2015-08-19 Mark Lam <mark....@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....@apple.com>
+
Add ability to save and restore JSC options.
https://bugs.webkit.org/show_bug.cgi?id=148125
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (188648 => 188649)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2015-08-19 20:41:30 UTC (rev 188648)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2015-08-19 21:18:15 UTC (rev 188649)
@@ -4640,14 +4640,17 @@
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()));
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (188648 => 188649)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2015-08-19 20:41:30 UTC (rev 188648)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2015-08-19 21:18:15 UTC (rev 188649)
@@ -4329,14 +4329,17 @@
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:
Modified: trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp (188648 => 188649)
--- trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2015-08-19 20:41:30 UTC (rev 188648)
+++ trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2015-08-19 21:18:15 UTC (rev 188649)
@@ -119,6 +119,7 @@
case CheckBadCell:
case CheckNotEmpty:
case CheckIdent:
+ case CheckWatchdogTimer:
case StringCharCodeAt:
case AllocatePropertyStorage:
case ReallocatePropertyStorage:
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp (188648 => 188649)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2015-08-19 20:41:30 UTC (rev 188648)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2015-08-19 21:18:15 UTC (rev 188649)
@@ -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>
@@ -829,6 +830,9 @@
case MaterializeCreateActivation:
compileMaterializeCreateActivation();
break;
+ case CheckWatchdogTimer:
+ compileCheckWatchdogTimer();
+ break;
case PhantomLocal:
case LoopHint:
@@ -5428,6 +5432,23 @@
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;
Modified: trunk/Source/_javascript_Core/jit/JIT.h (188648 => 188649)
--- trunk/Source/_javascript_Core/jit/JIT.h 2015-08-19 20:41:30 UTC (rev 188648)
+++ trunk/Source/_javascript_Core/jit/JIT.h 2015-08-19 21:18:15 UTC (rev 188649)
@@ -739,6 +739,7 @@
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);
Modified: trunk/Source/_javascript_Core/jit/JITInlines.h (188648 => 188649)
--- trunk/Source/_javascript_Core/jit/JITInlines.h 2015-08-19 20:41:30 UTC (rev 188648)
+++ trunk/Source/_javascript_Core/jit/JITInlines.h 2015-08-19 21:18:15 UTC (rev 188649)
@@ -187,6 +187,12 @@
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();
Modified: trunk/Source/_javascript_Core/jit/JITOperations.cpp (188648 => 188649)
--- trunk/Source/_javascript_Core/jit/JITOperations.cpp 2015-08-19 20:41:30 UTC (rev 188648)
+++ trunk/Source/_javascript_Core/jit/JITOperations.cpp 2015-08-19 21:18:15 UTC (rev 188649)
@@ -988,13 +988,19 @@
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)
Modified: trunk/Source/_javascript_Core/jit/JITOperations.h (188648 => 188649)
--- trunk/Source/_javascript_Core/jit/JITOperations.h 2015-08-19 20:41:30 UTC (rev 188648)
+++ trunk/Source/_javascript_Core/jit/JITOperations.h 2015-08-19 21:18:15 UTC (rev 188649)
@@ -51,6 +51,8 @@
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!
/*
@@ -293,7 +295,7 @@
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;