Initial patch.
[vuplus_webkit] / Source / JavaScriptCore / dfg / DFGJITCompiler.cpp
index 046e6ff..6d5c2f9 100644 (file)
@@ -30,7 +30,6 @@
 
 #include "CodeBlock.h"
 #include "DFGJITCodeGenerator.h"
-#include "DFGNonSpeculativeJIT.h"
 #include "DFGOperations.h"
 #include "DFGRegisterBank.h"
 #include "DFGSpeculativeJIT.h"
@@ -44,7 +43,7 @@ void JITCompiler::fillNumericToDouble(NodeIndex nodeIndex, FPRReg fpr, GPRReg te
 {
     Node& node = graph()[nodeIndex];
 
-    if (node.isConstant()) {
+    if (node.hasConstant()) {
         ASSERT(isNumberConstant(nodeIndex));
         move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfNumberConstant(nodeIndex)))), temporary);
         movePtrToDouble(temporary, fpr);
@@ -64,7 +63,7 @@ void JITCompiler::fillInt32ToInteger(NodeIndex nodeIndex, GPRReg gpr)
 {
     Node& node = graph()[nodeIndex];
 
-    if (node.isConstant()) {
+    if (node.hasConstant()) {
         ASSERT(isInt32Constant(nodeIndex));
         move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr);
     } else {
@@ -82,7 +81,7 @@ void JITCompiler::fillToJS(NodeIndex nodeIndex, GPRReg gpr)
 {
     Node& node = graph()[nodeIndex];
 
-    if (node.isConstant()) {
+    if (node.hasConstant()) {
         if (isInt32Constant(nodeIndex)) {
             JSValue jsValue = jsNumber(valueOfInt32Constant(nodeIndex));
             move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
@@ -100,7 +99,6 @@ void JITCompiler::fillToJS(NodeIndex nodeIndex, GPRReg gpr)
     loadPtr(addressFor(node.virtualRegister()), gpr);
 }
 
-#if ENABLE(DFG_OSR_EXIT)
 void JITCompiler::exitSpeculativeWithOSR(const OSRExit& exit, SpeculationRecovery* recovery, Vector<BytecodeAndMachineOffset>& decodedCodeMap)
 {
     // 1) Pro-forma stuff.
@@ -469,716 +467,6 @@ void JITCompiler::linkOSRExits(SpeculativeJIT& speculative)
         ++exitsIter;
     }
 }
-#else // ENABLE(DFG_OSR_EXIT)
-class GeneralizedRegister {
-public:
-    GeneralizedRegister() { }
-    
-    static GeneralizedRegister createGPR(GPRReg gpr)
-    {
-        GeneralizedRegister result;
-        result.m_isFPR = false;
-        result.m_register.gpr = gpr;
-        return result;
-    }
-    
-    static GeneralizedRegister createFPR(FPRReg fpr)
-    {
-        GeneralizedRegister result;
-        result.m_isFPR = true;
-        result.m_register.fpr = fpr;
-        return result;
-    }
-    
-    bool isFPR() const
-    {
-        return m_isFPR;
-    }
-    
-    GPRReg gpr() const
-    {
-        ASSERT(!m_isFPR);
-        return m_register.gpr;
-    }
-    
-    FPRReg fpr() const
-    {
-        ASSERT(m_isFPR);
-        return m_register.fpr;
-    }
-    
-    const SpeculationCheck::RegisterInfo& findInSpeculationCheck(const SpeculationCheck& check)
-    {
-        if (isFPR())
-            return check.m_fprInfo[FPRInfo::toIndex(fpr())];
-        return check.m_gprInfo[GPRInfo::toIndex(gpr())];
-    }
-    
-    const EntryLocation::RegisterInfo& findInEntryLocation(const EntryLocation& entry)
-    {
-        if (isFPR())
-            return entry.m_fprInfo[FPRInfo::toIndex(fpr())];
-        return entry.m_gprInfo[GPRInfo::toIndex(gpr())];
-    }
-    
-    DataFormat previousDataFormat(const SpeculationCheck& check)
-    {
-        return findInSpeculationCheck(check).format;
-    }
-    
-    DataFormat nextDataFormat(const EntryLocation& entry)
-    {
-        return findInEntryLocation(entry).format;
-    }
-    
-    void convert(DataFormat oldDataFormat, DataFormat newDataFormat, JITCompiler& jit)
-    {
-        if (LIKELY(!needDataFormatConversion(oldDataFormat, newDataFormat)))
-            return;
-        
-        if (oldDataFormat == DataFormatInteger) {
-            jit.orPtr(GPRInfo::tagTypeNumberRegister, gpr());
-            return;
-        }
-        
-        ASSERT(newDataFormat == DataFormatInteger);
-        jit.zeroExtend32ToPtr(gpr(), gpr());
-        return;
-    }
-    
-    void moveTo(GeneralizedRegister& other, DataFormat myDataFormat, DataFormat otherDataFormat, JITCompiler& jit, FPRReg scratchFPR)
-    {
-        if (UNLIKELY(isFPR())) {
-            if (UNLIKELY(other.isFPR())) {
-                jit.moveDouble(fpr(), other.fpr());
-                return;
-            }
-            
-            JITCompiler::Jump done;
-            
-            if (scratchFPR != InvalidFPRReg) {
-                // we have a scratch FPR, so attempt a conversion to int
-                JITCompiler::JumpList notInt;
-                jit.branchConvertDoubleToInt32(fpr(), other.gpr(), notInt, scratchFPR);
-                jit.orPtr(GPRInfo::tagTypeNumberRegister, other.gpr());
-                done = jit.jump();
-                notInt.link(&jit);
-            }
-            
-            jit.boxDouble(fpr(), other.gpr());
-            
-            if (done.isSet())
-                done.link(&jit);
-            return;
-        }
-        
-        if (UNLIKELY(other.isFPR())) {
-            jit.unboxDouble(gpr(), other.fpr());
-            return;
-        }
-        
-        if (LIKELY(!needDataFormatConversion(myDataFormat, otherDataFormat))) {
-            jit.move(gpr(), other.gpr());
-            return;
-        }
-        
-        if (myDataFormat == DataFormatInteger) {
-            jit.orPtr(gpr(), GPRInfo::tagTypeNumberRegister, other.gpr());
-            return;
-        }
-        
-        ASSERT(otherDataFormat == DataFormatInteger);
-        jit.zeroExtend32ToPtr(gpr(), other.gpr());
-    }
-    
-    void swapWith(GeneralizedRegister& other, DataFormat myDataFormat, DataFormat myNewDataFormat, DataFormat otherDataFormat, DataFormat otherNewDataFormat, JITCompiler& jit, GPRReg scratchGPR, FPRReg scratchFPR)
-    {
-        if (UNLIKELY(isFPR())) {
-            if (UNLIKELY(other.isFPR())) {
-                if (scratchFPR == InvalidFPRReg)
-                    jit.moveDoubleToPtr(fpr(), scratchGPR);
-                else
-                    jit.moveDouble(fpr(), scratchFPR);
-                jit.moveDouble(other.fpr(), fpr());
-                if (scratchFPR == InvalidFPRReg)
-                    jit.movePtrToDouble(scratchGPR, other.fpr());
-                else
-                    jit.moveDouble(scratchFPR, other.fpr());
-                return;
-            }
-            
-            jit.move(other.gpr(), scratchGPR);
-            
-            JITCompiler::Jump done;
-            
-            if (scratchFPR != InvalidFPRReg) {
-                JITCompiler::JumpList notInt;
-                jit.branchConvertDoubleToInt32(fpr(), other.gpr(), notInt, scratchFPR);
-                jit.orPtr(GPRInfo::tagTypeNumberRegister, other.gpr());
-                done = jit.jump();
-                notInt.link(&jit);
-            }
-            
-            jit.boxDouble(fpr(), other.gpr());
-            
-            if (done.isSet())
-                done.link(&jit);
-            
-            jit.unboxDouble(scratchGPR, fpr());
-            return;
-        }
-        
-        if (UNLIKELY(other.isFPR())) {
-            other.swapWith(*this, otherDataFormat, otherNewDataFormat, myDataFormat, myNewDataFormat, jit, scratchGPR, scratchFPR);
-            return;
-        }
-        
-        jit.swap(gpr(), other.gpr());
-        
-        if (UNLIKELY(needDataFormatConversion(otherDataFormat, myNewDataFormat))) {
-            if (otherDataFormat == DataFormatInteger)
-                jit.orPtr(GPRInfo::tagTypeNumberRegister, gpr());
-            else if (myNewDataFormat == DataFormatInteger)
-                jit.zeroExtend32ToPtr(gpr(), gpr());
-        }
-        
-        if (UNLIKELY(needDataFormatConversion(myDataFormat, otherNewDataFormat))) {
-            if (myDataFormat == DataFormatInteger)
-                jit.orPtr(GPRInfo::tagTypeNumberRegister, other.gpr());
-            else if (otherNewDataFormat == DataFormatInteger)
-                jit.zeroExtend32ToPtr(other.gpr(), other.gpr());
-        }
-    }
-
-private:
-    bool m_isFPR;
-    union {
-        GPRReg gpr;
-        FPRReg fpr;
-    } m_register;
-};
-
-struct ShuffledRegister {
-    GeneralizedRegister reg;
-    ShuffledRegister* previous;
-    bool hasFrom;
-    bool hasTo;
-    bool handled;
-    
-    ShuffledRegister() { }
-    
-    ShuffledRegister(GeneralizedRegister reg)
-        : reg(reg)
-        , previous(0)
-        , hasFrom(false)
-        , hasTo(false)
-        , handled(false)
-    {
-    }
-    
-    bool isEndOfNonCyclingPermutation()
-    {
-        return hasTo && !hasFrom;
-    }
-    
-    void handleNonCyclingPermutation(const SpeculationCheck& check, const EntryLocation& entry, JITCompiler& jit, FPRReg& scratchFPR1, FPRReg& scratchFPR2)
-    {
-        ShuffledRegister* cur = this;
-        while (cur->previous) {
-            cur->previous->reg.moveTo(cur->reg, cur->previous->reg.previousDataFormat(check), cur->reg.nextDataFormat(entry), jit, scratchFPR1);
-            cur->handled = true;
-            if (cur->reg.isFPR()) {
-                if (scratchFPR1 == InvalidFPRReg)
-                    scratchFPR1 = cur->reg.fpr();
-                else {
-                    ASSERT(scratchFPR1 != cur->reg.fpr());
-                    scratchFPR2 = cur->reg.fpr();
-                }
-            }
-            cur = cur->previous;
-        }
-        cur->handled = true;
-        if (cur->reg.isFPR()) {
-            if (scratchFPR1 == InvalidFPRReg)
-                scratchFPR1 = cur->reg.fpr();
-            else {
-                ASSERT(scratchFPR1 != cur->reg.fpr());
-                scratchFPR2 = cur->reg.fpr();
-            }
-        }
-    }
-    
-    void handleCyclingPermutation(const SpeculationCheck& check, const EntryLocation& entry, JITCompiler& jit, GPRReg scratchGPR, FPRReg scratchFPR1, FPRReg scratchFPR2)
-    {
-        // first determine the cycle length
-        
-        unsigned cycleLength = 0;
-        
-        ShuffledRegister* cur = this;
-        ShuffledRegister* next = 0;
-        do {
-            ASSERT(cur);
-            cycleLength++;
-            cur->handled = true;
-            next = cur;
-            cur = cur->previous;
-        } while (cur != this);
-        
-        ASSERT(cycleLength);
-        ASSERT(next->previous == cur);
-        
-        // now determine the best way to handle the permutation, depending on the
-        // length.
-        
-        switch (cycleLength) {
-        case 1:
-            reg.convert(reg.previousDataFormat(check), reg.nextDataFormat(entry), jit);
-            break;
-            
-        case 2:
-            reg.swapWith(previous->reg, reg.previousDataFormat(check), reg.nextDataFormat(entry), previous->reg.previousDataFormat(check), previous->reg.nextDataFormat(entry), jit, scratchGPR, scratchFPR1);
-            break;
-            
-        default:
-            GeneralizedRegister scratch;
-            if (UNLIKELY(reg.isFPR() && next->reg.isFPR())) {
-                if (scratchFPR2 == InvalidFPRReg) {
-                    scratch = GeneralizedRegister::createGPR(scratchGPR);
-                    reg.moveTo(scratch, DataFormatDouble, DataFormatJSDouble, jit, scratchFPR1);
-                } else {
-                    scratch = GeneralizedRegister::createFPR(scratchFPR2);
-                    reg.moveTo(scratch, DataFormatDouble, DataFormatDouble, jit, scratchFPR1);
-                }
-            } else {
-                scratch = GeneralizedRegister::createGPR(scratchGPR);
-                reg.moveTo(scratch, reg.previousDataFormat(check), next->reg.nextDataFormat(entry), jit, scratchFPR1);
-            }
-            
-            cur = this;
-            while (cur->previous != this) {
-                ASSERT(cur);
-                cur->previous->reg.moveTo(cur->reg, cur->previous->reg.previousDataFormat(check), cur->reg.nextDataFormat(entry), jit, scratchFPR1);
-                cur = cur->previous;
-            }
-            
-            if (UNLIKELY(reg.isFPR() && next->reg.isFPR())) {
-                if (scratchFPR2 == InvalidFPRReg)
-                    scratch.moveTo(next->reg, DataFormatJSDouble, DataFormatDouble, jit, scratchFPR1);
-                else
-                    scratch.moveTo(next->reg, DataFormatDouble, DataFormatDouble, jit, scratchFPR1);
-            } else
-                scratch.moveTo(next->reg, next->reg.nextDataFormat(entry), next->reg.nextDataFormat(entry), jit, scratchFPR1);
-            break;
-        }
-    }
-    
-    static ShuffledRegister* lookup(ShuffledRegister* gprs, ShuffledRegister* fprs, GeneralizedRegister& reg)
-    {
-        if (reg.isFPR())
-            return fprs + FPRInfo::toIndex(reg.fpr());
-        return gprs + GPRInfo::toIndex(reg.gpr());
-    }
-};
-
-template<typename T>
-T& lookupForRegister(T* gprs, T* fprs, unsigned index)
-{
-    ASSERT(index < GPRInfo::numberOfRegisters + FPRInfo::numberOfRegisters);
-    if (index < GPRInfo::numberOfRegisters)
-        return gprs[index];
-    return fprs[index - GPRInfo::numberOfRegisters];
-}
-
-// This is written in a way that allows for a HashMap<NodeIndex, GeneralizedRegister> to be
-// easily substituted, if it is found to be wise to do so. So far performance measurements
-// indicate that this is faster, likely because the HashMap would have never grown very big
-// and we would thus be wasting time performing complex hashing logic that, though O(1) on
-// average, would be less than the ~7 loop iterations that the find() method below would do
-// (since it's uncommon that we'd have register allocated more than 7 registers, in the
-// current scheme).
-class NodeToRegisterMap {
-public:
-    struct Tuple {
-        NodeIndex first;
-        GeneralizedRegister second;
-        
-        Tuple()
-        {
-        }
-    };
-    
-    typedef Tuple* iterator;
-    
-    NodeToRegisterMap()
-        : m_occupancy(0)
-    {
-    }
-    
-    void set(NodeIndex first, GeneralizedRegister second)
-    {
-        m_payload[m_occupancy].first = first;
-        m_payload[m_occupancy].second = second;
-        m_occupancy++;
-    }
-    
-    Tuple* end()
-    {
-        return 0;
-    }
-    
-    Tuple* find(NodeIndex first)
-    {
-        for (unsigned i = m_occupancy; i-- > 0;) {
-            if (m_payload[i].first == first)
-                return m_payload + i;
-        }
-        return 0;
-    }
-    
-    void clear()
-    {
-        m_occupancy = 0;
-    }
-    
-private:
-    Tuple m_payload[GPRInfo::numberOfRegisters + FPRInfo::numberOfRegisters];
-    unsigned m_occupancy;
-};
-
-void JITCompiler::jumpFromSpeculativeToNonSpeculative(const SpeculationCheck& check, const EntryLocation& entry, SpeculationRecovery* recovery, NodeToRegisterMap& checkNodeToRegisterMap, NodeToRegisterMap& entryNodeToRegisterMap)
-{
-    ASSERT(check.m_nodeIndex == entry.m_nodeIndex);
-
-    // Link the jump from the Speculative path to here.
-    check.m_check.link(this);
-
-#if ENABLE(DFG_DEBUG_VERBOSE)
-    fprintf(stderr, "Speculation failure for Node @%d at JIT offset 0x%x\n", (int)check.m_nodeIndex, debugOffset());
-#endif
-#if ENABLE(DFG_JIT_BREAK_ON_SPECULATION_FAILURE)
-    breakpoint();
-#endif
-    
-#if ENABLE(DFG_VERBOSE_SPECULATION_FAILURE)
-    SpeculationFailureDebugInfo* debugInfo = new SpeculationFailureDebugInfo;
-    debugInfo->codeBlock = m_codeBlock;
-    debugInfo->debugOffset = debugOffset();
-    
-    debugCall(debugOperationPrintSpeculationFailure, debugInfo);
-#endif
-
-#if ENABLE(DFG_SUCCESS_STATS)
-    static SamplingCounter counter("SpeculationFailure");
-    emitCount(counter);
-#endif
-
-    // Does this speculation check require any additional recovery to be performed,
-    // to restore any state that has been overwritten before we enter back in to the
-    // non-speculative path.
-    if (recovery) {
-        switch (recovery->type()) {
-        case SpeculativeAdd: {
-            ASSERT(check.m_gprInfo[GPRInfo::toIndex(recovery->dest())].nodeIndex != NoNode);
-            // Revert the add.
-            sub32(recovery->src(), recovery->dest());
-            
-            // If recovery->dest() should have been boxed prior to the addition, then rebox
-            // it.
-            DataFormat format = check.m_gprInfo[GPRInfo::toIndex(recovery->dest())].format;
-            ASSERT(format == DataFormatInteger || format == DataFormatJSInteger || format == DataFormatJS);
-            if (format != DataFormatInteger)
-                orPtr(GPRInfo::tagTypeNumberRegister, recovery->dest());
-            break;
-        }
-            
-        case BooleanSpeculationCheck: {
-            ASSERT(check.m_gprInfo[GPRInfo::toIndex(recovery->dest())].nodeIndex != NoNode);
-            // Rebox the (non-)boolean
-            xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), recovery->dest());
-            break;
-        }
-            
-        default:
-            ASSERT_NOT_REACHED();
-            break;
-        }
-    }
-    
-    // First, we need a reverse mapping that tells us, for a NodeIndex, which register
-    // that node is in.
-    
-    checkNodeToRegisterMap.clear();
-    entryNodeToRegisterMap.clear();
-    
-    GPRReg scratchGPR = InvalidGPRReg;
-    FPRReg scratchFPR1 = InvalidFPRReg;
-    FPRReg scratchFPR2 = InvalidFPRReg;
-    bool needToRestoreTagMaskRegister = false;
-    
-    for (unsigned index = 0; index < GPRInfo::numberOfRegisters; ++index) {
-        NodeIndex nodeIndexInCheck = check.m_gprInfo[index].nodeIndex;
-        if (nodeIndexInCheck != NoNode)
-            checkNodeToRegisterMap.set(nodeIndexInCheck, GeneralizedRegister::createGPR(GPRInfo::toRegister(index)));
-        NodeIndex nodeIndexInEntry = entry.m_gprInfo[index].nodeIndex;
-        if (nodeIndexInEntry != NoNode)
-            entryNodeToRegisterMap.set(nodeIndexInEntry, GeneralizedRegister::createGPR(GPRInfo::toRegister(index)));
-        else if (nodeIndexInCheck == NoNode)
-            scratchGPR = GPRInfo::toRegister(index);
-    }
-    
-    for (unsigned index = 0; index < FPRInfo::numberOfRegisters; ++index) {
-        NodeIndex nodeIndexInCheck = check.m_fprInfo[index].nodeIndex;
-        if (nodeIndexInCheck != NoNode)
-            checkNodeToRegisterMap.set(nodeIndexInCheck, GeneralizedRegister::createFPR(FPRInfo::toRegister(index)));
-        NodeIndex nodeIndexInEntry = entry.m_fprInfo[index].nodeIndex;
-        if (nodeIndexInEntry != NoNode)
-            entryNodeToRegisterMap.set(nodeIndexInEntry, GeneralizedRegister::createFPR(FPRInfo::toRegister(index)));
-        else if (nodeIndexInCheck == NoNode) {
-            if (scratchFPR1 == InvalidFPRReg)
-                scratchFPR1 = FPRInfo::toRegister(index);
-            else
-                scratchFPR2 = FPRInfo::toRegister(index);
-        }
-    }
-    
-    ASSERT((scratchFPR1 == InvalidFPRReg && scratchFPR2 == InvalidFPRReg) || (scratchFPR1 != scratchFPR2));
-    
-    // How this works:
-    // 1) Spill any values that are not spilled on speculative, but are spilled
-    //    on non-speculative.
-    // 2) For the set of nodes that are in registers on both paths, perform a
-    //    shuffling.
-    // 3) Fill any values that were spilled on speculative, but are not spilled
-    //    on non-speculative.
-    
-    // If we find registers that can be used as scratch registers along the way,
-    // save them.
-    
-    // Part 1: spill any values that are not spilled on speculative, but are
-    //         spilled on non-speculative.
-    
-    // This also sets up some data structures that Part 2 will need.
-    
-    ShuffledRegister gprs[GPRInfo::numberOfRegisters];
-    ShuffledRegister fprs[FPRInfo::numberOfRegisters];
-    
-    for (unsigned index = 0; index < GPRInfo::numberOfRegisters; ++index)
-        gprs[index] = ShuffledRegister(GeneralizedRegister::createGPR(GPRInfo::toRegister(index)));
-    for (unsigned index = 0; index < FPRInfo::numberOfRegisters; ++index)
-        fprs[index] = ShuffledRegister(GeneralizedRegister::createFPR(FPRInfo::toRegister(index)));
-
-    for (unsigned index = 0; index < GPRInfo::numberOfRegisters; ++index) {
-        NodeIndex nodeIndex = check.m_gprInfo[index].nodeIndex;
-        
-        // Bail out if this register isn't assigned to anything.
-        if (nodeIndex == NoNode)
-            continue;
-        
-        // If the non-speculative path also has a register for the nodeIndex that this
-        // register stores, link them together.
-        NodeToRegisterMap::iterator mapIterator = entryNodeToRegisterMap.find(nodeIndex);
-        if (mapIterator != entryNodeToRegisterMap.end()) {
-            gprs[index].hasFrom = true;
-            
-            ShuffledRegister* next = ShuffledRegister::lookup(gprs, fprs, mapIterator->second);
-            next->previous = gprs + index;
-            next->hasTo = true;
-            
-            // If the non-speculative path has not spilled this register, then skip the spillin
-            // part below regardless of whether or not the speculative path has spilled it.
-            if (!mapIterator->second.findInEntryLocation(entry).isSpilled)
-                continue;
-        } else {
-            // If the non-speculative entry isn't using this register and it does not need
-            // the value in this register to be placed into any other register, then this
-            // register can be used for scratch.
-            if (entry.m_gprInfo[index].nodeIndex == NoNode)
-                scratchGPR = GPRInfo::toRegister(index);
-        }
-        
-        // If the speculative path has already spilled the register then there is no need to
-        // spill it.
-        if (check.m_gprInfo[index].isSpilled)
-            continue;
-        
-        DataFormat dataFormat = check.m_gprInfo[index].format;
-        VirtualRegister virtualRegister = graph()[nodeIndex].virtualRegister();
-        
-        ASSERT(dataFormat == DataFormatInteger || DataFormatCell || dataFormat & DataFormatJS);
-        if (dataFormat == DataFormatInteger)
-            orPtr(GPRInfo::tagTypeNumberRegister, GPRInfo::toRegister(index));
-        storePtr(GPRInfo::toRegister(index), addressFor(virtualRegister));
-    }
-    
-    if (scratchGPR == InvalidGPRReg) {
-        scratchGPR = GPRInfo::tagMaskRegister;
-        needToRestoreTagMaskRegister = true;
-    }
-
-    for (unsigned index = 0; index < FPRInfo::numberOfRegisters; ++index) {
-        NodeIndex nodeIndex = check.m_fprInfo[index].nodeIndex;
-        if (nodeIndex == NoNode)
-            continue;
-
-        NodeToRegisterMap::iterator mapIterator = entryNodeToRegisterMap.find(nodeIndex);
-        if (mapIterator != entryNodeToRegisterMap.end()) {
-            fprs[index].hasFrom = true;
-            
-            ShuffledRegister* next = ShuffledRegister::lookup(gprs, fprs, mapIterator->second);
-            next->previous = fprs + index;
-            next->hasTo = true;
-
-            if (!mapIterator->second.findInEntryLocation(entry).isSpilled)
-                continue;
-        } else {
-            // If the non-speculative entry isn't using this register and it does not need
-            // the value in this register to be placed into any other register, then this
-            // register can be used for scratch.
-            if (entry.m_fprInfo[index].nodeIndex == NoNode) {
-                if (scratchFPR1 == InvalidFPRReg)
-                    scratchFPR1 = FPRInfo::toRegister(index);
-                else if (scratchFPR2)
-                    scratchFPR2 = FPRInfo::toRegister(index);
-                ASSERT((scratchFPR1 == InvalidFPRReg && scratchFPR2 == InvalidFPRReg) || (scratchFPR1 != scratchFPR2));
-            }
-        }
-        
-        if (check.m_fprInfo[index].isSpilled)
-            continue;
-
-        VirtualRegister virtualRegister = graph()[nodeIndex].virtualRegister();
-
-        moveDoubleToPtr(FPRInfo::toRegister(index), scratchGPR);
-        subPtr(GPRInfo::tagTypeNumberRegister, scratchGPR);
-        storePtr(scratchGPR, addressFor(virtualRegister));
-    }
-    
-#if !ASSERT_DISABLED
-    // Assert that we've not assigned a scratch register to something that we're going to shuffle.
-    ASSERT(scratchGPR != InvalidGPRReg);
-    if (scratchGPR != GPRInfo::tagMaskRegister) {
-        ASSERT(!gprs[GPRInfo::toIndex(scratchGPR)].hasTo);
-        ASSERT(!gprs[GPRInfo::toIndex(scratchGPR)].hasFrom);
-    }
-    if (scratchFPR1 != InvalidFPRReg) {
-        ASSERT(scratchFPR1 != scratchFPR2);
-        ASSERT(!fprs[FPRInfo::toIndex(scratchFPR1)].hasTo);
-        ASSERT(!fprs[FPRInfo::toIndex(scratchFPR1)].hasFrom);
-        if (scratchFPR2 != InvalidFPRReg) {
-            ASSERT(!fprs[FPRInfo::toIndex(scratchFPR2)].hasTo);
-            ASSERT(!fprs[FPRInfo::toIndex(scratchFPR2)].hasFrom);
-        }
-    } else
-        ASSERT(scratchFPR2 == InvalidFPRReg);
-#endif
-    
-    // Part 2: For the set of nodes that are in registers on both paths,
-    //         perform a shuffling.
-    
-    for (unsigned index = 0; index < GPRInfo::numberOfRegisters + FPRInfo::numberOfRegisters; ++index) {
-        ShuffledRegister& reg = lookupForRegister(gprs, fprs, index);
-        if (!reg.isEndOfNonCyclingPermutation() || reg.handled || (!reg.hasFrom && !reg.hasTo))
-            continue;
-        
-        reg.handleNonCyclingPermutation(check, entry, *this, scratchFPR1, scratchFPR2);
-        ASSERT((scratchFPR1 == InvalidFPRReg && scratchFPR2 == InvalidFPRReg) || (scratchFPR1 != scratchFPR2));
-    }
-    
-    for (unsigned index = 0; index < GPRInfo::numberOfRegisters + FPRInfo::numberOfRegisters; ++index) {
-        ShuffledRegister& reg = lookupForRegister(gprs, fprs, index);
-        if (reg.handled || (!reg.hasFrom && !reg.hasTo))
-            continue;
-        
-        reg.handleCyclingPermutation(check, entry, *this, scratchGPR, scratchFPR1, scratchFPR2);
-        ASSERT((scratchFPR1 == InvalidFPRReg && scratchFPR2 == InvalidFPRReg) || (scratchFPR1 != scratchFPR2));
-    }
-
-#if !ASSERT_DISABLED
-    for (unsigned index = 0; index < GPRInfo::numberOfRegisters + FPRInfo::numberOfRegisters; ++index) {
-        ShuffledRegister& reg = lookupForRegister(gprs, fprs, index);
-        ASSERT(reg.handled || (!reg.hasFrom && !reg.hasTo));
-    }
-#endif
-
-    // Part 3: Fill any values that were spilled on speculative, but are not spilled
-    //         on non-speculative.
-
-    for (unsigned index = 0; index < FPRInfo::numberOfRegisters; ++index) {
-        NodeIndex nodeIndex = entry.m_fprInfo[index].nodeIndex;
-        if (nodeIndex == NoNode || entry.m_fprInfo[index].isSpilled)
-            continue;
-        
-        NodeToRegisterMap::iterator mapIterator = checkNodeToRegisterMap.find(nodeIndex);
-        if (mapIterator != checkNodeToRegisterMap.end()
-            && !mapIterator->second.findInSpeculationCheck(check).isSpilled)
-            continue;
-
-        fillNumericToDouble(nodeIndex, FPRInfo::toRegister(index), GPRInfo::regT0);
-    }
-
-    for (unsigned index = 0; index < GPRInfo::numberOfRegisters; ++index) {
-        NodeIndex nodeIndex = entry.m_gprInfo[index].nodeIndex;
-        if (nodeIndex == NoNode || entry.m_gprInfo[index].isSpilled)
-            continue;
-
-        NodeToRegisterMap::iterator mapIterator = checkNodeToRegisterMap.find(nodeIndex);
-        if (mapIterator != checkNodeToRegisterMap.end()
-            && !mapIterator->second.findInSpeculationCheck(check).isSpilled)
-            continue;
-
-        DataFormat dataFormat = entry.m_gprInfo[index].format;
-        if (dataFormat == DataFormatInteger)
-            fillInt32ToInteger(nodeIndex, GPRInfo::toRegister(index));
-        else {
-            ASSERT(dataFormat & DataFormatJS || dataFormat == DataFormatCell); // Treat cell as JSValue for now!
-            fillToJS(nodeIndex, GPRInfo::toRegister(index));
-            // FIXME: For subtypes of DataFormatJS, should jitAssert the subtype?
-        }
-    }
-    
-    if (needToRestoreTagMaskRegister)
-        move(TrustedImmPtr(reinterpret_cast<void*>(TagMask)), GPRInfo::tagMaskRegister);
-
-    // Jump into the non-speculative path.
-    jump(entry.m_entry);
-}
-
-void JITCompiler::linkSpeculationChecks(SpeculativeJIT& speculative, NonSpeculativeJIT& nonSpeculative)
-{
-    // Iterators to walk over the set of bail outs & corresponding entry points.
-    SpeculationCheckVector::Iterator checksIter = speculative.speculationChecks().begin();
-    SpeculationCheckVector::Iterator checksEnd = speculative.speculationChecks().end();
-    NonSpeculativeJIT::EntryLocationVector::Iterator entriesIter = nonSpeculative.entryLocations().begin();
-    NonSpeculativeJIT::EntryLocationVector::Iterator entriesEnd = nonSpeculative.entryLocations().end();
-    
-    NodeToRegisterMap checkNodeToRegisterMap;
-    NodeToRegisterMap entryNodeToRegisterMap;
-    
-    // Iterate over the speculation checks.
-    while (checksIter != checksEnd) {
-        // For every bail out from the speculative path, we must have provided an entry point
-        // into the non-speculative one.
-        ASSERT(checksIter->m_nodeIndex == entriesIter->m_nodeIndex);
-
-        // There may be multiple bail outs that map to the same entry point!
-        do {
-            ASSERT(checksIter != checksEnd);
-            ASSERT(entriesIter != entriesEnd);
-
-            // Plant code to link this speculation failure.
-            const SpeculationCheck& check = *checksIter;
-            const EntryLocation& entry = *entriesIter;
-            jumpFromSpeculativeToNonSpeculative(check, entry, speculative.speculationRecovery(check.m_recoveryIndex), checkNodeToRegisterMap, entryNodeToRegisterMap);
-             ++checksIter;
-        } while (checksIter != checksEnd && checksIter->m_nodeIndex == entriesIter->m_nodeIndex);
-         ++entriesIter;
-    }
-
-    // FIXME: https://bugs.webkit.org/show_bug.cgi?id=56289
-    ASSERT(!(checksIter != checksEnd));
-    ASSERT(!(entriesIter != entriesEnd));
-}
-#endif // ENABLE(DFG_OSR_EXIT)
 
 void JITCompiler::compileEntry()
 {
@@ -1197,62 +485,24 @@ void JITCompiler::compileEntry()
 
 void JITCompiler::compileBody()
 {
-    // We generate the speculative code path, followed by the non-speculative
-    // code for the function. Next we need to link the two together, making
-    // bail-outs from the speculative path jump to the corresponding point on
-    // the non-speculative one (and generating any code necessary to juggle
-    // register values around, rebox values, and ensure spilled, to match the
-    // non-speculative path's requirements).
+    // We generate the speculative code path, followed by OSR exit code to return
+    // to the old JIT code if speculations fail.
 
 #if ENABLE(DFG_JIT_BREAK_ON_EVERY_FUNCTION)
     // Handy debug tool!
     breakpoint();
 #endif
 
-    // First generate the speculative path.
     Label speculativePathBegin = label();
     SpeculativeJIT speculative(*this);
-#if !ENABLE(DFG_DEBUG_LOCAL_DISBALE_SPECULATIVE)
     bool compiledSpeculative = speculative.compile();
-#else
-    bool compiledSpeculative = false;
-#endif
+    ASSERT_UNUSED(compiledSpeculative, compiledSpeculative);
 
-    // Next, generate the non-speculative path. We pass this a SpeculationCheckIndexIterator
-    // to allow it to check which nodes in the graph may bail out, and may need to reenter the
-    // non-speculative path.
-    if (compiledSpeculative) {
 #if ENABLE(DFG_OSR_ENTRY)
-        m_codeBlock->setJITCodeMap(m_jitCodeMapEncoder.finish());
+    m_codeBlock->setJITCodeMap(m_jitCodeMapEncoder.finish());
 #endif
-        
-#if ENABLE(DFG_OSR_EXIT)
-        linkOSRExits(speculative);
-#else
-        SpeculationCheckIndexIterator checkIterator(speculative.speculationChecks());
-        NonSpeculativeJIT nonSpeculative(*this);
-        nonSpeculative.compile(checkIterator);
-
-        // Link the bail-outs from the speculative path to the corresponding entry points into the non-speculative one.
-        linkSpeculationChecks(speculative, nonSpeculative);
-#endif
-    } else {
-        // If compilation through the SpeculativeJIT failed, throw away the code we generated.
-        m_calls.clear();
-        m_propertyAccesses.clear();
-        m_jsCalls.clear();
-        m_methodGets.clear();
-        rewindToLabel(speculativePathBegin);
-
-#if ENABLE(DFG_OSR_EXIT)
-        SpeculationCheckIndexIterator checkIterator;
-#else
-        SpeculationCheckVector noChecks;
-        SpeculationCheckIndexIterator checkIterator(noChecks);
-#endif
-        NonSpeculativeJIT nonSpeculative(*this);
-        nonSpeculative.compile(checkIterator);
-    }
+    
+    linkOSRExits(speculative);
 
     // Iterate over the m_calls vector, checking for exception checks,
     // and linking them to here.