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 "DFGJITCodeGenerator.h"
     28 
     29 #if ENABLE(DFG_JIT)
     30 
     31 #include "DFGNonSpeculativeJIT.h"
     32 #include "DFGSpeculativeJIT.h"
     33 #include "LinkBuffer.h"
     34 
     35 namespace JSC { namespace DFG {
     36 
     37 GPRReg JITCodeGenerator::fillInteger(NodeIndex nodeIndex, DataFormat& returnFormat)
     38 {
     39     Node& node = m_jit.graph()[nodeIndex];
     40     VirtualRegister virtualRegister = node.virtualRegister;
     41     GenerationInfo& info = m_generationInfo[virtualRegister];
     42 
     43     if (info.registerFormat() == DataFormatNone) {
     44         GPRReg gpr = allocate();
     45         JITCompiler::RegisterID reg = JITCompiler::gprToRegisterID(gpr);
     46 
     47         if (node.isConstant()) {
     48             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
     49             if (isInt32Constant(nodeIndex)) {
     50                 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), reg);
     51                 info.fillInteger(gpr);
     52                 returnFormat = DataFormatInteger;
     53                 return gpr;
     54             }
     55             if (isDoubleConstant(nodeIndex)) {
     56                 JSValue jsValue = jsNumber(valueOfDoubleConstant(nodeIndex));
     57                 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), reg);
     58             } else {
     59                 ASSERT(isJSConstant(nodeIndex));
     60                 JSValue jsValue = valueOfJSConstant(nodeIndex);
     61                 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), reg);
     62             }
     63         } else {
     64             ASSERT(info.spillFormat() == DataFormatJS || info.spillFormat() == DataFormatJSInteger);
     65             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
     66             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), reg);
     67         }
     68 
     69         // Since we statically know that we're filling an integer, and values
     70         // in the RegisterFile are boxed, this must be DataFormatJSInteger.
     71         // We will check this with a jitAssert below.
     72         info.fillJSValue(gpr, DataFormatJSInteger);
     73         unlock(gpr);
     74     }
     75 
     76     switch (info.registerFormat()) {
     77     case DataFormatNone:
     78         // Should have filled, above.
     79     case DataFormatJSDouble:
     80     case DataFormatDouble:
     81     case DataFormatJS:
     82     case DataFormatCell:
     83     case DataFormatJSCell:
     84         // Should only be calling this function if we know this operand to be integer.
     85         ASSERT_NOT_REACHED();
     86 
     87     case DataFormatJSInteger: {
     88         GPRReg gpr = info.gpr();
     89         m_gprs.lock(gpr);
     90         m_jit.jitAssertIsJSInt32(gpr);
     91         returnFormat = DataFormatJSInteger;
     92         return gpr;
     93     }
     94 
     95     case DataFormatInteger: {
     96         GPRReg gpr = info.gpr();
     97         m_gprs.lock(gpr);
     98         m_jit.jitAssertIsInt32(gpr);
     99         returnFormat = DataFormatInteger;
    100         return gpr;
    101     }
    102     }
    103 
    104     ASSERT_NOT_REACHED();
    105     return InvalidGPRReg;
    106 }
    107 
    108 FPRReg JITCodeGenerator::fillDouble(NodeIndex nodeIndex)
    109 {
    110     Node& node = m_jit.graph()[nodeIndex];
    111     VirtualRegister virtualRegister = node.virtualRegister;
    112     GenerationInfo& info = m_generationInfo[virtualRegister];
    113 
    114     if (info.registerFormat() == DataFormatNone) {
    115         GPRReg gpr = allocate();
    116         JITCompiler::RegisterID reg = JITCompiler::gprToRegisterID(gpr);
    117 
    118         if (node.isConstant()) {
    119             if (isInt32Constant(nodeIndex)) {
    120                 // FIXME: should not be reachable?
    121                 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), reg);
    122                 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
    123                 info.fillInteger(gpr);
    124                 unlock(gpr);
    125             } else if (isDoubleConstant(nodeIndex)) {
    126                 FPRReg fpr = fprAllocate();
    127                 m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfDoubleConstant(nodeIndex)))), reg);
    128                 m_jit.movePtrToDouble(reg, JITCompiler::fprToRegisterID(fpr));
    129                 unlock(gpr);
    130 
    131                 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
    132                 info.fillDouble(fpr);
    133                 return fpr;
    134             } else {
    135                 // FIXME: should not be reachable?
    136                 ASSERT(isJSConstant(nodeIndex));
    137                 JSValue jsValue = valueOfJSConstant(nodeIndex);
    138                 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), reg);
    139                 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
    140                 info.fillJSValue(gpr, DataFormatJS);
    141                 unlock(gpr);
    142             }
    143         } else {
    144             DataFormat spillFormat = info.spillFormat();
    145             ASSERT(spillFormat & DataFormatJS);
    146             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
    147             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), reg);
    148             info.fillJSValue(gpr, m_isSpeculative ? spillFormat : DataFormatJS);
    149             unlock(gpr);
    150         }
    151     }
    152 
    153     switch (info.registerFormat()) {
    154     case DataFormatNone:
    155         // Should have filled, above.
    156     case DataFormatCell:
    157     case DataFormatJSCell:
    158         // Should only be calling this function if we know this operand to be numeric.
    159         ASSERT_NOT_REACHED();
    160 
    161     case DataFormatJS: {
    162         GPRReg jsValueGpr = info.gpr();
    163         m_gprs.lock(jsValueGpr);
    164         FPRReg fpr = fprAllocate();
    165         GPRReg tempGpr = allocate(); // FIXME: can we skip this allocation on the last use of the virtual register?
    166 
    167         JITCompiler::RegisterID jsValueReg = JITCompiler::gprToRegisterID(jsValueGpr);
    168         JITCompiler::FPRegisterID fpReg = JITCompiler::fprToRegisterID(fpr);
    169         JITCompiler::RegisterID tempReg = JITCompiler::gprToRegisterID(tempGpr);
    170 
    171         JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueReg, JITCompiler::tagTypeNumberRegister);
    172 
    173         m_jit.jitAssertIsJSDouble(jsValueGpr);
    174 
    175         // First, if we get here we have a double encoded as a JSValue
    176         m_jit.move(jsValueReg, tempReg);
    177         m_jit.addPtr(JITCompiler::tagTypeNumberRegister, tempReg);
    178         m_jit.movePtrToDouble(tempReg, fpReg);
    179         JITCompiler::Jump hasUnboxedDouble = m_jit.jump();
    180 
    181         // Finally, handle integers.
    182         isInteger.link(&m_jit);
    183         m_jit.convertInt32ToDouble(jsValueReg, fpReg);
    184         hasUnboxedDouble.link(&m_jit);
    185 
    186         m_gprs.release(jsValueGpr);
    187         m_gprs.unlock(jsValueGpr);
    188         m_gprs.unlock(tempGpr);
    189         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
    190         info.fillDouble(fpr);
    191         return fpr;
    192     }
    193 
    194     case DataFormatJSInteger:
    195     case DataFormatInteger: {
    196         FPRReg fpr = fprAllocate();
    197         GPRReg gpr = info.gpr();
    198         m_gprs.lock(gpr);
    199         JITCompiler::RegisterID reg = JITCompiler::gprToRegisterID(gpr);
    200         JITCompiler::FPRegisterID fpReg = JITCompiler::fprToRegisterID(fpr);
    201 
    202         m_jit.convertInt32ToDouble(reg, fpReg);
    203 
    204         m_gprs.release(gpr);
    205         m_gprs.unlock(gpr);
    206         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
    207         info.fillDouble(fpr);
    208         return fpr;
    209     }
    210 
    211     // Unbox the double
    212     case DataFormatJSDouble: {
    213         GPRReg gpr = info.gpr();
    214         FPRReg fpr = unboxDouble(gpr);
    215 
    216         m_gprs.release(gpr);
    217         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
    218 
    219         info.fillDouble(fpr);
    220         return fpr;
    221     }
    222 
    223     case DataFormatDouble: {
    224         FPRReg fpr = info.fpr();
    225         m_fprs.lock(fpr);
    226         return fpr;
    227     }
    228     }
    229 
    230     ASSERT_NOT_REACHED();
    231     return InvalidFPRReg;
    232 }
    233 
    234 GPRReg JITCodeGenerator::fillJSValue(NodeIndex nodeIndex)
    235 {
    236     Node& node = m_jit.graph()[nodeIndex];
    237     VirtualRegister virtualRegister = node.virtualRegister;
    238     GenerationInfo& info = m_generationInfo[virtualRegister];
    239 
    240     switch (info.registerFormat()) {
    241     case DataFormatNone: {
    242         GPRReg gpr = allocate();
    243         JITCompiler::RegisterID reg = JITCompiler::gprToRegisterID(gpr);
    244 
    245         if (node.isConstant()) {
    246             if (isInt32Constant(nodeIndex)) {
    247                 info.fillJSValue(gpr, DataFormatJSInteger);
    248                 JSValue jsValue = jsNumber(valueOfInt32Constant(nodeIndex));
    249                 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), reg);
    250             } else if (isDoubleConstant(nodeIndex)) {
    251                 info.fillJSValue(gpr, DataFormatJSDouble);
    252                 JSValue jsValue(JSValue::EncodeAsDouble, valueOfDoubleConstant(nodeIndex));
    253                 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), reg);
    254             } else {
    255                 ASSERT(isJSConstant(nodeIndex));
    256                 JSValue jsValue = valueOfJSConstant(nodeIndex);
    257                 m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), reg);
    258                 info.fillJSValue(gpr, DataFormatJS);
    259             }
    260 
    261             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
    262         } else {
    263             DataFormat spillFormat = info.spillFormat();
    264             ASSERT(spillFormat & DataFormatJS);
    265             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
    266             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), reg);
    267             info.fillJSValue(gpr, m_isSpeculative ? spillFormat : DataFormatJS);
    268         }
    269         return gpr;
    270     }
    271 
    272     case DataFormatInteger: {
    273         GPRReg gpr = info.gpr();
    274         // If the register has already been locked we need to take a copy.
    275         // If not, we'll zero extend in place, so mark on the info that this is now type DataFormatInteger, not DataFormatJSInteger.
    276         if (m_gprs.isLocked(gpr)) {
    277             GPRReg result = allocate();
    278             m_jit.orPtr(JITCompiler::tagTypeNumberRegister, JITCompiler::gprToRegisterID(gpr), JITCompiler::gprToRegisterID(result));
    279             return result;
    280         }
    281         m_gprs.lock(gpr);
    282         m_jit.orPtr(JITCompiler::tagTypeNumberRegister, JITCompiler::gprToRegisterID(gpr));
    283         info.fillJSValue(gpr, DataFormatJSInteger);
    284         return gpr;
    285     }
    286 
    287     case DataFormatDouble: {
    288         FPRReg fpr = info.fpr();
    289         GPRReg gpr = boxDouble(fpr);
    290 
    291         // Update all info
    292         info.fillJSValue(gpr, DataFormatJSDouble);
    293         m_fprs.release(fpr);
    294         m_gprs.retain(gpr, virtualRegister, SpillOrderJS);
    295 
    296         return gpr;
    297     }
    298 
    299     case DataFormatCell:
    300         // No retag required on JSVALUE64!
    301     case DataFormatJS:
    302     case DataFormatJSInteger:
    303     case DataFormatJSDouble:
    304     case DataFormatJSCell: {
    305         GPRReg gpr = info.gpr();
    306         m_gprs.lock(gpr);
    307         return gpr;
    308     }
    309     }
    310 
    311     ASSERT_NOT_REACHED();
    312     return InvalidGPRReg;
    313 }
    314 
    315 void JITCodeGenerator::useChildren(Node& node)
    316 {
    317     NodeIndex child1 = node.child1;
    318     if (child1 == NoNode) {
    319         ASSERT(node.child2 == NoNode && node.child3 == NoNode);
    320         return;
    321     }
    322     use(child1);
    323 
    324     NodeIndex child2 = node.child2;
    325     if (child2 == NoNode) {
    326         ASSERT(node.child3 == NoNode);
    327         return;
    328     }
    329     use(child2);
    330 
    331     NodeIndex child3 = node.child3;
    332     if (child3 == NoNode)
    333         return;
    334     use(child3);
    335 }
    336 
    337 #ifndef NDEBUG
    338 static const char* dataFormatString(DataFormat format)
    339 {
    340     // These values correspond to the DataFormat enum.
    341     const char* strings[] = {
    342         "[  ]",
    343         "[ i]",
    344         "[ d]",
    345         "[ c]",
    346         "Err!",
    347         "Err!",
    348         "Err!",
    349         "Err!",
    350         "[J ]",
    351         "[Ji]",
    352         "[Jd]",
    353         "[Jc]",
    354         "Err!",
    355         "Err!",
    356         "Err!",
    357         "Err!",
    358     };
    359     return strings[format];
    360 }
    361 
    362 void JITCodeGenerator::dump(const char* label)
    363 {
    364     if (label)
    365         fprintf(stderr, "<%s>\n", label);
    366 
    367     fprintf(stderr, "  gprs:\n");
    368     m_gprs.dump();
    369     fprintf(stderr, "  fprs:\n");
    370     m_fprs.dump();
    371     fprintf(stderr, "  VirtualRegisters:\n");
    372     for (unsigned i = 0; i < m_generationInfo.size(); ++i) {
    373         GenerationInfo& info = m_generationInfo[i];
    374         if (info.alive())
    375             fprintf(stderr, "    % 3d:%s%s\n", i, dataFormatString(info.registerFormat()), dataFormatString(info.spillFormat()));
    376         else
    377             fprintf(stderr, "    % 3d:[__][__]\n", i);
    378     }
    379     if (label)
    380         fprintf(stderr, "</%s>\n", label);
    381 }
    382 #endif
    383 
    384 
    385 #if DFG_CONSISTENCY_CHECK
    386 void JITCodeGenerator::checkConsistency()
    387 {
    388     VirtualRegister grpContents[numberOfGPRs];
    389     VirtualRegister frpContents[numberOfFPRs];
    390 
    391     for (unsigned i = 0; i < numberOfGPRs; ++i)
    392         grpContents[i] = InvalidVirtualRegister;
    393     for (unsigned i = 0; i < numberOfFPRs; ++i)
    394         frpContents[i] = InvalidVirtualRegister;
    395     for (unsigned i = 0; i < m_generationInfo.size(); ++i) {
    396         GenerationInfo& info = m_generationInfo[i];
    397         if (!info.alive())
    398             continue;
    399         switch (info.registerFormat()) {
    400         case DataFormatNone:
    401             break;
    402         case DataFormatInteger:
    403         case DataFormatCell:
    404         case DataFormatJS:
    405         case DataFormatJSInteger:
    406         case DataFormatJSDouble:
    407         case DataFormatJSCell: {
    408             GPRReg gpr = info.gpr();
    409             ASSERT(gpr != InvalidGPRReg);
    410             grpContents[gpr] = (VirtualRegister)i;
    411             break;
    412         }
    413         case DataFormatDouble: {
    414             FPRReg fpr = info.fpr();
    415             ASSERT(fpr != InvalidFPRReg);
    416             frpContents[fpr] = (VirtualRegister)i;
    417             break;
    418         }
    419         }
    420     }
    421 
    422     for (GPRReg i = gpr0; i < numberOfGPRs; next(i)) {
    423         if (m_gprs.isLocked(i) || m_gprs.name(i) != grpContents[i]) {
    424             dump();
    425             CRASH();
    426         }
    427     }
    428     for (FPRReg i = fpr0; i < numberOfFPRs; next(i)) {
    429         if (m_fprs.isLocked(i) || m_fprs.name(i) != frpContents[i]) {
    430             dump();
    431             CRASH();
    432         }
    433     }
    434 }
    435 #endif
    436 
    437 GPRTemporary::GPRTemporary(JITCodeGenerator* jit)
    438     : m_jit(jit)
    439     , m_gpr(InvalidGPRReg)
    440 {
    441     m_gpr = m_jit->allocate();
    442 }
    443 
    444 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateIntegerOperand& op1)
    445     : m_jit(jit)
    446     , m_gpr(InvalidGPRReg)
    447 {
    448     // locking into a register may free for reuse!
    449     op1.gpr();
    450     if (m_jit->canReuse(op1.index()))
    451         m_gpr = m_jit->reuse(op1.gpr());
    452     else
    453         m_gpr = m_jit->allocate();
    454 }
    455 
    456 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateIntegerOperand& op1, SpeculateIntegerOperand& op2)
    457     : m_jit(jit)
    458     , m_gpr(InvalidGPRReg)
    459 {
    460     // locking into a register may free for reuse!
    461     op1.gpr();
    462     op2.gpr();
    463     if (m_jit->canReuse(op1.index()))
    464         m_gpr = m_jit->reuse(op1.gpr());
    465     else if (m_jit->canReuse(op2.index()))
    466         m_gpr = m_jit->reuse(op2.gpr());
    467     else
    468         m_gpr = m_jit->allocate();
    469 }
    470 
    471 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, IntegerOperand& op1)
    472     : m_jit(jit)
    473     , m_gpr(InvalidGPRReg)
    474 {
    475     // locking into a register may free for reuse!
    476     op1.gpr();
    477     if (m_jit->canReuse(op1.index()))
    478         m_gpr = m_jit->reuse(op1.gpr());
    479     else
    480         m_gpr = m_jit->allocate();
    481 }
    482 
    483 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, IntegerOperand& op1, IntegerOperand& op2)
    484     : m_jit(jit)
    485     , m_gpr(InvalidGPRReg)
    486 {
    487     // locking into a register may free for reuse!
    488     op1.gpr();
    489     op2.gpr();
    490     if (m_jit->canReuse(op1.index()))
    491         m_gpr = m_jit->reuse(op1.gpr());
    492     else if (m_jit->canReuse(op2.index()))
    493         m_gpr = m_jit->reuse(op2.gpr());
    494     else
    495         m_gpr = m_jit->allocate();
    496 }
    497 
    498 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateCellOperand& op1)
    499     : m_jit(jit)
    500     , m_gpr(InvalidGPRReg)
    501 {
    502     // locking into a register may free for reuse!
    503     op1.gpr();
    504     if (m_jit->canReuse(op1.index()))
    505         m_gpr = m_jit->reuse(op1.gpr());
    506     else
    507         m_gpr = m_jit->allocate();
    508 }
    509 
    510 GPRTemporary::GPRTemporary(JITCodeGenerator* jit, JSValueOperand& op1)
    511     : m_jit(jit)
    512     , m_gpr(InvalidGPRReg)
    513 {
    514     // locking into a register may free for reuse!
    515     op1.gpr();
    516     if (m_jit->canReuse(op1.index()))
    517         m_gpr = m_jit->reuse(op1.gpr());
    518     else
    519         m_gpr = m_jit->allocate();
    520 }
    521 
    522 FPRTemporary::FPRTemporary(JITCodeGenerator* jit)
    523     : m_jit(jit)
    524     , m_fpr(InvalidFPRReg)
    525 {
    526     m_fpr = m_jit->fprAllocate();
    527 }
    528 
    529 FPRTemporary::FPRTemporary(JITCodeGenerator* jit, DoubleOperand& op1)
    530     : m_jit(jit)
    531     , m_fpr(InvalidFPRReg)
    532 {
    533     // locking into a register may free for reuse!
    534     op1.fpr();
    535     if (m_jit->canReuse(op1.index()))
    536         m_fpr = m_jit->reuse(op1.fpr());
    537     else
    538         m_fpr = m_jit->fprAllocate();
    539 }
    540 
    541 FPRTemporary::FPRTemporary(JITCodeGenerator* jit, DoubleOperand& op1, DoubleOperand& op2)
    542     : m_jit(jit)
    543     , m_fpr(InvalidFPRReg)
    544 {
    545     // locking into a register may free for reuse!
    546     op1.fpr();
    547     op2.fpr();
    548     if (m_jit->canReuse(op1.index()))
    549         m_fpr = m_jit->reuse(op1.fpr());
    550     else if (m_jit->canReuse(op2.index()))
    551         m_fpr = m_jit->reuse(op2.fpr());
    552     else
    553         m_fpr = m_jit->fprAllocate();
    554 }
    555 
    556 } } // namespace JSC::DFG
    557 
    558 #endif
    559