spill unboxed values in DFG 32_64
authoryuqiang.xian@intel.com <yuqiang.xian@intel.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 29 Dec 2011 04:33:20 +0000 (04:33 +0000)
committeryuqiang.xian@intel.com <yuqiang.xian@intel.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 29 Dec 2011 04:33:20 +0000 (04:33 +0000)
https://bugs.webkit.org/show_bug.cgi?id=75291

Reviewed by Filip Pizlo.

Currently all the values are spilled as boxed in DFG 32_64, which is
not necessary and introduces additional stores/loads. Instead we
can spill them as unboxed if feasible. It can be applied to the
Integers, Cells and Booleans in DFG 32_64. Doubles are left as is
because they don't need to be boxed at all. The modifications to the
spill/fill and the OSR exit are required, as well as a bug fix to the
"isUnknownJS" logic.

* bytecode/ValueRecovery.h:
(JSC::ValueRecovery::displacedInRegisterFile):
(JSC::ValueRecovery::virtualRegister):
(JSC::ValueRecovery::dump):
* dfg/DFGGenerationInfo.h:
(JSC::DFG::GenerationInfo::isUnknownJS):
(JSC::DFG::GenerationInfo::spill):
* dfg/DFGOSRExitCompiler32_64.cpp:
(JSC::DFG::OSRExitCompiler::compileExit):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::isKnownNotBoolean):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::silentFillGPR):
(JSC::DFG::SpeculativeJIT::spill):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::fillInteger):
(JSC::DFG::SpeculativeJIT::fillDouble):
(JSC::DFG::SpeculativeJIT::fillJSValue):
(JSC::DFG::SpeculativeJIT::fillSpeculateIntInternal):
(JSC::DFG::SpeculativeJIT::fillSpeculateDouble):
(JSC::DFG::SpeculativeJIT::fillSpeculateCell):
(JSC::DFG::SpeculativeJIT::fillSpeculateBoolean):
(JSC::DFG::SpeculativeJIT::compileObjectEquality):
(JSC::DFG::SpeculativeJIT::compile):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@103792 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecode/ValueRecovery.h
Source/JavaScriptCore/dfg/DFGGenerationInfo.h
Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

index 47373bbe8183d916b8a7505c231abd8057c42af6..643e9aa9ce237df3e6ac1d1123434bdd0c969232 100644 (file)
@@ -1,3 +1,43 @@
+2011-12-28  Yuqiang Xian  <yuqiang.xian@intel.com>
+
+        spill unboxed values in DFG 32_64
+        https://bugs.webkit.org/show_bug.cgi?id=75291
+
+        Reviewed by Filip Pizlo.
+
+        Currently all the values are spilled as boxed in DFG 32_64, which is
+        not necessary and introduces additional stores/loads. Instead we
+        can spill them as unboxed if feasible. It can be applied to the
+        Integers, Cells and Booleans in DFG 32_64. Doubles are left as is
+        because they don't need to be boxed at all. The modifications to the
+        spill/fill and the OSR exit are required, as well as a bug fix to the
+        "isUnknownJS" logic.
+
+        * bytecode/ValueRecovery.h:
+        (JSC::ValueRecovery::displacedInRegisterFile):
+        (JSC::ValueRecovery::virtualRegister):
+        (JSC::ValueRecovery::dump):
+        * dfg/DFGGenerationInfo.h:
+        (JSC::DFG::GenerationInfo::isUnknownJS):
+        (JSC::DFG::GenerationInfo::spill):
+        * dfg/DFGOSRExitCompiler32_64.cpp:
+        (JSC::DFG::OSRExitCompiler::compileExit):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::isKnownNotBoolean):
+        * dfg/DFGSpeculativeJIT.h:
+        (JSC::DFG::SpeculativeJIT::silentFillGPR):
+        (JSC::DFG::SpeculativeJIT::spill):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::fillInteger):
+        (JSC::DFG::SpeculativeJIT::fillDouble):
+        (JSC::DFG::SpeculativeJIT::fillJSValue):
+        (JSC::DFG::SpeculativeJIT::fillSpeculateIntInternal):
+        (JSC::DFG::SpeculativeJIT::fillSpeculateDouble):
+        (JSC::DFG::SpeculativeJIT::fillSpeculateCell):
+        (JSC::DFG::SpeculativeJIT::fillSpeculateBoolean):
+        (JSC::DFG::SpeculativeJIT::compileObjectEquality):
+        (JSC::DFG::SpeculativeJIT::compile):
+
 2011-12-28  Anders Carlsson  <andersca@apple.com>
 
         Add an implicit block conversion operator to WTF::Function
index 5c9fd0a0f200586609a0a576fefe97b2dd1898ac..356abe84f08707fc6d405899a21b139ad467a480 100644 (file)
@@ -62,6 +62,8 @@ enum ValueRecoveryTechnique {
     // It's in the register file, at a different location, and it's unboxed.
     Int32DisplacedInRegisterFile,
     DoubleDisplacedInRegisterFile,
+    CellDisplacedInRegisterFile,
+    BooleanDisplacedInRegisterFile,
     // It's a constant.
     Constant,
     // Don't know how to recover it.
@@ -166,6 +168,14 @@ public:
             result.m_technique = DoubleDisplacedInRegisterFile;
             break;
 
+        case DataFormatCell:
+            result.m_technique = CellDisplacedInRegisterFile;
+            break;
+            
+        case DataFormatBoolean:
+            result.m_technique = BooleanDisplacedInRegisterFile;
+            break;
+            
         default:
             ASSERT(dataFormat != DataFormatNone && dataFormat != DataFormatStorage);
             result.m_technique = DisplacedInRegisterFile;
@@ -229,7 +239,7 @@ public:
     
     VirtualRegister virtualRegister() const
     {
-        ASSERT(m_technique == DisplacedInRegisterFile || m_technique == Int32DisplacedInRegisterFile || m_technique == DoubleDisplacedInRegisterFile);
+        ASSERT(m_technique == DisplacedInRegisterFile || m_technique == Int32DisplacedInRegisterFile || m_technique == DoubleDisplacedInRegisterFile || m_technique == CellDisplacedInRegisterFile || m_technique == BooleanDisplacedInRegisterFile);
         return m_source.virtualReg;
     }
     
@@ -287,6 +297,12 @@ public:
         case DoubleDisplacedInRegisterFile:
             fprintf(out, "*double(%d)", virtualRegister());
             break;
+        case CellDisplacedInRegisterFile:
+            fprintf(out, "*cell(%d)", virtualRegister());
+            break;
+        case BooleanDisplacedInRegisterFile:
+            fprintf(out, "*bool(%d)", virtualRegister());
+            break;
         case Constant:
             fprintf(out, "[%s]", constant().description());
             break;
index 72b91d6ca69857844e9362a5fd178bbc33e38411..6f0fe3143edbe6225178e2befeee85931371bcfc 100644 (file)
@@ -195,8 +195,9 @@ public:
     
     bool isUnknownJS()
     {
-        return registerFormat() == DataFormatNone || registerFormat() == DataFormatJS
-            || spillFormat() == DataFormatNone || spillFormat() == DataFormatJS;
+        return spillFormat() == DataFormatNone
+            ? registerFormat() == DataFormatJS || registerFormat() == DataFormatNone
+            : spillFormat() == DataFormatJS;
     }
 
     // Get the machine resister currently holding the value.
@@ -230,12 +231,6 @@ public:
         ASSERT(m_spillFormat == DataFormatNone);
         // We should only be spilling values that are currently in machine registers.
         ASSERT(m_registerFormat != DataFormatNone);
-        // We only spill values that have been boxed as a JSValue because historically
-        // we assumed that the GC would want to be able to precisely identify heap
-        // pointers. This is not true anymore, but we still assume, in the fill code,
-        // that any spill slot for a JS value is boxed. For storage pointers, there is
-        // nothing we can do to box them, so we allow that to be an exception.
-        ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatStorage || spillFormat == DataFormatInteger || spillFormat == DataFormatDouble);
 
         m_registerFormat = DataFormatNone;
         m_spillFormat = spillFormat;
index 57dcb275af6516b4a67c1af8a9fb80e1da32af12..3d27e00e4652b5f19e8fe4571e86294e0673f7f2 100644 (file)
@@ -133,6 +133,9 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, SpeculationRecovery* reco
         const ValueRecovery& recovery = exit.valueRecovery(index);
         switch (recovery.technique()) {
         case DisplacedInRegisterFile:
+        case Int32DisplacedInRegisterFile:
+        case CellDisplacedInRegisterFile:
+        case BooleanDisplacedInRegisterFile:
             numberOfDisplacedVirtualRegisters++;
             ASSERT((int)recovery.virtualRegister() >= 0);
             
@@ -346,19 +349,42 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, SpeculationRecovery* reco
             unsigned displacementIndex = 0;
             for (int index = 0; index < exit.numberOfRecoveries(); ++index) {
                 const ValueRecovery& recovery = exit.valueRecovery(index);
-                if (recovery.technique() != DisplacedInRegisterFile)
-                    continue;
-                m_jit.load32(AssemblyHelpers::payloadFor(recovery.virtualRegister()), GPRInfo::toRegister(displacementIndex++));
-                m_jit.load32(AssemblyHelpers::tagFor(recovery.virtualRegister()), GPRInfo::toRegister(displacementIndex++));
+                switch (recovery.technique()) {
+                case DisplacedInRegisterFile:
+                    m_jit.load32(AssemblyHelpers::payloadFor(recovery.virtualRegister()), GPRInfo::toRegister(displacementIndex++));
+                    m_jit.load32(AssemblyHelpers::tagFor(recovery.virtualRegister()), GPRInfo::toRegister(displacementIndex++));
+                    break;
+                case Int32DisplacedInRegisterFile:
+                    m_jit.load32(AssemblyHelpers::payloadFor(recovery.virtualRegister()), GPRInfo::toRegister(displacementIndex++));
+                    m_jit.move(AssemblyHelpers::TrustedImm32(JSValue::Int32Tag), GPRInfo::toRegister(displacementIndex++));
+                    break;
+                case CellDisplacedInRegisterFile:
+                    m_jit.load32(AssemblyHelpers::payloadFor(recovery.virtualRegister()), GPRInfo::toRegister(displacementIndex++));
+                    m_jit.move(AssemblyHelpers::TrustedImm32(JSValue::CellTag), GPRInfo::toRegister(displacementIndex++));
+                    break;
+                case BooleanDisplacedInRegisterFile:
+                    m_jit.load32(AssemblyHelpers::payloadFor(recovery.virtualRegister()), GPRInfo::toRegister(displacementIndex++));
+                    m_jit.move(AssemblyHelpers::TrustedImm32(JSValue::BooleanTag), GPRInfo::toRegister(displacementIndex++));
+                    break;
+                default:
+                    break;
+                }
             }
         
             displacementIndex = 0;
             for (int index = 0; index < exit.numberOfRecoveries(); ++index) {
                 const ValueRecovery& recovery = exit.valueRecovery(index);
-                if (recovery.technique() != DisplacedInRegisterFile)
-                    continue;
-                m_jit.store32(GPRInfo::toRegister(displacementIndex++), AssemblyHelpers::payloadFor((VirtualRegister)exit.operandForIndex(index)));
-                m_jit.store32(GPRInfo::toRegister(displacementIndex++), AssemblyHelpers::tagFor((VirtualRegister)exit.operandForIndex(index)));
+                switch (recovery.technique()) {
+                case DisplacedInRegisterFile:
+                case Int32DisplacedInRegisterFile:
+                case CellDisplacedInRegisterFile:
+                case BooleanDisplacedInRegisterFile:
+                    m_jit.store32(GPRInfo::toRegister(displacementIndex++), AssemblyHelpers::payloadFor((VirtualRegister)exit.operandForIndex(index)));
+                    m_jit.store32(GPRInfo::toRegister(displacementIndex++), AssemblyHelpers::tagFor((VirtualRegister)exit.operandForIndex(index)));
+                    break;
+                default:
+                    break;
+                }
             }
         } else {
             // FIXME: This should use the shuffling algorithm that we use
@@ -381,25 +407,54 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, SpeculationRecovery* reco
             unsigned scratchIndex = numberOfPoisonedVirtualRegisters;
             for (int index = 0; index < exit.numberOfRecoveries(); ++index) {
                 const ValueRecovery& recovery = exit.valueRecovery(index);
-                if (recovery.technique() != DisplacedInRegisterFile)
-                    continue;
-                m_jit.load32(AssemblyHelpers::payloadFor(recovery.virtualRegister()), GPRInfo::regT0);
-                m_jit.load32(AssemblyHelpers::tagFor(recovery.virtualRegister()), GPRInfo::regT1);
-                m_jit.store32(GPRInfo::regT0, reinterpret_cast<char*>(scratchBuffer + scratchIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
-                m_jit.store32(GPRInfo::regT1, reinterpret_cast<char*>(scratchBuffer + scratchIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
-                scratchIndex++;
+                switch (recovery.technique()) {
+                case DisplacedInRegisterFile:
+                    m_jit.load32(AssemblyHelpers::payloadFor(recovery.virtualRegister()), GPRInfo::regT0);
+                    m_jit.load32(AssemblyHelpers::tagFor(recovery.virtualRegister()), GPRInfo::regT1);
+                    m_jit.store32(GPRInfo::regT0, reinterpret_cast<char*>(scratchBuffer + scratchIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
+                    m_jit.store32(GPRInfo::regT1, reinterpret_cast<char*>(scratchBuffer + scratchIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
+                    scratchIndex++;
+                    break;
+                case Int32DisplacedInRegisterFile:
+                case CellDisplacedInRegisterFile:
+                case BooleanDisplacedInRegisterFile:
+                    m_jit.load32(AssemblyHelpers::payloadFor(recovery.virtualRegister()), GPRInfo::regT0);
+                    m_jit.store32(GPRInfo::regT0, reinterpret_cast<char*>(scratchBuffer + scratchIndex++) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
+                    break;
+                default:
+                    break;
+                }
             }
         
             scratchIndex = numberOfPoisonedVirtualRegisters;
             for (int index = 0; index < exit.numberOfRecoveries(); ++index) {
                 const ValueRecovery& recovery = exit.valueRecovery(index);
-                if (recovery.technique() != DisplacedInRegisterFile)
-                    continue;
-                m_jit.load32(reinterpret_cast<char*>(scratchBuffer + scratchIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload), GPRInfo::regT0);
-                m_jit.load32(reinterpret_cast<char*>(scratchBuffer + scratchIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag), GPRInfo::regT1);
-                m_jit.store32(GPRInfo::regT0, AssemblyHelpers::payloadFor((VirtualRegister)exit.operandForIndex(index)));
-                m_jit.store32(GPRInfo::regT1, AssemblyHelpers::tagFor((VirtualRegister)exit.operandForIndex(index)));
-                scratchIndex++;
+                switch (recovery.technique()) {
+                case DisplacedInRegisterFile:
+                    m_jit.load32(reinterpret_cast<char*>(scratchBuffer + scratchIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload), GPRInfo::regT0);
+                    m_jit.load32(reinterpret_cast<char*>(scratchBuffer + scratchIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag), GPRInfo::regT1);
+                    m_jit.store32(GPRInfo::regT0, AssemblyHelpers::payloadFor((VirtualRegister)exit.operandForIndex(index)));
+                    m_jit.store32(GPRInfo::regT1, AssemblyHelpers::tagFor((VirtualRegister)exit.operandForIndex(index)));
+                    scratchIndex++;
+                    break;
+                case Int32DisplacedInRegisterFile:
+                    m_jit.load32(reinterpret_cast<char*>(scratchBuffer + scratchIndex++) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload), GPRInfo::regT0);
+                    m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::Int32Tag), AssemblyHelpers::tagFor((VirtualRegister)exit.operandForIndex(index)));
+                    m_jit.store32(GPRInfo::regT0, AssemblyHelpers::payloadFor((VirtualRegister)exit.operandForIndex(index)));
+                    break;
+                case CellDisplacedInRegisterFile:
+                    m_jit.load32(reinterpret_cast<char*>(scratchBuffer + scratchIndex++) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload), GPRInfo::regT0);
+                    m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::CellTag), AssemblyHelpers::tagFor((VirtualRegister)exit.operandForIndex(index)));
+                    m_jit.store32(GPRInfo::regT0, AssemblyHelpers::payloadFor((VirtualRegister)exit.operandForIndex(index)));
+                    break;
+                case BooleanDisplacedInRegisterFile:
+                    m_jit.load32(reinterpret_cast<char*>(scratchBuffer + scratchIndex++) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload), GPRInfo::regT0);
+                    m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::BooleanTag), AssemblyHelpers::tagFor((VirtualRegister)exit.operandForIndex(index)));
+                    m_jit.store32(GPRInfo::regT0, AssemblyHelpers::payloadFor((VirtualRegister)exit.operandForIndex(index)));
+                    break;
+                default:
+                    break;
+                }
             }
         
             ASSERT(scratchIndex == numberOfPoisonedVirtualRegisters + numberOfDisplacedVirtualRegisters);
index 549c3d03246819d3c69171b7954d2085c66aaa04..939fef669e0084c3496ee933f57798d27203f391 100644 (file)
@@ -199,6 +199,16 @@ bool SpeculativeJIT::isKnownBoolean(NodeIndex nodeIndex)
     return info.isJSBoolean();
 }
 
+bool SpeculativeJIT::isKnownNotBoolean(NodeIndex nodeIndex)
+{
+    Node& node = m_jit.graph()[nodeIndex];
+    VirtualRegister virtualRegister = node.virtualRegister();
+    GenerationInfo& info = m_generationInfo[virtualRegister];
+    if (node.hasConstant() && !valueOfJSConstant(nodeIndex).isBoolean())
+        return true;
+    return !(info.isJSBoolean() || info.isUnknownJS());
+}
+
 void SpeculativeJIT::writeBarrier(MacroAssembler& jit, GPRReg owner, GPRReg scratch1, GPRReg scratch2, WriteBarrierUseKind useKind)
 {
     UNUSED_PARAM(jit);
index 7cc37a86d7424d943e6775109698ea8b5ebc290c..da48d3a2c7684b4d0261071d78053f4fc5b116e4 100644 (file)
@@ -481,14 +481,27 @@ private:
         if (node.hasConstant()) {
             JSValue v = valueOfJSConstant(nodeIndex);
             m_jit.move(info.tagGPR() == target ? Imm32(v.tag()) : Imm32(v.payload()), target);
-        } else if (info.spillFormat() == DataFormatInteger) {
-            ASSERT(registerFormat == DataFormatJSInteger);
-            if (info.payloadGPR() == target) 
-                m_jit.load32(JITCompiler::payloadFor(spillMe), target);
-            else
+        } else if (info.payloadGPR() == target)
+            m_jit.load32(JITCompiler::payloadFor(spillMe), target);
+        else { // Fill the Tag
+            switch (info.spillFormat()) {
+            case DataFormatInteger:
+                ASSERT(registerFormat == DataFormatJSInteger);
                 m_jit.move(TrustedImm32(JSValue::Int32Tag), target);
-        } else
-            m_jit.load32(info.tagGPR() == target ? JITCompiler::tagFor(spillMe) : JITCompiler::payloadFor(spillMe), target);
+                break;
+            case DataFormatCell:
+                ASSERT(registerFormat == DataFormatJSCell);
+                m_jit.move(TrustedImm32(JSValue::CellTag), target);
+                break;
+            case DataFormatBoolean:
+                ASSERT(registerFormat == DataFormatJSBoolean);
+                m_jit.move(TrustedImm32(JSValue::BooleanTag), target);
+                break;
+            default:
+                m_jit.load32(JITCompiler::tagFor(spillMe), target);
+                break;
+            }
+        }
 #endif
     }
 
@@ -636,6 +649,12 @@ private:
             return;
         }
 
+        case DataFormatInteger: {
+            m_jit.store32(info.gpr(), JITCompiler::payloadFor(spillMe));
+            info.spill(DataFormatInteger);
+            return;
+        }
+
 #if USE(JSVALUE64)
         case DataFormatDouble: {
             m_jit.storeDouble(info.fpr(), JITCompiler::addressFor(spillMe));
@@ -643,12 +662,6 @@ private:
             return;
         }
             
-        case DataFormatInteger: {
-            m_jit.store32(info.gpr(), JITCompiler::payloadFor(spillMe));
-            info.spill(DataFormatInteger);
-            return;
-        }
-
         default:
             // The following code handles JSValues, int32s, and cells.
             ASSERT(spillFormat == DataFormatCell || spillFormat & DataFormatJS);
@@ -664,6 +677,13 @@ private:
             info.spill((DataFormat)(spillFormat | DataFormatJS));
             return;
 #elif USE(JSVALUE32_64)
+        case DataFormatCell:
+        case DataFormatBoolean: {
+            m_jit.store32(info.gpr(), JITCompiler::payloadFor(spillMe));
+            info.spill(spillFormat);
+            return;
+        }
+
         case DataFormatDouble:
         case DataFormatJSDouble: {
             // On JSVALUE32_64 boxing a double is a no-op.
@@ -671,25 +691,13 @@ private:
             info.spill(DataFormatJSDouble);
             return;
         }
+
         default:
-            // The following code handles JSValues, int32s, cells and booleans.
-            ASSERT(spillFormat == DataFormatInteger || spillFormat == DataFormatCell || spillFormat == DataFormatBoolean || (spillFormat & DataFormatJS));
-
-            if (spillFormat & DataFormatJS) { // JSValue
-                m_jit.store32(info.tagGPR(), JITCompiler::tagFor(spillMe));
-                m_jit.store32(info.payloadGPR(), JITCompiler::payloadFor(spillMe));
-            } else {
-                GPRReg reg = info.gpr();
-                m_jit.store32(reg, JITCompiler::payloadFor(spillMe));
-                // We need to box int32s, booleans and cells.
-                if (spillFormat == DataFormatInteger)
-                    m_jit.store32(TrustedImm32(JSValue::Int32Tag), JITCompiler::tagFor(spillMe));
-                else if (spillFormat == DataFormatCell)
-                    m_jit.store32(TrustedImm32(JSValue::CellTag), JITCompiler::tagFor(spillMe));
-                else
-                    m_jit.store32(TrustedImm32(JSValue::BooleanTag), JITCompiler::tagFor(spillMe));
-            }
-            info.spill((DataFormat)(spillFormat | DataFormatJS));
+            // The following code handles JSValues.
+            ASSERT(spillFormat & DataFormatJS);
+            m_jit.store32(info.tagGPR(), JITCompiler::tagFor(spillMe));
+            m_jit.store32(info.payloadGPR(), JITCompiler::payloadFor(spillMe));
+            info.spill(spillFormat);
             return;
 #endif
         }
@@ -705,6 +713,7 @@ private:
     bool isKnownNotNumber(NodeIndex);
 
     bool isKnownBoolean(NodeIndex);
+    bool isKnownNotBoolean(NodeIndex);
 
     bool isKnownNotCell(NodeIndex);
     
index f509383852f4498f3c89687e3466f708f4101832..bbe6171eb1f1c0c0bd8b66d695bd70d06cd8cfe4 100644 (file)
@@ -56,7 +56,7 @@ GPRReg SpeculativeJIT::fillInteger(NodeIndex nodeIndex, DataFormat& returnFormat
                 m_jit.move(MacroAssembler::Imm32(jsValue.payload()), gpr);
             }
         } else {
-            ASSERT(info.spillFormat() == DataFormatJS || info.spillFormat() == DataFormatJSInteger);
+            ASSERT(info.spillFormat() == DataFormatJS || info.spillFormat() == DataFormatJSInteger || info.spillFormat() == DataFormatInteger);
             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
             m_jit.load32(JITCompiler::payloadFor(virtualRegister), gpr);
         }
@@ -136,7 +136,7 @@ FPRReg SpeculativeJIT::fillDouble(NodeIndex nodeIndex)
             }
         } else {
             DataFormat spillFormat = info.spillFormat();
-            ASSERT(spillFormat & DataFormatJS);
+            ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatInteger);
             if (spillFormat == DataFormatJSDouble) {
                 FPRReg fpr = fprAllocate();
                 m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
@@ -146,14 +146,20 @@ FPRReg SpeculativeJIT::fillDouble(NodeIndex nodeIndex)
             }
 
             FPRReg fpr = fprAllocate();
-            JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag));
-            m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
-            JITCompiler::Jump hasUnboxedDouble = m_jit.jump();
+            JITCompiler::Jump hasUnboxedDouble;
+
+            if (spillFormat != DataFormatJSInteger && spillFormat != DataFormatInteger) {
+                JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag));
+                m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
+                hasUnboxedDouble = m_jit.jump();
+                isInteger.link(&m_jit);
+            }
 
-            isInteger.link(&m_jit);
             m_jit.convertInt32ToDouble(JITCompiler::payloadFor(virtualRegister), fpr);
 
-            hasUnboxedDouble.link(&m_jit);
+            if (hasUnboxedDouble.isSet())
+                hasUnboxedDouble.link(&m_jit);
+
             m_fprs.retain(fpr, virtualRegister, SpillOrderSpilled);
             info.fillDouble(fpr);
             return fpr;
@@ -192,7 +198,7 @@ FPRReg SpeculativeJIT::fillDouble(NodeIndex nodeIndex)
 
         m_jit.convertInt32ToDouble(payloadGPR, fpr);
 
-        if (info.registerFormat() != DataFormatJSInteger)
+        if (hasUnboxedDouble.isSet())
             hasUnboxedDouble.link(&m_jit);
 
         m_gprs.release(tagGPR);
@@ -248,10 +254,26 @@ bool SpeculativeJIT::fillJSValue(NodeIndex nodeIndex, GPRReg& tagGPR, GPRReg& pa
             info.fillJSValue(tagGPR, payloadGPR, isInt32Constant(nodeIndex) ? DataFormatJSInteger : DataFormatJS);
         } else {
             DataFormat spillFormat = info.spillFormat();
-            ASSERT(spillFormat & DataFormatJS);
+            ASSERT(spillFormat != DataFormatNone && spillFormat != DataFormatStorage);
             tagGPR = allocate();
             payloadGPR = allocate();
-            m_jit.load32(JITCompiler::tagFor(virtualRegister), tagGPR);
+            switch (spillFormat) {
+            case DataFormatInteger:
+                m_jit.move(TrustedImm32(JSValue::Int32Tag), tagGPR);
+                spillFormat = DataFormatJSInteger; // This will be used as the new register format.
+                break;
+            case DataFormatCell:
+                m_jit.move(TrustedImm32(JSValue::CellTag), tagGPR);
+                spillFormat = DataFormatJSCell; // This will be used as the new register format.
+                break;
+            case DataFormatBoolean:
+                m_jit.move(TrustedImm32(JSValue::BooleanTag), tagGPR);
+                spillFormat = DataFormatJSBoolean; // This will be used as the new register format.
+                break;
+            default:
+                m_jit.load32(JITCompiler::tagFor(virtualRegister), tagGPR);
+                break;
+            }
             m_jit.load32(JITCompiler::payloadFor(virtualRegister), payloadGPR);
             m_gprs.retain(tagGPR, virtualRegister, SpillOrderSpilled);
             m_gprs.retain(payloadGPR, virtualRegister, SpillOrderSpilled);
@@ -956,37 +978,39 @@ GPRReg SpeculativeJIT::fillSpeculateIntInternal(NodeIndex nodeIndex, DataFormat&
 #if DFG_ENABLE(DEBUG_VERBOSE)
     fprintf(stderr, "SpecInt@%d   ", nodeIndex);
 #endif
+    if (isKnownNotInteger(nodeIndex)) {
+        terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+        returnFormat = DataFormatInteger;
+        return allocate();
+    }
+
     Node& node = at(nodeIndex);
     VirtualRegister virtualRegister = node.virtualRegister();
     GenerationInfo& info = m_generationInfo[virtualRegister];
 
     switch (info.registerFormat()) {
     case DataFormatNone: {
-        GPRReg gpr = allocate();
 
         if (node.hasConstant()) {
+            ASSERT(isInt32Constant(nodeIndex));
+            GPRReg gpr = allocate();
+            m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr);
             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
-            if (isInt32Constant(nodeIndex)) {
-                m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr);
-                info.fillInteger(gpr);
-                returnFormat = DataFormatInteger;
-                return gpr;
-            }
-            terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+            info.fillInteger(gpr);
             returnFormat = DataFormatInteger;
-            return allocate();
+            return gpr;
         }
 
         DataFormat spillFormat = info.spillFormat();
-        ASSERT(spillFormat & DataFormatJS);
-
-        m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
+        ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatInteger);
 
         // If we know this was spilled as an integer we can fill without checking.
-        if (spillFormat != DataFormatJSInteger)
+        if (spillFormat != DataFormatJSInteger && spillFormat != DataFormatInteger)
             speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag)));
 
+        GPRReg gpr = allocate();
         m_jit.load32(JITCompiler::payloadFor(virtualRegister), gpr);
+        m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
         info.fillInteger(gpr);
         returnFormat = DataFormatInteger;
         return gpr;
@@ -1023,12 +1047,7 @@ GPRReg SpeculativeJIT::fillSpeculateIntInternal(NodeIndex nodeIndex, DataFormat&
     case DataFormatBoolean:
     case DataFormatJSDouble:
     case DataFormatJSCell:
-    case DataFormatJSBoolean: {
-        terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
-        returnFormat = DataFormatInteger;
-        return allocate();
-    }
-
+    case DataFormatJSBoolean:
     case DataFormatStorage:
         ASSERT_NOT_REACHED();
     }
@@ -1055,6 +1074,11 @@ FPRReg SpeculativeJIT::fillSpeculateDouble(NodeIndex nodeIndex)
 #if DFG_ENABLE(DEBUG_VERBOSE)
     fprintf(stderr, "SpecDouble@%d   ", nodeIndex);
 #endif
+    if (isKnownNotNumber(nodeIndex)) {
+        terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+        return fprAllocate();
+    }
+
     Node& node = at(nodeIndex);
     VirtualRegister virtualRegister = node.virtualRegister();
     GenerationInfo& info = m_generationInfo[virtualRegister];
@@ -1074,13 +1098,11 @@ FPRReg SpeculativeJIT::fillSpeculateDouble(NodeIndex nodeIndex)
                 m_fprs.retain(fpr, virtualRegister, SpillOrderConstant);
                 info.fillDouble(fpr);
                 return fpr;
-            } else {
-                terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
-                return fprAllocate();
-            }
+            } else
+                ASSERT_NOT_REACHED();
         } else {
             DataFormat spillFormat = info.spillFormat();
-            ASSERT(spillFormat & DataFormatJS);
+            ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatInteger);
             if (spillFormat == DataFormatJSDouble) {
                 FPRReg fpr = fprAllocate();
                 m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
@@ -1090,15 +1112,22 @@ FPRReg SpeculativeJIT::fillSpeculateDouble(NodeIndex nodeIndex)
             }
 
             FPRReg fpr = fprAllocate();
-            JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag));
-            speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), nodeIndex, m_jit.branch32(MacroAssembler::AboveOrEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::LowestTag)));
-            m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
-            JITCompiler::Jump hasUnboxedDouble = m_jit.jump();
+            JITCompiler::Jump hasUnboxedDouble;
+
+            if (spillFormat != DataFormatJSInteger && spillFormat != DataFormatInteger) {
+                JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag));
+                speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), nodeIndex, m_jit.branch32(MacroAssembler::AboveOrEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::LowestTag)));
+                m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
+                hasUnboxedDouble = m_jit.jump();
+
+                isInteger.link(&m_jit);
+            }
 
-            isInteger.link(&m_jit);
             m_jit.convertInt32ToDouble(JITCompiler::payloadFor(virtualRegister), fpr);
 
-            hasUnboxedDouble.link(&m_jit);
+            if (hasUnboxedDouble.isSet())
+                hasUnboxedDouble.link(&m_jit);
+
             m_fprs.retain(fpr, virtualRegister, SpillOrderSpilled);
             info.fillDouble(fpr);
             return fpr;
@@ -1106,20 +1135,8 @@ FPRReg SpeculativeJIT::fillSpeculateDouble(NodeIndex nodeIndex)
     }
 
     switch (info.registerFormat()) {
-    case DataFormatNone:
-    case DataFormatBoolean:
-    case DataFormatStorage:
-        // Should have filled, above.
-        ASSERT_NOT_REACHED();
-
-    case DataFormatCell:
-        terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
-        return fprAllocate();
-
-    case DataFormatJSCell:
     case DataFormatJS:
-    case DataFormatJSInteger:
-    case DataFormatJSBoolean: {
+    case DataFormatJSInteger: {
         GPRReg tagGPR = info.tagGPR();
         GPRReg payloadGPR = info.payloadGPR();
         FPRReg fpr = fprAllocate();
@@ -1140,7 +1157,7 @@ FPRReg SpeculativeJIT::fillSpeculateDouble(NodeIndex nodeIndex)
 
         m_jit.convertInt32ToDouble(payloadGPR, fpr);
 
-        if (info.registerFormat() != DataFormatJSInteger)
+        if (hasUnboxedDouble.isSet())
             hasUnboxedDouble.link(&m_jit);
 
         m_gprs.release(tagGPR);
@@ -1168,6 +1185,14 @@ FPRReg SpeculativeJIT::fillSpeculateDouble(NodeIndex nodeIndex)
         m_fprs.lock(fpr);
         return fpr;
     }
+
+    case DataFormatNone:
+    case DataFormatStorage:
+    case DataFormatCell:
+    case DataFormatJSCell:
+    case DataFormatBoolean:
+    case DataFormatJSBoolean:
+        ASSERT_NOT_REACHED();
     }
 
     ASSERT_NOT_REACHED();
@@ -1179,6 +1204,11 @@ GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex)
 #if DFG_ENABLE(DEBUG_VERBOSE)
     fprintf(stderr, "SpecCell@%d   ", nodeIndex);
 #endif
+    if (isKnownNotCell(nodeIndex)) {
+        terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+        return allocate();
+    }
+
     Node& node = at(nodeIndex);
     VirtualRegister virtualRegister = node.virtualRegister();
     GenerationInfo& info = m_generationInfo[virtualRegister];
@@ -1186,21 +1216,20 @@ GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex)
     switch (info.registerFormat()) {
     case DataFormatNone: {
 
-        GPRReg gpr = allocate();
         if (node.hasConstant()) {
             JSValue jsValue = valueOfJSConstant(nodeIndex);
-            if (jsValue.isCell()) {
-                m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
-                m_jit.move(MacroAssembler::TrustedImmPtr(jsValue.asCell()), gpr);
-                info.fillCell(gpr);
-                return gpr;
-            }
-            terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+            ASSERT(jsValue.isCell());
+            GPRReg gpr = allocate();
+            m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
+            m_jit.move(MacroAssembler::TrustedImmPtr(jsValue.asCell()), gpr);
+            info.fillCell(gpr);
             return gpr;
         }
-        ASSERT(info.spillFormat() & DataFormatJS);
-        if (info.spillFormat() != DataFormatJSCell)
+
+        ASSERT((info.spillFormat() & DataFormatJS) || info.spillFormat() == DataFormatCell);
+        if (info.spillFormat() != DataFormatJSCell && info.spillFormat() != DataFormatCell)
             speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::CellTag)));
+        GPRReg gpr = allocate();
         m_jit.load32(JITCompiler::payloadFor(virtualRegister), gpr);
         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
         info.fillCell(gpr);
@@ -1234,11 +1263,7 @@ GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex)
     case DataFormatJSDouble:
     case DataFormatDouble:
     case DataFormatJSBoolean:
-    case DataFormatBoolean: {
-        terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
-        return allocate();
-    }
-
+    case DataFormatBoolean:
     case DataFormatStorage:
         ASSERT_NOT_REACHED();
     }
@@ -1252,32 +1277,36 @@ GPRReg SpeculativeJIT::fillSpeculateBoolean(NodeIndex nodeIndex)
 #if DFG_ENABLE(DEBUG_VERBOSE)
      fprintf(stderr, "SpecBool@%d   ", nodeIndex);
 #endif
+    if (isKnownNotBoolean(nodeIndex)) {
+        terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+        return allocate();
+    }
+
     Node& node = at(nodeIndex);
     VirtualRegister virtualRegister = node.virtualRegister();
     GenerationInfo& info = m_generationInfo[virtualRegister];
 
     switch (info.registerFormat()) {
     case DataFormatNone: {
-        GPRReg gpr = allocate();
 
         if (node.hasConstant()) {
             JSValue jsValue = valueOfJSConstant(nodeIndex);
-            if (jsValue.isBoolean()) {
-                m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
-                m_jit.move(MacroAssembler::TrustedImm32(jsValue.asBoolean()), gpr);
-                info.fillBoolean(gpr);
-                return gpr;
-            }
-            terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+            ASSERT(jsValue.isBoolean());
+            GPRReg gpr = allocate();
+            m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
+            m_jit.move(MacroAssembler::TrustedImm32(jsValue.asBoolean()), gpr);
+            info.fillBoolean(gpr);
             return gpr;
         }
-        ASSERT(info.spillFormat() & DataFormatJS);
-        m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
 
-        if (info.spillFormat() != DataFormatJSBoolean)
+        ASSERT((info.spillFormat() & DataFormatJS) || info.spillFormat() == DataFormatBoolean);
+
+        if (info.spillFormat() != DataFormatJSBoolean && info.spillFormat() != DataFormatBoolean)
             speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::BooleanTag)));
 
+        GPRReg gpr = allocate();
         m_jit.load32(JITCompiler::payloadFor(virtualRegister), gpr);
+        m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
         info.fillBoolean(gpr);
         return gpr;
     }
@@ -1310,11 +1339,7 @@ GPRReg SpeculativeJIT::fillSpeculateBoolean(NodeIndex nodeIndex)
     case DataFormatJSDouble:
     case DataFormatDouble:
     case DataFormatJSCell:
-    case DataFormatCell: {
-        terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
-        return allocate();
-    }
-        
+    case DataFormatCell:
     case DataFormatStorage:
         ASSERT_NOT_REACHED();
     }
@@ -1345,17 +1370,17 @@ void SpeculativeJIT::compileObjectEquality(Node& node, const ClassInfo* classInf
 {
     SpeculateCellOperand op1(this, node.child1());
     SpeculateCellOperand op2(this, node.child2());
-    GPRTemporary resultPayload(this, op2);
-    
     GPRReg op1GPR = op1.gpr();
     GPRReg op2GPR = op2.gpr();
-    GPRReg resultPayloadGPR = resultPayload.gpr();
     
     if (!predictionCheck(m_state.forNode(node.child1()).m_type))
         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
     if (!predictionCheck(m_state.forNode(node.child2()).m_type))
         speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node.child2(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
     
+    GPRTemporary resultPayload(this, op2);
+    GPRReg resultPayloadGPR = resultPayload.gpr();
+    
     MacroAssembler::Jump falseCase = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, op2GPR);
     m_jit.move(Imm32(1), resultPayloadGPR);
     MacroAssembler::Jump done = m_jit.jump();
@@ -1986,8 +2011,6 @@ void SpeculativeJIT::compile(Node& node)
 #if CPU(X86)
             SpeculateIntegerOperand op1(this, node.child1());
             SpeculateIntegerOperand op2(this, node.child2());
-            GPRTemporary eax(this, X86Registers::eax);
-            GPRTemporary edx(this, X86Registers::edx);
             GPRReg op1GPR = op1.gpr();
             GPRReg op2GPR = op2.gpr();
             
@@ -2001,6 +2024,9 @@ void SpeculativeJIT::compile(Node& node)
                 numeratorNonZero.link(&m_jit);
             }
             
+            GPRTemporary eax(this, X86Registers::eax);
+            GPRTemporary edx(this, X86Registers::edx);
+
             GPRReg temp2 = InvalidGPRReg;
             if (op2GPR == X86Registers::eax || op2GPR == X86Registers::edx) {
                 temp2 = allocate();
@@ -2917,13 +2943,13 @@ void SpeculativeJIT::compile(Node& node)
         
         if (isObjectPrediction(at(node.child1()).prediction())) {
             SpeculateCellOperand thisValue(this, node.child1());
-            GPRTemporary result(this, thisValue);
             GPRReg thisValueGPR = thisValue.gpr();
-            GPRReg resultGPR = result.gpr();
             
             if (!isObjectPrediction(m_state.forNode(node.child1()).m_type))
                 speculationCheck(BadType, JSValueSource::unboxedCell(thisValueGPR), node.child1(), m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(thisValueGPR, JSCell::classInfoOffset()), JITCompiler::TrustedImmPtr(&JSString::s_info)));
             
+            GPRTemporary result(this, thisValue);
+            GPRReg resultGPR = result.gpr();
             m_jit.move(thisValueGPR, resultGPR);
             cellResult(resultGPR, m_compileIndex);
             break;
@@ -3133,14 +3159,14 @@ void SpeculativeJIT::compile(Node& node)
 
     case GetArrayLength: {
         SpeculateCellOperand base(this, node.child1());
-        GPRTemporary result(this);
-        
         GPRReg baseGPR = base.gpr();
-        GPRReg resultGPR = result.gpr();
         
         if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
             speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
         
+        GPRTemporary result(this);
+        GPRReg resultGPR = result.gpr();
+
         m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), resultGPR);
         m_jit.load32(MacroAssembler::Address(resultGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), resultGPR);
         
@@ -3168,14 +3194,14 @@ void SpeculativeJIT::compile(Node& node)
 
     case GetByteArrayLength: {
         SpeculateCellOperand base(this, node.child1());
-        GPRTemporary result(this);
-        
         GPRReg baseGPR = base.gpr();
-        GPRReg resultGPR = result.gpr();
         
         if (!isByteArrayPrediction(m_state.forNode(node.child1()).m_type))
             speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info)));
         
+        GPRTemporary result(this);
+        GPRReg resultGPR = result.gpr();
+        
         m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSByteArray::offsetOfStorage()), resultGPR);
         m_jit.load32(MacroAssembler::Address(baseGPR, ByteArray::offsetOfSize()), resultGPR);