Changeset 89772 in webkit


Ignore:
Timestamp:
Jun 26, 2011 12:30:56 PM (13 years ago)
Author:
commit-queue@webkit.org
Message:

2011-06-26 Filip Pizlo <fpizlo@apple.com>

Reviewed by Gavin Barraclough.

DFG non-speculative JIT has potentially harmful speculations with respect to arithmetic operations.
https://bugs.webkit.org/show_bug.cgi?id=63347

  • dfg/DFGNonSpeculativeJIT.cpp:
    • Changed arithmetic operations to speculate in favor of integers.

(JSC::DFG::NonSpeculativeJIT::valueToNumber):
(JSC::DFG::NonSpeculativeJIT::knownConstantArithOp):
(JSC::DFG::NonSpeculativeJIT::basicArithOp):
(JSC::DFG::NonSpeculativeJIT::compile):

  • dfg/DFGNonSpeculativeJIT.h:
  • dfg/DFGOperations.cpp:
    • Added slow-path routines for arithmetic that perform no speculation; the non-speculative JIT will generate calls to these in cases where its speculation fails.
  • dfg/DFGOperations.h:
Location:
trunk/Source/JavaScriptCore
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r89732 r89772  
     12011-06-26  Filip Pizlo  <fpizlo@apple.com>
     2
     3        Reviewed by Gavin Barraclough.
     4
     5        DFG non-speculative JIT has potentially harmful speculations with respect to arithmetic operations.
     6        https://bugs.webkit.org/show_bug.cgi?id=63347
     7
     8        * dfg/DFGNonSpeculativeJIT.cpp:
     9            - Changed arithmetic operations to speculate in favor of integers.
     10        (JSC::DFG::NonSpeculativeJIT::valueToNumber):
     11        (JSC::DFG::NonSpeculativeJIT::knownConstantArithOp):
     12        (JSC::DFG::NonSpeculativeJIT::basicArithOp):
     13        (JSC::DFG::NonSpeculativeJIT::compile):
     14        * dfg/DFGNonSpeculativeJIT.h:
     15        * dfg/DFGOperations.cpp:
     16            - Added slow-path routines for arithmetic that perform no speculation; the
     17              non-speculative JIT will generate calls to these in cases where its
     18              speculation fails.
     19        * dfg/DFGOperations.h:
     20
    1212011-06-24  Nikolas Zimmermann  <nzimmermann@rim.com>
    222
  • trunk/Source/JavaScriptCore/dfg/DFGNonSpeculativeJIT.cpp

    r89643 r89772  
    5757}
    5858
    59 void NonSpeculativeJIT::valueToNumber(JSValueOperand& operand, FPRReg fpr)
     59void NonSpeculativeJIT::valueToNumber(JSValueOperand& operand, GPRReg gpr)
    6060{
    6161    GPRReg jsValueGpr = operand.gpr();
    62     GPRReg tempGpr = allocate(); // FIXME: can we skip this allocation on the last use of the virtual register?
    6362
    6463    JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
     
    6665
    6766    // First, if we get here we have a double encoded as a JSValue
    68     m_jit.move(jsValueGpr, tempGpr);
    69     m_jit.addPtr(GPRInfo::tagTypeNumberRegister, tempGpr);
    70     m_jit.movePtrToDouble(tempGpr, fpr);
     67    m_jit.move(jsValueGpr, gpr);
    7168    JITCompiler::Jump hasUnboxedDouble = m_jit.jump();
    7269
    7370    // Next handle cells (& other JS immediates)
    7471    nonNumeric.link(&m_jit);
    75     silentSpillAllRegisters(fpr, jsValueGpr);
     72    silentSpillAllRegisters(gpr, jsValueGpr);
    7673    m_jit.move(jsValueGpr, GPRInfo::argumentGPR1);
    7774    m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
    7875    appendCallWithExceptionCheck(dfgConvertJSValueToNumber);
    79     m_jit.moveDouble(FPRInfo::returnValueFPR, fpr);
    80     silentFillAllRegisters(fpr);
     76    boxDouble(FPRInfo::returnValueFPR, gpr);
     77    silentFillAllRegisters(gpr);
    8178    JITCompiler::Jump hasCalledToNumber = m_jit.jump();
    8279   
    8380    // Finally, handle integers.
    8481    isInteger.link(&m_jit);
    85     m_jit.convertInt32ToDouble(jsValueGpr, fpr);
     82    m_jit.orPtr(GPRInfo::tagTypeNumberRegister, jsValueGpr, gpr);
    8683    hasUnboxedDouble.link(&m_jit);
    8784    hasCalledToNumber.link(&m_jit);
    88 
    89     m_gprs.unlock(tempGpr);
    9085}
    9186
     
    166161}
    167162
     163void NonSpeculativeJIT::knownConstantArithOp(NodeType op, NodeIndex regChild, NodeIndex immChild, bool commute)
     164{
     165    JSValueOperand regArg(this, regChild);
     166    GPRReg regArgGPR = regArg.gpr();
     167    GPRTemporary result(this, regArg);
     168    GPRReg resultGPR = result.gpr();
     169
     170    JITCompiler::Jump notInt;
     171   
     172    int32_t imm = valueOfInt32Constant(immChild);
     173       
     174    if (!isKnownInteger(regChild))
     175        notInt = m_jit.branchPtr(MacroAssembler::Below, regArgGPR, GPRInfo::tagTypeNumberRegister);
     176       
     177    m_jit.zeroExtend32ToPtr(regArgGPR, resultGPR);
     178       
     179    JITCompiler::Jump overflow;
     180   
     181    switch (op) {
     182    case ValueAdd:
     183    case ArithAdd: {
     184        overflow = m_jit.branchAdd32(MacroAssembler::Overflow, Imm32(imm), resultGPR);
     185        break;
     186    }
     187       
     188    case ArithSub: {
     189        overflow = m_jit.branchSub32(MacroAssembler::Overflow, Imm32(imm), resultGPR);
     190        break;
     191    }
     192       
     193    default:
     194        ASSERT_NOT_REACHED();
     195    }
     196   
     197    m_jit.orPtr(GPRInfo::tagTypeNumberRegister, resultGPR);
     198       
     199    JITCompiler::Jump done = m_jit.jump();
     200   
     201    overflow.link(&m_jit);
     202   
     203    if (regArgGPR == resultGPR) {
     204        switch (op) {
     205        case ValueAdd:
     206        case ArithAdd: {
     207            m_jit.sub32(Imm32(imm), regArgGPR);
     208            break;
     209        }
     210           
     211        case ArithSub: {
     212            m_jit.add32(Imm32(imm), regArgGPR);
     213            break;
     214        }
     215           
     216        default:
     217            ASSERT_NOT_REACHED();
     218        }
     219        m_jit.orPtr(GPRInfo::tagTypeNumberRegister, regArgGPR);
     220    }
     221   
     222    if (!isKnownInteger(regChild))
     223        notInt.link(&m_jit);
     224   
     225    silentSpillAllRegisters(resultGPR, regArgGPR);
     226    switch (op) {
     227    case ValueAdd:
     228        if (commute) {
     229            m_jit.move(regArgGPR, GPRInfo::argumentGPR2);
     230            m_jit.move(MacroAssembler::ImmPtr(static_cast<const void*>(JSValue::encode(jsNumber(imm)))), GPRInfo::argumentGPR1);
     231        } else {
     232            m_jit.move(regArgGPR, GPRInfo::argumentGPR1);
     233            m_jit.move(MacroAssembler::ImmPtr(static_cast<const void*>(JSValue::encode(jsNumber(imm)))), GPRInfo::argumentGPR2);
     234        }
     235        m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
     236        appendCallWithExceptionCheck(operationValueAdd);
     237        break;
     238       
     239    case ArithAdd:
     240        if (commute) {
     241            m_jit.move(regArgGPR, GPRInfo::argumentGPR1);
     242            m_jit.move(MacroAssembler::ImmPtr(static_cast<const void*>(JSValue::encode(jsNumber(imm)))), GPRInfo::argumentGPR0);
     243        } else {
     244            m_jit.move(regArgGPR, GPRInfo::argumentGPR0);
     245            m_jit.move(MacroAssembler::ImmPtr(static_cast<const void*>(JSValue::encode(jsNumber(imm)))), GPRInfo::argumentGPR1);
     246        }
     247        m_jit.appendCall(operationArithAdd);
     248        break;
     249       
     250    case ArithSub:
     251        ASSERT(!commute);
     252        m_jit.move(regArgGPR, GPRInfo::argumentGPR0);
     253        m_jit.move(MacroAssembler::ImmPtr(static_cast<const void*>(JSValue::encode(jsNumber(imm)))), GPRInfo::argumentGPR1);
     254        m_jit.appendCall(operationArithSub);
     255        break;
     256       
     257    default:
     258        ASSERT_NOT_REACHED();
     259    }
     260    m_jit.move(GPRInfo::returnValueGPR, resultGPR);
     261    silentFillAllRegisters(resultGPR);
     262   
     263    done.link(&m_jit);
     264       
     265    jsValueResult(resultGPR, m_compileIndex);
     266}
     267
     268void NonSpeculativeJIT::basicArithOp(NodeType op, Node &node)
     269{
     270    JSValueOperand arg1(this, node.child1);
     271    JSValueOperand arg2(this, node.child2);
     272   
     273    GPRReg arg1GPR = arg1.gpr();
     274    GPRReg arg2GPR = arg2.gpr();
     275   
     276    GPRTemporary temp(this, arg2);
     277    GPRTemporary result(this);
     278
     279    GPRReg tempGPR = temp.gpr();
     280    GPRReg resultGPR = result.gpr();
     281   
     282    JITCompiler::JumpList slowPath;
     283    JITCompiler::JumpList overflowSlowPath;
     284   
     285    if (!isKnownInteger(node.child1))
     286        slowPath.append(m_jit.branchPtr(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister));
     287    if (!isKnownInteger(node.child2))
     288        slowPath.append(m_jit.branchPtr(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister));
     289   
     290    m_jit.zeroExtend32ToPtr(arg1GPR, resultGPR);
     291    m_jit.zeroExtend32ToPtr(arg2GPR, tempGPR);
     292   
     293    switch (op) {
     294    case ValueAdd:
     295    case ArithAdd: {
     296        overflowSlowPath.append(m_jit.branchAdd32(MacroAssembler::Overflow, tempGPR, resultGPR));
     297        break;
     298    }
     299       
     300    case ArithSub: {
     301        overflowSlowPath.append(m_jit.branchSub32(MacroAssembler::Overflow, tempGPR, resultGPR));
     302        break;
     303    }
     304       
     305    case ArithMul: {
     306        overflowSlowPath.append(m_jit.branchMul32(MacroAssembler::Overflow, tempGPR, resultGPR));
     307        overflowSlowPath.append(m_jit.branchTest32(MacroAssembler::Zero, resultGPR));
     308        break;
     309    }
     310       
     311    default:
     312        ASSERT_NOT_REACHED();
     313    }
     314   
     315    m_jit.orPtr(GPRInfo::tagTypeNumberRegister, resultGPR);
     316       
     317    JITCompiler::Jump done = m_jit.jump();
     318   
     319    overflowSlowPath.link(&m_jit);
     320   
     321    if (arg2GPR == tempGPR)
     322        m_jit.orPtr(GPRInfo::tagTypeNumberRegister, arg2GPR);
     323   
     324    slowPath.link(&m_jit);
     325   
     326    silentSpillAllRegisters(resultGPR, arg1GPR, arg2GPR);
     327    if (op == ValueAdd) {
     328        setupStubArguments(arg1GPR, arg2GPR);
     329        m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
     330        appendCallWithExceptionCheck(operationValueAdd);
     331    } else {
     332        setupTwoStubArgs<GPRInfo::argumentGPR0, GPRInfo::argumentGPR1>(arg1GPR, arg2GPR);
     333        switch (op) {
     334        case ArithAdd:
     335            m_jit.appendCall(operationArithAdd);
     336            break;
     337           
     338        case ArithSub:
     339            m_jit.appendCall(operationArithSub);
     340            break;
     341           
     342        case ArithMul:
     343            m_jit.appendCall(operationArithMul);
     344            break;
     345           
     346        default:
     347            ASSERT_NOT_REACHED();
     348        }
     349    }
     350    m_jit.move(GPRInfo::returnValueGPR, resultGPR);
     351    silentFillAllRegisters(resultGPR);
     352   
     353    done.link(&m_jit);
     354       
     355    jsValueResult(resultGPR, m_compileIndex);
     356}
     357
     358void NonSpeculativeJIT::compare(Node& node, MacroAssembler::RelationalCondition cond, const Z_DFGOperation_EJJ& helperFunction)
     359{
     360    // FIXME: should do some peephole to fuse compare/branch
     361       
     362    JSValueOperand arg1(this, node.child1);
     363    JSValueOperand arg2(this, node.child2);
     364    GPRReg arg1GPR = arg1.gpr();
     365    GPRReg arg2GPR = arg2.gpr();
     366   
     367    GPRTemporary result(this);
     368    GPRTemporary temp(this);
     369    GPRReg resultGPR = result.gpr();
     370    GPRReg tempGPR = temp.gpr();
     371   
     372    JITCompiler::JumpList slowPath;
     373   
     374    if (!isKnownInteger(node.child1))
     375        slowPath.append(m_jit.branchPtr(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister));
     376    if (!isKnownInteger(node.child2))
     377        slowPath.append(m_jit.branchPtr(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister));
     378   
     379    m_jit.zeroExtend32ToPtr(arg1GPR, tempGPR);
     380    m_jit.zeroExtend32ToPtr(arg2GPR, resultGPR);
     381   
     382    m_jit.compare32(cond, tempGPR, resultGPR, resultGPR);
     383   
     384    JITCompiler::Jump haveResult = m_jit.jump();
     385   
     386    slowPath.link(&m_jit);
     387   
     388    silentSpillAllRegisters(resultGPR, arg1GPR, arg2GPR);
     389    setupStubArguments(arg1GPR, arg2GPR);
     390    m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
     391    appendCallWithExceptionCheck(helperFunction);
     392    m_jit.move(GPRInfo::returnValueGPR, resultGPR);
     393    silentFillAllRegisters(resultGPR);
     394       
     395    m_jit.andPtr(TrustedImm32(static_cast<int32_t>(1)), resultGPR);
     396   
     397    haveResult.link(&m_jit);
     398   
     399    m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
     400    jsValueResult(resultGPR, m_compileIndex);
     401}
     402
    168403void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator, Node& node)
    169404{
     
    273508    case UInt32ToNumber: {
    274509        IntegerOperand op1(this, node.child1);
    275         FPRTemporary result(this);
    276         m_jit.convertInt32ToDouble(op1.gpr(), result.fpr());
    277 
    278         MacroAssembler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, op1.gpr(), TrustedImm32(0));
    279         m_jit.addDouble(JITCompiler::AbsoluteAddress(&twoToThe32), result.fpr());
     510        FPRTemporary boxer(this);
     511        GPRTemporary result(this, op1);
     512       
     513        JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, op1.gpr(), TrustedImm32(0));
     514       
     515        m_jit.convertInt32ToDouble(op1.gpr(), boxer.fpr());
     516        m_jit.addDouble(JITCompiler::AbsoluteAddress(&twoToThe32), boxer.fpr());
     517       
     518        m_jit.moveDoubleToPtr(boxer.fpr(), result.gpr());
     519        m_jit.subPtr(GPRInfo::tagTypeNumberRegister, result.gpr());
     520       
     521        JITCompiler::Jump done = m_jit.jump();
     522       
    280523        positive.link(&m_jit);
    281 
    282         doubleResult(result.fpr(), m_compileIndex);
     524       
     525        m_jit.orPtr(GPRInfo::tagTypeNumberRegister, op1.gpr(), result.gpr());
     526       
     527        done.link(&m_jit);
     528
     529        jsValueResult(result.gpr(), m_compileIndex);
    283530        break;
    284531    }
     
    296543
    297544        GenerationInfo& childInfo = m_generationInfo[m_jit.graph()[node.child1].virtualRegister()];
    298         if ((childInfo.registerFormat() || DataFormatJS) == DataFormatJSDouble) {
     545        if ((childInfo.registerFormat() | DataFormatJS) == DataFormatJSDouble) {
    299546            DoubleOperand op1(this, node.child1);
    300547            GPRTemporary result(this);
     
    315562        ASSERT(!isDoubleConstant(node.child1));
    316563
    317         if (isKnownInteger(node.child1)) {
    318             IntegerOperand op1(this, node.child1);
    319             FPRTemporary result(this);
    320             m_jit.convertInt32ToDouble(op1.gpr(), result.fpr());
    321             doubleResult(result.fpr(), m_compileIndex);
    322             break;
    323         }
    324 
    325         GenerationInfo& childInfo = m_generationInfo[m_jit.graph()[node.child1].virtualRegister()];
    326         if ((childInfo.registerFormat() || DataFormatJS) == DataFormatJSDouble) {
    327             DoubleOperand op1(this, node.child1);
    328             FPRTemporary result(this, op1);
    329             m_jit.moveDouble(op1.fpr(), result.fpr());
    330             doubleResult(result.fpr(), m_compileIndex);
     564        if (isKnownNumeric(node.child1)) {
     565            JSValueOperand op1(this, node.child1);
     566            GPRTemporary result(this, op1);
     567            m_jit.move(op1.gpr(), result.gpr());
     568            jsValueResult(result.gpr(), m_compileIndex);
    331569            break;
    332570        }
    333571
    334572        JSValueOperand op1(this, node.child1);
    335         FPRTemporary result(this);
    336         valueToNumber(op1, result.fpr());
    337         doubleResult(result.fpr(), m_compileIndex);
    338         break;
    339     }
    340 
    341     case ValueAdd: {
     573        GPRTemporary result(this);
     574        valueToNumber(op1, result.gpr());
     575        jsValueResult(result.gpr(), m_compileIndex);
     576        break;
     577    }
     578
     579    case ValueAdd:
     580    case ArithAdd: {
     581        if (isInt32Constant(node.child1)) {
     582            knownConstantArithOp(op, node.child2, node.child1, true);
     583            break;
     584        }
     585       
     586        if (isInt32Constant(node.child2)) {
     587            knownConstantArithOp(op, node.child1, node.child2, false);
     588            break;
     589        }
     590       
     591        basicArithOp(op, node);
     592        break;
     593    }
     594       
     595    case ArithSub: {
     596        if (isInt32Constant(node.child2)) {
     597            knownConstantArithOp(ArithSub, node.child1, node.child2, false);
     598            break;
     599        }
     600       
     601        basicArithOp(ArithSub, node);
     602        break;
     603    }
     604
     605    case ArithMul: {
     606        basicArithOp(ArithMul, node);
     607        break;
     608    }
     609
     610    case ArithDiv: {
     611        JSValueOperand arg1(this, node.child1);
     612        JSValueOperand arg2(this, node.child2);
     613        GPRReg arg1GPR = arg1.gpr();
     614        GPRReg arg2GPR = arg2.gpr();
     615       
     616        flushRegisters();
     617
     618        GPRResult result(this);
     619
     620        ASSERT(isFlushed());
     621        setupTwoStubArgs<GPRInfo::argumentGPR0, GPRInfo::argumentGPR1>(arg1GPR, arg2GPR);
     622        m_jit.appendCall(operationArithDiv);
     623        m_jit.move(GPRInfo::returnValueGPR, result.gpr());
     624
     625        jsValueResult(result.gpr(), m_compileIndex);
     626        break;
     627    }
     628
     629    case ArithMod: {
    342630        JSValueOperand arg1(this, node.child1);
    343631        JSValueOperand arg2(this, node.child2);
     
    347635
    348636        GPRResult result(this);
    349         callOperation(operationValueAdd, result.gpr(), arg1GPR, arg2GPR);
     637
     638        ASSERT(isFlushed());
     639        setupTwoStubArgs<GPRInfo::argumentGPR0, GPRInfo::argumentGPR1>(arg1GPR, arg2GPR);
     640        m_jit.appendCall(operationArithMod);
     641        m_jit.move(GPRInfo::returnValueGPR, result.gpr());
    350642
    351643        jsValueResult(result.gpr(), m_compileIndex);
    352         break;
    353     }
    354        
    355     case ArithAdd: {
    356         DoubleOperand op1(this, node.child1);
    357         DoubleOperand op2(this, node.child2);
    358         FPRTemporary result(this, op1, op2);
    359 
    360         FPRReg reg1 = op1.fpr();
    361         FPRReg reg2 = op2.fpr();
    362         m_jit.addDouble(reg1, reg2, result.fpr());
    363 
    364         doubleResult(result.fpr(), m_compileIndex);
    365         break;
    366     }
    367 
    368     case ArithSub: {
    369         DoubleOperand op1(this, node.child1);
    370         DoubleOperand op2(this, node.child2);
    371         FPRTemporary result(this, op1);
    372 
    373         FPRReg reg1 = op1.fpr();
    374         FPRReg reg2 = op2.fpr();
    375         m_jit.subDouble(reg1, reg2, result.fpr());
    376 
    377         doubleResult(result.fpr(), m_compileIndex);
    378         break;
    379     }
    380 
    381     case ArithMul: {
    382         DoubleOperand op1(this, node.child1);
    383         DoubleOperand op2(this, node.child2);
    384         FPRTemporary result(this, op1, op2);
    385 
    386         FPRReg reg1 = op1.fpr();
    387         FPRReg reg2 = op2.fpr();
    388         m_jit.mulDouble(reg1, reg2, result.fpr());
    389 
    390         doubleResult(result.fpr(), m_compileIndex);
    391         break;
    392     }
    393 
    394     case ArithDiv: {
    395         DoubleOperand op1(this, node.child1);
    396         DoubleOperand op2(this, node.child2);
    397         FPRTemporary result(this, op1);
    398 
    399         FPRReg reg1 = op1.fpr();
    400         FPRReg reg2 = op2.fpr();
    401         m_jit.divDouble(reg1, reg2, result.fpr());
    402 
    403         doubleResult(result.fpr(), m_compileIndex);
    404         break;
    405     }
    406 
    407     case ArithMod: {
    408         DoubleOperand arg1(this, node.child1);
    409         DoubleOperand arg2(this, node.child2);
    410         FPRReg arg1FPR = arg1.fpr();
    411         FPRReg arg2FPR = arg2.fpr();
    412         flushRegisters();
    413 
    414         FPRResult result(this);
    415         callOperation(fmod, result.fpr(), arg1FPR, arg2FPR);
    416 
    417         doubleResult(result.fpr(), m_compileIndex);
    418644        break;
    419645    }
     
    421647    case LogicalNot: {
    422648        JSValueOperand arg1(this, node.child1);
     649        GPRTemporary result(this);
     650
    423651        GPRReg arg1GPR = arg1.gpr();
    424         flushRegisters();
    425 
    426         GPRResult result(this);
    427         callOperation(dfgConvertJSValueToBoolean, result.gpr(), arg1GPR);
    428 
    429         // If we add a DataFormatBool, we should use it here.
    430         m_jit.xor32(TrustedImm32(ValueTrue), result.gpr());
    431         jsValueResult(result.gpr(), m_compileIndex);
    432         break;
    433     }
    434 
    435     case CompareLess: {
    436         JSValueOperand arg1(this, node.child1);
    437         JSValueOperand arg2(this, node.child2);
    438         GPRReg arg1GPR = arg1.gpr();
    439         GPRReg arg2GPR = arg2.gpr();
    440         flushRegisters();
    441 
    442         GPRResult result(this);
    443         callOperation(operationCompareLess, result.gpr(), arg1GPR, arg2GPR);
    444         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
    445 
    446         jsValueResult(result.gpr(), m_compileIndex);
    447         break;
    448     }
    449 
    450     case CompareLessEq: {
    451         JSValueOperand arg1(this, node.child1);
    452         JSValueOperand arg2(this, node.child2);
    453         GPRReg arg1GPR = arg1.gpr();
    454         GPRReg arg2GPR = arg2.gpr();
    455         flushRegisters();
    456 
    457         GPRResult result(this);
    458         callOperation(operationCompareLessEq, result.gpr(), arg1GPR, arg2GPR);
    459         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
    460 
    461         jsValueResult(result.gpr(), m_compileIndex);
    462         break;
    463     }
    464 
    465     case CompareEq: {
    466         JSValueOperand arg1(this, node.child1);
    467         JSValueOperand arg2(this, node.child2);
    468         GPRReg arg1GPR = arg1.gpr();
    469         GPRReg arg2GPR = arg2.gpr();
    470         flushRegisters();
    471 
    472         GPRResult result(this);
    473         callOperation(operationCompareEq, result.gpr(), arg1GPR, arg2GPR);
    474         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
    475 
    476         jsValueResult(result.gpr(), m_compileIndex);
    477         break;
    478     }
    479 
    480     case CompareStrictEq: {
    481         JSValueOperand arg1(this, node.child1);
    482         JSValueOperand arg2(this, node.child2);
    483         GPRReg arg1GPR = arg1.gpr();
    484         GPRReg arg2GPR = arg2.gpr();
    485         flushRegisters();
    486 
    487         GPRResult result(this);
    488         callOperation(operationCompareStrictEq, result.gpr(), arg1GPR, arg2GPR);
    489         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
    490 
    491         jsValueResult(result.gpr(), m_compileIndex);
    492         break;
    493     }
     652        GPRReg resultGPR = result.gpr();
     653       
     654        m_jit.move(arg1GPR, resultGPR);
     655        m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), resultGPR);
     656        JITCompiler::Jump fastCase = m_jit.branchTestPtr(JITCompiler::Zero, resultGPR, TrustedImm32(static_cast<int32_t>(~1)));
     657       
     658        silentSpillAllRegisters(resultGPR, arg1GPR);
     659        m_jit.move(arg1GPR, GPRInfo::argumentGPR1);
     660        m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
     661        appendCallWithExceptionCheck(dfgConvertJSValueToBoolean);
     662        m_jit.move(GPRInfo::returnValueGPR, resultGPR);
     663        silentFillAllRegisters(resultGPR);
     664       
     665        fastCase.link(&m_jit);
     666
     667        m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueTrue)), resultGPR);
     668        jsValueResult(resultGPR, m_compileIndex);
     669        break;
     670    }
     671
     672    case CompareLess:
     673        compare(node, MacroAssembler::LessThan, operationCompareLess);
     674        break;
     675       
     676    case CompareLessEq:
     677        compare(node, MacroAssembler::LessThanOrEqual, operationCompareLessEq);
     678        break;
     679       
     680    case CompareEq:
     681        compare(node, MacroAssembler::Equal, operationCompareEq);
     682        break;
     683
     684    case CompareStrictEq:
     685        compare(node, MacroAssembler::Equal, operationCompareStrictEq);
     686        break;
    494687
    495688    case GetByVal: {
  • trunk/Source/JavaScriptCore/dfg/DFGNonSpeculativeJIT.h

    r87364 r89772  
    8888    // These methods are used to plant calls out to C++
    8989    // helper routines to convert between types.
    90     void valueToNumber(JSValueOperand&, FPRReg result);
     90    void valueToNumber(JSValueOperand&, GPRReg result);
    9191    void valueToInt32(JSValueOperand&, GPRReg result);
    9292    void numberToInt32(FPRReg, GPRReg result);
     
    9999        m_entryLocations.append(EntryLocation(entry, this));
    100100    }
    101 
     101   
     102    // internal helpers for add/sub/mul operations
     103    void knownConstantArithOp(NodeType op, NodeIndex regChild, NodeIndex immChild, bool commute);
     104    void basicArithOp(NodeType op, Node&);
     105    void compare(Node&, MacroAssembler::RelationalCondition, const Z_DFGOperation_EJJ&);
     106   
    102107    EntryLocationVector m_entryLocations;
    103108};
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r88975 r89772  
    139139}
    140140
     141EncodedJSValue operationArithAdd(EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
     142{
     143    double num1 = JSValue::decode(encodedOp1).uncheckedGetNumber();
     144    double num2 = JSValue::decode(encodedOp2).uncheckedGetNumber();
     145    return JSValue::encode(jsNumber(num1 + num2));
     146}
     147
     148EncodedJSValue operationArithSub(EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
     149{
     150    double num1 = JSValue::decode(encodedOp1).uncheckedGetNumber();
     151    double num2 = JSValue::decode(encodedOp2).uncheckedGetNumber();
     152    return JSValue::encode(jsNumber(num1 - num2));
     153}
     154
     155EncodedJSValue operationArithMul(EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
     156{
     157    double num1 = JSValue::decode(encodedOp1).uncheckedGetNumber();
     158    double num2 = JSValue::decode(encodedOp2).uncheckedGetNumber();
     159    return JSValue::encode(jsNumber(num1 * num2));
     160}
     161
     162EncodedJSValue operationArithDiv(EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
     163{
     164    double num1 = JSValue::decode(encodedOp1).uncheckedGetNumber();
     165    double num2 = JSValue::decode(encodedOp2).uncheckedGetNumber();
     166    return JSValue::encode(jsNumber(num1 / num2));
     167}
     168
     169EncodedJSValue operationArithMod(EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
     170{
     171    double num1 = JSValue::decode(encodedOp1).uncheckedGetNumber();
     172    double num2 = JSValue::decode(encodedOp2).uncheckedGetNumber();
     173    return JSValue::encode(jsNumber(fmod(num1, num2)));
     174}
     175
    141176static inline EncodedJSValue getByVal(ExecState* exec, JSCell* base, uint32_t index)
    142177{
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.h

    r88280 r89772  
    5050EncodedJSValue operationConvertThis(ExecState*, EncodedJSValue encodedOp1);
    5151EncodedJSValue operationValueAdd(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
     52EncodedJSValue operationArithAdd(EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
     53EncodedJSValue operationArithSub(EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
     54EncodedJSValue operationArithMul(EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
     55EncodedJSValue operationArithDiv(EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
     56EncodedJSValue operationArithMod(EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
    5257EncodedJSValue operationGetByVal(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty);
    5358EncodedJSValue operationGetById(ExecState*, EncodedJSValue encodedBase, Identifier*);
Note: See TracChangeset for help on using the changeset viewer.