Home | History | Annotate | Download | only in dfg
      1 /*
      2  * Copyright (C) 2011 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "DFGNonSpeculativeJIT.h"
     28 
     29 #include "DFGSpeculativeJIT.h"
     30 
     31 #if ENABLE(DFG_JIT)
     32 
     33 namespace JSC { namespace DFG {
     34 
     35 const double twoToThe32 = (double)0x100000000ull;
     36 
     37 EntryLocation::EntryLocation(MacroAssembler::Label entry, NonSpeculativeJIT* jit)
     38     : m_entry(entry)
     39     , m_nodeIndex(jit->m_compileIndex)
     40 {
     41     for (GPRReg gpr = gpr0; gpr < numberOfGPRs; next(gpr)) {
     42         VirtualRegister virtualRegister = jit->m_gprs.name(gpr);
     43         if (virtualRegister != InvalidVirtualRegister) {
     44             GenerationInfo& info =  jit->m_generationInfo[virtualRegister];
     45             m_gprInfo[gpr].nodeIndex = info.nodeIndex();
     46             m_gprInfo[gpr].format = info.registerFormat();
     47         } else
     48             m_gprInfo[gpr].nodeIndex = NoNode;
     49     }
     50     for (FPRReg fpr = fpr0; fpr < numberOfFPRs; next(fpr)) {
     51         VirtualRegister virtualRegister = jit->m_fprs.name(fpr);
     52         if (virtualRegister != InvalidVirtualRegister) {
     53             GenerationInfo& info =  jit->m_generationInfo[virtualRegister];
     54             ASSERT(info.registerFormat() == DataFormatDouble);
     55             m_fprInfo[fpr] = info.nodeIndex();
     56         } else
     57             m_fprInfo[fpr] = NoNode;
     58     }
     59 }
     60 
     61 void NonSpeculativeJIT::valueToNumber(JSValueOperand& operand, FPRReg fpr)
     62 {
     63     GPRReg jsValueGpr = operand.gpr();
     64     GPRReg tempGpr = allocate(); // FIXME: can we skip this allocation on the last use of the virtual register?
     65 
     66     JITCompiler::RegisterID jsValueReg = JITCompiler::gprToRegisterID(jsValueGpr);
     67     JITCompiler::FPRegisterID fpReg = JITCompiler::fprToRegisterID(fpr);
     68     JITCompiler::RegisterID tempReg = JITCompiler::gprToRegisterID(tempGpr);
     69 
     70     JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueReg, JITCompiler::tagTypeNumberRegister);
     71     JITCompiler::Jump nonNumeric = m_jit.branchTestPtr(MacroAssembler::Zero, jsValueReg, JITCompiler::tagTypeNumberRegister);
     72 
     73     // First, if we get here we have a double encoded as a JSValue
     74     m_jit.move(jsValueReg, tempReg);
     75     m_jit.addPtr(JITCompiler::tagTypeNumberRegister, tempReg);
     76     m_jit.movePtrToDouble(tempReg, fpReg);
     77     JITCompiler::Jump hasUnboxedDouble = m_jit.jump();
     78 
     79     // Next handle cells (& other JS immediates)
     80     nonNumeric.link(&m_jit);
     81     silentSpillAllRegisters(fpr, jsValueGpr);
     82     m_jit.move(jsValueReg, JITCompiler::argumentRegister1);
     83     m_jit.move(JITCompiler::callFrameRegister, JITCompiler::argumentRegister0);
     84     appendCallWithExceptionCheck(dfgConvertJSValueToNumber);
     85     m_jit.moveDouble(JITCompiler::fpReturnValueRegister, fpReg);
     86     silentFillAllRegisters(fpr);
     87     JITCompiler::Jump hasCalledToNumber = m_jit.jump();
     88 
     89     // Finally, handle integers.
     90     isInteger.link(&m_jit);
     91     m_jit.convertInt32ToDouble(jsValueReg, fpReg);
     92     hasUnboxedDouble.link(&m_jit);
     93     hasCalledToNumber.link(&m_jit);
     94 
     95     m_gprs.unlock(tempGpr);
     96 }
     97 
     98 void NonSpeculativeJIT::valueToInt32(JSValueOperand& operand, GPRReg result)
     99 {
    100     GPRReg jsValueGpr = operand.gpr();
    101 
    102     JITCompiler::RegisterID jsValueReg = JITCompiler::gprToRegisterID(jsValueGpr);
    103     JITCompiler::RegisterID resultReg = JITCompiler::gprToRegisterID(result);
    104 
    105     JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueReg, JITCompiler::tagTypeNumberRegister);
    106 
    107     // First handle non-integers
    108     silentSpillAllRegisters(result, jsValueGpr);
    109     m_jit.move(jsValueReg, JITCompiler::argumentRegister1);
    110     m_jit.move(JITCompiler::callFrameRegister, JITCompiler::argumentRegister0);
    111     appendCallWithExceptionCheck(dfgConvertJSValueToInt32);
    112     m_jit.zeroExtend32ToPtr(JITCompiler::returnValueRegister, resultReg);
    113     silentFillAllRegisters(result);
    114     JITCompiler::Jump hasCalledToInt32 = m_jit.jump();
    115 
    116     // Then handle integers.
    117     isInteger.link(&m_jit);
    118     m_jit.zeroExtend32ToPtr(jsValueReg, resultReg);
    119     hasCalledToInt32.link(&m_jit);
    120 }
    121 
    122 void NonSpeculativeJIT::numberToInt32(FPRReg fpr, GPRReg gpr)
    123 {
    124     JITCompiler::FPRegisterID fpReg = JITCompiler::fprToRegisterID(fpr);
    125     JITCompiler::RegisterID reg = JITCompiler::gprToRegisterID(gpr);
    126 
    127     JITCompiler::Jump truncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpReg, reg, JITCompiler::BranchIfTruncateSuccessful);
    128 
    129     silentSpillAllRegisters(gpr);
    130 
    131     m_jit.moveDouble(fpReg, JITCompiler::fpArgumentRegister0);
    132     appendCallWithExceptionCheck(toInt32);
    133     m_jit.zeroExtend32ToPtr(JITCompiler::returnValueRegister, reg);
    134 
    135     silentFillAllRegisters(gpr);
    136 
    137     truncatedToInteger.link(&m_jit);
    138 }
    139 
    140 bool NonSpeculativeJIT::isKnownInteger(NodeIndex nodeIndex)
    141 {
    142     GenerationInfo& info = m_generationInfo[m_jit.graph()[nodeIndex].virtualRegister];
    143 
    144     DataFormat registerFormat = info.registerFormat();
    145     if (registerFormat != DataFormatNone)
    146         return (registerFormat | DataFormatJS) == DataFormatJSInteger;
    147 
    148     DataFormat spillFormat = info.spillFormat();
    149     if (spillFormat != DataFormatNone)
    150         return (spillFormat | DataFormatJS) == DataFormatJSInteger;
    151 
    152     ASSERT(isConstant(nodeIndex));
    153     return isInt32Constant(nodeIndex);
    154 }
    155 
    156 bool NonSpeculativeJIT::isKnownNumeric(NodeIndex nodeIndex)
    157 {
    158     GenerationInfo& info = m_generationInfo[m_jit.graph()[nodeIndex].virtualRegister];
    159 
    160     DataFormat registerFormat = info.registerFormat();
    161     if (registerFormat != DataFormatNone)
    162         return (registerFormat | DataFormatJS) == DataFormatJSInteger
    163             || (registerFormat | DataFormatJS) == DataFormatJSDouble;
    164 
    165     DataFormat spillFormat = info.spillFormat();
    166     if (spillFormat != DataFormatNone)
    167         return (spillFormat | DataFormatJS) == DataFormatJSInteger
    168             || (spillFormat | DataFormatJS) == DataFormatJSDouble;
    169 
    170     ASSERT(isConstant(nodeIndex));
    171     return isInt32Constant(nodeIndex) || isDoubleConstant(nodeIndex);
    172 }
    173 
    174 void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator, Node& node)
    175 {
    176     // ...
    177     if (checkIterator.hasCheckAtIndex(m_compileIndex))
    178         trackEntry(m_jit.label());
    179 
    180     checkConsistency();
    181     NodeType op = node.op;
    182 
    183     switch (op) {
    184     case ConvertThis: {
    185         JSValueOperand thisValue(this, node.child1);
    186         GPRReg thisGPR = thisValue.gpr();
    187         flushRegisters();
    188 
    189         GPRResult result(this);
    190         callOperation(operationConvertThis, result.gpr(), thisGPR);
    191         cellResult(result.gpr(), m_compileIndex);
    192         break;
    193     }
    194 
    195     case Int32Constant:
    196     case DoubleConstant:
    197     case JSConstant:
    198         initConstantInfo(m_compileIndex);
    199         break;
    200 
    201     case GetLocal: {
    202         GPRTemporary result(this);
    203         m_jit.loadPtr(JITCompiler::addressFor(node.local()), result.registerID());
    204         jsValueResult(result.gpr(), m_compileIndex);
    205         break;
    206     }
    207 
    208     case SetLocal: {
    209         JSValueOperand value(this, node.child1);
    210         m_jit.storePtr(value.registerID(), JITCompiler::addressFor(node.local()));
    211         noResult(m_compileIndex);
    212         break;
    213     }
    214 
    215     case BitAnd:
    216     case BitOr:
    217     case BitXor:
    218         if (isInt32Constant(node.child1)) {
    219             IntegerOperand op2(this, node.child2);
    220             GPRTemporary result(this, op2);
    221 
    222             bitOp(op, valueOfInt32Constant(node.child1), op2.registerID(), result.registerID());
    223 
    224             integerResult(result.gpr(), m_compileIndex);
    225         } else if (isInt32Constant(node.child2)) {
    226             IntegerOperand op1(this, node.child1);
    227             GPRTemporary result(this, op1);
    228 
    229             bitOp(op, valueOfInt32Constant(node.child2), op1.registerID(), result.registerID());
    230 
    231             integerResult(result.gpr(), m_compileIndex);
    232         } else {
    233             IntegerOperand op1(this, node.child1);
    234             IntegerOperand op2(this, node.child2);
    235             GPRTemporary result(this, op1, op2);
    236 
    237             MacroAssembler::RegisterID reg1 = op1.registerID();
    238             MacroAssembler::RegisterID reg2 = op2.registerID();
    239             bitOp(op, reg1, reg2, result.registerID());
    240 
    241             integerResult(result.gpr(), m_compileIndex);
    242         }
    243         break;
    244 
    245     case BitRShift:
    246     case BitLShift:
    247     case BitURShift:
    248         if (isInt32Constant(node.child2)) {
    249             IntegerOperand op1(this, node.child1);
    250             GPRTemporary result(this, op1);
    251 
    252             int shiftAmount = valueOfInt32Constant(node.child2) & 0x1f;
    253             // Shifts by zero should have been optimized out of the graph!
    254             ASSERT(shiftAmount);
    255             shiftOp(op, op1.registerID(), shiftAmount, result.registerID());
    256 
    257             integerResult(result.gpr(), m_compileIndex);
    258         } else {
    259             // Do not allow shift amount to be used as the result, MacroAssembler does not permit this.
    260             IntegerOperand op1(this, node.child1);
    261             IntegerOperand op2(this, node.child2);
    262             GPRTemporary result(this, op1);
    263 
    264             MacroAssembler::RegisterID reg1 = op1.registerID();
    265             MacroAssembler::RegisterID reg2 = op2.registerID();
    266             shiftOp(op, reg1, reg2, result.registerID());
    267 
    268             integerResult(result.gpr(), m_compileIndex);
    269         }
    270         break;
    271 
    272     case UInt32ToNumber: {
    273         IntegerOperand op1(this, node.child1);
    274         FPRTemporary result(this);
    275         m_jit.convertInt32ToDouble(op1.registerID(), result.registerID());
    276 
    277         MacroAssembler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, op1.registerID(), TrustedImm32(0));
    278         m_jit.addDouble(JITCompiler::AbsoluteAddress(&twoToThe32), result.registerID());
    279         positive.link(&m_jit);
    280 
    281         doubleResult(result.fpr(), m_compileIndex);
    282         break;
    283     }
    284 
    285     case Int32ToNumber: {
    286         IntegerOperand op1(this, node.child1);
    287         FPRTemporary result(this);
    288         m_jit.convertInt32ToDouble(op1.registerID(), result.registerID());
    289         doubleResult(result.fpr(), m_compileIndex);
    290         break;
    291     }
    292 
    293     case NumberToInt32:
    294     case ValueToInt32: {
    295         ASSERT(!isInt32Constant(node.child1));
    296 
    297         if (isKnownInteger(node.child1)) {
    298             IntegerOperand op1(this, node.child1);
    299             GPRTemporary result(this, op1);
    300             m_jit.move(op1.registerID(), result.registerID());
    301             integerResult(result.gpr(), m_compileIndex);
    302             break;
    303         }
    304 
    305         if (isKnownNumeric(node.child1)) {
    306             DoubleOperand op1(this, node.child1);
    307             GPRTemporary result(this);
    308             numberToInt32(op1.fpr(), result.gpr());
    309             integerResult(result.gpr(), m_compileIndex);
    310             break;
    311         }
    312 
    313         // We should have handled this via isKnownInteger, or isKnownNumeric!
    314         ASSERT(op != NumberToInt32);
    315 
    316         JSValueOperand op1(this, node.child1);
    317         GPRTemporary result(this, op1);
    318         valueToInt32(op1, result.gpr());
    319         integerResult(result.gpr(), m_compileIndex);
    320         break;
    321     }
    322 
    323     case ValueToNumber: {
    324         ASSERT(!isInt32Constant(node.child1));
    325         ASSERT(!isDoubleConstant(node.child1));
    326 
    327         if (isKnownInteger(node.child1)) {
    328             IntegerOperand op1(this, node.child1);
    329             FPRTemporary result(this);
    330             m_jit.convertInt32ToDouble(op1.registerID(), result.registerID());
    331             doubleResult(result.fpr(), m_compileIndex);
    332             break;
    333         }
    334 
    335         if (isKnownNumeric(node.child1)) {
    336             DoubleOperand op1(this, node.child1);
    337             FPRTemporary result(this, op1);
    338             m_jit.moveDouble(op1.registerID(), result.registerID());
    339             doubleResult(result.fpr(), m_compileIndex);
    340             break;
    341         }
    342 
    343         JSValueOperand op1(this, node.child1);
    344         FPRTemporary result(this);
    345         valueToNumber(op1, result.fpr());
    346         doubleResult(result.fpr(), m_compileIndex);
    347         break;
    348     }
    349 
    350     case ValueAdd: {
    351         JSValueOperand arg1(this, node.child1);
    352         JSValueOperand arg2(this, node.child2);
    353         GPRReg arg1GPR = arg1.gpr();
    354         GPRReg arg2GPR = arg2.gpr();
    355         flushRegisters();
    356 
    357         GPRResult result(this);
    358         callOperation(operationValueAdd, result.gpr(), arg1GPR, arg2GPR);
    359 
    360         jsValueResult(result.gpr(), m_compileIndex);
    361         break;
    362     }
    363 
    364     case ArithAdd: {
    365         DoubleOperand op1(this, node.child1);
    366         DoubleOperand op2(this, node.child2);
    367         FPRTemporary result(this, op1, op2);
    368 
    369         MacroAssembler::FPRegisterID reg1 = op1.registerID();
    370         MacroAssembler::FPRegisterID reg2 = op2.registerID();
    371         m_jit.addDouble(reg1, reg2, result.registerID());
    372 
    373         doubleResult(result.fpr(), m_compileIndex);
    374         break;
    375     }
    376 
    377     case ArithSub: {
    378         DoubleOperand op1(this, node.child1);
    379         DoubleOperand op2(this, node.child2);
    380         FPRTemporary result(this, op1);
    381 
    382         MacroAssembler::FPRegisterID reg1 = op1.registerID();
    383         MacroAssembler::FPRegisterID reg2 = op2.registerID();
    384         m_jit.subDouble(reg1, reg2, result.registerID());
    385 
    386         doubleResult(result.fpr(), m_compileIndex);
    387         break;
    388     }
    389 
    390     case ArithMul: {
    391         DoubleOperand op1(this, node.child1);
    392         DoubleOperand op2(this, node.child2);
    393         FPRTemporary result(this, op1, op2);
    394 
    395         MacroAssembler::FPRegisterID reg1 = op1.registerID();
    396         MacroAssembler::FPRegisterID reg2 = op2.registerID();
    397         m_jit.mulDouble(reg1, reg2, result.registerID());
    398 
    399         doubleResult(result.fpr(), m_compileIndex);
    400         break;
    401     }
    402 
    403     case ArithDiv: {
    404         DoubleOperand op1(this, node.child1);
    405         DoubleOperand op2(this, node.child2);
    406         FPRTemporary result(this, op1);
    407 
    408         MacroAssembler::FPRegisterID reg1 = op1.registerID();
    409         MacroAssembler::FPRegisterID reg2 = op2.registerID();
    410         m_jit.divDouble(reg1, reg2, result.registerID());
    411 
    412         doubleResult(result.fpr(), m_compileIndex);
    413         break;
    414     }
    415 
    416     case ArithMod: {
    417         DoubleOperand arg1(this, node.child1);
    418         DoubleOperand arg2(this, node.child2);
    419         FPRReg arg1FPR = arg1.fpr();
    420         FPRReg arg2FPR = arg2.fpr();
    421         flushRegisters();
    422 
    423         FPRResult result(this);
    424         callOperation(fmod, result.fpr(), arg1FPR, arg2FPR);
    425 
    426         doubleResult(result.fpr(), m_compileIndex);
    427         break;
    428     }
    429 
    430     case LogicalNot: {
    431         JSValueOperand arg1(this, node.child1);
    432         GPRReg arg1GPR = arg1.gpr();
    433         flushRegisters();
    434 
    435         GPRResult result(this);
    436         callOperation(dfgConvertJSValueToBoolean, result.gpr(), arg1GPR);
    437 
    438         // If we add a DataFormatBool, we should use it here.
    439         m_jit.xor32(TrustedImm32(ValueTrue), result.registerID());
    440         jsValueResult(result.gpr(), m_compileIndex);
    441         break;
    442     }
    443 
    444     case CompareLess: {
    445         JSValueOperand arg1(this, node.child1);
    446         JSValueOperand arg2(this, node.child2);
    447         GPRReg arg1GPR = arg1.gpr();
    448         GPRReg arg2GPR = arg2.gpr();
    449         flushRegisters();
    450 
    451         GPRResult result(this);
    452         callOperation(operationCompareLess, result.gpr(), arg1GPR, arg2GPR);
    453         m_jit.or32(TrustedImm32(ValueFalse), result.registerID());
    454 
    455         jsValueResult(result.gpr(), m_compileIndex);
    456         break;
    457     }
    458 
    459     case CompareLessEq: {
    460         JSValueOperand arg1(this, node.child1);
    461         JSValueOperand arg2(this, node.child2);
    462         GPRReg arg1GPR = arg1.gpr();
    463         GPRReg arg2GPR = arg2.gpr();
    464         flushRegisters();
    465 
    466         GPRResult result(this);
    467         callOperation(operationCompareLessEq, result.gpr(), arg1GPR, arg2GPR);
    468         m_jit.or32(TrustedImm32(ValueFalse), result.registerID());
    469 
    470         jsValueResult(result.gpr(), m_compileIndex);
    471         break;
    472     }
    473 
    474     case CompareEq: {
    475         JSValueOperand arg1(this, node.child1);
    476         JSValueOperand arg2(this, node.child2);
    477         GPRReg arg1GPR = arg1.gpr();
    478         GPRReg arg2GPR = arg2.gpr();
    479         flushRegisters();
    480 
    481         GPRResult result(this);
    482         callOperation(operationCompareEq, result.gpr(), arg1GPR, arg2GPR);
    483         m_jit.or32(TrustedImm32(ValueFalse), result.registerID());
    484 
    485         jsValueResult(result.gpr(), m_compileIndex);
    486         break;
    487     }
    488 
    489     case CompareStrictEq: {
    490         JSValueOperand arg1(this, node.child1);
    491         JSValueOperand arg2(this, node.child2);
    492         GPRReg arg1GPR = arg1.gpr();
    493         GPRReg arg2GPR = arg2.gpr();
    494         flushRegisters();
    495 
    496         GPRResult result(this);
    497         callOperation(operationCompareStrictEq, result.gpr(), arg1GPR, arg2GPR);
    498         m_jit.or32(TrustedImm32(ValueFalse), result.registerID());
    499 
    500         jsValueResult(result.gpr(), m_compileIndex);
    501         break;
    502     }
    503 
    504     case GetByVal: {
    505         JSValueOperand arg1(this, node.child1);
    506         JSValueOperand arg2(this, node.child2);
    507         GPRReg arg1GPR = arg1.gpr();
    508         GPRReg arg2GPR = arg2.gpr();
    509         flushRegisters();
    510 
    511         GPRResult result(this);
    512         callOperation(operationGetByVal, result.gpr(), arg1GPR, arg2GPR);
    513 
    514         jsValueResult(result.gpr(), m_compileIndex);
    515         break;
    516     }
    517 
    518     case PutByVal:
    519     case PutByValAlias: {
    520         JSValueOperand arg1(this, node.child1);
    521         JSValueOperand arg2(this, node.child2);
    522         JSValueOperand arg3(this, node.child3);
    523         GPRReg arg1GPR = arg1.gpr();
    524         GPRReg arg2GPR = arg2.gpr();
    525         GPRReg arg3GPR = arg3.gpr();
    526         flushRegisters();
    527 
    528         GPRResult result(this);
    529         callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByValStrict : operationPutByValNonStrict, arg1GPR, arg2GPR, arg3GPR);
    530 
    531         noResult(m_compileIndex);
    532         break;
    533     }
    534 
    535     case GetById: {
    536         JSValueOperand base(this, node.child1);
    537         GPRReg baseGPR = base.gpr();
    538         flushRegisters();
    539 
    540         GPRResult result(this);
    541         callOperation(operationGetById, result.gpr(), baseGPR, identifier(node.identifierNumber()));
    542         jsValueResult(result.gpr(), m_compileIndex);
    543         break;
    544     }
    545 
    546     case PutById: {
    547         JSValueOperand base(this, node.child1);
    548         JSValueOperand value(this, node.child2);
    549         GPRReg valueGPR = value.gpr();
    550         GPRReg baseGPR = base.gpr();
    551         flushRegisters();
    552 
    553         callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByIdStrict : operationPutByIdNonStrict, valueGPR, baseGPR, identifier(node.identifierNumber()));
    554         noResult(m_compileIndex);
    555         break;
    556     }
    557 
    558     case PutByIdDirect: {
    559         JSValueOperand base(this, node.child1);
    560         JSValueOperand value(this, node.child2);
    561         GPRReg valueGPR = value.gpr();
    562         GPRReg baseGPR = base.gpr();
    563         flushRegisters();
    564 
    565         callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByIdDirectStrict : operationPutByIdDirectNonStrict, valueGPR, baseGPR, identifier(node.identifierNumber()));
    566         noResult(m_compileIndex);
    567         break;
    568     }
    569 
    570     case GetGlobalVar: {
    571         GPRTemporary result(this);
    572 
    573         JSVariableObject* globalObject = m_jit.codeBlock()->globalObject();
    574         m_jit.loadPtr(globalObject->addressOfRegisters(), result.registerID());
    575         m_jit.loadPtr(JITCompiler::addressForGlobalVar(result.registerID(), node.varNumber()), result.registerID());
    576 
    577         jsValueResult(result.gpr(), m_compileIndex);
    578         break;
    579     }
    580 
    581     case PutGlobalVar: {
    582         JSValueOperand value(this, node.child1);
    583         GPRTemporary temp(this);
    584 
    585         JSVariableObject* globalObject = m_jit.codeBlock()->globalObject();
    586         m_jit.loadPtr(globalObject->addressOfRegisters(), temp.registerID());
    587         m_jit.storePtr(value.registerID(), JITCompiler::addressForGlobalVar(temp.registerID(), node.varNumber()));
    588 
    589         noResult(m_compileIndex);
    590         break;
    591     }
    592 
    593     case DFG::Jump: {
    594         BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());
    595         if (taken != (m_block + 1))
    596             addBranch(m_jit.jump(), taken);
    597         noResult(m_compileIndex);
    598         break;
    599     }
    600 
    601     case Branch: {
    602         JSValueOperand value(this, node.child1);
    603         GPRReg valueGPR = value.gpr();
    604         flushRegisters();
    605 
    606         GPRResult result(this);
    607         callOperation(dfgConvertJSValueToBoolean, result.gpr(), valueGPR);
    608 
    609         BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());
    610         BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(node.notTakenBytecodeOffset());
    611 
    612         addBranch(m_jit.branchTest8(MacroAssembler::NonZero, result.registerID()), taken);
    613         if (notTaken != (m_block + 1))
    614             addBranch(m_jit.jump(), notTaken);
    615 
    616         noResult(m_compileIndex);
    617         break;
    618     }
    619 
    620     case Return: {
    621         ASSERT(JITCompiler::callFrameRegister != JITCompiler::regT1);
    622         ASSERT(JITCompiler::regT1 != JITCompiler::returnValueRegister);
    623         ASSERT(JITCompiler::returnValueRegister != JITCompiler::callFrameRegister);
    624 
    625 #if DFG_SUCCESS_STATS
    626         static SamplingCounter counter("NonSpeculativeJIT");
    627         m_jit.emitCount(counter);
    628 #endif
    629 
    630         // Return the result in returnValueRegister.
    631         JSValueOperand op1(this, node.child1);
    632         m_jit.move(op1.registerID(), JITCompiler::returnValueRegister);
    633 
    634         // Grab the return address.
    635         m_jit.emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, JITCompiler::regT1);
    636         // Restore our caller's "r".
    637         m_jit.emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, JITCompiler::callFrameRegister);
    638         // Return.
    639         m_jit.restoreReturnAddressBeforeReturn(JITCompiler::regT1);
    640         m_jit.ret();
    641 
    642         noResult(m_compileIndex);
    643         break;
    644     }
    645     }
    646 
    647     if (node.mustGenerate())
    648         use(m_compileIndex);
    649 
    650     checkConsistency();
    651 }
    652 
    653 void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator, BasicBlock& block)
    654 {
    655     ASSERT(m_compileIndex == block.begin);
    656     m_blockHeads[m_block] = m_jit.label();
    657 
    658 #if DFG_JIT_BREAK_ON_EVERY_BLOCK
    659     m_jit.breakpoint();
    660 #endif
    661 
    662     for (; m_compileIndex < block.end; ++m_compileIndex) {
    663         Node& node = m_jit.graph()[m_compileIndex];
    664         if (!node.refCount)
    665             continue;
    666 
    667 #if DFG_DEBUG_VERBOSE
    668         fprintf(stderr, "NonSpeculativeJIT generating Node @%d at code offset 0x%x\n", (int)m_compileIndex, m_jit.debugOffset());
    669 #endif
    670 #if DFG_JIT_BREAK_ON_EVERY_NODE
    671     m_jit.breakpoint();
    672 #endif
    673 
    674         compile(checkIterator, node);
    675     }
    676 }
    677 
    678 void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator)
    679 {
    680     ASSERT(!m_compileIndex);
    681     Vector<BasicBlock> blocks = m_jit.graph().m_blocks;
    682     for (m_block = 0; m_block < blocks.size(); ++m_block)
    683         compile(checkIterator, blocks[m_block]);
    684     linkBranches();
    685 }
    686 
    687 } } // namespace JSC::DFG
    688 
    689 #endif
    690