Diff
Modified: branches/jsc-tailcall/Source/_javascript_Core/ChangeLog (188070 => 188071)
--- branches/jsc-tailcall/Source/_javascript_Core/ChangeLog 2015-08-06 22:40:11 UTC (rev 188070)
+++ branches/jsc-tailcall/Source/_javascript_Core/ChangeLog 2015-08-06 22:41:51 UTC (rev 188071)
@@ -1,3 +1,124 @@
+2015-08-06 Michael Saboff <msab...@apple.com>
+
+ jsc-tailcall: Exceptions should properly restore callee save register contents during unwinding
+ https://bugs.webkit.org/show_bug.cgi?id=147639
+
+ Reviewed by Basile Clement.
+
+ Added handling of callee save register restoration to exception handling.
+ The basic flow is when an exception is thrown or one is recognized to have been
+ generated in C++ code, we save the current state of all callee save registers to
+ VM::calleeSaveRegistersBuffer. As we unwind looking for the corresponding catch,
+ we copy the callee saves from call frames to the same VM::calleeSaveRegistersBuffer.
+ This is done for all call frames on the stack up to but not including the call
+ frame that has the corresponding catch block. When we process the catch, we
+ restore the callee save registers with the contents of VM::calleeSaveRegistersBuffer.
+ If there isn't a catch, then handleUncaughtException will restore callee saves
+ before it returns back to the calling C++.
+
+ As part of this change, restructured callee save handling in OSR exit handlers so
+ that we always use the current values of the tag registers for boxing. Also
+ eliminated the writing out of undefined for the baseline's callee saves slots.
+
+ Eliminated callee saves registers as possible locals for various thunk generation
+ as the callee saves may not have been saved by the function calling the thunk.
+
+ Cleaned up the static RegisterSet's including added one for LLInt callee saves and
+ one to be used to allocate local registers not including the callee saves or other
+ special registers.
+
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::CodeBlock): Set the initial callee saves to what the LLInt needs.
+
+ * dfg/DFGJITCompiler.cpp:
+ (JSC::DFG::JITCompiler::compileExceptionHandlers):
+ * interpreter/Interpreter.cpp:
+ (JSC::UnwindFunctor::operator()):
+ (JSC::UnwindFunctor::copyCalleeSavesToVMCalleeSavesBuffer):
+ * jit/AssemblyHelpers.h:
+ (JSC::AssemblyHelpers::emitRestoreCalleeSaves):
+ * jit/JIT.cpp:
+ (JSC::JIT::emitEnterOptimizationCheck):
+ (JSC::JIT::privateCompileExceptionHandlers):
+ * jit/JITOpcodes.cpp:
+ (JSC::JIT::emit_op_throw):
+ * jit/JITOpcodes32_64.cpp:
+ (JSC::JIT::emit_op_throw):
+ * jit/Repatch.cpp:
+ (JSC::generateByIdStub):
+ * jit/ThunkGenerators.cpp:
+ (JSC::throwExceptionFromCallSlowPathGenerator):
+ (JSC::nativeForGenerator):
+ * llint/LowLevelInterpreter32.asm:
+ (_llint_throw_from_slow_path_trampoline):
+ * llint/LowLevelInterpreter64.asm:
+ (_llint_throw_from_slow_path_trampoline):
+ * llint/LowLevelInterpreter.asm:
+ (copyCalleeSavesToVMCalleeSavesBuffer):
+ Copy callee saves register contents to VM::calleeSaveRegistersBuffer.
+
+ * jit/AssemblyHelpers.h:
+ (JSC::AssemblyHelpers::restoreCalleeSavesFromVMCalleeSavesBuffer):
+ * jit/JITOpcodes.cpp:
+ (JSC::JIT::emit_op_catch):
+ * jit/JITOpcodes32_64.cpp:
+ (JSC::JIT::emit_op_catch):
+ * llint/LowLevelInterpreter32.asm:
+ (_handleUncaughtException):
+ (_llint_op_catch):
+ * llint/LowLevelInterpreter64.asm:
+ (_handleUncaughtException):
+ (_llint_op_catch):
+ * llint/LowLevelInterpreter.asm:
+ (restoreCalleeSavesFromVMCalleeSavesBuffer):
+ Restore callee saves register contents from VM::calleeSaveRegistersBuffer.
+
+ * dfg/DFGOSRExitCompiler32_64.cpp:
+ (JSC::DFG::OSRExitCompiler::compileExit):
+ * dfg/DFGOSRExitCompiler64.cpp:
+ (JSC::DFG::OSRExitCompiler::compileExit):
+ * dfg/DFGOSRExitCompilerCommon.cpp:
+ Restore callee saves from the DFG and save the appropriate ones for the baseline JIT.
+ Materialize the tag registers on 64 bit platforms.
+
+ (JSC::DFG::adjustAndJumpToTarget):
+ * jit/AssemblyHelpers.h:
+ (JSC::AssemblyHelpers::copyCalleeSavesToVMCalleeSavesBuffer):
+ (JSC::AssemblyHelpers::copyCalleeSavesFromFrameToVMCalleeSavesBuffer):
+ (JSC::AssemblyHelpers::copyCalleeSavesFromFrameOrRegisterToVMCalleeSavesBuffer):
+ * jit/CCallHelpers.h:
+ (JSC::CCallHelpers::jumpToExceptionHandler):
+ (JSC::CCallHelpers::prepareForTailCallSlow):
+ * jit/JITOpcodes.cpp:
+ (JSC::JIT::emitSlow_op_loop_hint):
+ * jit/JITPropertyAccess.cpp:
+ (JSC::JIT::emit_op_get_by_id):
+ (JSC::JIT::emit_op_put_by_id):
+ * jit/JITPropertyAccess32_64.cpp:
+ (JSC::JIT::emit_op_get_by_id):
+ (JSC::JIT::emit_op_put_by_id):
+ * jit/RegisterSet.cpp:
+ (JSC::RegisterSet::specialRegisters):
+ (JSC::RegisterSet::nonTempRegisters):
+ (JSC::RegisterSet::calleeSaveRegisters):
+ (JSC::RegisterSet::llintCalleeSaveRegisters):
+ (JSC::RegisterSet::baselineCalleeSaveRegisters):
+ (JSC::RegisterSet::dfgCalleeSaveRegisters):
+ (JSC::RegisterSet::allVMCalleeSaveRegisters):
+ (JSC::RegisterSet::allGPRs):
+ * jit/RegisterSet.h:
+ Added LLInt callee saves register set.
+ Updated the register set of used registers to include callee saves.
+
+ * jit/GPRInfo.h:
+ * llint/LowLevelInterpreter.asm:
+ (preserveCalleeSavesUsedByLLInt):
+ (restoreCalleeSavesUsedByLLInt):
+ Fixed numberOfLLIntBaselineCalleeSaveRegisters for X86-64 Windows.
+
+ * llint/LowLevelInterpreter.asm:
+ (prologue): Moved callee save preservation to before we overwrite the PC callee save.
+
2015-08-04 Michael Saboff <msab...@apple.com>
jsc-tailcall: Align callee save registers names across LLInt and JITs
Modified: branches/jsc-tailcall/Source/_javascript_Core/bytecode/CodeBlock.cpp (188070 => 188071)
--- branches/jsc-tailcall/Source/_javascript_Core/bytecode/CodeBlock.cpp 2015-08-06 22:40:11 UTC (rev 188070)
+++ branches/jsc-tailcall/Source/_javascript_Core/bytecode/CodeBlock.cpp 2015-08-06 22:41:51 UTC (rev 188071)
@@ -1879,6 +1879,10 @@
if (size_t size = unlinkedCodeBlock->numberOfObjectAllocationProfiles())
m_objectAllocationProfiles.resizeToFit(size);
+#if ENABLE(JIT)
+ setCalleeSaveRegisters(RegisterSet::llintCalleeSaveRegisters());
+#endif
+
// Copy and translate the UnlinkedInstructions
unsigned instructionCount = unlinkedCodeBlock->instructions().count();
UnlinkedInstructionStream::Reader instructionReader(unlinkedCodeBlock->instructions());
Modified: branches/jsc-tailcall/Source/_javascript_Core/dfg/DFGJITCompiler.cpp (188070 => 188071)
--- branches/jsc-tailcall/Source/_javascript_Core/dfg/DFGJITCompiler.cpp 2015-08-06 22:40:11 UTC (rev 188070)
+++ branches/jsc-tailcall/Source/_javascript_Core/dfg/DFGJITCompiler.cpp 2015-08-06 22:41:51 UTC (rev 188071)
@@ -123,6 +123,8 @@
if (!m_exceptionChecksWithCallFrameRollback.empty()) {
m_exceptionChecksWithCallFrameRollback.link(this);
+ copyCalleeSavesToVMCalleeSavesBuffer();
+
// lookupExceptionHandlerFromCallerFrame is passed two arguments, the VM and the exec (the CallFrame*).
move(TrustedImmPtr(vm()), GPRInfo::argumentGPR0);
move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1);
@@ -141,6 +143,8 @@
if (!m_exceptionChecks.empty()) {
m_exceptionChecks.link(this);
+ copyCalleeSavesToVMCalleeSavesBuffer();
+
// lookupExceptionHandler is passed two arguments, the VM and the exec (the CallFrame*).
move(TrustedImmPtr(vm()), GPRInfo::argumentGPR0);
move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1);
Modified: branches/jsc-tailcall/Source/_javascript_Core/dfg/DFGOSRExitCompiler32_64.cpp (188070 => 188071)
--- branches/jsc-tailcall/Source/_javascript_Core/dfg/DFGOSRExitCompiler32_64.cpp 2015-08-06 22:40:11 UTC (rev 188070)
+++ branches/jsc-tailcall/Source/_javascript_Core/dfg/DFGOSRExitCompiler32_64.cpp 2015-08-06 22:41:51 UTC (rev 188071)
@@ -243,12 +243,21 @@
-m_jit.codeBlock()->jitCode()->dfgCommon()->requiredRegisterCountForExit * sizeof(Register)),
CCallHelpers::framePointerRegister, CCallHelpers::stackPointerRegister);
+ // Restore the DFG callee saves and then save the ones the baseline JIT uses.
+ m_jit.emitRestoreCalleeSaves();
+ m_jit.emitSaveCalleeSavesFor(m_jit.baselineCodeBlock());
+
// Do all data format conversions and store the results into the stack.
for (size_t index = 0; index < operands.size(); ++index) {
const ValueRecovery& recovery = operands[index];
- int operand = operands.operandForIndex(index);
-
+ VirtualRegister reg = operands.virtualRegisterForIndex(index);
+
+ if (reg.isLocal() && reg.toLocal() < static_cast<int>(m_jit.baselineCodeBlock()->calleeSaveSpaceAsVirtualRegisters()))
+ continue;
+
+ int operand = reg.offset();
+
switch (recovery.technique()) {
case InPair:
case DisplacedInJSStack:
Modified: branches/jsc-tailcall/Source/_javascript_Core/dfg/DFGOSRExitCompiler64.cpp (188070 => 188071)
--- branches/jsc-tailcall/Source/_javascript_Core/dfg/DFGOSRExitCompiler64.cpp 2015-08-06 22:40:11 UTC (rev 188070)
+++ branches/jsc-tailcall/Source/_javascript_Core/dfg/DFGOSRExitCompiler64.cpp 2015-08-06 22:41:51 UTC (rev 188071)
@@ -203,9 +203,6 @@
// And voila, all GPRs are free to reuse.
- m_jit.emitRestoreCalleeSaves();
- // The code below cannot use any callee save registers.
-
// Save all state from FPRs into the scratch buffer.
for (size_t index = 0; index < operands.size(); ++index) {
@@ -256,12 +253,24 @@
-m_jit.codeBlock()->jitCode()->dfgCommon()->requiredRegisterCountForExit * sizeof(Register)),
CCallHelpers::framePointerRegister, CCallHelpers::stackPointerRegister);
+ // Restore the DFG callee saves and then save the ones the baseline JIT uses.
+ m_jit.emitRestoreCalleeSaves();
+ m_jit.emitSaveCalleeSavesFor(m_jit.baselineCodeBlock());
+
+ // The tag registers are needed to materialize recoveries below.
+ m_jit.emitMaterializeTagCheckRegisters();
+
// Do all data format conversions and store the results into the stack.
for (size_t index = 0; index < operands.size(); ++index) {
const ValueRecovery& recovery = operands[index];
- int operand = operands.operandForIndex(index);
-
+ VirtualRegister reg = operands.virtualRegisterForIndex(index);
+
+ if (reg.isLocal() && reg.toLocal() < static_cast<int>(m_jit.baselineCodeBlock()->calleeSaveSpaceAsVirtualRegisters()))
+ continue;
+
+ int operand = reg.offset();
+
switch (recovery.technique()) {
case InGPR:
case UnboxedCellInGPR:
@@ -322,10 +331,6 @@
}
}
- // The DFG callee saves were restored up above. Save the ones the baseline JIT uses.
-
- m_jit.emitSaveCalleeSavesFor(m_jit.baselineCodeBlock());
-
// Now that things on the stack are recovered, do the arguments recovery. We assume that arguments
// recoveries don't recursively refer to each other. But, we don't try to assume that they only
// refer to certain ranges of locals. Hence why we need to do this here, once the stack is sensible.
Modified: branches/jsc-tailcall/Source/_javascript_Core/dfg/DFGOSRExitCompilerCommon.cpp (188070 => 188071)
--- branches/jsc-tailcall/Source/_javascript_Core/dfg/DFGOSRExitCompilerCommon.cpp 2015-08-06 22:40:11 UTC (rev 188070)
+++ branches/jsc-tailcall/Source/_javascript_Core/dfg/DFGOSRExitCompilerCommon.cpp 2015-08-06 22:41:51 UTC (rev 188071)
@@ -298,8 +298,6 @@
jit.addPtr(AssemblyHelpers::TrustedImm32(JIT::stackPointerOffsetFor(baselineCodeBlock) * sizeof(Register)), GPRInfo::callFrameRegister, AssemblyHelpers::stackPointerRegister);
- jit.emitMaterializeTagCheckRegisters();
-
jit.move(AssemblyHelpers::TrustedImmPtr(jumpTarget), GPRInfo::regT2);
jit.jump(GPRInfo::regT2);
}
Modified: branches/jsc-tailcall/Source/_javascript_Core/interpreter/Interpreter.cpp (188070 => 188071)
--- branches/jsc-tailcall/Source/_javascript_Core/interpreter/Interpreter.cpp 2015-08-06 22:40:11 UTC (rev 188070)
+++ branches/jsc-tailcall/Source/_javascript_Core/interpreter/Interpreter.cpp 2015-08-06 22:41:51 UTC (rev 188071)
@@ -639,10 +639,41 @@
} else
return StackVisitor::Done;
+ copyCalleeSavesToVMCalleeSavesBuffer(visitor);
+
return StackVisitor::Continue;
}
private:
+ void copyCalleeSavesToVMCalleeSavesBuffer(StackVisitor& visitor)
+ {
+#if ENABLE(JIT)
+ if (!visitor->isJSFrame())
+ return;
+
+#if ENABLE(DFG_JIT)
+ if (visitor->inlineCallFrame())
+ return;
+#endif
+ RegisterSaveMap* currentCalleeSaves = m_codeBlock ? m_codeBlock->calleeSaveRegisters() : nullptr;
+
+ if (!currentCalleeSaves)
+ return;
+
+ VM& vm = m_callFrame->vm();
+ RegisterSaveMap* allCalleeSavesMap = vm.getAllCalleeSaveRegistersMap();
+ VirtualRegister calleeSaveBase = virtualRegisterForLocal(m_codeBlock->calleeSaveSpaceAsVirtualRegisters() - 1);
+
+ intptr_t* calleeSaves = reinterpret_cast<intptr_t*>(m_callFrame->registers()) + calleeSaveBase.offset();
+
+ for (Reg reg = Reg::first(); reg <= Reg::last(); reg = reg.next()) {
+ if (currentCalleeSaves->has(reg))
+ vm.calleeSaveRegistersBuffer[allCalleeSavesMap->getIndexFor(reg)] = calleeSaves[currentCalleeSaves->getIndexFor(reg)];
+ }
+#endif
+ }
+
+
VMEntryFrame*& m_vmEntryFrame;
CallFrame*& m_callFrame;
bool m_isTermination;
Modified: branches/jsc-tailcall/Source/_javascript_Core/jit/AssemblyHelpers.h (188070 => 188071)
--- branches/jsc-tailcall/Source/_javascript_Core/jit/AssemblyHelpers.h 2015-08-06 22:40:11 UTC (rev 188070)
+++ branches/jsc-tailcall/Source/_javascript_Core/jit/AssemblyHelpers.h 2015-08-06 22:41:51 UTC (rev 188071)
@@ -34,6 +34,7 @@
#include "JITCode.h"
#include "MacroAssembler.h"
#include "RegisterSaveMap.h"
+#include "RegisterSet.h"
#include "TypeofType.h"
#include "VM.h"
@@ -219,13 +220,44 @@
emitRestoreCalleeSavesFor(codeBlock());
}
- void copyCalleeSavesFromFrameOrRegisterToVMCalleeSavesBuffer(GPRReg tempGPR)
+ void copyCalleeSavesToVMCalleeSavesBuffer(const TempRegisterSet& usedRegisters = { RegisterSet::nonTempRegisters() })
{
+ GPRReg temp1 = usedRegisters.getFreeGPR(0);
+
+ move(TrustedImmPtr(m_vm->calleeSaveRegistersBuffer), temp1);
+
+ RegisterSaveMap* allCalleeSavesMap = m_vm->getAllCalleeSaveRegistersMap();
+
+ for (Reg reg = Reg::first(); reg <= Reg::last(); reg = reg.next()) {
+ if (allCalleeSavesMap->has(reg) && reg.isGPR())
+ storePtr(reg.gpr(), Address(temp1, allCalleeSavesMap->getOffsetFor(reg)));
+ }
+ }
+
+ void restoreCalleeSavesFromVMCalleeSavesBuffer(const TempRegisterSet& usedRegisters = { RegisterSet::nonTempRegisters() })
+ {
+ GPRReg temp1 = usedRegisters.getFreeGPR(0);
+
+ move(TrustedImmPtr(m_vm->calleeSaveRegistersBuffer), temp1);
+
+ RegisterSaveMap* allCalleeSavesMap = m_vm->getAllCalleeSaveRegistersMap();
+
+ for (Reg reg = Reg::first(); reg <= Reg::last(); reg = reg.next()) {
+ if (allCalleeSavesMap->has(reg) && reg.isGPR())
+ loadPtr(Address(temp1, allCalleeSavesMap->getOffsetFor(reg)), reg.gpr());
+ }
+ }
+
+ void copyCalleeSavesFromFrameToVMCalleeSavesBuffer(const TempRegisterSet& usedRegisters = { RegisterSet::nonTempRegisters() })
+ {
+ GPRReg temp1 = usedRegisters.getFreeGPR(0);
+ GPRReg temp2 = usedRegisters.getFreeGPR(1);
+ ASSERT(temp2 != InvalidGPRReg);
+
ASSERT(codeBlock());
// Copy saved calleeSaves on stack or unsaved calleeSaves in register to vm calleeSave buffer
- move(TrustedImmPtr(m_vm), tempGPR);
- addPtr(TrustedImm32(VM::calleeSaveRegistersBufferOffset()), tempGPR);
+ move(TrustedImmPtr(m_vm->calleeSaveRegistersBuffer), temp1);
RegisterSaveMap* allCalleeSavesMap = m_vm->getAllCalleeSaveRegistersMap();
RegisterSaveMap* currentCalleeSaves = codeBlock()->calleeSaveRegisters();
@@ -237,13 +269,46 @@
if (allCalleeSavesMap->has(reg) && reg.isGPR()) {
if (currentCalleeSaves->has(reg)) {
// Load calleeSave from stack into temp register
- regToStore = GPRInfo::regT0;
+ regToStore = temp2;
loadPtr(Address(framePointerRegister, calleeSaveBase.offsetInBytes() + currentCalleeSaves->getOffsetFor(reg)), regToStore);
} else
// Just store callee save directly
regToStore = reg.gpr();
+
+ storePtr(regToStore, Address(temp1, allCalleeSavesMap->getOffsetFor(reg)));
+ }
+ }
+ }
+
+ void copyCalleeSavesFromFrameOrRegisterToVMCalleeSavesBuffer(const TempRegisterSet& usedRegisters = { RegisterSet::nonTempRegisters() })
+ {
+ GPRReg temp1 = usedRegisters.getFreeGPR(0);
+ GPRReg temp2 = usedRegisters.getFreeGPR(1);
+ ASSERT(temp2 != InvalidGPRReg);
+
+ ASSERT(codeBlock());
+
+ // Copy saved calleeSaves on stack or unsaved calleeSaves in register to vm calleeSave buffer
+ move(TrustedImmPtr(m_vm), temp1);
+ addPtr(TrustedImm32(VM::calleeSaveRegistersBufferOffset()), temp1);
+
+ RegisterSaveMap* allCalleeSavesMap = m_vm->getAllCalleeSaveRegistersMap();
+ RegisterSaveMap* currentCalleeSaves = codeBlock()->calleeSaveRegisters();
+ VirtualRegister calleeSaveBase = virtualRegisterForLocal(codeBlock()->calleeSaveSpaceAsVirtualRegisters() - 1);
+
+ for (Reg reg = Reg::first(); reg <= Reg::last(); reg = reg.next()) {
+ GPRReg regToStore;
+
+ if (allCalleeSavesMap->has(reg) && reg.isGPR()) {
+ if (currentCalleeSaves->has(reg)) {
+ // Load calleeSave from stack into temp register
+ regToStore = temp2;
+ loadPtr(Address(framePointerRegister, calleeSaveBase.offsetInBytes() + currentCalleeSaves->getOffsetFor(reg)), regToStore);
+ } else
+ // Just store callee save directly
+ regToStore = reg.gpr();
- storePtr(regToStore, Address(tempGPR, allCalleeSavesMap->getOffsetFor(reg)));
+ storePtr(regToStore, Address(temp1, allCalleeSavesMap->getOffsetFor(reg)));
}
}
}
Modified: branches/jsc-tailcall/Source/_javascript_Core/jit/CCallHelpers.h (188070 => 188071)
--- branches/jsc-tailcall/Source/_javascript_Core/jit/CCallHelpers.h 2015-08-06 22:40:11 UTC (rev 188070)
+++ branches/jsc-tailcall/Source/_javascript_Core/jit/CCallHelpers.h 2015-08-06 22:41:51 UTC (rev 188071)
@@ -2022,7 +2022,7 @@
jump(GPRInfo::regT1);
}
- void prepareForTailCallSlow(const TempRegisterSet& usedRegisters = { RegisterSet::specialRegisters() })
+ void prepareForTailCallSlow(const TempRegisterSet& usedRegisters = { RegisterSet::nonTempRegisters() })
{
GPRReg temp1 = usedRegisters.getFreeGPR(0);
GPRReg temp2 = usedRegisters.getFreeGPR(1);
@@ -2086,7 +2086,7 @@
void prepareForTailCallSlow(GPRReg calleeGPR)
{
- TempRegisterSet usedRegisters { RegisterSet::specialRegisters() };
+ TempRegisterSet usedRegisters { RegisterSet::nonTempRegisters() };
usedRegisters.set(calleeGPR);
prepareForTailCallSlow(usedRegisters);
}
Modified: branches/jsc-tailcall/Source/_javascript_Core/jit/GPRInfo.h (188070 => 188071)
--- branches/jsc-tailcall/Source/_javascript_Core/jit/GPRInfo.h 2015-08-06 22:40:11 UTC (rev 188070)
+++ branches/jsc-tailcall/Source/_javascript_Core/jit/GPRInfo.h 2015-08-06 22:41:51 UTC (rev 188071)
@@ -443,7 +443,7 @@
static const int numberOfLLIntBaselineCalleeSaveRegisters = 3; // rbx, r14 & r15
static const int numberCalleeSaveRegisters = 5;
#else
- static const int numberOfLLIntBaselineCalleeSaveRegisters = 4; // rbx, rdi, r14 & r15
+ static const int numberOfLLIntBaselineCalleeSaveRegisters = 3; // rbx, r14 & r15
static const int numberCalleeSaveRegisters = 7;
#endif
Modified: branches/jsc-tailcall/Source/_javascript_Core/jit/JIT.cpp (188070 => 188071)
--- branches/jsc-tailcall/Source/_javascript_Core/jit/JIT.cpp 2015-08-06 22:40:11 UTC (rev 188070)
+++ branches/jsc-tailcall/Source/_javascript_Core/jit/JIT.cpp 2015-08-06 22:41:51 UTC (rev 188071)
@@ -91,7 +91,7 @@
skipOptimize.append(branchAdd32(Signed, TrustedImm32(Options::executionCounterIncrementForEntry()), AbsoluteAddress(m_codeBlock->addressOfJITExecuteCounter())));
ASSERT(!m_bytecodeOffset);
- copyCalleeSavesFromFrameOrRegisterToVMCalleeSavesBuffer(regT1);
+ copyCalleeSavesFromFrameOrRegisterToVMCalleeSavesBuffer();
callOperation(operationOptimize, m_bytecodeOffset);
skipOptimize.append(branchTestPtr(Zero, returnValueGPR));
@@ -721,6 +721,8 @@
if (!m_exceptionChecksWithCallFrameRollback.empty()) {
m_exceptionChecksWithCallFrameRollback.link(this);
+ copyCalleeSavesToVMCalleeSavesBuffer();
+
// lookupExceptionHandlerFromCallerFrame is passed two arguments, the VM and the exec (the CallFrame*).
move(TrustedImmPtr(vm()), GPRInfo::argumentGPR0);
@@ -738,6 +740,8 @@
if (!m_exceptionChecks.empty()) {
m_exceptionChecks.link(this);
+ copyCalleeSavesToVMCalleeSavesBuffer();
+
// lookupExceptionHandler is passed two arguments, the VM and the exec (the CallFrame*).
move(TrustedImmPtr(vm()), GPRInfo::argumentGPR0);
move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1);
Modified: branches/jsc-tailcall/Source/_javascript_Core/jit/JITOpcodes.cpp (188070 => 188071)
--- branches/jsc-tailcall/Source/_javascript_Core/jit/JITOpcodes.cpp 2015-08-06 22:40:11 UTC (rev 188070)
+++ branches/jsc-tailcall/Source/_javascript_Core/jit/JITOpcodes.cpp 2015-08-06 22:41:51 UTC (rev 188071)
@@ -421,6 +421,7 @@
void JIT::emit_op_throw(Instruction* currentInstruction)
{
ASSERT(regT0 == returnValueGPR);
+ copyCalleeSavesToVMCalleeSavesBuffer();
emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
callOperationNoExceptionCheck(operationThrow, regT0);
jumpToExceptionHandler();
@@ -517,11 +518,8 @@
void JIT::emit_op_catch(Instruction* currentInstruction)
{
- // Gotta restore the tag registers. We could be throwing from FTL, which may
- // clobber them.
- move(TrustedImm64(TagTypeNumber), tagTypeNumberRegister);
- move(TrustedImm64(TagMask), tagMaskRegister);
-
+ restoreCalleeSavesFromVMCalleeSavesBuffer();
+
move(TrustedImmPtr(m_vm), regT3);
load64(Address(regT3, VM::callFrameForThrowOffset()), callFrameRegister);
load64(Address(regT3, VM::vmEntryFrameForThrowOffset()), regT0);
@@ -936,9 +934,9 @@
// Emit the slow path for the JIT optimization check:
if (canBeOptimized()) {
linkSlowCase(iter);
-
- copyCalleeSavesFromFrameOrRegisterToVMCalleeSavesBuffer(regT1);
+ copyCalleeSavesFromFrameOrRegisterToVMCalleeSavesBuffer();
+
callOperation(operationOptimize, m_bytecodeOffset);
Jump noOptimizedEntry = branchTestPtr(Zero, returnValueGPR);
if (!ASSERT_DISABLED) {
Modified: branches/jsc-tailcall/Source/_javascript_Core/jit/JITOpcodes32_64.cpp (188070 => 188071)
--- branches/jsc-tailcall/Source/_javascript_Core/jit/JITOpcodes32_64.cpp 2015-08-06 22:40:11 UTC (rev 188070)
+++ branches/jsc-tailcall/Source/_javascript_Core/jit/JITOpcodes32_64.cpp 2015-08-06 22:41:51 UTC (rev 188071)
@@ -743,6 +743,7 @@
void JIT::emit_op_throw(Instruction* currentInstruction)
{
ASSERT(regT0 == returnValueGPR);
+ copyCalleeSavesToVMCalleeSavesBuffer();
emitLoad(currentInstruction[1].u.operand, regT1, regT0);
callOperationNoExceptionCheck(operationThrow, regT1, regT0);
jumpToExceptionHandler();
@@ -822,6 +823,8 @@
void JIT::emit_op_catch(Instruction* currentInstruction)
{
+ restoreCalleeSavesFromVMCalleeSavesBuffer();
+
move(TrustedImmPtr(m_vm), regT3);
// operationThrow returns the callFrame for the handler.
load32(Address(regT3, VM::callFrameForThrowOffset()), callFrameRegister);
Modified: branches/jsc-tailcall/Source/_javascript_Core/jit/JITPropertyAccess.cpp (188070 => 188071)
--- branches/jsc-tailcall/Source/_javascript_Core/jit/JITPropertyAccess.cpp 2015-08-06 22:40:11 UTC (rev 188070)
+++ branches/jsc-tailcall/Source/_javascript_Core/jit/JITPropertyAccess.cpp 2015-08-06 22:41:51 UTC (rev 188071)
@@ -483,7 +483,7 @@
emitArrayProfilingSiteForBytecodeIndexWithCell(regT0, regT1, m_bytecodeOffset);
JITGetByIdGenerator gen(
- m_codeBlock, CodeOrigin(m_bytecodeOffset), RegisterSet::specialRegisters(),
+ m_codeBlock, CodeOrigin(m_bytecodeOffset), RegisterSet::nonTempRegisters(),
JSValueRegs(regT0), JSValueRegs(regT0), DontSpill);
gen.generateFastPath(*this);
addSlowCase(gen.slowPathJump());
@@ -530,7 +530,7 @@
emitJumpSlowCaseIfNotJSCell(regT0, baseVReg);
JITPutByIdGenerator gen(
- m_codeBlock, CodeOrigin(m_bytecodeOffset), RegisterSet::specialRegisters(),
+ m_codeBlock, CodeOrigin(m_bytecodeOffset), RegisterSet::nonTempRegisters(),
JSValueRegs(regT0), JSValueRegs(regT1), regT2, DontSpill, m_codeBlock->ecmaMode(),
direct ? Direct : NotDirect);
Modified: branches/jsc-tailcall/Source/_javascript_Core/jit/JITPropertyAccess32_64.cpp (188070 => 188071)
--- branches/jsc-tailcall/Source/_javascript_Core/jit/JITPropertyAccess32_64.cpp 2015-08-06 22:40:11 UTC (rev 188070)
+++ branches/jsc-tailcall/Source/_javascript_Core/jit/JITPropertyAccess32_64.cpp 2015-08-06 22:41:51 UTC (rev 188071)
@@ -487,7 +487,7 @@
emitArrayProfilingSiteForBytecodeIndexWithCell(regT0, regT2, m_bytecodeOffset);
JITGetByIdGenerator gen(
- m_codeBlock, CodeOrigin(m_bytecodeOffset), RegisterSet::specialRegisters(),
+ m_codeBlock, CodeOrigin(m_bytecodeOffset), RegisterSet::nonTempRegisters(),
JSValueRegs::payloadOnly(regT0), JSValueRegs(regT1, regT0), DontSpill);
gen.generateFastPath(*this);
addSlowCase(gen.slowPathJump());
@@ -532,7 +532,7 @@
emitJumpSlowCaseIfNotJSCell(base, regT1);
JITPutByIdGenerator gen(
- m_codeBlock, CodeOrigin(m_bytecodeOffset), RegisterSet::specialRegisters(),
+ m_codeBlock, CodeOrigin(m_bytecodeOffset), RegisterSet::nonTempRegisters(),
JSValueRegs::payloadOnly(regT0), JSValueRegs(regT3, regT2),
regT1, DontSpill, m_codeBlock->ecmaMode(), direct ? Direct : NotDirect);
Modified: branches/jsc-tailcall/Source/_javascript_Core/jit/RegisterSet.cpp (188070 => 188071)
--- branches/jsc-tailcall/Source/_javascript_Core/jit/RegisterSet.cpp 2015-08-06 22:40:11 UTC (rev 188070)
+++ branches/jsc-tailcall/Source/_javascript_Core/jit/RegisterSet.cpp 2015-08-06 22:41:51 UTC (rev 188071)
@@ -66,6 +66,11 @@
stackRegisters(), reservedHardwareRegisters(), runtimeRegisters());
}
+RegisterSet RegisterSet::nonTempRegisters()
+{
+ return RegisterSet(specialRegisters(), allVMCalleeSaveRegisters());
+}
+
RegisterSet RegisterSet::calleeSaveRegisters()
{
RegisterSet result;
@@ -122,22 +127,18 @@
return result;
}
-RegisterSet RegisterSet::allVMCalleeSaveRegisters()
+RegisterSet RegisterSet::llintCalleeSaveRegisters()
{
RegisterSet result;
#if CPU(X86)
#elif CPU(X86_64)
result.set(GPRInfo::regCS0);
- result.set(GPRInfo::regCS1);
- result.set(GPRInfo::regCS2);
#if !OS(WINDOWS)
ASSERT(GPRInfo::regCS3 == GPRInfo::tagTypeNumberRegister);
ASSERT(GPRInfo::regCS4 == GPRInfo::tagMaskRegister);
result.set(GPRInfo::regCS3);
result.set(GPRInfo::regCS4);
#else
- result.set(GPRInfo::regCS3);
- result.set(GPRInfo::regCS4);
ASSERT(GPRInfo::regCS5 == GPRInfo::tagTypeNumberRegister);
ASSERT(GPRInfo::regCS6 == GPRInfo::tagMaskRegister);
result.set(GPRInfo::regCS5);
@@ -171,7 +172,6 @@
result.set(GPRInfo::regCS3);
result.set(GPRInfo::regCS4);
#else
- result.set(GPRInfo::regCS4);
ASSERT(GPRInfo::regCS5 == GPRInfo::tagTypeNumberRegister);
ASSERT(GPRInfo::regCS6 == GPRInfo::tagMaskRegister);
result.set(GPRInfo::regCS5);
@@ -228,6 +228,13 @@
return result;
}
+RegisterSet RegisterSet::allVMCalleeSaveRegisters()
+{
+ return RegisterSet(llintCalleeSaveRegisters(),
+ baselineCalleeSaveRegisters(),
+ dfgCalleeSaveRegisters());
+}
+
RegisterSet RegisterSet::allGPRs()
{
RegisterSet result;
Modified: branches/jsc-tailcall/Source/_javascript_Core/jit/RegisterSet.h (188070 => 188071)
--- branches/jsc-tailcall/Source/_javascript_Core/jit/RegisterSet.h 2015-08-06 22:40:11 UTC (rev 188070)
+++ branches/jsc-tailcall/Source/_javascript_Core/jit/RegisterSet.h 2015-08-06 22:41:51 UTC (rev 188071)
@@ -50,9 +50,11 @@
static RegisterSet runtimeRegisters();
static RegisterSet specialRegisters(); // The union of stack, reserved hardware, and runtime registers.
static RegisterSet calleeSaveRegisters();
- static RegisterSet allVMCalleeSaveRegisters(); // The union of egisters saved and used by any VM.
+ static RegisterSet llintCalleeSaveRegisters(); // Registers saved and used by the LLInt.
static RegisterSet baselineCalleeSaveRegisters(); // Registers saved and used by the baseline JIT.
static RegisterSet dfgCalleeSaveRegisters(); // Registers saved and used by the DFG JIT.
+ static RegisterSet allVMCalleeSaveRegisters(); // The union of registers saved and used by any VM.
+ static RegisterSet nonTempRegisters(); // The union of VM callee save and special registers.
static RegisterSet allGPRs();
static RegisterSet allFPRs();
static RegisterSet allRegisters();
Modified: branches/jsc-tailcall/Source/_javascript_Core/jit/Repatch.cpp (188070 => 188071)
--- branches/jsc-tailcall/Source/_javascript_Core/jit/Repatch.cpp 2015-08-06 22:40:11 UTC (rev 188070)
+++ branches/jsc-tailcall/Source/_javascript_Core/jit/Repatch.cpp 2015-08-06 22:41:51 UTC (rev 188071)
@@ -565,7 +565,9 @@
if (kind == CallCustomGetter)
stubJit.setupResults(valueRegs);
MacroAssembler::Jump noException = stubJit.emitExceptionCheck(CCallHelpers::InvertedExceptionCheck);
-
+
+ stubJit.copyCalleeSavesToVMCalleeSavesBuffer();
+
stubJit.setupArguments(CCallHelpers::TrustedImmPtr(vm), GPRInfo::callFrameRegister);
handlerCall = stubJit.call();
stubJit.jumpToExceptionHandler();
Modified: branches/jsc-tailcall/Source/_javascript_Core/jit/ThunkGenerators.cpp (188070 => 188071)
--- branches/jsc-tailcall/Source/_javascript_Core/jit/ThunkGenerators.cpp 2015-08-06 22:40:11 UTC (rev 188070)
+++ branches/jsc-tailcall/Source/_javascript_Core/jit/ThunkGenerators.cpp 2015-08-06 22:41:51 UTC (rev 188071)
@@ -66,6 +66,8 @@
// even though we won't use it.
jit.preserveReturnAddressAfterCall(GPRInfo::nonPreservedNonReturnGPR);
+ jit.copyCalleeSavesToVMCalleeSavesBuffer();
+
jit.setupArguments(CCallHelpers::TrustedImmPtr(vm), GPRInfo::callFrameRegister);
jit.move(CCallHelpers::TrustedImmPtr(bitwise_cast<void*>(lookupExceptionHandler)), GPRInfo::nonArgGPR0);
emitPointerValidation(jit, GPRInfo::nonArgGPR0);
@@ -318,6 +320,7 @@
// Handle an exception
exceptionHandler.link(&jit);
+ jit.copyCalleeSavesToVMCalleeSavesBuffer();
jit.storePtr(JSInterfaceJIT::callFrameRegister, &vm->topCallFrame);
#if CPU(X86) && USE(JSVALUE32_64)
Modified: branches/jsc-tailcall/Source/_javascript_Core/llint/LowLevelInterpreter.asm (188070 => 188071)
--- branches/jsc-tailcall/Source/_javascript_Core/llint/LowLevelInterpreter.asm 2015-08-06 22:40:11 UTC (rev 188070)
+++ branches/jsc-tailcall/Source/_javascript_Core/llint/LowLevelInterpreter.asm 2015-08-06 22:41:51 UTC (rev 188071)
@@ -582,13 +582,62 @@
loadp -16[cfr], csr3
loadp -8[cfr], csr4
elsif X86_64_WIN
- loadp -32[cfr], csr0
- loadp -24[cfr], csr5
- loadp -16[cfr], csr6
- loadp -8[cfr], t4
+ loadp -24[cfr], csr0
+ loadp -16[cfr], csr5
+ loadp -8[cfr], csr6
end
end
+macro copyCalleeSavesToVMCalleeSavesBuffer(vm, temp)
+ if ARM64 or X86_64 or X86_64_WIN
+ leap VM::calleeSaveRegistersBuffer[vm], temp
+ if ARM64
+ storep csr0, [temp]
+ storep csr1, 8[temp]
+ storep csr2, 16[temp]
+ elsif X86_64
+ storep csr0, [temp]
+ storep csr1, 8[temp]
+ storep csr2, 16[temp]
+ storep csr3, 24[temp]
+ storep csr4, 32[temp]
+ elsif X86_64_WIN
+ storep csr0, [temp]
+ storep csr1, 8[temp]
+ storep csr2, 16[temp]
+ storep csr3, 24[temp]
+ storep csr4, 32[temp]
+ storep csr5, 40[temp]
+ storep csr6, 48[temp]
+ end
+ end
+end
+
+macro restoreCalleeSavesFromVMCalleeSavesBuffer(vm, temp)
+ if ARM64 or X86_64 or X86_64_WIN
+ leap VM::calleeSaveRegistersBuffer[vm], temp
+ if ARM64
+ loadp [temp], csr0
+ loadp 8[temp], csr1
+ loadp 16[temp], csr2
+ elsif X86_64
+ loadp [temp], csr0
+ loadp 8[temp], csr1
+ loadp 16[temp], csr2
+ loadp 24[temp], csr3
+ loadp 32[temp], csr4
+ elsif X86_64_WIN
+ loadp [temp], csr0
+ loadp 8[temp], csr1
+ loadp 16[temp], csr2
+ loadp 24[temp], csr3
+ loadp 32[temp], csr4
+ loadp 40[temp], csr5
+ loadp 48[temp], csr6
+ end
+ end
+end
+
macro preserveReturnAddressAfterCall(destinationRegister)
if C_LOOP or ARM or ARMv7 or ARMv7_TRADITIONAL or ARM64 or MIPS or SH4
# In C_LOOP case, we're only preserving the bytecode vPC.
@@ -854,6 +903,8 @@
codeBlockSetter(t1)
+ preserveCalleeSavesUsedByLLInt()
+
# Set up the PC.
if JSVALUE64
loadp CodeBlock::m_instructions[t1], PB
@@ -885,8 +936,6 @@
.stackHeightOK:
move t0, sp
- preserveCalleeSavesUsedByLLInt()
-
if JSVALUE64
move TagTypeNumber, tagTypeNumber
addp TagBitTypeOther, tagTypeNumber, tagMask
Modified: branches/jsc-tailcall/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm (188070 => 188071)
--- branches/jsc-tailcall/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm 2015-08-06 22:40:11 UTC (rev 188070)
+++ branches/jsc-tailcall/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm 2015-08-06 22:41:51 UTC (rev 188071)
@@ -302,6 +302,7 @@
loadp Callee + PayloadOffset[cfr], t3
andp MarkedBlockMask, t3
loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
+ restoreCalleeSavesFromVMCalleeSavesBuffer(t3, t0)
loadp VM::callFrameForThrow[t3], cfr
loadp CallerFrame[cfr], cfr
@@ -1876,6 +1877,7 @@
loadp Callee + PayloadOffset[cfr], t3
andp MarkedBlockMask, t3
loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
+ restoreCalleeSavesFromVMCalleeSavesBuffer(t3, t0)
loadp VM::callFrameForThrow[t3], cfr
loadp VM::vmEntryFrameForThrow[t3], t0
storep t0, VM::topVMEntryFrame[t3]
@@ -1916,6 +1918,7 @@
loadp Callee[cfr], t1
andp MarkedBlockMask, t1
loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t1], t1
+ copyCalleeSavesToVMCalleeSavesBuffer(t1, t2)
jmp VM::targetMachinePCForThrow[t1]
Modified: branches/jsc-tailcall/Source/_javascript_Core/llint/LowLevelInterpreter64.asm (188070 => 188071)
--- branches/jsc-tailcall/Source/_javascript_Core/llint/LowLevelInterpreter64.asm 2015-08-06 22:40:11 UTC (rev 188070)
+++ branches/jsc-tailcall/Source/_javascript_Core/llint/LowLevelInterpreter64.asm 2015-08-06 22:41:51 UTC (rev 188071)
@@ -277,6 +277,7 @@
loadp Callee[cfr], t3
andp MarkedBlockMask, t3
loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
+ restoreCalleeSavesFromVMCalleeSavesBuffer(t3, t0)
loadp VM::callFrameForThrow[t3], cfr
loadp CallerFrame[cfr], cfr
@@ -1751,11 +1752,6 @@
_llint_op_catch:
- # Gotta restore the tag registers. We could be throwing from FTL, which may
- # clobber them.
- move TagTypeNumber, tagTypeNumber
- move TagMask, tagMask
-
# This is where we end up from the JIT's throw trampoline (because the
# machine code return address will be set to _llint_op_catch), and from
# the interpreter's throw trampoline (see _llint_throw_trampoline).
@@ -1764,6 +1760,7 @@
loadp Callee[cfr], t3
andp MarkedBlockMask, t3
loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
+ restoreCalleeSavesFromVMCalleeSavesBuffer(t3, t0)
loadp VM::callFrameForThrow[t3], cfr
loadp VM::vmEntryFrameForThrow[t3], t0
storep t0, VM::topVMEntryFrame[t3]
@@ -1806,6 +1803,7 @@
loadp Callee[cfr], t1
andp MarkedBlockMask, t1
loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t1], t1
+ copyCalleeSavesToVMCalleeSavesBuffer(t1, t2)
jmp VM::targetMachinePCForThrow[t1]