- Revision
- 114675
- Author
- fpi...@apple.com
- Date
- 2012-04-19 14:55:00 -0700 (Thu, 19 Apr 2012)
Log Message
It should be possible to perform debugCall on ARMv7
https://bugs.webkit.org/show_bug.cgi?id=84381
Reviewed by Oliver Hunt.
debugCall() was clobbering the argument to the call it was making, leading to a
corrupt ExecState*. This change fixes that issue by using a scratch register that
does not clobber arguments, and it also introduces more assertions that we have
a valid call frame.
* dfg/DFGAssemblyHelpers.cpp:
(DFG):
(JSC::DFG::AssemblyHelpers::jitAssertHasValidCallFrame):
* dfg/DFGAssemblyHelpers.h:
(JSC::DFG::AssemblyHelpers::selectScratchGPR):
(AssemblyHelpers):
(JSC::DFG::AssemblyHelpers::debugCall):
(JSC::DFG::AssemblyHelpers::jitAssertHasValidCallFrame):
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::linkOSRExits):
* dfg/DFGOSRExitCompiler.cpp:
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::selectScratchGPR):
Modified Paths
Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (114674 => 114675)
--- trunk/Source/_javascript_Core/ChangeLog 2012-04-19 21:32:41 UTC (rev 114674)
+++ trunk/Source/_javascript_Core/ChangeLog 2012-04-19 21:55:00 UTC (rev 114675)
@@ -1,5 +1,33 @@
2012-04-19 Filip Pizlo <fpi...@apple.com>
+ It should be possible to perform debugCall on ARMv7
+ https://bugs.webkit.org/show_bug.cgi?id=84381
+
+ Reviewed by Oliver Hunt.
+
+ debugCall() was clobbering the argument to the call it was making, leading to a
+ corrupt ExecState*. This change fixes that issue by using a scratch register that
+ does not clobber arguments, and it also introduces more assertions that we have
+ a valid call frame.
+
+ * dfg/DFGAssemblyHelpers.cpp:
+ (DFG):
+ (JSC::DFG::AssemblyHelpers::jitAssertHasValidCallFrame):
+ * dfg/DFGAssemblyHelpers.h:
+ (JSC::DFG::AssemblyHelpers::selectScratchGPR):
+ (AssemblyHelpers):
+ (JSC::DFG::AssemblyHelpers::debugCall):
+ (JSC::DFG::AssemblyHelpers::jitAssertHasValidCallFrame):
+ * dfg/DFGJITCompiler.cpp:
+ (JSC::DFG::JITCompiler::linkOSRExits):
+ * dfg/DFGOSRExitCompiler.cpp:
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::selectScratchGPR):
+
+2012-04-19 Filip Pizlo <fpi...@apple.com>
+
LLInt no-JIT fallback native call trampoline's exception handler incorrectly assumes that
the PB/PC has been preserved
https://bugs.webkit.org/show_bug.cgi?id=84367
Modified: trunk/Source/_javascript_Core/dfg/DFGAssemblyHelpers.cpp (114674 => 114675)
--- trunk/Source/_javascript_Core/dfg/DFGAssemblyHelpers.cpp 2012-04-19 21:32:41 UTC (rev 114674)
+++ trunk/Source/_javascript_Core/dfg/DFGAssemblyHelpers.cpp 2012-04-19 21:55:00 UTC (rev 114675)
@@ -140,6 +140,13 @@
checkCell.link(this);
}
#endif // USE(JSVALUE32_64)
+
+void AssemblyHelpers::jitAssertHasValidCallFrame()
+{
+ Jump checkCFR = branchTestPtr(Zero, GPRInfo::callFrameRegister, TrustedImm32(7));
+ breakpoint();
+ checkCFR.link(this);
+}
#endif // DFG_ENABLE(JIT_ASSERT)
} } // namespace JSC::DFG
Modified: trunk/Source/_javascript_Core/dfg/DFGAssemblyHelpers.h (114674 => 114675)
--- trunk/Source/_javascript_Core/dfg/DFGAssemblyHelpers.h 2012-04-19 21:32:41 UTC (rev 114674)
+++ trunk/Source/_javascript_Core/dfg/DFGAssemblyHelpers.h 2012-04-19 21:55:00 UTC (rev 114675)
@@ -150,6 +150,23 @@
return branch8(Below, Address(structureReg, Structure::typeInfoTypeOffset()), TrustedImm32(ObjectType));
}
+ static GPRReg selectScratchGPR(GPRReg preserve1 = InvalidGPRReg, GPRReg preserve2 = InvalidGPRReg, GPRReg preserve3 = InvalidGPRReg, GPRReg preserve4 = InvalidGPRReg)
+ {
+ if (preserve1 != GPRInfo::regT0 && preserve2 != GPRInfo::regT0 && preserve3 != GPRInfo::regT0 && preserve4 != GPRInfo::regT0)
+ return GPRInfo::regT0;
+
+ if (preserve1 != GPRInfo::regT1 && preserve2 != GPRInfo::regT1 && preserve3 != GPRInfo::regT1 && preserve4 != GPRInfo::regT1)
+ return GPRInfo::regT1;
+
+ if (preserve1 != GPRInfo::regT2 && preserve2 != GPRInfo::regT2 && preserve3 != GPRInfo::regT2 && preserve4 != GPRInfo::regT2)
+ return GPRInfo::regT2;
+
+ if (preserve1 != GPRInfo::regT3 && preserve2 != GPRInfo::regT3 && preserve3 != GPRInfo::regT3 && preserve4 != GPRInfo::regT3)
+ return GPRInfo::regT3;
+
+ return GPRInfo::regT4;
+ }
+
// Add a debug call. This call has no effect on JIT code execution state.
void debugCall(V_DFGDebugOperation_EP function, void* argument)
{
@@ -164,14 +181,16 @@
#if CPU(X86_64) || CPU(ARM_THUMB2)
move(TrustedImmPtr(argument), GPRInfo::argumentGPR1);
move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+ GPRReg scratch = selectScratchGPR(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1);
#elif CPU(X86)
poke(GPRInfo::callFrameRegister, 0);
poke(TrustedImmPtr(argument), 1);
+ GPRReg scratch = GPRInfo::regT0;
#else
#error "DFG JIT not supported on this platform."
#endif
- move(TrustedImmPtr(reinterpret_cast<void*>(function)), GPRInfo::regT0);
- call(GPRInfo::regT0);
+ move(TrustedImmPtr(reinterpret_cast<void*>(function)), scratch);
+ call(scratch);
for (unsigned i = 0; i < FPRInfo::numberOfRegisters; ++i) {
move(TrustedImmPtr(buffer + GPRInfo::numberOfRegisters + i), GPRInfo::regT0);
loadDouble(GPRInfo::regT0, FPRInfo::toRegister(i));
@@ -187,12 +206,14 @@
void jitAssertIsJSNumber(GPRReg);
void jitAssertIsJSDouble(GPRReg);
void jitAssertIsCell(GPRReg);
+ void jitAssertHasValidCallFrame();
#else
void jitAssertIsInt32(GPRReg) { }
void jitAssertIsJSInt32(GPRReg) { }
void jitAssertIsJSNumber(GPRReg) { }
void jitAssertIsJSDouble(GPRReg) { }
void jitAssertIsCell(GPRReg) { }
+ void jitAssertHasValidCallFrame() { }
#endif
// These methods convert between doubles, and doubles boxed and JSValues.
Modified: trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp (114674 => 114675)
--- trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp 2012-04-19 21:32:41 UTC (rev 114674)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp 2012-04-19 21:55:00 UTC (rev 114675)
@@ -44,6 +44,7 @@
for (unsigned i = 0; i < codeBlock()->numberOfOSRExits(); ++i) {
OSRExit& exit = codeBlock()->osrExit(i);
exit.m_check.initialJump().link(this);
+ jitAssertHasValidCallFrame();
store32(TrustedImm32(i), &globalData()->osrExitIndex);
beginUninterruptedSequence();
exit.m_check.switchToLateJump(jump());
Modified: trunk/Source/_javascript_Core/dfg/DFGOSRExitCompiler.cpp (114674 => 114675)
--- trunk/Source/_javascript_Core/dfg/DFGOSRExitCompiler.cpp 2012-04-19 21:32:41 UTC (rev 114674)
+++ trunk/Source/_javascript_Core/dfg/DFGOSRExitCompiler.cpp 2012-04-19 21:55:00 UTC (rev 114675)
@@ -74,7 +74,8 @@
{
AssemblyHelpers jit(globalData, codeBlock);
OSRExitCompiler exitCompiler(jit);
-
+
+ jit.jitAssertHasValidCallFrame();
exitCompiler.compileExit(exit, recovery);
LinkBuffer patchBuffer(*globalData, &jit, codeBlock);
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (114674 => 114675)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2012-04-19 21:32:41 UTC (rev 114674)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2012-04-19 21:55:00 UTC (rev 114675)
@@ -931,6 +931,8 @@
#if DFG_ENABLE(JIT_BREAK_ON_EVERY_BLOCK)
m_jit.breakpoint();
#endif
+
+ m_jit.jitAssertHasValidCallFrame();
ASSERT(m_arguments.size() == block.variablesAtHead.numberOfArguments());
for (size_t i = 0; i < m_arguments.size(); ++i) {
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (114674 => 114675)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2012-04-19 21:32:41 UTC (rev 114674)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2012-04-19 21:55:00 UTC (rev 114675)
@@ -342,19 +342,7 @@
static GPRReg selectScratchGPR(GPRReg preserve1 = InvalidGPRReg, GPRReg preserve2 = InvalidGPRReg, GPRReg preserve3 = InvalidGPRReg, GPRReg preserve4 = InvalidGPRReg)
{
- if (preserve1 != GPRInfo::regT0 && preserve2 != GPRInfo::regT0 && preserve3 != GPRInfo::regT0 && preserve4 != GPRInfo::regT0)
- return GPRInfo::regT0;
-
- if (preserve1 != GPRInfo::regT1 && preserve2 != GPRInfo::regT1 && preserve3 != GPRInfo::regT1 && preserve4 != GPRInfo::regT1)
- return GPRInfo::regT1;
-
- if (preserve1 != GPRInfo::regT2 && preserve2 != GPRInfo::regT2 && preserve3 != GPRInfo::regT2 && preserve4 != GPRInfo::regT2)
- return GPRInfo::regT2;
-
- if (preserve1 != GPRInfo::regT3 && preserve2 != GPRInfo::regT3 && preserve3 != GPRInfo::regT3 && preserve4 != GPRInfo::regT3)
- return GPRInfo::regT3;
-
- return GPRInfo::regT4;
+ return AssemblyHelpers::selectScratchGPR(preserve1, preserve2, preserve3, preserve4);
}
// Called by the speculative operand types, below, to fill operand to