DFG Speculative JIT does not always insert speculation checks when speculating
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGSpeculativeJIT.cpp
index e70ab27..47def27 100644 (file)
@@ -40,17 +40,18 @@ GPRReg SpeculativeJIT::fillSpeculateIntInternal(NodeIndex nodeIndex, DataFormat&
     switch (info.registerFormat()) {
     case DataFormatNone: {
         GPRReg gpr = allocate();
-        JITCompiler::RegisterID reg = JITCompiler::gprToRegisterID(gpr);
 
         if (node.isConstant()) {
             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
             if (isInt32Constant(nodeIndex)) {
-                m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), reg);
+                m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr);
                 info.fillInteger(gpr);
                 returnFormat = DataFormatInteger;
                 return gpr;
             }
-            m_jit.move(constantAsJSValueAsImmPtr(nodeIndex), reg);
+            terminateSpeculativeExecution();
+            returnFormat = DataFormatInteger;
+            return allocate();
         } else {
             DataFormat spillFormat = info.spillFormat();
             ASSERT(spillFormat & DataFormatJS);
@@ -60,17 +61,17 @@ GPRReg SpeculativeJIT::fillSpeculateIntInternal(NodeIndex nodeIndex, DataFormat&
             if (spillFormat == DataFormatJSInteger) {
                 // If we know this was spilled as an integer we can fill without checking.
                 if (strict) {
-                    m_jit.load32(JITCompiler::addressFor(virtualRegister), reg);
+                    m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
                     info.fillInteger(gpr);
                     returnFormat = DataFormatInteger;
                     return gpr;
                 }
-                m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), reg);
+                m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
                 info.fillJSValue(gpr, DataFormatJSInteger);
                 returnFormat = DataFormatJSInteger;
                 return gpr;
             }
-            m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), reg);
+            m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
         }
 
         // Fill as JSValue, and fall through.
@@ -82,8 +83,7 @@ GPRReg SpeculativeJIT::fillSpeculateIntInternal(NodeIndex nodeIndex, DataFormat&
         // Check the value is an integer.
         GPRReg gpr = info.gpr();
         m_gprs.lock(gpr);
-        JITCompiler::RegisterID reg = JITCompiler::gprToRegisterID(gpr);
-        speculationCheck(m_jit.branchPtr(MacroAssembler::Below, reg, JITCompiler::tagTypeNumberRegister));
+        speculationCheck(m_jit.branchPtr(MacroAssembler::Below, gpr, GPRInfo::tagTypeNumberRegister));
         info.fillJSValue(gpr, DataFormatJSInteger);
         // If !strict we're done, return.
         if (!strict) {
@@ -108,7 +108,7 @@ GPRReg SpeculativeJIT::fillSpeculateIntInternal(NodeIndex nodeIndex, DataFormat&
                 info.fillInteger(gpr);
                 result = gpr;
             }
-            m_jit.zeroExtend32ToPtr(JITCompiler::gprToRegisterID(gpr), JITCompiler::gprToRegisterID(result));
+            m_jit.zeroExtend32ToPtr(gpr, result);
             returnFormat = DataFormatInteger;
             return result;
         }
@@ -145,23 +145,21 @@ SpeculationCheck::SpeculationCheck(MacroAssembler::Jump check, SpeculativeJIT* j
     , m_nodeIndex(jit->m_compileIndex)
     , m_recoveryIndex(recoveryIndex)
 {
-    for (GPRReg gpr = gpr0; gpr < numberOfGPRs; next(gpr)) {
-        VirtualRegister virtualRegister = jit->m_gprs.name(gpr);
-        if (virtualRegister != InvalidVirtualRegister) {
-            GenerationInfo& info =  jit->m_generationInfo[virtualRegister];
-            m_gprInfo[gpr].nodeIndex = info.nodeIndex();
-            m_gprInfo[gpr].format = info.registerFormat();
+    for (gpr_iterator iter = jit->m_gprs.begin(); iter != jit->m_gprs.end(); ++iter) {
+        if (iter.name() != InvalidVirtualRegister) {
+            GenerationInfo& info =  jit->m_generationInfo[iter.name()];
+            m_gprInfo[iter.index()].nodeIndex = info.nodeIndex();
+            m_gprInfo[iter.index()].format = info.registerFormat();
         } else
-            m_gprInfo[gpr].nodeIndex = NoNode;
+            m_gprInfo[iter.index()].nodeIndex = NoNode;
     }
-    for (FPRReg fpr = fpr0; fpr < numberOfFPRs; next(fpr)) {
-        VirtualRegister virtualRegister = jit->m_fprs.name(fpr);
-        if (virtualRegister != InvalidVirtualRegister) {
-            GenerationInfo& info =  jit->m_generationInfo[virtualRegister];
+    for (fpr_iterator iter = jit->m_fprs.begin(); iter != jit->m_fprs.end(); ++iter) {
+        if (iter.name() != InvalidVirtualRegister) {
+            GenerationInfo& info =  jit->m_generationInfo[iter.name()];
             ASSERT(info.registerFormat() == DataFormatDouble);
-            m_fprInfo[fpr] = info.nodeIndex();
+            m_fprInfo[iter.index()] = info.nodeIndex();
         } else
-            m_fprInfo[fpr] = NoNode;
+            m_fprInfo[iter.index()] = NoNode;
     }
 }
 
@@ -178,6 +176,121 @@ GPRReg SpeculativeJIT::fillSpeculateIntStrict(NodeIndex nodeIndex)
     return result;
 }
 
+FPRReg SpeculativeJIT::fillSpeculateDouble(NodeIndex nodeIndex)
+{
+    Node& node = m_jit.graph()[nodeIndex];
+    VirtualRegister virtualRegister = node.virtualRegister();
+    GenerationInfo& info = m_generationInfo[virtualRegister];
+
+    if (info.registerFormat() == DataFormatNone) {
+        GPRReg gpr = allocate();
+
+        if (node.isConstant()) {
+            if (isInt32Constant(nodeIndex)) {
+                FPRReg fpr = fprAllocate();
+                m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(static_cast<double>(valueOfInt32Constant(nodeIndex))))), gpr);
+                m_jit.movePtrToDouble(gpr, fpr);
+                unlock(gpr);
+
+                m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
+                info.fillDouble(fpr);
+                return fpr;
+            }
+            if (isDoubleConstant(nodeIndex)) {
+                FPRReg fpr = fprAllocate();
+                m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfDoubleConstant(nodeIndex)))), gpr);
+                m_jit.movePtrToDouble(gpr, fpr);
+                unlock(gpr);
+
+                m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
+                info.fillDouble(fpr);
+                return fpr;
+            }
+            ASSERT(isJSConstant(nodeIndex));
+            JSValue jsValue = valueOfJSConstant(nodeIndex);
+            m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
+            m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
+            info.fillJSValue(gpr, DataFormatJS);
+            unlock(gpr);
+        } else {
+            DataFormat spillFormat = info.spillFormat();
+            ASSERT(spillFormat & DataFormatJS);
+            m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
+            m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
+            info.fillJSValue(gpr, spillFormat);
+            unlock(gpr);
+        }
+    }
+
+    switch (info.registerFormat()) {
+    case DataFormatNone:
+        // Should have filled, above.
+        ASSERT_NOT_REACHED();
+        
+    case DataFormatCell:
+    case DataFormatJSCell:
+    case DataFormatJS: {
+        GPRReg jsValueGpr = info.gpr();
+        m_gprs.lock(jsValueGpr);
+        FPRReg fpr = fprAllocate();
+        GPRReg tempGpr = allocate();
+
+        JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
+
+        speculationCheck(m_jit.branchTestPtr(MacroAssembler::Zero, jsValueGpr, GPRInfo::tagTypeNumberRegister));
+
+        // First, if we get here we have a double encoded as a JSValue
+        m_jit.move(jsValueGpr, tempGpr);
+        m_jit.addPtr(GPRInfo::tagTypeNumberRegister, tempGpr);
+        m_jit.movePtrToDouble(tempGpr, fpr);
+        JITCompiler::Jump hasUnboxedDouble = m_jit.jump();
+
+        // Finally, handle integers.
+        isInteger.link(&m_jit);
+        m_jit.convertInt32ToDouble(jsValueGpr, fpr);
+        hasUnboxedDouble.link(&m_jit);
+
+        m_gprs.release(jsValueGpr);
+        m_gprs.unlock(jsValueGpr);
+        m_gprs.unlock(tempGpr);
+        m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
+        info.fillDouble(fpr);
+        return fpr;
+    }
+
+    case DataFormatJSInteger:
+    case DataFormatInteger: {
+        FPRReg fpr = fprAllocate();
+        GPRReg gpr = info.gpr();
+        m_gprs.lock(gpr);
+        m_jit.convertInt32ToDouble(gpr, fpr);
+        m_gprs.unlock(gpr);
+        return fpr;
+    }
+
+    // Unbox the double
+    case DataFormatJSDouble: {
+        GPRReg gpr = info.gpr();
+        FPRReg fpr = unboxDouble(gpr);
+
+        m_gprs.release(gpr);
+        m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
+
+        info.fillDouble(fpr);
+        return fpr;
+    }
+
+    case DataFormatDouble: {
+        FPRReg fpr = info.fpr();
+        m_fprs.lock(fpr);
+        return fpr;
+    }
+    }
+
+    ASSERT_NOT_REACHED();
+    return InvalidFPRReg;
+}
+
 GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex)
 {
     Node& node = m_jit.graph()[nodeIndex];
@@ -187,13 +300,12 @@ GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex)
     switch (info.registerFormat()) {
     case DataFormatNone: {
         GPRReg gpr = allocate();
-        JITCompiler::RegisterID reg = JITCompiler::gprToRegisterID(gpr);
 
         if (node.isConstant()) {
-            m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
-            JSValue jsValue = constantAsJSValue(nodeIndex);
+            JSValue jsValue = valueOfJSConstant(nodeIndex);
             if (jsValue.isCell()) {
-                m_jit.move(MacroAssembler::TrustedImmPtr(jsValue.asCell()), reg);
+                m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
+                m_jit.move(MacroAssembler::TrustedImmPtr(jsValue.asCell()), gpr);
                 info.fillJSValue(gpr, DataFormatJSCell);
                 return gpr;
             }
@@ -202,10 +314,10 @@ GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex)
         }
         ASSERT(info.spillFormat() & DataFormatJS);
         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
-        m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), reg);
+        m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
 
         if (info.spillFormat() != DataFormatJSCell)
-            speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, reg, JITCompiler::tagMaskRegister));
+            speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister));
         info.fillJSValue(gpr, DataFormatJSCell);
         return gpr;
     }
@@ -220,8 +332,7 @@ GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex)
     case DataFormatJS: {
         GPRReg gpr = info.gpr();
         m_gprs.lock(gpr);
-        JITCompiler::RegisterID reg = JITCompiler::gprToRegisterID(gpr);
-        speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, reg, JITCompiler::tagMaskRegister));
+        speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister));
         info.fillJSValue(gpr, DataFormatJSCell);
         return gpr;
     }
@@ -239,9 +350,9 @@ GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex)
     return InvalidGPRReg;
 }
 
-void SpeculativeJIT::compilePeepHoleBranch(Node& node, JITCompiler::RelationalCondition condition)
+void SpeculativeJIT::compilePeepHoleIntegerBranch(Node& node, NodeIndex branchNodeIndex, JITCompiler::RelationalCondition condition)
 {
-    Node& branchNode = m_jit.graph()[m_compileIndex + 1];
+    Node& branchNode = m_jit.graph()[branchNodeIndex];
     BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
     BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
 
@@ -254,17 +365,18 @@ void SpeculativeJIT::compilePeepHoleBranch(Node& node, JITCompiler::RelationalCo
         notTaken = tmp;
     }
 
-    int32_t imm;
-    if (isJSConstantWithInt32Value(node.child1, imm)) {
-        SpeculateIntegerOperand op2(this, node.child2);
-        addBranch(m_jit.branch32(condition, JITCompiler::Imm32(imm), op2.registerID()), taken);
-    } else if (isJSConstantWithInt32Value(node.child2, imm)) {
-        SpeculateIntegerOperand op1(this, node.child1);
-        addBranch(m_jit.branch32(condition, op1.registerID(), JITCompiler::Imm32(imm)), taken);
+    if (isInt32Constant(node.child1())) {
+        int32_t imm = valueOfInt32Constant(node.child1());
+        SpeculateIntegerOperand op2(this, node.child2());
+        addBranch(m_jit.branch32(condition, JITCompiler::Imm32(imm), op2.gpr()), taken);
+    } else if (isInt32Constant(node.child2())) {
+        SpeculateIntegerOperand op1(this, node.child1());
+        int32_t imm = valueOfInt32Constant(node.child2());
+        addBranch(m_jit.branch32(condition, op1.gpr(), JITCompiler::Imm32(imm)), taken);
     } else {
-        SpeculateIntegerOperand op1(this, node.child1);
-        SpeculateIntegerOperand op2(this, node.child2);
-        addBranch(m_jit.branch32(condition, op1.registerID(), op2.registerID()), taken);
+        SpeculateIntegerOperand op1(this, node.child1());
+        SpeculateIntegerOperand op2(this, node.child2());
+        addBranch(m_jit.branch32(condition, op1.gpr(), op2.gpr()), taken);
     }
 
     // Check for fall through, otherwise we need to jump.
@@ -272,13 +384,76 @@ void SpeculativeJIT::compilePeepHoleBranch(Node& node, JITCompiler::RelationalCo
         addBranch(m_jit.jump(), notTaken);
 }
 
+void SpeculativeJIT::compilePeepHoleCall(Node& node, NodeIndex branchNodeIndex, Z_DFGOperation_EJJ operation)
+{
+    Node& branchNode = m_jit.graph()[branchNodeIndex];
+    BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
+    BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
+
+    // The branch instruction will branch to the taken block.
+    // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
+    JITCompiler::ResultCondition condition = JITCompiler::NonZero;
+    if (taken == (m_block + 1)) {
+        condition = JITCompiler::Zero;
+        BlockIndex tmp = taken;
+        taken = notTaken;
+        notTaken = tmp;
+    }
+
+    JSValueOperand op1(this, node.child1());
+    JSValueOperand op2(this, node.child2());
+    GPRReg op1GPR = op1.gpr();
+    GPRReg op2GPR = op2.gpr();
+    flushRegisters();
+
+    GPRResult result(this);
+    callOperation(operation, result.gpr(), op1GPR, op2GPR);
+    addBranch(m_jit.branchTest8(condition, result.gpr()), taken);
+
+    // Check for fall through, otherwise we need to jump.
+    if (notTaken != (m_block + 1))
+        addBranch(m_jit.jump(), notTaken);
+}
+
+// Returns true if the compare is fused with a subsequent branch.
+bool SpeculativeJIT::compare(Node& node, MacroAssembler::RelationalCondition condition, Z_DFGOperation_EJJ operation)
+{
+    // Fused compare & branch.
+    NodeIndex branchNodeIndex = detectPeepHoleBranch();
+    if (branchNodeIndex != NoNode) {
+        // detectPeepHoleBranch currently only permits the branch to be the very next node,
+        // so can be no intervening nodes to also reference the compare. 
+        ASSERT(node.adjustedRefCount() == 1);
+
+        if (shouldSpeculateInteger(node.child1(), node.child2()))
+            compilePeepHoleIntegerBranch(node, branchNodeIndex, condition);
+        else
+            compilePeepHoleCall(node, branchNodeIndex, operation);
+
+        use(node.child1());
+        use(node.child2());
+        m_compileIndex = branchNodeIndex;
+        return true;
+    }
+
+    // Normal case, not fused to branch.
+    SpeculateIntegerOperand op1(this, node.child1());
+    SpeculateIntegerOperand op2(this, node.child2());
+    GPRTemporary result(this, op1, op2);
+
+    m_jit.compare32(condition, op1.gpr(), op2.gpr(), result.gpr());
+
+    // If we add a DataFormatBool, we should use it here.
+    m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
+    jsValueResult(result.gpr(), m_compileIndex);
+    return false;
+}
+
 void SpeculativeJIT::compile(Node& node)
 {
     NodeType op = node.op;
 
     switch (op) {
-    case Int32Constant:
-    case DoubleConstant:
     case JSConstant:
         initConstantInfo(m_compileIndex);
         break;
@@ -287,7 +462,7 @@ void SpeculativeJIT::compile(Node& node)
         GPRTemporary result(this);
         PredictedType prediction = m_jit.graph().getPrediction(node.local());
         if (prediction == PredictInt32) {
-            m_jit.load32(JITCompiler::payloadFor(node.local()), result.registerID());
+            m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr());
 
             // Like integerResult, but don't useChildren - our children are phi nodes,
             // and don't represent values within this dataflow with virtual registers.
@@ -295,7 +470,7 @@ void SpeculativeJIT::compile(Node& node)
             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger);
             m_generationInfo[virtualRegister].initInteger(m_compileIndex, node.refCount(), result.gpr());
         } else {
-            m_jit.loadPtr(JITCompiler::addressFor(node.local()), result.registerID());
+            m_jit.loadPtr(JITCompiler::addressFor(node.local()), result.gpr());
 
             // Like jsValueResult, but don't useChildren - our children are phi nodes,
             // and don't represent values within this dataflow with virtual registers.
@@ -309,21 +484,23 @@ void SpeculativeJIT::compile(Node& node)
     case SetLocal: {
         switch (m_jit.graph().getPrediction(node.local())) {
         case PredictInt32: {
-            SpeculateIntegerOperand value(this, node.child1);
-            m_jit.store32(value.registerID(), JITCompiler::payloadFor(node.local()));
+            SpeculateIntegerOperand value(this, node.child1());
+            m_jit.store32(value.gpr(), JITCompiler::payloadFor(node.local()));
             noResult(m_compileIndex);
             break;
         }
         case PredictArray: {
-            SpeculateCellOperand cell(this, node.child1);
-            m_jit.storePtr(cell.registerID(), JITCompiler::addressFor(node.local()));
+            SpeculateCellOperand cell(this, node.child1());
+            GPRReg cellGPR = cell.gpr();
+            speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
+            m_jit.storePtr(cellGPR, JITCompiler::addressFor(node.local()));
             noResult(m_compileIndex);
             break;
         }
 
         default: {
-            JSValueOperand value(this, node.child1);
-            m_jit.storePtr(value.registerID(), JITCompiler::addressFor(node.local()));
+            JSValueOperand value(this, node.child1());
+            m_jit.storePtr(value.gpr(), JITCompiler::addressFor(node.local()));
             noResult(m_compileIndex);
             break;
         }
@@ -334,28 +511,28 @@ void SpeculativeJIT::compile(Node& node)
     case BitAnd:
     case BitOr:
     case BitXor:
-        if (isInt32Constant(node.child1)) {
-            SpeculateIntegerOperand op2(this, node.child2);
+        if (isInt32Constant(node.child1())) {
+            SpeculateIntegerOperand op2(this, node.child2());
             GPRTemporary result(this, op2);
 
-            bitOp(op, valueOfInt32Constant(node.child1), op2.registerID(), result.registerID());
+            bitOp(op, valueOfInt32Constant(node.child1()), op2.gpr(), result.gpr());
 
             integerResult(result.gpr(), m_compileIndex);
-        } else if (isInt32Constant(node.child2)) {
-            SpeculateIntegerOperand op1(this, node.child1);
+        } else if (isInt32Constant(node.child2())) {
+            SpeculateIntegerOperand op1(this, node.child1());
             GPRTemporary result(this, op1);
 
-            bitOp(op, valueOfInt32Constant(node.child2), op1.registerID(), result.registerID());
+            bitOp(op, valueOfInt32Constant(node.child2()), op1.gpr(), result.gpr());
 
             integerResult(result.gpr(), m_compileIndex);
         } else {
-            SpeculateIntegerOperand op1(this, node.child1);
-            SpeculateIntegerOperand op2(this, node.child2);
+            SpeculateIntegerOperand op1(this, node.child1());
+            SpeculateIntegerOperand op2(this, node.child2());
             GPRTemporary result(this, op1, op2);
 
-            MacroAssembler::RegisterID reg1 = op1.registerID();
-            MacroAssembler::RegisterID reg2 = op2.registerID();
-            bitOp(op, reg1, reg2, result.registerID());
+            GPRReg reg1 = op1.gpr();
+            GPRReg reg2 = op2.gpr();
+            bitOp(op, reg1, reg2, result.gpr());
 
             integerResult(result.gpr(), m_compileIndex);
         }
@@ -364,296 +541,297 @@ void SpeculativeJIT::compile(Node& node)
     case BitRShift:
     case BitLShift:
     case BitURShift:
-        if (isInt32Constant(node.child2)) {
-            SpeculateIntegerOperand op1(this, node.child1);
+        if (isInt32Constant(node.child2())) {
+            SpeculateIntegerOperand op1(this, node.child1());
             GPRTemporary result(this, op1);
 
-            shiftOp(op, op1.registerID(), valueOfInt32Constant(node.child2) & 0x1f, result.registerID());
+            shiftOp(op, op1.gpr(), valueOfInt32Constant(node.child2()) & 0x1f, result.gpr());
 
             integerResult(result.gpr(), m_compileIndex);
         } else {
             // Do not allow shift amount to be used as the result, MacroAssembler does not permit this.
-            SpeculateIntegerOperand op1(this, node.child1);
-            SpeculateIntegerOperand op2(this, node.child2);
+            SpeculateIntegerOperand op1(this, node.child1());
+            SpeculateIntegerOperand op2(this, node.child2());
             GPRTemporary result(this, op1);
 
-            MacroAssembler::RegisterID reg1 = op1.registerID();
-            MacroAssembler::RegisterID reg2 = op2.registerID();
-            shiftOp(op, reg1, reg2, result.registerID());
+            GPRReg reg1 = op1.gpr();
+            GPRReg reg2 = op2.gpr();
+            shiftOp(op, reg1, reg2, result.gpr());
 
             integerResult(result.gpr(), m_compileIndex);
         }
         break;
 
     case UInt32ToNumber: {
-        IntegerOperand op1(this, node.child1);
+        IntegerOperand op1(this, node.child1());
         GPRTemporary result(this, op1);
 
         // Test the operand is positive.
-        speculationCheck(m_jit.branch32(MacroAssembler::LessThan, op1.registerID(), TrustedImm32(0)));
+        speculationCheck(m_jit.branch32(MacroAssembler::LessThan, op1.gpr(), TrustedImm32(0)));
 
-        m_jit.move(op1.registerID(), result.registerID());
-        integerResult(result.gpr(), m_compileIndex, op1.format());
-        break;
-    }
-
-    case NumberToInt32: {
-        SpeculateIntegerOperand op1(this, node.child1);
-        GPRTemporary result(this, op1);
-        m_jit.move(op1.registerID(), result.registerID());
-        integerResult(result.gpr(), m_compileIndex, op1.format());
-        break;
-    }
-
-    case Int32ToNumber: {
-        SpeculateIntegerOperand op1(this, node.child1);
-        GPRTemporary result(this, op1);
-        m_jit.move(op1.registerID(), result.registerID());
+        m_jit.move(op1.gpr(), result.gpr());
         integerResult(result.gpr(), m_compileIndex, op1.format());
         break;
     }
 
     case ValueToInt32: {
-        SpeculateIntegerOperand op1(this, node.child1);
+        SpeculateIntegerOperand op1(this, node.child1());
         GPRTemporary result(this, op1);
-        m_jit.move(op1.registerID(), result.registerID());
+        m_jit.move(op1.gpr(), result.gpr());
         integerResult(result.gpr(), m_compileIndex, op1.format());
         break;
     }
 
     case ValueToNumber: {
-        SpeculateIntegerOperand op1(this, node.child1);
-        GPRTemporary result(this, op1);
-        m_jit.move(op1.registerID(), result.registerID());
-        integerResult(result.gpr(), m_compileIndex, op1.format());
+        if (isInteger(node.child1())) {
+            SpeculateIntegerOperand op1(this, node.child1());
+            GPRTemporary result(this, op1);
+            m_jit.move(op1.gpr(), result.gpr());
+            integerResult(result.gpr(), m_compileIndex, op1.format());
+            break;
+        }
+        SpeculateDoubleOperand op1(this, node.child1());
+        FPRTemporary result(this, op1);
+        m_jit.moveDouble(op1.fpr(), result.fpr());
+        doubleResult(result.fpr(), m_compileIndex);
         break;
     }
 
     case ValueAdd:
     case ArithAdd: {
-        int32_t imm1;
-        if (isDoubleConstantWithInt32Value(node.child1, imm1)) {
-            SpeculateIntegerOperand op2(this, node.child2);
-            GPRTemporary result(this);
+        if (shouldSpeculateInteger(node.child1(), node.child2())) {
+            if (isInt32Constant(node.child1())) {
+                int32_t imm1 = valueOfInt32Constant(node.child1());
+                SpeculateIntegerOperand op2(this, node.child2());
+                GPRTemporary result(this);
 
-            MacroAssembler::RegisterID reg = op2.registerID();
-            speculationCheck(m_jit.branchAdd32(MacroAssembler::Overflow, reg, Imm32(imm1), result.registerID()));
+                speculationCheck(m_jit.branchAdd32(MacroAssembler::Overflow, op2.gpr(), Imm32(imm1), result.gpr()));
 
-            integerResult(result.gpr(), m_compileIndex);
-            break;
-        }
-            
-        int32_t imm2;
-        if (isDoubleConstantWithInt32Value(node.child2, imm2)) {
-            SpeculateIntegerOperand op1(this, node.child1);
-            GPRTemporary result(this);
+                integerResult(result.gpr(), m_compileIndex);
+                break;
+            }
+                
+            if (isInt32Constant(node.child2())) {
+                SpeculateIntegerOperand op1(this, node.child1());
+                int32_t imm2 = valueOfInt32Constant(node.child2());
+                GPRTemporary result(this);
 
-            MacroAssembler::RegisterID reg = op1.registerID();
-            speculationCheck(m_jit.branchAdd32(MacroAssembler::Overflow, reg, Imm32(imm2), result.registerID()));
+                speculationCheck(m_jit.branchAdd32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
 
-            integerResult(result.gpr(), m_compileIndex);
+                integerResult(result.gpr(), m_compileIndex);
+                break;
+            }
+                
+            SpeculateIntegerOperand op1(this, node.child1());
+            SpeculateIntegerOperand op2(this, node.child2());
+            GPRTemporary result(this, op1, op2);
+
+            GPRReg gpr1 = op1.gpr();
+            GPRReg gpr2 = op2.gpr();
+            GPRReg gprResult = result.gpr();
+            MacroAssembler::Jump check = m_jit.branchAdd32(MacroAssembler::Overflow, gpr1, gpr2, gprResult);
+
+            if (gpr1 == gprResult)
+                speculationCheck(check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr2));
+            else if (gpr2 == gprResult)
+                speculationCheck(check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr1));
+            else
+                speculationCheck(check);
+
+            integerResult(gprResult, m_compileIndex);
             break;
         }
-            
-        SpeculateIntegerOperand op1(this, node.child1);
-        SpeculateIntegerOperand op2(this, node.child2);
-        GPRTemporary result(this, op1, op2);
 
-        GPRReg gpr1 = op1.gpr();
-        GPRReg gpr2 = op2.gpr();
-        GPRReg gprResult = result.gpr();
-        MacroAssembler::Jump check = m_jit.branchAdd32(MacroAssembler::Overflow, JITCompiler::gprToRegisterID(gpr1), JITCompiler::gprToRegisterID(gpr2), JITCompiler::gprToRegisterID(gprResult));
+        SpeculateDoubleOperand op1(this, node.child1());
+        SpeculateDoubleOperand op2(this, node.child2());
+        FPRTemporary result(this, op1, op2);
 
-        if (gpr1 == gprResult)
-            speculationCheck(check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr2));
-        else if (gpr2 == gprResult)
-            speculationCheck(check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr1));
-        else
-            speculationCheck(check);
+        FPRReg reg1 = op1.fpr();
+        FPRReg reg2 = op2.fpr();
+        m_jit.addDouble(reg1, reg2, result.fpr());
 
-        integerResult(gprResult, m_compileIndex);
+        doubleResult(result.fpr(), m_compileIndex);
         break;
     }
 
     case ArithSub: {
-        int32_t imm2;
-        if (isDoubleConstantWithInt32Value(node.child2, imm2)) {
-            SpeculateIntegerOperand op1(this, node.child1);
+        if (shouldSpeculateInteger(node.child1(), node.child2())) {
+            if (isInt32Constant(node.child2())) {
+                SpeculateIntegerOperand op1(this, node.child1());
+                int32_t imm2 = valueOfInt32Constant(node.child2());
+                GPRTemporary result(this);
+
+                speculationCheck(m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
+
+                integerResult(result.gpr(), m_compileIndex);
+                break;
+            }
+                
+            SpeculateIntegerOperand op1(this, node.child1());
+            SpeculateIntegerOperand op2(this, node.child2());
             GPRTemporary result(this);
 
-            MacroAssembler::RegisterID reg = op1.registerID();
-            speculationCheck(m_jit.branchSub32(MacroAssembler::Overflow, reg, Imm32(imm2), result.registerID()));
+            speculationCheck(m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), op2.gpr(), result.gpr()));
 
             integerResult(result.gpr(), m_compileIndex);
             break;
         }
-            
-        SpeculateIntegerOperand op1(this, node.child1);
-        SpeculateIntegerOperand op2(this, node.child2);
-        GPRTemporary result(this);
 
-        MacroAssembler::RegisterID reg1 = op1.registerID();
-        MacroAssembler::RegisterID reg2 = op2.registerID();
-        speculationCheck(m_jit.branchSub32(MacroAssembler::Overflow, reg1, reg2, result.registerID()));
+        SpeculateDoubleOperand op1(this, node.child1());
+        SpeculateDoubleOperand op2(this, node.child2());
+        FPRTemporary result(this, op1);
+
+        FPRReg reg1 = op1.fpr();
+        FPRReg reg2 = op2.fpr();
+        m_jit.subDouble(reg1, reg2, result.fpr());
 
-        integerResult(result.gpr(), m_compileIndex);
+        doubleResult(result.fpr(), m_compileIndex);
         break;
     }
 
     case ArithMul: {
-        SpeculateIntegerOperand op1(this, node.child1);
-        SpeculateIntegerOperand op2(this, node.child2);
-        GPRTemporary result(this);
+        if (shouldSpeculateInteger(node.child1(), node.child2())) {
+            SpeculateIntegerOperand op1(this, node.child1());
+            SpeculateIntegerOperand op2(this, node.child2());
+            GPRTemporary result(this);
+
+            GPRReg reg1 = op1.gpr();
+            GPRReg reg2 = op2.gpr();
+            speculationCheck(m_jit.branchMul32(MacroAssembler::Overflow, reg1, reg2, result.gpr()));
 
-        MacroAssembler::RegisterID reg1 = op1.registerID();
-        MacroAssembler::RegisterID reg2 = op2.registerID();
-        speculationCheck(m_jit.branchMul32(MacroAssembler::Overflow, reg1, reg2, result.registerID()));
+            MacroAssembler::Jump resultNonZero = m_jit.branchTest32(MacroAssembler::NonZero, result.gpr());
+            speculationCheck(m_jit.branch32(MacroAssembler::LessThan, reg1, TrustedImm32(0)));
+            speculationCheck(m_jit.branch32(MacroAssembler::LessThan, reg2, TrustedImm32(0)));
+            resultNonZero.link(&m_jit);
+
+            integerResult(result.gpr(), m_compileIndex);
+            break;
+        }
 
-        MacroAssembler::Jump resultNonZero = m_jit.branchTest32(MacroAssembler::NonZero, result.registerID());
-        speculationCheck(m_jit.branch32(MacroAssembler::LessThan, reg1, TrustedImm32(0)));
-        speculationCheck(m_jit.branch32(MacroAssembler::LessThan, reg2, TrustedImm32(0)));
-        resultNonZero.link(&m_jit);
+        SpeculateDoubleOperand op1(this, node.child1());
+        SpeculateDoubleOperand op2(this, node.child2());
+        FPRTemporary result(this, op1, op2);
 
-        integerResult(result.gpr(), m_compileIndex);
+        FPRReg reg1 = op1.fpr();
+        FPRReg reg2 = op2.fpr();
+        
+        m_jit.mulDouble(reg1, reg2, result.fpr());
+        
+        doubleResult(result.fpr(), m_compileIndex);
         break;
     }
 
     case ArithDiv: {
-        SpeculateIntegerOperand op1(this, node.child1);
-        SpeculateIntegerOperand op2(this, node.child2);
-        GPRTemporary result(this, op1, op2);
+        SpeculateDoubleOperand op1(this, node.child1());
+        SpeculateDoubleOperand op2(this, node.child2());
+        FPRTemporary result(this, op1);
 
-        terminateSpeculativeExecution();
+        FPRReg reg1 = op1.fpr();
+        FPRReg reg2 = op2.fpr();
+        m_jit.divDouble(reg1, reg2, result.fpr());
 
-        integerResult(result.gpr(), m_compileIndex);
+        doubleResult(result.fpr(), m_compileIndex);
         break;
     }
 
     case ArithMod: {
-        SpeculateIntegerOperand op1(this, node.child1);
-        SpeculateIntegerOperand op2(this, node.child2);
-        GPRTemporary result(this, op1, op2);
+        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();
+
+        speculationCheck(m_jit.branchTestPtr(JITCompiler::Zero, op2Gpr));
+
+        GPRReg temp2 = InvalidGPRReg;
+        if (op2Gpr == X86Registers::eax || op2Gpr == X86Registers::edx) {
+            temp2 = allocate();
+            m_jit.move(op2Gpr, temp2);
+            op2Gpr = temp2;
+        }
 
-        terminateSpeculativeExecution();
+        m_jit.move(op1Gpr, eax.gpr());
+        m_jit.assembler().cdq();
+        m_jit.assembler().idivl_r(op2Gpr);
+
+        if (temp2 != InvalidGPRReg)
+            unlock(temp2);
 
-        integerResult(result.gpr(), m_compileIndex);
+        integerResult(edx.gpr(), m_compileIndex);
         break;
     }
 
     case LogicalNot: {
-        JSValueOperand value(this, node.child1);
+        JSValueOperand value(this, node.child1());
         GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add).
 
-        m_jit.move(value.registerID(), result.registerID());
-        m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.registerID());
-        speculationCheck(m_jit.branchTestPtr(JITCompiler::NonZero, result.registerID(), TrustedImm32(static_cast<int32_t>(~1))));
-        m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueTrue)), result.registerID());
+        m_jit.move(value.gpr(), result.gpr());
+        m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.gpr());
+        speculationCheck(m_jit.branchTestPtr(JITCompiler::NonZero, result.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
+        m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueTrue)), result.gpr());
 
         // If we add a DataFormatBool, we should use it here.
         jsValueResult(result.gpr(), m_compileIndex);
         break;
     }
 
-    case CompareLess: {
-        // Fused compare & branch.
-        if (detectPeepHoleBranch()) {
-            // detectPeepHoleBranch currently only permits the branch to be the very next node,
-            // so can be no intervening nodes to also reference the compare. 
-            ASSERT(node.adjustedRefCount() == 1);
-
-            compilePeepHoleBranch(node, JITCompiler::LessThan);
-
-            use(node.child1);
-            use(node.child2);
-            ++m_compileIndex;
+    case CompareLess:
+        if (compare(node, JITCompiler::LessThan, operationCompareLess))
             return;
-        }
-
-        // Normal case, not fused to branch.
-        SpeculateIntegerOperand op1(this, node.child1);
-        SpeculateIntegerOperand op2(this, node.child2);
-        GPRTemporary result(this, op1, op2);
-
-        m_jit.compare32(JITCompiler::LessThan, op1.registerID(), op2.registerID(), result.registerID());
-
-        // If we add a DataFormatBool, we should use it here.
-        m_jit.or32(TrustedImm32(ValueFalse), result.registerID());
-        jsValueResult(result.gpr(), m_compileIndex);
         break;
-    }
-
-    case CompareLessEq: {
-        // Fused compare & branch.
-        if (detectPeepHoleBranch()) {
-            // detectPeepHoleBranch currently only permits the branch to be the very next node,
-            // so can be no intervening nodes to also reference the compare. 
-            ASSERT(node.adjustedRefCount() == 1);
 
-            compilePeepHoleBranch(node, JITCompiler::LessThanOrEqual);
-
-            use(node.child1);
-            use(node.child2);
-            ++m_compileIndex;
+    case CompareLessEq:
+        if (compare(node, JITCompiler::LessThanOrEqual, operationCompareLessEq))
             return;
-        }
-
-        // Normal case, not fused to branch.
-        SpeculateIntegerOperand op1(this, node.child1);
-        SpeculateIntegerOperand op2(this, node.child2);
-        GPRTemporary result(this, op1, op2);
-
-        m_jit.compare32(JITCompiler::LessThanOrEqual, op1.registerID(), op2.registerID(), result.registerID());
-
-        // If we add a DataFormatBool, we should use it here.
-        m_jit.or32(TrustedImm32(ValueFalse), result.registerID());
-        jsValueResult(result.gpr(), m_compileIndex);
         break;
-    }
 
-    case CompareEq: {
-        SpeculateIntegerOperand op1(this, node.child1);
-        SpeculateIntegerOperand op2(this, node.child2);
-        GPRTemporary result(this, op1, op2);
+    case CompareGreater:
+        if (compare(node, JITCompiler::GreaterThan, operationCompareGreater))
+            return;
+        break;
 
-        m_jit.compare32(JITCompiler::Equal, op1.registerID(), op2.registerID(), result.registerID());
+    case CompareGreaterEq:
+        if (compare(node, JITCompiler::GreaterThanOrEqual, operationCompareGreaterEq))
+            return;
+        break;
 
-        // If we add a DataFormatBool, we should use it here.
-        m_jit.or32(TrustedImm32(ValueFalse), result.registerID());
-        jsValueResult(result.gpr(), m_compileIndex);
+    case CompareEq:
+        if (compare(node, JITCompiler::Equal, operationCompareEq))
+            return;
         break;
-    }
 
     case CompareStrictEq: {
-        SpeculateIntegerOperand op1(this, node.child1);
-        SpeculateIntegerOperand op2(this, node.child2);
+        SpeculateIntegerOperand op1(this, node.child1());
+        SpeculateIntegerOperand op2(this, node.child2());
         GPRTemporary result(this, op1, op2);
 
-        m_jit.compare32(JITCompiler::Equal, op1.registerID(), op2.registerID(), result.registerID());
+        m_jit.compare32(JITCompiler::Equal, op1.gpr(), op2.gpr(), result.gpr());
 
         // If we add a DataFormatBool, we should use it here.
-        m_jit.or32(TrustedImm32(ValueFalse), result.registerID());
+        m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
         jsValueResult(result.gpr(), m_compileIndex);
         break;
     }
 
     case GetByVal: {
-        NodeIndex alias = node.child3;
+        NodeIndex alias = node.child3();
         if (alias != NoNode) {
             // FIXME: result should be able to reuse child1, child2. Should have an 'UnusedOperand' type.
-            JSValueOperand aliasedValue(this, node.child3);
+            JSValueOperand aliasedValue(this, node.child3());
             GPRTemporary result(this, aliasedValue);
-            m_jit.move(aliasedValue.registerID(), result.registerID());
+            m_jit.move(aliasedValue.gpr(), result.gpr());
             jsValueResult(result.gpr(), m_compileIndex);
             break;
         }
 
-        SpeculateCellOperand base(this, node.child1);
-        SpeculateStrictInt32Operand property(this, node.child2);
+        SpeculateCellOperand base(this, node.child1());
+        SpeculateStrictInt32Operand property(this, node.child2());
         GPRTemporary storage(this);
 
-        MacroAssembler::RegisterID baseReg = base.registerID();
-        MacroAssembler::RegisterID propertyReg = property.registerID();
-        MacroAssembler::RegisterID storageReg = storage.registerID();
+        GPRReg baseReg = base.gpr();
+        GPRReg propertyReg = property.gpr();
+        GPRReg storageReg = storage.gpr();
 
         // Get the array storage. We haven't yet checked this is a JSArray, so this is only safe if
         // an access with offset JSArray::storageOffset() is valid for all JSCells!
@@ -661,7 +839,7 @@ void SpeculativeJIT::compile(Node& node)
 
         // Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
         // If we have predicted the base to be type array, we can skip the check.
-        Node& baseNode = m_jit.graph()[node.child1];
+        Node& baseNode = m_jit.graph()[node.child1()];
         if (baseNode.op != GetLocal || m_jit.graph().getPrediction(baseNode.local()) != PredictArray)
             speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
         speculationCheck(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset())));
@@ -670,33 +848,49 @@ void SpeculativeJIT::compile(Node& node)
         // the storage pointer - especially if there happens to be another register free right now. If we do so,
         // then we'll need to allocate a new temporary for result.
         GPRTemporary& result = storage;
-        m_jit.loadPtr(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), result.registerID());
-        speculationCheck(m_jit.branchTestPtr(MacroAssembler::Zero, result.registerID()));
+        m_jit.loadPtr(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), result.gpr());
+        speculationCheck(m_jit.branchTestPtr(MacroAssembler::Zero, result.gpr()));
 
         jsValueResult(result.gpr(), m_compileIndex);
         break;
     }
 
     case PutByVal: {
-        SpeculateCellOperand base(this, node.child1);
-        SpeculateStrictInt32Operand property(this, node.child2);
-        JSValueOperand value(this, node.child3);
-        GPRTemporary storage(this);
+        SpeculateCellOperand base(this, node.child1());
+        SpeculateStrictInt32Operand property(this, node.child2());
+        JSValueOperand value(this, node.child3());
+        GPRTemporary scratch(this);
+
+        // Map base, property & value into registers, allocate a scratch register.
+        GPRReg baseReg = base.gpr();
+        GPRReg propertyReg = property.gpr();
+        GPRReg valueReg = value.gpr();
+        GPRReg scratchReg = scratch.gpr();
+        
+        if (!m_compileOkay)
+            return;
 
-        // Map base, property & value into registers, allocate a register for storage.
-        MacroAssembler::RegisterID baseReg = base.registerID();
-        MacroAssembler::RegisterID propertyReg = property.registerID();
-        MacroAssembler::RegisterID valueReg = value.registerID();
-        MacroAssembler::RegisterID storageReg = storage.registerID();
+        writeBarrier(m_jit, baseReg, scratchReg);
 
         // Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
         // If we have predicted the base to be type array, we can skip the check.
-        Node& baseNode = m_jit.graph()[node.child1];
+        Node& baseNode = m_jit.graph()[node.child1()];
         if (baseNode.op != GetLocal || m_jit.graph().getPrediction(baseNode.local()) != PredictArray)
             speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
-        speculationCheck(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset())));
+        MacroAssembler::Jump withinArrayBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset()));
+
+        // Code to handle put beyond array bounds.
+        silentSpillAllRegisters(scratchReg, baseReg, propertyReg, valueReg);
+        setupStubArguments(baseReg, propertyReg, valueReg);
+        m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+        JITCompiler::Call functionCall = appendCallWithExceptionCheck(operationPutByValBeyondArrayBounds);
+        silentFillAllRegisters(scratchReg);
+        JITCompiler::Jump wasBeyondArrayBounds = m_jit.jump();
+
+        withinArrayBounds.link(&m_jit);
 
         // Get the array storage.
+        GPRReg storageReg = scratchReg;
         m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
 
         // Check if we're writing to a hole; if so increment m_numValuesInVector.
@@ -715,25 +909,30 @@ void SpeculativeJIT::compile(Node& node)
         // Store the value to the array.
         m_jit.storePtr(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
 
+        wasBeyondArrayBounds.link(&m_jit);
+
         noResult(m_compileIndex);
         break;
     }
 
     case PutByValAlias: {
-        SpeculateCellOperand base(this, node.child1);
-        SpeculateStrictInt32Operand property(this, node.child2);
-        JSValueOperand value(this, node.child3);
-        GPRTemporary storage(this, base); // storage may overwrite base.
+        SpeculateCellOperand base(this, node.child1());
+        SpeculateStrictInt32Operand property(this, node.child2());
+        JSValueOperand value(this, node.child3());
+        GPRTemporary scratch(this);
+        
+        GPRReg baseReg = base.gpr();
+        GPRReg scratchReg = scratch.gpr();
 
-        // Get the array storage.
-        MacroAssembler::RegisterID storageReg = storage.registerID();
-        m_jit.loadPtr(MacroAssembler::Address(base.registerID(), JSArray::storageOffset()), storageReg);
+        writeBarrier(m_jit, baseReg, scratchReg);
 
-        // Map property & value into registers.
-        MacroAssembler::RegisterID propertyReg = property.registerID();
-        MacroAssembler::RegisterID valueReg = value.registerID();
+        // Get the array storage.
+        GPRReg storageReg = scratchReg;
+        m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
 
         // Store the value to the array.
+        GPRReg propertyReg = property.gpr();
+        GPRReg valueReg = value.gpr();
         m_jit.storePtr(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
 
         noResult(m_compileIndex);
@@ -749,15 +948,15 @@ void SpeculativeJIT::compile(Node& node)
     }
 
     case Branch: {
-        JSValueOperand value(this, node.child1);
-        MacroAssembler::RegisterID valueReg = value.registerID();
+        JSValueOperand value(this, node.child1());
+        GPRReg valueReg = value.gpr();
 
         BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());
         BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(node.notTakenBytecodeOffset());
 
         // Integers
         addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueReg, MacroAssembler::ImmPtr(JSValue::encode(jsNumber(0)))), notTaken);
-        MacroAssembler::Jump isNonZeroInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, valueReg, JITCompiler::tagTypeNumberRegister);
+        MacroAssembler::Jump isNonZeroInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, valueReg, GPRInfo::tagTypeNumberRegister);
 
         // Booleans
         addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueReg, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(false)))), notTaken);
@@ -775,25 +974,25 @@ void SpeculativeJIT::compile(Node& node)
     }
 
     case Return: {
-        ASSERT(JITCompiler::callFrameRegister != JITCompiler::regT1);
-        ASSERT(JITCompiler::regT1 != JITCompiler::returnValueRegister);
-        ASSERT(JITCompiler::returnValueRegister != JITCompiler::callFrameRegister);
+        ASSERT(GPRInfo::callFrameRegister != GPRInfo::regT1);
+        ASSERT(GPRInfo::regT1 != GPRInfo::returnValueGPR);
+        ASSERT(GPRInfo::returnValueGPR != GPRInfo::callFrameRegister);
 
 #if DFG_SUCCESS_STATS
         static SamplingCounter counter("SpeculativeJIT");
         m_jit.emitCount(counter);
 #endif
 
-        // Return the result in returnValueRegister.
-        JSValueOperand op1(this, node.child1);
-        m_jit.move(op1.registerID(), JITCompiler::returnValueRegister);
+        // Return the result in returnValueGPR.
+        JSValueOperand op1(this, node.child1());
+        m_jit.move(op1.gpr(), GPRInfo::returnValueGPR);
 
         // Grab the return address.
-        m_jit.emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, JITCompiler::regT1);
+        m_jit.emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, GPRInfo::regT1);
         // Restore our caller's "r".
-        m_jit.emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, JITCompiler::callFrameRegister);
+        m_jit.emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, GPRInfo::callFrameRegister);
         // Return.
-        m_jit.restoreReturnAddressBeforeReturn(JITCompiler::regT1);
+        m_jit.restoreReturnAddressBeforeReturn(GPRInfo::regT1);
         m_jit.ret();
         
         noResult(m_compileIndex);
@@ -801,47 +1000,58 @@ void SpeculativeJIT::compile(Node& node)
     }
 
     case ConvertThis: {
-        SpeculateCellOperand thisValue(this, node.child1);
+        SpeculateCellOperand thisValue(this, node.child1());
         GPRTemporary temp(this);
 
-        m_jit.loadPtr(JITCompiler::Address(thisValue.registerID(), JSCell::structureOffset()), temp.registerID());
-        speculationCheck(m_jit.branchTest8(JITCompiler::NonZero, JITCompiler::Address(temp.registerID(), Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(NeedsThisConversion)));
+        m_jit.loadPtr(JITCompiler::Address(thisValue.gpr(), JSCell::structureOffset()), temp.gpr());
+        speculationCheck(m_jit.branchTest8(JITCompiler::NonZero, JITCompiler::Address(temp.gpr(), Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(NeedsThisConversion)));
 
         cellResult(thisValue.gpr(), m_compileIndex);
         break;
     }
 
     case GetById: {
-        JSValueOperand base(this, node.child1);
-        GPRReg baseGPR = base.gpr();
-        flushRegisters();
+        SpeculateCellOperand base(this, node.child1());
+        GPRTemporary result(this, base);
 
-        GPRResult result(this);
-        callOperation(operationGetById, result.gpr(), baseGPR, identifier(node.identifierNumber()));
-        jsValueResult(result.gpr(), m_compileIndex);
+        GPRReg resultGPR = result.gpr();
+
+        cachedGetById(base.gpr(), resultGPR, node.identifierNumber());
+
+        jsValueResult(resultGPR, m_compileIndex);
+        break;
+    }
+        
+    case GetMethod: {
+        SpeculateCellOperand base(this, node.child1());
+        GPRTemporary result(this, base);
+
+        GPRReg resultGPR = result.gpr();
+
+        cachedGetMethod(base.gpr(), resultGPR, node.identifierNumber());
+
+        jsValueResult(resultGPR, m_compileIndex);
         break;
     }
 
     case PutById: {
-        JSValueOperand base(this, node.child1);
-        JSValueOperand value(this, node.child2);
-        GPRReg valueGPR = value.gpr();
-        GPRReg baseGPR = base.gpr();
-        flushRegisters();
+        SpeculateCellOperand base(this, node.child1());
+        JSValueOperand value(this, node.child2());
+        GPRTemporary scratch(this);
 
-        callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByIdStrict : operationPutByIdNonStrict, valueGPR, baseGPR, identifier(node.identifierNumber()));
+        cachedPutById(base.gpr(), value.gpr(), scratch.gpr(), node.identifierNumber(), NotDirect);
+        
         noResult(m_compileIndex);
         break;
     }
 
     case PutByIdDirect: {
-        JSValueOperand base(this, node.child1);
-        JSValueOperand value(this, node.child2);
-        GPRReg valueGPR = value.gpr();
-        GPRReg baseGPR = base.gpr();
-        flushRegisters();
+        SpeculateCellOperand base(this, node.child1());
+        JSValueOperand value(this, node.child2());
+        GPRTemporary scratch(this);
+
+        cachedPutById(base.gpr(), value.gpr(), scratch.gpr(), node.identifierNumber(), Direct);
 
-        callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByIdDirectStrict : operationPutByIdDirectNonStrict, valueGPR, baseGPR, identifier(node.identifierNumber()));
         noResult(m_compileIndex);
         break;
     }
@@ -850,27 +1060,95 @@ void SpeculativeJIT::compile(Node& node)
         GPRTemporary result(this);
 
         JSVariableObject* globalObject = m_jit.codeBlock()->globalObject();
-        m_jit.loadPtr(globalObject->addressOfRegisters(), result.registerID());
-        m_jit.loadPtr(JITCompiler::addressForGlobalVar(result.registerID(), node.varNumber()), result.registerID());
+        m_jit.loadPtr(globalObject->addressOfRegisters(), result.gpr());
+        m_jit.loadPtr(JITCompiler::addressForGlobalVar(result.gpr(), node.varNumber()), result.gpr());
 
         jsValueResult(result.gpr(), m_compileIndex);
         break;
     }
 
     case PutGlobalVar: {
-        JSValueOperand value(this, node.child1);
-        GPRTemporary temp(this);
+        JSValueOperand value(this, node.child1());
+        GPRTemporary globalObject(this);
+        GPRTemporary scratch(this);
+        
+        GPRReg globalObjectReg = globalObject.gpr();
+        GPRReg scratchReg = scratch.gpr();
 
-        JSVariableObject* globalObject = m_jit.codeBlock()->globalObject();
-        m_jit.loadPtr(globalObject->addressOfRegisters(), temp.registerID());
-        m_jit.storePtr(value.registerID(), JITCompiler::addressForGlobalVar(temp.registerID(), node.varNumber()));
+        m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.codeBlock()->globalObject()), globalObjectReg);
+
+        writeBarrier(m_jit, globalObjectReg, scratchReg);
+
+        m_jit.loadPtr(MacroAssembler::Address(globalObjectReg, JSVariableObject::offsetOfRegisters()), scratchReg);
+        m_jit.storePtr(value.gpr(), JITCompiler::addressForGlobalVar(scratchReg, node.varNumber()));
+
+        noResult(m_compileIndex);
+        break;
+    }
+
+    case CheckHasInstance: {
+        SpeculateCellOperand base(this, node.child1());
+        GPRTemporary structure(this);
+
+        // Speculate that base 'ImplementsDefaultHasInstance'.
+        m_jit.loadPtr(MacroAssembler::Address(base.gpr(), JSCell::structureOffset()), structure.gpr());
+        speculationCheck(m_jit.branchTest8(MacroAssembler::Zero, MacroAssembler::Address(structure.gpr(), Structure::typeInfoFlagsOffset()), MacroAssembler::TrustedImm32(ImplementsDefaultHasInstance)));
 
         noResult(m_compileIndex);
         break;
     }
 
+    case InstanceOf: {
+        SpeculateCellOperand value(this, node.child1());
+        // Base unused since we speculate default InstanceOf behaviour in CheckHasInstance.
+        SpeculateCellOperand prototype(this, node.child3());
+
+        GPRTemporary scratch(this);
+
+        GPRReg valueReg = value.gpr();
+        GPRReg prototypeReg = prototype.gpr();
+        GPRReg scratchReg = scratch.gpr();
+
+        // Check that prototype is an object.
+        m_jit.loadPtr(MacroAssembler::Address(prototypeReg, JSCell::structureOffset()), scratchReg);
+        speculationCheck(m_jit.branch8(MacroAssembler::NotEqual, MacroAssembler::Address(scratchReg, Structure::typeInfoTypeOffset()), MacroAssembler::TrustedImm32(ObjectType)));
+
+        // Initialize scratchReg with the value being checked.
+        m_jit.move(valueReg, scratchReg);
+
+        // Walk up the prototype chain of the value (in scratchReg), comparing to prototypeReg.
+        MacroAssembler::Label loop(&m_jit);
+        m_jit.loadPtr(MacroAssembler::Address(scratchReg, JSCell::structureOffset()), scratchReg);
+        m_jit.loadPtr(MacroAssembler::Address(scratchReg, Structure::prototypeOffset()), scratchReg);
+        MacroAssembler::Jump isInstance = m_jit.branchPtr(MacroAssembler::Equal, scratchReg, prototypeReg);
+        m_jit.branchTestPtr(MacroAssembler::Zero, scratchReg, GPRInfo::tagMaskRegister).linkTo(loop, &m_jit);
+
+        // No match - result is false.
+        m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(false))), scratchReg);
+        MacroAssembler::Jump putResult = m_jit.jump();
+
+        isInstance.link(&m_jit);
+        m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(true))), scratchReg);
+
+        putResult.link(&m_jit);
+        jsValueResult(scratchReg, m_compileIndex);
+        break;
+    }
+
     case Phi:
         ASSERT_NOT_REACHED();
+
+    case Breakpoint:
+#if ENABLE(DEBUG_WITH_BREAKPOINT)
+        m_jit.breakpoint();
+#else
+        ASSERT_NOT_REACHED();
+#endif
+        break;
+        
+    case Call:
+        emitCall(node);
+        break;
     }
 
     if (node.hasResult() && node.mustGenerate())
@@ -911,17 +1189,16 @@ void SpeculativeJIT::checkArgumentTypes()
     ASSERT(!m_compileIndex);
     for (int i = 0; i < m_jit.codeBlock()->m_numParameters; ++i) {
         VirtualRegister virtualRegister = (VirtualRegister)(m_jit.codeBlock()->thisRegister() + i);
-        if (m_jit.graph().getPrediction(virtualRegister) == PredictInt32)
         switch (m_jit.graph().getPrediction(virtualRegister)) {
         case PredictInt32:
-            speculationCheck(m_jit.branchPtr(MacroAssembler::Below, JITCompiler::addressFor(virtualRegister), JITCompiler::tagTypeNumberRegister));
+            speculationCheck(m_jit.branchPtr(MacroAssembler::Below, JITCompiler::addressFor(virtualRegister), GPRInfo::tagTypeNumberRegister));
             break;
 
         case PredictArray: {
             GPRTemporary temp(this);
-            m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.registerID());
-            speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, temp.registerID(), JITCompiler::tagMaskRegister));
-            speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.registerID()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
+            m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
+            speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
+            speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
             break;
         }
 
@@ -940,7 +1217,7 @@ void SpeculativeJIT::initializeVariableTypes()
     ASSERT(!m_compileIndex);
     for (int var = 0; var < m_jit.codeBlock()->m_numVars; ++var) {
         if (m_jit.graph().getPrediction(var) == PredictInt32)
-            m_jit.storePtr(JITCompiler::tagTypeNumberRegister, JITCompiler::addressFor((VirtualRegister)var));
+            m_jit.storePtr(GPRInfo::tagTypeNumberRegister, JITCompiler::addressFor((VirtualRegister)var));
     }
 }