FTL OSR exit shouldn't make X86-specific assumptions
https://bugs.webkit.org/show_bug.cgi?id=128890
Reviewed by Mark Hahnenberg.
Mostly this is about not using push/pop, but instead using the more abstract pushToSave() and popToRestore() while reflecting on the stack alignment.
* assembler/MacroAssembler.h:
(JSC::MacroAssembler::pushToSaveImmediateWithoutTouchingRegisters):
(JSC::MacroAssembler::pushToSaveByteOffset):
* assembler/MacroAssemblerARM64.h:
(JSC::MacroAssemblerARM64::pushToSaveImmediateWithoutTouchingRegisters):
(JSC::MacroAssemblerARM64::pushToSaveByteOffset):
* ftl/FTLExitThunkGenerator.cpp:
(JSC::FTL::ExitThunkGenerator::emitThunk):
* ftl/FTLOSRExitCompiler.cpp:
(JSC::FTL::compileStub):
* ftl/FTLThunks.cpp:
(JSC::FTL::osrExitGenerationThunkGenerator):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@164228 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/ftl/FTLExitThunkGenerator.cpp b/Source/JavaScriptCore/ftl/FTLExitThunkGenerator.cpp
index 86c8723..3d40bdf 100644
--- a/Source/JavaScriptCore/ftl/FTLExitThunkGenerator.cpp
+++ b/Source/JavaScriptCore/ftl/FTLExitThunkGenerator.cpp
@@ -51,7 +51,7 @@
OSRExitCompilationInfo& info = m_state.finalizer->osrExit[index];
info.m_thunkLabel = label();
- push(TrustedImm32(index));
+ pushToSaveImmediateWithoutTouchingRegisters(TrustedImm32(index));
info.m_thunkJump = patchableJump();
m_didThings = true;
diff --git a/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp b/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp
index f37a6f6..c1eb2f9 100644
--- a/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp
+++ b/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp
@@ -70,14 +70,14 @@
char* registerScratch = bitwise_cast<char*>(scratch + exit.m_values.size());
uint64_t* unwindScratch = bitwise_cast<uint64_t*>(registerScratch + requiredScratchMemorySizeInBytes());
- // Make sure that saveAllRegisters() has a place on top of the stack to spill things. That
- // function expects to be able to use top of stack for scratch memory.
- jit.push(GPRInfo::regT0);
+ // Note that we come in here, the stack used to be as LLVM left it except that someone called pushToSave().
+ // We don't care about the value they saved. But, we do appreciate the fact that they did it, because we use
+ // that slot for saveAllRegisters().
+
saveAllRegisters(jit, registerScratch);
// Bring the stack back into a sane form.
- jit.pop(GPRInfo::regT0);
- jit.pop(GPRInfo::regT0);
+ jit.popToRestore(GPRInfo::regT0);
if (vm->m_perBytecodeProfiler && codeBlock->jitCode()->dfgCommon()->compilation) {
Profiler::Database& database = *vm->m_perBytecodeProfiler;
diff --git a/Source/JavaScriptCore/ftl/FTLThunks.cpp b/Source/JavaScriptCore/ftl/FTLThunks.cpp
index e25407f..0c306c6 100644
--- a/Source/JavaScriptCore/ftl/FTLThunks.cpp
+++ b/Source/JavaScriptCore/ftl/FTLThunks.cpp
@@ -45,11 +45,20 @@
// Note that the "return address" will be the OSR exit ID.
+ ptrdiff_t stackMisalignment = MacroAssembler::pushToSaveByteOffset();
+
// Pretend that we're a C call frame.
- jit.push(MacroAssembler::framePointerRegister);
+ jit.pushToSave(MacroAssembler::framePointerRegister);
jit.move(MacroAssembler::stackPointerRegister, MacroAssembler::framePointerRegister);
- jit.push(GPRInfo::regT0);
- jit.push(GPRInfo::regT0);
+ stackMisalignment += MacroAssembler::pushToSaveByteOffset();
+
+ // Now create ourselves enough stack space to give saveAllRegisters() a scratch slot.
+ unsigned numberOfRequiredPops = 0;
+ do {
+ jit.pushToSave(GPRInfo::regT0);
+ stackMisalignment += MacroAssembler::pushToSaveByteOffset();
+ numberOfRequiredPops++;
+ } while (stackMisalignment % stackAlignmentBytes());
ScratchBuffer* scratchBuffer = vm->scratchBufferForSize(requiredScratchMemorySizeInBytes());
char* buffer = static_cast<char*>(scratchBuffer->dataBuffer());
@@ -61,7 +70,7 @@
jit.storePtr(MacroAssembler::TrustedImmPtr(requiredScratchMemorySizeInBytes()), GPRInfo::nonArgGPR1);
jit.loadPtr(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
- jit.peek(GPRInfo::argumentGPR1, 3);
+ jit.peek(GPRInfo::argumentGPR1, (stackMisalignment / sizeof(void*)) - 1);
MacroAssembler::Call functionCall = jit.call();
// At this point we want to make a tail call to what was returned to us in the
@@ -76,9 +85,9 @@
jit.storePtr(MacroAssembler::TrustedImmPtr(0), GPRInfo::regT1);
// Prepare for tail call.
- jit.pop(GPRInfo::regT1);
- jit.pop(GPRInfo::regT1);
- jit.pop(MacroAssembler::framePointerRegister);
+ while (numberOfRequiredPops--)
+ jit.popToRestore(GPRInfo::regT1);
+ jit.popToRestore(MacroAssembler::framePointerRegister);
// At this point we're sitting on the return address - so if we did a jump right now, the
// tail-callee would be happy. Instead we'll stash the callee in the return address and then