Modified: branches/jsc-tailcall/Source/_javascript_Core/ChangeLog (188985 => 188986)
--- branches/jsc-tailcall/Source/_javascript_Core/ChangeLog 2015-08-26 20:38:42 UTC (rev 188985)
+++ branches/jsc-tailcall/Source/_javascript_Core/ChangeLog 2015-08-26 20:43:35 UTC (rev 188986)
@@ -1,5 +1,27 @@
2015-08-26 Michael Saboff <msab...@apple.com>
+ jsc-tailcall: Integrate FTL OSR entry / exit and exceptions handling of callee save registers with other tiers
+ https://bugs.webkit.org/show_bug.cgi?id=148099
+
+ Reviewed by Basile Clement.
+
+ Turned off register preservation thunks for outgoing calls from FTL generated code.
+ Handled callee saves registers for DFG to FTL OSR entry.
+ Fxed the FTL OSR exit compiler to restore the callee saves from an FTL function to
+ either the baseline call frame for callee saves the baseline handles or directly to
+ the callee save register itself.
+
+ * bytecode/CallLinkInfo.h:
+ (JSC::CallLinkInfo::setUpCallFromFTL):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * ftl/FTLCompile.cpp:
+ (JSC::FTL::fixFunctionBasedOnStackMaps):
+ * ftl/FTLOSRExitCompiler.cpp:
+ (JSC::FTL::compileStub):
+
+2015-08-26 Michael Saboff <msab...@apple.com>
+
Unreviewed build fix for release builds after r188937.
* jit/CallFrameShuffler.cpp:
Modified: branches/jsc-tailcall/Source/_javascript_Core/bytecode/CallLinkInfo.h (188985 => 188986)
--- branches/jsc-tailcall/Source/_javascript_Core/bytecode/CallLinkInfo.h 2015-08-26 20:38:42 UTC (rev 188985)
+++ branches/jsc-tailcall/Source/_javascript_Core/bytecode/CallLinkInfo.h 2015-08-26 20:43:35 UTC (rev 188986)
@@ -161,7 +161,7 @@
CodeLocationNearCall callReturnLocation, CodeLocationDataLabelPtr hotPathBegin,
CodeLocationNearCall hotPathOther, unsigned calleeGPR)
{
- m_registerPreservationMode = static_cast<unsigned>(MustPreserveRegisters);
+ m_registerPreservationMode = static_cast<unsigned>(RegisterPreservationNotRequired);
m_callType = callType;
m_codeOrigin = codeOrigin;
m_callReturnLocation = callReturnLocation;
Modified: branches/jsc-tailcall/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (188985 => 188986)
--- branches/jsc-tailcall/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2015-08-26 20:38:42 UTC (rev 188985)
+++ branches/jsc-tailcall/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2015-08-26 20:43:35 UTC (rev 188986)
@@ -4818,6 +4818,7 @@
TrustedImm32(m_stream->size()));
appendCallSetResult(triggerOSREntryNow, tempGPR);
MacroAssembler::Jump dontEnter = m_jit.branchTestPtr(MacroAssembler::Zero, tempGPR);
+ m_jit.emitRestoreCalleeSaves();
m_jit.jump(tempGPR);
dontEnter.link(&m_jit);
silentFillAllRegisters(tempGPR);
Modified: branches/jsc-tailcall/Source/_javascript_Core/ftl/FTLCompile.cpp (188985 => 188986)
--- branches/jsc-tailcall/Source/_javascript_Core/ftl/FTLCompile.cpp 2015-08-26 20:38:42 UTC (rev 188985)
+++ branches/jsc-tailcall/Source/_javascript_Core/ftl/FTLCompile.cpp 2015-08-26 20:43:35 UTC (rev 188986)
@@ -366,12 +366,14 @@
// At this point it's perfectly fair to just blow away all state and restore the
// JS JIT view of the universe.
+ checkJIT.copyCalleeSavesToVMCalleeSavesBuffer();
checkJIT.move(MacroAssembler::TrustedImmPtr(&vm), GPRInfo::argumentGPR0);
checkJIT.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1);
MacroAssembler::Call callLookupExceptionHandler = checkJIT.call();
checkJIT.jumpToExceptionHandler();
stackOverflowException = checkJIT.label();
+ checkJIT.copyCalleeSavesToVMCalleeSavesBuffer();
checkJIT.move(MacroAssembler::TrustedImmPtr(&vm), GPRInfo::argumentGPR0);
checkJIT.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1);
MacroAssembler::Call callLookupExceptionHandlerFromCallerFrame = checkJIT.call();
Modified: branches/jsc-tailcall/Source/_javascript_Core/ftl/FTLOSRExitCompiler.cpp (188985 => 188986)
--- branches/jsc-tailcall/Source/_javascript_Core/ftl/FTLOSRExitCompiler.cpp 2015-08-26 20:38:42 UTC (rev 188985)
+++ branches/jsc-tailcall/Source/_javascript_Core/ftl/FTLOSRExitCompiler.cpp 2015-08-26 20:43:35 UTC (rev 188986)
@@ -404,10 +404,12 @@
jit.add32(GPRInfo::regT3, GPRInfo::regT2);
arityIntact.link(&jit);
+ CodeBlock* baselineCodeBlock = jit.baselineCodeBlockFor(exit.m_codeOrigin);
+
// First set up SP so that our data doesn't get clobbered by signals.
unsigned conservativeStackDelta =
registerPreservationOffset() +
- exit.m_values.numberOfLocals() * sizeof(Register) +
+ (exit.m_values.numberOfLocals() + baselineCodeBlock->calleeSaveSpaceAsVirtualRegisters()) * sizeof(Register) +
maxFrameExtentForSlowPathCall;
conservativeStackDelta = WTF::roundUpToMultipleOf(
stackAlignmentBytes(), conservativeStackDelta);
@@ -429,67 +431,44 @@
jit.store64(GPRInfo::regT0, GPRInfo::regT1);
jit.addPtr(MacroAssembler::TrustedImm32(sizeof(Register)), GPRInfo::regT1);
jit.branchTest32(MacroAssembler::NonZero, GPRInfo::regT2).linkTo(loop, &jit);
-
- // At this point regT1 points to where we would save our registers. Save them here.
- ptrdiff_t currentOffset = 0;
+
+ RegisterAtOffsetList* baselineCalleeSaves = baselineCodeBlock->calleeSaveRegisters();
+
for (Reg reg = Reg::first(); reg <= Reg::last(); reg = reg.next()) {
- if (!toSave.get(reg))
+ if (!toSave.get(reg) || !reg.isGPR())
continue;
- currentOffset += sizeof(Register);
unsigned unwindIndex = codeBlock->calleeSaveRegisters()->indexOf(reg);
+ RegisterAtOffset* baselineRegisterOffset = baselineCalleeSaves->find(reg);
+
if (unwindIndex == UINT_MAX) {
// The FTL compilation didn't preserve this register. This means that it also
// didn't use the register. So its value at the beginning of OSR exit should be
// preserved by the thunk. Luckily, we saved all registers into the register
// scratch buffer, so we can restore them from there.
- jit.load64(registerScratch + offsetOfReg(reg), GPRInfo::regT0);
+ jit.load64(registerScratch + offsetOfReg(reg), reg.gpr());
} else {
// The FTL compilation preserved the register. Its new value is therefore
// irrelevant, but we can get the value that was preserved by using the unwind
// data. We've already copied all unwind-able preserved registers into the unwind
// scratch buffer, so we can get it from there.
- jit.load64(unwindScratch + unwindIndex, GPRInfo::regT0);
+ jit.load64(unwindScratch + unwindIndex, reg.gpr());
}
- jit.store64(GPRInfo::regT0, AssemblyHelpers::Address(GPRInfo::regT1, currentOffset));
+
+ if (baselineRegisterOffset)
+ jit.store64(reg.gpr(), MacroAssembler::Address(MacroAssembler::framePointerRegister, baselineRegisterOffset->offset()));
}
-
- // We need to make sure that we return into the register restoration thunk. This works
- // differently depending on whether or not we had arity issues.
- MacroAssembler::Jump arityIntactForReturnPC = jit.branch32(
- MacroAssembler::GreaterThanOrEqual,
- CCallHelpers::payloadFor(JSStack::ArgumentCount),
- MacroAssembler::TrustedImm32(codeBlock->numParameters()));
-
- // The return PC in the call frame header points at exactly the right arity restoration
- // thunk. We don't want to change that. But the arity restoration thunk's frame has a
- // return PC and we want to reroute that to our register restoration thunk. The arity
- // restoration's return PC just just below regT1, and the register restoration's return PC
- // is right at regT1.
- jit.loadPtr(MacroAssembler::Address(GPRInfo::regT1, -static_cast<ptrdiff_t>(sizeof(Register))), GPRInfo::regT0);
- jit.storePtr(GPRInfo::regT0, GPRInfo::regT1);
- jit.storePtr(
- MacroAssembler::TrustedImmPtr(vm->getCTIStub(registerRestorationThunkGenerator).code().executableAddress()),
- MacroAssembler::Address(GPRInfo::regT1, -static_cast<ptrdiff_t>(sizeof(Register))));
-
- MacroAssembler::Jump arityReturnPCReady = jit.jump();
+ size_t baselineVirtualRegistersForCalleeSaves = baselineCodeBlock->calleeSaveSpaceAsVirtualRegisters();
- arityIntactForReturnPC.link(&jit);
-
- jit.loadPtr(MacroAssembler::Address(MacroAssembler::framePointerRegister, CallFrame::returnPCOffset()), GPRInfo::regT0);
- jit.storePtr(GPRInfo::regT0, GPRInfo::regT1);
- jit.storePtr(
- MacroAssembler::TrustedImmPtr(vm->getCTIStub(registerRestorationThunkGenerator).code().executableAddress()),
- MacroAssembler::Address(MacroAssembler::framePointerRegister, CallFrame::returnPCOffset()));
-
- arityReturnPCReady.link(&jit);
-
// Now get state out of the scratch buffer and place it back into the stack. The values are
// already reboxed so we just move them.
for (unsigned index = exit.m_values.size(); index--;) {
- int operand = exit.m_values.operandForIndex(index);
-
+ VirtualRegister reg = exit.m_values.virtualRegisterForIndex(index);
+
+ if (reg.isLocal() && reg.toLocal() < static_cast<int>(baselineVirtualRegistersForCalleeSaves))
+ continue;
+
jit.load64(scratch + index, GPRInfo::regT0);
- jit.store64(GPRInfo::regT0, AssemblyHelpers::addressFor(static_cast<VirtualRegister>(operand)));
+ jit.store64(GPRInfo::regT0, AssemblyHelpers::addressFor(reg));
}
handleExitCounts(jit, exit);