PredictedType should be called SpeculatedType
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGSpeculativeJIT.cpp
index fa19cd4..da4dfd4 100644 (file)
 
 #if ENABLE(DFG_JIT)
 
-#include "JSByteArray.h"
+#include "Arguments.h"
+#include "DFGSlowPathGenerator.h"
 #include "LinkBuffer.h"
 
 namespace JSC { namespace DFG {
 
+SpeculativeJIT::SpeculativeJIT(JITCompiler& jit)
+    : m_compileOkay(true)
+    , m_jit(jit)
+    , m_compileIndex(0)
+    , m_indexInBlock(0)
+    , m_generationInfo(m_jit.codeBlock()->m_numCalleeRegisters)
+    , m_blockHeads(jit.graph().m_blocks.size())
+    , m_arguments(jit.codeBlock()->numParameters())
+    , m_variables(jit.graph().m_localVars)
+    , m_lastSetOperand(std::numeric_limits<int>::max())
+    , m_state(m_jit.graph())
+    , m_isCheckingArgumentTypes(false)
+{
+}
+
+SpeculativeJIT::~SpeculativeJIT()
+{
+    WTF::deleteAllValues(m_slowPathGenerators);
+}
+
+void SpeculativeJIT::addSlowPathGenerator(PassOwnPtr<SlowPathGenerator> slowPathGenerator)
+{
+    m_slowPathGenerators.append(slowPathGenerator.leakPtr());
+}
+
+void SpeculativeJIT::runSlowPathGenerators()
+{
+#if DFG_ENABLE(DEBUG_VERBOSE)
+    dataLog("Running %lu slow path generators.\n", m_slowPathGenerators.size());
+#endif
+    for (unsigned i = 0; i < m_slowPathGenerators.size(); ++i)
+        m_slowPathGenerators[i]->generate(this);
+}
+
 // On Windows we need to wrap fmod; on other platforms we can call it directly.
 // On ARMv7 we assert that all function pointers have to low bit set (point to thumb code).
 #if CALLING_CONVENTION_IS_STDCALL || CPU(ARM_THUMB2)
@@ -60,12 +95,16 @@ GPRReg SpeculativeJIT::fillStorage(NodeIndex nodeIndex)
     
     switch (info.registerFormat()) {
     case DataFormatNone: {
-        GPRReg gpr = allocate();
-        ASSERT(info.spillFormat() == DataFormatStorage);
-        m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
-        m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
-        info.fillStorage(gpr);
-        return gpr;
+        if (info.spillFormat() == DataFormatStorage) {
+            GPRReg gpr = allocate();
+            m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
+            m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
+            info.fillStorage(gpr);
+            return gpr;
+        }
+        
+        // Must be a cell; fill it as a cell and then return the pointer.
+        return fillSpeculateCell(nodeIndex);
     }
         
     case DataFormatStorage: {
@@ -75,34 +114,32 @@ GPRReg SpeculativeJIT::fillStorage(NodeIndex nodeIndex)
     }
         
     default:
-        ASSERT_NOT_REACHED();
+        return fillSpeculateCell(nodeIndex);
     }
-    
-    return InvalidGPRReg;
 }
 
 void SpeculativeJIT::useChildren(Node& node)
 {
-    if (node.op & NodeHasVarArgs) {
+    if (node.flags() & NodeHasVarArgs) {
         for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++)
             use(m_jit.graph().m_varArgChildren[childIdx]);
     } else {
-        NodeIndex child1 = node.child1();
-        if (child1 == NoNode) {
-            ASSERT(node.child2() == NoNode && node.child3() == NoNode);
+        Edge child1 = node.child1();
+        if (!child1) {
+            ASSERT(!node.child2() && !node.child3());
             return;
         }
         use(child1);
         
-        NodeIndex child2 = node.child2();
-        if (child2 == NoNode) {
-            ASSERT(node.child3() == NoNode);
+        Edge child2 = node.child2();
+        if (!child2) {
+            ASSERT(!node.child3());
             return;
         }
         use(child2);
         
-        NodeIndex child3 = node.child3();
-        if (child3 == NoNode)
+        Edge child3 = node.child3();
+        if (!child3)
             return;
         use(child3);
     }
@@ -184,21 +221,6 @@ bool SpeculativeJIT::isKnownNotNumber(NodeIndex nodeIndex)
         || (node.hasConstant() && !isNumberConstant(nodeIndex));
 }
 
-bool SpeculativeJIT::isKnownBoolean(NodeIndex nodeIndex)
-{
-    Node& node = m_jit.graph()[nodeIndex];
-    if (node.hasBooleanResult())
-        return true;
-    
-    if (isBooleanConstant(nodeIndex))
-        return true;
-    
-    VirtualRegister virtualRegister = node.virtualRegister();
-    GenerationInfo& info = m_generationInfo[virtualRegister];
-    
-    return info.isJSBoolean();
-}
-
 void SpeculativeJIT::writeBarrier(MacroAssembler& jit, GPRReg owner, GPRReg scratch1, GPRReg scratch2, WriteBarrierUseKind useKind)
 {
     UNUSED_PARAM(jit);
@@ -239,7 +261,7 @@ void SpeculativeJIT::markCellCard(MacroAssembler& jit, GPRReg owner, GPRReg scra
 #endif
 }
 
-void SpeculativeJIT::writeBarrier(GPRReg ownerGPR, GPRReg valueGPR, NodeIndex valueIndex, WriteBarrierUseKind useKind, GPRReg scratch1, GPRReg scratch2)
+void SpeculativeJIT::writeBarrier(GPRReg ownerGPR, GPRReg valueGPR, Edge valueUse, WriteBarrierUseKind useKind, GPRReg scratch1, GPRReg scratch2)
 {
     UNUSED_PARAM(ownerGPR);
     UNUSED_PARAM(valueGPR);
@@ -247,7 +269,7 @@ void SpeculativeJIT::writeBarrier(GPRReg ownerGPR, GPRReg valueGPR, NodeIndex va
     UNUSED_PARAM(scratch2);
     UNUSED_PARAM(useKind);
 
-    if (isKnownNotCell(valueIndex))
+    if (isKnownNotCell(valueUse.index()))
         return;
 
 #if ENABLE(WRITE_BARRIER_PROFILING)
@@ -270,7 +292,7 @@ void SpeculativeJIT::writeBarrier(GPRReg ownerGPR, GPRReg valueGPR, NodeIndex va
     
     JITCompiler::Jump rhsNotCell;
     bool hadCellCheck = false;
-    if (!isKnownCell(valueIndex) && !isCellPrediction(m_jit.getPrediction(valueIndex))) {
+    if (!isKnownCell(valueUse.index()) && !isCellSpeculation(m_jit.getSpeculation(valueUse.index()))) {
         hadCellCheck = true;
         rhsNotCell = m_jit.branchIfNotCell(valueGPR);
     }
@@ -315,14 +337,14 @@ void SpeculativeJIT::writeBarrier(GPRReg ownerGPR, JSCell* value, WriteBarrierUs
 #endif
 }
 
-void SpeculativeJIT::writeBarrier(JSCell* owner, GPRReg valueGPR, NodeIndex valueIndex, WriteBarrierUseKind useKind, GPRReg scratch)
+void SpeculativeJIT::writeBarrier(JSCell* owner, GPRReg valueGPR, Edge valueUse, WriteBarrierUseKind useKind, GPRReg scratch)
 {
     UNUSED_PARAM(owner);
     UNUSED_PARAM(valueGPR);
     UNUSED_PARAM(scratch);
     UNUSED_PARAM(useKind);
 
-    if (isKnownNotCell(valueIndex))
+    if (isKnownNotCell(valueUse.index()))
         return;
 
 #if ENABLE(WRITE_BARRIER_PROFILING)
@@ -332,7 +354,7 @@ void SpeculativeJIT::writeBarrier(JSCell* owner, GPRReg valueGPR, NodeIndex valu
 #if ENABLE(GGC)
     JITCompiler::Jump rhsNotCell;
     bool hadCellCheck = false;
-    if (!isKnownCell(valueIndex) && !isCellPrediction(m_jit.getPrediction(valueIndex))) {
+    if (!isKnownCell(valueUse.index()) && !isCellSpeculation(m_jit.getSpeculation(valueUse.index()))) {
         hadCellCheck = true;
         rhsNotCell = m_jit.branchIfNotCell(valueGPR);
     }
@@ -355,12 +377,15 @@ void SpeculativeJIT::writeBarrier(JSCell* owner, GPRReg valueGPR, NodeIndex valu
 
 bool SpeculativeJIT::nonSpeculativeCompare(Node& node, MacroAssembler::RelationalCondition cond, S_DFGOperation_EJJ helperFunction)
 {
-    NodeIndex branchNodeIndex = detectPeepHoleBranch();
-    if (branchNodeIndex != NoNode) {
+    unsigned branchIndexInBlock = detectPeepHoleBranch();
+    if (branchIndexInBlock != UINT_MAX) {
+        NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
+
         ASSERT(node.adjustedRefCount() == 1);
         
         nonSpeculativePeepholeBranch(node, branchNodeIndex, cond, helperFunction);
     
+        m_indexInBlock = branchIndexInBlock;
         m_compileIndex = branchNodeIndex;
         
         return true;
@@ -373,15 +398,15 @@ bool SpeculativeJIT::nonSpeculativeCompare(Node& node, MacroAssembler::Relationa
 
 bool SpeculativeJIT::nonSpeculativeStrictEq(Node& node, bool invert)
 {
-    if (!invert && (isKnownNumeric(node.child1()) || isKnownNumeric(node.child2())))
-        return nonSpeculativeCompare(node, MacroAssembler::Equal, operationCompareStrictEq);
-    
-    NodeIndex branchNodeIndex = detectPeepHoleBranch();
-    if (branchNodeIndex != NoNode) {
+    unsigned branchIndexInBlock = detectPeepHoleBranch();
+    if (branchIndexInBlock != UINT_MAX) {
+        NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
+
         ASSERT(node.adjustedRefCount() == 1);
         
         nonSpeculativePeepholeStrictEq(node, branchNodeIndex, invert);
     
+        m_indexInBlock = branchIndexInBlock;
         m_compileIndex = branchNodeIndex;
         
         return true;
@@ -420,33 +445,33 @@ static const char* dataFormatString(DataFormat format)
 void SpeculativeJIT::dump(const char* label)
 {
     if (label)
-        fprintf(stderr, "<%s>\n", label);
+        dataLog("<%s>\n", label);
 
-    fprintf(stderr, "  gprs:\n");
+    dataLog("  gprs:\n");
     m_gprs.dump();
-    fprintf(stderr, "  fprs:\n");
+    dataLog("  fprs:\n");
     m_fprs.dump();
-    fprintf(stderr, "  VirtualRegisters:\n");
+    dataLog("  VirtualRegisters:\n");
     for (unsigned i = 0; i < m_generationInfo.size(); ++i) {
         GenerationInfo& info = m_generationInfo[i];
         if (info.alive())
-            fprintf(stderr, "    % 3d:%s%s", i, dataFormatString(info.registerFormat()), dataFormatString(info.spillFormat()));
+            dataLog("    % 3d:%s%s", i, dataFormatString(info.registerFormat()), dataFormatString(info.spillFormat()));
         else
-            fprintf(stderr, "    % 3d:[__][__]", i);
+            dataLog("    % 3d:[__][__]", i);
         if (info.registerFormat() == DataFormatDouble)
-            fprintf(stderr, ":fpr%d\n", info.fpr());
+            dataLog(":fpr%d\n", info.fpr());
         else if (info.registerFormat() != DataFormatNone
 #if USE(JSVALUE32_64)
             && !(info.registerFormat() & DataFormatJS)
 #endif
             ) {
             ASSERT(info.gpr() != InvalidGPRReg);
-            fprintf(stderr, ":%s\n", GPRInfo::debugName(info.gpr()));
+            dataLog(":%s\n", GPRInfo::debugName(info.gpr()));
         } else
-            fprintf(stderr, "\n");
+            dataLog("\n");
     }
     if (label)
-        fprintf(stderr, "</%s>\n", label);
+        dataLog("</%s>\n", label);
 }
 #endif
 
@@ -458,13 +483,13 @@ void SpeculativeJIT::checkConsistency()
 
     for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
         if (iter.isLocked()) {
-            fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: gpr %s is locked.\n", iter.debugName());
+            dataLog("DFG_CONSISTENCY_CHECK failed: gpr %s is locked.\n", iter.debugName());
             failed = true;
         }
     }
     for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
         if (iter.isLocked()) {
-            fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: fpr %s is locked.\n", iter.debugName());
+            dataLog("DFG_CONSISTENCY_CHECK failed: fpr %s is locked.\n", iter.debugName());
             failed = true;
         }
     }
@@ -492,7 +517,7 @@ void SpeculativeJIT::checkConsistency()
             GPRReg gpr = info.gpr();
             ASSERT(gpr != InvalidGPRReg);
             if (m_gprs.name(gpr) != virtualRegister) {
-                fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for virtual register %d (gpr %s).\n", virtualRegister, GPRInfo::debugName(gpr));
+                dataLog("DFG_CONSISTENCY_CHECK failed: name mismatch for virtual register %d (gpr %s).\n", virtualRegister, GPRInfo::debugName(gpr));
                 failed = true;
             }
             break;
@@ -501,7 +526,7 @@ void SpeculativeJIT::checkConsistency()
             FPRReg fpr = info.fpr();
             ASSERT(fpr != InvalidFPRReg);
             if (m_fprs.name(fpr) != virtualRegister) {
-                fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for virtual register %d (fpr %s).\n", virtualRegister, FPRInfo::debugName(fpr));
+                dataLog("DFG_CONSISTENCY_CHECK failed: name mismatch for virtual register %d (fpr %s).\n", virtualRegister, FPRInfo::debugName(fpr));
                 failed = true;
             }
             break;
@@ -517,18 +542,18 @@ void SpeculativeJIT::checkConsistency()
         GenerationInfo& info = m_generationInfo[virtualRegister];
 #if USE(JSVALUE64)
         if (iter.regID() != info.gpr()) {
-            fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for gpr %s (virtual register %d).\n", iter.debugName(), virtualRegister);
+            dataLog("DFG_CONSISTENCY_CHECK failed: name mismatch for gpr %s (virtual register %d).\n", iter.debugName(), virtualRegister);
             failed = true;
         }
 #else
         if (!(info.registerFormat() & DataFormatJS)) {
             if (iter.regID() != info.gpr()) {
-                fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for gpr %s (virtual register %d).\n", iter.debugName(), virtualRegister);
+                dataLog("DFG_CONSISTENCY_CHECK failed: name mismatch for gpr %s (virtual register %d).\n", iter.debugName(), virtualRegister);
                 failed = true;
             }
         } else {
             if (iter.regID() != info.tagGPR() && iter.regID() != info.payloadGPR()) {
-                fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for gpr %s (virtual register %d).\n", iter.debugName(), virtualRegister);
+                dataLog("DFG_CONSISTENCY_CHECK failed: name mismatch for gpr %s (virtual register %d).\n", iter.debugName(), virtualRegister);
                 failed = true;
             }
         }
@@ -542,7 +567,7 @@ void SpeculativeJIT::checkConsistency()
 
         GenerationInfo& info = m_generationInfo[virtualRegister];
         if (iter.regID() != info.fpr()) {
-            fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for fpr %s (virtual register %d).\n", iter.debugName(), virtualRegister);
+            dataLog("DFG_CONSISTENCY_CHECK failed: name mismatch for fpr %s (virtual register %d).\n", iter.debugName(), virtualRegister);
             failed = true;
         }
     }
@@ -564,11 +589,7 @@ GPRTemporary::GPRTemporary(SpeculativeJIT* jit)
     : m_jit(jit)
     , m_gpr(InvalidGPRReg)
 {
-#if CPU(X86)
-    // we currenty lazily allocate the reg, as the number of regs on X86 is limited.
-#else
     m_gpr = m_jit->allocate();
-#endif
 }
 
 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, GPRReg specific)
@@ -759,13 +780,15 @@ FPRTemporary::FPRTemporary(SpeculativeJIT* jit, JSValueOperand& op1)
 }
 #endif
 
-#ifndef NDEBUG
 void ValueSource::dump(FILE* out) const
 {
     switch (kind()) {
     case SourceNotSet:
         fprintf(out, "NotSet");
         break;
+    case SourceIsDead:
+        fprintf(out, "IsDead");
+        break;
     case ValueInRegisterFile:
         fprintf(out, "InRegFile");
         break;
@@ -781,12 +804,14 @@ void ValueSource::dump(FILE* out) const
     case DoubleInRegisterFile:
         fprintf(out, "Double");
         break;
+    case ArgumentsSource:
+        fprintf(out, "Arguments");
+        break;
     case HaveNode:
         fprintf(out, "Node(%d)", m_nodeIndex);
         break;
     }
 }
-#endif
 
 void SpeculativeJIT::compilePeepHoleDoubleBranch(Node& node, NodeIndex branchNodeIndex, JITCompiler::DoubleCondition condition)
 {
@@ -797,13 +822,11 @@ void SpeculativeJIT::compilePeepHoleDoubleBranch(Node& node, NodeIndex branchNod
     SpeculateDoubleOperand op1(this, node.child1());
     SpeculateDoubleOperand op2(this, node.child2());
     
-    addBranch(m_jit.branchDouble(condition, op1.fpr(), op2.fpr()), taken);
-    
-    if (notTaken != (m_block + 1))
-        addBranch(m_jit.jump(), notTaken);
+    branchDouble(condition, op1.fpr(), op2.fpr(), taken);
+    jump(notTaken);
 }
 
-void SpeculativeJIT::compilePeepHoleObjectEquality(Node& node, NodeIndex branchNodeIndex, const ClassInfo* classInfo, PredictionChecker predictionCheck)
+void SpeculativeJIT::compilePeepHoleObjectEquality(Node& node, NodeIndex branchNodeIndex, const ClassInfo* classInfo, SpeculatedTypeChecker speculatedTypeChecker)
 {
     Node& branchNode = at(branchNodeIndex);
     BlockIndex taken = branchNode.takenBlockIndex();
@@ -811,7 +834,7 @@ void SpeculativeJIT::compilePeepHoleObjectEquality(Node& node, NodeIndex branchN
 
     MacroAssembler::RelationalCondition condition = MacroAssembler::Equal;
     
-    if (taken == (m_block + 1)) {
+    if (taken == nextBlock()) {
         condition = MacroAssembler::NotEqual;
         BlockIndex tmp = taken;
         taken = notTaken;
@@ -824,14 +847,13 @@ void SpeculativeJIT::compilePeepHoleObjectEquality(Node& node, NodeIndex branchN
     GPRReg op1GPR = op1.gpr();
     GPRReg op2GPR = op2.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)));
+    if (!speculatedTypeChecker(m_state.forNode(node.child1()).m_type))
+        speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node.child1().index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
+    if (!speculatedTypeChecker(m_state.forNode(node.child2()).m_type))
+        speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node.child2().index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
     
-    addBranch(m_jit.branchPtr(condition, op1GPR, op2GPR), taken);
-    if (notTaken != (m_block + 1))
-        addBranch(m_jit.jump(), notTaken);
+    branchPtr(condition, op1GPR, op2GPR, taken);
+    jump(notTaken);
 }
 
 void SpeculativeJIT::compilePeepHoleIntegerBranch(Node& node, NodeIndex branchNodeIndex, JITCompiler::RelationalCondition condition)
@@ -842,61 +864,89 @@ void SpeculativeJIT::compilePeepHoleIntegerBranch(Node& node, NodeIndex branchNo
 
     // 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.
-    if (taken == (m_block + 1)) {
+    if (taken == nextBlock()) {
         condition = JITCompiler::invert(condition);
         BlockIndex tmp = taken;
         taken = notTaken;
         notTaken = tmp;
     }
 
-    if (isInt32Constant(node.child1())) {
-        int32_t imm = valueOfInt32Constant(node.child1());
+    if (isInt32Constant(node.child1().index())) {
+        int32_t imm = valueOfInt32Constant(node.child1().index());
         SpeculateIntegerOperand op2(this, node.child2());
-        addBranch(m_jit.branch32(condition, JITCompiler::Imm32(imm), op2.gpr()), taken);
-    } else if (isInt32Constant(node.child2())) {
+        branch32(condition, JITCompiler::Imm32(imm), op2.gpr(), taken);
+    } else if (isInt32Constant(node.child2().index())) {
         SpeculateIntegerOperand op1(this, node.child1());
-        int32_t imm = valueOfInt32Constant(node.child2());
-        addBranch(m_jit.branch32(condition, op1.gpr(), JITCompiler::Imm32(imm)), taken);
+        int32_t imm = valueOfInt32Constant(node.child2().index());
+        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.gpr(), op2.gpr()), taken);
+        branch32(condition, op1.gpr(), op2.gpr(), taken);
     }
 
-    // Check for fall through, otherwise we need to jump.
-    if (notTaken != (m_block + 1))
-        addBranch(m_jit.jump(), notTaken);
+    jump(notTaken);
 }
 
 // Returns true if the compare is fused with a subsequent branch.
 bool SpeculativeJIT::compilePeepHoleBranch(Node& node, MacroAssembler::RelationalCondition condition, MacroAssembler::DoubleCondition doubleCondition, S_DFGOperation_EJJ operation)
 {
     // Fused compare & branch.
-    NodeIndex branchNodeIndex = detectPeepHoleBranch();
-    if (branchNodeIndex != NoNode) {
+    unsigned branchIndexInBlock = detectPeepHoleBranch();
+    if (branchIndexInBlock != UINT_MAX) {
+        NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
+
         // 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 (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2()))) {
+        if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())))
             compilePeepHoleIntegerBranch(node, branchNodeIndex, condition);
-            use(node.child1());
-            use(node.child2());
-        } else if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2()))) {
+        else if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2())))
             compilePeepHoleDoubleBranch(node, branchNodeIndex, doubleCondition);
-            use(node.child1());
-            use(node.child2());
-        } else if (node.op == CompareEq && Node::shouldSpeculateFinalObject(at(node.child1()), at(node.child2()))) {
-            compilePeepHoleObjectEquality(node, branchNodeIndex, &JSFinalObject::s_info, isFinalObjectPrediction);
-            use(node.child1());
-            use(node.child2());
-        } else if (node.op == CompareEq && Node::shouldSpeculateArray(at(node.child1()), at(node.child2()))) {
-            compilePeepHoleObjectEquality(node, branchNodeIndex, &JSArray::s_info, isArrayPrediction);
-            use(node.child1());
-            use(node.child2());
-        } else
+        else if (node.op() == CompareEq) {
+            if (Node::shouldSpeculateFinalObject(
+                    at(node.child1()), at(node.child2()))) {
+                compilePeepHoleObjectEquality(
+                    node, branchNodeIndex, &JSFinalObject::s_info,
+                    isFinalObjectSpeculation);
+            } else if (Node::shouldSpeculateArray(
+                           at(node.child1()), at(node.child2()))) {
+                compilePeepHoleObjectEquality(
+                    node, branchNodeIndex, &JSArray::s_info,
+                    isArraySpeculation);
+            } else if (at(node.child1()).shouldSpeculateFinalObject()
+                       && at(node.child2()).shouldSpeculateFinalObjectOrOther()) {
+                compilePeepHoleObjectToObjectOrOtherEquality(
+                    node.child1(), node.child2(), branchNodeIndex,
+                    &JSFinalObject::s_info, isFinalObjectSpeculation);
+            } else if (at(node.child1()).shouldSpeculateFinalObjectOrOther()
+                       && at(node.child2()).shouldSpeculateFinalObject()) {
+                compilePeepHoleObjectToObjectOrOtherEquality(
+                    node.child2(), node.child1(), branchNodeIndex,
+                    &JSFinalObject::s_info, isFinalObjectSpeculation);
+            } else if (at(node.child1()).shouldSpeculateArray()
+                       && at(node.child2()).shouldSpeculateArrayOrOther()) {
+                compilePeepHoleObjectToObjectOrOtherEquality(
+                    node.child1(), node.child2(), branchNodeIndex,
+                    &JSArray::s_info, isArraySpeculation);
+            } else if (at(node.child1()).shouldSpeculateArrayOrOther()
+                       && at(node.child2()).shouldSpeculateArray()) {
+                compilePeepHoleObjectToObjectOrOtherEquality(
+                    node.child2(), node.child1(), branchNodeIndex,
+                    &JSArray::s_info, isArraySpeculation);
+            } else {
+                nonSpeculativePeepholeBranch(node, branchNodeIndex, condition, operation);
+                return true;
+            }
+        } else {
             nonSpeculativePeepholeBranch(node, branchNodeIndex, condition, operation);
+            return true;
+        }
 
+        use(node.child1());
+        use(node.child2());
+        m_indexInBlock = branchIndexInBlock;
         m_compileIndex = branchNodeIndex;
         return true;
     }
@@ -905,19 +955,26 @@ bool SpeculativeJIT::compilePeepHoleBranch(Node& node, MacroAssembler::Relationa
 
 void SpeculativeJIT::compileMovHint(Node& node)
 {
-    ASSERT(node.op == SetLocal);
+    ASSERT(node.op() == SetLocal);
     
-    setNodeIndexForOperand(node.child1(), node.local());
+    setNodeIndexForOperand(node.child1().index(), node.local());
     m_lastSetOperand = node.local();
 }
 
 void SpeculativeJIT::compile(BasicBlock& block)
 {
     ASSERT(m_compileOkay);
-    ASSERT(m_compileIndex == block.begin);
     
-    if (!block.isReachable) {
-        m_compileIndex = block.end;
+    if (!block.isReachable)
+        return;
+    
+    if (!block.cfaHasVisited) {
+        // Don't generate code for basic blocks that are unreachable according to CFA.
+        // But to be sure that nobody has generated a jump to this block, drop in a
+        // breakpoint here.
+#if !ASSERT_DISABLED
+        m_jit.breakpoint();
+#endif
         return;
     }
 
@@ -925,14 +982,16 @@ void SpeculativeJIT::compile(BasicBlock& block)
 #if DFG_ENABLE(JIT_BREAK_ON_EVERY_BLOCK)
     m_jit.breakpoint();
 #endif
+    
+    m_jit.jitAssertHasValidCallFrame();
 
     ASSERT(m_arguments.size() == block.variablesAtHead.numberOfArguments());
     for (size_t i = 0; i < m_arguments.size(); ++i) {
         NodeIndex nodeIndex = block.variablesAtHead.argument(i);
-        if (nodeIndex == NoNode)
+        if (nodeIndex == NoNode || m_jit.codeBlock()->argumentIsCaptured(i))
             m_arguments[i] = ValueSource(ValueInRegisterFile);
         else
-            m_arguments[i] = ValueSource::forPrediction(at(nodeIndex).variableAccessData()->prediction());
+            m_arguments[i] = ValueSource::forSpeculation(at(nodeIndex).variableAccessData()->prediction());
     }
     
     m_state.reset();
@@ -942,24 +1001,38 @@ void SpeculativeJIT::compile(BasicBlock& block)
     for (size_t i = 0; i < m_variables.size(); ++i) {
         NodeIndex nodeIndex = block.variablesAtHead.local(i);
         if (nodeIndex == NoNode)
+            m_variables[i] = ValueSource(SourceIsDead);
+        else if (at(nodeIndex).variableAccessData()->isArgumentsAlias())
+            m_variables[i] = ValueSource(ArgumentsSource);
+        else if (at(nodeIndex).variableAccessData()->isCaptured())
             m_variables[i] = ValueSource(ValueInRegisterFile);
+        else if (!at(nodeIndex).refCount())
+            m_variables[i] = ValueSource(SourceIsDead);
         else if (at(nodeIndex).variableAccessData()->shouldUseDoubleFormat())
             m_variables[i] = ValueSource(DoubleInRegisterFile);
         else
-            m_variables[i] = ValueSource::forPrediction(at(nodeIndex).variableAccessData()->prediction());
+            m_variables[i] = ValueSource::forSpeculation(at(nodeIndex).variableAccessData()->argumentAwarePrediction());
     }
     
     m_lastSetOperand = std::numeric_limits<int>::max();
     m_codeOriginForOSR = CodeOrigin();
+    
+    if (DFG_ENABLE_EDGE_CODE_VERIFICATION) {
+        JITCompiler::Jump verificationSucceeded =
+            m_jit.branch32(JITCompiler::Equal, GPRInfo::regT0, TrustedImm32(m_block));
+        m_jit.breakpoint();
+        verificationSucceeded.link(&m_jit);
+    }
 
-    for (; m_compileIndex < block.end; ++m_compileIndex) {
+    for (m_indexInBlock = 0; m_indexInBlock < block.size(); ++m_indexInBlock) {
+        m_compileIndex = block[m_indexInBlock];
         Node& node = at(m_compileIndex);
         m_codeOriginForOSR = node.codeOrigin;
         if (!node.shouldGenerate()) {
 #if DFG_ENABLE(DEBUG_VERBOSE)
-            fprintf(stderr, "SpeculativeJIT skipping Node @%d (bc#%u) at JIT offset 0x%x     ", (int)m_compileIndex, node.codeOrigin.bytecodeIndex, m_jit.debugOffset());
+            dataLog("SpeculativeJIT skipping Node @%d (bc#%u) at JIT offset 0x%x     ", (int)m_compileIndex, node.codeOrigin.bytecodeIndex, m_jit.debugOffset());
 #endif
-            switch (node.op) {
+            switch (node.op()) {
             case SetLocal:
                 compileMovHint(node);
                 break;
@@ -967,12 +1040,38 @@ void SpeculativeJIT::compile(BasicBlock& block)
             case InlineStart: {
                 InlineCallFrame* inlineCallFrame = node.codeOrigin.inlineCallFrame;
                 int argumentCountIncludingThis = inlineCallFrame->arguments.size();
+                unsigned argumentPositionStart = node.argumentPositionStart();
+                bool argumentsAreCaptured =
+                    baselineCodeBlockForInlineCallFrame(inlineCallFrame)->argumentsAreCaptured();
                 for (int i = 0; i < argumentCountIncludingThis; ++i) {
-                    ValueRecovery recovery = computeValueRecoveryFor(m_variables[inlineCallFrame->stackOffset + CallFrame::argumentOffsetIncludingThis(i)]);
-                    // The recovery cannot point to registers, since the call frame reification isn't
-                    // as smart as OSR, so it can't handle that. The exception is the this argument,
-                    // which we don't really need to be able to recover.
-                    ASSERT(!i || !recovery.isInRegisters());
+                    ValueRecovery recovery;
+                    if (argumentsAreCaptured)
+                        recovery = ValueRecovery::alreadyInRegisterFile();
+                    else {
+                        ArgumentPosition& argumentPosition =
+                            m_jit.graph().m_argumentPositions[argumentPositionStart + i];
+                        ValueSource valueSource;
+                        if (argumentPosition.shouldUseDoubleFormat())
+                            valueSource = ValueSource(DoubleInRegisterFile);
+                        else if (isInt32Speculation(argumentPosition.prediction()))
+                            valueSource = ValueSource(Int32InRegisterFile);
+                        else if (isArraySpeculation(argumentPosition.prediction()))
+                            valueSource = ValueSource(CellInRegisterFile);
+                        else if (isBooleanSpeculation(argumentPosition.prediction()))
+                            valueSource = ValueSource(BooleanInRegisterFile);
+                        else
+                            valueSource = ValueSource(ValueInRegisterFile);
+                        recovery = computeValueRecoveryFor(valueSource);
+                    }
+                    // The recovery should refer either to something that has already been
+                    // stored into the register file at the right place, or to a constant,
+                    // since the Arguments code isn't smart enough to handle anything else.
+                    // The exception is the this argument, which we don't really need to be
+                    // able to recover.
+#if DFG_ENABLE(DEBUG_VERBOSE)
+                    dataLog("\nRecovery for argument %d: ", i);
+                    recovery.dump(WTF::dataFile());
+#endif
                     inlineCallFrame->arguments[i] = recovery;
                 }
                 break;
@@ -984,7 +1083,7 @@ void SpeculativeJIT::compile(BasicBlock& block)
         } else {
             
 #if DFG_ENABLE(DEBUG_VERBOSE)
-            fprintf(stderr, "SpeculativeJIT generating Node @%d (bc#%u) at JIT offset 0x%x   ", (int)m_compileIndex, node.codeOrigin.bytecodeIndex, m_jit.debugOffset());
+            dataLog("SpeculativeJIT generating Node @%d (bc#%u) at JIT offset 0x%x   ", (int)m_compileIndex, node.codeOrigin.bytecodeIndex, m_jit.debugOffset());
 #endif
 #if DFG_ENABLE(JIT_BREAK_ON_EVERY_NODE)
             m_jit.breakpoint();
@@ -997,7 +1096,6 @@ void SpeculativeJIT::compile(BasicBlock& block)
             compile(node);
             if (!m_compileOkay) {
                 m_compileOkay = true;
-                m_compileIndex = block.end;
                 clearGenerationInfo();
                 return;
             }
@@ -1005,20 +1103,20 @@ void SpeculativeJIT::compile(BasicBlock& block)
 #if DFG_ENABLE(DEBUG_VERBOSE)
             if (node.hasResult()) {
                 GenerationInfo& info = m_generationInfo[node.virtualRegister()];
-                fprintf(stderr, "-> %s, vr#%d", dataFormatToString(info.registerFormat()), (int)node.virtualRegister());
+                dataLog("-> %s, vr#%d", dataFormatToString(info.registerFormat()), (int)node.virtualRegister());
                 if (info.registerFormat() != DataFormatNone) {
                     if (info.registerFormat() == DataFormatDouble)
-                        fprintf(stderr, ", %s", FPRInfo::debugName(info.fpr()));
+                        dataLog(", %s", FPRInfo::debugName(info.fpr()));
 #if USE(JSVALUE32_64)
                     else if (info.registerFormat() & DataFormatJS)
-                        fprintf(stderr, ", %s %s", GPRInfo::debugName(info.tagGPR()), GPRInfo::debugName(info.payloadGPR()));
+                        dataLog(", %s %s", GPRInfo::debugName(info.tagGPR()), GPRInfo::debugName(info.payloadGPR()));
 #endif
                     else
-                        fprintf(stderr, ", %s", GPRInfo::debugName(info.gpr()));
+                        dataLog(", %s", GPRInfo::debugName(info.gpr()));
                 }
-                fprintf(stderr, "    ");
+                dataLog("    ");
             } else
-                fprintf(stderr, "    ");
+                dataLog("    ");
 #endif
         }
         
@@ -1026,22 +1124,30 @@ void SpeculativeJIT::compile(BasicBlock& block)
         for (size_t i = 0; i < m_arguments.size(); ++i)
             computeValueRecoveryFor(argumentToOperand(i)).dump(stderr);
         
-        fprintf(stderr, " : ");
+        dataLog(" : ");
         
         for (int operand = 0; operand < (int)m_variables.size(); ++operand)
             computeValueRecoveryFor(operand).dump(stderr);
 #endif
 
 #if DFG_ENABLE(DEBUG_VERBOSE)
-        fprintf(stderr, "\n");
+        dataLog("\n");
 #endif
         
         // Make sure that the abstract state is rematerialized for the next node.
-        m_state.execute(m_compileIndex);
+        m_state.execute(m_indexInBlock);
         
         if (node.shouldGenerate())
             checkConsistency();
     }
+    
+    // Perform the most basic verification that children have been used correctly.
+#if !ASSERT_DISABLED
+    for (unsigned index = 0; index < m_generationInfo.size(); ++index) {
+        GenerationInfo& info = m_generationInfo[index];
+        ASSERT(!info.alive());
+    }
+#endif
 }
 
 // If we are making type predictions about our arguments then
@@ -1049,6 +1155,7 @@ void SpeculativeJIT::compile(BasicBlock& block)
 void SpeculativeJIT::checkArgumentTypes()
 {
     ASSERT(!m_compileIndex);
+    m_isCheckingArgumentTypes = true;
     m_codeOriginForOSR = CodeOrigin(0);
 
     for (size_t i = 0; i < m_arguments.size(); ++i)
@@ -1056,162 +1163,212 @@ void SpeculativeJIT::checkArgumentTypes()
     for (size_t i = 0; i < m_variables.size(); ++i)
         m_variables[i] = ValueSource(ValueInRegisterFile);
     
-    for (int i = 0; i < m_jit.codeBlock()->m_numParameters; ++i) {
-        VariableAccessData* variableAccessData = at(m_jit.graph().m_arguments[i]).variableAccessData();
+    for (int i = 0; i < m_jit.codeBlock()->numParameters(); ++i) {
+        NodeIndex nodeIndex = m_jit.graph().m_arguments[i];
+        Node& node = at(nodeIndex);
+        ASSERT(node.op() == SetArgument);
+        if (!node.shouldGenerate()) {
+            // The argument is dead. We don't do any checks for such arguments.
+            continue;
+        }
+        
+        VariableAccessData* variableAccessData = node.variableAccessData();
         VirtualRegister virtualRegister = variableAccessData->local();
-        PredictedType predictedType = variableAccessData->prediction();
+        SpeculatedType predictedType = variableAccessData->prediction();
+
+        JSValueSource valueSource = JSValueSource(JITCompiler::addressFor(virtualRegister));
+        
 #if USE(JSVALUE64)
-        if (isInt32Prediction(predictedType))
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::Below, JITCompiler::addressFor(virtualRegister), GPRInfo::tagTypeNumberRegister));
-        else if (isArrayPrediction(predictedType)) {
+        if (isInt32Speculation(predictedType))
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::Below, JITCompiler::addressFor(virtualRegister), GPRInfo::tagTypeNumberRegister));
+        else if (isArraySpeculation(predictedType)) {
             GPRTemporary temp(this);
             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
-        } else if (isByteArrayPrediction(predictedType)) {
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
+        } else if (isBooleanSpeculation(predictedType)) {
             GPRTemporary temp(this);
             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info)));
-        } else if (isBooleanPrediction(predictedType)) {
+            m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), temp.gpr());
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
+        } else if (isInt8ArraySpeculation(predictedType)) {
             GPRTemporary temp(this);
             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
-            m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), temp.gpr());
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
-        } else if (isInt8ArrayPrediction(predictedType)) {
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int8ArrayDescriptor().m_classInfo)));
+        } else if (isInt16ArraySpeculation(predictedType)) {
             GPRTemporary temp(this);
             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int8ArrayDescriptor().m_classInfo)));
-        } else if (isInt16ArrayPrediction(predictedType)) {
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int16ArrayDescriptor().m_classInfo)));
+        } else if (isInt32ArraySpeculation(predictedType)) {
             GPRTemporary temp(this);
             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int16ArrayDescriptor().m_classInfo)));
-        } else if (isInt32ArrayPrediction(predictedType)) {
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int32ArrayDescriptor().m_classInfo)));
+        } else if (isUint8ArraySpeculation(predictedType)) {
             GPRTemporary temp(this);
             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int32ArrayDescriptor().m_classInfo)));
-        } else if (isUint8ArrayPrediction(predictedType)) {
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ArrayDescriptor().m_classInfo)));
+        } else if (isUint8ClampedArraySpeculation(predictedType)) {
             GPRTemporary temp(this);
             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ArrayDescriptor().m_classInfo)));
-        } else if (isUint16ArrayPrediction(predictedType)) {
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ClampedArrayDescriptor().m_classInfo)));
+        } else if (isUint16ArraySpeculation(predictedType)) {
             GPRTemporary temp(this);
             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint16ArrayDescriptor().m_classInfo)));
-        } else if (isUint32ArrayPrediction(predictedType)) {
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint16ArrayDescriptor().m_classInfo)));
+        } else if (isUint32ArraySpeculation(predictedType)) {
             GPRTemporary temp(this);
             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint32ArrayDescriptor().m_classInfo)));
-        } else if (isFloat32ArrayPrediction(predictedType)) {
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint32ArrayDescriptor().m_classInfo)));
+        } else if (isFloat32ArraySpeculation(predictedType)) {
             GPRTemporary temp(this);
             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float32ArrayDescriptor().m_classInfo)));
-        } else if (isFloat64ArrayPrediction(predictedType)) {
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float32ArrayDescriptor().m_classInfo)));
+        } else if (isFloat64ArraySpeculation(predictedType)) {
             GPRTemporary temp(this);
             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float64ArrayDescriptor().m_classInfo)));
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float64ArrayDescriptor().m_classInfo)));
         }
 #else
-        if (isInt32Prediction(predictedType))
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag)));
-        else if (isArrayPrediction(predictedType)) {
+        if (isInt32Speculation(predictedType))
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag)));
+        else if (isArraySpeculation(predictedType)) {
             GPRTemporary temp(this);
             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
-        } else if (isByteArrayPrediction(predictedType)) {
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
+        } else if (isBooleanSpeculation(predictedType))
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::BooleanTag)));
+        else if (isInt8ArraySpeculation(predictedType)) {
             GPRTemporary temp(this);
             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info)));
-        } else if (isBooleanPrediction(predictedType))
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::BooleanTag)));
-        else if (isInt8ArrayPrediction(predictedType)) {
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int8ArrayDescriptor().m_classInfo)));
+        } else if (isInt16ArraySpeculation(predictedType)) {
             GPRTemporary temp(this);
             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int8ArrayDescriptor().m_classInfo)));
-        } else if (isInt16ArrayPrediction(predictedType)) {
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int16ArrayDescriptor().m_classInfo)));
+        } else if (isInt32ArraySpeculation(predictedType)) {
             GPRTemporary temp(this);
             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int16ArrayDescriptor().m_classInfo)));
-        } else if (isInt32ArrayPrediction(predictedType)) {
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int32ArrayDescriptor().m_classInfo)));
+        } else if (isUint8ArraySpeculation(predictedType)) {
             GPRTemporary temp(this);
             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int32ArrayDescriptor().m_classInfo)));
-        } else if (isUint8ArrayPrediction(predictedType)) {
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ArrayDescriptor().m_classInfo)));
+        } else if (isUint8ClampedArraySpeculation(predictedType)) {
             GPRTemporary temp(this);
             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ArrayDescriptor().m_classInfo)));
-        } else if (isUint16ArrayPrediction(predictedType)) {
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ClampedArrayDescriptor().m_classInfo)));
+        } else if (isUint16ArraySpeculation(predictedType)) {
             GPRTemporary temp(this);
             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint16ArrayDescriptor().m_classInfo)));
-        }  else if (isUint32ArrayPrediction(predictedType)) {
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint16ArrayDescriptor().m_classInfo)));
+        }  else if (isUint32ArraySpeculation(predictedType)) {
             GPRTemporary temp(this);
             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint32ArrayDescriptor().m_classInfo)));
-        }  else if (isFloat32ArrayPrediction(predictedType)) {
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint32ArrayDescriptor().m_classInfo)));
+        }  else if (isFloat32ArraySpeculation(predictedType)) {
             GPRTemporary temp(this);
             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float32ArrayDescriptor().m_classInfo)));
-        }   else if (isFloat64ArrayPrediction(predictedType)) {
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float32ArrayDescriptor().m_classInfo)));
+        }   else if (isFloat64ArraySpeculation(predictedType)) {
             GPRTemporary temp(this);
             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
-            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float64ArrayDescriptor().m_classInfo)));
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float64ArrayDescriptor().m_classInfo)));
         } 
 #endif
     }
+    m_isCheckingArgumentTypes = false;
 }
 
 bool SpeculativeJIT::compile()
 {
     checkArgumentTypes();
 
+    if (DFG_ENABLE_EDGE_CODE_VERIFICATION)
+        m_jit.move(TrustedImm32(0), GPRInfo::regT0);
+
     ASSERT(!m_compileIndex);
-    for (m_block = 0; m_block < m_jit.graph().m_blocks.size(); ++m_block)
-        compile(*m_jit.graph().m_blocks[m_block]);
+    for (m_block = 0; m_block < m_jit.graph().m_blocks.size(); ++m_block) {
+        BasicBlock* block = m_jit.graph().m_blocks[m_block].get();
+        if (block)
+            compile(*block);
+    }
     linkBranches();
     return true;
 }
 
+void SpeculativeJIT::createOSREntries()
+{
+    for (BlockIndex blockIndex = 0; blockIndex < m_jit.graph().m_blocks.size(); ++blockIndex) {
+        BasicBlock* block = m_jit.graph().m_blocks[blockIndex].get();
+        if (!block)
+            continue;
+        if (!block->isOSRTarget)
+            continue;
+
+        // Currently we only need to create OSR entry trampolines when using edge code
+        // verification. But in the future, we'll need this for other things as well (like
+        // when we have global reg alloc).
+        // If we don't need OSR entry trampolin
+        if (!DFG_ENABLE_EDGE_CODE_VERIFICATION) {
+            m_osrEntryHeads.append(m_blockHeads[blockIndex]);
+            continue;
+        }
+        
+        m_osrEntryHeads.append(m_jit.label());
+        m_jit.move(TrustedImm32(blockIndex), GPRInfo::regT0);
+        m_jit.jump().linkTo(m_blockHeads[blockIndex], &m_jit);
+    }
+}
+
 void SpeculativeJIT::linkOSREntries(LinkBuffer& linkBuffer)
 {
+    unsigned osrEntryIndex = 0;
     for (BlockIndex blockIndex = 0; blockIndex < m_jit.graph().m_blocks.size(); ++blockIndex) {
-        BasicBlock& block = *m_jit.graph().m_blocks[blockIndex];
-        if (block.isOSRTarget)
-            m_jit.noticeOSREntry(block, m_blockHeads[blockIndex], linkBuffer);
+        BasicBlock* block = m_jit.graph().m_blocks[blockIndex].get();
+        if (!block)
+            continue;
+        if (!block->isOSRTarget)
+            continue;
+        m_jit.noticeOSREntry(*block, m_osrEntryHeads[osrEntryIndex++], linkBuffer);
     }
+    ASSERT(osrEntryIndex == m_osrEntryHeads.size());
 }
 
 ValueRecovery SpeculativeJIT::computeValueRecoveryFor(const ValueSource& valueSource)
 {
     switch (valueSource.kind()) {
+    case SourceIsDead:
+        return ValueRecovery::constant(jsUndefined());
+        
     case ValueInRegisterFile:
         return ValueRecovery::alreadyInRegisterFile();
         
@@ -1226,12 +1383,19 @@ ValueRecovery SpeculativeJIT::computeValueRecoveryFor(const ValueSource& valueSo
         
     case DoubleInRegisterFile:
         return ValueRecovery::alreadyInRegisterFileAsUnboxedDouble();
+        
+    case ArgumentsSource:
+        return ValueRecovery::argumentsThatWereNotCreated();
 
     case HaveNode: {
-        if (m_jit.isConstant(valueSource.nodeIndex()))
-            return ValueRecovery::constant(m_jit.valueOfJSConstant(valueSource.nodeIndex()));
-    
         Node* nodePtr = &at(valueSource.nodeIndex());
+
+        if (nodePtr->isPhantomArguments())
+            return ValueRecovery::argumentsThatWereNotCreated();
+        
+        if (nodePtr->hasConstant())
+            return ValueRecovery::constant(valueOfJSConstant(valueSource.nodeIndex()));
+        
         if (!nodePtr->shouldGenerate()) {
             // It's legitimately dead. As in, nobody will ever use this node, or operand,
             // ever. Set it to Undefined to make the GC happy after the OSR.
@@ -1243,15 +1407,12 @@ ValueRecovery SpeculativeJIT::computeValueRecoveryFor(const ValueSource& valueSo
             // Try to see if there is an alternate node that would contain the value we want.
             // There are four possibilities:
             //
-            // ValueToNumber: If the only live version of the value is a ValueToNumber node
-            //    then it means that all remaining uses of the value would have performed a
-            //    ValueToNumber conversion anyway. Thus, we can substitute ValueToNumber.
+            // Int32ToDouble: We can use this in place of the original node, but
+            //    we'd rather not; so we use it only if it is the only remaining
+            //    live version.
             //
-            // ValueToInt32: Likewise, if the only remaining live version of the value is
-            //    ValueToInt32, then we can use it. But if there is both a ValueToInt32
-            //    and a ValueToNumber, then we better go with ValueToNumber because it
-            //    means that some remaining uses would have converted to number while
-            //    others would have converted to Int32.
+            // ValueToInt32: If the only remaining live version of the value is
+            //    ValueToInt32, then we can use it.
             //
             // UInt32ToNumber: If the only live version of the value is a UInt32ToNumber
             //    then the only remaining uses are ones that want a properly formed number
@@ -1260,11 +1421,14 @@ ValueRecovery SpeculativeJIT::computeValueRecoveryFor(const ValueSource& valueSo
             // The reverse of the above: This node could be a UInt32ToNumber, but its
             //    alternative is still alive. This means that the only remaining uses of
             //    the number would be fine with a UInt32 intermediate.
+            //
+            // DoubleAsInt32: Same as UInt32ToNumber.
+            //
         
             bool found = false;
         
-            if (nodePtr->op == UInt32ToNumber) {
-                NodeIndex nodeIndex = nodePtr->child1();
+            if (nodePtr->op() == UInt32ToNumber || nodePtr->op() == DoubleAsInt32) {
+                NodeIndex nodeIndex = nodePtr->child1().index();
                 nodePtr = &at(nodeIndex);
                 infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
                 if (infoPtr->alive() && infoPtr->nodeIndex() == nodeIndex)
@@ -1272,9 +1436,10 @@ ValueRecovery SpeculativeJIT::computeValueRecoveryFor(const ValueSource& valueSo
             }
         
             if (!found) {
-                NodeIndex valueToNumberIndex = NoNode;
+                NodeIndex int32ToDoubleIndex = NoNode;
                 NodeIndex valueToInt32Index = NoNode;
                 NodeIndex uint32ToNumberIndex = NoNode;
+                NodeIndex doubleAsInt32Index = NoNode;
             
                 for (unsigned virtualRegister = 0; virtualRegister < m_generationInfo.size(); ++virtualRegister) {
                     GenerationInfo& info = m_generationInfo[virtualRegister];
@@ -1285,10 +1450,9 @@ ValueRecovery SpeculativeJIT::computeValueRecoveryFor(const ValueSource& valueSo
                     Node& node = at(info.nodeIndex());
                     if (node.child1Unchecked() != valueSource.nodeIndex())
                         continue;
-                    switch (node.op) {
-                    case ValueToNumber:
-                    case ValueToDouble:
-                        valueToNumberIndex = info.nodeIndex();
+                    switch (node.op()) {
+                    case Int32ToDouble:
+                        int32ToDoubleIndex = info.nodeIndex();
                         break;
                     case ValueToInt32:
                         valueToInt32Index = info.nodeIndex();
@@ -1296,14 +1460,18 @@ ValueRecovery SpeculativeJIT::computeValueRecoveryFor(const ValueSource& valueSo
                     case UInt32ToNumber:
                         uint32ToNumberIndex = info.nodeIndex();
                         break;
+                    case DoubleAsInt32:
+                        doubleAsInt32Index = info.nodeIndex();
                     default:
                         break;
                     }
                 }
             
                 NodeIndex nodeIndexToUse;
-                if (valueToNumberIndex != NoNode)
-                    nodeIndexToUse = valueToNumberIndex;
+                if (doubleAsInt32Index != NoNode)
+                    nodeIndexToUse = doubleAsInt32Index;
+                else if (int32ToDoubleIndex != NoNode)
+                    nodeIndexToUse = int32ToDoubleIndex;
                 else if (valueToInt32Index != NoNode)
                     nodeIndexToUse = valueToInt32Index;
                 else if (uint32ToNumberIndex != NoNode)
@@ -1358,8 +1526,8 @@ void SpeculativeJIT::compileGetCharCodeAt(Node& node)
     GPRReg indexReg = index.gpr();
     GPRReg storageReg = storage.gpr();
     
-    if (!isStringPrediction(m_state.forNode(node.child1()).m_type)) {
-        ASSERT(!(at(node.child1()).prediction() & PredictString));
+    if (!isStringSpeculation(m_state.forNode(node.child1()).m_type)) {
+        ASSERT(!(at(node.child1()).prediction() & SpecString));
         terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
         noResult(m_compileIndex);
         return;
@@ -1397,8 +1565,8 @@ void SpeculativeJIT::compileGetByValOnString(Node& node)
     GPRReg propertyReg = property.gpr();
     GPRReg storageReg = storage.gpr();
 
-    if (!isStringPrediction(m_state.forNode(node.child1()).m_type)) {
-        ASSERT(!(at(node.child1()).prediction() & PredictString));
+    if (!isStringSpeculation(m_state.forNode(node.child1()).m_type)) {
+        ASSERT(!(at(node.child1()).prediction() & SpecString));
         terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
         noResult(m_compileIndex);
         return;
@@ -1436,33 +1604,178 @@ void SpeculativeJIT::compileGetByValOnString(Node& node)
     cellResult(scratchReg, m_compileIndex);
 }
 
+GeneratedOperandType SpeculativeJIT::checkGeneratedTypeForToInt32(NodeIndex nodeIndex)
+{
+#if DFG_ENABLE(DEBUG_VERBOSE)
+    dataLog("checkGeneratedTypeForToInt32@%d   ", nodeIndex);
+#endif
+    Node& node = at(nodeIndex);
+    VirtualRegister virtualRegister = node.virtualRegister();
+    GenerationInfo& info = m_generationInfo[virtualRegister];
+
+    if (info.registerFormat() == DataFormatNone) {
+        if (node.hasConstant()) {
+            if (isInt32Constant(nodeIndex))
+                return GeneratedOperandInteger;
+
+            if (isNumberConstant(nodeIndex))
+                return GeneratedOperandDouble;
+
+            terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+            return GeneratedOperandTypeUnknown;
+        }
+
+        if (info.spillFormat() == DataFormatDouble)
+            return GeneratedOperandDouble;
+    }
+
+    switch (info.registerFormat()) {
+    case DataFormatBoolean: // This type never occurs.
+    case DataFormatStorage:
+        ASSERT_NOT_REACHED();
+
+    case DataFormatCell:
+        terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+        return GeneratedOperandTypeUnknown;
+
+    case DataFormatNone:
+    case DataFormatJSCell:
+    case DataFormatJS:
+    case DataFormatJSBoolean:
+        return GeneratedOperandJSValue;
+
+    case DataFormatJSInteger:
+    case DataFormatInteger:
+        return GeneratedOperandInteger;
+
+    case DataFormatJSDouble:
+    case DataFormatDouble:
+        return GeneratedOperandDouble;
+    }
+
+    ASSERT_NOT_REACHED();
+    return GeneratedOperandTypeUnknown;
+}
+
 void SpeculativeJIT::compileValueToInt32(Node& node)
 {
-    if (at(node.child1()).shouldNotSpeculateInteger()) {
-        if (at(node.child1()).shouldSpeculateDouble()) {
-            SpeculateDoubleOperand op1(this, node.child1());
+    if (at(node.child1()).shouldSpeculateInteger()) {
+        SpeculateIntegerOperand op1(this, node.child1());
+        GPRTemporary result(this, op1);
+        m_jit.move(op1.gpr(), result.gpr());
+        integerResult(result.gpr(), m_compileIndex, op1.format());
+        return;
+    }
+    
+    if (at(node.child1()).shouldSpeculateNumber()) {
+        switch (checkGeneratedTypeForToInt32(node.child1().index())) {
+        case GeneratedOperandInteger: {
+            SpeculateIntegerOperand op1(this, node.child1());
+            GPRTemporary result(this, op1);
+            m_jit.move(op1.gpr(), result.gpr());
+            integerResult(result.gpr(), m_compileIndex, op1.format());
+            return;
+        }
+        case GeneratedOperandDouble: {
             GPRTemporary result(this);
+            DoubleOperand op1(this, node.child1());
             FPRReg fpr = op1.fpr();
             GPRReg gpr = result.gpr();
-            JITCompiler::Jump truncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateSuccessful);
+            JITCompiler::Jump notTruncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateFailed);
             
-            silentSpillAllRegisters(gpr);
-            callOperation(toInt32, gpr, fpr);
-            silentFillAllRegisters(gpr);
-            
-            truncatedToInteger.link(&m_jit);
+            addSlowPathGenerator(slowPathCall(notTruncatedToInteger, this, toInt32, gpr, fpr));
+
             integerResult(gpr, m_compileIndex);
             return;
         }
-        // Do it the safe way.
-        nonSpeculativeValueToInt32(node);
+        case GeneratedOperandJSValue: {
+            GPRTemporary result(this);
+#if USE(JSVALUE64)
+            JSValueOperand op1(this, node.child1());
+
+            GPRReg gpr = op1.gpr();
+            GPRReg resultGpr = result.gpr();
+            FPRTemporary tempFpr(this);
+            FPRReg fpr = tempFpr.fpr();
+
+            JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, gpr, GPRInfo::tagTypeNumberRegister);
+
+            if (!isNumberSpeculation(m_state.forNode(node.child1()).m_type))
+                speculationCheck(BadType, JSValueRegs(gpr), node.child1().index(), m_jit.branchTestPtr(MacroAssembler::Zero, gpr, GPRInfo::tagTypeNumberRegister));
+
+            // First, if we get here we have a double encoded as a JSValue
+            m_jit.move(gpr, resultGpr);
+            unboxDouble(resultGpr, fpr);
+
+            silentSpillAllRegisters(resultGpr);
+            callOperation(toInt32, resultGpr, fpr);
+            silentFillAllRegisters(resultGpr);
+
+            JITCompiler::Jump converted = m_jit.jump();
+
+            isInteger.link(&m_jit);
+            m_jit.zeroExtend32ToPtr(gpr, resultGpr);
+
+            converted.link(&m_jit);
+#else
+            Node& childNode = at(node.child1().index());
+            VirtualRegister virtualRegister = childNode.virtualRegister();
+            GenerationInfo& info = m_generationInfo[virtualRegister];
+
+            JSValueOperand op1(this, node.child1());
+
+            GPRReg payloadGPR = op1.payloadGPR();
+            GPRReg resultGpr = result.gpr();
+
+            if (info.registerFormat() == DataFormatJSInteger)
+                m_jit.move(payloadGPR, resultGpr);
+            else {
+                GPRReg tagGPR = op1.tagGPR();
+                FPRTemporary tempFpr(this);
+                FPRReg fpr = tempFpr.fpr();
+                FPRTemporary scratch(this);
+
+                JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, tagGPR, TrustedImm32(JSValue::Int32Tag));
+
+                if (!isNumberSpeculation(m_state.forNode(node.child1()).m_type))
+                    speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), node.child1().index(), m_jit.branch32(MacroAssembler::AboveOrEqual, tagGPR, TrustedImm32(JSValue::LowestTag)));
+
+                unboxDouble(tagGPR, payloadGPR, fpr, scratch.fpr());
+
+                silentSpillAllRegisters(resultGpr);
+                callOperation(toInt32, resultGpr, fpr);
+                silentFillAllRegisters(resultGpr);
+
+                JITCompiler::Jump converted = m_jit.jump();
+
+                isInteger.link(&m_jit);
+                m_jit.move(payloadGPR, resultGpr);
+
+                converted.link(&m_jit);
+            }
+#endif
+            integerResult(resultGpr, m_compileIndex);
+            return;
+        }
+        case GeneratedOperandTypeUnknown:
+            ASSERT_NOT_REACHED();
+            break;
+        }
+    }
+    
+    if (at(node.child1()).shouldSpeculateBoolean()) {
+        SpeculateBooleanOperand op1(this, node.child1());
+        GPRTemporary result(this, op1);
+        
+        m_jit.and32(JITCompiler::TrustedImm32(1), op1.gpr());
+        
+        integerResult(op1.gpr(), m_compileIndex);
         return;
     }
     
-    SpeculateIntegerOperand op1(this, node.child1());
-    GPRTemporary result(this, op1);
-    m_jit.move(op1.gpr(), result.gpr());
-    integerResult(result.gpr(), m_compileIndex, op1.format());
+    // Do it the safe way.
+    nonSpeculativeValueToInt32(node);
+    return;
 }
 
 void SpeculativeJIT::compileUInt32ToNumber(Node& node)
@@ -1495,26 +1808,131 @@ void SpeculativeJIT::compileUInt32ToNumber(Node& node)
     // instruction that follows us, rather than the one we're executing right now. We have
     // to do this because by this point, the original values necessary to compile whatever
     // operation the UInt32ToNumber originated from might be dead.
-    speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, op1.gpr(), TrustedImm32(0)));
-        
-    // Verify that we can do roll forward.
-    ASSERT(at(m_compileIndex + 1).op == SetLocal);
-    ASSERT(at(m_compileIndex + 1).codeOrigin == node.codeOrigin);
-    ASSERT(at(m_compileIndex + 2).codeOrigin != node.codeOrigin);
-        
-    // Now do the magic.
-    OSRExit& exit = m_jit.codeBlock()->lastOSRExit();
-    Node& setLocal = at(m_compileIndex + 1);
-    exit.m_codeOrigin = at(m_compileIndex + 2).codeOrigin;
-    exit.m_lastSetOperand = setLocal.local();
-        
-    // Create the value recovery, and stuff it into the right place.
-    exit.valueRecoveryForOperand(setLocal.local()) = ValueRecovery::uint32InGPR(op1.gpr());
+    forwardSpeculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, op1.gpr(), TrustedImm32(0)), ValueRecovery::uint32InGPR(op1.gpr()));
 
     m_jit.move(op1.gpr(), result.gpr());
     integerResult(result.gpr(), m_compileIndex, op1.format());
 }
 
+void SpeculativeJIT::compileDoubleAsInt32(Node& node)
+{
+    SpeculateDoubleOperand op1(this, node.child1());
+    FPRTemporary scratch(this);
+    GPRTemporary result(this);
+    
+    FPRReg valueFPR = op1.fpr();
+    FPRReg scratchFPR = scratch.fpr();
+    GPRReg resultGPR = result.gpr();
+
+    JITCompiler::JumpList failureCases;
+    m_jit.branchConvertDoubleToInt32(valueFPR, resultGPR, failureCases, scratchFPR);
+    forwardSpeculationCheck(Overflow, JSValueRegs(), NoNode, failureCases, ValueRecovery::inFPR(valueFPR));
+
+    integerResult(resultGPR, m_compileIndex);
+}
+
+void SpeculativeJIT::compileInt32ToDouble(Node& node)
+{
+#if USE(JSVALUE64)
+    // On JSVALUE64 we have a way of loading double constants in a more direct manner
+    // than a int->double conversion. On 32_64, unfortunately, we currently don't have
+    // any such mechanism - though we could have it, if we just provisioned some memory
+    // in CodeBlock for the double form of integer constants.
+    if (at(node.child1()).hasConstant()) {
+        ASSERT(isInt32Constant(node.child1().index()));
+        FPRTemporary result(this);
+        GPRTemporary temp(this);
+        m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfNumberConstant(node.child1().index())))), temp.gpr());
+        m_jit.movePtrToDouble(temp.gpr(), result.fpr());
+        doubleResult(result.fpr(), m_compileIndex);
+        return;
+    }
+#endif
+    
+    if (isInt32Speculation(m_state.forNode(node.child1()).m_type)) {
+        SpeculateIntegerOperand op1(this, node.child1());
+        FPRTemporary result(this);
+        m_jit.convertInt32ToDouble(op1.gpr(), result.fpr());
+        doubleResult(result.fpr(), m_compileIndex);
+        return;
+    }
+    
+    JSValueOperand op1(this, node.child1());
+    FPRTemporary result(this);
+    
+#if USE(JSVALUE64)
+    GPRTemporary temp(this);
+
+    GPRReg op1GPR = op1.gpr();
+    GPRReg tempGPR = temp.gpr();
+    FPRReg resultFPR = result.fpr();
+    
+    JITCompiler::Jump isInteger = m_jit.branchPtr(
+        MacroAssembler::AboveOrEqual, op1GPR, GPRInfo::tagTypeNumberRegister);
+    
+    if (!isNumberSpeculation(m_state.forNode(node.child1()).m_type)) {
+        speculationCheck(
+            BadType, JSValueRegs(op1GPR), node.child1(),
+            m_jit.branchTestPtr(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister));
+    }
+    
+    m_jit.move(op1GPR, tempGPR);
+    unboxDouble(tempGPR, resultFPR);
+    JITCompiler::Jump done = m_jit.jump();
+    
+    isInteger.link(&m_jit);
+    m_jit.convertInt32ToDouble(op1GPR, resultFPR);
+    done.link(&m_jit);
+#else
+    FPRTemporary temp(this);
+    
+    GPRReg op1TagGPR = op1.tagGPR();
+    GPRReg op1PayloadGPR = op1.payloadGPR();
+    FPRReg tempFPR = temp.fpr();
+    FPRReg resultFPR = result.fpr();
+    
+    JITCompiler::Jump isInteger = m_jit.branch32(
+        MacroAssembler::Equal, op1TagGPR, TrustedImm32(JSValue::Int32Tag));
+    
+    if (!isNumberSpeculation(m_state.forNode(node.child1()).m_type)) {
+        speculationCheck(
+            BadType, JSValueRegs(op1TagGPR, op1PayloadGPR), node.child1(),
+            m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag)));
+    }
+    
+    unboxDouble(op1TagGPR, op1PayloadGPR, resultFPR, tempFPR);
+    JITCompiler::Jump done = m_jit.jump();
+    
+    isInteger.link(&m_jit);
+    m_jit.convertInt32ToDouble(op1PayloadGPR, resultFPR);
+    done.link(&m_jit);
+#endif
+    
+    doubleResult(resultFPR, m_compileIndex);
+}
+
+static double clampDoubleToByte(double d)
+{
+    d += 0.5;
+    if (!(d > 0))
+        d = 0;
+    else if (d > 255)
+        d = 255;
+    return d;
+}
+
+static void compileClampIntegerToByte(JITCompiler& jit, GPRReg result)
+{
+    MacroAssembler::Jump inBounds = jit.branch32(MacroAssembler::BelowOrEqual, result, JITCompiler::TrustedImm32(0xff));
+    MacroAssembler::Jump tooBig = jit.branch32(MacroAssembler::GreaterThan, result, JITCompiler::TrustedImm32(0xff));
+    jit.xorPtr(result, result);
+    MacroAssembler::Jump clamped = jit.jump();
+    tooBig.link(&jit);
+    jit.move(JITCompiler::TrustedImm32(255), result);
+    clamped.link(&jit);
+    inBounds.link(&jit);
+}
+
 static void compileClampDoubleToByte(JITCompiler& jit, GPRReg result, FPRReg source, FPRReg scratch)
 {
     // Unordered compare so we pick up NaN
@@ -1545,108 +1963,21 @@ static void compileClampDoubleToByte(JITCompiler& jit, GPRReg result, FPRReg sou
 
 }
 
-void SpeculativeJIT::compilePutByValForByteArray(GPRReg base, GPRReg property, Node& node)
+void SpeculativeJIT::compileGetTypedArrayLength(const TypedArrayDescriptor& descriptor, Node& node, bool needsSpeculationCheck)
 {
-    NodeIndex baseIndex = node.child1();
-    NodeIndex valueIndex = node.child3();
+    SpeculateCellOperand base(this, node.child1());
+    GPRTemporary result(this);
     
-    if (!isByteArrayPrediction(m_state.forNode(baseIndex).m_type))
-        speculationCheck(BadType, JSValueSource::unboxedCell(base), baseIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info)));
-    GPRTemporary value;
-
-    if (at(valueIndex).isConstant()) {
-        JSValue jsValue = valueOfJSConstant(valueIndex);
-        if (!jsValue.isNumber()) {
-            terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
-            noResult(m_compileIndex);
-            return;
-        }
-        double d = jsValue.asNumber();
-        d += 0.5;
-        if (!(d > 0))
-            d = 0;
-        else if (d > 255)
-            d = 255;
-        GPRTemporary scratch(this);
-        GPRReg scratchReg = scratch.gpr();
-        m_jit.move(Imm32((int)d), scratchReg);
-        value.adopt(scratch);
-    } else if (!at(valueIndex).shouldNotSpeculateInteger()) {
-        SpeculateIntegerOperand valueOp(this, valueIndex);
-        GPRTemporary scratch(this);
-        GPRReg scratchReg = scratch.gpr();
-        m_jit.move(valueOp.gpr(), scratchReg);
-        MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::BelowOrEqual, scratchReg, TrustedImm32(0xff));
-        MacroAssembler::Jump tooBig = m_jit.branch32(MacroAssembler::GreaterThan, scratchReg, TrustedImm32(0xff));
-        m_jit.xorPtr(scratchReg, scratchReg);
-        MacroAssembler::Jump clamped = m_jit.jump();
-        tooBig.link(&m_jit);
-        m_jit.move(TrustedImm32(255), scratchReg);
-        clamped.link(&m_jit);
-        inBounds.link(&m_jit);
-        value.adopt(scratch);
-    } else {
-        SpeculateDoubleOperand valueOp(this, valueIndex);
-        GPRTemporary result(this);
-        FPRTemporary floatScratch(this);
-        FPRReg fpr = valueOp.fpr();
-        GPRReg gpr = result.gpr();
-        compileClampDoubleToByte(m_jit, gpr, fpr, floatScratch.fpr());
-        value.adopt(result);
-    }
-    ASSERT_UNUSED(valueGPR, valueGPR != property);
-    ASSERT(valueGPR != base);
-    GPRTemporary storage(this);
-    GPRReg storageReg = storage.gpr();
-    ASSERT(valueGPR != storageReg);
-    m_jit.loadPtr(MacroAssembler::Address(base, JSByteArray::offsetOfStorage()), storageReg);
-    MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, property, MacroAssembler::Address(storageReg, ByteArray::offsetOfSize()));
-    m_jit.store8(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesOne, ByteArray::offsetOfData()));
-    outOfBounds.link(&m_jit);
-    noResult(m_compileIndex);
-}
-
-void SpeculativeJIT::compileGetByValOnByteArray(Node& node)
-{
-    SpeculateCellOperand base(this, node.child1());
-    SpeculateStrictInt32Operand property(this, node.child2());
-
-    GPRReg baseReg = base.gpr();
-    GPRReg propertyReg = property.gpr();
-
-    if (!isByteArrayPrediction(m_state.forNode(node.child1()).m_type)) {
-        terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
-        noResult(m_compileIndex);
-        return;
-    }
-
-    // Load the character into scratchReg
-    GPRTemporary storage(this);
-    GPRReg storageReg = storage.gpr();
-    m_jit.loadPtr(MacroAssembler::Address(baseReg, JSByteArray::offsetOfStorage()), storageReg);
-    
-    // unsigned comparison so we can filter out negative indices and indices that are too large
-    speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ByteArray::offsetOfSize())));
-
-    m_jit.load8(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne, ByteArray::offsetOfData()), storageReg);
-    integerResult(storageReg, m_compileIndex);
-}
-
-void SpeculativeJIT::compileGetTypedArrayLength(const TypedArrayDescriptor& descriptor, Node& node, bool needsSpeculationCheck)
-{
-    SpeculateCellOperand base(this, node.child1());
-    GPRTemporary result(this);
-    
-    GPRReg baseGPR = base.gpr();
-    GPRReg resultGPR = result.gpr();
-    
-    if (needsSpeculationCheck)
-        speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
-    
-    m_jit.load32(MacroAssembler::Address(baseGPR, descriptor.m_lengthOffset), resultGPR);
-    
-    integerResult(resultGPR, m_compileIndex);
-}
+    GPRReg baseGPR = base.gpr();
+    GPRReg resultGPR = result.gpr();
+    
+    if (needsSpeculationCheck)
+        speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
+    
+    m_jit.load32(MacroAssembler::Address(baseGPR, descriptor.m_lengthOffset), resultGPR);
+    
+    integerResult(resultGPR, m_compileIndex);
+}
 
 void SpeculativeJIT::compileGetByValOnIntTypedArray(const TypedArrayDescriptor& descriptor, Node& node, size_t elementSize, TypedArraySpeculationRequirements speculationRequirements, TypedArraySignedness signedness)
 {
@@ -1674,10 +2005,16 @@ void SpeculativeJIT::compileGetByValOnIntTypedArray(const TypedArrayDescriptor&
     inBounds.link(&m_jit);
     switch (elementSize) {
     case 1:
-        m_jit.load8(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne), resultReg);
+        if (signedness == SignedTypedArray)
+            m_jit.load8Signed(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne), resultReg);
+        else
+            m_jit.load8(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne), resultReg);
         break;
     case 2:
-        m_jit.load16(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesTwo), resultReg);
+        if (signedness == SignedTypedArray)
+            m_jit.load16Signed(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesTwo), resultReg);
+        else
+            m_jit.load16(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesTwo), resultReg);
         break;
     case 4:
         m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesFour), resultReg);
@@ -1686,47 +2023,76 @@ void SpeculativeJIT::compileGetByValOnIntTypedArray(const TypedArrayDescriptor&
         ASSERT_NOT_REACHED();
     }
     outOfBounds.link(&m_jit);
-    if (elementSize < 4 || signedness == SignedTypedArray)
+    if (elementSize < 4 || signedness == SignedTypedArray) {
         integerResult(resultReg, m_compileIndex);
-    else {
-        FPRTemporary fresult(this);
-        m_jit.convertInt32ToDouble(resultReg, fresult.fpr());
-        JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, resultReg, TrustedImm32(0));
-        m_jit.addDouble(JITCompiler::AbsoluteAddress(&AssemblyHelpers::twoToThe32), fresult.fpr());
-        positive.link(&m_jit);
-        doubleResult(fresult.fpr(), m_compileIndex);
+        return;
+    }
+    
+    ASSERT(elementSize == 4 && signedness == UnsignedTypedArray);
+    if (node.shouldSpeculateInteger()) {
+        forwardSpeculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, resultReg, TrustedImm32(0)), ValueRecovery::uint32InGPR(resultReg));
+        integerResult(resultReg, m_compileIndex);
+        return;
     }
+    
+    FPRTemporary fresult(this);
+    m_jit.convertInt32ToDouble(resultReg, fresult.fpr());
+    JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, resultReg, TrustedImm32(0));
+    m_jit.addDouble(JITCompiler::AbsoluteAddress(&AssemblyHelpers::twoToThe32), fresult.fpr());
+    positive.link(&m_jit);
+    doubleResult(fresult.fpr(), m_compileIndex);
 }
 
-void SpeculativeJIT::compilePutByValForIntTypedArray(const TypedArrayDescriptor& descriptor, GPRReg base, GPRReg property, Node& node, size_t elementSize, TypedArraySpeculationRequirements speculationRequirements, TypedArraySignedness signedness)
+void SpeculativeJIT::compilePutByValForIntTypedArray(const TypedArrayDescriptor& descriptor, GPRReg base, GPRReg property, Node& node, size_t elementSize, TypedArraySpeculationRequirements speculationRequirements, TypedArraySignedness signedness, TypedArrayRounding rounding)
 {
-    NodeIndex baseIndex = node.child1();
-    NodeIndex valueIndex = node.child3();
+    Edge baseUse = node.child1();
+    Edge valueUse = node.child3();
     
     if (speculationRequirements != NoTypedArrayTypeSpecCheck)
-        speculationCheck(BadType, JSValueSource::unboxedCell(base), baseIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
+        speculationCheck(BadType, JSValueSource::unboxedCell(base), baseUse, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
     GPRTemporary value;
+    GPRReg valueGPR;
     
-    if (at(valueIndex).isConstant()) {
-        JSValue jsValue = valueOfJSConstant(valueIndex);
+    if (at(valueUse).isConstant()) {
+        JSValue jsValue = valueOfJSConstant(valueUse.index());
         if (!jsValue.isNumber()) {
             terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
             noResult(m_compileIndex);
             return;
         }
         double d = jsValue.asNumber();
+        if (rounding == ClampRounding) {
+            ASSERT(elementSize == 1);
+            d = clampDoubleToByte(d);
+        }
         GPRTemporary scratch(this);
         GPRReg scratchReg = scratch.gpr();
-        m_jit.move(Imm32((int)d), scratchReg);
+        m_jit.move(Imm32(toInt32(d)), scratchReg);
         value.adopt(scratch);
-    } else if (!at(valueIndex).shouldNotSpeculateInteger()) {
-        SpeculateIntegerOperand valueOp(this, valueIndex);
+        valueGPR = scratchReg;
+    } else if (at(valueUse).shouldSpeculateInteger()) {
+        SpeculateIntegerOperand valueOp(this, valueUse);
         GPRTemporary scratch(this);
         GPRReg scratchReg = scratch.gpr();
         m_jit.move(valueOp.gpr(), scratchReg);
+        if (rounding == ClampRounding) {
+            ASSERT(elementSize == 1);
+            compileClampIntegerToByte(m_jit, scratchReg);
+        }
         value.adopt(scratch);
+        valueGPR = scratchReg;
+    } else if (rounding == ClampRounding) {
+        ASSERT(elementSize == 1);
+        SpeculateDoubleOperand valueOp(this, valueUse);
+        GPRTemporary result(this);
+        FPRTemporary floatScratch(this);
+        FPRReg fpr = valueOp.fpr();
+        GPRReg gpr = result.gpr();
+        compileClampDoubleToByte(m_jit, gpr, fpr, floatScratch.fpr());
+        value.adopt(result);
+        valueGPR = gpr;
     } else {
-        SpeculateDoubleOperand valueOp(this, valueIndex);
+        SpeculateDoubleOperand valueOp(this, valueUse);
         GPRTemporary result(this);
         FPRReg fpr = valueOp.fpr();
         GPRReg gpr = result.gpr();
@@ -1734,13 +2100,18 @@ void SpeculativeJIT::compilePutByValForIntTypedArray(const TypedArrayDescriptor&
         m_jit.xorPtr(gpr, gpr);
         MacroAssembler::Jump fixed = m_jit.jump();
         notNaN.link(&m_jit);
-    
+
+        MacroAssembler::Jump failed;
         if (signedness == SignedTypedArray)
-            m_jit.truncateDoubleToInt32(fpr, gpr);
+            failed = m_jit.branchTruncateDoubleToInt32(fpr, gpr, MacroAssembler::BranchIfTruncateFailed);
         else
-            m_jit.truncateDoubleToUint32(fpr, gpr);
+            failed = m_jit.branchTruncateDoubleToUint32(fpr, gpr, MacroAssembler::BranchIfTruncateFailed);
+        
+        addSlowPathGenerator(slowPathCall(failed, this, toInt32, gpr, fpr));
+
         fixed.link(&m_jit);
         value.adopt(result);
+        valueGPR = gpr;
     }
     ASSERT_UNUSED(valueGPR, valueGPR != property);
     ASSERT(valueGPR != base);
@@ -1817,13 +2188,13 @@ void SpeculativeJIT::compileGetByValOnFloatTypedArray(const TypedArrayDescriptor
 
 void SpeculativeJIT::compilePutByValForFloatTypedArray(const TypedArrayDescriptor& descriptor, GPRReg base, GPRReg property, Node& node, size_t elementSize, TypedArraySpeculationRequirements speculationRequirements)
 {
-    NodeIndex baseIndex = node.child1();
-    NodeIndex valueIndex = node.child3();
+    Edge baseUse = node.child1();
+    Edge valueUse = node.child3();
     
-    SpeculateDoubleOperand valueOp(this, valueIndex);
+    SpeculateDoubleOperand valueOp(this, valueUse);
     
     if (speculationRequirements != NoTypedArrayTypeSpecCheck)
-        speculationCheck(BadType, JSValueSource::unboxedCell(base), baseIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
+        speculationCheck(BadType, JSValueSource::unboxedCell(base), baseUse.index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
     
     GPRTemporary result(this);
     
@@ -1898,8 +2269,12 @@ void SpeculativeJIT::compileInstanceOfForObject(Node&, GPRReg valueReg, GPRReg p
 
 void SpeculativeJIT::compileInstanceOf(Node& node)
 {
-    if (!!(at(node.child1()).prediction() & ~PredictCell) && !!(m_state.forNode(node.child1()).m_type & ~PredictCell)) {
+    if ((!!(at(node.child1()).prediction() & ~SpecCell)
+         && !!(m_state.forNode(node.child1()).m_type & ~SpecCell))
+        || at(node.child1()).adjustedRefCount() == 1) {
         // It might not be a cell. Speculate less aggressively.
+        // Or: it might only be used once (i.e. by us), so we get zero benefit
+        // from speculating any more aggressively than we absolutely need to.
         
         JSValueOperand value(this, node.child1());
         SpeculateCellOperand prototype(this, node.child3());
@@ -1954,177 +2329,321 @@ void SpeculativeJIT::compileInstanceOf(Node& node)
 #endif
 }
 
-static bool isPowerOfTwo(int32_t num)
-{
-    return num && !(num & (num - 1));
-}
-
 void SpeculativeJIT::compileSoftModulo(Node& node)
 {
-    bool shouldGeneratePowerOfTwoCheck = true;
-
     // In the fast path, the dividend value could be the final result
     // (in case of |dividend| < |divisor|), so we speculate it as strict int32.
     SpeculateStrictInt32Operand op1(this, node.child1());
-    GPRReg op1Gpr = op1.gpr();
-
-    if (isInt32Constant(node.child2())) {
-        int32_t divisor = valueOfInt32Constant(node.child2());
-        if (divisor < 0)
-            divisor = -divisor;
-
-        if (isPowerOfTwo(divisor)) {
-            GPRTemporary result(this);
-            GPRReg resultGPR = result.gpr();
-            m_jit.move(op1Gpr, resultGPR);
-            JITCompiler::Jump positiveDividend = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op1Gpr, TrustedImm32(0));
-            m_jit.neg32(resultGPR);
-            m_jit.and32(TrustedImm32(divisor - 1), resultGPR);
-            m_jit.neg32(resultGPR);
-            JITCompiler::Jump done = m_jit.jump();
-
-            positiveDividend.link(&m_jit);
-            m_jit.and32(TrustedImm32(divisor - 1), resultGPR);
-
-            done.link(&m_jit);
-            integerResult(resultGPR, m_compileIndex);
-            return;
-        }
 #if CPU(X86) || CPU(X86_64)
+    if (isInt32Constant(node.child2().index())) {
+        int32_t divisor = valueOfInt32Constant(node.child2().index());
         if (divisor) {
+            GPRReg op1Gpr = op1.gpr();
+
             GPRTemporary eax(this, X86Registers::eax);
             GPRTemporary edx(this, X86Registers::edx);
             GPRTemporary scratch(this);
             GPRReg scratchGPR = scratch.gpr();
 
+            GPRReg op1SaveGPR;
+            if (op1Gpr == X86Registers::eax || op1Gpr == X86Registers::edx) {
+                op1SaveGPR = allocate();
+                ASSERT(op1Gpr != op1SaveGPR);
+                m_jit.move(op1Gpr, op1SaveGPR);
+            } else
+                op1SaveGPR = op1Gpr;
+            ASSERT(op1SaveGPR != X86Registers::eax);
+            ASSERT(op1SaveGPR != X86Registers::edx);
+
             m_jit.move(op1Gpr, eax.gpr());
             m_jit.move(TrustedImm32(divisor), scratchGPR);
+            if (divisor == -1)
+                speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(JITCompiler::Equal, eax.gpr(), TrustedImm32(-2147483647-1)));
             m_jit.assembler().cdq();
             m_jit.assembler().idivl_r(scratchGPR);
+            // Check that we're not about to create negative zero.
+            // FIXME: if the node use doesn't care about neg zero, we can do this more easily.
+            JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op1SaveGPR, TrustedImm32(0));
+            speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::Zero, edx.gpr()));
+            numeratorPositive.link(&m_jit);
+            
+            if (op1SaveGPR != op1Gpr)
+                unlock(op1SaveGPR);
+
             integerResult(edx.gpr(), m_compileIndex);
             return;
         }
-#endif
-        // Fallback to non-constant case but avoid unnecessary checks.
-        shouldGeneratePowerOfTwoCheck = false;
     }
+#endif
 
     SpeculateIntegerOperand op2(this, node.child2());
-    GPRReg op2Gpr = op2.gpr();
-
-    speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::Zero, op2Gpr));
-
 #if CPU(X86) || CPU(X86_64)
     GPRTemporary eax(this, X86Registers::eax);
     GPRTemporary edx(this, X86Registers::edx);
-    GPRReg temp2 = InvalidGPRReg;
-    if (op2Gpr == X86Registers::eax || op2Gpr == X86Registers::edx) {
-        temp2 = allocate();
-        m_jit.move(op2Gpr, temp2);
-        op2Gpr = temp2;
-    }
-    GPRReg resultGPR = edx.gpr();
-    GPRReg scratchGPR = eax.gpr();
-#else
-    GPRTemporary result(this);
-    GPRTemporary scratch(this);
-    GPRTemporary scratch3(this);
-    GPRReg scratchGPR3 = scratch3.gpr();
-    GPRReg resultGPR = result.gpr();
-    GPRReg scratchGPR = scratch.gpr();
-#endif
+    GPRReg op1GPR = op1.gpr();
+    GPRReg op2GPR = op2.gpr();
+    
+    GPRReg op2TempGPR;
+    GPRReg temp;
+    GPRReg op1SaveGPR;
+    
+    if (op2GPR == X86Registers::eax || op2GPR == X86Registers::edx) {
+        op2TempGPR = allocate();
+        temp = op2TempGPR;
+    } else {
+        op2TempGPR = InvalidGPRReg;
+        if (op1GPR == X86Registers::eax)
+            temp = X86Registers::edx;
+        else
+            temp = X86Registers::eax;
+    }
+    
+    if (op1GPR == X86Registers::eax || op1GPR == X86Registers::edx) {
+        op1SaveGPR = allocate();
+        ASSERT(op1GPR != op1SaveGPR);
+        m_jit.move(op1GPR, op1SaveGPR);
+    } else
+        op1SaveGPR = op1GPR;
+    
+    ASSERT(temp != op1GPR);
+    ASSERT(temp != op2GPR);
+    ASSERT(op1SaveGPR != X86Registers::eax);
+    ASSERT(op1SaveGPR != X86Registers::edx);
+    
+    m_jit.add32(JITCompiler::TrustedImm32(1), op2GPR, temp);
+    
+    JITCompiler::Jump safeDenominator = m_jit.branch32(JITCompiler::Above, temp, JITCompiler::TrustedImm32(1));
+    
+    JITCompiler::Jump done;
+    // FIXME: if the node is not used as number then we can do this more easily.
+    speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::Zero, op2GPR));
+    speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(JITCompiler::Equal, op1GPR, TrustedImm32(-2147483647-1)));
+    
+    safeDenominator.link(&m_jit);
+            
+    if (op2TempGPR != InvalidGPRReg) {
+        m_jit.move(op2GPR, op2TempGPR);
+        op2GPR = op2TempGPR;
+    }
+            
+    m_jit.move(op1GPR, eax.gpr());
+    m_jit.assembler().cdq();
+    m_jit.assembler().idivl_r(op2GPR);
+            
+    if (op2TempGPR != InvalidGPRReg)
+        unlock(op2TempGPR);
 
-    GPRTemporary scratch2(this);
-    GPRReg scratchGPR2 = scratch2.gpr();
-    JITCompiler::JumpList exitBranch;
+    // Check that we're not about to create negative zero.
+    // FIXME: if the node use doesn't care about neg zero, we can do this more easily.
+    JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op1SaveGPR, TrustedImm32(0));
+    speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::Zero, edx.gpr()));
+    numeratorPositive.link(&m_jit);
+    
+    if (op1SaveGPR != op1GPR)
+        unlock(op1SaveGPR);
+            
+    integerResult(edx.gpr(), m_compileIndex);
+#else // CPU(X86) || CPU(X86_64) --> so not X86
+    // Do this the *safest* way possible: call out to a C function that will do the modulo,
+    // and then attempt to convert back.
+    GPRReg op1GPR = op1.gpr();
+    GPRReg op2GPR = op2.gpr();
+    
+    FPRResult result(this);
+    
+    flushRegisters();
+    callOperation(operationFModOnInts, result.fpr(), op1GPR, op2GPR);
+    
+    FPRTemporary scratch(this);
+    GPRTemporary intResult(this);
+    JITCompiler::JumpList failureCases;
+    m_jit.branchConvertDoubleToInt32(result.fpr(), intResult.gpr(), failureCases, scratch.fpr());
+    speculationCheck(Overflow, JSValueRegs(), NoNode, failureCases);
+    
+    integerResult(intResult.gpr(), m_compileIndex);
+#endif // CPU(X86) || CPU(X86_64)
+}
 
-    // resultGPR is to hold the ABS value of the dividend before final result is produced
-    m_jit.move(op1Gpr, resultGPR);
-    // scratchGPR2 is to hold the ABS value of the divisor
-    m_jit.move(op2Gpr, scratchGPR2);
+void SpeculativeJIT::compileAdd(Node& node)
+{
+    if (m_jit.graph().addShouldSpeculateInteger(node)) {
+        if (isNumberConstant(node.child1().index())) {
+            int32_t imm1 = valueOfNumberConstantAsInt32(node.child1().index());
+            SpeculateIntegerOperand op2(this, node.child2());
+            GPRTemporary result(this);
 
-    // Check for negative result remainder
-    // According to ECMA-262, the sign of the result equals the sign of the dividend
-    JITCompiler::Jump positiveDividend = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op1Gpr, TrustedImm32(0));
-    m_jit.neg32(resultGPR);
-    m_jit.move(TrustedImm32(1), scratchGPR);
-    JITCompiler::Jump saveCondition = m_jit.jump();
+            if (nodeCanTruncateInteger(node.arithNodeFlags())) {
+                m_jit.move(op2.gpr(), result.gpr());
+                m_jit.add32(Imm32(imm1), result.gpr());
+            } else
+                speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchAdd32(MacroAssembler::Overflow, op2.gpr(), Imm32(imm1), result.gpr()));
 
-    positiveDividend.link(&m_jit);
-    m_jit.move(TrustedImm32(0), scratchGPR);
+            integerResult(result.gpr(), m_compileIndex);
+            return;
+        }
+                
+        if (isNumberConstant(node.child2().index())) {
+            SpeculateIntegerOperand op1(this, node.child1());
+            int32_t imm2 = valueOfNumberConstantAsInt32(node.child2().index());
+            GPRTemporary result(this);
+                
+            if (nodeCanTruncateInteger(node.arithNodeFlags())) {
+                m_jit.move(op1.gpr(), result.gpr());
+                m_jit.add32(Imm32(imm2), result.gpr());
+            } else
+                speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchAdd32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
 
-    // Save the condition for negative remainder
-    saveCondition.link(&m_jit);
-    m_jit.push(scratchGPR);
+            integerResult(result.gpr(), m_compileIndex);
+            return;
+        }
+                
+        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();
+
+        if (nodeCanTruncateInteger(node.arithNodeFlags())) {
+            if (gpr1 == gprResult)
+                m_jit.add32(gpr2, gprResult);
+            else {
+                m_jit.move(gpr2, gprResult);
+                m_jit.add32(gpr1, gprResult);
+            }
+        } else {
+            MacroAssembler::Jump check = m_jit.branchAdd32(MacroAssembler::Overflow, gpr1, gpr2, gprResult);
+                
+            if (gpr1 == gprResult)
+                speculationCheck(Overflow, JSValueRegs(), NoNode, check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr2));
+            else if (gpr2 == gprResult)
+                speculationCheck(Overflow, JSValueRegs(), NoNode, check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr1));
+            else
+                speculationCheck(Overflow, JSValueRegs(), NoNode, check);
+        }
 
-    JITCompiler::Jump positiveDivisor = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op2Gpr, TrustedImm32(0));
-    m_jit.neg32(scratchGPR2);
+        integerResult(gprResult, m_compileIndex);
+        return;
+    }
+        
+    if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2()))) {
+        SpeculateDoubleOperand op1(this, node.child1());
+        SpeculateDoubleOperand op2(this, node.child2());
+        FPRTemporary result(this, op1, op2);
 
-    positiveDivisor.link(&m_jit);
-    exitBranch.append(m_jit.branch32(JITCompiler::LessThan, resultGPR, scratchGPR2));
+        FPRReg reg1 = op1.fpr();
+        FPRReg reg2 = op2.fpr();
+        m_jit.addDouble(reg1, reg2, result.fpr());
 
-    // Power of two fast case
-    if (shouldGeneratePowerOfTwoCheck) {
-        m_jit.move(scratchGPR2, scratchGPR);
-        m_jit.sub32(TrustedImm32(1), scratchGPR);
-        JITCompiler::Jump notPowerOfTwo = m_jit.branchTest32(JITCompiler::NonZero, scratchGPR, scratchGPR2);
-        m_jit.and32(scratchGPR, resultGPR);
-        exitBranch.append(m_jit.jump());
+        doubleResult(result.fpr(), m_compileIndex);
+        return;
+    }
 
-        notPowerOfTwo.link(&m_jit);
+    if (node.op() == ValueAdd) {
+        compileValueAdd(node);
+        return;
     }
+    
+    // We don't handle this yet. :-(
+    terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+}
 
-#if CPU(X86) || CPU(X86_64)
-    m_jit.move(resultGPR, eax.gpr());
-    m_jit.assembler().cdq();
-    m_jit.assembler().idivl_r(scratchGPR2);
-#elif CPU(ARM_THUMB2)
-    m_jit.countLeadingZeros32(scratchGPR2, scratchGPR);
-    m_jit.countLeadingZeros32(resultGPR, scratchGPR3);
-    m_jit.sub32(scratchGPR3, scratchGPR);
+void SpeculativeJIT::compileArithSub(Node& node)
+{
+    if (m_jit.graph().addShouldSpeculateInteger(node)) {
+        if (isNumberConstant(node.child2().index())) {
+            SpeculateIntegerOperand op1(this, node.child1());
+            int32_t imm2 = valueOfNumberConstantAsInt32(node.child2().index());
+            GPRTemporary result(this);
 
-    JITCompiler::Jump useFullTable = m_jit.branch32(JITCompiler::Equal, scratchGPR, TrustedImm32(31));
+            if (nodeCanTruncateInteger(node.arithNodeFlags())) {
+                m_jit.move(op1.gpr(), result.gpr());
+                m_jit.sub32(Imm32(imm2), result.gpr());
+            } else {
+#if ENABLE(JIT_CONSTANT_BLINDING)
+                GPRTemporary scratch(this);
+                speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr(), scratch.gpr()));
+#else
+                speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
+#endif
+            }
 
-    m_jit.neg32(scratchGPR);
-    m_jit.add32(TrustedImm32(31), scratchGPR);
+            integerResult(result.gpr(), m_compileIndex);
+            return;
+        }
+            
+        if (isNumberConstant(node.child1().index())) {
+            int32_t imm1 = valueOfNumberConstantAsInt32(node.child1().index());
+            SpeculateIntegerOperand op2(this, node.child2());
+            GPRTemporary result(this);
+                
+            m_jit.move(Imm32(imm1), result.gpr());
+            if (nodeCanTruncateInteger(node.arithNodeFlags()))
+                m_jit.sub32(op2.gpr(), result.gpr());
+            else
+                speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchSub32(MacroAssembler::Overflow, op2.gpr(), result.gpr()));
+                
+            integerResult(result.gpr(), m_compileIndex);
+            return;
+        }
+            
+        SpeculateIntegerOperand op1(this, node.child1());
+        SpeculateIntegerOperand op2(this, node.child2());
+        GPRTemporary result(this);
 
-    int elementSizeByShift = -1;
-    elementSizeByShift = 3;
-    m_jit.relativeTableJump(scratchGPR, elementSizeByShift);
+        if (nodeCanTruncateInteger(node.arithNodeFlags())) {
+            m_jit.move(op1.gpr(), result.gpr());
+            m_jit.sub32(op2.gpr(), result.gpr());
+        } else
+            speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), op2.gpr(), result.gpr()));
 
-    useFullTable.link(&m_jit);
-    // Modulo table
-    for (int i = 31; i > 0; --i) {
-        ShiftTypeAndAmount shift(SRType_LSL, i);
-        m_jit.assembler().sub_S(scratchGPR, resultGPR, scratchGPR2, shift);
-        m_jit.assembler().it(ARMv7Assembler::ConditionCS);
-        m_jit.assembler().mov(resultGPR, scratchGPR);
+        integerResult(result.gpr(), m_compileIndex);
+        return;
     }
+        
+    SpeculateDoubleOperand op1(this, node.child1());
+    SpeculateDoubleOperand op2(this, node.child2());
+    FPRTemporary result(this, op1);
 
-    JITCompiler::Jump lower = m_jit.branch32(JITCompiler::Below, resultGPR, scratchGPR2);
-    m_jit.sub32(scratchGPR2, resultGPR);
-    lower.link(&m_jit);
-#endif // CPU(X86) || CPU(X86_64)
+    FPRReg reg1 = op1.fpr();
+    FPRReg reg2 = op2.fpr();
+    m_jit.subDouble(reg1, reg2, result.fpr());
 
-    exitBranch.link(&m_jit);
+    doubleResult(result.fpr(), m_compileIndex);
+}
 
-    // Check for negative remainder
-    m_jit.pop(scratchGPR);
-    JITCompiler::Jump positiveResult = m_jit.branch32(JITCompiler::Equal, scratchGPR, TrustedImm32(0));
-    m_jit.neg32(resultGPR);
-    positiveResult.link(&m_jit);
+void SpeculativeJIT::compileArithNegate(Node& node)
+{
+    if (m_jit.graph().negateShouldSpeculateInteger(node)) {
+        SpeculateIntegerOperand op1(this, node.child1());
+        GPRTemporary result(this);
 
-    integerResult(resultGPR, m_compileIndex);
+        m_jit.move(op1.gpr(), result.gpr());
 
-#if CPU(X86) || CPU(X86_64)
-    if (temp2 != InvalidGPRReg)
-        unlock(temp2);
-#endif
+        if (nodeCanTruncateInteger(node.arithNodeFlags()))
+            m_jit.neg32(result.gpr());
+        else {
+            speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchNeg32(MacroAssembler::Overflow, result.gpr()));
+            if (!nodeCanIgnoreNegativeZero(node.arithNodeFlags()))
+                speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(MacroAssembler::Zero, result.gpr()));
+        }
+
+        integerResult(result.gpr(), m_compileIndex);
+        return;
+    }
+        
+    SpeculateDoubleOperand op1(this, node.child1());
+    FPRTemporary result(this);
+
+    m_jit.negateDouble(op1.fpr(), result.fpr());
+
+    doubleResult(result.fpr(), m_compileIndex);
 }
 
 void SpeculativeJIT::compileArithMul(Node& node)
 {
-    if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) {
+    if (m_jit.graph().mulShouldSpeculateInteger(node)) {
         SpeculateIntegerOperand op1(this, node.child1());
         SpeculateIntegerOperand op2(this, node.child2());
         GPRTemporary result(this);
@@ -2132,15 +2651,17 @@ void SpeculativeJIT::compileArithMul(Node& node)
         GPRReg reg1 = op1.gpr();
         GPRReg reg2 = op2.gpr();
 
-        // What is unfortunate is that we cannot take advantage of nodeCanTruncateInteger()
-        // here. A multiply on integers performed in the double domain and then truncated to
-        // an integer will give a different result than a multiply performed in the integer
-        // domain and then truncated, if the integer domain result would have resulted in
-        // something bigger than what a 32-bit integer can hold. JavaScript mandates that
-        // the semantics are always as if the multiply had been performed in the double
-        // domain.
-            
-        speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchMul32(MacroAssembler::Overflow, reg1, reg2, result.gpr()));
+        // We can perform truncated multiplications if we get to this point, because if the
+        // fixup phase could not prove that it would be safe, it would have turned us into
+        // a double multiplication.
+        if (nodeCanTruncateInteger(node.arithNodeFlags())) {
+            m_jit.move(reg1, result.gpr());
+            m_jit.mul32(reg2, result.gpr());
+        } else {
+            speculationCheck(
+                Overflow, JSValueRegs(), NoNode,
+                m_jit.branchMul32(MacroAssembler::Overflow, reg1, reg2, result.gpr()));
+        }
             
         // Check for negative zero, if the users of this node care about such things.
         if (!nodeCanIgnoreNegativeZero(node.arithNodeFlags())) {
@@ -2166,9 +2687,85 @@ void SpeculativeJIT::compileArithMul(Node& node)
     doubleResult(result.fpr(), m_compileIndex);
 }
 
+#if CPU(X86) || CPU(X86_64)
+void SpeculativeJIT::compileIntegerArithDivForX86(Node& node)
+{
+    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();
+    
+    GPRReg op2TempGPR;
+    GPRReg temp;
+    if (op2GPR == X86Registers::eax || op2GPR == X86Registers::edx) {
+        op2TempGPR = allocate();
+        temp = op2TempGPR;
+    } else {
+        op2TempGPR = InvalidGPRReg;
+        if (op1GPR == X86Registers::eax)
+            temp = X86Registers::edx;
+        else
+            temp = X86Registers::eax;
+    }
+    
+    ASSERT(temp != op1GPR);
+    ASSERT(temp != op2GPR);
+    
+    m_jit.add32(JITCompiler::TrustedImm32(1), op2GPR, temp);
+    
+    JITCompiler::Jump safeDenominator = m_jit.branch32(JITCompiler::Above, temp, JITCompiler::TrustedImm32(1));
+    
+    JITCompiler::Jump done;
+    if (nodeUsedAsNumber(node.arithNodeFlags())) {
+        speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::Zero, op2GPR));
+        speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(JITCompiler::Equal, op1GPR, TrustedImm32(-2147483647-1)));
+    } else {
+        JITCompiler::Jump zero = m_jit.branchTest32(JITCompiler::Zero, op2GPR);
+        JITCompiler::Jump notNeg2ToThe31 = m_jit.branch32(JITCompiler::Equal, op1GPR, TrustedImm32(-2147483647-1));
+        zero.link(&m_jit);
+        m_jit.move(TrustedImm32(0), eax.gpr());
+        done = m_jit.jump();
+        notNeg2ToThe31.link(&m_jit);
+    }
+    
+    safeDenominator.link(&m_jit);
+            
+    // If the user cares about negative zero, then speculate that we're not about
+    // to produce negative zero.
+    if (!nodeCanIgnoreNegativeZero(node.arithNodeFlags())) {
+        MacroAssembler::Jump numeratorNonZero = m_jit.branchTest32(MacroAssembler::NonZero, op1GPR);
+        speculationCheck(NegativeZero, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, op2GPR, TrustedImm32(0)));
+        numeratorNonZero.link(&m_jit);
+    }
+    
+    if (op2TempGPR != InvalidGPRReg) {
+        m_jit.move(op2GPR, op2TempGPR);
+        op2GPR = op2TempGPR;
+    }
+            
+    m_jit.move(op1GPR, eax.gpr());
+    m_jit.assembler().cdq();
+    m_jit.assembler().idivl_r(op2GPR);
+            
+    if (op2TempGPR != InvalidGPRReg)
+        unlock(op2TempGPR);
+
+    // Check that there was no remainder. If there had been, then we'd be obligated to
+    // produce a double result instead.
+    if (nodeUsedAsNumber(node.arithNodeFlags()))
+        speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::NonZero, edx.gpr()));
+    else
+        done.link(&m_jit);
+            
+    integerResult(eax.gpr(), m_compileIndex);
+}
+#endif // CPU(X86) || CPU(X86_64)
+
 void SpeculativeJIT::compileArithMod(Node& node)
 {
-    if (!at(node.child1()).shouldNotSpeculateInteger() && !at(node.child2()).shouldNotSpeculateInteger()
+    if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2()))
         && node.canSpeculateInteger()) {
         compileSoftModulo(node);
         return;
@@ -2195,26 +2792,71 @@ bool SpeculativeJIT::compare(Node& node, MacroAssembler::RelationalCondition con
     if (compilePeepHoleBranch(node, condition, doubleCondition, operation))
         return true;
 
-    if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())))
+    if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2()))) {
         compileIntegerCompare(node, condition);
-    else if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2())))
+        return false;
+    }
+    
+    if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2()))) {
         compileDoubleCompare(node, doubleCondition);
-    else if (node.op == CompareEq && Node::shouldSpeculateFinalObject(at(node.child1()), at(node.child2())))
-        compileObjectEquality(node, &JSFinalObject::s_info, isFinalObjectPrediction);
-    else if (node.op == CompareEq && Node::shouldSpeculateArray(at(node.child1()), at(node.child2())))
-        compileObjectEquality(node, &JSArray::s_info, isArrayPrediction);
-    else
-        nonSpeculativeNonPeepholeCompare(node, condition, operation);
+        return false;
+    }
+    
+    if (node.op() == CompareEq) {
+        if (Node::shouldSpeculateFinalObject(at(node.child1()), at(node.child2()))) {
+            compileObjectEquality(node, &JSFinalObject::s_info, isFinalObjectSpeculation);
+            return false;
+        }
+        
+        if (Node::shouldSpeculateArray(at(node.child1()), at(node.child2()))) {
+            compileObjectEquality(node, &JSArray::s_info, isArraySpeculation);
+            return false;
+        }
+        
+        if (at(node.child1()).shouldSpeculateFinalObject()
+            && at(node.child2()).shouldSpeculateFinalObjectOrOther()) {
+            compileObjectToObjectOrOtherEquality(
+                node.child1(), node.child2(), &JSFinalObject::s_info,
+                isFinalObjectSpeculation);
+            return false;
+        }
+        
+        if (at(node.child1()).shouldSpeculateFinalObjectOrOther()
+            && at(node.child2()).shouldSpeculateFinalObject()) {
+            compileObjectToObjectOrOtherEquality(
+                node.child2(), node.child1(), &JSFinalObject::s_info,
+                isFinalObjectSpeculation);
+            return false;
+        }
+        
+        if (at(node.child1()).shouldSpeculateArray()
+            && at(node.child2()).shouldSpeculateArrayOrOther()) {
+            compileObjectToObjectOrOtherEquality(
+                node.child1(), node.child2(), &JSArray::s_info,
+                isArraySpeculation);
+            return false;
+        }
+        
+        if (at(node.child1()).shouldSpeculateArrayOrOther()
+            && at(node.child2()).shouldSpeculateArray()) {
+            compileObjectToObjectOrOtherEquality(
+                node.child2(), node.child1(), &JSArray::s_info,
+                isArraySpeculation);
+            return false;
+        }
+    }
     
+    nonSpeculativeNonPeepholeCompare(node, condition, operation);
     return false;
 }
 
-bool SpeculativeJIT::compileStrictEqForConstant(Node& node, NodeIndex value, JSValue constant)
+bool SpeculativeJIT::compileStrictEqForConstant(Node& node, Edge value, JSValue constant)
 {
     JSValueOperand op1(this, value);
     
-    NodeIndex branchNodeIndex = detectPeepHoleBranch();
-    if (branchNodeIndex != NoNode) {
+    unsigned branchIndexInBlock = detectPeepHoleBranch();
+    if (branchIndexInBlock != UINT_MAX) {
+        NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
         Node& branchNode = at(branchNodeIndex);
         BlockIndex taken = branchNode.takenBlockIndex();
         BlockIndex notTaken = branchNode.notTakenBlockIndex();
@@ -2222,7 +2864,7 @@ bool SpeculativeJIT::compileStrictEqForConstant(Node& node, NodeIndex value, JSV
         
         // 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.
-        if (taken == (m_block + 1)) {
+        if (taken == nextBlock()) {
             condition = MacroAssembler::NotEqual;
             BlockIndex tmp = taken;
             taken = notTaken;
@@ -2230,27 +2872,27 @@ bool SpeculativeJIT::compileStrictEqForConstant(Node& node, NodeIndex value, JSV
         }
 
 #if USE(JSVALUE64)
-        addBranch(m_jit.branchPtr(condition, op1.gpr(), MacroAssembler::TrustedImmPtr(bitwise_cast<void*>(JSValue::encode(constant)))), taken);
+        branchPtr(condition, op1.gpr(), MacroAssembler::TrustedImmPtr(bitwise_cast<void*>(JSValue::encode(constant))), taken);
 #else
         GPRReg payloadGPR = op1.payloadGPR();
         GPRReg tagGPR = op1.tagGPR();
         if (condition == MacroAssembler::Equal) {
             // Drop down if not equal, go elsewhere if equal.
             MacroAssembler::Jump notEqual = m_jit.branch32(MacroAssembler::NotEqual, tagGPR, MacroAssembler::Imm32(constant.tag()));
-            addBranch(m_jit.branch32(MacroAssembler::Equal, payloadGPR, MacroAssembler::Imm32(constant.payload())), taken);
+            branch32(MacroAssembler::Equal, payloadGPR, MacroAssembler::Imm32(constant.payload()), taken);
             notEqual.link(&m_jit);
         } else {
             // Drop down if equal, go elsehwere if not equal.
-            addBranch(m_jit.branch32(MacroAssembler::NotEqual, tagGPR, MacroAssembler::Imm32(constant.tag())), taken);
-            addBranch(m_jit.branch32(MacroAssembler::NotEqual, payloadGPR, MacroAssembler::Imm32(constant.payload())), taken);
+            branch32(MacroAssembler::NotEqual, tagGPR, MacroAssembler::Imm32(constant.tag()), taken);
+            branch32(MacroAssembler::NotEqual, payloadGPR, MacroAssembler::Imm32(constant.payload()), taken);
         }
 #endif
         
-        if (notTaken != (m_block + 1))
-            addBranch(m_jit.jump(), notTaken);
+        jump(notTaken);
         
         use(node.child1());
         use(node.child2());
+        m_indexInBlock = branchIndexInBlock;
         m_compileIndex = branchNodeIndex;
         return true;
     }
@@ -2262,18 +2904,18 @@ bool SpeculativeJIT::compileStrictEqForConstant(Node& node, NodeIndex value, JSV
     GPRReg resultGPR = result.gpr();
     m_jit.move(MacroAssembler::TrustedImmPtr(bitwise_cast<void*>(ValueFalse)), resultGPR);
     MacroAssembler::Jump notEqual = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, MacroAssembler::TrustedImmPtr(bitwise_cast<void*>(JSValue::encode(constant))));
-    m_jit.or32(MacroAssembler::Imm32(1), resultGPR);
+    m_jit.or32(MacroAssembler::TrustedImm32(1), resultGPR);
     notEqual.link(&m_jit);
     jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean);
 #else
     GPRReg op1PayloadGPR = op1.payloadGPR();
     GPRReg op1TagGPR = op1.tagGPR();
     GPRReg resultGPR = result.gpr();
-    m_jit.move(Imm32(0), resultGPR);
+    m_jit.move(TrustedImm32(0), resultGPR);
     MacroAssembler::JumpList notEqual;
     notEqual.append(m_jit.branch32(MacroAssembler::NotEqual, op1TagGPR, MacroAssembler::Imm32(constant.tag())));
     notEqual.append(m_jit.branch32(MacroAssembler::NotEqual, op1PayloadGPR, MacroAssembler::Imm32(constant.payload())));
-    m_jit.move(Imm32(1), resultGPR);
+    m_jit.move(TrustedImm32(1), resultGPR);
     notEqual.link(&m_jit);
     booleanResult(resultGPR, m_compileIndex);
 #endif
@@ -2286,14 +2928,14 @@ bool SpeculativeJIT::compileStrictEq(Node& node)
     // 1) If either operand is a constant and that constant is not a double, integer,
     //    or string, then do a JSValue comparison.
     
-    if (isJSConstant(node.child1())) {
-        JSValue value = valueOfJSConstant(node.child1());
+    if (isJSConstant(node.child1().index())) {
+        JSValue value = valueOfJSConstant(node.child1().index());
         if (!value.isNumber() && !value.isString())
             return compileStrictEqForConstant(node, node.child2(), value);
     }
     
-    if (isJSConstant(node.child2())) {
-        JSValue value = valueOfJSConstant(node.child2());
+    if (isJSConstant(node.child2().index())) {
+        JSValue value = valueOfJSConstant(node.child2().index());
         if (!value.isNumber() && !value.isString())
             return compileStrictEqForConstant(node, node.child1(), value);
     }
@@ -2301,11 +2943,13 @@ bool SpeculativeJIT::compileStrictEq(Node& node)
     // 2) If the operands are predicted integer, do an integer comparison.
     
     if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2()))) {
-        NodeIndex branchNodeIndex = detectPeepHoleBranch();
-        if (branchNodeIndex != NoNode) {
+        unsigned branchIndexInBlock = detectPeepHoleBranch();
+        if (branchIndexInBlock != UINT_MAX) {
+            NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
             compilePeepHoleIntegerBranch(node, branchNodeIndex, MacroAssembler::Equal);
             use(node.child1());
             use(node.child2());
+            m_indexInBlock = branchIndexInBlock;
             m_compileIndex = branchNodeIndex;
             return true;
         }
@@ -2316,11 +2960,13 @@ bool SpeculativeJIT::compileStrictEq(Node& node)
     // 3) If the operands are predicted double, do a double comparison.
     
     if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2()))) {
-        NodeIndex branchNodeIndex = detectPeepHoleBranch();
-        if (branchNodeIndex != NoNode) {
+        unsigned branchIndexInBlock = detectPeepHoleBranch();
+        if (branchIndexInBlock != UINT_MAX) {
+            NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
             compilePeepHoleDoubleBranch(node, branchNodeIndex, MacroAssembler::DoubleEqual);
             use(node.child1());
             use(node.child2());
+            m_indexInBlock = branchIndexInBlock;
             m_compileIndex = branchNodeIndex;
             return true;
         }
@@ -2332,28 +2978,32 @@ bool SpeculativeJIT::compileStrictEq(Node& node)
     //    or array comparison.
     
     if (Node::shouldSpeculateFinalObject(at(node.child1()), at(node.child2()))) {
-        NodeIndex branchNodeIndex = detectPeepHoleBranch();
-        if (branchNodeIndex != NoNode) {
-            compilePeepHoleObjectEquality(node, branchNodeIndex, &JSFinalObject::s_info, isFinalObjectPrediction);
+        unsigned branchIndexInBlock = detectPeepHoleBranch();
+        if (branchIndexInBlock != UINT_MAX) {
+            NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
+            compilePeepHoleObjectEquality(node, branchNodeIndex, &JSFinalObject::s_info, isFinalObjectSpeculation);
             use(node.child1());
             use(node.child2());
+            m_indexInBlock = branchIndexInBlock;
             m_compileIndex = branchNodeIndex;
             return true;
         }
-        compileObjectEquality(node, &JSFinalObject::s_info, isFinalObjectPrediction);
+        compileObjectEquality(node, &JSFinalObject::s_info, isFinalObjectSpeculation);
         return false;
     }
     
     if (Node::shouldSpeculateArray(at(node.child1()), at(node.child2()))) {
-        NodeIndex branchNodeIndex = detectPeepHoleBranch();
-        if (branchNodeIndex != NoNode) {
-            compilePeepHoleObjectEquality(node, branchNodeIndex, &JSArray::s_info, isArrayPrediction);
+        unsigned branchIndexInBlock = detectPeepHoleBranch();
+        if (branchIndexInBlock != UINT_MAX) {
+            NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
+            compilePeepHoleObjectEquality(node, branchNodeIndex, &JSArray::s_info, isArraySpeculation);
             use(node.child1());
             use(node.child2());
+            m_indexInBlock = branchIndexInBlock;
             m_compileIndex = branchNodeIndex;
             return true;
         }
-        compileObjectEquality(node, &JSArray::s_info, isArrayPrediction);
+        compileObjectEquality(node, &JSArray::s_info, isArraySpeculation);
         return false;
     }
     
@@ -2364,11 +3014,16 @@ bool SpeculativeJIT::compileStrictEq(Node& node)
 
 void SpeculativeJIT::compileGetIndexedPropertyStorage(Node& node)
 {
+    if (!node.prediction() || !at(node.child1()).prediction() || !at(node.child2()).prediction()) {
+        terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode);
+        return;
+    }
+        
     SpeculateCellOperand base(this, node.child1());
     GPRReg baseReg = base.gpr();
     
-    PredictedType basePrediction = at(node.child2()).prediction();
-    if (!(basePrediction & PredictInt32) && basePrediction) {
+    SpeculatedType basePrediction = at(node.child2()).prediction();
+    if (!(basePrediction & SpecInt32) && basePrediction) {
         ASSERT_NOT_REACHED();
         terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
         noResult(m_compileIndex);
@@ -2377,8 +3032,10 @@ void SpeculativeJIT::compileGetIndexedPropertyStorage(Node& node)
     
     GPRTemporary storage(this);
     GPRReg storageReg = storage.gpr();
-    if (at(node.child1()).prediction() == PredictString) {
-        if (!isStringPrediction(m_state.forNode(node.child1()).m_type))
+    if (at(node.child1()).shouldSpeculateArguments()) {
+        ASSERT_NOT_REACHED();
+    } else if (at(node.child1()).prediction() == SpecString) {
+        if (!isStringSpeculation(m_state.forNode(node.child1()).m_type))
             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSString::s_info)));
 
         m_jit.loadPtr(MacroAssembler::Address(baseReg, JSString::offsetOfValue()), storageReg);
@@ -2387,58 +3044,235 @@ void SpeculativeJIT::compileGetIndexedPropertyStorage(Node& node)
         speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTest32(MacroAssembler::Zero, storageReg));
 
         m_jit.loadPtr(MacroAssembler::Address(storageReg, StringImpl::dataOffset()), storageReg);
-    } else if (at(node.child1()).shouldSpeculateByteArray()) {
-        if (!isByteArrayPrediction(m_state.forNode(node.child1()).m_type))
-            speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info)));
-        m_jit.loadPtr(MacroAssembler::Address(baseReg, JSByteArray::offsetOfStorage()), storageReg);
     } else if (at(node.child1()).shouldSpeculateInt8Array()) {
         const TypedArrayDescriptor& descriptor = m_jit.globalData()->int8ArrayDescriptor();
-        if (!isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type))
+        if (!isInt8ArraySpeculation(m_state.forNode(node.child1()).m_type))
             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
     } else if (at(node.child1()).shouldSpeculateInt16Array()) {
         const TypedArrayDescriptor& descriptor = m_jit.globalData()->int16ArrayDescriptor();
-        if (!isInt16ArrayPrediction(m_state.forNode(node.child1()).m_type))
+        if (!isInt16ArraySpeculation(m_state.forNode(node.child1()).m_type))
             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
     } else if (at(node.child1()).shouldSpeculateInt32Array()) {
         const TypedArrayDescriptor& descriptor = m_jit.globalData()->int32ArrayDescriptor();
-        if (!isInt32ArrayPrediction(m_state.forNode(node.child1()).m_type))
+        if (!isInt32ArraySpeculation(m_state.forNode(node.child1()).m_type))
             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
     } else if (at(node.child1()).shouldSpeculateUint8Array()) {
         const TypedArrayDescriptor& descriptor = m_jit.globalData()->uint8ArrayDescriptor();
-        if (!isUint8ArrayPrediction(m_state.forNode(node.child1()).m_type))
+        if (!isUint8ArraySpeculation(m_state.forNode(node.child1()).m_type))
             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
+    } else if (at(node.child1()).shouldSpeculateUint8ClampedArray()) {
+        const TypedArrayDescriptor& descriptor = m_jit.globalData()->uint8ClampedArrayDescriptor();
+        if (!isUint8ClampedArraySpeculation(m_state.forNode(node.child1()).m_type))
+            speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
+        m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
     } else if (at(node.child1()).shouldSpeculateUint16Array()) {
         const TypedArrayDescriptor& descriptor = m_jit.globalData()->uint16ArrayDescriptor();
-        if (!isUint16ArrayPrediction(m_state.forNode(node.child1()).m_type))
+        if (!isUint16ArraySpeculation(m_state.forNode(node.child1()).m_type))
             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
     } else if (at(node.child1()).shouldSpeculateUint32Array()) {
         const TypedArrayDescriptor& descriptor = m_jit.globalData()->uint32ArrayDescriptor();
-        if (!isUint32ArrayPrediction(m_state.forNode(node.child1()).m_type))
+        if (!isUint32ArraySpeculation(m_state.forNode(node.child1()).m_type))
             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
     } else if (at(node.child1()).shouldSpeculateFloat32Array()) {
         const TypedArrayDescriptor& descriptor = m_jit.globalData()->float32ArrayDescriptor();
-        if (!isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type))
+        if (!isFloat32ArraySpeculation(m_state.forNode(node.child1()).m_type))
             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
     } else if (at(node.child1()).shouldSpeculateFloat64Array()) {
         const TypedArrayDescriptor& descriptor = m_jit.globalData()->float64ArrayDescriptor();
-        if (!isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type))
+        if (!isFloat64ArraySpeculation(m_state.forNode(node.child1()).m_type))
             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
     } else {
-        if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+        if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
         m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
     }
     storageResult(storageReg, m_compileIndex);
 }
 
+void SpeculativeJIT::compileGetByValOnArguments(Node& node)
+{
+    SpeculateCellOperand base(this, node.child1());
+    SpeculateStrictInt32Operand property(this, node.child2());
+    GPRTemporary result(this);
+#if USE(JSVALUE32_64)
+    GPRTemporary resultTag(this);
+#endif
+    GPRTemporary scratch(this);
+    
+    GPRReg baseReg = base.gpr();
+    GPRReg propertyReg = property.gpr();
+    GPRReg resultReg = result.gpr();
+#if USE(JSVALUE32_64)
+    GPRReg resultTagReg = resultTag.gpr();
+#endif
+    GPRReg scratchReg = scratch.gpr();
+    
+    if (!m_compileOkay)
+        return;
+    
+    if (!isArgumentsSpeculation(m_state.forNode(node.child1()).m_type)) {
+        speculationCheck(
+            BadType, JSValueSource::unboxedCell(baseReg), node.child1(),
+            m_jit.branchPtr(
+                MacroAssembler::NotEqual,
+                MacroAssembler::Address(baseReg, JSCell::classInfoOffset()),
+                MacroAssembler::TrustedImmPtr(&Arguments::s_info)));
+    }
+    
+    m_jit.loadPtr(
+        MacroAssembler::Address(baseReg, Arguments::offsetOfData()),
+        scratchReg);
+
+    // Two really lame checks.
+    speculationCheck(
+        Uncountable, JSValueSource(), NoNode,
+        m_jit.branchPtr(
+            MacroAssembler::AboveOrEqual, propertyReg,
+            MacroAssembler::Address(scratchReg, OBJECT_OFFSETOF(ArgumentsData, numArguments))));
+    speculationCheck(
+        Uncountable, JSValueSource(), NoNode,
+        m_jit.branchTestPtr(
+            MacroAssembler::NonZero,
+            MacroAssembler::Address(
+                scratchReg, OBJECT_OFFSETOF(ArgumentsData, deletedArguments))));
+    
+    m_jit.move(propertyReg, resultReg);
+    m_jit.neg32(resultReg);
+    m_jit.signExtend32ToPtr(resultReg, resultReg);
+    m_jit.loadPtr(
+        MacroAssembler::Address(scratchReg, OBJECT_OFFSETOF(ArgumentsData, registers)),
+        scratchReg);
+    
+#if USE(JSVALUE32_64)
+    m_jit.load32(
+        MacroAssembler::BaseIndex(
+            scratchReg, resultReg, MacroAssembler::TimesEight,
+            CallFrame::thisArgumentOffset() * sizeof(Register) - sizeof(Register) +
+            OBJECT_OFFSETOF(JSValue, u.asBits.tag)),
+        resultTagReg);
+    m_jit.load32(
+        MacroAssembler::BaseIndex(
+            scratchReg, resultReg, MacroAssembler::TimesEight,
+            CallFrame::thisArgumentOffset() * sizeof(Register) - sizeof(Register) +
+            OBJECT_OFFSETOF(JSValue, u.asBits.payload)),
+        resultReg);
+    jsValueResult(resultTagReg, resultReg, m_compileIndex);
+#else
+    m_jit.loadPtr(
+        MacroAssembler::BaseIndex(
+            scratchReg, resultReg, MacroAssembler::TimesEight,
+            CallFrame::thisArgumentOffset() * sizeof(Register) - sizeof(Register)),
+        resultReg);
+    jsValueResult(resultReg, m_compileIndex);
+#endif
+}
+
+void SpeculativeJIT::compileGetArgumentsLength(Node& node)
+{
+    SpeculateCellOperand base(this, node.child1());
+    GPRTemporary result(this, base);
+    
+    GPRReg baseReg = base.gpr();
+    GPRReg resultReg = result.gpr();
+    
+    if (!m_compileOkay)
+        return;
+    
+    if (!isArgumentsSpeculation(m_state.forNode(node.child1()).m_type)) {
+        speculationCheck(
+            BadType, JSValueSource::unboxedCell(baseReg), node.child1(),
+            m_jit.branchPtr(
+                MacroAssembler::NotEqual,
+                MacroAssembler::Address(baseReg, JSCell::classInfoOffset()),
+                MacroAssembler::TrustedImmPtr(&Arguments::s_info)));
+    }
+    
+    m_jit.loadPtr(
+        MacroAssembler::Address(baseReg, Arguments::offsetOfData()),
+        resultReg);
+
+    speculationCheck(
+        Uncountable, JSValueSource(), NoNode,
+        m_jit.branchTest8(
+            MacroAssembler::NonZero,
+            MacroAssembler::Address(resultReg, OBJECT_OFFSETOF(ArgumentsData, overrodeLength))));
+    
+    m_jit.load32(
+        MacroAssembler::Address(resultReg, OBJECT_OFFSETOF(ArgumentsData, numArguments)),
+        resultReg);
+    integerResult(resultReg, m_compileIndex);
+}
+
+void SpeculativeJIT::compileNewFunctionNoCheck(Node& node)
+{
+    GPRResult result(this);
+    GPRReg resultGPR = result.gpr();
+    flushRegisters();
+    callOperation(
+        operationNewFunction, resultGPR, m_jit.codeBlock()->functionDecl(node.functionDeclIndex()));
+    cellResult(resultGPR, m_compileIndex);
+}
+
+void SpeculativeJIT::compileNewFunctionExpression(Node& node)
+{
+    GPRResult result(this);
+    GPRReg resultGPR = result.gpr();
+    flushRegisters();
+    callOperation(
+        operationNewFunctionExpression,
+        resultGPR,
+        m_jit.codeBlock()->functionExpr(node.functionExprIndex()));
+    cellResult(resultGPR, m_compileIndex);
+}
+
+bool SpeculativeJIT::compileRegExpExec(Node& node)
+{
+    unsigned branchIndexInBlock = detectPeepHoleBranch();
+    if (branchIndexInBlock == UINT_MAX)
+        return false;
+    NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
+    ASSERT(node.adjustedRefCount() == 1);
+
+    Node& branchNode = at(branchNodeIndex);
+    BlockIndex taken = branchNode.takenBlockIndex();
+    BlockIndex notTaken = branchNode.notTakenBlockIndex();
+    
+    bool invert = false;
+    if (taken == nextBlock()) {
+        invert = true;
+        BlockIndex tmp = taken;
+        taken = notTaken;
+        notTaken = tmp;
+    }
+
+    SpeculateCellOperand base(this, node.child1());
+    SpeculateCellOperand argument(this, node.child2());
+    GPRReg baseGPR = base.gpr();
+    GPRReg argumentGPR = argument.gpr();
+    
+    flushRegisters();
+    GPRResult result(this);
+    callOperation(operationRegExpTest, result.gpr(), baseGPR, argumentGPR);
+
+    branchTest32(invert ? JITCompiler::Zero : JITCompiler::NonZero, result.gpr(), taken);
+    jump(notTaken);
+
+    use(node.child1());
+    use(node.child2());
+    m_indexInBlock = branchIndexInBlock;
+    m_compileIndex = branchNodeIndex;
+
+    return true;
+}
+
 } } // namespace JSC::DFG
 
 #endif