Changeset 205675 in webkit


Ignore:
Timestamp:
Sep 8, 2016 4:19:38 PM (8 years ago)
Author:
sbarati@apple.com
Message:

We should inline operationConvertJSValueToBoolean into JIT code
https://bugs.webkit.org/show_bug.cgi?id=161729

Reviewed by Filip Pizlo.

JSTests:

  • stress/value-to-boolean.js: Added.

(assert):
(test1):
(test2):
(test3):

Source/JavaScriptCore:

This patch introduces an AssemblyHelpers emitter function
that replaces operationConvertJSValueToBoolean. This operation
was showing up when I was doing performance analysis for the
speedometer benchmark. I saw that it was spending about 1% of
its time in this function. Hopefully this patch can help us speedup
up speedometer by a little bit.

  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::compileLogicalNot):
(JSC::DFG::SpeculativeJIT::emitBranch):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compileLogicalNot):
(JSC::DFG::SpeculativeJIT::emitBranch):

  • jit/AssemblyHelpers.cpp:

(JSC::AssemblyHelpers::emitConvertValueToBoolean):

  • jit/AssemblyHelpers.h:

(JSC::AssemblyHelpers::emitAllocateDestructibleObject): Deleted.

  • jit/JIT.cpp:

(JSC::JIT::privateCompileSlowCases):

  • jit/JIT.h:
  • jit/JITOpcodes.cpp:

(JSC::JIT::emit_op_jfalse):
(JSC::JIT::emit_op_jtrue):
(JSC::JIT::emitSlow_op_jfalse): Deleted.
(JSC::JIT::emitSlow_op_jtrue): Deleted.

  • jit/JITOpcodes32_64.cpp:

(JSC::JIT::emit_op_jfalse):
(JSC::JIT::emit_op_jtrue):
(JSC::JIT::emitSlow_op_jfalse): Deleted.
(JSC::JIT::emitSlow_op_jtrue): Deleted.

  • jit/JITOperations.cpp:
  • jit/JITOperations.h:
Location:
trunk
Files:
1 added
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r205664 r205675  
     12016-09-08  Saam Barati  <sbarati@apple.com>
     2
     3        We should inline operationConvertJSValueToBoolean into JIT code
     4        https://bugs.webkit.org/show_bug.cgi?id=161729
     5
     6        Reviewed by Filip Pizlo.
     7
     8        * stress/value-to-boolean.js: Added.
     9        (assert):
     10        (test1):
     11        (test2):
     12        (test3):
     13
    1142016-09-08  Mark Lam  <mark.lam@apple.com>
    215
  • trunk/Source/JavaScriptCore/ChangeLog

    r205670 r205675  
     12016-09-08  Saam Barati  <sbarati@apple.com>
     2
     3        We should inline operationConvertJSValueToBoolean into JIT code
     4        https://bugs.webkit.org/show_bug.cgi?id=161729
     5
     6        Reviewed by Filip Pizlo.
     7
     8        This patch introduces an AssemblyHelpers emitter function
     9        that replaces operationConvertJSValueToBoolean. This operation
     10        was showing up when I was doing performance analysis for the
     11        speedometer benchmark. I saw that it was spending about 1% of
     12        its time in this function. Hopefully this patch can help us speedup
     13        up speedometer by a little bit.
     14
     15        * dfg/DFGSpeculativeJIT32_64.cpp:
     16        (JSC::DFG::SpeculativeJIT::compileLogicalNot):
     17        (JSC::DFG::SpeculativeJIT::emitBranch):
     18        * dfg/DFGSpeculativeJIT64.cpp:
     19        (JSC::DFG::SpeculativeJIT::compileLogicalNot):
     20        (JSC::DFG::SpeculativeJIT::emitBranch):
     21        * jit/AssemblyHelpers.cpp:
     22        (JSC::AssemblyHelpers::emitConvertValueToBoolean):
     23        * jit/AssemblyHelpers.h:
     24        (JSC::AssemblyHelpers::emitAllocateDestructibleObject): Deleted.
     25        * jit/JIT.cpp:
     26        (JSC::JIT::privateCompileSlowCases):
     27        * jit/JIT.h:
     28        * jit/JITOpcodes.cpp:
     29        (JSC::JIT::emit_op_jfalse):
     30        (JSC::JIT::emit_op_jtrue):
     31        (JSC::JIT::emitSlow_op_jfalse): Deleted.
     32        (JSC::JIT::emitSlow_op_jtrue): Deleted.
     33        * jit/JITOpcodes32_64.cpp:
     34        (JSC::JIT::emit_op_jfalse):
     35        (JSC::JIT::emit_op_jtrue):
     36        (JSC::JIT::emitSlow_op_jfalse): Deleted.
     37        (JSC::JIT::emitSlow_op_jtrue): Deleted.
     38        * jit/JITOperations.cpp:
     39        * jit/JITOperations.h:
     40
    1412016-09-08  Chris Dumez  <cdumez@apple.com>
    242
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r205520 r205675  
    435435            else if (node->child1()->shouldSpeculateStringOrOther())
    436436                fixEdge<StringOrOtherUse>(node->child1());
     437            else {
     438                WatchpointSet* masqueradesAsUndefinedWatchpoint = m_graph.globalObjectFor(node->origin.semantic)->masqueradesAsUndefinedWatchpoint();
     439                if (masqueradesAsUndefinedWatchpoint->isStillValid())
     440                    m_graph.watchpoints().addLazily(masqueradesAsUndefinedWatchpoint);
     441            }
    437442            break;
    438443        }
     
    979984            else if (node->child1()->shouldSpeculateStringOrOther())
    980985                fixEdge<StringOrOtherUse>(node->child1());
     986            else {
     987                WatchpointSet* masqueradesAsUndefinedWatchpoint = m_graph.globalObjectFor(node->origin.semantic)->masqueradesAsUndefinedWatchpoint();
     988                if (masqueradesAsUndefinedWatchpoint->isStillValid())
     989                    m_graph.watchpoints().addLazily(masqueradesAsUndefinedWatchpoint);
     990            }
    981991            break;
    982992        }
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r205520 r205675  
    16861686    case UntypedUse: {
    16871687        JSValueOperand arg1(this, node->child1());
    1688         GPRTemporary resultPayload(this, Reuse, arg1, PayloadWord);
    1689         GPRReg arg1TagGPR = arg1.tagGPR();
    1690         GPRReg arg1PayloadGPR = arg1.payloadGPR();
    1691         JSValueRegs arg1Regs = arg1.jsValueRegs();
    1692         GPRReg resultPayloadGPR = resultPayload.gpr();
    1693        
    1694         arg1.use();
    1695 
    1696         JITCompiler::Jump slowCase = m_jit.branch32(JITCompiler::NotEqual, arg1TagGPR, TrustedImm32(JSValue::BooleanTag));
    1697    
    1698         m_jit.move(arg1PayloadGPR, resultPayloadGPR);
    1699 
    1700         addSlowPathGenerator(
    1701             slowPathCall(
    1702                 slowCase, this, operationConvertJSValueToBoolean, resultPayloadGPR, arg1Regs, NeedToSpill, ExceptionCheckRequirement::CheckNotNeeded));
    1703    
    1704         m_jit.xor32(TrustedImm32(1), resultPayloadGPR);
    1705         booleanResult(resultPayloadGPR, node, UseChildrenCalledExplicitly);
     1688        GPRTemporary result(this);
     1689        GPRTemporary temp(this);
     1690        FPRTemporary valueFPR(this);
     1691        FPRTemporary tempFPR(this);
     1692
     1693        GPRReg resultGPR = result.gpr();
     1694
     1695        bool shouldCheckMasqueradesAsUndefined = !masqueradesAsUndefinedWatchpointIsStillValid();
     1696        JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
     1697        bool negateResult = true;
     1698        m_jit.emitConvertValueToBoolean(arg1.jsValueRegs(), resultGPR, temp.gpr(), valueFPR.fpr(), tempFPR.fpr(), shouldCheckMasqueradesAsUndefined, globalObject, negateResult);
     1699        booleanResult(resultGPR, node);
    17061700        return;
    17071701    }
     
    18351829    case UntypedUse: {
    18361830        JSValueOperand value(this, node->child1());
    1837         value.fill();
    1838         GPRReg valueTagGPR = value.tagGPR();
    1839         GPRReg valuePayloadGPR = value.payloadGPR();
    1840 
     1831        FPRTemporary valueFPR(this);
     1832        FPRTemporary tempFPR(this);
    18411833        GPRTemporary result(this);
     1834        GPRTemporary temp(this);
     1835
     1836        JSValueRegs valueRegs = value.jsValueRegs();
    18421837        GPRReg resultGPR = result.gpr();
    18431838   
    18441839        use(node->child1());
    1845    
    1846         JITCompiler::Jump fastPath = m_jit.branch32(JITCompiler::Equal, valueTagGPR, JITCompiler::TrustedImm32(JSValue::Int32Tag));
    1847         JITCompiler::Jump slowPath = m_jit.branch32(JITCompiler::NotEqual, valueTagGPR, JITCompiler::TrustedImm32(JSValue::BooleanTag));
    1848 
    1849         fastPath.link(&m_jit);
    1850         branchTest32(JITCompiler::Zero, valuePayloadGPR, notTaken);
     1840
     1841        bool shouldCheckMasqueradesAsUndefined = !masqueradesAsUndefinedWatchpointIsStillValid();
     1842        JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
     1843        m_jit.emitConvertValueToBoolean(valueRegs, resultGPR, temp.gpr(), valueFPR.fpr(), tempFPR.fpr(), shouldCheckMasqueradesAsUndefined, globalObject);
     1844        branchTest32(JITCompiler::Zero, resultGPR, notTaken);
    18511845        jump(taken, ForceJump);
    18521846
    1853         slowPath.link(&m_jit);
    1854         silentSpillAllRegisters(resultGPR);
    1855         callOperation(operationConvertJSValueToBoolean, resultGPR, value.jsValueRegs());
    1856         silentFillAllRegisters(resultGPR);
    1857    
    1858         branchTest32(JITCompiler::NonZero, resultGPR, taken);
    1859         jump(notTaken);
    1860    
    18611847        noResult(node, UseChildrenCalledExplicitly);
    18621848        return;
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r205611 r205675  
    18391839        GPRReg arg1GPR = arg1.gpr();
    18401840        GPRReg resultGPR = result.gpr();
    1841    
    1842         arg1.use();
    1843    
    1844         m_jit.move(arg1GPR, resultGPR);
    1845         m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), resultGPR);
    1846         JITCompiler::Jump slowCase = m_jit.branchTest64(JITCompiler::NonZero, resultGPR, TrustedImm32(static_cast<int32_t>(~1)));
    1847    
    1848         addSlowPathGenerator(
    1849             slowPathCall(slowCase, this, operationConvertJSValueToBoolean, resultGPR, arg1GPR, NeedToSpill, ExceptionCheckRequirement::CheckNotNeeded));
    1850    
    1851         m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueTrue)), resultGPR);
    1852         jsValueResult(resultGPR, node, DataFormatJSBoolean, UseChildrenCalledExplicitly);
     1841
     1842        FPRTemporary valueFPR(this);
     1843        FPRTemporary tempFPR(this);
     1844
     1845        bool shouldCheckMasqueradesAsUndefined = !masqueradesAsUndefinedWatchpointIsStillValid();
     1846        JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
     1847        Optional<GPRTemporary> scratch;
     1848        GPRReg scratchGPR = InvalidGPRReg;
     1849        if (shouldCheckMasqueradesAsUndefined) {
     1850            scratch = GPRTemporary(this);
     1851            scratchGPR = scratch->gpr();
     1852        }
     1853        bool negateResult = true;
     1854        m_jit.emitConvertValueToBoolean(JSValueRegs(arg1GPR), resultGPR, scratchGPR, valueFPR.fpr(), tempFPR.fpr(), shouldCheckMasqueradesAsUndefined, globalObject, negateResult);
     1855        m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
     1856        jsValueResult(resultGPR, node, DataFormatJSBoolean);
    18531857        return;
    18541858    }
     
    19931997        } else {
    19941998            GPRTemporary result(this);
     1999            FPRTemporary fprValue(this);
     2000            FPRTemporary fprTemp(this);
     2001            Optional<GPRTemporary> scratch;
     2002
     2003            GPRReg scratchGPR = InvalidGPRReg;
     2004            bool shouldCheckMasqueradesAsUndefined = !masqueradesAsUndefinedWatchpointIsStillValid();
     2005            if (shouldCheckMasqueradesAsUndefined) {
     2006                scratch = GPRTemporary(this);
     2007                scratchGPR = scratch->gpr();
     2008            }
     2009
    19952010            GPRReg resultGPR = result.gpr();
     2011            FPRReg valueFPR = fprValue.fpr();
     2012            FPRReg tempFPR = fprTemp.fpr();
    19962013           
    19972014            if (node->child1()->prediction() & SpecInt32Only) {
     
    20062023   
    20072024            value.use();
    2008    
    2009             silentSpillAllRegisters(resultGPR);
    2010             callOperation(operationConvertJSValueToBoolean, resultGPR, valueGPR);
    2011             silentFillAllRegisters(resultGPR);
     2025
     2026            JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
     2027            m_jit.emitConvertValueToBoolean(JSValueRegs(valueGPR), resultGPR, scratchGPR, valueFPR, tempFPR, shouldCheckMasqueradesAsUndefined, globalObject);
    20122028   
    20132029            branchTest32(MacroAssembler::NonZero, resultGPR, taken);
  • trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp

    r205520 r205675  
    673673#endif // USE(JSVALUE64)
    674674
     675void AssemblyHelpers::emitConvertValueToBoolean(JSValueRegs value, GPRReg result, GPRReg scratch, FPRReg valueAsFPR, FPRReg tempFPR, bool shouldCheckMasqueradesAsUndefined, JSGlobalObject* globalObject, bool negateResult)
     676{
     677    // Implements the following control flow structure:
     678    // if (value is boolean) {
     679    //     result = value === true
     680    // } else if (value is integer) {
     681    //     result = value !== 0
     682    // } else if (value is double) {
     683    //     result = value !== 0.0 && !isNaN(value);
     684    // } else if (value is cell) {
     685    //     if (value is string) {
     686    //          result = value.length() !== 0;
     687    //     } else {
     688    //          do crazy things for masquerades as undefined
     689    //     }
     690    // } else {
     691    //     result = false;
     692    // }
     693    //
     694    // if (negateResult)
     695    //     result = !result;
     696
     697    JumpList done;
     698    auto notBoolean = branchIfNotBoolean(value, result);
     699#if USE(JSVALUE64)
     700    compare32(negateResult ? NotEqual : Equal, value.gpr(), TrustedImm32(ValueTrue), result);
     701#else
     702    compare32(negateResult ? Equal : NotEqual, value.payloadGPR(), TrustedImm32(0), result);
     703#endif
     704    done.append(jump());
     705
     706    notBoolean.link(this);
     707#if USE(JSVALUE64)
     708    auto isNotNumber = branchIfNotNumber(value.gpr());
     709#else
     710    ASSERT(scratch != InvalidGPRReg);
     711    auto isNotNumber = branchIfNotNumber(value, scratch);
     712#endif
     713    auto isDouble = branchIfNotInt32(value);
     714
     715    // It's an int32.
     716    compare32(negateResult ? Equal : NotEqual, value.payloadGPR(), TrustedImm32(0), result);
     717    done.append(jump());
     718
     719    isDouble.link(this);
     720#if USE(JSVALUE64)
     721    unboxDouble(value.gpr(), result, valueAsFPR);
     722#else
     723    unboxDouble(value, valueAsFPR, tempFPR);
     724#endif
     725    auto isZeroOrNaN = branchDoubleZeroOrNaN(valueAsFPR, tempFPR);
     726    move(negateResult ? TrustedImm32(0) : TrustedImm32(1), result);
     727    done.append(jump());
     728    isZeroOrNaN.link(this);
     729    move(negateResult ? TrustedImm32(1) : TrustedImm32(0), result);
     730    done.append(jump());
     731
     732    isNotNumber.link(this);
     733    auto isNotCellAndIsNotNumberAndIsNotBoolean = branchIfNotCell(value);
     734    auto isCellButNotString = branch8(NotEqual,
     735        Address(value.payloadGPR(), JSCell::typeInfoTypeOffset()), TrustedImm32(StringType));
     736    load32(Address(value.payloadGPR(), JSString::offsetOfLength()), result);
     737    compare32(negateResult ? Equal : NotEqual, result, TrustedImm32(0), result);
     738    done.append(jump());
     739
     740    isCellButNotString.link(this);
     741    if (shouldCheckMasqueradesAsUndefined) {
     742        ASSERT(scratch != InvalidGPRReg);
     743        JumpList isNotMasqueradesAsUndefined;
     744        isNotMasqueradesAsUndefined.append(branchTest8(Zero, Address(value.payloadGPR(), JSCell::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined)));
     745        emitLoadStructure(value.payloadGPR(), result, scratch);
     746        move(TrustedImmPtr(globalObject), scratch);
     747        isNotMasqueradesAsUndefined.append(branchPtr(NotEqual, Address(result, Structure::globalObjectOffset()), scratch));
     748        // We act like we are "undefined" here.
     749        move(negateResult ? TrustedImm32(1) : TrustedImm32(0), result);
     750        done.append(jump());
     751        isNotMasqueradesAsUndefined.link(this);
     752    }
     753    move(negateResult ? TrustedImm32(0) : TrustedImm32(1), result);
     754    done.append(jump());
     755
     756    // null or undefined.
     757    isNotCellAndIsNotNumberAndIsNotBoolean.link(this);
     758    move(negateResult ? TrustedImm32(1) : TrustedImm32(0), result);
     759
     760    done.link(this);
     761}
     762
    675763} // namespace JSC
    676764
  • trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h

    r205666 r205675  
    15261526        storePtr(TrustedImmPtr(0), Address(resultGPR, JSObject::butterflyOffset()));
    15271527    }
     1528
     1529    void emitConvertValueToBoolean(JSValueRegs value, GPRReg result, GPRReg scratchIfShouldCheckMasqueradesAsUndefined, FPRReg, FPRReg, bool shouldCheckMasqueradesAsUndefined, JSGlobalObject*, bool negateResult = false);
    15281530   
    15291531    template<typename ClassType>
  • trunk/Source/JavaScriptCore/jit/JIT.cpp

    r205462 r205675  
    448448        DEFINE_SLOWCASE_OP(op_instanceof)
    449449        DEFINE_SLOWCASE_OP(op_instanceof_custom)
    450         DEFINE_SLOWCASE_OP(op_jfalse)
    451450        DEFINE_SLOWCASE_OP(op_jless)
    452451        DEFINE_SLOWCASE_OP(op_jlesseq)
     
    457456        DEFINE_SLOWCASE_OP(op_jngreater)
    458457        DEFINE_SLOWCASE_OP(op_jngreatereq)
    459         DEFINE_SLOWCASE_OP(op_jtrue)
    460458        DEFINE_SLOWCASE_OP(op_loop_hint)
    461459        DEFINE_SLOWCASE_OP(op_watchdog)
  • trunk/Source/JavaScriptCore/jit/JIT.h

    r205462 r205675  
    625625        void emitSlow_op_instanceof(Instruction*, Vector<SlowCaseEntry>::iterator&);
    626626        void emitSlow_op_instanceof_custom(Instruction*, Vector<SlowCaseEntry>::iterator&);
    627         void emitSlow_op_jfalse(Instruction*, Vector<SlowCaseEntry>::iterator&);
    628627        void emitSlow_op_jless(Instruction*, Vector<SlowCaseEntry>::iterator&);
    629628        void emitSlow_op_jlesseq(Instruction*, Vector<SlowCaseEntry>::iterator&);
  • trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp

    r205666 r205675  
    362362{
    363363    unsigned target = currentInstruction[2].u.operand;
    364     emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
    365 
    366     addJump(branch64(Equal, regT0, TrustedImm64(JSValue::encode(jsNumber(0)))), target);
    367     Jump isNonZero = emitJumpIfInt(regT0);
    368 
    369     addJump(branch64(Equal, regT0, TrustedImm64(JSValue::encode(jsBoolean(false)))), target);
    370     addSlowCase(branch64(NotEqual, regT0, TrustedImm64(JSValue::encode(jsBoolean(true)))));
    371 
    372     isNonZero.link(this);
     364
     365    GPRReg value = regT0;
     366    GPRReg result = regT1;
     367    GPRReg scratch = regT2;
     368    bool shouldCheckMasqueradesAsUndefined = true;
     369
     370    emitGetVirtualRegister(currentInstruction[1].u.operand, value);
     371    emitConvertValueToBoolean(JSValueRegs(value), result, scratch, fpRegT0, fpRegT1, shouldCheckMasqueradesAsUndefined, m_codeBlock->globalObject());
     372
     373    addJump(branchTest32(Zero, result), target);
    373374}
    374375
     
    444445{
    445446    unsigned target = currentInstruction[2].u.operand;
    446     emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
    447 
    448     Jump isZero = branch64(Equal, regT0, TrustedImm64(JSValue::encode(jsNumber(0))));
    449     addJump(emitJumpIfInt(regT0), target);
    450 
    451     addJump(branch64(Equal, regT0, TrustedImm64(JSValue::encode(jsBoolean(true)))), target);
    452     addSlowCase(branch64(NotEqual, regT0, TrustedImm64(JSValue::encode(jsBoolean(false)))));
    453 
    454     isZero.link(this);
     447
     448    GPRReg value = regT0;
     449    GPRReg result = regT1;
     450    GPRReg scratch = regT2;
     451    bool shouldCheckMasqueradesAsUndefined = true;
     452    emitGetVirtualRegister(currentInstruction[1].u.operand, value);
     453    emitConvertValueToBoolean(JSValueRegs(value), result, scratch, fpRegT0, fpRegT1, shouldCheckMasqueradesAsUndefined, m_codeBlock->globalObject());
     454    addJump(branchTest32(NonZero, result), target);
    455455}
    456456
     
    835835    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_not);
    836836    slowPathCall.call();
    837 }
    838 
    839 void JIT::emitSlow_op_jfalse(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
    840 {
    841     linkSlowCase(iter);
    842     callOperation(operationConvertJSValueToBoolean, regT0);
    843     emitJumpSlowToHot(branchTest32(Zero, returnValueGPR), currentInstruction[2].u.operand); // inverted!
    844 }
    845 
    846 void JIT::emitSlow_op_jtrue(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
    847 {
    848     linkSlowCase(iter);
    849     callOperation(operationConvertJSValueToBoolean, regT0);
    850     emitJumpSlowToHot(branchTest32(NonZero, returnValueGPR), currentInstruction[2].u.operand);
    851837}
    852838
  • trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp

    r205462 r205675  
    476476    emitLoad(cond, regT1, regT0);
    477477
    478     ASSERT((JSValue::BooleanTag + 1 == JSValue::Int32Tag) && !(JSValue::Int32Tag + 1));
    479     addSlowCase(branch32(Below, regT1, TrustedImm32(JSValue::BooleanTag)));
    480     addJump(branchTest32(Zero, regT0), target);
    481 }
    482 
    483 void JIT::emitSlow_op_jfalse(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
     478    JSValueRegs value(regT1, regT0);
     479    GPRReg scratch = regT2;
     480    GPRReg result = regT3;
     481    bool shouldCheckMasqueradesAsUndefined = true;
     482    emitConvertValueToBoolean(value, result, scratch, fpRegT0, fpRegT1, shouldCheckMasqueradesAsUndefined, m_codeBlock->globalObject());
     483
     484    addJump(branchTest32(Zero, result), target);
     485}
     486
     487void JIT::emit_op_jtrue(Instruction* currentInstruction)
    484488{
    485489    int cond = currentInstruction[1].u.operand;
    486490    unsigned target = currentInstruction[2].u.operand;
    487491
    488     linkSlowCase(iter);
    489 
    490     if (supportsFloatingPoint()) {
    491         // regT1 contains the tag from the hot path.
    492         Jump notNumber = branch32(Above, regT1, TrustedImm32(JSValue::LowestTag));
    493 
    494         emitLoadDouble(cond, fpRegT0);
    495         emitJumpSlowToHot(branchDoubleZeroOrNaN(fpRegT0, fpRegT1), target);
    496         emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jfalse));
    497 
    498         notNumber.link(this);
    499     }
    500 
    501     callOperation(operationConvertJSValueToBoolean, regT1, regT0);
    502     emitJumpSlowToHot(branchTest32(Zero, returnValueGPR), target); // Inverted.
    503 }
    504 
    505 void JIT::emit_op_jtrue(Instruction* currentInstruction)
    506 {
    507     int cond = currentInstruction[1].u.operand;
    508     unsigned target = currentInstruction[2].u.operand;
    509 
    510492    emitLoad(cond, regT1, regT0);
    511 
    512     ASSERT((JSValue::BooleanTag + 1 == JSValue::Int32Tag) && !(JSValue::Int32Tag + 1));
    513     addSlowCase(branch32(Below, regT1, TrustedImm32(JSValue::BooleanTag)));
    514     addJump(branchTest32(NonZero, regT0), target);
    515 }
    516 
    517 void JIT::emitSlow_op_jtrue(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
    518 {
    519     int cond = currentInstruction[1].u.operand;
    520     unsigned target = currentInstruction[2].u.operand;
    521 
    522     linkSlowCase(iter);
    523 
    524     if (supportsFloatingPoint()) {
    525         // regT1 contains the tag from the hot path.
    526         Jump notNumber = branch32(Above, regT1, TrustedImm32(JSValue::LowestTag));
    527 
    528         emitLoadDouble(cond, fpRegT0);
    529         emitJumpSlowToHot(branchDoubleNonZero(fpRegT0, fpRegT1), target);
    530         emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jtrue));
    531 
    532         notNumber.link(this);
    533     }
    534 
    535     callOperation(operationConvertJSValueToBoolean, regT1, regT0);
    536     emitJumpSlowToHot(branchTest32(NonZero, returnValueGPR), target);
     493    bool shouldCheckMasqueradesAsUndefined = true;
     494    JSValueRegs value(regT1, regT0);
     495    GPRReg scratch = regT2;
     496    GPRReg result = regT3;
     497    emitConvertValueToBoolean(value, result, scratch, fpRegT0, fpRegT1, shouldCheckMasqueradesAsUndefined, m_codeBlock->globalObject());
     498
     499    addJump(branchTest32(NonZero, result), target);
    537500}
    538501
  • trunk/Source/JavaScriptCore/jit/JITOperations.cpp

    r205569 r205675  
    10341034
    10351035    return jsLessEq<false>(exec, JSValue::decode(encodedOp2), JSValue::decode(encodedOp1));
    1036 }
    1037 
    1038 size_t JIT_OPERATION operationConvertJSValueToBoolean(ExecState* exec, EncodedJSValue encodedOp)
    1039 {
    1040     VM* vm = &exec->vm();
    1041     NativeCallFrameTracer tracer(vm, exec);
    1042    
    1043     return JSValue::decode(encodedOp).toBoolean(exec);
    10441036}
    10451037
  • trunk/Source/JavaScriptCore/jit/JITOperations.h

    r205648 r205675  
    347347size_t JIT_OPERATION operationCompareGreater(ExecState*, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
    348348size_t JIT_OPERATION operationCompareGreaterEq(ExecState*, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
    349 size_t JIT_OPERATION operationConvertJSValueToBoolean(ExecState*, EncodedJSValue) WTF_INTERNAL;
    350349size_t JIT_OPERATION operationCompareEq(ExecState*, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
    351350#if USE(JSVALUE64)
Note: See TracChangeset for help on using the changeset viewer.