Changeset 96379 in webkit


Ignore:
Timestamp:
Sep 29, 2011 5:09:46 PM (13 years ago)
Author:
barraclough@apple.com
Message:

Start refactoring DFGSpeculativeJIT
https://bugs.webkit.org/show_bug.cgi?id=69112

Reviewed by Oliver Hunt.

Again, move JSVALUE64 code into a DFJSpeculativeJIT64.cpp

(JSC::DFG::ValueSource::dump):
(JSC::DFG::ValueRecovery::dump):
(JSC::DFG::OSRExit::OSRExit):
(JSC::DFG::OSRExit::dump):
(JSC::DFG::SpeculativeJIT::compilePeepHoleDoubleBranch):
(JSC::DFG::SpeculativeJIT::compilePeepHoleObjectEquality):
(JSC::DFG::SpeculativeJIT::compilePeepHoleIntegerBranch):
(JSC::DFG::SpeculativeJIT::compile):
(JSC::DFG::SpeculativeJIT::checkArgumentTypes):
(JSC::DFG::SpeculativeJIT::computeValueRecoveryFor):

  • dfg/DFGSpeculativeJIT.h:

(JSC::DFG::SpeculativeJIT::emitAllocateJSFinalObject):

  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::compare):

  • dfg/DFGSpeculativeJIT64.cpp: Copied from Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp.

(JSC::DFG::SpeculativeJIT::fillSpeculateIntInternal):
(JSC::DFG::SpeculativeJIT::fillSpeculateCell):
(JSC::DFG::SpeculativeJIT::compile):

Location:
trunk/Source/JavaScriptCore
Files:
5 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r96377 r96379  
     12011-09-29  Gavin Barraclough  <barraclough@apple.com>
     2
     3        Start refactoring DFGSpeculativeJIT
     4        https://bugs.webkit.org/show_bug.cgi?id=69112
     5
     6        Reviewed by Oliver Hunt.
     7
     8        Again, move JSVALUE64 code into a DFJSpeculativeJIT64.cpp
     9
     10        * JavaScriptCore.xcodeproj/project.pbxproj:
     11        * dfg/DFGSpeculativeJIT.cpp:
     12        (JSC::DFG::ValueSource::dump):
     13        (JSC::DFG::ValueRecovery::dump):
     14        (JSC::DFG::OSRExit::OSRExit):
     15        (JSC::DFG::OSRExit::dump):
     16        (JSC::DFG::SpeculativeJIT::compilePeepHoleDoubleBranch):
     17        (JSC::DFG::SpeculativeJIT::compilePeepHoleObjectEquality):
     18        (JSC::DFG::SpeculativeJIT::compilePeepHoleIntegerBranch):
     19        (JSC::DFG::SpeculativeJIT::compile):
     20        (JSC::DFG::SpeculativeJIT::checkArgumentTypes):
     21        (JSC::DFG::SpeculativeJIT::computeValueRecoveryFor):
     22        * dfg/DFGSpeculativeJIT.h:
     23        (JSC::DFG::SpeculativeJIT::emitAllocateJSFinalObject):
     24        * dfg/DFGSpeculativeJIT32_64.cpp:
     25        (JSC::DFG::SpeculativeJIT::compare):
     26        * dfg/DFGSpeculativeJIT64.cpp: Copied from Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp.
     27        (JSC::DFG::SpeculativeJIT::fillSpeculateIntInternal):
     28        (JSC::DFG::SpeculativeJIT::fillSpeculateCell):
     29        (JSC::DFG::SpeculativeJIT::compile):
     30
    1312011-09-29  Gavin Barraclough  <barraclough@apple.com>
    232
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r96377 r96379  
    305305                86880F1F14328BB900B08D42 /* DFGSpeculativeJIT32_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86880F1B14328BB900B08D42 /* DFGSpeculativeJIT32_64.cpp */; };
    306306                86880F44143531A800B08D42 /* DFGJITCodeGenerator64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86880F43143531A700B08D42 /* DFGJITCodeGenerator64.cpp */; };
     307                86880F4D14353B2100B08D42 /* DFGSpeculativeJIT64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86880F4C14353B2100B08D42 /* DFGSpeculativeJIT64.cpp */; };
    307308                868BFA08117CEFD100B908B1 /* AtomicString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 868BFA00117CEFD100B908B1 /* AtomicString.cpp */; };
    308309                868BFA09117CEFD100B908B1 /* AtomicString.h in Headers */ = {isa = PBXBuildFile; fileRef = 868BFA01117CEFD100B908B1 /* AtomicString.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    10721073                86880F311434FFAF00B08D42 /* ChangeLog */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ChangeLog; sourceTree = "<group>"; };
    10731074                86880F43143531A700B08D42 /* DFGJITCodeGenerator64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGJITCodeGenerator64.cpp; path = dfg/DFGJITCodeGenerator64.cpp; sourceTree = "<group>"; };
     1075                86880F4C14353B2100B08D42 /* DFGSpeculativeJIT64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGSpeculativeJIT64.cpp; path = dfg/DFGSpeculativeJIT64.cpp; sourceTree = "<group>"; };
    10741076                868BFA00117CEFD100B908B1 /* AtomicString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AtomicString.cpp; path = text/AtomicString.cpp; sourceTree = "<group>"; };
    10751077                868BFA01117CEFD100B908B1 /* AtomicString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AtomicString.h; path = text/AtomicString.h; sourceTree = "<group>"; };
     
    23022304                                86EC9DC31328DF82002B2AD7 /* DFGSpeculativeJIT.h */,
    23032305                                86880F1B14328BB900B08D42 /* DFGSpeculativeJIT32_64.cpp */,
     2306                                86880F4C14353B2100B08D42 /* DFGSpeculativeJIT64.cpp */,
    23042307                        );
    23052308                        name = dfg;
     
    33853388                                86880F1F14328BB900B08D42 /* DFGSpeculativeJIT32_64.cpp in Sources */,
    33863389                                86880F44143531A800B08D42 /* DFGJITCodeGenerator64.cpp in Sources */,
     3390                                86880F4D14353B2100B08D42 /* DFGSpeculativeJIT64.cpp in Sources */,
    33873391                        );
    33883392                        runOnlyForDeploymentPostprocessing = 0;
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r96375 r96379  
    2929
    3030#if ENABLE(DFG_JIT)
    31 #if USE(JSVALUE64)
    3231
    3332namespace JSC { namespace DFG {
    34 
    35 template<bool strict>
    36 GPRReg SpeculativeJIT::fillSpeculateIntInternal(NodeIndex nodeIndex, DataFormat& returnFormat)
    37 {
    38 #if ENABLE(DFG_DEBUG_VERBOSE)
    39     fprintf(stderr, "SpecInt@%d   ", nodeIndex);
    40 #endif
    41     Node& node = m_jit.graph()[nodeIndex];
    42     VirtualRegister virtualRegister = node.virtualRegister();
    43     GenerationInfo& info = m_generationInfo[virtualRegister];
    44 
    45     switch (info.registerFormat()) {
    46     case DataFormatNone: {
    47         if (node.hasConstant() && !isInt32Constant(nodeIndex)) {
    48             terminateSpeculativeExecution();
    49             returnFormat = DataFormatInteger;
    50             return allocate();
    51         }
    52        
    53         GPRReg gpr = allocate();
    54 
    55         if (node.hasConstant()) {
    56             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
    57             ASSERT(isInt32Constant(nodeIndex));
    58             m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr);
    59             info.fillInteger(gpr);
    60             returnFormat = DataFormatInteger;
    61             return gpr;
    62         }
    63        
    64         DataFormat spillFormat = info.spillFormat();
    65         ASSERT(spillFormat & DataFormatJS);
    66        
    67         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
    68        
    69         if (spillFormat == DataFormatJSInteger) {
    70             // If we know this was spilled as an integer we can fill without checking.
    71             if (strict) {
    72                 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
    73                 info.fillInteger(gpr);
    74                 returnFormat = DataFormatInteger;
    75                 return gpr;
    76             }
    77             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
    78             info.fillJSValue(gpr, DataFormatJSInteger);
    79             returnFormat = DataFormatJSInteger;
    80             return gpr;
    81         }
    82         m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
    83 
    84         // Fill as JSValue, and fall through.
    85         info.fillJSValue(gpr, DataFormatJSInteger);
    86         m_gprs.unlock(gpr);
    87     }
    88 
    89     case DataFormatJS: {
    90         // Check the value is an integer.
    91         GPRReg gpr = info.gpr();
    92         m_gprs.lock(gpr);
    93         speculationCheck(m_jit.branchPtr(MacroAssembler::Below, gpr, GPRInfo::tagTypeNumberRegister));
    94         info.fillJSValue(gpr, DataFormatJSInteger);
    95         // If !strict we're done, return.
    96         if (!strict) {
    97             returnFormat = DataFormatJSInteger;
    98             return gpr;
    99         }
    100         // else fall through & handle as DataFormatJSInteger.
    101         m_gprs.unlock(gpr);
    102     }
    103 
    104     case DataFormatJSInteger: {
    105         // In a strict fill we need to strip off the value tag.
    106         if (strict) {
    107             GPRReg gpr = info.gpr();
    108             GPRReg result;
    109             // If the register has already been locked we need to take a copy.
    110             // If not, we'll zero extend in place, so mark on the info that this is now type DataFormatInteger, not DataFormatJSInteger.
    111             if (m_gprs.isLocked(gpr))
    112                 result = allocate();
    113             else {
    114                 m_gprs.lock(gpr);
    115                 info.fillInteger(gpr);
    116                 result = gpr;
    117             }
    118             m_jit.zeroExtend32ToPtr(gpr, result);
    119             returnFormat = DataFormatInteger;
    120             return result;
    121         }
    122 
    123         GPRReg gpr = info.gpr();
    124         m_gprs.lock(gpr);
    125         returnFormat = DataFormatJSInteger;
    126         return gpr;
    127     }
    128 
    129     case DataFormatInteger: {
    130         GPRReg gpr = info.gpr();
    131         m_gprs.lock(gpr);
    132         returnFormat = DataFormatInteger;
    133         return gpr;
    134     }
    135 
    136     case DataFormatDouble:
    137     case DataFormatCell:
    138     case DataFormatBoolean:
    139     case DataFormatJSDouble:
    140     case DataFormatJSCell:
    141     case DataFormatJSBoolean: {
    142         terminateSpeculativeExecution();
    143         returnFormat = DataFormatInteger;
    144         return allocate();
    145     }
    146        
    147     case DataFormatStorage:
    148         ASSERT_NOT_REACHED();
    149     }
    150 
    151     ASSERT_NOT_REACHED();
    152     return InvalidGPRReg;
    153 }
    15433
    15534#ifndef NDEBUG
     
    19069        fprintf(out, "%%%s", FPRInfo::debugName(fpr()));
    19170        break;
     71#if USE(JSVALUE32_64)
     72    case InPair:
     73        fprintf(out, "pair(%%%s, %%%s)", GPRInfo::debugName(tagGPR()), GPRInfo::debugName(payloadGPR()));
     74        break;
     75#endif
    19276    case DisplacedInRegisterFile:
    19377        fprintf(out, "*%d", virtualRegister());
     
    233117#endif
    234118
    235 GPRReg SpeculativeJIT::fillSpeculateInt(NodeIndex nodeIndex, DataFormat& returnFormat)
    236 {
    237     return fillSpeculateIntInternal<false>(nodeIndex, returnFormat);
    238 }
    239 
    240 GPRReg SpeculativeJIT::fillSpeculateIntStrict(NodeIndex nodeIndex)
    241 {
    242     DataFormat mustBeDataFormatInteger;
    243     GPRReg result = fillSpeculateIntInternal<true>(nodeIndex, mustBeDataFormatInteger);
    244     ASSERT(mustBeDataFormatInteger == DataFormatInteger);
    245     return result;
    246 }
    247 
    248 FPRReg SpeculativeJIT::fillSpeculateDouble(NodeIndex nodeIndex)
    249 {
    250 #if ENABLE(DFG_DEBUG_VERBOSE)
    251     fprintf(stderr, "SpecDouble@%d   ", nodeIndex);
    252 #endif
    253     Node& node = m_jit.graph()[nodeIndex];
    254     VirtualRegister virtualRegister = node.virtualRegister();
    255     GenerationInfo& info = m_generationInfo[virtualRegister];
    256 
    257     if (info.registerFormat() == DataFormatNone) {
    258         GPRReg gpr = allocate();
    259 
    260         if (node.hasConstant()) {
    261             if (isInt32Constant(nodeIndex)) {
    262                 FPRReg fpr = fprAllocate();
    263                 m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(static_cast<double>(valueOfInt32Constant(nodeIndex))))), gpr);
    264                 m_jit.movePtrToDouble(gpr, fpr);
    265                 unlock(gpr);
    266 
    267                 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
    268                 info.fillDouble(fpr);
    269                 return fpr;
    270             }
    271             if (isNumberConstant(nodeIndex)) {
    272                 FPRReg fpr = fprAllocate();
    273                 m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfNumberConstant(nodeIndex)))), gpr);
    274                 m_jit.movePtrToDouble(gpr, fpr);
    275                 unlock(gpr);
    276 
    277                 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
    278                 info.fillDouble(fpr);
    279                 return fpr;
    280             }
    281             terminateSpeculativeExecution();
    282             return fprAllocate();
    283         }
    284        
    285         DataFormat spillFormat = info.spillFormat();
    286         ASSERT(spillFormat & DataFormatJS);
    287         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
    288         m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
    289         info.fillJSValue(gpr, spillFormat);
    290         unlock(gpr);
    291     }
    292 
    293     switch (info.registerFormat()) {
    294     case DataFormatNone: // Should have filled, above.
    295     case DataFormatBoolean: // This type never occurs.
    296     case DataFormatStorage:
    297         ASSERT_NOT_REACHED();
    298        
    299     case DataFormatCell:
    300     case DataFormatJSCell:
    301     case DataFormatJS:
    302     case DataFormatJSBoolean: {
    303         GPRReg jsValueGpr = info.gpr();
    304         m_gprs.lock(jsValueGpr);
    305         FPRReg fpr = fprAllocate();
    306         GPRReg tempGpr = allocate();
    307 
    308         JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
    309 
    310         speculationCheck(m_jit.branchTestPtr(MacroAssembler::Zero, jsValueGpr, GPRInfo::tagTypeNumberRegister));
    311 
    312         // First, if we get here we have a double encoded as a JSValue
    313         m_jit.move(jsValueGpr, tempGpr);
    314         unboxDouble(tempGpr, fpr);
    315         JITCompiler::Jump hasUnboxedDouble = m_jit.jump();
    316 
    317         // Finally, handle integers.
    318         isInteger.link(&m_jit);
    319         m_jit.convertInt32ToDouble(jsValueGpr, fpr);
    320         hasUnboxedDouble.link(&m_jit);
    321 
    322         m_gprs.release(jsValueGpr);
    323         m_gprs.unlock(jsValueGpr);
    324         m_gprs.unlock(tempGpr);
    325         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
    326         info.fillDouble(fpr);
    327         info.killSpilled();
    328         return fpr;
    329     }
    330 
    331     case DataFormatJSInteger:
    332     case DataFormatInteger: {
    333         FPRReg fpr = fprAllocate();
    334         GPRReg gpr = info.gpr();
    335         m_gprs.lock(gpr);
    336         m_jit.convertInt32ToDouble(gpr, fpr);
    337         m_gprs.unlock(gpr);
    338         return fpr;
    339     }
    340 
    341     // Unbox the double
    342     case DataFormatJSDouble: {
    343         GPRReg gpr = info.gpr();
    344         FPRReg fpr = fprAllocate();
    345         if (m_gprs.isLocked(gpr)) {
    346             // Make sure we don't trample gpr if it is in use.
    347             GPRReg temp = allocate();
    348             m_jit.move(gpr, temp);
    349             unboxDouble(temp, fpr);
    350             unlock(temp);
    351         } else
    352             unboxDouble(gpr, fpr);
    353 
    354         m_gprs.release(gpr);
    355         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
    356 
    357         info.fillDouble(fpr);
    358         return fpr;
    359     }
    360 
    361     case DataFormatDouble: {
    362         FPRReg fpr = info.fpr();
    363         m_fprs.lock(fpr);
    364         return fpr;
    365     }
    366     }
    367 
    368     ASSERT_NOT_REACHED();
    369     return InvalidFPRReg;
    370 }
    371 
    372 GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex)
    373 {
    374 #if ENABLE(DFG_DEBUG_VERBOSE)
    375     fprintf(stderr, "SpecCell@%d   ", nodeIndex);
    376 #endif
    377     Node& node = m_jit.graph()[nodeIndex];
    378     VirtualRegister virtualRegister = node.virtualRegister();
    379     GenerationInfo& info = m_generationInfo[virtualRegister];
    380 
    381     switch (info.registerFormat()) {
    382     case DataFormatNone: {
    383         GPRReg gpr = allocate();
    384 
    385         if (node.hasConstant()) {
    386             JSValue jsValue = valueOfJSConstant(nodeIndex);
    387             if (jsValue.isCell()) {
    388                 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
    389                 m_jit.move(MacroAssembler::TrustedImmPtr(jsValue.asCell()), gpr);
    390                 info.fillJSValue(gpr, DataFormatJSCell);
    391                 return gpr;
    392             }
    393             terminateSpeculativeExecution();
    394             return gpr;
    395         }
    396         ASSERT(info.spillFormat() & DataFormatJS);
    397         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
    398         m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
    399 
    400         info.fillJSValue(gpr, DataFormatJS);
    401         if (info.spillFormat() != DataFormatJSCell)
    402             speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister));
    403         info.fillJSValue(gpr, DataFormatJSCell);
    404         return gpr;
    405     }
    406 
    407     case DataFormatCell:
    408     case DataFormatJSCell: {
    409         GPRReg gpr = info.gpr();
    410         m_gprs.lock(gpr);
    411         return gpr;
    412     }
    413 
    414     case DataFormatJS: {
    415         GPRReg gpr = info.gpr();
    416         m_gprs.lock(gpr);
    417         speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister));
    418         info.fillJSValue(gpr, DataFormatJSCell);
    419         return gpr;
    420     }
    421 
    422     case DataFormatJSInteger:
    423     case DataFormatInteger:
    424     case DataFormatJSDouble:
    425     case DataFormatDouble:
    426     case DataFormatJSBoolean:
    427     case DataFormatBoolean: {
    428         terminateSpeculativeExecution();
    429         return allocate();
    430     }
    431        
    432     case DataFormatStorage:
    433         ASSERT_NOT_REACHED();
    434     }
    435 
    436     ASSERT_NOT_REACHED();
    437     return InvalidGPRReg;
    438 }
    439 
    440 GPRReg SpeculativeJIT::fillSpeculateBoolean(NodeIndex nodeIndex)
    441 {
    442 #if ENABLE(DFG_DEBUG_VERBOSE)
    443     fprintf(stderr, "SpecBool@%d   ", nodeIndex);
    444 #endif
    445     Node& node = m_jit.graph()[nodeIndex];
    446     VirtualRegister virtualRegister = node.virtualRegister();
    447     GenerationInfo& info = m_generationInfo[virtualRegister];
    448 
    449     switch (info.registerFormat()) {
    450     case DataFormatNone: {
    451         GPRReg gpr = allocate();
    452 
    453         if (node.hasConstant()) {
    454             JSValue jsValue = valueOfJSConstant(nodeIndex);
    455             if (jsValue.isBoolean()) {
    456                 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
    457                 m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsValue)), gpr);
    458                 info.fillJSValue(gpr, DataFormatJSBoolean);
    459                 return gpr;
    460             }
    461             terminateSpeculativeExecution();
    462             return gpr;
    463         }
    464         ASSERT(info.spillFormat() & DataFormatJS);
    465         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
    466         m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
    467 
    468         info.fillJSValue(gpr, DataFormatJS);
    469         if (info.spillFormat() != DataFormatJSBoolean) {
    470             m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
    471             speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg));
    472             m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
    473         }
    474         info.fillJSValue(gpr, DataFormatJSBoolean);
    475         return gpr;
    476     }
    477 
    478     case DataFormatBoolean:
    479     case DataFormatJSBoolean: {
    480         GPRReg gpr = info.gpr();
    481         m_gprs.lock(gpr);
    482         return gpr;
    483     }
    484 
    485     case DataFormatJS: {
    486         GPRReg gpr = info.gpr();
    487         m_gprs.lock(gpr);
    488         m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
    489         speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg));
    490         m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
    491         info.fillJSValue(gpr, DataFormatJSBoolean);
    492         return gpr;
    493     }
    494 
    495     case DataFormatJSInteger:
    496     case DataFormatInteger:
    497     case DataFormatJSDouble:
    498     case DataFormatDouble:
    499     case DataFormatJSCell:
    500     case DataFormatCell: {
    501         terminateSpeculativeExecution();
    502         return allocate();
    503     }
    504        
    505     case DataFormatStorage:
    506         ASSERT_NOT_REACHED();
    507     }
    508 
    509     ASSERT_NOT_REACHED();
    510     return InvalidGPRReg;
     119void SpeculativeJIT::compilePeepHoleDoubleBranch(Node& node, NodeIndex branchNodeIndex, JITCompiler::DoubleCondition condition)
     120{
     121    Node& branchNode = m_jit.graph()[branchNodeIndex];
     122    BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
     123    BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
     124   
     125    SpeculateDoubleOperand op1(this, node.child1());
     126    SpeculateDoubleOperand op2(this, node.child2());
     127   
     128    addBranch(m_jit.branchDouble(condition, op1.fpr(), op2.fpr()), taken);
     129   
     130    if (notTaken != (m_block + 1))
     131        addBranch(m_jit.jump(), notTaken);
     132}
     133
     134void SpeculativeJIT::compilePeepHoleObjectEquality(Node& node, NodeIndex branchNodeIndex, void* vptr)
     135{
     136    Node& branchNode = m_jit.graph()[branchNodeIndex];
     137    BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
     138    BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
     139
     140    MacroAssembler::RelationalCondition condition = MacroAssembler::Equal;
     141   
     142    if (taken == (m_block + 1)) {
     143        condition = MacroAssembler::NotEqual;
     144        BlockIndex tmp = taken;
     145        taken = notTaken;
     146        notTaken = tmp;
     147    }
     148
     149    SpeculateCellOperand op1(this, node.child1());
     150    SpeculateCellOperand op2(this, node.child2());
     151   
     152    GPRReg op1GPR = op1.gpr();
     153    GPRReg op2GPR = op2.gpr();
     154   
     155    speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR), MacroAssembler::TrustedImmPtr(vptr)));
     156    speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR), MacroAssembler::TrustedImmPtr(vptr)));
     157   
     158    addBranch(m_jit.branchPtr(condition, op1GPR, op2GPR), taken);
     159    if (notTaken != (m_block + 1))
     160        addBranch(m_jit.jump(), notTaken);
    511161}
    512162
     
    545195}
    546196
    547 JITCompiler::Jump SpeculativeJIT::convertToDouble(GPRReg value, FPRReg result, GPRReg tmp)
    548 {
    549     JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, value, GPRInfo::tagTypeNumberRegister);
    550    
    551     JITCompiler::Jump notNumber = m_jit.branchTestPtr(MacroAssembler::Zero, value, GPRInfo::tagTypeNumberRegister);
    552    
    553     m_jit.move(value, tmp);
    554     unboxDouble(tmp, result);
    555    
    556     JITCompiler::Jump done = m_jit.jump();
    557    
    558     isInteger.link(&m_jit);
    559    
    560     m_jit.convertInt32ToDouble(value, result);
    561    
    562     done.link(&m_jit);
    563 
    564     return notNumber;
    565 }
    566 
    567 void SpeculativeJIT::compilePeepHoleDoubleBranch(Node& node, NodeIndex branchNodeIndex, JITCompiler::DoubleCondition condition)
    568 {
    569     Node& branchNode = m_jit.graph()[branchNodeIndex];
    570     BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
    571     BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
    572    
    573     SpeculateDoubleOperand op1(this, node.child1());
    574     SpeculateDoubleOperand op2(this, node.child2());
    575    
    576     addBranch(m_jit.branchDouble(condition, op1.fpr(), op2.fpr()), taken);
    577    
    578     if (notTaken != (m_block + 1))
    579         addBranch(m_jit.jump(), notTaken);
    580 }
    581 
    582 void SpeculativeJIT::compilePeepHoleObjectEquality(Node& node, NodeIndex branchNodeIndex, void* vptr)
    583 {
    584     Node& branchNode = m_jit.graph()[branchNodeIndex];
    585     BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
    586     BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
    587 
    588     MacroAssembler::RelationalCondition condition = MacroAssembler::Equal;
    589    
    590     if (taken == (m_block + 1)) {
    591         condition = MacroAssembler::NotEqual;
    592         BlockIndex tmp = taken;
    593         taken = notTaken;
    594         notTaken = tmp;
    595     }
    596 
    597     SpeculateCellOperand op1(this, node.child1());
    598     SpeculateCellOperand op2(this, node.child2());
    599    
    600     GPRReg op1GPR = op1.gpr();
    601     GPRReg op2GPR = op2.gpr();
    602    
    603     speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR), MacroAssembler::TrustedImmPtr(vptr)));
    604     speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR), MacroAssembler::TrustedImmPtr(vptr)));
    605    
    606     addBranch(m_jit.branchPtr(condition, op1GPR, op2GPR), taken);
    607     if (notTaken != (m_block + 1))
    608         addBranch(m_jit.jump(), notTaken);
    609 }
    610 
    611 void SpeculativeJIT::compileObjectEquality(Node& node, void* vptr)
    612 {
    613     SpeculateCellOperand op1(this, node.child1());
    614     SpeculateCellOperand op2(this, node.child2());
    615     GPRTemporary result(this, op1);
    616    
    617     GPRReg op1GPR = op1.gpr();
    618     GPRReg op2GPR = op2.gpr();
    619     GPRReg resultGPR = result.gpr();
    620    
    621     speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR), MacroAssembler::TrustedImmPtr(vptr)));
    622     speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR), MacroAssembler::TrustedImmPtr(vptr)));
    623    
    624     MacroAssembler::Jump falseCase = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, op2GPR);
    625     m_jit.move(Imm32(ValueTrue), resultGPR);
    626     MacroAssembler::Jump done = m_jit.jump();
    627     falseCase.link(&m_jit);
    628     m_jit.move(Imm32(ValueFalse), resultGPR);
    629     done.link(&m_jit);
    630 
    631     jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean);
    632 }
    633 
    634 // Returns true if the compare is fused with a subsequent branch.
    635 bool SpeculativeJIT::compare(Node& node, MacroAssembler::RelationalCondition condition, MacroAssembler::DoubleCondition doubleCondition, Z_DFGOperation_EJJ operation)
    636 {
    637     // Fused compare & branch.
    638     NodeIndex branchNodeIndex = detectPeepHoleBranch();
    639     if (branchNodeIndex != NoNode) {
    640         // detectPeepHoleBranch currently only permits the branch to be the very next node,
    641         // so can be no intervening nodes to also reference the compare.
    642         ASSERT(node.adjustedRefCount() == 1);
    643 
    644         if (shouldSpeculateInteger(node.child1(), node.child2())) {
    645             compilePeepHoleIntegerBranch(node, branchNodeIndex, condition);
    646             use(node.child1());
    647             use(node.child2());
    648         } else if (shouldSpeculateNumber(node.child1(), node.child2())) {
    649             compilePeepHoleDoubleBranch(node, branchNodeIndex, doubleCondition);
    650             use(node.child1());
    651             use(node.child2());
    652         } else if (node.op == CompareEq && shouldSpeculateFinalObject(node.child1(), node.child2())) {
    653             compilePeepHoleObjectEquality(node, branchNodeIndex, m_jit.globalData()->jsFinalObjectVPtr);
    654             use(node.child1());
    655             use(node.child2());
    656         } else if (node.op == CompareEq && shouldSpeculateArray(node.child1(), node.child2())) {
    657             compilePeepHoleObjectEquality(node, branchNodeIndex, m_jit.globalData()->jsArrayVPtr);
    658             use(node.child1());
    659             use(node.child2());
    660         } else
    661             nonSpeculativePeepholeBranch(node, branchNodeIndex, condition, operation);
    662 
    663         m_compileIndex = branchNodeIndex;
    664         return true;
    665     }
    666 
    667     if (shouldSpeculateInteger(node.child1(), node.child2())) {
    668         SpeculateIntegerOperand op1(this, node.child1());
    669         SpeculateIntegerOperand op2(this, node.child2());
    670         GPRTemporary result(this, op1, op2);
    671        
    672         m_jit.compare32(condition, op1.gpr(), op2.gpr(), result.gpr());
    673        
    674         // If we add a DataFormatBool, we should use it here.
    675         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
    676         jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
    677     } else if (shouldSpeculateNumber(node.child1(), node.child2())) {
    678         SpeculateDoubleOperand op1(this, node.child1());
    679         SpeculateDoubleOperand op2(this, node.child2());
    680         GPRTemporary result(this);
    681        
    682         m_jit.move(TrustedImm32(ValueTrue), result.gpr());
    683         MacroAssembler::Jump trueCase = m_jit.branchDouble(doubleCondition, op1.fpr(), op2.fpr());
    684         m_jit.xorPtr(Imm32(true), result.gpr());
    685         trueCase.link(&m_jit);
    686 
    687         jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
    688     } else if (node.op == CompareEq && shouldSpeculateFinalObject(node.child1(), node.child2()))
    689         compileObjectEquality(node, m_jit.globalData()->jsFinalObjectVPtr);
    690     else if (node.op == CompareEq && shouldSpeculateArray(node.child1(), node.child2()))
    691         compileObjectEquality(node, m_jit.globalData()->jsArrayVPtr);
    692     else
    693         nonSpeculativeNonPeepholeCompare(node, condition, operation);
    694    
    695     return false;
    696 }
    697 
    698 template<typename T>
    699 void SpeculativeJIT::emitAllocateJSFinalObject(T structure, GPRReg resultGPR, GPRReg scratchGPR, MacroAssembler::JumpList& slowPath)
    700 {
    701     MarkedSpace::SizeClass* sizeClass = &m_jit.globalData()->heap.sizeClassForObject(sizeof(JSFinalObject));
    702    
    703     m_jit.loadPtr(&sizeClass->firstFreeCell, resultGPR);
    704     slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, resultGPR));
    705    
    706     // The object is half-allocated: we have what we know is a fresh object, but
    707     // it's still on the GC's free list.
    708    
    709     // Ditch the structure by placing it into the structure slot, so that we can reuse
    710     // scratchGPR.
    711     m_jit.storePtr(structure, MacroAssembler::Address(resultGPR, JSObject::structureOffset()));
    712    
    713     // Now that we have scratchGPR back, remove the object from the free list
    714     m_jit.loadPtr(MacroAssembler::Address(resultGPR), scratchGPR);
    715     m_jit.storePtr(scratchGPR, &sizeClass->firstFreeCell);
    716    
    717     // Initialize the object's vtable
    718     m_jit.storePtr(MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsFinalObjectVPtr), MacroAssembler::Address(resultGPR));
    719    
    720     // Initialize the object's inheritorID.
    721     m_jit.storePtr(MacroAssembler::TrustedImmPtr(0), MacroAssembler::Address(resultGPR, JSObject::offsetOfInheritorID()));
    722    
    723     // Initialize the object's property storage pointer.
    724     m_jit.addPtr(MacroAssembler::TrustedImm32(sizeof(JSObject)), resultGPR, scratchGPR);
    725     m_jit.storePtr(scratchGPR, MacroAssembler::Address(resultGPR, JSFinalObject::offsetOfPropertyStorage()));
    726 }
    727 
    728 void SpeculativeJIT::compile(Node& node)
    729 {
    730     NodeType op = node.op;
    731 
    732     switch (op) {
    733     case JSConstant:
    734         initConstantInfo(m_compileIndex);
    735         break;
    736 
    737     case GetLocal: {
    738         PredictedType prediction = node.variableAccessData()->prediction();
    739 
    740         // If we have no prediction for this local, then don't attempt to compile.
    741         if (prediction == PredictNone) {
    742             terminateSpeculativeExecution();
    743             break;
    744         }
    745        
    746         GPRTemporary result(this);
    747         if (isInt32Prediction(prediction)) {
    748             m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr());
    749 
    750             // Like integerResult, but don't useChildren - our children are phi nodes,
    751             // and don't represent values within this dataflow with virtual registers.
    752             VirtualRegister virtualRegister = node.virtualRegister();
    753             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger);
    754             m_generationInfo[virtualRegister].initInteger(m_compileIndex, node.refCount(), result.gpr());
    755         } else {
    756             m_jit.loadPtr(JITCompiler::addressFor(node.local()), result.gpr());
    757 
    758             // Like jsValueResult, but don't useChildren - our children are phi nodes,
    759             // and don't represent values within this dataflow with virtual registers.
    760             VirtualRegister virtualRegister = node.virtualRegister();
    761             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
    762            
    763             DataFormat format;
    764             if (isArrayPrediction(prediction))
    765                 format = DataFormatJSCell;
    766             else if (isBooleanPrediction(prediction))
    767                 format = DataFormatJSBoolean;
    768             else
    769                 format = DataFormatJS;
    770            
    771             m_generationInfo[virtualRegister].initJSValue(m_compileIndex, node.refCount(), result.gpr(), format);
    772         }
    773         break;
    774     }
    775 
    776     case SetLocal: {
    777         // SetLocal doubles as a hint as to where a node will be stored and
    778         // as a speculation point. So before we speculate make sure that we
    779         // know where the child of this node needs to go in the virtual
    780         // register file.
    781         compileMovHint(node);
    782        
    783         // As far as OSR is concerned, we're on the bytecode index corresponding
    784         // to the *next* instruction, since we've already "executed" the
    785         // SetLocal and whatever other DFG Nodes are associated with the same
    786         // bytecode index as the SetLocal.
    787         ASSERT(m_bytecodeIndexForOSR == node.codeOrigin.bytecodeIndex());
    788         Node& nextNode = m_jit.graph()[m_compileIndex+1];
    789        
    790         // This assertion will fail if we ever emit multiple SetLocal's for
    791         // a single bytecode instruction. That's unlikely to happen. But if
    792         // it does, the solution is to to have this perform a search until
    793         // it finds a Node with a different bytecode index from the one we've
    794         // got, and to abstractly execute the SetLocal's along the way. Or,
    795         // better yet, handle all of the SetLocal's at once: abstract interpret
    796         // all of them, then emit code for all of them, with OSR exiting to
    797         // the next non-SetLocal instruction. Note the special case for when
    798         // both this SetLocal and the next op have a bytecode index of 0; this
    799         // occurs for SetLocal's generated at the top of the code block to
    800         // initialize locals to undefined. Ideally, we'd have a way of marking
    801         // in the CodeOrigin that a SetLocal is synthetic. This will make the
    802         // assertion more sensible-looking. We should then also assert that
    803         // synthetic SetLocal's don't have speculation checks, since they
    804         // should only be dropping values that we statically know we are
    805         // allowed to drop into the variables. DFGPropagator will guarantee
    806         // this, since it should have at least an approximation (if not
    807         // exact knowledge) of the type of the SetLocal's child node, and
    808         // should merge that information into the local that is being set.
    809         ASSERT(m_bytecodeIndexForOSR != nextNode.codeOrigin.bytecodeIndex()
    810                || (!m_bytecodeIndexForOSR && !nextNode.codeOrigin.bytecodeIndex()));
    811         m_bytecodeIndexForOSR = nextNode.codeOrigin.bytecodeIndex();
    812        
    813         PredictedType predictedType = node.variableAccessData()->prediction();
    814         if (isInt32Prediction(predictedType)) {
    815             SpeculateIntegerOperand value(this, node.child1());
    816             m_jit.store32(value.gpr(), JITCompiler::payloadFor(node.local()));
    817             noResult(m_compileIndex);
    818         } else if (isArrayPrediction(predictedType)) {
    819             SpeculateCellOperand cell(this, node.child1());
    820             GPRReg cellGPR = cell.gpr();
    821             speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
    822             m_jit.storePtr(cellGPR, JITCompiler::addressFor(node.local()));
    823             noResult(m_compileIndex);
    824         } else if (isBooleanPrediction(predictedType)) {
    825             SpeculateBooleanOperand boolean(this, node.child1());
    826             m_jit.storePtr(boolean.gpr(), JITCompiler::addressFor(node.local()));
    827             noResult(m_compileIndex);
    828         } else {
    829             JSValueOperand value(this, node.child1());
    830             m_jit.storePtr(value.gpr(), JITCompiler::addressFor(node.local()));
    831             noResult(m_compileIndex);
    832         }
    833        
    834         // Indicate that it's no longer necessary to retrieve the value of
    835         // this bytecode variable from registers or other locations in the register file.
    836         valueSourceReferenceForOperand(node.local()) = ValueSource::forPrediction(predictedType);
    837         break;
    838     }
    839        
    840     case SetArgument:
    841         // This is a no-op; it just marks the fact that the argument is being used.
    842         // But it may be profitable to use this as a hook to run speculation checks
    843         // on arguments, thereby allowing us to trivially eliminate such checks if
    844         // the argument is not used.
    845         break;
    846 
    847     case BitAnd:
    848     case BitOr:
    849     case BitXor:
    850         if (isInt32Constant(node.child1())) {
    851             SpeculateIntegerOperand op2(this, node.child2());
    852             GPRTemporary result(this, op2);
    853 
    854             bitOp(op, valueOfInt32Constant(node.child1()), op2.gpr(), result.gpr());
    855 
    856             integerResult(result.gpr(), m_compileIndex);
    857         } else if (isInt32Constant(node.child2())) {
    858             SpeculateIntegerOperand op1(this, node.child1());
    859             GPRTemporary result(this, op1);
    860 
    861             bitOp(op, valueOfInt32Constant(node.child2()), op1.gpr(), result.gpr());
    862 
    863             integerResult(result.gpr(), m_compileIndex);
    864         } else {
    865             SpeculateIntegerOperand op1(this, node.child1());
    866             SpeculateIntegerOperand op2(this, node.child2());
    867             GPRTemporary result(this, op1, op2);
    868 
    869             GPRReg reg1 = op1.gpr();
    870             GPRReg reg2 = op2.gpr();
    871             bitOp(op, reg1, reg2, result.gpr());
    872 
    873             integerResult(result.gpr(), m_compileIndex);
    874         }
    875         break;
    876 
    877     case BitRShift:
    878     case BitLShift:
    879     case BitURShift:
    880         if (isInt32Constant(node.child2())) {
    881             SpeculateIntegerOperand op1(this, node.child1());
    882             GPRTemporary result(this, op1);
    883 
    884             shiftOp(op, op1.gpr(), valueOfInt32Constant(node.child2()) & 0x1f, result.gpr());
    885 
    886             integerResult(result.gpr(), m_compileIndex);
    887         } else {
    888             // Do not allow shift amount to be used as the result, MacroAssembler does not permit this.
    889             SpeculateIntegerOperand op1(this, node.child1());
    890             SpeculateIntegerOperand op2(this, node.child2());
    891             GPRTemporary result(this, op1);
    892 
    893             GPRReg reg1 = op1.gpr();
    894             GPRReg reg2 = op2.gpr();
    895             shiftOp(op, reg1, reg2, result.gpr());
    896 
    897             integerResult(result.gpr(), m_compileIndex);
    898         }
    899         break;
    900 
    901     case UInt32ToNumber: {
    902         if (!nodeCanSpeculateInteger(node.arithNodeFlags())) {
    903             // We know that this sometimes produces doubles. So produce a double every
    904             // time. This at least allows subsequent code to not have weird conditionals.
    905            
    906             IntegerOperand op1(this, node.child1());
    907             FPRTemporary result(this);
    908            
    909             GPRReg inputGPR = op1.gpr();
    910             FPRReg outputFPR = result.fpr();
    911            
    912             m_jit.convertInt32ToDouble(inputGPR, outputFPR);
    913            
    914             JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, inputGPR, TrustedImm32(0));
    915             m_jit.addDouble(JITCompiler::AbsoluteAddress(&twoToThe32), outputFPR);
    916             positive.link(&m_jit);
    917            
    918             doubleResult(outputFPR, m_compileIndex);
    919         }
    920        
    921         IntegerOperand op1(this, node.child1());
    922         GPRTemporary result(this, op1);
    923 
    924         // Test the operand is positive.
    925         speculationCheck(m_jit.branch32(MacroAssembler::LessThan, op1.gpr(), TrustedImm32(0)));
    926 
    927         m_jit.move(op1.gpr(), result.gpr());
    928         integerResult(result.gpr(), m_compileIndex, op1.format());
    929         break;
    930     }
    931        
    932     case ValueToInt32: {
    933         if (shouldNotSpeculateInteger(node.child1())) {
    934             // Do it the safe way.
    935             nonSpeculativeValueToInt32(node);
    936             break;
    937         }
    938        
    939         if (shouldNotSpeculateInteger(node.child1())) {
    940             // Do it the safe way.
    941             nonSpeculativeValueToInt32(node);
    942             break;
    943         }
    944        
    945         SpeculateIntegerOperand op1(this, node.child1());
    946         GPRTemporary result(this, op1);
    947         m_jit.move(op1.gpr(), result.gpr());
    948         integerResult(result.gpr(), m_compileIndex, op1.format());
    949         break;
    950     }
    951 
    952     case ValueToNumber: {
    953         if (shouldNotSpeculateInteger(node.child1())) {
    954             SpeculateDoubleOperand op1(this, node.child1());
    955             FPRTemporary result(this, op1);
    956             m_jit.moveDouble(op1.fpr(), result.fpr());
    957             doubleResult(result.fpr(), m_compileIndex);
    958             break;
    959         }
    960        
    961         SpeculateIntegerOperand op1(this, node.child1());
    962         GPRTemporary result(this, op1);
    963         m_jit.move(op1.gpr(), result.gpr());
    964         integerResult(result.gpr(), m_compileIndex, op1.format());
    965         break;
    966     }
    967 
    968     case ValueToDouble: {
    969         SpeculateDoubleOperand op1(this, node.child1());
    970         FPRTemporary result(this, op1);
    971         m_jit.moveDouble(op1.fpr(), result.fpr());
    972         doubleResult(result.fpr(), m_compileIndex);
    973         break;
    974     }
    975 
    976     case ValueAdd:
    977     case ArithAdd: {
    978         if (shouldSpeculateInteger(node.child1(), node.child2()) && nodeCanSpeculateInteger(node.arithNodeFlags())) {
    979             if (isInt32Constant(node.child1())) {
    980                 int32_t imm1 = valueOfInt32Constant(node.child1());
    981                 SpeculateIntegerOperand op2(this, node.child2());
    982                 GPRTemporary result(this);
    983                
    984                 if (nodeCanTruncateInteger(node.arithNodeFlags())) {
    985                     m_jit.move(op2.gpr(), result.gpr());
    986                     m_jit.add32(Imm32(imm1), result.gpr());
    987                 } else
    988                     speculationCheck(m_jit.branchAdd32(MacroAssembler::Overflow, op2.gpr(), Imm32(imm1), result.gpr()));
    989 
    990                 integerResult(result.gpr(), m_compileIndex);
    991                 break;
    992             }
    993                
    994             if (isInt32Constant(node.child2())) {
    995                 SpeculateIntegerOperand op1(this, node.child1());
    996                 int32_t imm2 = valueOfInt32Constant(node.child2());
    997                 GPRTemporary result(this);
    998                
    999                 if (nodeCanTruncateInteger(node.arithNodeFlags())) {
    1000                     m_jit.move(op1.gpr(), result.gpr());
    1001                     m_jit.add32(Imm32(imm2), result.gpr());
    1002                 } else
    1003                     speculationCheck(m_jit.branchAdd32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
    1004 
    1005                 integerResult(result.gpr(), m_compileIndex);
    1006                 break;
    1007             }
    1008                
    1009             SpeculateIntegerOperand op1(this, node.child1());
    1010             SpeculateIntegerOperand op2(this, node.child2());
    1011             GPRTemporary result(this, op1, op2);
    1012 
    1013             GPRReg gpr1 = op1.gpr();
    1014             GPRReg gpr2 = op2.gpr();
    1015             GPRReg gprResult = result.gpr();
    1016            
    1017             if (nodeCanTruncateInteger(node.arithNodeFlags())) {
    1018                 if (gpr1 == gprResult)
    1019                     m_jit.add32(gpr2, gprResult);
    1020                 else {
    1021                     m_jit.move(gpr2, gprResult);
    1022                     m_jit.add32(gpr1, gprResult);
    1023                 }
    1024             } else {
    1025                 MacroAssembler::Jump check = m_jit.branchAdd32(MacroAssembler::Overflow, gpr1, gpr2, gprResult);
    1026                
    1027                 if (gpr1 == gprResult)
    1028                     speculationCheck(check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr2));
    1029                 else if (gpr2 == gprResult)
    1030                     speculationCheck(check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr1));
    1031                 else
    1032                     speculationCheck(check);
    1033             }
    1034 
    1035             integerResult(gprResult, m_compileIndex);
    1036             break;
    1037         }
    1038        
    1039         if (shouldSpeculateNumber(node.child1(), node.child2())) {
    1040             SpeculateDoubleOperand op1(this, node.child1());
    1041             SpeculateDoubleOperand op2(this, node.child2());
    1042             FPRTemporary result(this, op1, op2);
    1043            
    1044             FPRReg reg1 = op1.fpr();
    1045             FPRReg reg2 = op2.fpr();
    1046             m_jit.addDouble(reg1, reg2, result.fpr());
    1047            
    1048             doubleResult(result.fpr(), m_compileIndex);
    1049             break;
    1050         }
    1051        
    1052         ASSERT(op == ValueAdd);
    1053        
    1054         JSValueOperand op1(this, node.child1());
    1055         JSValueOperand op2(this, node.child2());
    1056        
    1057         GPRReg op1GPR = op1.gpr();
    1058         GPRReg op2GPR = op2.gpr();
    1059        
    1060         flushRegisters();
    1061        
    1062         GPRResult result(this);
    1063         if (isKnownNotNumber(node.child1()) || isKnownNotNumber(node.child2()))
    1064             callOperation(operationValueAddNotNumber, result.gpr(), op1GPR, op2GPR);
    1065         else
    1066             callOperation(operationValueAdd, result.gpr(), op1GPR, op2GPR);
    1067        
    1068         jsValueResult(result.gpr(), m_compileIndex);
    1069         break;
    1070     }
    1071 
    1072     case ArithSub: {
    1073         if (shouldSpeculateInteger(node.child1(), node.child2()) && nodeCanSpeculateInteger(node.arithNodeFlags())) {
    1074             if (isInt32Constant(node.child2())) {
    1075                 SpeculateIntegerOperand op1(this, node.child1());
    1076                 int32_t imm2 = valueOfInt32Constant(node.child2());
    1077                 GPRTemporary result(this);
    1078 
    1079                 if (nodeCanTruncateInteger(node.arithNodeFlags())) {
    1080                     m_jit.move(op1.gpr(), result.gpr());
    1081                     m_jit.sub32(Imm32(imm2), result.gpr());
    1082                 } else
    1083                     speculationCheck(m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
    1084 
    1085                 integerResult(result.gpr(), m_compileIndex);
    1086                 break;
    1087             }
    1088                
    1089             SpeculateIntegerOperand op1(this, node.child1());
    1090             SpeculateIntegerOperand op2(this, node.child2());
    1091             GPRTemporary result(this);
    1092 
    1093             if (nodeCanTruncateInteger(node.arithNodeFlags())) {
    1094                 m_jit.move(op1.gpr(), result.gpr());
    1095                 m_jit.sub32(op2.gpr(), result.gpr());
    1096             } else
    1097                 speculationCheck(m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), op2.gpr(), result.gpr()));
    1098 
    1099             integerResult(result.gpr(), m_compileIndex);
    1100             break;
    1101         }
    1102        
    1103         SpeculateDoubleOperand op1(this, node.child1());
    1104         SpeculateDoubleOperand op2(this, node.child2());
    1105         FPRTemporary result(this, op1);
    1106 
    1107         FPRReg reg1 = op1.fpr();
    1108         FPRReg reg2 = op2.fpr();
    1109         m_jit.subDouble(reg1, reg2, result.fpr());
    1110 
    1111         doubleResult(result.fpr(), m_compileIndex);
    1112         break;
    1113     }
    1114 
    1115     case ArithMul: {
    1116         if (shouldSpeculateInteger(node.child1(), node.child2()) && nodeCanSpeculateInteger(node.arithNodeFlags())) {
    1117             SpeculateIntegerOperand op1(this, node.child1());
    1118             SpeculateIntegerOperand op2(this, node.child2());
    1119             GPRTemporary result(this);
    1120 
    1121             GPRReg reg1 = op1.gpr();
    1122             GPRReg reg2 = op2.gpr();
    1123            
    1124             // What is unfortunate is that we cannot take advantage of nodeCanTruncateInteger()
    1125             // here. A multiply on integers performed in the double domain and then truncated to
    1126             // an integer will give a different result than a multiply performed in the integer
    1127             // domain and then truncated, if the integer domain result would have resulted in
    1128             // something bigger than what a 32-bit integer can hold. JavaScript mandates that
    1129             // the semantics are always as if the multiply had been performed in the double
    1130             // domain.
    1131            
    1132             speculationCheck(m_jit.branchMul32(MacroAssembler::Overflow, reg1, reg2, result.gpr()));
    1133            
    1134             // Check for negative zero, if the users of this node care about such things.
    1135             if (!nodeCanIgnoreNegativeZero(node.arithNodeFlags())) {
    1136                 MacroAssembler::Jump resultNonZero = m_jit.branchTest32(MacroAssembler::NonZero, result.gpr());
    1137                 speculationCheck(m_jit.branch32(MacroAssembler::LessThan, reg1, TrustedImm32(0)));
    1138                 speculationCheck(m_jit.branch32(MacroAssembler::LessThan, reg2, TrustedImm32(0)));
    1139                 resultNonZero.link(&m_jit);
    1140             }
    1141 
    1142             integerResult(result.gpr(), m_compileIndex);
    1143             break;
    1144         }
    1145        
    1146         SpeculateDoubleOperand op1(this, node.child1());
    1147         SpeculateDoubleOperand op2(this, node.child2());
    1148         FPRTemporary result(this, op1, op2);
    1149 
    1150         FPRReg reg1 = op1.fpr();
    1151         FPRReg reg2 = op2.fpr();
    1152        
    1153         m_jit.mulDouble(reg1, reg2, result.fpr());
    1154        
    1155         doubleResult(result.fpr(), m_compileIndex);
    1156         break;
    1157     }
    1158 
    1159     case ArithDiv: {
    1160         if (shouldSpeculateInteger(node.child1(), node.child2()) && nodeCanSpeculateInteger(node.arithNodeFlags())) {
    1161             SpeculateIntegerOperand op1(this, node.child1());
    1162             SpeculateIntegerOperand op2(this, node.child2());
    1163             GPRTemporary eax(this, X86Registers::eax);
    1164             GPRTemporary edx(this, X86Registers::edx);
    1165             GPRReg op1GPR = op1.gpr();
    1166             GPRReg op2GPR = op2.gpr();
    1167            
    1168             speculationCheck(m_jit.branchTest32(JITCompiler::Zero, op2GPR));
    1169            
    1170             // If the user cares about negative zero, then speculate that we're not about
    1171             // to produce negative zero.
    1172             if (!nodeCanIgnoreNegativeZero(node.arithNodeFlags())) {
    1173                 MacroAssembler::Jump numeratorNonZero = m_jit.branchTest32(MacroAssembler::NonZero, op1GPR);
    1174                 speculationCheck(m_jit.branch32(MacroAssembler::LessThan, op2GPR, TrustedImm32(0)));
    1175                 numeratorNonZero.link(&m_jit);
    1176             }
    1177            
    1178             GPRReg temp2 = InvalidGPRReg;
    1179             if (op2GPR == X86Registers::eax || op2GPR == X86Registers::edx) {
    1180                 temp2 = allocate();
    1181                 m_jit.move(op2GPR, temp2);
    1182                 op2GPR = temp2;
    1183             }
    1184            
    1185             m_jit.move(op1GPR, eax.gpr());
    1186             m_jit.assembler().cdq();
    1187             m_jit.assembler().idivl_r(op2GPR);
    1188            
    1189             // Check that there was no remainder. If there had been, then we'd be obligated to
    1190             // produce a double result instead.
    1191             speculationCheck(m_jit.branchTest32(JITCompiler::NonZero, edx.gpr()));
    1192            
    1193             integerResult(eax.gpr(), m_compileIndex);
    1194             break;
    1195         }
    1196        
    1197         SpeculateDoubleOperand op1(this, node.child1());
    1198         SpeculateDoubleOperand op2(this, node.child2());
    1199         FPRTemporary result(this, op1);
    1200 
    1201         FPRReg reg1 = op1.fpr();
    1202         FPRReg reg2 = op2.fpr();
    1203         m_jit.divDouble(reg1, reg2, result.fpr());
    1204 
    1205         doubleResult(result.fpr(), m_compileIndex);
    1206         break;
    1207     }
    1208 
    1209     case ArithMod: {
    1210         if (shouldNotSpeculateInteger(node.child1()) || shouldNotSpeculateInteger(node.child2())
    1211             || !nodeCanSpeculateInteger(node.arithNodeFlags())) {
    1212             SpeculateDoubleOperand op1(this, node.child1());
    1213             SpeculateDoubleOperand op2(this, node.child2());
    1214            
    1215             FPRReg op1FPR = op1.fpr();
    1216             FPRReg op2FPR = op2.fpr();
    1217            
    1218             flushRegisters();
    1219            
    1220             FPRResult result(this);
    1221 
    1222             callOperation(fmod, result.fpr(), op1FPR, op2FPR);
    1223            
    1224             doubleResult(result.fpr(), m_compileIndex);
    1225             break;
    1226         }
    1227        
    1228         SpeculateIntegerOperand op1(this, node.child1());
    1229         SpeculateIntegerOperand op2(this, node.child2());
    1230         GPRTemporary eax(this, X86Registers::eax);
    1231         GPRTemporary edx(this, X86Registers::edx);
    1232         GPRReg op1Gpr = op1.gpr();
    1233         GPRReg op2Gpr = op2.gpr();
    1234 
    1235         speculationCheck(m_jit.branchTest32(JITCompiler::Zero, op2Gpr));
    1236 
    1237         GPRReg temp2 = InvalidGPRReg;
    1238         if (op2Gpr == X86Registers::eax || op2Gpr == X86Registers::edx) {
    1239             temp2 = allocate();
    1240             m_jit.move(op2Gpr, temp2);
    1241             op2Gpr = temp2;
    1242         }
    1243 
    1244         m_jit.move(op1Gpr, eax.gpr());
    1245         m_jit.assembler().cdq();
    1246         m_jit.assembler().idivl_r(op2Gpr);
    1247 
    1248         if (temp2 != InvalidGPRReg)
    1249             unlock(temp2);
    1250 
    1251         integerResult(edx.gpr(), m_compileIndex);
    1252         break;
    1253     }
    1254        
    1255     case ArithAbs: {
    1256         if (shouldSpeculateInteger(node.child1()) && nodeCanSpeculateInteger(node.arithNodeFlags())) {
    1257             SpeculateIntegerOperand op1(this, node.child1());
    1258             GPRTemporary result(this, op1);
    1259             GPRTemporary scratch(this);
    1260            
    1261             m_jit.zeroExtend32ToPtr(op1.gpr(), result.gpr());
    1262             m_jit.rshift32(result.gpr(), MacroAssembler::TrustedImm32(31), scratch.gpr());
    1263             m_jit.add32(scratch.gpr(), result.gpr());
    1264             m_jit.xor32(scratch.gpr(), result.gpr());
    1265             speculationCheck(m_jit.branch32(MacroAssembler::Equal, result.gpr(), MacroAssembler::TrustedImm32(1 << 31)));
    1266             integerResult(result.gpr(), m_compileIndex);
    1267             break;
    1268         }
    1269        
    1270         SpeculateDoubleOperand op1(this, node.child1());
    1271         FPRTemporary result(this);
    1272        
    1273         static const double negativeZeroConstant = -0.0;
    1274        
    1275         m_jit.loadDouble(&negativeZeroConstant, result.fpr());
    1276         m_jit.andnotDouble(op1.fpr(), result.fpr());
    1277         doubleResult(result.fpr(), m_compileIndex);
    1278         break;
    1279     }
    1280        
    1281     case ArithMin:
    1282     case ArithMax: {
    1283         if (shouldSpeculateInteger(node.child1(), node.child2()) && nodeCanSpeculateInteger(node.arithNodeFlags())) {
    1284             SpeculateStrictInt32Operand op1(this, node.child1());
    1285             SpeculateStrictInt32Operand op2(this, node.child2());
    1286             GPRTemporary result(this, op1);
    1287            
    1288             MacroAssembler::Jump op1Less = m_jit.branch32(op == ArithMin ? MacroAssembler::LessThan : MacroAssembler::GreaterThan, op1.gpr(), op2.gpr());
    1289             m_jit.move(op2.gpr(), result.gpr());
    1290             if (op1.gpr() != result.gpr()) {
    1291                 MacroAssembler::Jump done = m_jit.jump();
    1292                 op1Less.link(&m_jit);
    1293                 m_jit.move(op1.gpr(), result.gpr());
    1294                 done.link(&m_jit);
    1295             } else
    1296                 op1Less.link(&m_jit);
    1297            
    1298             integerResult(result.gpr(), m_compileIndex);
    1299             break;
    1300         }
    1301        
    1302         SpeculateDoubleOperand op1(this, node.child1());
    1303         SpeculateDoubleOperand op2(this, node.child2());
    1304         FPRTemporary result(this, op1);
    1305        
    1306         MacroAssembler::JumpList done;
    1307        
    1308         MacroAssembler::Jump op1Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleLessThan : MacroAssembler::DoubleGreaterThan, op1.fpr(), op2.fpr());
    1309        
    1310         // op2 is eather the lesser one or one of then is NaN
    1311         MacroAssembler::Jump op2Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleGreaterThan : MacroAssembler::DoubleLessThan, op1.fpr(), op2.fpr());
    1312        
    1313         // Unordered case. We don't know which of op1, op2 is NaN. Manufacture NaN by adding
    1314         // op1 + op2 and putting it into result.
    1315         m_jit.addDouble(op1.fpr(), op2.fpr(), result.fpr());
    1316         done.append(m_jit.jump());
    1317        
    1318         op2Less.link(&m_jit);
    1319         m_jit.moveDouble(op2.fpr(), result.fpr());
    1320        
    1321         if (op1.fpr() != result.fpr()) {
    1322             done.append(m_jit.jump());
    1323            
    1324             op1Less.link(&m_jit);
    1325             m_jit.moveDouble(op1.fpr(), result.fpr());
    1326         } else
    1327             op1Less.link(&m_jit);
    1328        
    1329         done.link(&m_jit);
    1330        
    1331         doubleResult(result.fpr(), m_compileIndex);
    1332         break;
    1333     }
    1334        
    1335     case ArithSqrt: {
    1336         SpeculateDoubleOperand op1(this, node.child1());
    1337         FPRTemporary result(this, op1);
    1338        
    1339         m_jit.sqrtDouble(op1.fpr(), result.fpr());
    1340        
    1341         doubleResult(result.fpr(), m_compileIndex);
    1342         break;
    1343     }
    1344 
    1345     case LogicalNot: {
    1346         if (isKnownBoolean(node.child1())) {
    1347             SpeculateBooleanOperand value(this, node.child1());
    1348             GPRTemporary result(this, value);
    1349            
    1350             m_jit.move(value.gpr(), result.gpr());
    1351             m_jit.xorPtr(TrustedImm32(true), result.gpr());
    1352            
    1353             jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
    1354             break;
    1355         }
    1356        
    1357         PredictedType prediction = m_jit.getPrediction(node.child1());
    1358         if (isBooleanPrediction(prediction) || !prediction) {
    1359             JSValueOperand value(this, node.child1());
    1360             GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add).
    1361            
    1362             m_jit.move(value.gpr(), result.gpr());
    1363             m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.gpr());
    1364             speculationCheck(m_jit.branchTestPtr(JITCompiler::NonZero, result.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
    1365             m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueTrue)), result.gpr());
    1366            
    1367             // If we add a DataFormatBool, we should use it here.
    1368             jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
    1369             break;
    1370         }
    1371        
    1372         nonSpeculativeLogicalNot(node);
    1373        
    1374         break;
    1375     }
    1376 
    1377     case CompareLess:
    1378         if (compare(node, JITCompiler::LessThan, JITCompiler::DoubleLessThan, operationCompareLess))
    1379             return;
    1380         break;
    1381 
    1382     case CompareLessEq:
    1383         if (compare(node, JITCompiler::LessThanOrEqual, JITCompiler::DoubleLessThanOrEqual, operationCompareLessEq))
    1384             return;
    1385         break;
    1386 
    1387     case CompareGreater:
    1388         if (compare(node, JITCompiler::GreaterThan, JITCompiler::DoubleGreaterThan, operationCompareGreater))
    1389             return;
    1390         break;
    1391 
    1392     case CompareGreaterEq:
    1393         if (compare(node, JITCompiler::GreaterThanOrEqual, JITCompiler::DoubleGreaterThanOrEqual, operationCompareGreaterEq))
    1394             return;
    1395         break;
    1396 
    1397     case CompareEq:
    1398         if (isNullConstant(node.child1())) {
    1399             if (nonSpeculativeCompareNull(node, node.child2()))
    1400                 return;
    1401             break;
    1402         }
    1403         if (isNullConstant(node.child2())) {
    1404             if (nonSpeculativeCompareNull(node, node.child1()))
    1405                 return;
    1406             break;
    1407         }
    1408         if (compare(node, JITCompiler::Equal, JITCompiler::DoubleEqual, operationCompareEq))
    1409             return;
    1410         break;
    1411 
    1412     case CompareStrictEq:
    1413         if (nonSpeculativeStrictEq(node))
    1414             return;
    1415         break;
    1416 
    1417     case GetByVal: {
    1418         ASSERT(node.child3() == NoNode);
    1419         SpeculateCellOperand base(this, node.child1());
    1420         SpeculateStrictInt32Operand property(this, node.child2());
    1421         GPRTemporary storage(this);
    1422 
    1423         GPRReg baseReg = base.gpr();
    1424         GPRReg propertyReg = property.gpr();
    1425         GPRReg storageReg = storage.gpr();
    1426        
    1427         if (!m_compileOkay)
    1428             return;
    1429 
    1430         // Get the array storage. We haven't yet checked this is a JSArray, so this is only safe if
    1431         // an access with offset JSArray::storageOffset() is valid for all JSCells!
    1432         m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
    1433 
    1434         // Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
    1435         // If we have predicted the base to be type array, we can skip the check.
    1436         if (!isKnownArray(node.child1()))
    1437             speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
    1438         speculationCheck(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset())));
    1439 
    1440         // FIXME: In cases where there are subsequent by_val accesses to the same base it might help to cache
    1441         // the storage pointer - especially if there happens to be another register free right now. If we do so,
    1442         // then we'll need to allocate a new temporary for result.
    1443         GPRTemporary& result = storage;
    1444         m_jit.loadPtr(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), result.gpr());
    1445         speculationCheck(m_jit.branchTestPtr(MacroAssembler::Zero, result.gpr()));
    1446 
    1447         jsValueResult(result.gpr(), m_compileIndex);
    1448         break;
    1449     }
    1450 
    1451     case PutByVal: {
    1452         SpeculateCellOperand base(this, node.child1());
    1453         SpeculateStrictInt32Operand property(this, node.child2());
    1454         JSValueOperand value(this, node.child3());
    1455         GPRTemporary scratch(this);
    1456 
    1457         // Map base, property & value into registers, allocate a scratch register.
    1458         GPRReg baseReg = base.gpr();
    1459         GPRReg propertyReg = property.gpr();
    1460         GPRReg valueReg = value.gpr();
    1461         GPRReg scratchReg = scratch.gpr();
    1462        
    1463         if (!m_compileOkay)
    1464             return;
    1465 
    1466         writeBarrier(baseReg, value.gpr(), node.child3(), WriteBarrierForPropertyAccess, scratchReg);
    1467 
    1468         // Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
    1469         // If we have predicted the base to be type array, we can skip the check.
    1470         if (!isKnownArray(node.child1()))
    1471             speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
    1472 
    1473         base.use();
    1474         property.use();
    1475         value.use();
    1476        
    1477         MacroAssembler::Jump withinArrayBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset()));
    1478 
    1479         // Code to handle put beyond array bounds.
    1480         silentSpillAllRegisters(scratchReg);
    1481         setupStubArguments(baseReg, propertyReg, valueReg);
    1482         m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
    1483         JITCompiler::Call functionCall = appendCallWithExceptionCheck(operationPutByValBeyondArrayBounds);
    1484         silentFillAllRegisters(scratchReg);
    1485         JITCompiler::Jump wasBeyondArrayBounds = m_jit.jump();
    1486 
    1487         withinArrayBounds.link(&m_jit);
    1488 
    1489         // Get the array storage.
    1490         GPRReg storageReg = scratchReg;
    1491         m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
    1492 
    1493         // Check if we're writing to a hole; if so increment m_numValuesInVector.
    1494         MacroAssembler::Jump notHoleValue = m_jit.branchTestPtr(MacroAssembler::NonZero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
    1495         m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
    1496 
    1497         // If we're writing to a hole we might be growing the array;
    1498         MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, OBJECT_OFFSETOF(ArrayStorage, m_length)));
    1499         m_jit.add32(TrustedImm32(1), propertyReg);
    1500         m_jit.store32(propertyReg, MacroAssembler::Address(storageReg, OBJECT_OFFSETOF(ArrayStorage, m_length)));
    1501         m_jit.sub32(TrustedImm32(1), propertyReg);
    1502 
    1503         lengthDoesNotNeedUpdate.link(&m_jit);
    1504         notHoleValue.link(&m_jit);
    1505 
    1506         // Store the value to the array.
    1507         m_jit.storePtr(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
    1508 
    1509         wasBeyondArrayBounds.link(&m_jit);
    1510 
    1511         noResult(m_compileIndex, UseChildrenCalledExplicitly);
    1512         break;
    1513     }
    1514 
    1515     case PutByValAlias: {
    1516         SpeculateCellOperand base(this, node.child1());
    1517         SpeculateStrictInt32Operand property(this, node.child2());
    1518         JSValueOperand value(this, node.child3());
    1519         GPRTemporary scratch(this);
    1520        
    1521         GPRReg baseReg = base.gpr();
    1522         GPRReg scratchReg = scratch.gpr();
    1523 
    1524         writeBarrier(base.gpr(), value.gpr(), node.child3(), WriteBarrierForPropertyAccess, scratchReg);
    1525 
    1526         // Get the array storage.
    1527         GPRReg storageReg = scratchReg;
    1528         m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
    1529 
    1530         // Store the value to the array.
    1531         GPRReg propertyReg = property.gpr();
    1532         GPRReg valueReg = value.gpr();
    1533         m_jit.storePtr(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
    1534 
    1535         noResult(m_compileIndex);
    1536         break;
    1537     }
    1538 
    1539     case DFG::Jump: {
    1540         BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());
    1541         if (taken != (m_block + 1))
    1542             addBranch(m_jit.jump(), taken);
    1543         noResult(m_compileIndex);
    1544         break;
    1545     }
    1546 
    1547     case Branch:
    1548         if (isStrictInt32(node.child1())) {
    1549             SpeculateStrictInt32Operand op(this, node.child1());
    1550            
    1551             BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());
    1552             BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(node.notTakenBytecodeOffset());
    1553            
    1554             MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;
    1555            
    1556             if (taken == (m_block + 1)) {
    1557                 condition = MacroAssembler::Zero;
    1558                 BlockIndex tmp = taken;
    1559                 taken = notTaken;
    1560                 notTaken = tmp;
    1561             }
    1562            
    1563             addBranch(m_jit.branchTest32(condition, op.gpr()), taken);
    1564             if (notTaken != (m_block + 1))
    1565                 addBranch(m_jit.jump(), notTaken);
    1566            
    1567             noResult(m_compileIndex);
    1568             break;
    1569         }
    1570         if (shouldSpeculateInteger(node.child1())) {
    1571             SpeculateIntegerOperand op(this, node.child1());
    1572 
    1573             BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());
    1574             BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(node.notTakenBytecodeOffset());
    1575            
    1576             MacroAssembler::RelationalCondition condition = MacroAssembler::NotEqual;
    1577 
    1578             if (taken == (m_block + 1)) {
    1579                 condition = MacroAssembler::Equal;
    1580                 BlockIndex tmp = taken;
    1581                 taken = notTaken;
    1582                 notTaken = tmp;
    1583             }
    1584            
    1585             addBranch(m_jit.branchPtr(condition, op.gpr(), GPRInfo::tagTypeNumberRegister), taken);
    1586 
    1587             if (notTaken != (m_block + 1))
    1588                 addBranch(m_jit.jump(), notTaken);
    1589            
    1590             noResult(m_compileIndex);
    1591             break;
    1592         }
    1593         emitBranch(node);
    1594         break;
    1595 
    1596     case Return: {
    1597         ASSERT(GPRInfo::callFrameRegister != GPRInfo::regT1);
    1598         ASSERT(GPRInfo::regT1 != GPRInfo::returnValueGPR);
    1599         ASSERT(GPRInfo::returnValueGPR != GPRInfo::callFrameRegister);
    1600 
    1601 #if ENABLE(DFG_SUCCESS_STATS)
    1602         static SamplingCounter counter("SpeculativeJIT");
    1603         m_jit.emitCount(counter);
    1604 #endif
    1605 
    1606         // Return the result in returnValueGPR.
    1607         JSValueOperand op1(this, node.child1());
    1608         m_jit.move(op1.gpr(), GPRInfo::returnValueGPR);
    1609 
    1610         // Grab the return address.
    1611         m_jit.emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, GPRInfo::regT1);
    1612         // Restore our caller's "r".
    1613         m_jit.emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, GPRInfo::callFrameRegister);
    1614         // Return.
    1615         m_jit.restoreReturnAddressBeforeReturn(GPRInfo::regT1);
    1616         m_jit.ret();
    1617        
    1618         noResult(m_compileIndex);
    1619         break;
    1620     }
    1621        
    1622     case Throw:
    1623     case ThrowReferenceError: {
    1624         // We expect that throw statements are rare and are intended to exit the code block
    1625         // anyway, so we just OSR back to the old JIT for now.
    1626         terminateSpeculativeExecution();
    1627         break;
    1628     }
    1629        
    1630     case ToPrimitive: {
    1631         if (shouldSpeculateInteger(node.child1())) {
    1632             // It's really profitable to speculate integer, since it's really cheap,
    1633             // it means we don't have to do any real work, and we emit a lot less code.
    1634            
    1635             SpeculateIntegerOperand op1(this, node.child1());
    1636             GPRTemporary result(this, op1);
    1637            
    1638             m_jit.move(op1.gpr(), result.gpr());
    1639             if (op1.format() == DataFormatInteger)
    1640                 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, result.gpr());
    1641            
    1642             jsValueResult(result.gpr(), m_compileIndex);
    1643             break;
    1644         }
    1645        
    1646         // FIXME: Add string speculation here.
    1647        
    1648         bool wasPrimitive = isKnownNumeric(node.child1()) || isKnownBoolean(node.child1());
    1649        
    1650         JSValueOperand op1(this, node.child1());
    1651         GPRTemporary result(this, op1);
    1652        
    1653         GPRReg op1GPR = op1.gpr();
    1654         GPRReg resultGPR = result.gpr();
    1655        
    1656         op1.use();
    1657        
    1658         if (wasPrimitive)
    1659             m_jit.move(op1GPR, resultGPR);
    1660         else {
    1661             MacroAssembler::JumpList alreadyPrimitive;
    1662            
    1663             alreadyPrimitive.append(m_jit.branchTestPtr(MacroAssembler::NonZero, op1GPR, GPRInfo::tagMaskRegister));
    1664             alreadyPrimitive.append(m_jit.branchPtr(MacroAssembler::Equal, MacroAssembler::Address(op1GPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr)));
    1665            
    1666             silentSpillAllRegisters(resultGPR);
    1667             m_jit.move(op1GPR, GPRInfo::argumentGPR1);
    1668             m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
    1669             appendCallWithExceptionCheck(operationToPrimitive);
    1670             m_jit.move(GPRInfo::returnValueGPR, resultGPR);
    1671             silentFillAllRegisters(resultGPR);
    1672            
    1673             MacroAssembler::Jump done = m_jit.jump();
    1674            
    1675             alreadyPrimitive.link(&m_jit);
    1676             m_jit.move(op1GPR, resultGPR);
    1677            
    1678             done.link(&m_jit);
    1679         }
    1680        
    1681         jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
    1682         break;
    1683     }
    1684        
    1685     case StrCat:
    1686     case NewArray: {
    1687         // We really don't want to grow the register file just to do a StrCat or NewArray.
    1688         // Say we have 50 functions on the stack that all have a StrCat in them that has
    1689         // upwards of 10 operands. In the DFG this would mean that each one gets
    1690         // some random virtual register, and then to do the StrCat we'd need a second
    1691         // span of 10 operands just to have somewhere to copy the 10 operands to, where
    1692         // they'd be contiguous and we could easily tell the C code how to find them.
    1693         // Ugly! So instead we use the scratchBuffer infrastructure in JSGlobalData. That
    1694         // way, those 50 functions will share the same scratchBuffer for offloading their
    1695         // StrCat operands. It's about as good as we can do, unless we start doing
    1696         // virtual register coalescing to ensure that operands to StrCat get spilled
    1697         // in exactly the place where StrCat wants them, or else have the StrCat
    1698         // refer to those operands' SetLocal instructions to force them to spill in
    1699         // the right place. Basically, any way you cut it, the current approach
    1700         // probably has the best balance of performance and sensibility in the sense
    1701         // that it does not increase the complexity of the DFG JIT just to make StrCat
    1702         // fast and pretty.
    1703        
    1704         EncodedJSValue* buffer = static_cast<EncodedJSValue*>(m_jit.globalData()->scratchBufferForSize(sizeof(EncodedJSValue) * node.numChildren()));
    1705        
    1706         for (unsigned operandIdx = 0; operandIdx < node.numChildren(); ++operandIdx) {
    1707             JSValueOperand operand(this, m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx]);
    1708             GPRReg opGPR = operand.gpr();
    1709             operand.use();
    1710            
    1711             m_jit.storePtr(opGPR, buffer + operandIdx);
    1712         }
    1713        
    1714         flushRegisters();
    1715        
    1716         GPRResult result(this);
    1717        
    1718         callOperation(op == StrCat ? operationStrCat : operationNewArray, result.gpr(), buffer, node.numChildren());
    1719        
    1720         cellResult(result.gpr(), m_compileIndex, UseChildrenCalledExplicitly);
    1721         break;
    1722     }
    1723        
    1724     case NewArrayBuffer: {
    1725         flushRegisters();
    1726         GPRResult result(this);
    1727        
    1728         callOperation(operationNewArrayBuffer, result.gpr(), node.startConstant(), node.numConstants());
    1729        
    1730         cellResult(result.gpr(), m_compileIndex);
    1731         break;
    1732     }
    1733        
    1734     case NewRegexp: {
    1735         flushRegisters();
    1736         GPRResult result(this);
    1737        
    1738         callOperation(operationNewRegexp, result.gpr(), m_jit.codeBlock()->regexp(node.regexpIndex()));
    1739        
    1740         cellResult(result.gpr(), m_compileIndex);
    1741         break;
    1742     }
    1743        
    1744     case ConvertThis: {
    1745         SpeculateCellOperand thisValue(this, node.child1());
    1746 
    1747         speculationCheck(m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(thisValue.gpr()), JITCompiler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr)));
    1748 
    1749         cellResult(thisValue.gpr(), m_compileIndex);
    1750         break;
    1751     }
    1752 
    1753     case CreateThis: {
    1754         // Note that there is not so much profit to speculate here. The only things we
    1755         // speculate on are (1) that it's a cell, since that eliminates cell checks
    1756         // later if the proto is reused, and (2) if we have a FinalObject prediction
    1757         // then we speculate because we want to get recompiled if it isn't (since
    1758         // otherwise we'd start taking slow path a lot).
    1759        
    1760         SpeculateCellOperand proto(this, node.child1());
    1761         GPRTemporary result(this);
    1762         GPRTemporary scratch(this);
    1763        
    1764         GPRReg protoGPR = proto.gpr();
    1765         GPRReg resultGPR = result.gpr();
    1766         GPRReg scratchGPR = scratch.gpr();
    1767        
    1768         proto.use();
    1769        
    1770         MacroAssembler::JumpList slowPath;
    1771        
    1772         // Need to verify that the prototype is an object. If we have reason to believe
    1773         // that it's a FinalObject then we speculate on that directly. Otherwise we
    1774         // do the slow (structure-based) check.
    1775         if (shouldSpeculateFinalObject(node.child1()))
    1776             speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(protoGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsFinalObjectVPtr)));
    1777         else {
    1778             m_jit.loadPtr(MacroAssembler::Address(protoGPR, JSCell::structureOffset()), scratchGPR);
    1779             slowPath.append(m_jit.branch8(MacroAssembler::Below, MacroAssembler::Address(scratchGPR, Structure::typeInfoTypeOffset()), MacroAssembler::TrustedImm32(ObjectType)));
    1780         }
    1781        
    1782         // Load the inheritorID (the Structure that objects who have protoGPR as the prototype
    1783         // use to refer to that prototype). If the inheritorID is not set, go to slow path.
    1784         m_jit.loadPtr(MacroAssembler::Address(protoGPR, JSObject::offsetOfInheritorID()), scratchGPR);
    1785         slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, scratchGPR));
    1786        
    1787         emitAllocateJSFinalObject(scratchGPR, resultGPR, scratchGPR, slowPath);
    1788        
    1789         MacroAssembler::Jump done = m_jit.jump();
    1790        
    1791         slowPath.link(&m_jit);
    1792        
    1793         silentSpillAllRegisters(resultGPR);
    1794         m_jit.move(protoGPR, GPRInfo::argumentGPR1);
    1795         m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
    1796         appendCallWithExceptionCheck(operationCreateThis);
    1797         m_jit.move(GPRInfo::returnValueGPR, resultGPR);
    1798         silentFillAllRegisters(resultGPR);
    1799        
    1800         done.link(&m_jit);
    1801        
    1802         cellResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
    1803         break;
    1804     }
    1805 
    1806     case NewObject: {
    1807         GPRTemporary result(this);
    1808         GPRTemporary scratch(this);
    1809        
    1810         GPRReg resultGPR = result.gpr();
    1811         GPRReg scratchGPR = scratch.gpr();
    1812        
    1813         MacroAssembler::JumpList slowPath;
    1814        
    1815         emitAllocateJSFinalObject(MacroAssembler::TrustedImmPtr(m_jit.codeBlock()->globalObject()->emptyObjectStructure()), resultGPR, scratchGPR, slowPath);
    1816        
    1817         MacroAssembler::Jump done = m_jit.jump();
    1818        
    1819         slowPath.link(&m_jit);
    1820        
    1821         silentSpillAllRegisters(resultGPR);
    1822         m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
    1823         appendCallWithExceptionCheck(operationNewObject);
    1824         m_jit.move(GPRInfo::returnValueGPR, resultGPR);
    1825         silentFillAllRegisters(resultGPR);
    1826        
    1827         done.link(&m_jit);
    1828        
    1829         cellResult(resultGPR, m_compileIndex);
    1830         break;
    1831     }
    1832 
    1833     case GetCallee: {
    1834         GPRTemporary result(this);
    1835         m_jit.loadPtr(JITCompiler::addressFor(static_cast<VirtualRegister>(RegisterFile::Callee)), result.gpr());
    1836         cellResult(result.gpr(), m_compileIndex);
    1837         break;
    1838     }
    1839 
    1840     case GetScopeChain: {
    1841         GPRTemporary result(this);
    1842         GPRReg resultGPR = result.gpr();
    1843 
    1844         m_jit.loadPtr(JITCompiler::addressFor(static_cast<VirtualRegister>(RegisterFile::ScopeChain)), resultGPR);
    1845         bool checkTopLevel = m_jit.codeBlock()->codeType() == FunctionCode && m_jit.codeBlock()->needsFullScopeChain();
    1846         int skip = node.scopeChainDepth();
    1847         ASSERT(skip || !checkTopLevel);
    1848         if (checkTopLevel && skip--) {
    1849             JITCompiler::Jump activationNotCreated;
    1850             if (checkTopLevel)
    1851                 activationNotCreated = m_jit.branchTestPtr(JITCompiler::Zero, JITCompiler::addressFor(static_cast<VirtualRegister>(m_jit.codeBlock()->activationRegister())));
    1852             m_jit.loadPtr(JITCompiler::Address(resultGPR, OBJECT_OFFSETOF(ScopeChainNode, next)), resultGPR);
    1853             activationNotCreated.link(&m_jit);
    1854         }
    1855         while (skip--)
    1856             m_jit.loadPtr(JITCompiler::Address(resultGPR, OBJECT_OFFSETOF(ScopeChainNode, next)), resultGPR);
    1857        
    1858         m_jit.loadPtr(JITCompiler::Address(resultGPR, OBJECT_OFFSETOF(ScopeChainNode, object)), resultGPR);
    1859 
    1860         cellResult(resultGPR, m_compileIndex);
    1861         break;
    1862     }
    1863     case GetScopedVar: {
    1864         SpeculateCellOperand scopeChain(this, node.child1());
    1865         GPRTemporary result(this);
    1866         GPRReg resultGPR = result.gpr();
    1867         m_jit.loadPtr(JITCompiler::Address(scopeChain.gpr(), JSVariableObject::offsetOfRegisters()), resultGPR);
    1868         m_jit.loadPtr(JITCompiler::Address(resultGPR, node.varNumber() * sizeof(Register)), resultGPR);
    1869         jsValueResult(resultGPR, m_compileIndex);
    1870         break;
    1871     }
    1872     case PutScopedVar: {
    1873         SpeculateCellOperand scopeChain(this, node.child1());
    1874         GPRTemporary scratchRegister(this);
    1875         GPRReg scratchGPR = scratchRegister.gpr();
    1876         m_jit.loadPtr(JITCompiler::Address(scopeChain.gpr(), JSVariableObject::offsetOfRegisters()), scratchGPR);
    1877         JSValueOperand value(this, node.child2());
    1878         m_jit.storePtr(value.gpr(), JITCompiler::Address(scratchGPR, node.varNumber() * sizeof(Register)));
    1879         writeBarrier(scopeChain.gpr(), value.gpr(), node.child2(), WriteBarrierForVariableAccess, scratchGPR);
    1880         noResult(m_compileIndex);
    1881         break;
    1882     }
    1883     case GetById: {
    1884         SpeculateCellOperand base(this, node.child1());
    1885         GPRTemporary result(this, base);
    1886        
    1887         GPRReg baseGPR = base.gpr();
    1888         GPRReg resultGPR = result.gpr();
    1889         GPRReg scratchGPR;
    1890        
    1891         if (resultGPR == baseGPR)
    1892             scratchGPR = tryAllocate();
    1893         else
    1894             scratchGPR = resultGPR;
    1895        
    1896         base.use();
    1897 
    1898         cachedGetById(baseGPR, resultGPR, scratchGPR, node.identifierNumber());
    1899 
    1900         jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
    1901         break;
    1902     }
    1903 
    1904     case GetArrayLength: {
    1905         SpeculateCellOperand base(this, node.child1());
    1906         GPRTemporary result(this);
    1907        
    1908         GPRReg baseGPR = base.gpr();
    1909         GPRReg resultGPR = result.gpr();
    1910        
    1911         if (!isKnownArray(node.child1()))
    1912             speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
    1913        
    1914         m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), resultGPR);
    1915         m_jit.load32(MacroAssembler::Address(resultGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), resultGPR);
    1916        
    1917         speculationCheck(m_jit.branch32(MacroAssembler::LessThan, resultGPR, MacroAssembler::TrustedImm32(0)));
    1918        
    1919         integerResult(resultGPR, m_compileIndex);
    1920         break;
    1921     }
    1922 
    1923     case CheckStructure: {
    1924         SpeculateCellOperand base(this, node.child1());
    1925         GPRTemporary result(this, base);
    1926        
    1927         GPRReg baseGPR = base.gpr();
    1928         GPRReg resultGPR = result.gpr();
    1929        
    1930         speculationCheck(m_jit.branchPtr(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), JITCompiler::TrustedImmPtr(node.structure())));
    1931        
    1932         m_jit.loadPtr(JITCompiler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), resultGPR);
    1933        
    1934         storageResult(resultGPR, m_compileIndex);
    1935         break;
    1936     }
    1937        
    1938     case GetByOffset: {
    1939         StorageOperand storage(this, node.child1());
    1940         GPRTemporary result(this, storage);
    1941        
    1942         GPRReg storageGPR = storage.gpr();
    1943         GPRReg resultGPR = result.gpr();
    1944        
    1945         StorageAccessData& storageAccessData = m_jit.graph().m_storageAccessData[node.storageAccessDataIndex()];
    1946        
    1947         m_jit.loadPtr(JITCompiler::Address(storageGPR, storageAccessData.offset * sizeof(EncodedJSValue)), resultGPR);
    1948        
    1949         jsValueResult(resultGPR, m_compileIndex);
    1950         break;
    1951     }
    1952        
    1953     case GetMethod: {
    1954         SpeculateCellOperand base(this, node.child1());
    1955         GPRTemporary result(this, base);
    1956 
    1957         GPRReg baseGPR = base.gpr();
    1958         GPRReg resultGPR = result.gpr();
    1959         GPRReg scratchGPR;
    1960        
    1961         if (resultGPR == baseGPR)
    1962             scratchGPR = tryAllocate();
    1963         else
    1964             scratchGPR = resultGPR;
    1965        
    1966         base.use();
    1967 
    1968         cachedGetMethod(baseGPR, resultGPR, scratchGPR, node.identifierNumber());
    1969 
    1970         jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
    1971         break;
    1972     }
    1973        
    1974     case CheckMethod: {
    1975         MethodCheckData& methodCheckData = m_jit.graph().m_methodCheckData[node.methodCheckDataIndex()];
    1976        
    1977         SpeculateCellOperand base(this, node.child1());
    1978         GPRTemporary scratch(this); // this needs to be a separate register, unfortunately.
    1979         GPRReg baseGPR = base.gpr();
    1980         GPRReg scratchGPR = scratch.gpr();
    1981        
    1982         speculationCheck(m_jit.branchPtr(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), JITCompiler::TrustedImmPtr(methodCheckData.structure)));
    1983         if (methodCheckData.prototype != m_jit.codeBlock()->globalObject()->methodCallDummy()) {
    1984             m_jit.move(JITCompiler::TrustedImmPtr(methodCheckData.prototype->structureAddress()), scratchGPR);
    1985             speculationCheck(m_jit.branchPtr(JITCompiler::NotEqual, JITCompiler::Address(scratchGPR), JITCompiler::TrustedImmPtr(methodCheckData.prototypeStructure)));
    1986         }
    1987        
    1988         useChildren(node);
    1989         initConstantInfo(m_compileIndex);
    1990         break;
    1991     }
    1992 
    1993     case PutById: {
    1994         SpeculateCellOperand base(this, node.child1());
    1995         JSValueOperand value(this, node.child2());
    1996         GPRTemporary scratch(this);
    1997        
    1998         GPRReg baseGPR = base.gpr();
    1999         GPRReg valueGPR = value.gpr();
    2000         GPRReg scratchGPR = scratch.gpr();
    2001        
    2002         base.use();
    2003         value.use();
    2004 
    2005         cachedPutById(baseGPR, valueGPR, node.child2(), scratchGPR, node.identifierNumber(), NotDirect);
    2006        
    2007         noResult(m_compileIndex, UseChildrenCalledExplicitly);
    2008         break;
    2009     }
    2010 
    2011     case PutByIdDirect: {
    2012         SpeculateCellOperand base(this, node.child1());
    2013         JSValueOperand value(this, node.child2());
    2014         GPRTemporary scratch(this);
    2015        
    2016         GPRReg baseGPR = base.gpr();
    2017         GPRReg valueGPR = value.gpr();
    2018         GPRReg scratchGPR = scratch.gpr();
    2019        
    2020         base.use();
    2021         value.use();
    2022 
    2023         cachedPutById(baseGPR, valueGPR, node.child2(), scratchGPR, node.identifierNumber(), Direct);
    2024 
    2025         noResult(m_compileIndex, UseChildrenCalledExplicitly);
    2026         break;
    2027     }
    2028 
    2029     case GetGlobalVar: {
    2030         GPRTemporary result(this);
    2031 
    2032         JSVariableObject* globalObject = m_jit.codeBlock()->globalObject();
    2033         m_jit.loadPtr(globalObject->addressOfRegisters(), result.gpr());
    2034         m_jit.loadPtr(JITCompiler::addressForGlobalVar(result.gpr(), node.varNumber()), result.gpr());
    2035 
    2036         jsValueResult(result.gpr(), m_compileIndex);
    2037         break;
    2038     }
    2039 
    2040     case PutGlobalVar: {
    2041         JSValueOperand value(this, node.child1());
    2042         GPRTemporary globalObject(this);
    2043         GPRTemporary scratch(this);
    2044        
    2045         GPRReg globalObjectReg = globalObject.gpr();
    2046         GPRReg scratchReg = scratch.gpr();
    2047 
    2048         m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.codeBlock()->globalObject()), globalObjectReg);
    2049 
    2050         writeBarrier(m_jit.codeBlock()->globalObject(), value.gpr(), node.child1(), WriteBarrierForVariableAccess, scratchReg);
    2051 
    2052         m_jit.loadPtr(MacroAssembler::Address(globalObjectReg, JSVariableObject::offsetOfRegisters()), scratchReg);
    2053         m_jit.storePtr(value.gpr(), JITCompiler::addressForGlobalVar(scratchReg, node.varNumber()));
    2054 
    2055         noResult(m_compileIndex);
    2056         break;
    2057     }
    2058 
    2059     case CheckHasInstance: {
    2060         SpeculateCellOperand base(this, node.child1());
    2061         GPRTemporary structure(this);
    2062 
    2063         // Speculate that base 'ImplementsDefaultHasInstance'.
    2064         m_jit.loadPtr(MacroAssembler::Address(base.gpr(), JSCell::structureOffset()), structure.gpr());
    2065         speculationCheck(m_jit.branchTest8(MacroAssembler::Zero, MacroAssembler::Address(structure.gpr(), Structure::typeInfoFlagsOffset()), MacroAssembler::TrustedImm32(ImplementsDefaultHasInstance)));
    2066 
    2067         noResult(m_compileIndex);
    2068         break;
    2069     }
    2070 
    2071     case InstanceOf: {
    2072         SpeculateCellOperand value(this, node.child1());
    2073         // Base unused since we speculate default InstanceOf behaviour in CheckHasInstance.
    2074         SpeculateCellOperand prototype(this, node.child3());
    2075 
    2076         GPRTemporary scratch(this);
    2077 
    2078         GPRReg valueReg = value.gpr();
    2079         GPRReg prototypeReg = prototype.gpr();
    2080         GPRReg scratchReg = scratch.gpr();
    2081 
    2082         // Check that prototype is an object.
    2083         m_jit.loadPtr(MacroAssembler::Address(prototypeReg, JSCell::structureOffset()), scratchReg);
    2084         speculationCheck(m_jit.branchIfNotObject(scratchReg));
    2085 
    2086         // Initialize scratchReg with the value being checked.
    2087         m_jit.move(valueReg, scratchReg);
    2088 
    2089         // Walk up the prototype chain of the value (in scratchReg), comparing to prototypeReg.
    2090         MacroAssembler::Label loop(&m_jit);
    2091         m_jit.loadPtr(MacroAssembler::Address(scratchReg, JSCell::structureOffset()), scratchReg);
    2092         m_jit.loadPtr(MacroAssembler::Address(scratchReg, Structure::prototypeOffset()), scratchReg);
    2093         MacroAssembler::Jump isInstance = m_jit.branchPtr(MacroAssembler::Equal, scratchReg, prototypeReg);
    2094         m_jit.branchTestPtr(MacroAssembler::Zero, scratchReg, GPRInfo::tagMaskRegister).linkTo(loop, &m_jit);
    2095 
    2096         // No match - result is false.
    2097         m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(false))), scratchReg);
    2098         MacroAssembler::Jump putResult = m_jit.jump();
    2099 
    2100         isInstance.link(&m_jit);
    2101         m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(true))), scratchReg);
    2102 
    2103         putResult.link(&m_jit);
    2104         jsValueResult(scratchReg, m_compileIndex, DataFormatJSBoolean);
    2105         break;
    2106     }
    2107 
    2108     case Phi:
    2109         ASSERT_NOT_REACHED();
    2110 
    2111     case Breakpoint:
    2112 #if ENABLE(DEBUG_WITH_BREAKPOINT)
    2113         m_jit.breakpoint();
    2114 #else
    2115         ASSERT_NOT_REACHED();
    2116 #endif
    2117         break;
    2118        
    2119     case Call:
    2120     case Construct:
    2121         emitCall(node);
    2122         break;
    2123 
    2124     case Resolve: {
    2125         flushRegisters();
    2126         GPRResult result(this);
    2127         callOperation(operationResolve, result.gpr(), identifier(node.identifierNumber()));
    2128         jsValueResult(result.gpr(), m_compileIndex);
    2129         break;
    2130     }
    2131 
    2132     case ResolveBase: {
    2133         flushRegisters();
    2134         GPRResult result(this);
    2135         callOperation(operationResolveBase, result.gpr(), identifier(node.identifierNumber()));
    2136         jsValueResult(result.gpr(), m_compileIndex);
    2137         break;
    2138     }
    2139 
    2140     case ResolveBaseStrictPut: {
    2141         flushRegisters();
    2142         GPRResult result(this);
    2143         callOperation(operationResolveBaseStrictPut, result.gpr(), identifier(node.identifierNumber()));
    2144         jsValueResult(result.gpr(), m_compileIndex);
    2145         break;
    2146     }
    2147 
    2148     case ResolveGlobal: {
    2149         GPRTemporary globalObject(this);
    2150         GPRTemporary resolveInfo(this);
    2151         GPRTemporary result(this);
    2152 
    2153         GPRReg globalObjectGPR = globalObject.gpr();
    2154         GPRReg resolveInfoGPR = resolveInfo.gpr();
    2155         GPRReg resultGPR = result.gpr();
    2156 
    2157         ResolveGlobalData& data = m_jit.graph().m_resolveGlobalData[node.resolveGlobalDataIndex()];
    2158         GlobalResolveInfo* resolveInfoAddress = &(m_jit.codeBlock()->globalResolveInfo(data.resolveInfoIndex));
    2159 
    2160         // Check Structure of global object
    2161         m_jit.move(JITCompiler::TrustedImmPtr(m_jit.codeBlock()->globalObject()), globalObjectGPR);
    2162         m_jit.move(JITCompiler::TrustedImmPtr(resolveInfoAddress), resolveInfoGPR);
    2163         m_jit.loadPtr(JITCompiler::Address(resolveInfoGPR, OBJECT_OFFSETOF(GlobalResolveInfo, structure)), resultGPR);
    2164         JITCompiler::Jump structuresMatch = m_jit.branchPtr(JITCompiler::Equal, resultGPR, JITCompiler::Address(globalObjectGPR, JSCell::structureOffset()));
    2165 
    2166         silentSpillAllRegisters(resultGPR);
    2167         m_jit.move(resolveInfoGPR, GPRInfo::argumentGPR1);
    2168         m_jit.move(JITCompiler::TrustedImmPtr(&m_jit.codeBlock()->identifier(data.identifierNumber)), GPRInfo::argumentGPR2);
    2169         m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
    2170         JITCompiler::Call functionCall = appendCallWithExceptionCheck(operationResolveGlobal);
    2171         m_jit.move(GPRInfo::returnValueGPR, resultGPR);
    2172         silentFillAllRegisters(resultGPR);
    2173 
    2174         JITCompiler::Jump wasSlow = m_jit.jump();
    2175 
    2176         // Fast case
    2177         structuresMatch.link(&m_jit);
    2178         m_jit.loadPtr(JITCompiler::Address(globalObjectGPR, JSObject::offsetOfPropertyStorage()), resultGPR);
    2179         m_jit.load32(JITCompiler::Address(resolveInfoGPR, OBJECT_OFFSETOF(GlobalResolveInfo, offset)), resolveInfoGPR);
    2180         m_jit.loadPtr(JITCompiler::BaseIndex(resultGPR, resolveInfoGPR, JITCompiler::ScalePtr), resultGPR);
    2181 
    2182         wasSlow.link(&m_jit);
    2183 
    2184         jsValueResult(resultGPR, m_compileIndex);
    2185         break;
    2186     }
    2187 
    2188     case ForceOSRExit: {
    2189         terminateSpeculativeExecution();
    2190         break;
    2191     }
    2192 
    2193     case Phantom:
    2194         // This is a no-op.
    2195         noResult(m_compileIndex);
    2196         break;
    2197     }
    2198    
    2199     if (node.hasResult() && node.mustGenerate())
    2200         use(m_compileIndex);
    2201 }
    2202 
    2203197void SpeculativeJIT::compileMovHint(Node& node)
    2204198{
     
    2213207    ASSERT(m_compileOkay);
    2214208    ASSERT(m_compileIndex == block.begin);
    2215    
     209
    2216210    if (block.isOSRTarget)
    2217211        m_jit.noticeOSREntry(block);
    2218    
     212
    2219213    m_blockHeads[m_block] = m_jit.label();
    2220214#if ENABLE(DFG_JIT_BREAK_ON_EVERY_BLOCK)
    2221215    m_jit.breakpoint();
    2222216#endif
    2223    
     217
    2224218    ASSERT(m_arguments.size() == block.m_argumentsAtHead.size());
    2225219    for (size_t i = 0; i < m_arguments.size(); ++i) {
     
    2276270                    if (info.registerFormat() == DataFormatDouble)
    2277271                        fprintf(stderr, ", %s", FPRInfo::debugName(info.fpr()));
     272#if USE(JSVALUE32_64)
     273                    else if (info.registerFormat() & DataFormatJS)
     274                        fprintf(stderr, ", %s %s", GPRInfo::debugName(info.tagGPR()), GPRInfo::debugName(info.payloadGPR()));
     275#endif
    2278276                    else
    2279277                        fprintf(stderr, ", %s", GPRInfo::debugName(info.gpr()));
     
    2294292            computeValueRecoveryFor(operand).dump(stderr);
    2295293#endif
    2296      
     294
    2297295#if ENABLE(DFG_DEBUG_VERBOSE)
    2298296        fprintf(stderr, "\n");
     
    2319317        VirtualRegister virtualRegister = (VirtualRegister)(m_jit.codeBlock()->thisRegister() + i);
    2320318        PredictedType predictedType = m_jit.graph()[m_jit.graph().m_arguments[i]].variableAccessData()->prediction();
     319#if USE(JSVALUE64)
    2321320        if (isInt32Prediction(predictedType))
    2322321            speculationCheck(m_jit.branchPtr(MacroAssembler::Below, JITCompiler::addressFor(virtualRegister), GPRInfo::tagTypeNumberRegister));
     
    2332331            speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
    2333332        }
     333#else
     334        if (isInt32Prediction(predictedType))
     335            speculationCheck(m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag)));
     336        else if (isArrayPrediction(predictedType)) {
     337            GPRTemporary temp(this);
     338            m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
     339            speculationCheck(m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
     340            m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
     341            speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
     342        } // FIXME: need boolean predictions, but we currently don't have that support.
     343#endif
    2334344    }
    2335345}
     
    2354364    case Int32InRegisterFile:
    2355365        return ValueRecovery::alreadyInRegisterFileAsUnboxedInt32();
    2356        
     366
    2357367    case HaveNode: {
    2358368        if (m_jit.isConstant(valueSource.nodeIndex()))
     
    2456466            if (infoPtr->registerFormat() == DataFormatDouble)
    2457467                return ValueRecovery::inFPR(infoPtr->fpr());
     468#if USE(JSVALUE32_64)
     469            if (infoPtr->registerFormat() & DataFormatJS)
     470                return ValueRecovery::inPair(infoPtr->tagGPR(), infoPtr->payloadGPR());
     471#endif
    2458472            return ValueRecovery::inGPR(infoPtr->gpr(), infoPtr->registerFormat());
    2459473        }
     
    2474488
    2475489#endif
    2476 #endif
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r96375 r96379  
    579579    // with the structure GPR being clobbered.
    580580    template<typename T>
    581     void emitAllocateJSFinalObject(T structure, GPRReg resultGPR, GPRReg scratchGPR, MacroAssembler::JumpList& slowPath);
    582    
     581    void emitAllocateJSFinalObject(T structure, GPRReg resultGPR, GPRReg scratchGPR, MacroAssembler::JumpList& slowPath)
     582    {
     583        MarkedSpace::SizeClass* sizeClass = &m_jit.globalData()->heap.sizeClassForObject(sizeof(JSFinalObject));
     584       
     585        m_jit.loadPtr(&sizeClass->firstFreeCell, resultGPR);
     586        slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, resultGPR));
     587       
     588        // The object is half-allocated: we have what we know is a fresh object, but
     589        // it's still on the GC's free list.
     590       
     591        // Ditch the structure by placing it into the structure slot, so that we can reuse
     592        // scratchGPR.
     593        m_jit.storePtr(structure, MacroAssembler::Address(resultGPR, JSObject::structureOffset()));
     594       
     595        // Now that we have scratchGPR back, remove the object from the free list
     596        m_jit.loadPtr(MacroAssembler::Address(resultGPR), scratchGPR);
     597        m_jit.storePtr(scratchGPR, &sizeClass->firstFreeCell);
     598       
     599        // Initialize the object's vtable
     600        m_jit.storePtr(MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsFinalObjectVPtr), MacroAssembler::Address(resultGPR));
     601       
     602        // Initialize the object's inheritorID.
     603        m_jit.storePtr(MacroAssembler::TrustedImmPtr(0), MacroAssembler::Address(resultGPR, JSObject::offsetOfInheritorID()));
     604       
     605        // Initialize the object's property storage pointer.
     606        m_jit.addPtr(MacroAssembler::TrustedImm32(sizeof(JSObject)), resultGPR, scratchGPR);
     607        m_jit.storePtr(scratchGPR, MacroAssembler::Address(resultGPR, JSFinalObject::offsetOfPropertyStorage()));
     608    }
     609
    583610#if USE(JSVALUE64)
    584611    JITCompiler::Jump convertToDouble(GPRReg value, FPRReg result, GPRReg tmp);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r96375 r96379  
    2828
    2929#if ENABLE(DFG_JIT)
     30
     31#include "DFGJITCompilerInlineMethods.h"
     32
     33namespace JSC { namespace DFG {
     34
    3035#if USE(JSVALUE32_64)
    31 #include "DFGJITCompilerInlineMethods.h"
    32 
    33 namespace JSC { namespace DFG {
    3436
    3537template<bool strict>
     
    114116    return InvalidGPRReg;
    115117}
    116 
    117 #ifndef NDEBUG
    118 void ValueSource::dump(FILE* out) const
    119 {
    120     switch (kind()) {
    121     case SourceNotSet:
    122         fprintf(out, "NotSet");
    123         break;
    124     case ValueInRegisterFile:
    125         fprintf(out, "InRegFile");
    126         break;
    127     case Int32InRegisterFile:
    128         fprintf(out, "Int32");
    129         break;
    130     case HaveNode:
    131         fprintf(out, "Node(%d)", m_nodeIndex);
    132         break;
    133     }
    134 }
    135 
    136 void ValueRecovery::dump(FILE* out) const
    137 {
    138     switch (technique()) {
    139     case AlreadyInRegisterFile:
    140         fprintf(out, "-");
    141         break;
    142     case AlreadyInRegisterFileAsUnboxedInt32:
    143         fprintf(out, "(int32)");
    144         break;
    145     case InGPR:
    146         fprintf(out, "%%%s", GPRInfo::debugName(gpr()));
    147         break;
    148     case UnboxedInt32InGPR:
    149         fprintf(out, "int32(%%%s)", GPRInfo::debugName(gpr()));
    150         break;
    151     case InFPR:
    152         fprintf(out, "%%%s", FPRInfo::debugName(fpr()));
    153         break;
    154 #if USE(JSVALUE32_64)
    155     case InPair:
    156         fprintf(out, "pair(%%%s, %%%s)", GPRInfo::debugName(tagGPR()), GPRInfo::debugName(payloadGPR()));
    157         break;
    158 #endif
    159     case DisplacedInRegisterFile:
    160         fprintf(out, "*%d", virtualRegister());
    161         break;
    162     case Constant:
    163         fprintf(out, "[%s]", constant().description());
    164         break;
    165     case DontKnow:
    166         fprintf(out, "!");
    167         break;
    168     default:
    169         fprintf(out, "?%d", technique());
    170         break;
    171     }
    172 }
    173 #endif
    174 
    175 OSRExit::OSRExit(MacroAssembler::Jump check, SpeculativeJIT* jit, unsigned recoveryIndex)
    176     : m_check(check)
    177     , m_nodeIndex(jit->m_compileIndex)
    178     , m_bytecodeIndex(jit->m_bytecodeIndexForOSR)
    179     , m_recoveryIndex(recoveryIndex)
    180     , m_arguments(jit->m_arguments.size())
    181     , m_variables(jit->m_variables.size())
    182     , m_lastSetOperand(jit->m_lastSetOperand)
    183 {
    184     ASSERT(m_bytecodeIndex != std::numeric_limits<uint32_t>::max());
    185     for (unsigned argument = 0; argument < m_arguments.size(); ++argument)
    186         m_arguments[argument] = jit->computeValueRecoveryFor(jit->m_arguments[argument]);
    187     for (unsigned variable = 0; variable < m_variables.size(); ++variable)
    188         m_variables[variable] = jit->computeValueRecoveryFor(jit->m_variables[variable]);
    189 }
    190 
    191 #ifndef NDEBUG
    192 void OSRExit::dump(FILE* out) const
    193 {
    194     for (unsigned argument = 0; argument < m_arguments.size(); ++argument)
    195         m_arguments[argument].dump(out);
    196     fprintf(out, " : ");
    197     for (unsigned variable = 0; variable < m_variables.size(); ++variable)
    198         m_variables[variable].dump(out);
    199 }
    200 #endif
    201118
    202119GPRReg SpeculativeJIT::fillSpeculateInt(NodeIndex nodeIndex, DataFormat& returnFormat)
     
    412329}
    413330
    414 void SpeculativeJIT::compilePeepHoleIntegerBranch(Node& node, NodeIndex branchNodeIndex, JITCompiler::RelationalCondition condition)
    415 {
    416     Node& branchNode = m_jit.graph()[branchNodeIndex];
    417     BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
    418     BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
    419 
    420     // The branch instruction will branch to the taken block.
    421     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
    422     if (taken == (m_block + 1)) {
    423         condition = JITCompiler::invert(condition);
    424         BlockIndex tmp = taken;
    425         taken = notTaken;
    426         notTaken = tmp;
    427     }
    428 
    429     if (isInt32Constant(node.child1())) {
    430         int32_t imm = valueOfInt32Constant(node.child1());
    431         SpeculateIntegerOperand op2(this, node.child2());
    432         addBranch(m_jit.branch32(condition, JITCompiler::Imm32(imm), op2.gpr()), taken);
    433     } else if (isInt32Constant(node.child2())) {
    434         SpeculateIntegerOperand op1(this, node.child1());
    435         int32_t imm = valueOfInt32Constant(node.child2());
    436         addBranch(m_jit.branch32(condition, op1.gpr(), JITCompiler::Imm32(imm)), taken);
    437     } else {
    438         SpeculateIntegerOperand op1(this, node.child1());
    439         SpeculateIntegerOperand op2(this, node.child2());
    440         addBranch(m_jit.branch32(condition, op1.gpr(), op2.gpr()), taken);
    441     }
    442 
    443     // Check for fall through, otherwise we need to jump.
    444     if (notTaken != (m_block + 1))
    445         addBranch(m_jit.jump(), notTaken);
    446 }
    447 
    448331JITCompiler::Jump SpeculativeJIT::convertToDouble(JSValueOperand& op, FPRReg result)
    449332{
     
    460343
    461344    return notNumber;
    462 }
    463 
    464 void SpeculativeJIT::compilePeepHoleDoubleBranch(Node& node, NodeIndex branchNodeIndex, JITCompiler::DoubleCondition condition)
    465 {
    466     Node& branchNode = m_jit.graph()[branchNodeIndex];
    467     BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
    468     BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
    469    
    470     SpeculateDoubleOperand op1(this, node.child1());
    471     SpeculateDoubleOperand op2(this, node.child2());
    472    
    473     addBranch(m_jit.branchDouble(condition, op1.fpr(), op2.fpr()), taken);
    474    
    475     if (notTaken != (m_block + 1))
    476         addBranch(m_jit.jump(), notTaken);
    477 }
    478 
    479 void SpeculativeJIT::compilePeepHoleObjectEquality(Node& node, NodeIndex branchNodeIndex, void* vptr)
    480 {
    481     Node& branchNode = m_jit.graph()[branchNodeIndex];
    482     BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
    483     BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
    484 
    485     MacroAssembler::RelationalCondition condition = MacroAssembler::Equal;
    486    
    487     if (taken == (m_block + 1)) {
    488         condition = MacroAssembler::NotEqual;
    489         BlockIndex tmp = taken;
    490         taken = notTaken;
    491         notTaken = tmp;
    492     }
    493 
    494     SpeculateCellOperand op1(this, node.child1());
    495     SpeculateCellOperand op2(this, node.child2());
    496    
    497     GPRReg op1GPR = op1.gpr();
    498     GPRReg op2GPR = op2.gpr();
    499    
    500     speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR), MacroAssembler::TrustedImmPtr(vptr)));
    501     speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR), MacroAssembler::TrustedImmPtr(vptr)));
    502    
    503     addBranch(m_jit.branchPtr(condition, op1GPR, op2GPR), taken);
    504     if (notTaken != (m_block + 1))
    505         addBranch(m_jit.jump(), notTaken);
    506345}
    507346
     
    556395        } else if (node.op == CompareEq && shouldSpeculateArray(node.child1(), node.child2())) {
    557396            compilePeepHoleObjectEquality(node, branchNodeIndex, m_jit.globalData()->jsArrayVPtr);
    558         // } else if (isKnownNumeric(node.child1()) || isKnownNumeric(node.child2())) {
    559         //    compilePeepHoleDoubleBranch(node, branchNodeIndex, doubleCondition, operation);
    560397            use(node.child1());
    561398            use(node.child2());
     
    567404    }
    568405
    569     // if (isKnownNotInteger(node.child1()) || isKnownNotInteger(node.child2()))
    570406    if (shouldSpeculateFinalObject(node.child1(), node.child2()))
    571407        compileObjectEquality(node, m_jit.globalData()->jsFinalObjectVPtr);
     
    603439   
    604440    return false;
    605 }
    606 
    607 template<typename T>
    608 void SpeculativeJIT::emitAllocateJSFinalObject(T structure, GPRReg resultGPR, GPRReg scratchGPR, MacroAssembler::JumpList& slowPath)
    609 {
    610     MarkedSpace::SizeClass* sizeClass = &m_jit.globalData()->heap.sizeClassForObject(sizeof(JSFinalObject));
    611    
    612     m_jit.loadPtr(&sizeClass->firstFreeCell, resultGPR);
    613     slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, resultGPR));
    614    
    615     // The object is half-allocated: we have what we know is a fresh object, but
    616     // it's still on the GC's free list.
    617    
    618     // Ditch the structure by placing it into the structure slot, so that we can reuse
    619     // scratchGPR.
    620     m_jit.storePtr(structure, MacroAssembler::Address(resultGPR, JSObject::structureOffset()));
    621    
    622     // Now that we have scratchGPR back, remove the object from the free list
    623     m_jit.loadPtr(MacroAssembler::Address(resultGPR), scratchGPR);
    624     m_jit.storePtr(scratchGPR, &sizeClass->firstFreeCell);
    625    
    626     // Initialize the object's vtable
    627     m_jit.storePtr(MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsFinalObjectVPtr), MacroAssembler::Address(resultGPR));
    628    
    629     // Initialize the object's inheritorID.
    630     m_jit.storePtr(MacroAssembler::TrustedImmPtr(0), MacroAssembler::Address(resultGPR, JSObject::offsetOfInheritorID()));
    631    
    632     // Initialize the object's property storage pointer.
    633     m_jit.addPtr(MacroAssembler::TrustedImm32(sizeof(JSObject)), resultGPR, scratchGPR);
    634     m_jit.storePtr(scratchGPR, MacroAssembler::Address(resultGPR, JSFinalObject::offsetOfPropertyStorage()));
    635441}
    636442
     
    21341940}
    21351941
    2136 void SpeculativeJIT::compileMovHint(Node& node)
    2137 {
    2138     ASSERT(node.op == SetLocal);
    2139    
    2140     setNodeIndexForOperand(node.child1(), node.local());
    2141     m_lastSetOperand = node.local();
    2142 }
    2143 
    2144 void SpeculativeJIT::compile(BasicBlock& block)
    2145 {
    2146     ASSERT(m_compileOkay);
    2147     ASSERT(m_compileIndex == block.begin);
    2148 
    2149     if (block.isOSRTarget)
    2150         m_jit.noticeOSREntry(block);
    2151 
    2152     m_blockHeads[m_block] = m_jit.label();
    2153 #if ENABLE(DFG_JIT_BREAK_ON_EVERY_BLOCK)
    2154     m_jit.breakpoint();
    21551942#endif
    21561943
    2157     ASSERT(m_arguments.size() == block.m_argumentsAtHead.size());
    2158     for (size_t i = 0; i < m_arguments.size(); ++i) {
    2159         NodeIndex nodeIndex = block.m_argumentsAtHead[i].value;
    2160         if (nodeIndex == NoNode)
    2161             m_arguments[i] = ValueSource(ValueInRegisterFile);
    2162         else
    2163             m_arguments[i] = ValueSource::forPrediction(m_jit.graph()[nodeIndex].variableAccessData()->prediction());
    2164     }
    2165    
    2166     ASSERT(m_variables.size() == block.m_localsAtHead.size());
    2167     for (size_t i = 0; i < m_variables.size(); ++i) {
    2168         NodeIndex nodeIndex = block.m_localsAtHead[i].value;
    2169         if (nodeIndex == NoNode)
    2170             m_variables[i] = ValueSource(ValueInRegisterFile);
    2171         else
    2172             m_variables[i] = ValueSource::forPrediction(m_jit.graph()[nodeIndex].variableAccessData()->prediction());
    2173     }
    2174    
    2175     m_lastSetOperand = std::numeric_limits<int>::max();
    2176     m_bytecodeIndexForOSR = std::numeric_limits<uint32_t>::max();
    2177 
    2178     for (; m_compileIndex < block.end; ++m_compileIndex) {
    2179         Node& node = m_jit.graph()[m_compileIndex];
    2180         m_bytecodeIndexForOSR = node.codeOrigin.bytecodeIndex();
    2181         if (!node.shouldGenerate()) {
    2182 #if ENABLE(DFG_DEBUG_VERBOSE)
    2183             fprintf(stderr, "SpeculativeJIT skipping Node @%d (bc#%u) at JIT offset 0x%x     ", (int)m_compileIndex, node.codeOrigin.bytecodeIndex(), m_jit.debugOffset());
     1944} } // namespace JSC::DFG
     1945
    21841946#endif
    2185             if (node.op == SetLocal)
    2186                 compileMovHint(node);
    2187         } else {
    2188            
    2189 #if ENABLE(DFG_DEBUG_VERBOSE)
    2190             fprintf(stderr, "SpeculativeJIT generating Node @%d (bc#%u) at JIT offset 0x%x   ", (int)m_compileIndex, node.codeOrigin.bytecodeIndex(), m_jit.debugOffset());
    2191 #endif
    2192 #if ENABLE(DFG_JIT_BREAK_ON_EVERY_NODE)
    2193             m_jit.breakpoint();
    2194 #endif
    2195             checkConsistency();
    2196             compile(node);
    2197             if (!m_compileOkay) {
    2198                 m_compileOkay = true;
    2199                 m_compileIndex = block.end;
    2200                 clearGenerationInfo();
    2201                 return;
    2202             }
    2203            
    2204 #if ENABLE(DFG_DEBUG_VERBOSE)
    2205             if (node.hasResult()) {
    2206                 GenerationInfo& info = m_generationInfo[node.virtualRegister()];
    2207                 fprintf(stderr, "-> %s, vr#%d", dataFormatToString(info.registerFormat()), (int)node.virtualRegister());
    2208                 if (info.registerFormat() != DataFormatNone) {
    2209                     if (info.registerFormat() == DataFormatDouble)
    2210                         fprintf(stderr, ", %s", FPRInfo::debugName(info.fpr()));
    2211                     else if (!(info.registerFormat() & DataFormatJS))
    2212                         fprintf(stderr, ", %s", GPRInfo::debugName(info.gpr()));
    2213                     else
    2214                         fprintf(stderr, ", %s %s", GPRInfo::debugName(info.tagGPR()), GPRInfo::debugName(info.payloadGPR()));
    2215                 }
    2216                 fprintf(stderr, "    ");
    2217             } else
    2218                 fprintf(stderr, "    ");
    2219 #endif
    2220         }
    2221        
    2222 #if ENABLE(DFG_VERBOSE_VALUE_RECOVERIES)
    2223         for (int operand = -m_arguments.size() - RegisterFile::CallFrameHeaderSize; operand < -RegisterFile::CallFrameHeaderSize; ++operand)
    2224             computeValueRecoveryFor(operand).dump(stderr);
    2225        
    2226         fprintf(stderr, " : ");
    2227        
    2228         for (int operand = 0; operand < (int)m_variables.size(); ++operand)
    2229             computeValueRecoveryFor(operand).dump(stderr);
    2230 #endif
    2231 
    2232 #if ENABLE(DFG_DEBUG_VERBOSE)
    2233         fprintf(stderr, "\n");
    2234 #endif
    2235        
    2236         if (node.shouldGenerate())
    2237             checkConsistency();
    2238     }
    2239 }
    2240 
    2241 // If we are making type predictions about our arguments then
    2242 // we need to check that they are correct on function entry.
    2243 void SpeculativeJIT::checkArgumentTypes()
    2244 {
    2245     ASSERT(!m_compileIndex);
    2246     m_bytecodeIndexForOSR = 0;
    2247 
    2248     for (size_t i = 0; i < m_arguments.size(); ++i)
    2249         m_arguments[i] = ValueSource(ValueInRegisterFile);
    2250     for (size_t i = 0; i < m_variables.size(); ++i)
    2251         m_variables[i] = ValueSource(ValueInRegisterFile);
    2252    
    2253     for (int i = 0; i < m_jit.codeBlock()->m_numParameters; ++i) {
    2254         VirtualRegister virtualRegister = (VirtualRegister)(m_jit.codeBlock()->thisRegister() + i);
    2255         PredictedType predictedType = m_jit.graph()[m_jit.graph().m_arguments[i]].variableAccessData()->prediction();
    2256         if (isInt32Prediction(predictedType))
    2257             speculationCheck(m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag)));
    2258         else if (isArrayPrediction(predictedType)) {
    2259             GPRTemporary temp(this);
    2260             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
    2261             speculationCheck(m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
    2262             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
    2263             speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
    2264         } // FIXME: need boolean predictions, but we currently don't have that support.
    2265     }
    2266 }
    2267 
    2268 bool SpeculativeJIT::compile()
    2269 {
    2270     checkArgumentTypes();
    2271 
    2272     ASSERT(!m_compileIndex);
    2273     for (m_block = 0; m_block < m_jit.graph().m_blocks.size(); ++m_block)
    2274         compile(*m_jit.graph().m_blocks[m_block]);
    2275     linkBranches();
    2276     return true;
    2277 }
    2278 
    2279 ValueRecovery SpeculativeJIT::computeValueRecoveryFor(const ValueSource& valueSource)
    2280 {
    2281     switch (valueSource.kind()) {
    2282     case ValueInRegisterFile:
    2283         return ValueRecovery::alreadyInRegisterFile();
    2284        
    2285     case Int32InRegisterFile:
    2286         return ValueRecovery::alreadyInRegisterFileAsUnboxedInt32();
    2287 
    2288     case HaveNode: {
    2289         if (m_jit.isConstant(valueSource.nodeIndex()))
    2290             return ValueRecovery::constant(m_jit.valueOfJSConstant(valueSource.nodeIndex()));
    2291    
    2292         Node* nodePtr = &m_jit.graph()[valueSource.nodeIndex()];
    2293         if (!nodePtr->shouldGenerate()) {
    2294             // It's legitimately dead. As in, nobody will ever use this node, or operand,
    2295             // ever. Set it to Undefined to make the GC happy after the OSR.
    2296             return ValueRecovery::constant(jsUndefined());
    2297         }
    2298    
    2299         GenerationInfo* infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
    2300         if (!infoPtr->alive() || infoPtr->nodeIndex() != valueSource.nodeIndex()) {
    2301             // Try to see if there is an alternate node that would contain the value we want.
    2302             // There are four possibilities:
    2303             //
    2304             // ValueToNumber: If the only live version of the value is a ValueToNumber node
    2305             //    then it means that all remaining uses of the value would have performed a
    2306             //    ValueToNumber conversion anyway. Thus, we can substitute ValueToNumber.
    2307             //
    2308             // ValueToInt32: Likewise, if the only remaining live version of the value is
    2309             //    ValueToInt32, then we can use it. But if there is both a ValueToInt32
    2310             //    and a ValueToNumber, then we better go with ValueToNumber because it
    2311             //    means that some remaining uses would have converted to number while
    2312             //    others would have converted to Int32.
    2313             //
    2314             // UInt32ToNumber: If the only live version of the value is a UInt32ToNumber
    2315             //    then the only remaining uses are ones that want a properly formed number
    2316             //    rather than a UInt32 intermediate.
    2317             //
    2318             // The reverse of the above: This node could be a UInt32ToNumber, but its
    2319             //    alternative is still alive. This means that the only remaining uses of
    2320             //    the number would be fine with a UInt32 intermediate.
    2321        
    2322             bool found = false;
    2323        
    2324             if (nodePtr->op == UInt32ToNumber) {
    2325                 NodeIndex nodeIndex = nodePtr->child1();
    2326                 nodePtr = &m_jit.graph()[nodeIndex];
    2327                 infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
    2328                 if (infoPtr->alive() && infoPtr->nodeIndex() == nodeIndex)
    2329                     found = true;
    2330             }
    2331        
    2332             if (!found) {
    2333                 NodeIndex valueToNumberIndex = NoNode;
    2334                 NodeIndex valueToInt32Index = NoNode;
    2335                 NodeIndex uint32ToNumberIndex = NoNode;
    2336            
    2337                 for (unsigned virtualRegister = 0; virtualRegister < m_generationInfo.size(); ++virtualRegister) {
    2338                     GenerationInfo& info = m_generationInfo[virtualRegister];
    2339                     if (!info.alive())
    2340                         continue;
    2341                     if (info.nodeIndex() == NoNode)
    2342                         continue;
    2343                     Node& node = m_jit.graph()[info.nodeIndex()];
    2344                     if (node.child1Unchecked() != valueSource.nodeIndex())
    2345                         continue;
    2346                     switch (node.op) {
    2347                     case ValueToNumber:
    2348                     case ValueToDouble:
    2349                         valueToNumberIndex = info.nodeIndex();
    2350                         break;
    2351                     case ValueToInt32:
    2352                         valueToInt32Index = info.nodeIndex();
    2353                         break;
    2354                     case UInt32ToNumber:
    2355                         uint32ToNumberIndex = info.nodeIndex();
    2356                         break;
    2357                     default:
    2358                         break;
    2359                     }
    2360                 }
    2361            
    2362                 NodeIndex nodeIndexToUse;
    2363                 if (valueToNumberIndex != NoNode)
    2364                     nodeIndexToUse = valueToNumberIndex;
    2365                 else if (valueToInt32Index != NoNode)
    2366                     nodeIndexToUse = valueToInt32Index;
    2367                 else if (uint32ToNumberIndex != NoNode)
    2368                     nodeIndexToUse = uint32ToNumberIndex;
    2369                 else
    2370                     nodeIndexToUse = NoNode;
    2371            
    2372                 if (nodeIndexToUse != NoNode) {
    2373                     nodePtr = &m_jit.graph()[nodeIndexToUse];
    2374                     infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
    2375                     ASSERT(infoPtr->alive() && infoPtr->nodeIndex() == nodeIndexToUse);
    2376                     found = true;
    2377                 }
    2378             }
    2379        
    2380             if (!found)
    2381                 return ValueRecovery::constant(jsUndefined());
    2382         }
    2383    
    2384         ASSERT(infoPtr->alive());
    2385 
    2386         if (infoPtr->registerFormat() != DataFormatNone) {
    2387             if (infoPtr->registerFormat() == DataFormatDouble)
    2388                 return ValueRecovery::inFPR(infoPtr->fpr());
    2389             if (infoPtr->registerFormat() & DataFormatJS)
    2390                 return ValueRecovery::inPair(infoPtr->tagGPR(), infoPtr->payloadGPR());
    2391             return ValueRecovery::inGPR(infoPtr->gpr(), infoPtr->registerFormat());
    2392         }
    2393         if (infoPtr->spillFormat() != DataFormatNone)
    2394             return ValueRecovery::displacedInRegisterFile(static_cast<VirtualRegister>(nodePtr->virtualRegister()));
    2395    
    2396         ASSERT_NOT_REACHED();
    2397         return ValueRecovery();
    2398     }
    2399        
    2400     default:
    2401         ASSERT_NOT_REACHED();
    2402         return ValueRecovery();
    2403     }
    2404 }
    2405 
    2406 } } // namespace JSC::DFG
    2407 
    2408 #endif
    2409 #endif
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r96376 r96379  
    2525
    2626#include "config.h"
    27 
    2827#include "DFGSpeculativeJIT.h"
    2928
    3029#if ENABLE(DFG_JIT)
     30
     31namespace JSC { namespace DFG {
     32
    3133#if USE(JSVALUE64)
    32 
    33 namespace JSC { namespace DFG {
    3434
    3535template<bool strict>
     
    144144        return allocate();
    145145    }
    146        
     146
    147147    case DataFormatStorage:
    148148        ASSERT_NOT_REACHED();
     
    152152    return InvalidGPRReg;
    153153}
    154 
    155 #ifndef NDEBUG
    156 void ValueSource::dump(FILE* out) const
    157 {
    158     switch (kind()) {
    159     case SourceNotSet:
    160         fprintf(out, "NotSet");
    161         break;
    162     case ValueInRegisterFile:
    163         fprintf(out, "InRegFile");
    164         break;
    165     case Int32InRegisterFile:
    166         fprintf(out, "Int32");
    167         break;
    168     case HaveNode:
    169         fprintf(out, "Node(%d)", m_nodeIndex);
    170         break;
    171     }
    172 }
    173 
    174 void ValueRecovery::dump(FILE* out) const
    175 {
    176     switch (technique()) {
    177     case AlreadyInRegisterFile:
    178         fprintf(out, "-");
    179         break;
    180     case AlreadyInRegisterFileAsUnboxedInt32:
    181         fprintf(out, "(int32)");
    182         break;
    183     case InGPR:
    184         fprintf(out, "%%%s", GPRInfo::debugName(gpr()));
    185         break;
    186     case UnboxedInt32InGPR:
    187         fprintf(out, "int32(%%%s)", GPRInfo::debugName(gpr()));
    188         break;
    189     case InFPR:
    190         fprintf(out, "%%%s", FPRInfo::debugName(fpr()));
    191         break;
    192     case DisplacedInRegisterFile:
    193         fprintf(out, "*%d", virtualRegister());
    194         break;
    195     case Constant:
    196         fprintf(out, "[%s]", constant().description());
    197         break;
    198     case DontKnow:
    199         fprintf(out, "!");
    200         break;
    201     default:
    202         fprintf(out, "?%d", technique());
    203         break;
    204     }
    205 }
    206 #endif
    207 
    208 OSRExit::OSRExit(MacroAssembler::Jump check, SpeculativeJIT* jit, unsigned recoveryIndex)
    209     : m_check(check)
    210     , m_nodeIndex(jit->m_compileIndex)
    211     , m_bytecodeIndex(jit->m_bytecodeIndexForOSR)
    212     , m_recoveryIndex(recoveryIndex)
    213     , m_arguments(jit->m_arguments.size())
    214     , m_variables(jit->m_variables.size())
    215     , m_lastSetOperand(jit->m_lastSetOperand)
    216 {
    217     ASSERT(m_bytecodeIndex != std::numeric_limits<uint32_t>::max());
    218     for (unsigned argument = 0; argument < m_arguments.size(); ++argument)
    219         m_arguments[argument] = jit->computeValueRecoveryFor(jit->m_arguments[argument]);
    220     for (unsigned variable = 0; variable < m_variables.size(); ++variable)
    221         m_variables[variable] = jit->computeValueRecoveryFor(jit->m_variables[variable]);
    222 }
    223 
    224 #ifndef NDEBUG
    225 void OSRExit::dump(FILE* out) const
    226 {
    227     for (unsigned argument = 0; argument < m_arguments.size(); ++argument)
    228         m_arguments[argument].dump(out);
    229     fprintf(out, " : ");
    230     for (unsigned variable = 0; variable < m_variables.size(); ++variable)
    231         m_variables[variable].dump(out);
    232 }
    233 #endif
    234154
    235155GPRReg SpeculativeJIT::fillSpeculateInt(NodeIndex nodeIndex, DataFormat& returnFormat)
     
    429349        return allocate();
    430350    }
    431        
     351
    432352    case DataFormatStorage:
    433353        ASSERT_NOT_REACHED();
     
    509429    ASSERT_NOT_REACHED();
    510430    return InvalidGPRReg;
    511 }
    512 
    513 void SpeculativeJIT::compilePeepHoleIntegerBranch(Node& node, NodeIndex branchNodeIndex, JITCompiler::RelationalCondition condition)
    514 {
    515     Node& branchNode = m_jit.graph()[branchNodeIndex];
    516     BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
    517     BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
    518 
    519     // The branch instruction will branch to the taken block.
    520     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
    521     if (taken == (m_block + 1)) {
    522         condition = JITCompiler::invert(condition);
    523         BlockIndex tmp = taken;
    524         taken = notTaken;
    525         notTaken = tmp;
    526     }
    527 
    528     if (isInt32Constant(node.child1())) {
    529         int32_t imm = valueOfInt32Constant(node.child1());
    530         SpeculateIntegerOperand op2(this, node.child2());
    531         addBranch(m_jit.branch32(condition, JITCompiler::Imm32(imm), op2.gpr()), taken);
    532     } else if (isInt32Constant(node.child2())) {
    533         SpeculateIntegerOperand op1(this, node.child1());
    534         int32_t imm = valueOfInt32Constant(node.child2());
    535         addBranch(m_jit.branch32(condition, op1.gpr(), JITCompiler::Imm32(imm)), taken);
    536     } else {
    537         SpeculateIntegerOperand op1(this, node.child1());
    538         SpeculateIntegerOperand op2(this, node.child2());
    539         addBranch(m_jit.branch32(condition, op1.gpr(), op2.gpr()), taken);
    540     }
    541 
    542     // Check for fall through, otherwise we need to jump.
    543     if (notTaken != (m_block + 1))
    544         addBranch(m_jit.jump(), notTaken);
    545431}
    546432
     
    563449
    564450    return notNumber;
    565 }
    566 
    567 void SpeculativeJIT::compilePeepHoleDoubleBranch(Node& node, NodeIndex branchNodeIndex, JITCompiler::DoubleCondition condition)
    568 {
    569     Node& branchNode = m_jit.graph()[branchNodeIndex];
    570     BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
    571     BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
    572    
    573     SpeculateDoubleOperand op1(this, node.child1());
    574     SpeculateDoubleOperand op2(this, node.child2());
    575    
    576     addBranch(m_jit.branchDouble(condition, op1.fpr(), op2.fpr()), taken);
    577    
    578     if (notTaken != (m_block + 1))
    579         addBranch(m_jit.jump(), notTaken);
    580 }
    581 
    582 void SpeculativeJIT::compilePeepHoleObjectEquality(Node& node, NodeIndex branchNodeIndex, void* vptr)
    583 {
    584     Node& branchNode = m_jit.graph()[branchNodeIndex];
    585     BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
    586     BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
    587 
    588     MacroAssembler::RelationalCondition condition = MacroAssembler::Equal;
    589    
    590     if (taken == (m_block + 1)) {
    591         condition = MacroAssembler::NotEqual;
    592         BlockIndex tmp = taken;
    593         taken = notTaken;
    594         notTaken = tmp;
    595     }
    596 
    597     SpeculateCellOperand op1(this, node.child1());
    598     SpeculateCellOperand op2(this, node.child2());
    599    
    600     GPRReg op1GPR = op1.gpr();
    601     GPRReg op2GPR = op2.gpr();
    602    
    603     speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR), MacroAssembler::TrustedImmPtr(vptr)));
    604     speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR), MacroAssembler::TrustedImmPtr(vptr)));
    605    
    606     addBranch(m_jit.branchPtr(condition, op1GPR, op2GPR), taken);
    607     if (notTaken != (m_block + 1))
    608         addBranch(m_jit.jump(), notTaken);
    609451}
    610452
     
    696538}
    697539
    698 template<typename T>
    699 void SpeculativeJIT::emitAllocateJSFinalObject(T structure, GPRReg resultGPR, GPRReg scratchGPR, MacroAssembler::JumpList& slowPath)
    700 {
    701     MarkedSpace::SizeClass* sizeClass = &m_jit.globalData()->heap.sizeClassForObject(sizeof(JSFinalObject));
    702    
    703     m_jit.loadPtr(&sizeClass->firstFreeCell, resultGPR);
    704     slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, resultGPR));
    705    
    706     // The object is half-allocated: we have what we know is a fresh object, but
    707     // it's still on the GC's free list.
    708    
    709     // Ditch the structure by placing it into the structure slot, so that we can reuse
    710     // scratchGPR.
    711     m_jit.storePtr(structure, MacroAssembler::Address(resultGPR, JSObject::structureOffset()));
    712    
    713     // Now that we have scratchGPR back, remove the object from the free list
    714     m_jit.loadPtr(MacroAssembler::Address(resultGPR), scratchGPR);
    715     m_jit.storePtr(scratchGPR, &sizeClass->firstFreeCell);
    716    
    717     // Initialize the object's vtable
    718     m_jit.storePtr(MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsFinalObjectVPtr), MacroAssembler::Address(resultGPR));
    719    
    720     // Initialize the object's inheritorID.
    721     m_jit.storePtr(MacroAssembler::TrustedImmPtr(0), MacroAssembler::Address(resultGPR, JSObject::offsetOfInheritorID()));
    722    
    723     // Initialize the object's property storage pointer.
    724     m_jit.addPtr(MacroAssembler::TrustedImm32(sizeof(JSObject)), resultGPR, scratchGPR);
    725     m_jit.storePtr(scratchGPR, MacroAssembler::Address(resultGPR, JSFinalObject::offsetOfPropertyStorage()));
    726 }
    727 
    728540void SpeculativeJIT::compile(Node& node)
    729541{
     
    768580            else
    769581                format = DataFormatJS;
    770            
     582
    771583            m_generationInfo[virtualRegister].initJSValue(m_compileIndex, node.refCount(), result.gpr(), format);
    772584        }
     
    831643            noResult(m_compileIndex);
    832644        }
    833        
     645
    834646        // Indicate that it's no longer necessary to retrieve the value of
    835647        // this bytecode variable from registers or other locations in the register file.
     
    837649        break;
    838650    }
    839        
     651
    840652    case SetArgument:
    841653        // This is a no-op; it just marks the fact that the argument is being used.
     
    918730            doubleResult(outputFPR, m_compileIndex);
    919731        }
    920        
     732
    921733        IntegerOperand op1(this, node.child1());
    922734        GPRTemporary result(this, op1);
     
    929741        break;
    930742    }
    931        
     743
    932744    case ValueToInt32: {
    933745        if (shouldNotSpeculateInteger(node.child1())) {
     
    981793                SpeculateIntegerOperand op2(this, node.child2());
    982794                GPRTemporary result(this);
    983                
     795
    984796                if (nodeCanTruncateInteger(node.arithNodeFlags())) {
    985797                    m_jit.move(op2.gpr(), result.gpr());
     
    1014826            GPRReg gpr2 = op2.gpr();
    1015827            GPRReg gprResult = result.gpr();
    1016            
     828
    1017829            if (nodeCanTruncateInteger(node.arithNodeFlags())) {
    1018830                if (gpr1 == gprResult)
     
    1041853            SpeculateDoubleOperand op2(this, node.child2());
    1042854            FPRTemporary result(this, op1, op2);
    1043            
     855
    1044856            FPRReg reg1 = op1.fpr();
    1045857            FPRReg reg2 = op2.fpr();
    1046858            m_jit.addDouble(reg1, reg2, result.fpr());
    1047            
     859
    1048860            doubleResult(result.fpr(), m_compileIndex);
    1049861            break;
    1050862        }
    1051        
     863
    1052864        ASSERT(op == ValueAdd);
    1053        
     865
    1054866        JSValueOperand op1(this, node.child1());
    1055867        JSValueOperand op2(this, node.child2());
     
    1121933            GPRReg reg1 = op1.gpr();
    1122934            GPRReg reg2 = op2.gpr();
    1123            
     935
    1124936            // What is unfortunate is that we cannot take advantage of nodeCanTruncateInteger()
    1125937            // here. A multiply on integers performed in the double domain and then truncated to
     
    1143955            break;
    1144956        }
    1145        
     957
    1146958        SpeculateDoubleOperand op1(this, node.child1());
    1147959        SpeculateDoubleOperand op2(this, node.child2());
     
    12521064        break;
    12531065    }
    1254        
     1066
    12551067    case ArithAbs: {
    12561068        if (shouldSpeculateInteger(node.child1()) && nodeCanSpeculateInteger(node.arithNodeFlags())) {
     
    19711783        break;
    19721784    }
    1973        
     1785
    19741786    case CheckMethod: {
    19751787        MethodCheckData& methodCheckData = m_jit.graph().m_methodCheckData[node.methodCheckDataIndex()];
     
    21962008        break;
    21972009    }
    2198    
     2010
    21992011    if (node.hasResult() && node.mustGenerate())
    22002012        use(m_compileIndex);
    22012013}
    22022014
    2203 void SpeculativeJIT::compileMovHint(Node& node)
    2204 {
    2205     ASSERT(node.op == SetLocal);
    2206    
    2207     setNodeIndexForOperand(node.child1(), node.local());
    2208     m_lastSetOperand = node.local();
    2209 }
    2210 
    2211 void SpeculativeJIT::compile(BasicBlock& block)
    2212 {
    2213     ASSERT(m_compileOkay);
    2214     ASSERT(m_compileIndex == block.begin);
    2215    
    2216     if (block.isOSRTarget)
    2217         m_jit.noticeOSREntry(block);
    2218    
    2219     m_blockHeads[m_block] = m_jit.label();
    2220 #if ENABLE(DFG_JIT_BREAK_ON_EVERY_BLOCK)
    2221     m_jit.breakpoint();
    22222015#endif
    2223    
    2224     ASSERT(m_arguments.size() == block.m_argumentsAtHead.size());
    2225     for (size_t i = 0; i < m_arguments.size(); ++i) {
    2226         NodeIndex nodeIndex = block.m_argumentsAtHead[i].value;
    2227         if (nodeIndex == NoNode)
    2228             m_arguments[i] = ValueSource(ValueInRegisterFile);
    2229         else
    2230             m_arguments[i] = ValueSource::forPrediction(m_jit.graph()[nodeIndex].variableAccessData()->prediction());
    2231     }
    2232    
    2233     ASSERT(m_variables.size() == block.m_localsAtHead.size());
    2234     for (size_t i = 0; i < m_variables.size(); ++i) {
    2235         NodeIndex nodeIndex = block.m_localsAtHead[i].value;
    2236         if (nodeIndex == NoNode)
    2237             m_variables[i] = ValueSource(ValueInRegisterFile);
    2238         else
    2239             m_variables[i] = ValueSource::forPrediction(m_jit.graph()[nodeIndex].variableAccessData()->prediction());
    2240     }
    2241    
    2242     m_lastSetOperand = std::numeric_limits<int>::max();
    2243     m_bytecodeIndexForOSR = std::numeric_limits<uint32_t>::max();
    2244 
    2245     for (; m_compileIndex < block.end; ++m_compileIndex) {
    2246         Node& node = m_jit.graph()[m_compileIndex];
    2247         m_bytecodeIndexForOSR = node.codeOrigin.bytecodeIndex();
    2248         if (!node.shouldGenerate()) {
    2249 #if ENABLE(DFG_DEBUG_VERBOSE)
    2250             fprintf(stderr, "SpeculativeJIT skipping Node @%d (bc#%u) at JIT offset 0x%x     ", (int)m_compileIndex, node.codeOrigin.bytecodeIndex(), m_jit.debugOffset());
     2016
     2017} } // namespace JSC::DFG
     2018
    22512019#endif
    2252             if (node.op == SetLocal)
    2253                 compileMovHint(node);
    2254         } else {
    2255            
    2256 #if ENABLE(DFG_DEBUG_VERBOSE)
    2257             fprintf(stderr, "SpeculativeJIT generating Node @%d (bc#%u) at JIT offset 0x%x   ", (int)m_compileIndex, node.codeOrigin.bytecodeIndex(), m_jit.debugOffset());
    2258 #endif
    2259 #if ENABLE(DFG_JIT_BREAK_ON_EVERY_NODE)
    2260             m_jit.breakpoint();
    2261 #endif
    2262             checkConsistency();
    2263             compile(node);
    2264             if (!m_compileOkay) {
    2265                 m_compileOkay = true;
    2266                 m_compileIndex = block.end;
    2267                 clearGenerationInfo();
    2268                 return;
    2269             }
    2270            
    2271 #if ENABLE(DFG_DEBUG_VERBOSE)
    2272             if (node.hasResult()) {
    2273                 GenerationInfo& info = m_generationInfo[node.virtualRegister()];
    2274                 fprintf(stderr, "-> %s, vr#%d", dataFormatToString(info.registerFormat()), (int)node.virtualRegister());
    2275                 if (info.registerFormat() != DataFormatNone) {
    2276                     if (info.registerFormat() == DataFormatDouble)
    2277                         fprintf(stderr, ", %s", FPRInfo::debugName(info.fpr()));
    2278                     else
    2279                         fprintf(stderr, ", %s", GPRInfo::debugName(info.gpr()));
    2280                 }
    2281                 fprintf(stderr, "    ");
    2282             } else
    2283                 fprintf(stderr, "    ");
    2284 #endif
    2285         }
    2286        
    2287 #if ENABLE(DFG_VERBOSE_VALUE_RECOVERIES)
    2288         for (int operand = -m_arguments.size() - RegisterFile::CallFrameHeaderSize; operand < -RegisterFile::CallFrameHeaderSize; ++operand)
    2289             computeValueRecoveryFor(operand).dump(stderr);
    2290        
    2291         fprintf(stderr, " : ");
    2292        
    2293         for (int operand = 0; operand < (int)m_variables.size(); ++operand)
    2294             computeValueRecoveryFor(operand).dump(stderr);
    2295 #endif
    2296      
    2297 #if ENABLE(DFG_DEBUG_VERBOSE)
    2298         fprintf(stderr, "\n");
    2299 #endif
    2300        
    2301         if (node.shouldGenerate())
    2302             checkConsistency();
    2303     }
    2304 }
    2305 
    2306 // If we are making type predictions about our arguments then
    2307 // we need to check that they are correct on function entry.
    2308 void SpeculativeJIT::checkArgumentTypes()
    2309 {
    2310     ASSERT(!m_compileIndex);
    2311     m_bytecodeIndexForOSR = 0;
    2312 
    2313     for (size_t i = 0; i < m_arguments.size(); ++i)
    2314         m_arguments[i] = ValueSource(ValueInRegisterFile);
    2315     for (size_t i = 0; i < m_variables.size(); ++i)
    2316         m_variables[i] = ValueSource(ValueInRegisterFile);
    2317    
    2318     for (int i = 0; i < m_jit.codeBlock()->m_numParameters; ++i) {
    2319         VirtualRegister virtualRegister = (VirtualRegister)(m_jit.codeBlock()->thisRegister() + i);
    2320         PredictedType predictedType = m_jit.graph()[m_jit.graph().m_arguments[i]].variableAccessData()->prediction();
    2321         if (isInt32Prediction(predictedType))
    2322             speculationCheck(m_jit.branchPtr(MacroAssembler::Below, JITCompiler::addressFor(virtualRegister), GPRInfo::tagTypeNumberRegister));
    2323         else if (isArrayPrediction(predictedType)) {
    2324             GPRTemporary temp(this);
    2325             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
    2326             speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
    2327             speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
    2328         } else if (isBooleanPrediction(predictedType)) {
    2329             GPRTemporary temp(this);
    2330             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
    2331             m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), temp.gpr());
    2332             speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
    2333         }
    2334     }
    2335 }
    2336 
    2337 bool SpeculativeJIT::compile()
    2338 {
    2339     checkArgumentTypes();
    2340 
    2341     ASSERT(!m_compileIndex);
    2342     for (m_block = 0; m_block < m_jit.graph().m_blocks.size(); ++m_block)
    2343         compile(*m_jit.graph().m_blocks[m_block]);
    2344     linkBranches();
    2345     return true;
    2346 }
    2347 
    2348 ValueRecovery SpeculativeJIT::computeValueRecoveryFor(const ValueSource& valueSource)
    2349 {
    2350     switch (valueSource.kind()) {
    2351     case ValueInRegisterFile:
    2352         return ValueRecovery::alreadyInRegisterFile();
    2353        
    2354     case Int32InRegisterFile:
    2355         return ValueRecovery::alreadyInRegisterFileAsUnboxedInt32();
    2356        
    2357     case HaveNode: {
    2358         if (m_jit.isConstant(valueSource.nodeIndex()))
    2359             return ValueRecovery::constant(m_jit.valueOfJSConstant(valueSource.nodeIndex()));
    2360    
    2361         Node* nodePtr = &m_jit.graph()[valueSource.nodeIndex()];
    2362         if (!nodePtr->shouldGenerate()) {
    2363             // It's legitimately dead. As in, nobody will ever use this node, or operand,
    2364             // ever. Set it to Undefined to make the GC happy after the OSR.
    2365             return ValueRecovery::constant(jsUndefined());
    2366         }
    2367    
    2368         GenerationInfo* infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
    2369         if (!infoPtr->alive() || infoPtr->nodeIndex() != valueSource.nodeIndex()) {
    2370             // Try to see if there is an alternate node that would contain the value we want.
    2371             // There are four possibilities:
    2372             //
    2373             // ValueToNumber: If the only live version of the value is a ValueToNumber node
    2374             //    then it means that all remaining uses of the value would have performed a
    2375             //    ValueToNumber conversion anyway. Thus, we can substitute ValueToNumber.
    2376             //
    2377             // ValueToInt32: Likewise, if the only remaining live version of the value is
    2378             //    ValueToInt32, then we can use it. But if there is both a ValueToInt32
    2379             //    and a ValueToNumber, then we better go with ValueToNumber because it
    2380             //    means that some remaining uses would have converted to number while
    2381             //    others would have converted to Int32.
    2382             //
    2383             // UInt32ToNumber: If the only live version of the value is a UInt32ToNumber
    2384             //    then the only remaining uses are ones that want a properly formed number
    2385             //    rather than a UInt32 intermediate.
    2386             //
    2387             // The reverse of the above: This node could be a UInt32ToNumber, but its
    2388             //    alternative is still alive. This means that the only remaining uses of
    2389             //    the number would be fine with a UInt32 intermediate.
    2390        
    2391             bool found = false;
    2392        
    2393             if (nodePtr->op == UInt32ToNumber) {
    2394                 NodeIndex nodeIndex = nodePtr->child1();
    2395                 nodePtr = &m_jit.graph()[nodeIndex];
    2396                 infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
    2397                 if (infoPtr->alive() && infoPtr->nodeIndex() == nodeIndex)
    2398                     found = true;
    2399             }
    2400        
    2401             if (!found) {
    2402                 NodeIndex valueToNumberIndex = NoNode;
    2403                 NodeIndex valueToInt32Index = NoNode;
    2404                 NodeIndex uint32ToNumberIndex = NoNode;
    2405            
    2406                 for (unsigned virtualRegister = 0; virtualRegister < m_generationInfo.size(); ++virtualRegister) {
    2407                     GenerationInfo& info = m_generationInfo[virtualRegister];
    2408                     if (!info.alive())
    2409                         continue;
    2410                     if (info.nodeIndex() == NoNode)
    2411                         continue;
    2412                     Node& node = m_jit.graph()[info.nodeIndex()];
    2413                     if (node.child1Unchecked() != valueSource.nodeIndex())
    2414                         continue;
    2415                     switch (node.op) {
    2416                     case ValueToNumber:
    2417                     case ValueToDouble:
    2418                         valueToNumberIndex = info.nodeIndex();
    2419                         break;
    2420                     case ValueToInt32:
    2421                         valueToInt32Index = info.nodeIndex();
    2422                         break;
    2423                     case UInt32ToNumber:
    2424                         uint32ToNumberIndex = info.nodeIndex();
    2425                         break;
    2426                     default:
    2427                         break;
    2428                     }
    2429                 }
    2430            
    2431                 NodeIndex nodeIndexToUse;
    2432                 if (valueToNumberIndex != NoNode)
    2433                     nodeIndexToUse = valueToNumberIndex;
    2434                 else if (valueToInt32Index != NoNode)
    2435                     nodeIndexToUse = valueToInt32Index;
    2436                 else if (uint32ToNumberIndex != NoNode)
    2437                     nodeIndexToUse = uint32ToNumberIndex;
    2438                 else
    2439                     nodeIndexToUse = NoNode;
    2440            
    2441                 if (nodeIndexToUse != NoNode) {
    2442                     nodePtr = &m_jit.graph()[nodeIndexToUse];
    2443                     infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
    2444                     ASSERT(infoPtr->alive() && infoPtr->nodeIndex() == nodeIndexToUse);
    2445                     found = true;
    2446                 }
    2447             }
    2448        
    2449             if (!found)
    2450                 return ValueRecovery::constant(jsUndefined());
    2451         }
    2452    
    2453         ASSERT(infoPtr->alive());
    2454 
    2455         if (infoPtr->registerFormat() != DataFormatNone) {
    2456             if (infoPtr->registerFormat() == DataFormatDouble)
    2457                 return ValueRecovery::inFPR(infoPtr->fpr());
    2458             return ValueRecovery::inGPR(infoPtr->gpr(), infoPtr->registerFormat());
    2459         }
    2460         if (infoPtr->spillFormat() != DataFormatNone)
    2461             return ValueRecovery::displacedInRegisterFile(static_cast<VirtualRegister>(nodePtr->virtualRegister()));
    2462    
    2463         ASSERT_NOT_REACHED();
    2464         return ValueRecovery();
    2465     }
    2466        
    2467     default:
    2468         ASSERT_NOT_REACHED();
    2469         return ValueRecovery();
    2470     }
    2471 }
    2472 
    2473 } } // namespace JSC::DFG
    2474 
    2475 #endif
    2476 #endif
Note: See TracChangeset for help on using the changeset viewer.