Title: [188071] branches/jsc-tailcall/Source/_javascript_Core
Revision
188071
Author
msab...@apple.com
Date
2015-08-06 15:41:51 -0700 (Thu, 06 Aug 2015)

Log Message

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.

Modified Paths

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]
 
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to