Changeset 95230 in webkit


Ignore:
Timestamp:
Sep 15, 2011 2:41:41 PM (13 years ago)
Author:
fpizlo@apple.com
Message:

All of the functionality in the non-speculative JIT should be
available to the speculative JIT via helper methods
https://bugs.webkit.org/show_bug.cgi?id=68186

Reviewed by Oliver Hunt.

Stole all of the goodness from NonSpeculativeJIT and placed it
in JITCodeGenerator. Left all of the badness (i.e. subtle code
duplication with SpeculativeJIT, etc). This is in preparation
for removing the NonSpeculativeJIT entirely, but having its
goodness available for reuse in the SpeculativeJIT if necessary.

  • dfg/DFGJITCodeGenerator.cpp:

(JSC::DFG::JITCodeGenerator::nonSpeculativeValueToNumber):
(JSC::DFG::JITCodeGenerator::nonSpeculativeValueToInt32):
(JSC::DFG::JITCodeGenerator::nonSpeculativeUInt32ToNumber):
(JSC::DFG::JITCodeGenerator::nonSpeculativeKnownConstantArithOp):
(JSC::DFG::JITCodeGenerator::nonSpeculativeBasicArithOp):
(JSC::DFG::JITCodeGenerator::nonSpeculativeArithMod):
(JSC::DFG::JITCodeGenerator::nonSpeculativeCheckHasInstance):
(JSC::DFG::JITCodeGenerator::nonSpeculativeInstanceOf):

  • dfg/DFGJITCodeGenerator.h:

(JSC::DFG::JITCodeGenerator::nonSpeculativeAdd):
(JSC::DFG::JITCodeGenerator::nonSpeculativeArithSub):

  • dfg/DFGNonSpeculativeJIT.cpp:

(JSC::DFG::NonSpeculativeJIT::compile):

  • dfg/DFGNonSpeculativeJIT.h:
Location:
trunk/Source/JavaScriptCore
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r95229 r95230  
     12011-09-15  Filip Pizlo  <fpizlo@apple.com>
     2
     3        All of the functionality in the non-speculative JIT should be
     4        available to the speculative JIT via helper methods
     5        https://bugs.webkit.org/show_bug.cgi?id=68186
     6
     7        Reviewed by Oliver Hunt.
     8       
     9        Stole all of the goodness from NonSpeculativeJIT and placed it
     10        in JITCodeGenerator.  Left all of the badness (i.e. subtle code
     11        duplication with SpeculativeJIT, etc).  This is in preparation
     12        for removing the NonSpeculativeJIT entirely, but having its
     13        goodness available for reuse in the SpeculativeJIT if necessary.
     14
     15        * dfg/DFGJITCodeGenerator.cpp:
     16        (JSC::DFG::JITCodeGenerator::nonSpeculativeValueToNumber):
     17        (JSC::DFG::JITCodeGenerator::nonSpeculativeValueToInt32):
     18        (JSC::DFG::JITCodeGenerator::nonSpeculativeUInt32ToNumber):
     19        (JSC::DFG::JITCodeGenerator::nonSpeculativeKnownConstantArithOp):
     20        (JSC::DFG::JITCodeGenerator::nonSpeculativeBasicArithOp):
     21        (JSC::DFG::JITCodeGenerator::nonSpeculativeArithMod):
     22        (JSC::DFG::JITCodeGenerator::nonSpeculativeCheckHasInstance):
     23        (JSC::DFG::JITCodeGenerator::nonSpeculativeInstanceOf):
     24        * dfg/DFGJITCodeGenerator.h:
     25        (JSC::DFG::JITCodeGenerator::nonSpeculativeAdd):
     26        (JSC::DFG::JITCodeGenerator::nonSpeculativeArithSub):
     27        * dfg/DFGNonSpeculativeJIT.cpp:
     28        (JSC::DFG::NonSpeculativeJIT::compile):
     29        * dfg/DFGNonSpeculativeJIT.h:
     30
    1312011-09-15  Sheriff Bot  <webkit.review.bot@gmail.com>
    232
  • trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.cpp

    r95170 r95230  
    3535namespace JSC { namespace DFG {
    3636
     37const double twoToThe32 = (double)0x100000000ull;
     38
    3739void JITCodeGenerator::clearGenerationInfo()
    3840{
     
    430432   
    431433    return info.isJSBoolean();
     434}
     435
     436void JITCodeGenerator::nonSpeculativeValueToNumber(Node& node)
     437{
     438    if (isKnownNumeric(node.child1())) {
     439        JSValueOperand op1(this, node.child1());
     440        GPRTemporary result(this, op1);
     441        m_jit.move(op1.gpr(), result.gpr());
     442        jsValueResult(result.gpr(), m_compileIndex);
     443        return;
     444    }
     445
     446    JSValueOperand op1(this, node.child1());
     447    GPRTemporary result(this);
     448   
     449    ASSERT(!isInt32Constant(node.child1()));
     450    ASSERT(!isNumberConstant(node.child1()));
     451   
     452    GPRReg jsValueGpr = op1.gpr();
     453    GPRReg gpr = result.gpr();
     454    op1.use();
     455
     456    JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
     457    JITCompiler::Jump nonNumeric = m_jit.branchTestPtr(MacroAssembler::Zero, jsValueGpr, GPRInfo::tagTypeNumberRegister);
     458
     459    // First, if we get here we have a double encoded as a JSValue
     460    m_jit.move(jsValueGpr, gpr);
     461    JITCompiler::Jump hasUnboxedDouble = m_jit.jump();
     462
     463    // Next handle cells (& other JS immediates)
     464    nonNumeric.link(&m_jit);
     465    silentSpillAllRegisters(gpr);
     466    m_jit.move(jsValueGpr, GPRInfo::argumentGPR1);
     467    m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
     468    appendCallWithExceptionCheck(dfgConvertJSValueToNumber);
     469    boxDouble(FPRInfo::returnValueFPR, gpr);
     470    silentFillAllRegisters(gpr);
     471    JITCompiler::Jump hasCalledToNumber = m_jit.jump();
     472   
     473    // Finally, handle integers.
     474    isInteger.link(&m_jit);
     475    m_jit.orPtr(GPRInfo::tagTypeNumberRegister, jsValueGpr, gpr);
     476    hasUnboxedDouble.link(&m_jit);
     477    hasCalledToNumber.link(&m_jit);
     478   
     479    jsValueResult(result.gpr(), m_compileIndex, UseChildrenCalledExplicitly);
     480}
     481
     482void JITCodeGenerator::nonSpeculativeValueToInt32(Node& node)
     483{
     484    ASSERT(!isInt32Constant(node.child1()));
     485   
     486    if (isKnownInteger(node.child1())) {
     487        IntegerOperand op1(this, node.child1());
     488        GPRTemporary result(this, op1);
     489        m_jit.move(op1.gpr(), result.gpr());
     490        integerResult(result.gpr(), m_compileIndex);
     491        return;
     492    }
     493   
     494    GenerationInfo& childInfo = m_generationInfo[m_jit.graph()[node.child1()].virtualRegister()];
     495    if (isJSDouble(childInfo.registerFormat())) {
     496        DoubleOperand op1(this, node.child1());
     497        GPRTemporary result(this);
     498        FPRReg fpr = op1.fpr();
     499        GPRReg gpr = result.gpr();
     500        op1.use();
     501        JITCompiler::Jump truncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateSuccessful);
     502       
     503        silentSpillAllRegisters(gpr);
     504       
     505        m_jit.moveDouble(fpr, FPRInfo::argumentFPR0);
     506        appendCallWithExceptionCheck(toInt32);
     507        m_jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, gpr);
     508       
     509        silentFillAllRegisters(gpr);
     510       
     511        truncatedToInteger.link(&m_jit);
     512        integerResult(gpr, m_compileIndex, UseChildrenCalledExplicitly);
     513        return;
     514    }
     515   
     516    JSValueOperand op1(this, node.child1());
     517    GPRTemporary result(this, op1);
     518    GPRReg jsValueGpr = op1.gpr();
     519    GPRReg resultGPR = result.gpr();
     520    op1.use();
     521
     522    JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
     523
     524    // First handle non-integers
     525    silentSpillAllRegisters(resultGPR);
     526    m_jit.move(jsValueGpr, GPRInfo::argumentGPR1);
     527    m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
     528    appendCallWithExceptionCheck(dfgConvertJSValueToInt32);
     529    m_jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, resultGPR);
     530    silentFillAllRegisters(resultGPR);
     531    JITCompiler::Jump hasCalledToInt32 = m_jit.jump();
     532
     533    // Then handle integers.
     534    isInteger.link(&m_jit);
     535    m_jit.zeroExtend32ToPtr(jsValueGpr, resultGPR);
     536    hasCalledToInt32.link(&m_jit);
     537    integerResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
     538}
     539
     540void JITCodeGenerator::nonSpeculativeUInt32ToNumber(Node& node)
     541{
     542    IntegerOperand op1(this, node.child1());
     543    FPRTemporary boxer(this);
     544    GPRTemporary result(this, op1);
     545   
     546    JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, op1.gpr(), TrustedImm32(0));
     547   
     548    m_jit.convertInt32ToDouble(op1.gpr(), boxer.fpr());
     549    m_jit.addDouble(JITCompiler::AbsoluteAddress(&twoToThe32), boxer.fpr());
     550   
     551    boxDouble(boxer.fpr(), result.gpr());
     552   
     553    JITCompiler::Jump done = m_jit.jump();
     554   
     555    positive.link(&m_jit);
     556   
     557    m_jit.orPtr(GPRInfo::tagTypeNumberRegister, op1.gpr(), result.gpr());
     558   
     559    done.link(&m_jit);
     560   
     561    jsValueResult(result.gpr(), m_compileIndex);
     562}
     563
     564void JITCodeGenerator::nonSpeculativeKnownConstantArithOp(NodeType op, NodeIndex regChild, NodeIndex immChild, bool commute)
     565{
     566    JSValueOperand regArg(this, regChild);
     567    GPRReg regArgGPR = regArg.gpr();
     568    GPRTemporary result(this);
     569    GPRReg resultGPR = result.gpr();
     570    FPRTemporary tmp1(this);
     571    FPRTemporary tmp2(this);
     572    FPRReg tmp1FPR = tmp1.fpr();
     573    FPRReg tmp2FPR = tmp2.fpr();
     574   
     575    regArg.use();
     576    use(immChild);
     577
     578    JITCompiler::Jump notInt;
     579   
     580    int32_t imm = valueOfInt32Constant(immChild);
     581       
     582    if (!isKnownInteger(regChild))
     583        notInt = m_jit.branchPtr(MacroAssembler::Below, regArgGPR, GPRInfo::tagTypeNumberRegister);
     584   
     585    JITCompiler::Jump overflow;
     586   
     587    switch (op) {
     588    case ValueAdd:
     589    case ArithAdd:
     590        overflow = m_jit.branchAdd32(MacroAssembler::Overflow, regArgGPR, Imm32(imm), resultGPR);
     591        break;
     592       
     593    case ArithSub:
     594        overflow = m_jit.branchSub32(MacroAssembler::Overflow, regArgGPR, Imm32(imm), resultGPR);
     595        break;
     596       
     597    default:
     598        ASSERT_NOT_REACHED();
     599    }
     600   
     601    m_jit.orPtr(GPRInfo::tagTypeNumberRegister, resultGPR);
     602       
     603    JITCompiler::Jump done = m_jit.jump();
     604   
     605    overflow.link(&m_jit);
     606   
     607    JITCompiler::Jump notNumber;
     608   
     609    // first deal with overflow case
     610    m_jit.convertInt32ToDouble(regArgGPR, tmp2FPR);
     611   
     612    // now deal with not-int case, if applicable
     613    if (!isKnownInteger(regChild)) {
     614        JITCompiler::Jump haveValue = m_jit.jump();
     615       
     616        notInt.link(&m_jit);
     617       
     618        if (!isKnownNumeric(regChild)) {
     619            ASSERT(op == ValueAdd);
     620            notNumber = m_jit.branchTestPtr(MacroAssembler::Zero, regArgGPR, GPRInfo::tagTypeNumberRegister);
     621        }
     622       
     623        m_jit.move(regArgGPR, resultGPR);
     624        m_jit.addPtr(GPRInfo::tagTypeNumberRegister, resultGPR);
     625        m_jit.movePtrToDouble(resultGPR, tmp2FPR);
     626       
     627        haveValue.link(&m_jit);
     628    }
     629   
     630    m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfNumberConstant(immChild)))), resultGPR);
     631    m_jit.movePtrToDouble(resultGPR, tmp1FPR);
     632    switch (op) {
     633    case ValueAdd:
     634    case ArithAdd:
     635        m_jit.addDouble(tmp1FPR, tmp2FPR);
     636        break;
     637       
     638    case ArithSub:
     639        m_jit.subDouble(tmp1FPR, tmp2FPR);
     640        break;
     641           
     642    default:
     643        ASSERT_NOT_REACHED();
     644    }
     645   
     646    JITCompiler::Jump doneCaseConvertedToInt;
     647   
     648    if (op == ValueAdd) {
     649        JITCompiler::JumpList failureCases;
     650        m_jit.branchConvertDoubleToInt32(tmp2FPR, resultGPR, failureCases, tmp1FPR);
     651        m_jit.orPtr(GPRInfo::tagTypeNumberRegister, resultGPR);
     652       
     653        doneCaseConvertedToInt = m_jit.jump();
     654       
     655        failureCases.link(&m_jit);
     656    }
     657   
     658    m_jit.moveDoubleToPtr(tmp2FPR, resultGPR);
     659    m_jit.subPtr(GPRInfo::tagTypeNumberRegister, resultGPR);
     660       
     661    if (!isKnownNumeric(regChild)) {
     662        ASSERT(notNumber.isSet());
     663        ASSERT(op == ValueAdd);
     664           
     665        JITCompiler::Jump doneCaseWasNumber = m_jit.jump();
     666           
     667        notNumber.link(&m_jit);
     668           
     669        silentSpillAllRegisters(resultGPR);
     670        if (commute) {
     671            m_jit.move(regArgGPR, GPRInfo::argumentGPR2);
     672            m_jit.move(MacroAssembler::ImmPtr(static_cast<const void*>(JSValue::encode(jsNumber(imm)))), GPRInfo::argumentGPR1);
     673        } else {
     674            m_jit.move(regArgGPR, GPRInfo::argumentGPR1);
     675            m_jit.move(MacroAssembler::ImmPtr(static_cast<const void*>(JSValue::encode(jsNumber(imm)))), GPRInfo::argumentGPR2);
     676        }
     677        m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
     678        appendCallWithExceptionCheck(operationValueAddNotNumber);
     679        m_jit.move(GPRInfo::returnValueGPR, resultGPR);
     680        silentFillAllRegisters(resultGPR);
     681           
     682        doneCaseWasNumber.link(&m_jit);
     683    }
     684   
     685    done.link(&m_jit);
     686    if (doneCaseConvertedToInt.isSet())
     687        doneCaseConvertedToInt.link(&m_jit);
     688       
     689    jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
     690}
     691
     692void JITCodeGenerator::nonSpeculativeBasicArithOp(NodeType op, Node &node)
     693{
     694    JSValueOperand arg1(this, node.child1());
     695    JSValueOperand arg2(this, node.child2());
     696   
     697    FPRTemporary tmp1(this);
     698    FPRTemporary tmp2(this);
     699    FPRReg tmp1FPR = tmp1.fpr();
     700    FPRReg tmp2FPR = tmp2.fpr();
     701   
     702    GPRTemporary result(this);
     703
     704    GPRReg arg1GPR = arg1.gpr();
     705    GPRReg arg2GPR = arg2.gpr();
     706   
     707    GPRReg resultGPR = result.gpr();
     708   
     709    arg1.use();
     710    arg2.use();
     711   
     712    JITCompiler::Jump child1NotInt;
     713    JITCompiler::Jump child2NotInt;
     714    JITCompiler::JumpList overflow;
     715   
     716    if (!isKnownInteger(node.child1()))
     717        child1NotInt = m_jit.branchPtr(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister);
     718    if (!isKnownInteger(node.child2()))
     719        child2NotInt = m_jit.branchPtr(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister);
     720   
     721    switch (op) {
     722    case ValueAdd:
     723    case ArithAdd: {
     724        overflow.append(m_jit.branchAdd32(MacroAssembler::Overflow, arg1GPR, arg2GPR, resultGPR));
     725        break;
     726    }
     727       
     728    case ArithSub: {
     729        overflow.append(m_jit.branchSub32(MacroAssembler::Overflow, arg1GPR, arg2GPR, resultGPR));
     730        break;
     731    }
     732       
     733    case ArithMul: {
     734        overflow.append(m_jit.branchMul32(MacroAssembler::Overflow, arg1GPR, arg2GPR, resultGPR));
     735        overflow.append(m_jit.branchTest32(MacroAssembler::Zero, resultGPR));
     736        break;
     737    }
     738       
     739    default:
     740        ASSERT_NOT_REACHED();
     741    }
     742   
     743    m_jit.orPtr(GPRInfo::tagTypeNumberRegister, resultGPR);
     744       
     745    JITCompiler::Jump done = m_jit.jump();
     746   
     747    JITCompiler::JumpList haveFPRArguments;
     748
     749    overflow.link(&m_jit);
     750       
     751    // both arguments are integers
     752    m_jit.convertInt32ToDouble(arg1GPR, tmp1FPR);
     753    m_jit.convertInt32ToDouble(arg2GPR, tmp2FPR);
     754       
     755    haveFPRArguments.append(m_jit.jump());
     756       
     757    JITCompiler::JumpList notNumbers;
     758       
     759    JITCompiler::Jump child2NotInt2;
     760       
     761    if (!isKnownInteger(node.child1())) {
     762        child1NotInt.link(&m_jit);
     763           
     764        if (!isKnownNumeric(node.child1())) {
     765            ASSERT(op == ValueAdd);
     766            notNumbers.append(m_jit.branchTestPtr(MacroAssembler::Zero, arg1GPR, GPRInfo::tagTypeNumberRegister));
     767        }
     768           
     769        m_jit.move(arg1GPR, resultGPR);
     770        unboxDouble(resultGPR, tmp1FPR);
     771           
     772        // child1 is converted to a double; child2 may either be an int or
     773        // a boxed double
     774           
     775        if (!isKnownInteger(node.child2())) {
     776            if (isKnownNumeric(node.child2()))
     777                child2NotInt2 = m_jit.branchPtr(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister);
     778            else {
     779                ASSERT(op == ValueAdd);
     780                JITCompiler::Jump child2IsInt = m_jit.branchPtr(MacroAssembler::AboveOrEqual, arg2GPR, GPRInfo::tagTypeNumberRegister);
     781                notNumbers.append(m_jit.branchTestPtr(MacroAssembler::Zero, arg2GPR, GPRInfo::tagTypeNumberRegister));
     782                child2NotInt2 = m_jit.jump();
     783                child2IsInt.link(&m_jit);
     784            }
     785        }
     786           
     787        // child 2 is definitely an integer
     788        m_jit.convertInt32ToDouble(arg2GPR, tmp2FPR);
     789           
     790        haveFPRArguments.append(m_jit.jump());
     791    }
     792       
     793    if (!isKnownInteger(node.child2())) {
     794        child2NotInt.link(&m_jit);
     795           
     796        if (!isKnownNumeric(node.child2())) {
     797            ASSERT(op == ValueAdd);
     798            notNumbers.append(m_jit.branchTestPtr(MacroAssembler::Zero, arg2GPR, GPRInfo::tagTypeNumberRegister));
     799        }
     800           
     801        // child1 is definitely an integer, and child 2 is definitely not
     802           
     803        m_jit.convertInt32ToDouble(arg1GPR, tmp1FPR);
     804           
     805        if (child2NotInt2.isSet())
     806            child2NotInt2.link(&m_jit);
     807           
     808        m_jit.move(arg2GPR, resultGPR);
     809        unboxDouble(resultGPR, tmp2FPR);
     810    }
     811       
     812    haveFPRArguments.link(&m_jit);
     813       
     814    switch (op) {
     815    case ValueAdd:
     816    case ArithAdd:
     817        m_jit.addDouble(tmp2FPR, tmp1FPR);
     818        break;
     819           
     820    case ArithSub:
     821        m_jit.subDouble(tmp2FPR, tmp1FPR);
     822        break;
     823           
     824    case ArithMul:
     825        m_jit.mulDouble(tmp2FPR, tmp1FPR);
     826        break;
     827           
     828    default:
     829        ASSERT_NOT_REACHED();
     830    }
     831   
     832    JITCompiler::Jump doneCaseConvertedToInt;
     833   
     834    if (op == ValueAdd) {
     835        JITCompiler::JumpList failureCases;
     836        m_jit.branchConvertDoubleToInt32(tmp1FPR, resultGPR, failureCases, tmp2FPR);
     837        m_jit.orPtr(GPRInfo::tagTypeNumberRegister, resultGPR);
     838       
     839        doneCaseConvertedToInt = m_jit.jump();
     840       
     841        failureCases.link(&m_jit);
     842    }
     843       
     844    boxDouble(tmp1FPR, resultGPR);
     845       
     846    if (!notNumbers.empty()) {
     847        ASSERT(op == ValueAdd);
     848           
     849        JITCompiler::Jump doneCaseWasNumber = m_jit.jump();
     850           
     851        notNumbers.link(&m_jit);
     852           
     853        silentSpillAllRegisters(resultGPR);
     854        setupStubArguments(arg1GPR, arg2GPR);
     855        m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
     856        appendCallWithExceptionCheck(operationValueAddNotNumber);
     857        m_jit.move(GPRInfo::returnValueGPR, resultGPR);
     858        silentFillAllRegisters(resultGPR);
     859
     860        doneCaseWasNumber.link(&m_jit);
     861    }
     862   
     863    done.link(&m_jit);
     864    if (doneCaseConvertedToInt.isSet())
     865        doneCaseConvertedToInt.link(&m_jit);
     866       
     867    jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
     868}
     869
     870void JITCodeGenerator::nonSpeculativeArithMod(Node& node)
     871{
     872    JSValueOperand op1(this, node.child1());
     873    JSValueOperand op2(this, node.child2());
     874    GPRTemporary eax(this, X86Registers::eax);
     875    GPRTemporary edx(this, X86Registers::edx);
     876
     877    FPRTemporary op1Double(this);
     878    FPRTemporary op2Double(this);
     879   
     880    GPRReg op1GPR = op1.gpr();
     881    GPRReg op2GPR = op2.gpr();
     882   
     883    FPRReg op1FPR = op1Double.fpr();
     884    FPRReg op2FPR = op2Double.fpr();
     885       
     886    op1.use();
     887    op2.use();
     888   
     889    GPRReg temp2 = InvalidGPRReg;
     890    GPRReg unboxGPR;
     891    if (op2GPR == X86Registers::eax || op2GPR == X86Registers::edx) {
     892        temp2 = allocate();
     893        m_jit.move(op2GPR, temp2);
     894        op2GPR = temp2;
     895        unboxGPR = temp2;
     896    } else if (op1GPR == X86Registers::eax)
     897        unboxGPR = X86Registers::edx;
     898    else
     899        unboxGPR = X86Registers::eax;
     900    ASSERT(unboxGPR != op1.gpr());
     901    ASSERT(unboxGPR != op2.gpr());
     902
     903    JITCompiler::Jump firstOpNotInt;
     904    JITCompiler::Jump secondOpNotInt;
     905    JITCompiler::JumpList done;
     906    JITCompiler::Jump modByZero;
     907   
     908    if (!isKnownInteger(node.child1()))
     909        firstOpNotInt = m_jit.branchPtr(MacroAssembler::Below, op1GPR, GPRInfo::tagTypeNumberRegister);
     910    if (!isKnownInteger(node.child2()))
     911        secondOpNotInt = m_jit.branchPtr(MacroAssembler::Below, op2GPR, GPRInfo::tagTypeNumberRegister);
     912   
     913    modByZero = m_jit.branchTest32(MacroAssembler::Zero, op2GPR);
     914   
     915    m_jit.move(op1GPR, eax.gpr());
     916    m_jit.assembler().cdq();
     917    m_jit.assembler().idivl_r(op2GPR);
     918   
     919    m_jit.orPtr(GPRInfo::tagTypeNumberRegister, X86Registers::edx);
     920   
     921    done.append(m_jit.jump());
     922       
     923    JITCompiler::Jump gotDoubleArgs;
     924   
     925    modByZero.link(&m_jit);
     926       
     927    m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsNumber(std::numeric_limits<double>::quiet_NaN()))), X86Registers::edx);
     928    done.append(m_jit.jump());
     929   
     930    if (!isKnownInteger(node.child1())) {
     931        firstOpNotInt.link(&m_jit);
     932       
     933        JITCompiler::Jump secondOpNotInt2;
     934       
     935        if (!isKnownInteger(node.child2()))
     936            secondOpNotInt2 = m_jit.branchPtr(MacroAssembler::Below, op2GPR, GPRInfo::tagTypeNumberRegister);
     937           
     938        // first op is a double, second op is an int.
     939        m_jit.convertInt32ToDouble(op2GPR, op2FPR);
     940
     941        if (!isKnownInteger(node.child2())) {
     942            JITCompiler::Jump gotSecondOp = m_jit.jump();
     943           
     944            secondOpNotInt2.link(&m_jit);
     945           
     946            // first op is a double, second op is a double.
     947            m_jit.move(op2GPR, unboxGPR);
     948            unboxDouble(unboxGPR, op2FPR);
     949           
     950            gotSecondOp.link(&m_jit);
     951        }
     952       
     953        m_jit.move(op1GPR, unboxGPR);
     954        unboxDouble(unboxGPR, op1FPR);
     955       
     956        gotDoubleArgs = m_jit.jump();
     957    }
     958   
     959    if (!isKnownInteger(node.child2())) {
     960        secondOpNotInt.link(&m_jit);
     961       
     962        // we know that the first op is an int, and the second is a double
     963        m_jit.convertInt32ToDouble(op1GPR, op1FPR);
     964        m_jit.move(op2GPR, unboxGPR);
     965        unboxDouble(unboxGPR, op2FPR);
     966    }
     967   
     968    if (!isKnownInteger(node.child1()))
     969        gotDoubleArgs.link(&m_jit);
     970   
     971    if (!isKnownInteger(node.child1()) || !isKnownInteger(node.child2())) {
     972        silentSpillAllRegisters(X86Registers::edx);
     973        setupTwoStubArgs<FPRInfo::argumentFPR0, FPRInfo::argumentFPR1>(op1FPR, op2FPR);
     974        m_jit.appendCall(fmod);
     975        boxDouble(FPRInfo::returnValueFPR, X86Registers::edx);
     976        silentFillAllRegisters(X86Registers::edx);
     977    }
     978       
     979    done.link(&m_jit);
     980   
     981    if (temp2 != InvalidGPRReg)
     982        unlock(temp2);
     983   
     984    jsValueResult(X86Registers::edx, m_compileIndex, UseChildrenCalledExplicitly);
     985}
     986
     987void JITCodeGenerator::nonSpeculativeCheckHasInstance(Node& node)
     988{
     989    JSValueOperand base(this, node.child1());
     990    GPRTemporary structure(this);
     991   
     992    GPRReg baseReg = base.gpr();
     993    GPRReg structureReg = structure.gpr();
     994   
     995    // Check that base is a cell.
     996    MacroAssembler::Jump baseNotCell = m_jit.branchTestPtr(MacroAssembler::NonZero, baseReg, GPRInfo::tagMaskRegister);
     997   
     998    // Check that base 'ImplementsHasInstance'.
     999    m_jit.loadPtr(MacroAssembler::Address(baseReg, JSCell::structureOffset()), structureReg);
     1000    MacroAssembler::Jump implementsHasInstance = m_jit.branchTest8(MacroAssembler::NonZero, MacroAssembler::Address(structureReg, Structure::typeInfoFlagsOffset()), MacroAssembler::TrustedImm32(ImplementsHasInstance));
     1001   
     1002    // At this point we always throw, so no need to preserve registers.
     1003    baseNotCell.link(&m_jit);
     1004    m_jit.move(baseReg, GPRInfo::argumentGPR1);
     1005    m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
     1006    // At some point we could optimize this to plant a direct jump, rather then checking
     1007    // for an exception (operationThrowHasInstanceError always throws). Probably not worth
     1008    // adding the extra interface to do this now, but we may also want this for op_throw.
     1009    appendCallWithExceptionCheck(operationThrowHasInstanceError);
     1010   
     1011    implementsHasInstance.link(&m_jit);
     1012    noResult(m_compileIndex);
     1013}
     1014
     1015void JITCodeGenerator::nonSpeculativeInstanceOf(Node& node)
     1016{
     1017    JSValueOperand value(this, node.child1());
     1018    JSValueOperand base(this, node.child2());
     1019    JSValueOperand prototype(this, node.child3());
     1020    GPRTemporary scratch(this, base);
     1021
     1022    GPRReg valueReg = value.gpr();
     1023    GPRReg baseReg = base.gpr();
     1024    GPRReg prototypeReg = prototype.gpr();
     1025    GPRReg scratchReg = scratch.gpr();
     1026       
     1027    value.use();
     1028    base.use();
     1029    prototype.use();
     1030
     1031    // Check that operands are cells (base is checked by CheckHasInstance, so we can just assert).
     1032    MacroAssembler::Jump valueNotCell = m_jit.branchTestPtr(MacroAssembler::NonZero, valueReg, GPRInfo::tagMaskRegister);
     1033    m_jit.jitAssertIsCell(baseReg);
     1034    MacroAssembler::Jump prototypeNotCell = m_jit.branchTestPtr(MacroAssembler::NonZero, prototypeReg, GPRInfo::tagMaskRegister);
     1035
     1036    // Check that baseVal 'ImplementsDefaultHasInstance'.
     1037    m_jit.loadPtr(MacroAssembler::Address(baseReg, JSCell::structureOffset()), scratchReg);
     1038    MacroAssembler::Jump notDefaultHasInstance = m_jit.branchTest8(MacroAssembler::Zero, MacroAssembler::Address(scratchReg, Structure::typeInfoFlagsOffset()), TrustedImm32(ImplementsDefaultHasInstance));
     1039
     1040    // Check that prototype is an object
     1041    m_jit.loadPtr(MacroAssembler::Address(prototypeReg, JSCell::structureOffset()), scratchReg);
     1042    MacroAssembler::Jump protoNotObject = m_jit.branchIfNotObject(scratchReg);
     1043
     1044    // Initialize scratchReg with the value being checked.
     1045    m_jit.move(valueReg, scratchReg);
     1046
     1047    // Walk up the prototype chain of the value (in scratchReg), comparing to prototypeReg.
     1048    MacroAssembler::Label loop(&m_jit);
     1049    m_jit.loadPtr(MacroAssembler::Address(scratchReg, JSCell::structureOffset()), scratchReg);
     1050    m_jit.loadPtr(MacroAssembler::Address(scratchReg, Structure::prototypeOffset()), scratchReg);
     1051    MacroAssembler::Jump isInstance = m_jit.branchPtr(MacroAssembler::Equal, scratchReg, prototypeReg);
     1052    m_jit.branchTestPtr(MacroAssembler::Zero, scratchReg, GPRInfo::tagMaskRegister).linkTo(loop, &m_jit);
     1053
     1054    // No match - result is false.
     1055    m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(false))), scratchReg);
     1056    MacroAssembler::Jump wasNotInstance = m_jit.jump();
     1057
     1058    // Link to here if any checks fail that require us to try calling out to an operation to help,
     1059    // e.g. for an API overridden HasInstance.
     1060    valueNotCell.link(&m_jit);
     1061    prototypeNotCell.link(&m_jit);
     1062    notDefaultHasInstance.link(&m_jit);
     1063    protoNotObject.link(&m_jit);
     1064
     1065    silentSpillAllRegisters(scratchReg);
     1066    setupStubArguments(valueReg, baseReg, prototypeReg);
     1067    m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
     1068    appendCallWithExceptionCheck(operationInstanceOf);
     1069    m_jit.move(GPRInfo::returnValueGPR, scratchReg);
     1070    silentFillAllRegisters(scratchReg);
     1071
     1072    MacroAssembler::Jump wasNotDefaultHasInstance = m_jit.jump();
     1073
     1074    isInstance.link(&m_jit);
     1075    m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(true))), scratchReg);
     1076
     1077    wasNotInstance.link(&m_jit);
     1078    wasNotDefaultHasInstance.link(&m_jit);
     1079    jsValueResult(scratchReg, m_compileIndex, UseChildrenCalledExplicitly);
    4321080}
    4331081
  • trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.h

    r95170 r95230  
    563563        return lastNode.op == Branch && lastNode.child1() == m_compileIndex ? lastNodeIndex : NoNode;
    564564    }
     565   
     566    void nonSpeculativeValueToNumber(Node&);
     567    void nonSpeculativeValueToInt32(Node&);
     568    void nonSpeculativeUInt32ToNumber(Node&);
     569
     570    void nonSpeculativeKnownConstantArithOp(NodeType op, NodeIndex regChild, NodeIndex immChild, bool commute);
     571    void nonSpeculativeBasicArithOp(NodeType op, Node&);
     572   
     573    // Handles both ValueAdd and ArithAdd.
     574    void nonSpeculativeAdd(NodeType op, Node& node)
     575    {
     576        if (isInt32Constant(node.child1())) {
     577            nonSpeculativeKnownConstantArithOp(op, node.child2(), node.child1(), true);
     578            return;
     579        }
     580       
     581        if (isInt32Constant(node.child2())) {
     582            nonSpeculativeKnownConstantArithOp(op, node.child1(), node.child2(), false);
     583            return;
     584        }
     585       
     586        nonSpeculativeBasicArithOp(op, node);
     587    }
     588   
     589    void nonSpeculativeArithSub(Node& node)
     590    {
     591        if (isInt32Constant(node.child2())) {
     592            nonSpeculativeKnownConstantArithOp(ArithSub, node.child1(), node.child2(), false);
     593            return;
     594        }
     595       
     596        nonSpeculativeBasicArithOp(ArithSub, node);
     597    }
     598   
     599    void nonSpeculativeArithMod(Node&);
     600    void nonSpeculativeCheckHasInstance(Node&);
     601    void nonSpeculativeInstanceOf(Node&);
    565602
    566603    JITCompiler::Call cachedGetById(GPRReg baseGPR, GPRReg resultGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget = JITCompiler::Jump(), NodeType = GetById);
  • trunk/Source/JavaScriptCore/dfg/DFGNonSpeculativeJIT.cpp

    r95147 r95230  
    3333namespace JSC { namespace DFG {
    3434
    35 const double twoToThe32 = (double)0x100000000ull;
    36 
    3735EntryLocation::EntryLocation(MacroAssembler::Label entry, NonSpeculativeJIT* jit)
    3836    : m_entry(entry)
     
    6159}
    6260
    63 void NonSpeculativeJIT::valueToNumber(JSValueOperand& operand, GPRReg gpr)
    64 {
    65     GPRReg jsValueGpr = operand.gpr();
    66     operand.use();
    67 
    68     JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
    69     JITCompiler::Jump nonNumeric = m_jit.branchTestPtr(MacroAssembler::Zero, jsValueGpr, GPRInfo::tagTypeNumberRegister);
    70 
    71     // First, if we get here we have a double encoded as a JSValue
    72     m_jit.move(jsValueGpr, gpr);
    73     JITCompiler::Jump hasUnboxedDouble = m_jit.jump();
    74 
    75     // Next handle cells (& other JS immediates)
    76     nonNumeric.link(&m_jit);
    77     silentSpillAllRegisters(gpr);
    78     m_jit.move(jsValueGpr, GPRInfo::argumentGPR1);
    79     m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
    80     appendCallWithExceptionCheck(dfgConvertJSValueToNumber);
    81     boxDouble(FPRInfo::returnValueFPR, gpr);
    82     silentFillAllRegisters(gpr);
    83     JITCompiler::Jump hasCalledToNumber = m_jit.jump();
    84    
    85     // Finally, handle integers.
    86     isInteger.link(&m_jit);
    87     m_jit.orPtr(GPRInfo::tagTypeNumberRegister, jsValueGpr, gpr);
    88     hasUnboxedDouble.link(&m_jit);
    89     hasCalledToNumber.link(&m_jit);
    90 }
    91 
    92 void NonSpeculativeJIT::valueToInt32(JSValueOperand& operand, GPRReg result)
    93 {
    94     GPRReg jsValueGpr = operand.gpr();
    95     operand.use();
    96 
    97     JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
    98 
    99     // First handle non-integers
    100     silentSpillAllRegisters(result);
    101     m_jit.move(jsValueGpr, GPRInfo::argumentGPR1);
    102     m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
    103     appendCallWithExceptionCheck(dfgConvertJSValueToInt32);
    104     m_jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, result);
    105     silentFillAllRegisters(result);
    106     JITCompiler::Jump hasCalledToInt32 = m_jit.jump();
    107 
    108     // Then handle integers.
    109     isInteger.link(&m_jit);
    110     m_jit.zeroExtend32ToPtr(jsValueGpr, result);
    111     hasCalledToInt32.link(&m_jit);
    112 }
    113 
    114 void NonSpeculativeJIT::numberToInt32(FPRReg fpr, GPRReg gpr)
    115 {
    116     JITCompiler::Jump truncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateSuccessful);
    117 
    118     silentSpillAllRegisters(gpr);
    119 
    120     m_jit.moveDouble(fpr, FPRInfo::argumentFPR0);
    121     appendCallWithExceptionCheck(toInt32);
    122     m_jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, gpr);
    123 
    124     silentFillAllRegisters(gpr);
    125 
    126     truncatedToInteger.link(&m_jit);
    127 }
    128 
    129 void NonSpeculativeJIT::knownConstantArithOp(NodeType op, NodeIndex regChild, NodeIndex immChild, bool commute)
    130 {
    131     JSValueOperand regArg(this, regChild);
    132     GPRReg regArgGPR = regArg.gpr();
    133     GPRTemporary result(this);
    134     GPRReg resultGPR = result.gpr();
    135     FPRTemporary tmp1(this);
    136     FPRTemporary tmp2(this);
    137     FPRReg tmp1FPR = tmp1.fpr();
    138     FPRReg tmp2FPR = tmp2.fpr();
    139    
    140     regArg.use();
    141     use(immChild);
    142 
    143     JITCompiler::Jump notInt;
    144    
    145     int32_t imm = valueOfInt32Constant(immChild);
    146        
    147     if (!isKnownInteger(regChild))
    148         notInt = m_jit.branchPtr(MacroAssembler::Below, regArgGPR, GPRInfo::tagTypeNumberRegister);
    149    
    150     JITCompiler::Jump overflow;
    151    
    152     switch (op) {
    153     case ValueAdd:
    154     case ArithAdd:
    155         overflow = m_jit.branchAdd32(MacroAssembler::Overflow, regArgGPR, Imm32(imm), resultGPR);
    156         break;
    157        
    158     case ArithSub:
    159         overflow = m_jit.branchSub32(MacroAssembler::Overflow, regArgGPR, Imm32(imm), resultGPR);
    160         break;
    161        
    162     default:
    163         ASSERT_NOT_REACHED();
    164     }
    165    
    166     m_jit.orPtr(GPRInfo::tagTypeNumberRegister, resultGPR);
    167        
    168     JITCompiler::Jump done = m_jit.jump();
    169    
    170     overflow.link(&m_jit);
    171    
    172     JITCompiler::Jump notNumber;
    173    
    174     // first deal with overflow case
    175     m_jit.convertInt32ToDouble(regArgGPR, tmp2FPR);
    176    
    177     // now deal with not-int case, if applicable
    178     if (!isKnownInteger(regChild)) {
    179         JITCompiler::Jump haveValue = m_jit.jump();
    180        
    181         notInt.link(&m_jit);
    182        
    183         if (!isKnownNumeric(regChild)) {
    184             ASSERT(op == ValueAdd);
    185             notNumber = m_jit.branchTestPtr(MacroAssembler::Zero, regArgGPR, GPRInfo::tagTypeNumberRegister);
    186         }
    187        
    188         m_jit.move(regArgGPR, resultGPR);
    189         m_jit.addPtr(GPRInfo::tagTypeNumberRegister, resultGPR);
    190         m_jit.movePtrToDouble(resultGPR, tmp2FPR);
    191        
    192         haveValue.link(&m_jit);
    193     }
    194    
    195     m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfNumberConstant(immChild)))), resultGPR);
    196     m_jit.movePtrToDouble(resultGPR, tmp1FPR);
    197     switch (op) {
    198     case ValueAdd:
    199     case ArithAdd:
    200         m_jit.addDouble(tmp1FPR, tmp2FPR);
    201         break;
    202        
    203     case ArithSub:
    204         m_jit.subDouble(tmp1FPR, tmp2FPR);
    205         break;
    206            
    207     default:
    208         ASSERT_NOT_REACHED();
    209     }
    210    
    211     JITCompiler::Jump doneCaseConvertedToInt;
    212    
    213     if (op == ValueAdd) {
    214         JITCompiler::JumpList failureCases;
    215         m_jit.branchConvertDoubleToInt32(tmp2FPR, resultGPR, failureCases, tmp1FPR);
    216         m_jit.orPtr(GPRInfo::tagTypeNumberRegister, resultGPR);
    217        
    218         doneCaseConvertedToInt = m_jit.jump();
    219        
    220         failureCases.link(&m_jit);
    221     }
    222    
    223     m_jit.moveDoubleToPtr(tmp2FPR, resultGPR);
    224     m_jit.subPtr(GPRInfo::tagTypeNumberRegister, resultGPR);
    225        
    226     if (!isKnownNumeric(regChild)) {
    227         ASSERT(notNumber.isSet());
    228         ASSERT(op == ValueAdd);
    229            
    230         JITCompiler::Jump doneCaseWasNumber = m_jit.jump();
    231            
    232         notNumber.link(&m_jit);
    233            
    234         silentSpillAllRegisters(resultGPR);
    235         if (commute) {
    236             m_jit.move(regArgGPR, GPRInfo::argumentGPR2);
    237             m_jit.move(MacroAssembler::ImmPtr(static_cast<const void*>(JSValue::encode(jsNumber(imm)))), GPRInfo::argumentGPR1);
    238         } else {
    239             m_jit.move(regArgGPR, GPRInfo::argumentGPR1);
    240             m_jit.move(MacroAssembler::ImmPtr(static_cast<const void*>(JSValue::encode(jsNumber(imm)))), GPRInfo::argumentGPR2);
    241         }
    242         m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
    243         appendCallWithExceptionCheck(operationValueAddNotNumber);
    244         m_jit.move(GPRInfo::returnValueGPR, resultGPR);
    245         silentFillAllRegisters(resultGPR);
    246            
    247         doneCaseWasNumber.link(&m_jit);
    248     }
    249    
    250     done.link(&m_jit);
    251     if (doneCaseConvertedToInt.isSet())
    252         doneCaseConvertedToInt.link(&m_jit);
    253        
    254     jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
    255 }
    256 
    257 void NonSpeculativeJIT::basicArithOp(NodeType op, Node &node)
    258 {
    259     JSValueOperand arg1(this, node.child1());
    260     JSValueOperand arg2(this, node.child2());
    261    
    262     FPRTemporary tmp1(this);
    263     FPRTemporary tmp2(this);
    264     FPRReg tmp1FPR = tmp1.fpr();
    265     FPRReg tmp2FPR = tmp2.fpr();
    266    
    267     GPRTemporary result(this);
    268 
    269     GPRReg arg1GPR = arg1.gpr();
    270     GPRReg arg2GPR = arg2.gpr();
    271    
    272     GPRReg resultGPR = result.gpr();
    273    
    274     arg1.use();
    275     arg2.use();
    276    
    277     JITCompiler::Jump child1NotInt;
    278     JITCompiler::Jump child2NotInt;
    279     JITCompiler::JumpList overflow;
    280    
    281     if (!isKnownInteger(node.child1()))
    282         child1NotInt = m_jit.branchPtr(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister);
    283     if (!isKnownInteger(node.child2()))
    284         child2NotInt = m_jit.branchPtr(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister);
    285    
    286     switch (op) {
    287     case ValueAdd:
    288     case ArithAdd: {
    289         overflow.append(m_jit.branchAdd32(MacroAssembler::Overflow, arg1GPR, arg2GPR, resultGPR));
    290         break;
    291     }
    292        
    293     case ArithSub: {
    294         overflow.append(m_jit.branchSub32(MacroAssembler::Overflow, arg1GPR, arg2GPR, resultGPR));
    295         break;
    296     }
    297        
    298     case ArithMul: {
    299         overflow.append(m_jit.branchMul32(MacroAssembler::Overflow, arg1GPR, arg2GPR, resultGPR));
    300         overflow.append(m_jit.branchTest32(MacroAssembler::Zero, resultGPR));
    301         break;
    302     }
    303        
    304     default:
    305         ASSERT_NOT_REACHED();
    306     }
    307    
    308     m_jit.orPtr(GPRInfo::tagTypeNumberRegister, resultGPR);
    309        
    310     JITCompiler::Jump done = m_jit.jump();
    311    
    312     JITCompiler::JumpList haveFPRArguments;
    313 
    314     overflow.link(&m_jit);
    315        
    316     // both arguments are integers
    317     m_jit.convertInt32ToDouble(arg1GPR, tmp1FPR);
    318     m_jit.convertInt32ToDouble(arg2GPR, tmp2FPR);
    319        
    320     haveFPRArguments.append(m_jit.jump());
    321        
    322     JITCompiler::JumpList notNumbers;
    323        
    324     JITCompiler::Jump child2NotInt2;
    325        
    326     if (!isKnownInteger(node.child1())) {
    327         child1NotInt.link(&m_jit);
    328            
    329         if (!isKnownNumeric(node.child1())) {
    330             ASSERT(op == ValueAdd);
    331             notNumbers.append(m_jit.branchTestPtr(MacroAssembler::Zero, arg1GPR, GPRInfo::tagTypeNumberRegister));
    332         }
    333            
    334         m_jit.move(arg1GPR, resultGPR);
    335         unboxDouble(resultGPR, tmp1FPR);
    336            
    337         // child1 is converted to a double; child2 may either be an int or
    338         // a boxed double
    339            
    340         if (!isKnownInteger(node.child2())) {
    341             if (isKnownNumeric(node.child2()))
    342                 child2NotInt2 = m_jit.branchPtr(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister);
    343             else {
    344                 ASSERT(op == ValueAdd);
    345                 JITCompiler::Jump child2IsInt = m_jit.branchPtr(MacroAssembler::AboveOrEqual, arg2GPR, GPRInfo::tagTypeNumberRegister);
    346                 notNumbers.append(m_jit.branchTestPtr(MacroAssembler::Zero, arg2GPR, GPRInfo::tagTypeNumberRegister));
    347                 child2NotInt2 = m_jit.jump();
    348                 child2IsInt.link(&m_jit);
    349             }
    350         }
    351            
    352         // child 2 is definitely an integer
    353         m_jit.convertInt32ToDouble(arg2GPR, tmp2FPR);
    354            
    355         haveFPRArguments.append(m_jit.jump());
    356     }
    357        
    358     if (!isKnownInteger(node.child2())) {
    359         child2NotInt.link(&m_jit);
    360            
    361         if (!isKnownNumeric(node.child2())) {
    362             ASSERT(op == ValueAdd);
    363             notNumbers.append(m_jit.branchTestPtr(MacroAssembler::Zero, arg2GPR, GPRInfo::tagTypeNumberRegister));
    364         }
    365            
    366         // child1 is definitely an integer, and child 2 is definitely not
    367            
    368         m_jit.convertInt32ToDouble(arg1GPR, tmp1FPR);
    369            
    370         if (child2NotInt2.isSet())
    371             child2NotInt2.link(&m_jit);
    372            
    373         m_jit.move(arg2GPR, resultGPR);
    374         unboxDouble(resultGPR, tmp2FPR);
    375     }
    376        
    377     haveFPRArguments.link(&m_jit);
    378        
    379     switch (op) {
    380     case ValueAdd:
    381     case ArithAdd:
    382         m_jit.addDouble(tmp2FPR, tmp1FPR);
    383         break;
    384            
    385     case ArithSub:
    386         m_jit.subDouble(tmp2FPR, tmp1FPR);
    387         break;
    388            
    389     case ArithMul:
    390         m_jit.mulDouble(tmp2FPR, tmp1FPR);
    391         break;
    392            
    393     default:
    394         ASSERT_NOT_REACHED();
    395     }
    396    
    397     JITCompiler::Jump doneCaseConvertedToInt;
    398    
    399     if (op == ValueAdd) {
    400         JITCompiler::JumpList failureCases;
    401         m_jit.branchConvertDoubleToInt32(tmp1FPR, resultGPR, failureCases, tmp2FPR);
    402         m_jit.orPtr(GPRInfo::tagTypeNumberRegister, resultGPR);
    403        
    404         doneCaseConvertedToInt = m_jit.jump();
    405        
    406         failureCases.link(&m_jit);
    407     }
    408        
    409     boxDouble(tmp1FPR, resultGPR);
    410        
    411     if (!notNumbers.empty()) {
    412         ASSERT(op == ValueAdd);
    413            
    414         JITCompiler::Jump doneCaseWasNumber = m_jit.jump();
    415            
    416         notNumbers.link(&m_jit);
    417            
    418         silentSpillAllRegisters(resultGPR);
    419         setupStubArguments(arg1GPR, arg2GPR);
    420         m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
    421         appendCallWithExceptionCheck(operationValueAddNotNumber);
    422         m_jit.move(GPRInfo::returnValueGPR, resultGPR);
    423         silentFillAllRegisters(resultGPR);
    424 
    425         doneCaseWasNumber.link(&m_jit);
    426     }
    427    
    428     done.link(&m_jit);
    429     if (doneCaseConvertedToInt.isSet())
    430         doneCaseConvertedToInt.link(&m_jit);
    431        
    432     jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
    433 }
    434 
    43561void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator, Node& node)
    43662{
     
    543169
    544170    case UInt32ToNumber: {
    545         IntegerOperand op1(this, node.child1());
    546         FPRTemporary boxer(this);
    547         GPRTemporary result(this, op1);
    548        
    549         JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, op1.gpr(), TrustedImm32(0));
    550        
    551         m_jit.convertInt32ToDouble(op1.gpr(), boxer.fpr());
    552         m_jit.addDouble(JITCompiler::AbsoluteAddress(&twoToThe32), boxer.fpr());
    553        
    554         boxDouble(boxer.fpr(), result.gpr());
    555        
    556         JITCompiler::Jump done = m_jit.jump();
    557        
    558         positive.link(&m_jit);
    559        
    560         m_jit.orPtr(GPRInfo::tagTypeNumberRegister, op1.gpr(), result.gpr());
    561        
    562         done.link(&m_jit);
    563 
    564         jsValueResult(result.gpr(), m_compileIndex);
     171        nonSpeculativeUInt32ToNumber(node);
    565172        break;
    566173    }
    567174
    568175    case ValueToInt32: {
    569         ASSERT(!isInt32Constant(node.child1()));
    570 
    571         if (isKnownInteger(node.child1())) {
    572             IntegerOperand op1(this, node.child1());
    573             GPRTemporary result(this, op1);
    574             m_jit.move(op1.gpr(), result.gpr());
    575             integerResult(result.gpr(), m_compileIndex);
    576             break;
    577         }
    578 
    579         GenerationInfo& childInfo = m_generationInfo[m_jit.graph()[node.child1()].virtualRegister()];
    580         if (isJSDouble(childInfo.registerFormat())) {
    581             DoubleOperand op1(this, node.child1());
    582             GPRTemporary result(this);
    583             FPRReg fpr = op1.fpr();
    584             GPRReg gpr = result.gpr();
    585             op1.use();
    586             numberToInt32(fpr, gpr);
    587             integerResult(gpr, m_compileIndex, UseChildrenCalledExplicitly);
    588             break;
    589         }
    590 
    591         JSValueOperand op1(this, node.child1());
    592         GPRTemporary result(this, op1);
    593         valueToInt32(op1, result.gpr());
    594         integerResult(result.gpr(), m_compileIndex, UseChildrenCalledExplicitly);
     176        nonSpeculativeValueToInt32(node);
    595177        break;
    596178    }
     
    598180    case ValueToNumber:
    599181    case ValueToDouble: {
    600         ASSERT(!isInt32Constant(node.child1()));
    601         ASSERT(!isNumberConstant(node.child1()));
    602 
    603         if (isKnownNumeric(node.child1())) {
    604             JSValueOperand op1(this, node.child1());
    605             GPRTemporary result(this, op1);
    606             m_jit.move(op1.gpr(), result.gpr());
    607             jsValueResult(result.gpr(), m_compileIndex);
    608             break;
    609         }
    610 
    611         JSValueOperand op1(this, node.child1());
    612         GPRTemporary result(this);
    613         valueToNumber(op1, result.gpr());
    614         jsValueResult(result.gpr(), m_compileIndex, UseChildrenCalledExplicitly);
     182        nonSpeculativeValueToNumber(node);
    615183        break;
    616184    }
     
    618186    case ValueAdd:
    619187    case ArithAdd: {
    620         if (isInt32Constant(node.child1())) {
    621             knownConstantArithOp(op, node.child2(), node.child1(), true);
    622             break;
    623         }
    624        
    625         if (isInt32Constant(node.child2())) {
    626             knownConstantArithOp(op, node.child1(), node.child2(), false);
    627             break;
    628         }
    629        
    630         basicArithOp(op, node);
     188        nonSpeculativeAdd(op, node);
    631189        break;
    632190    }
    633191       
    634192    case ArithSub: {
    635         if (isInt32Constant(node.child2())) {
    636             knownConstantArithOp(ArithSub, node.child1(), node.child2(), false);
    637             break;
    638         }
    639        
    640         basicArithOp(ArithSub, node);
     193        nonSpeculativeArithSub(node);
    641194        break;
    642195    }
    643196
    644197    case ArithMul: {
    645         basicArithOp(ArithMul, node);
     198        nonSpeculativeBasicArithOp(ArithMul, node);
    646199        break;
    647200    }
     
    662215
    663216    case ArithMod: {
    664         JSValueOperand op1(this, node.child1());
    665         JSValueOperand op2(this, node.child2());
    666         GPRTemporary eax(this, X86Registers::eax);
    667         GPRTemporary edx(this, X86Registers::edx);
    668 
    669         FPRTemporary op1Double(this);
    670         FPRTemporary op2Double(this);
    671    
    672         GPRReg op1GPR = op1.gpr();
    673         GPRReg op2GPR = op2.gpr();
    674    
    675         FPRReg op1FPR = op1Double.fpr();
    676         FPRReg op2FPR = op2Double.fpr();
    677        
    678         op1.use();
    679         op2.use();
    680    
    681         GPRReg temp2 = InvalidGPRReg;
    682         GPRReg unboxGPR;
    683         if (op2GPR == X86Registers::eax || op2GPR == X86Registers::edx) {
    684             temp2 = allocate();
    685             m_jit.move(op2GPR, temp2);
    686             op2GPR = temp2;
    687             unboxGPR = temp2;
    688         } else if (op1GPR == X86Registers::eax)
    689             unboxGPR = X86Registers::edx;
    690         else
    691             unboxGPR = X86Registers::eax;
    692         ASSERT(unboxGPR != op1.gpr());
    693         ASSERT(unboxGPR != op2.gpr());
    694 
    695         JITCompiler::Jump firstOpNotInt;
    696         JITCompiler::Jump secondOpNotInt;
    697         JITCompiler::JumpList done;
    698         JITCompiler::Jump modByZero;
    699    
    700         if (!isKnownInteger(node.child1()))
    701             firstOpNotInt = m_jit.branchPtr(MacroAssembler::Below, op1GPR, GPRInfo::tagTypeNumberRegister);
    702         if (!isKnownInteger(node.child2()))
    703             secondOpNotInt = m_jit.branchPtr(MacroAssembler::Below, op2GPR, GPRInfo::tagTypeNumberRegister);
    704    
    705         modByZero = m_jit.branchTest32(MacroAssembler::Zero, op2GPR);
    706    
    707         m_jit.move(op1GPR, eax.gpr());
    708         m_jit.assembler().cdq();
    709         m_jit.assembler().idivl_r(op2GPR);
    710    
    711         m_jit.orPtr(GPRInfo::tagTypeNumberRegister, X86Registers::edx);
    712    
    713         done.append(m_jit.jump());
    714        
    715         JITCompiler::Jump gotDoubleArgs;
    716    
    717         modByZero.link(&m_jit);
    718        
    719         m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsNumber(std::numeric_limits<double>::quiet_NaN()))), X86Registers::edx);
    720         done.append(m_jit.jump());
    721    
    722         if (!isKnownInteger(node.child1())) {
    723             firstOpNotInt.link(&m_jit);
    724        
    725             JITCompiler::Jump secondOpNotInt2;
    726        
    727             if (!isKnownInteger(node.child2()))
    728                 secondOpNotInt2 = m_jit.branchPtr(MacroAssembler::Below, op2GPR, GPRInfo::tagTypeNumberRegister);
    729            
    730             // first op is a double, second op is an int.
    731             m_jit.convertInt32ToDouble(op2GPR, op2FPR);
    732 
    733             if (!isKnownInteger(node.child2())) {
    734                 JITCompiler::Jump gotSecondOp = m_jit.jump();
    735            
    736                 secondOpNotInt2.link(&m_jit);
    737            
    738                 // first op is a double, second op is a double.
    739                 m_jit.move(op2GPR, unboxGPR);
    740                 unboxDouble(unboxGPR, op2FPR);
    741            
    742                 gotSecondOp.link(&m_jit);
    743             }
    744        
    745             m_jit.move(op1GPR, unboxGPR);
    746             unboxDouble(unboxGPR, op1FPR);
    747        
    748             gotDoubleArgs = m_jit.jump();
    749         }
    750    
    751         if (!isKnownInteger(node.child2())) {
    752             secondOpNotInt.link(&m_jit);
    753        
    754             // we know that the first op is an int, and the second is a double
    755             m_jit.convertInt32ToDouble(op1GPR, op1FPR);
    756             m_jit.move(op2GPR, unboxGPR);
    757             unboxDouble(unboxGPR, op2FPR);
    758         }
    759    
    760         if (!isKnownInteger(node.child1()))
    761             gotDoubleArgs.link(&m_jit);
    762    
    763         if (!isKnownInteger(node.child1()) || !isKnownInteger(node.child2())) {
    764             silentSpillAllRegisters(X86Registers::edx);
    765             setupTwoStubArgs<FPRInfo::argumentFPR0, FPRInfo::argumentFPR1>(op1FPR, op2FPR);
    766             m_jit.appendCall(fmod);
    767             boxDouble(FPRInfo::returnValueFPR, X86Registers::edx);
    768             silentFillAllRegisters(X86Registers::edx);
    769         }
    770        
    771         done.link(&m_jit);
    772    
    773         if (temp2 != InvalidGPRReg)
    774             unlock(temp2);
    775    
    776         jsValueResult(X86Registers::edx, m_compileIndex, UseChildrenCalledExplicitly);
     217        nonSpeculativeArithMod(node);
    777218        break;
    778219    }
     
    1092533
    1093534    case CheckHasInstance: {
    1094         JSValueOperand base(this, node.child1());
    1095         GPRTemporary structure(this);
    1096 
    1097         GPRReg baseReg = base.gpr();
    1098         GPRReg structureReg = structure.gpr();
    1099 
    1100         // Check that base is a cell.
    1101         MacroAssembler::Jump baseNotCell = m_jit.branchTestPtr(MacroAssembler::NonZero, baseReg, GPRInfo::tagMaskRegister);
    1102 
    1103         // Check that base 'ImplementsHasInstance'.
    1104         m_jit.loadPtr(MacroAssembler::Address(baseReg, JSCell::structureOffset()), structureReg);
    1105         MacroAssembler::Jump implementsHasInstance = m_jit.branchTest8(MacroAssembler::NonZero, MacroAssembler::Address(structureReg, Structure::typeInfoFlagsOffset()), MacroAssembler::TrustedImm32(ImplementsHasInstance));
    1106 
    1107         // At this point we always throw, so no need to preserve registers.
    1108         baseNotCell.link(&m_jit);
    1109         m_jit.move(baseReg, GPRInfo::argumentGPR1);
    1110         m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
    1111         // At some point we could optimize this to plant a direct jump, rather then checking
    1112         // for an exception (operationThrowHasInstanceError always throws). Probably not worth
    1113         // adding the extra interface to do this now, but we may also want this for op_throw.
    1114         appendCallWithExceptionCheck(operationThrowHasInstanceError);
    1115 
    1116         implementsHasInstance.link(&m_jit);
    1117         noResult(m_compileIndex);
     535        nonSpeculativeCheckHasInstance(node);
    1118536        break;
    1119537    }
    1120538
    1121539    case InstanceOf: {
    1122         JSValueOperand value(this, node.child1());
    1123         JSValueOperand base(this, node.child2());
    1124         JSValueOperand prototype(this, node.child3());
    1125         GPRTemporary scratch(this, base);
    1126 
    1127         GPRReg valueReg = value.gpr();
    1128         GPRReg baseReg = base.gpr();
    1129         GPRReg prototypeReg = prototype.gpr();
    1130         GPRReg scratchReg = scratch.gpr();
    1131        
    1132         value.use();
    1133         base.use();
    1134         prototype.use();
    1135 
    1136         // Check that operands are cells (base is checked by CheckHasInstance, so we can just assert).
    1137         MacroAssembler::Jump valueNotCell = m_jit.branchTestPtr(MacroAssembler::NonZero, valueReg, GPRInfo::tagMaskRegister);
    1138         m_jit.jitAssertIsCell(baseReg);
    1139         MacroAssembler::Jump prototypeNotCell = m_jit.branchTestPtr(MacroAssembler::NonZero, prototypeReg, GPRInfo::tagMaskRegister);
    1140 
    1141         // Check that baseVal 'ImplementsDefaultHasInstance'.
    1142         m_jit.loadPtr(MacroAssembler::Address(baseReg, JSCell::structureOffset()), scratchReg);
    1143         MacroAssembler::Jump notDefaultHasInstance = m_jit.branchTest8(MacroAssembler::Zero, MacroAssembler::Address(scratchReg, Structure::typeInfoFlagsOffset()), TrustedImm32(ImplementsDefaultHasInstance));
    1144 
    1145         // Check that prototype is an object
    1146         m_jit.loadPtr(MacroAssembler::Address(prototypeReg, JSCell::structureOffset()), scratchReg);
    1147         MacroAssembler::Jump protoNotObject = m_jit.branchIfNotObject(scratchReg);
    1148 
    1149         // Initialize scratchReg with the value being checked.
    1150         m_jit.move(valueReg, scratchReg);
    1151 
    1152         // Walk up the prototype chain of the value (in scratchReg), comparing to prototypeReg.
    1153         MacroAssembler::Label loop(&m_jit);
    1154         m_jit.loadPtr(MacroAssembler::Address(scratchReg, JSCell::structureOffset()), scratchReg);
    1155         m_jit.loadPtr(MacroAssembler::Address(scratchReg, Structure::prototypeOffset()), scratchReg);
    1156         MacroAssembler::Jump isInstance = m_jit.branchPtr(MacroAssembler::Equal, scratchReg, prototypeReg);
    1157         m_jit.branchTestPtr(MacroAssembler::Zero, scratchReg, GPRInfo::tagMaskRegister).linkTo(loop, &m_jit);
    1158 
    1159         // No match - result is false.
    1160         m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(false))), scratchReg);
    1161         MacroAssembler::Jump wasNotInstance = m_jit.jump();
    1162 
    1163         // Link to here if any checks fail that require us to try calling out to an operation to help,
    1164         // e.g. for an API overridden HasInstance.
    1165         valueNotCell.link(&m_jit);
    1166         prototypeNotCell.link(&m_jit);
    1167         notDefaultHasInstance.link(&m_jit);
    1168         protoNotObject.link(&m_jit);
    1169 
    1170         silentSpillAllRegisters(scratchReg);
    1171         setupStubArguments(valueReg, baseReg, prototypeReg);
    1172         m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
    1173         appendCallWithExceptionCheck(operationInstanceOf);
    1174         m_jit.move(GPRInfo::returnValueGPR, scratchReg);
    1175         silentFillAllRegisters(scratchReg);
    1176 
    1177         MacroAssembler::Jump wasNotDefaultHasInstance = m_jit.jump();
    1178 
    1179         isInstance.link(&m_jit);
    1180         m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(true))), scratchReg);
    1181 
    1182         wasNotInstance.link(&m_jit);
    1183         wasNotDefaultHasInstance.link(&m_jit);
    1184         jsValueResult(scratchReg, m_compileIndex, UseChildrenCalledExplicitly);
     540        nonSpeculativeInstanceOf(node);
    1185541        break;
    1186542    }
  • trunk/Source/JavaScriptCore/dfg/DFGNonSpeculativeJIT.h

    r91804 r95230  
    8686    // These methods are used to plant calls out to C++
    8787    // helper routines to convert between types.
    88     void valueToNumber(JSValueOperand&, GPRReg result);
    89     void valueToInt32(JSValueOperand&, GPRReg result);
    90     void numberToInt32(FPRReg, GPRReg result);
    9188
    9289    // Record an entry location into the non-speculative code path;
     
    9895    }
    9996   
    100     // internal helpers for add/sub/mul operations
    101     void knownConstantArithOp(NodeType op, NodeIndex regChild, NodeIndex immChild, bool commute);
    102     void basicArithOp(NodeType op, Node&);
    103 
    10497    EntryLocationVector m_entryLocations;
    10598};
Note: See TracChangeset for help on using the changeset viewer.