Changeset 143241 in webkit


Ignore:
Timestamp:
Feb 18, 2013 10:40:09 AM (11 years ago)
Author:
fpizlo@apple.com
Message:

Get rid of DFG::DoubleOperand and simplify ValueToInt32
https://bugs.webkit.org/show_bug.cgi?id=110072

Source/JavaScriptCore:

Reviewed by Geoffrey Garen.

ValueToInt32 had a side-effecting path, which was not OSR-friendly: an OSR after
the side-effect would lead to the side-effect re-executing. I got rid of that path
and replaced it with an optimization for the case where the input is speculated
number-or-other. This makes idioms like null|0 and true|0 work as expected, and
get optimized appropriately.

Also got rid of DoubleOperand. Replaced all remaining uses of it with
SpeculateDoubleOperand. Because the latter asserts that the Edge is a DoubleUse
edge and the remaining uses of DoubleOperand are all for untyped uses, I worked
around the assertion by setting the UseKind to DoubleUse by force. This is sound,
since all existing assertions for DoubleUse are actually asserting that we're not
converting a value to double unexpectedly. But all of these calls to
SpeculateDoubleOperand are when the operand is already known to be represented as
double, so there is no conversion.

This is neutral on benchmarks, except stanford-crypto-ccm, which speeds up a
little. Mostly, this is intended to delete a bunch of code. DoubleOperand was
equivalent to the replace-edge-with-DoubleUse trick that I'm using now, except it
involved a _lot_ more code.

  • dfg/DFGAbstractState.cpp:

(JSC::DFG::AbstractState::execute):

  • dfg/DFGCSEPhase.cpp:

(JSC::DFG::CSEPhase::performNodeCSE):

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::fixupNode):

  • dfg/DFGNodeType.h:

(DFG):

  • dfg/DFGSpeculativeJIT.cpp:

(DFG):
(JSC::DFG::SpeculativeJIT::compileValueToInt32):

  • dfg/DFGSpeculativeJIT.h:

(SpeculativeJIT):
(DFG):
(FPRTemporary):

  • dfg/DFGSpeculativeJIT32_64.cpp:

(DFG):
(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGSpeculativeJIT64.cpp:

(DFG):

LayoutTests:

Reviewed by Geoffrey Garen.

  • fast/js/dfg-value-to-int32-with-side-effect-expected.txt: Added.
  • fast/js/dfg-value-to-int32-with-side-effect.html: Added.
  • fast/js/jsc-test-list:
  • fast/js/script-tests/dfg-value-to-int32-with-side-effect.js: Added.

(foo):
(.result.foo):

Location:
trunk
Files:
3 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r143240 r143241  
     12013-02-17  Filip Pizlo  <fpizlo@apple.com>
     2
     3        Get rid of DFG::DoubleOperand and simplify ValueToInt32
     4        https://bugs.webkit.org/show_bug.cgi?id=110072
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        * fast/js/dfg-value-to-int32-with-side-effect-expected.txt: Added.
     9        * fast/js/dfg-value-to-int32-with-side-effect.html: Added.
     10        * fast/js/jsc-test-list:
     11        * fast/js/script-tests/dfg-value-to-int32-with-side-effect.js: Added.
     12        (foo):
     13        (.result.foo):
     14
    1152013-02-18  Joseph Pecoraro  <pecoraro@apple.com>
    216
  • trunk/LayoutTests/fast/js/jsc-test-list

    r142779 r143241  
    188188fast/js/dfg-uint8array
    189189fast/js/dfg-uint8clampedarray
     190fast/js/dfg-value-to-int32-with-side-effects
    190191fast/js/dfg-weak-js-constant-silent-fill
    191192fast/js/dictionary-no-cache
  • trunk/Source/JavaScriptCore/ChangeLog

    r143235 r143241  
     12013-02-17  Filip Pizlo  <fpizlo@apple.com>
     2
     3        Get rid of DFG::DoubleOperand and simplify ValueToInt32
     4        https://bugs.webkit.org/show_bug.cgi?id=110072
     5
     6        Reviewed by Geoffrey Garen.
     7       
     8        ValueToInt32 had a side-effecting path, which was not OSR-friendly: an OSR after
     9        the side-effect would lead to the side-effect re-executing. I got rid of that path
     10        and replaced it with an optimization for the case where the input is speculated
     11        number-or-other. This makes idioms like null|0 and true|0 work as expected, and
     12        get optimized appropriately.
     13       
     14        Also got rid of DoubleOperand. Replaced all remaining uses of it with
     15        SpeculateDoubleOperand. Because the latter asserts that the Edge is a DoubleUse
     16        edge and the remaining uses of DoubleOperand are all for untyped uses, I worked
     17        around the assertion by setting the UseKind to DoubleUse by force. This is sound,
     18        since all existing assertions for DoubleUse are actually asserting that we're not
     19        converting a value to double unexpectedly. But all of these calls to
     20        SpeculateDoubleOperand are when the operand is already known to be represented as
     21        double, so there is no conversion.
     22       
     23        This is neutral on benchmarks, except stanford-crypto-ccm, which speeds up a
     24        little. Mostly, this is intended to delete a bunch of code. DoubleOperand was
     25        equivalent to the replace-edge-with-DoubleUse trick that I'm using now, except it
     26        involved a _lot_ more code.
     27
     28        * dfg/DFGAbstractState.cpp:
     29        (JSC::DFG::AbstractState::execute):
     30        * dfg/DFGCSEPhase.cpp:
     31        (JSC::DFG::CSEPhase::performNodeCSE):
     32        * dfg/DFGFixupPhase.cpp:
     33        (JSC::DFG::FixupPhase::fixupNode):
     34        * dfg/DFGNodeType.h:
     35        (DFG):
     36        * dfg/DFGSpeculativeJIT.cpp:
     37        (DFG):
     38        (JSC::DFG::SpeculativeJIT::compileValueToInt32):
     39        * dfg/DFGSpeculativeJIT.h:
     40        (SpeculativeJIT):
     41        (DFG):
     42        (FPRTemporary):
     43        * dfg/DFGSpeculativeJIT32_64.cpp:
     44        (DFG):
     45        (JSC::DFG::SpeculativeJIT::compile):
     46        * dfg/DFGSpeculativeJIT64.cpp:
     47        (DFG):
     48
    1492013-02-18  Ádám Kallai  <kadam@inf.u-szeged.hu>
    250
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractState.cpp

    r143024 r143241  
    426426        if (node->child1()->shouldSpeculateInteger())
    427427            speculateInt32Unary(node);
     428        else if (node->child1()->shouldSpeculateBoolean())
     429            speculateBooleanUnary(node);
    428430        else if (node->child1()->shouldSpeculateNumber())
    429431            speculateNumberUnary(node);
    430         else if (node->child1()->shouldSpeculateBoolean())
    431             speculateBooleanUnary(node);
    432         else
    433             node->setCanExit(false);
     432        else {
     433            node->setCanExit(forNode(node->child1()).m_type & SpecCell);
     434            forNode(node->child1()).filter(~SpecCell);
     435        }
    434436       
    435437        forNode(node).set(SpecInt32);
  • trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp

    r142544 r143241  
    11331133        case TypeOf:
    11341134        case CompareEqConstant:
     1135        case ValueToInt32:
    11351136            setReplacement(pureCSE(node));
    11361137            break;
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r142779 r143241  
    178178        case ArrayPop: {
    179179            blessArrayOperation(node->child1(), Edge(), 1);
    180             break;
    181         }
    182            
    183         case ValueToInt32: {
    184             if (node->child1()->shouldSpeculateNumber()
    185                 && node->mustGenerate()) {
    186                 node->clearFlags(NodeMustGenerate);
    187                 m_graph.deref(node);
    188             }
    189180            break;
    190181        }
  • trunk/Source/JavaScriptCore/dfg/DFGNodeType.h

    r142544 r143241  
    8787    macro(BitURShift, NodeResultInt32) \
    8888    /* Bitwise operators call ToInt32 on their operands. */\
    89     macro(ValueToInt32, NodeResultInt32 | NodeMustGenerate) \
     89    macro(ValueToInt32, NodeResultInt32) \
    9090    /* Used to box the result of URShift nodes (result has range 0..2^32-1). */\
    9191    macro(UInt32ToNumber, NodeResultNumber) \
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r143168 r143241  
    13891389}
    13901390
    1391 FPRTemporary::FPRTemporary(SpeculativeJIT* jit, DoubleOperand& op1)
    1392     : m_jit(jit)
    1393     , m_fpr(InvalidFPRReg)
    1394 {
    1395     if (m_jit->canReuse(op1.node()))
    1396         m_fpr = m_jit->reuse(op1.fpr());
    1397     else
    1398         m_fpr = m_jit->fprAllocate();
    1399 }
    1400 
    1401 FPRTemporary::FPRTemporary(SpeculativeJIT* jit, DoubleOperand& op1, DoubleOperand& op2)
    1402     : m_jit(jit)
    1403     , m_fpr(InvalidFPRReg)
    1404 {
    1405     if (m_jit->canReuse(op1.node()))
    1406         m_fpr = m_jit->reuse(op1.fpr());
    1407     else if (m_jit->canReuse(op2.node()))
    1408         m_fpr = m_jit->reuse(op2.fpr());
    1409     else
    1410         m_fpr = m_jit->fprAllocate();
    1411 }
    1412 
    14131391FPRTemporary::FPRTemporary(SpeculativeJIT* jit, SpeculateDoubleOperand& op1)
    14141392    : m_jit(jit)
     
    21802158    }
    21812159   
    2182     if (node->child1()->shouldSpeculateNumber()) {
    2183         switch (checkGeneratedTypeForToInt32(node->child1().node())) {
    2184         case GeneratedOperandInteger: {
    2185             SpeculateIntegerOperand op1(this, node->child1());
    2186             GPRTemporary result(this, op1);
    2187             m_jit.move(op1.gpr(), result.gpr());
    2188             integerResult(result.gpr(), node, op1.format());
    2189             return;
    2190         }
    2191         case GeneratedOperandDouble: {
    2192             GPRTemporary result(this);
    2193             DoubleOperand op1(this, node->child1());
    2194             FPRReg fpr = op1.fpr();
    2195             GPRReg gpr = result.gpr();
    2196             JITCompiler::Jump notTruncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateFailed);
     2160    if (node->child1()->shouldSpeculateBoolean()) {
     2161        SpeculateBooleanOperand op1(this, node->child1());
     2162        GPRTemporary result(this, op1);
     2163       
     2164        m_jit.move(op1.gpr(), result.gpr());
     2165        m_jit.and32(JITCompiler::TrustedImm32(1), result.gpr());
     2166       
     2167        integerResult(result.gpr(), node);
     2168        return;
     2169    }
     2170   
     2171    switch (checkGeneratedTypeForToInt32(node->child1().node())) {
     2172    case GeneratedOperandInteger: {
     2173        SpeculateIntegerOperand op1(this, node->child1());
     2174        GPRTemporary result(this, op1);
     2175        m_jit.move(op1.gpr(), result.gpr());
     2176        integerResult(result.gpr(), node, op1.format());
     2177        return;
     2178    }
     2179    case GeneratedOperandDouble: {
     2180        GPRTemporary result(this);
     2181        SpeculateDoubleOperand op1(this, Edge(node->child1().node(), DoubleUse)); // SpeculateDoubleOperand will assert that this is a double use. We force it to think that it was a double use, since we are inferring that we ought to emit a double use quite late.
     2182        FPRReg fpr = op1.fpr();
     2183        GPRReg gpr = result.gpr();
     2184        JITCompiler::Jump notTruncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateFailed);
    21972185           
    2198             addSlowPathGenerator(slowPathCall(notTruncatedToInteger, this, toInt32, gpr, fpr));
    2199 
    2200             integerResult(gpr, node);
    2201             return;
    2202         }
    2203         case GeneratedOperandJSValue: {
    2204             GPRTemporary result(this);
     2186        addSlowPathGenerator(slowPathCall(notTruncatedToInteger, this, toInt32, gpr, fpr));
     2187
     2188        integerResult(gpr, node);
     2189        return;
     2190    }
     2191    case GeneratedOperandJSValue: {
     2192        GPRTemporary result(this);
    22052193#if USE(JSVALUE64)
    2206             JSValueOperand op1(this, node->child1());
    2207 
    2208             GPRReg gpr = op1.gpr();
    2209             GPRReg resultGpr = result.gpr();
     2194        JSValueOperand op1(this, node->child1());
     2195
     2196        GPRReg gpr = op1.gpr();
     2197        GPRReg resultGpr = result.gpr();
     2198        FPRTemporary tempFpr(this);
     2199        FPRReg fpr = tempFpr.fpr();
     2200
     2201        JITCompiler::Jump isInteger = m_jit.branch64(MacroAssembler::AboveOrEqual, gpr, GPRInfo::tagTypeNumberRegister);
     2202        JITCompiler::JumpList converted;
     2203
     2204        if (!isNumberSpeculation(m_state.forNode(node->child1()).m_type)) {
     2205            if (node->child1()->shouldSpeculateNumber())
     2206                speculationCheck(BadType, JSValueRegs(gpr), node->child1(), m_jit.branchTest64(MacroAssembler::Zero, gpr, GPRInfo::tagTypeNumberRegister));
     2207            else {
     2208                JITCompiler::Jump isNumber = m_jit.branchTest64(MacroAssembler::NonZero, gpr, GPRInfo::tagTypeNumberRegister);
     2209               
     2210                if (m_state.forNode(node->child1()).m_type & SpecCell)
     2211                    speculationCheck(BadType, JSValueRegs(gpr), node->child1(), m_jit.branchTest64(JITCompiler::Zero, gpr, GPRInfo::tagMaskRegister));
     2212               
     2213                // It's not a cell: so true turns into 1 and all else turns into 0.
     2214                m_jit.compare64(JITCompiler::Equal, gpr, TrustedImm32(ValueTrue), resultGpr);
     2215                converted.append(m_jit.jump());
     2216               
     2217                isNumber.link(&m_jit);
     2218            }
     2219        }
     2220
     2221        // First, if we get here we have a double encoded as a JSValue
     2222        m_jit.move(gpr, resultGpr);
     2223        unboxDouble(resultGpr, fpr);
     2224
     2225        silentSpillAllRegisters(resultGpr);
     2226        callOperation(toInt32, resultGpr, fpr);
     2227        silentFillAllRegisters(resultGpr);
     2228
     2229        converted.append(m_jit.jump());
     2230
     2231        isInteger.link(&m_jit);
     2232        m_jit.zeroExtend32ToPtr(gpr, resultGpr);
     2233
     2234        converted.link(&m_jit);
     2235#else
     2236        Node* childNode = node->child1().node();
     2237        VirtualRegister virtualRegister = childNode->virtualRegister();
     2238        GenerationInfo& info = m_generationInfo[virtualRegister];
     2239
     2240        JSValueOperand op1(this, node->child1());
     2241
     2242        GPRReg payloadGPR = op1.payloadGPR();
     2243        GPRReg resultGpr = result.gpr();
     2244       
     2245        JITCompiler::JumpList converted;
     2246
     2247        if (info.registerFormat() == DataFormatJSInteger)
     2248            m_jit.move(payloadGPR, resultGpr);
     2249        else {
     2250            GPRReg tagGPR = op1.tagGPR();
    22102251            FPRTemporary tempFpr(this);
    22112252            FPRReg fpr = tempFpr.fpr();
    2212 
    2213             JITCompiler::Jump isInteger = m_jit.branch64(MacroAssembler::AboveOrEqual, gpr, GPRInfo::tagTypeNumberRegister);
    2214 
    2215             if (!isNumberSpeculation(m_state.forNode(node->child1()).m_type))
    2216                 speculationCheck(BadType, JSValueRegs(gpr), node->child1(), m_jit.branchTest64(MacroAssembler::Zero, gpr, GPRInfo::tagTypeNumberRegister));
    2217 
    2218             // First, if we get here we have a double encoded as a JSValue
    2219             m_jit.move(gpr, resultGpr);
    2220             unboxDouble(resultGpr, fpr);
     2253            FPRTemporary scratch(this);
     2254
     2255            JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, tagGPR, TrustedImm32(JSValue::Int32Tag));
     2256
     2257            if (!isNumberSpeculation(m_state.forNode(node->child1()).m_type)) {
     2258                if (node->child1()->shouldSpeculateNumber())
     2259                    speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), node->child1(), m_jit.branch32(MacroAssembler::AboveOrEqual, tagGPR, TrustedImm32(JSValue::LowestTag)));
     2260                else {
     2261                    JITCompiler::Jump isNumber = m_jit.branch32(MacroAssembler::Below, tagGPR, TrustedImm32(JSValue::LowestTag));
     2262                   
     2263                    if (m_state.forNode(node->child1()).m_type & SpecCell)
     2264                        speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), node->child1(), m_jit.branch32(JITCompiler::Equal, tagGPR, TrustedImm32(JSValue::CellTag)));
     2265                   
     2266                    // It's not a cell: so true turns into 1 and all else turns into 0.
     2267                    JITCompiler::Jump isBoolean = m_jit.branch32(JITCompiler::Equal, tagGPR, TrustedImm32(JSValue::BooleanTag));
     2268                    m_jit.move(TrustedImm32(0), resultGpr);
     2269                    converted.append(m_jit.jump());
     2270                   
     2271                    isBoolean.link(&m_jit);
     2272                    m_jit.move(payloadGPR, resultGpr);
     2273                    converted.append(m_jit.jump());
     2274                   
     2275                    isNumber.link(&m_jit);
     2276                }
     2277            }
     2278
     2279            unboxDouble(tagGPR, payloadGPR, fpr, scratch.fpr());
    22212280
    22222281            silentSpillAllRegisters(resultGpr);
     
    22242283            silentFillAllRegisters(resultGpr);
    22252284
    2226             JITCompiler::Jump converted = m_jit.jump();
     2285            converted.append(m_jit.jump());
    22272286
    22282287            isInteger.link(&m_jit);
    2229             m_jit.zeroExtend32ToPtr(gpr, resultGpr);
     2288            m_jit.move(payloadGPR, resultGpr);
    22302289
    22312290            converted.link(&m_jit);
    2232 #else
    2233             Node* childNode = node->child1().node();
    2234             VirtualRegister virtualRegister = childNode->virtualRegister();
    2235             GenerationInfo& info = m_generationInfo[virtualRegister];
    2236 
    2237             JSValueOperand op1(this, node->child1());
    2238 
    2239             GPRReg payloadGPR = op1.payloadGPR();
    2240             GPRReg resultGpr = result.gpr();
    2241 
    2242             if (info.registerFormat() == DataFormatJSInteger)
    2243                 m_jit.move(payloadGPR, resultGpr);
    2244             else {
    2245                 GPRReg tagGPR = op1.tagGPR();
    2246                 FPRTemporary tempFpr(this);
    2247                 FPRReg fpr = tempFpr.fpr();
    2248                 FPRTemporary scratch(this);
    2249 
    2250                 JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, tagGPR, TrustedImm32(JSValue::Int32Tag));
    2251 
    2252                 if (!isNumberSpeculation(m_state.forNode(node->child1()).m_type))
    2253                     speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), node->child1(), m_jit.branch32(MacroAssembler::AboveOrEqual, tagGPR, TrustedImm32(JSValue::LowestTag)));
    2254 
    2255                 unboxDouble(tagGPR, payloadGPR, fpr, scratch.fpr());
    2256 
    2257                 silentSpillAllRegisters(resultGpr);
    2258                 callOperation(toInt32, resultGpr, fpr);
    2259                 silentFillAllRegisters(resultGpr);
    2260 
    2261                 JITCompiler::Jump converted = m_jit.jump();
    2262 
    2263                 isInteger.link(&m_jit);
    2264                 m_jit.move(payloadGPR, resultGpr);
    2265 
    2266                 converted.link(&m_jit);
    2267             }
    2268 #endif
    2269             integerResult(resultGpr, node);
    2270             return;
    2271         }
    2272         case GeneratedOperandTypeUnknown:
    2273             RELEASE_ASSERT_NOT_REACHED();
    2274             break;
    2275         }
    2276     }
    2277    
    2278     if (node->child1()->shouldSpeculateBoolean()) {
    2279         SpeculateBooleanOperand op1(this, node->child1());
    2280         GPRTemporary result(this, op1);
    2281        
    2282         m_jit.move(op1.gpr(), result.gpr());
    2283         m_jit.and32(JITCompiler::TrustedImm32(1), result.gpr());
    2284        
    2285         integerResult(result.gpr(), node);
    2286         return;
    2287     }
    2288    
    2289     // Do it the safe way.
    2290     nonSpeculativeValueToInt32(node);
    2291     return;
     2291        }
     2292#endif
     2293        integerResult(resultGpr, node);
     2294        return;
     2295    }
     2296    case GeneratedOperandTypeUnknown:
     2297        RELEASE_ASSERT_NOT_REACHED();
     2298        break;
     2299    }
    22922300}
    22932301
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r143168 r143241  
    123123   
    124124    GPRReg fillInteger(Node*, DataFormat& returnFormat);
    125     FPRReg fillDouble(Node*);
    126125#if USE(JSVALUE64)
    127126    GPRReg fillJSValue(Node*);
     
    691690    }
    692691   
    693     void nonSpeculativeValueToInt32(Node*);
    694692    void nonSpeculativeUInt32ToNumber(Node*);
    695693
     
    22982296// === Operand types ===
    22992297//
    2300 // IntegerOperand, DoubleOperand and JSValueOperand.
     2298// IntegerOperand and JSValueOperand.
    23012299//
    23022300// These classes are used to lock the operands to a node into machine
     
    23582356    GPRReg m_gprOrInvalid;
    23592357    DataFormat m_format;
    2360 };
    2361 
    2362 class DoubleOperand {
    2363 public:
    2364     explicit DoubleOperand(SpeculativeJIT* jit, Edge use)
    2365         : m_jit(jit)
    2366         , m_node(use.node())
    2367         , m_fprOrInvalid(InvalidFPRReg)
    2368     {
    2369         ASSERT(m_jit);
    2370        
    2371         // This is counter-intuitive but correct. DoubleOperand is intended to
    2372         // be used only when you're a node that is happy to accept an untyped
    2373         // value, but will special-case for doubles (using DoubleOperand) if the
    2374         // value happened to already be represented as a double. The implication
    2375         // is that you will not try to force the value to become a double if it
    2376         // is not one already.
    2377         ASSERT(use.useKind() != DoubleUse);
    2378        
    2379         if (jit->isFilledDouble(m_node))
    2380             fpr();
    2381     }
    2382 
    2383     ~DoubleOperand()
    2384     {
    2385         ASSERT(m_fprOrInvalid != InvalidFPRReg);
    2386         m_jit->unlock(m_fprOrInvalid);
    2387     }
    2388 
    2389     Node* node() const
    2390     {
    2391         return m_node;
    2392     }
    2393 
    2394     FPRReg fpr()
    2395     {
    2396         if (m_fprOrInvalid == InvalidFPRReg)
    2397             m_fprOrInvalid = m_jit->fillDouble(node());
    2398         return m_fprOrInvalid;
    2399     }
    2400    
    2401     void use()
    2402     {
    2403         m_jit->use(m_node);
    2404     }
    2405 
    2406 private:
    2407     SpeculativeJIT* m_jit;
    2408     Node* m_node;
    2409     FPRReg m_fprOrInvalid;
    24102358};
    24112359
     
    26152563public:
    26162564    FPRTemporary(SpeculativeJIT*);
    2617     FPRTemporary(SpeculativeJIT*, DoubleOperand&);
    2618     FPRTemporary(SpeculativeJIT*, DoubleOperand&, DoubleOperand&);
    26192565    FPRTemporary(SpeculativeJIT*, SpeculateDoubleOperand&);
    26202566    FPRTemporary(SpeculativeJIT*, SpeculateDoubleOperand&, SpeculateDoubleOperand&);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r143165 r143241  
    111111        RELEASE_ASSERT_NOT_REACHED();
    112112        return InvalidGPRReg;
    113     }
    114 }
    115 
    116 FPRReg SpeculativeJIT::fillDouble(Node* node)
    117 {
    118     VirtualRegister virtualRegister = node->virtualRegister();
    119     GenerationInfo& info = m_generationInfo[virtualRegister];
    120 
    121     if (info.registerFormat() == DataFormatNone) {
    122 
    123         if (node->hasConstant()) {
    124             if (isInt32Constant(node)) {
    125                 // FIXME: should not be reachable?
    126                 GPRReg gpr = allocate();
    127                 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(node)), gpr);
    128                 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
    129                 info.fillInteger(*m_stream, gpr);
    130                 unlock(gpr);
    131             } else if (isNumberConstant(node)) {
    132                 FPRReg fpr = fprAllocate();
    133                 m_jit.loadDouble(addressOfDoubleConstant(node), fpr);
    134                 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
    135                 info.fillDouble(*m_stream, fpr);
    136                 return fpr;
    137             } else {
    138                 // FIXME: should not be reachable?
    139                 RELEASE_ASSERT_NOT_REACHED();
    140             }
    141         } else {
    142             DataFormat spillFormat = info.spillFormat();
    143             ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatInteger);
    144             if (spillFormat == DataFormatJSDouble) {
    145                 FPRReg fpr = fprAllocate();
    146                 m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
    147                 m_fprs.retain(fpr, virtualRegister, SpillOrderSpilled);
    148                 info.fillDouble(*m_stream, fpr);
    149                 return fpr;
    150             }
    151 
    152             FPRReg fpr = fprAllocate();
    153             JITCompiler::Jump hasUnboxedDouble;
    154 
    155             if (spillFormat != DataFormatJSInteger && spillFormat != DataFormatInteger) {
    156                 JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag));
    157                 m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
    158                 hasUnboxedDouble = m_jit.jump();
    159                 isInteger.link(&m_jit);
    160             }
    161 
    162             m_jit.convertInt32ToDouble(JITCompiler::payloadFor(virtualRegister), fpr);
    163 
    164             if (hasUnboxedDouble.isSet())
    165                 hasUnboxedDouble.link(&m_jit);
    166 
    167             m_fprs.retain(fpr, virtualRegister, SpillOrderSpilled);
    168             info.fillDouble(*m_stream, fpr);
    169             return fpr;
    170         }
    171     }
    172 
    173     switch (info.registerFormat()) {
    174     case DataFormatNone:
    175         // Should have filled, above.
    176     case DataFormatCell:
    177     case DataFormatJSCell:
    178     case DataFormatBoolean:
    179     case DataFormatJSBoolean:
    180     case DataFormatStorage:
    181         // Should only be calling this function if we know this operand to be numeric.
    182         RELEASE_ASSERT_NOT_REACHED();
    183 
    184     case DataFormatJSInteger:
    185     case DataFormatJS: {
    186         GPRReg tagGPR = info.tagGPR();
    187         GPRReg payloadGPR = info.payloadGPR();
    188         FPRReg fpr = fprAllocate();
    189         m_gprs.lock(tagGPR);
    190         m_gprs.lock(payloadGPR);
    191 
    192         JITCompiler::Jump hasUnboxedDouble;
    193 
    194         if (info.registerFormat() != DataFormatJSInteger) {
    195             FPRTemporary scratch(this);
    196             JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, tagGPR, TrustedImm32(JSValue::Int32Tag));
    197             m_jit.jitAssertIsJSDouble(tagGPR);
    198             unboxDouble(tagGPR, payloadGPR, fpr, scratch.fpr());
    199             hasUnboxedDouble = m_jit.jump();
    200             isInteger.link(&m_jit);
    201         }
    202 
    203         m_jit.convertInt32ToDouble(payloadGPR, fpr);
    204 
    205         if (hasUnboxedDouble.isSet())
    206             hasUnboxedDouble.link(&m_jit);
    207 
    208         m_gprs.release(tagGPR);
    209         m_gprs.release(payloadGPR);
    210         m_gprs.unlock(tagGPR);
    211         m_gprs.unlock(payloadGPR);
    212         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
    213         info.fillDouble(*m_stream, fpr);
    214         info.killSpilled();
    215         return fpr;
    216     }
    217 
    218     case DataFormatInteger: {
    219         FPRReg fpr = fprAllocate();
    220         GPRReg gpr = info.gpr();
    221         m_gprs.lock(gpr);
    222         m_jit.convertInt32ToDouble(gpr, fpr);
    223         m_gprs.unlock(gpr);
    224         return fpr;
    225     }
    226 
    227     case DataFormatJSDouble:
    228     case DataFormatDouble: {
    229         FPRReg fpr = info.fpr();
    230         m_fprs.lock(fpr);
    231         return fpr;
    232     }
    233 
    234     default:
    235         RELEASE_ASSERT_NOT_REACHED();
    236         return InvalidFPRReg;
    237113    }
    238114}
     
    364240}
    365241
    366 void SpeculativeJIT::nonSpeculativeValueToInt32(Node* node)
    367 {
    368     ASSERT(!isInt32Constant(node->child1().node()));
    369 
    370     if (isKnownInteger(node->child1().node())) {
    371         IntegerOperand op1(this, node->child1());
    372         GPRTemporary result(this, op1);
    373         m_jit.move(op1.gpr(), result.gpr());
    374         integerResult(result.gpr(), node);
    375         return;
    376     }
    377 
    378     GenerationInfo& childInfo = m_generationInfo[node->child1()->virtualRegister()];
    379     if (childInfo.isJSDouble()) {
    380         DoubleOperand op1(this, node->child1());
    381         GPRTemporary result(this);
    382         FPRReg fpr = op1.fpr();
    383         GPRReg gpr = result.gpr();
    384         op1.use();
    385         JITCompiler::Jump notTruncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateFailed);
    386 
    387         addSlowPathGenerator(slowPathCall(notTruncatedToInteger, this, toInt32, gpr, fpr));
    388 
    389         integerResult(gpr, node, UseChildrenCalledExplicitly);
    390         return;
    391     }
    392 
    393     JSValueOperand op1(this, node->child1());
    394     GPRTemporary result(this);
    395     GPRReg tagGPR = op1.tagGPR();
    396     GPRReg payloadGPR = op1.payloadGPR();
    397     GPRReg resultGPR = result.gpr();
    398     op1.use();
    399 
    400     JITCompiler::Jump isNotInteger = m_jit.branch32(MacroAssembler::NotEqual, tagGPR, TrustedImm32(JSValue::Int32Tag));
    401 
    402     m_jit.move(payloadGPR, resultGPR);
    403    
    404     addSlowPathGenerator(slowPathCall(isNotInteger, this, dfgConvertJSValueToInt32, resultGPR, tagGPR, payloadGPR));
    405    
    406     integerResult(resultGPR, node, UseChildrenCalledExplicitly);
    407 }
    408 
    409242void SpeculativeJIT::nonSpeculativeUInt32ToNumber(Node* node)
    410243{
     
    22162049            SpeculatedType predictedType = node->variableAccessData()->argumentAwarePrediction();
    22172050            if (m_generationInfo[node->child1()->virtualRegister()].registerFormat() == DataFormatDouble) {
    2218                 DoubleOperand value(this, node->child1());
     2051                SpeculateDoubleOperand value(this, Edge(node->child1().node(), DoubleUse));
    22192052                m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node->local()));
    22202053                noResult(node);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r143165 r143241  
    118118}
    119119
    120 FPRReg SpeculativeJIT::fillDouble(Node* node)
    121 {
    122     VirtualRegister virtualRegister = node->virtualRegister();
    123     GenerationInfo& info = m_generationInfo[virtualRegister];
    124 
    125     if (info.registerFormat() == DataFormatNone) {
    126         if (node->hasConstant()) {
    127             GPRReg gpr = allocate();
    128        
    129             if (isInt32Constant(node)) {
    130                 // FIXME: should not be reachable?
    131                 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(node)), gpr);
    132                 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
    133                 info.fillInteger(*m_stream, gpr);
    134                 unlock(gpr);
    135             } else if (isNumberConstant(node)) {
    136                 FPRReg fpr = fprAllocate();
    137                 m_jit.move(MacroAssembler::Imm64(reinterpretDoubleToInt64(valueOfNumberConstant(node))), gpr);
    138                 m_jit.move64ToDouble(gpr, fpr);
    139                 unlock(gpr);
    140 
    141                 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
    142                 info.fillDouble(*m_stream, fpr);
    143                 return fpr;
    144             } else {
    145                 // FIXME: should not be reachable?
    146                 ASSERT(isJSConstant(node));
    147                 JSValue jsValue = valueOfJSConstant(node);
    148                 m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsValue)), gpr);
    149                 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
    150                 info.fillJSValue(*m_stream, gpr, DataFormatJS);
    151                 unlock(gpr);
    152             }
    153         } else {
    154             DataFormat spillFormat = info.spillFormat();
    155             switch (spillFormat) {
    156             case DataFormatDouble: {
    157                 FPRReg fpr = fprAllocate();
    158                 m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
    159                 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
    160                 info.fillDouble(*m_stream, fpr);
    161                 return fpr;
    162             }
    163                
    164             case DataFormatInteger: {
    165                 GPRReg gpr = allocate();
    166                
    167                 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
    168                 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
    169                 info.fillInteger(*m_stream, gpr);
    170                 unlock(gpr);
    171                 break;
    172             }
    173 
    174             default:
    175                 GPRReg gpr = allocate();
    176        
    177                 RELEASE_ASSERT(spillFormat & DataFormatJS);
    178                 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
    179                 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
    180                 info.fillJSValue(*m_stream, gpr, spillFormat);
    181                 unlock(gpr);
    182                 break;
    183             }
    184         }
    185     }
    186 
    187     switch (info.registerFormat()) {
    188     case DataFormatNone:
    189         // Should have filled, above.
    190     case DataFormatCell:
    191     case DataFormatJSCell:
    192     case DataFormatBoolean:
    193     case DataFormatJSBoolean:
    194     case DataFormatStorage:
    195         // Should only be calling this function if we know this operand to be numeric.
    196         RELEASE_ASSERT_NOT_REACHED();
    197 
    198     case DataFormatJS: {
    199         GPRReg jsValueGpr = info.gpr();
    200         m_gprs.lock(jsValueGpr);
    201         FPRReg fpr = fprAllocate();
    202         GPRReg tempGpr = allocate(); // FIXME: can we skip this allocation on the last use of the virtual register?
    203 
    204         JITCompiler::Jump isInteger = m_jit.branch64(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
    205 
    206         m_jit.jitAssertIsJSDouble(jsValueGpr);
    207 
    208         // First, if we get here we have a double encoded as a JSValue
    209         m_jit.move(jsValueGpr, tempGpr);
    210         unboxDouble(tempGpr, fpr);
    211         JITCompiler::Jump hasUnboxedDouble = m_jit.jump();
    212 
    213         // Finally, handle integers.
    214         isInteger.link(&m_jit);
    215         m_jit.convertInt32ToDouble(jsValueGpr, fpr);
    216         hasUnboxedDouble.link(&m_jit);
    217 
    218         m_gprs.release(jsValueGpr);
    219         m_gprs.unlock(jsValueGpr);
    220         m_gprs.unlock(tempGpr);
    221         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
    222         info.fillDouble(*m_stream, fpr);
    223         info.killSpilled();
    224         return fpr;
    225     }
    226 
    227     case DataFormatJSInteger:
    228     case DataFormatInteger: {
    229         FPRReg fpr = fprAllocate();
    230         GPRReg gpr = info.gpr();
    231         m_gprs.lock(gpr);
    232         m_jit.convertInt32ToDouble(gpr, fpr);
    233         m_gprs.unlock(gpr);
    234         return fpr;
    235     }
    236 
    237     // Unbox the double
    238     case DataFormatJSDouble: {
    239         GPRReg gpr = info.gpr();
    240         FPRReg fpr = fprAllocate();
    241         if (m_gprs.isLocked(gpr)) {
    242             // Make sure we don't trample gpr if it is in use.
    243             GPRReg temp = allocate();
    244             m_jit.move(gpr, temp);
    245             unboxDouble(temp, fpr);
    246             unlock(temp);
    247         } else
    248             unboxDouble(gpr, fpr);
    249 
    250         m_gprs.release(gpr);
    251         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
    252 
    253         info.fillDouble(*m_stream, fpr);
    254         return fpr;
    255     }
    256 
    257     case DataFormatDouble: {
    258         FPRReg fpr = info.fpr();
    259         m_fprs.lock(fpr);
    260         return fpr;
    261     }
    262        
    263     default:
    264         RELEASE_ASSERT_NOT_REACHED();
    265         return InvalidFPRReg;
    266     }
    267 }
    268 
    269120GPRReg SpeculativeJIT::fillJSValue(Node* node)
    270121{
     
    362213        return InvalidGPRReg;
    363214    }
    364 }
    365 
    366 void SpeculativeJIT::nonSpeculativeValueToInt32(Node* node)
    367 {
    368     ASSERT(!isInt32Constant(node->child1().node()));
    369    
    370     if (isKnownInteger(node->child1().node())) {
    371         IntegerOperand op1(this, node->child1());
    372         GPRTemporary result(this, op1);
    373         m_jit.zeroExtend32ToPtr(op1.gpr(), result.gpr());
    374         integerResult(result.gpr(), m_currentNode);
    375         return;
    376     }
    377    
    378     GenerationInfo& childInfo = m_generationInfo[node->child1()->virtualRegister()];
    379     if (childInfo.isJSDouble()) {
    380         DoubleOperand op1(this, node->child1());
    381         GPRTemporary result(this);
    382         FPRReg fpr = op1.fpr();
    383         GPRReg gpr = result.gpr();
    384         op1.use();
    385         JITCompiler::Jump notTruncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateFailed);
    386        
    387         addSlowPathGenerator(
    388             slowPathCall(notTruncatedToInteger, this, toInt32, gpr, fpr));
    389 
    390         integerResult(gpr, m_currentNode, UseChildrenCalledExplicitly);
    391         return;
    392     }
    393    
    394     JSValueOperand op1(this, node->child1());
    395     GPRTemporary result(this, op1);
    396     GPRReg jsValueGpr = op1.gpr();
    397     GPRReg resultGPR = result.gpr();
    398     op1.use();
    399 
    400     JITCompiler::Jump isNotInteger = m_jit.branch64(MacroAssembler::Below, jsValueGpr, GPRInfo::tagTypeNumberRegister);
    401 
    402     m_jit.zeroExtend32ToPtr(jsValueGpr, resultGPR);
    403    
    404     addSlowPathGenerator(
    405         slowPathCall(isNotInteger, this, dfgConvertJSValueToInt32, resultGPR, jsValueGpr));
    406 
    407     integerResult(resultGPR, m_currentNode, UseChildrenCalledExplicitly);
    408215}
    409216
Note: See TracChangeset for help on using the changeset viewer.