Changeset 36976 in webkit for trunk/JavaScriptCore/VM/CTI.cpp


Ignore:
Timestamp:
Sep 26, 2008, 6:44:15 PM (17 years ago)
Author:
[email protected]
Message:

2008-09-26 Gavin Barraclough <[email protected]>

Reviewed by Maciej Stachowiak & Oliver Hunt.

Add support for reusing temporary JSNumberCells. This change is based on the observation
that if the result of certain operations is a JSNumberCell and is consumed by a subsequent
operation that would produce a JSNumberCell, we can reuse the object rather than allocating
a fresh one. E.g. given the expression ((a * b) * c), we can statically determine that
(a * b) will have a numeric result (or else it will have thrown an exception), so the result
will either be a JSNumberCell or a JSImmediate.

This patch changes three areas of JSC:

  • The AST now tracks type information about the result of each node.
  • This information is consumed in bytecode compilation, and certain bytecode operations now carry the statically determined type information about their operands.
  • CTI uses the information in a number of fashions:
    • Where an operand to certain arithmetic operations is reusable, it will plant code to try to perform the operation in JIT code & reuse the cell, where appropriate.
    • Where it can be statically determined that an operand can only be numeric (typically the result of another arithmetic operation) the code will not redundantly check that the JSCell is a JSNumberCell.
    • Where either of the operands to an add are non-numeric do not plant an optimized arithmetic code path, just call straight out to the C function.

+6% Sunspider (10% progression on 3D, 16% progression on math, 60% progression on access-nbody),
+1% v8-tests (improvements in raytrace & crypto)

  • VM/CTI.cpp: Add optimized code generation with reuse of temporary JSNumberCells.
  • VM/CTI.h:
  • kjs/JSNumberCell.h:
  • masm/X86Assembler.h:
  • VM/CodeBlock.cpp: Add type information to specific bytecodes.
  • VM/CodeGenerator.cpp:
  • VM/CodeGenerator.h:
  • VM/Machine.cpp:
  • kjs/nodes.cpp: Track static type information for nodes.
  • kjs/nodes.h:
  • kjs/ResultDescriptor.h: (Added)
  • JavaScriptCore.xcodeproj/project.pbxproj:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/VM/CTI.cpp

    r36972 r36976  
    3333#include "Machine.h"
    3434#include "wrec/WREC.h"
     35#include "ResultType.h"
     36#if PLATFORM(MAC)
     37#include <sys/sysctl.h>
     38#endif
    3539
    3640using namespace std;
    3741
    3842namespace JSC {
     43
     44#if PLATFORM(MAC)
     45bool isSSE3Present()
     46{
     47    struct SSE3Check {
     48        SSE3Check()
     49        {
     50            int hasSSE3 = 0;
     51            size_t length = sizeof(hasSSE3);
     52            int error = sysctlbyname("hw.optional.sse3", &hasSSE3, &length, NULL, 0);
     53            present = hasSSE3 && !error;
     54        }
     55        bool present;
     56    };
     57    static SSE3Check check;
     58    return check.present;
     59}
     60#else
     61bool isSSE3Present()
     62{
     63    return false;
     64}
     65#endif
    3966
    4067#if COMPILER(GCC) && PLATFORM(X86)
     
    602629}
    603630
     631/*
     632  This is required since number representation is canonical - values representable as a JSImmediate should not be stored in a JSNumberCell.
     633 
     634  In the common case, the double value from 'xmmSource' is written to the reusable JSNumberCell pointed to by 'jsNumberCell', then 'jsNumberCell'
     635  is written to the output SF Register 'dst', and then a jump is planted (stored into *wroteJSNumberCell).
     636 
     637  However if the value from xmmSource is representable as a JSImmediate, then the JSImmediate value will be written to the output, and flow
     638  control will fall through from the code planted.
     639*/
     640void CTI::putDoubleResultToJSNumberCellOrJSImmediate(X86::XMMRegisterID xmmSource, X86::RegisterID jsNumberCell, unsigned dst, X86Assembler::JmpSrc* wroteJSNumberCell,  X86::XMMRegisterID tempXmm, X86::RegisterID tempReg1, X86::RegisterID tempReg2)
     641{
     642    // convert (double -> JSImmediate -> double), and check if the value is unchanged - in which case the value is representable as a JSImmediate.
     643    m_jit.cvttsd2si_rr(xmmSource, tempReg1);
     644    m_jit.addl_rr(tempReg1, tempReg1);
     645    m_jit.sarl_i8r(1, tempReg1);
     646    m_jit.cvtsi2sd_rr(tempReg1, tempXmm);
     647    // Compare & branch if immediate.
     648    m_jit.ucomis_rr(tempXmm, xmmSource);
     649    X86Assembler::JmpSrc resultIsImm = m_jit.emitUnlinkedJe();
     650    X86Assembler::JmpDst resultLookedLikeImmButActuallyIsnt = m_jit.label();
     651   
     652    // Store the result to the JSNumberCell and jump.
     653    m_jit.movsd_rm(xmmSource, OBJECT_OFFSET(JSNumberCell, m_value), jsNumberCell);
     654    emitPutResult(dst, jsNumberCell);
     655    *wroteJSNumberCell = m_jit.emitUnlinkedJmp();
     656
     657    m_jit.link(resultIsImm, m_jit.label());
     658    // value == (double)(JSImmediate)value... or at least, it looks that way...
     659    // ucomi will report that (0 == -0), and will report true if either input in NaN (result is unordered).
     660    m_jit.link(m_jit.emitUnlinkedJp(), resultLookedLikeImmButActuallyIsnt); // Actually was a NaN
     661    m_jit.pextrw_irr(3, xmmSource, tempReg2);
     662    m_jit.cmpl_i32r(0x8000, tempReg2);
     663    m_jit.link(m_jit.emitUnlinkedJe(), resultLookedLikeImmButActuallyIsnt); // Actually was -0
     664    // Yes it really really really is representable as a JSImmediate.
     665    emitFastArithIntToImmNoCheck(tempReg1);
     666    emitPutResult(dst, X86::ecx);
     667}
     668
     669void CTI::compileBinaryArithOp(OpcodeID opcodeID, unsigned dst, unsigned src1, unsigned src2, OperandTypes types, unsigned i)
     670{
     671    StructureID* numberStructureID = m_exec->globalData().numberStructureID.get();
     672    X86Assembler::JmpSrc wasJSNumberCell1, wasJSNumberCell1b, wasJSNumberCell2, wasJSNumberCell2b;
     673
     674    emitGetArg(src1, X86::eax);
     675    emitGetArg(src2, X86::edx);
     676
     677    if (types.second().isReusable() && isSSE3Present()) {
     678        ASSERT(types.second().mightBeNumber());
     679
     680        // Check op2 is a number
     681        m_jit.testl_i32r(JSImmediate::TagBitTypeInteger, X86::edx);
     682        X86Assembler::JmpSrc op2imm = m_jit.emitUnlinkedJne();
     683        if (!types.second().definitelyIsNumber()) {
     684            emitJumpSlowCaseIfNotJSCell(X86::edx, i);
     685            m_jit.cmpl_i32m(reinterpret_cast<unsigned>(numberStructureID), OBJECT_OFFSET(JSCell, m_structureID), X86::edx);
     686            m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
     687        }
     688
     689        // (1) In this case src2 is a reusable number cell.
     690        //     Slow case if src1 is not a number type.
     691        m_jit.testl_i32r(JSImmediate::TagBitTypeInteger, X86::eax);
     692        X86Assembler::JmpSrc op1imm = m_jit.emitUnlinkedJne();
     693        if (!types.first().definitelyIsNumber()) {
     694            emitJumpSlowCaseIfNotJSCell(X86::eax, i);
     695            m_jit.cmpl_i32m(reinterpret_cast<unsigned>(numberStructureID), OBJECT_OFFSET(JSCell, m_structureID), X86::eax);
     696            m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
     697        }
     698
     699        // (1a) if we get here, src1 is also a number cell
     700        m_jit.movsd_mr(OBJECT_OFFSET(JSNumberCell, m_value), X86::eax, X86::xmm0);
     701        X86Assembler::JmpSrc loadedDouble = m_jit.emitUnlinkedJmp();
     702        // (1b) if we get here, src1 is an immediate
     703        m_jit.link(op1imm, m_jit.label());
     704        emitFastArithImmToInt(X86::eax);
     705        m_jit.cvtsi2sd_rr(X86::eax, X86::xmm0);
     706        // (1c)
     707        m_jit.link(loadedDouble, m_jit.label());
     708        if (opcodeID == op_add)
     709            m_jit.addsd_mr(OBJECT_OFFSET(JSNumberCell, m_value), X86::edx, X86::xmm0);
     710        else if (opcodeID == op_sub)
     711            m_jit.subsd_mr(OBJECT_OFFSET(JSNumberCell, m_value), X86::edx, X86::xmm0);
     712        else {
     713            ASSERT(opcodeID == op_mul);
     714            m_jit.mulsd_mr(OBJECT_OFFSET(JSNumberCell, m_value), X86::edx, X86::xmm0);
     715        }
     716
     717        putDoubleResultToJSNumberCellOrJSImmediate(X86::xmm0, X86::edx, dst, &wasJSNumberCell2, X86::xmm1, X86::ecx, X86::eax);
     718        wasJSNumberCell2b = m_jit.emitUnlinkedJmp();
     719
     720        // (2) This handles cases where src2 is an immediate number.
     721        //     Two slow cases - either src1 isn't an immediate, or the subtract overflows.
     722        m_jit.link(op2imm, m_jit.label());
     723        emitJumpSlowCaseIfNotImmNum(X86::eax, i);
     724    } else if (types.first().isReusable() && isSSE3Present()) {
     725        ASSERT(types.first().mightBeNumber());
     726
     727        // Check op1 is a number
     728        m_jit.testl_i32r(JSImmediate::TagBitTypeInteger, X86::eax);
     729        X86Assembler::JmpSrc op1imm = m_jit.emitUnlinkedJne();
     730        if (!types.first().definitelyIsNumber()) {
     731            emitJumpSlowCaseIfNotJSCell(X86::eax, i);
     732            m_jit.cmpl_i32m(reinterpret_cast<unsigned>(numberStructureID), OBJECT_OFFSET(JSCell, m_structureID), X86::eax);
     733            m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
     734        }
     735
     736        // (1) In this case src1 is a reusable number cell.
     737        //     Slow case if src2 is not a number type.
     738        m_jit.testl_i32r(JSImmediate::TagBitTypeInteger, X86::edx);
     739        X86Assembler::JmpSrc op2imm = m_jit.emitUnlinkedJne();
     740        if (!types.second().definitelyIsNumber()) {
     741            emitJumpSlowCaseIfNotJSCell(X86::edx, i);
     742            m_jit.cmpl_i32m(reinterpret_cast<unsigned>(numberStructureID), OBJECT_OFFSET(JSCell, m_structureID), X86::edx);
     743            m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
     744        }
     745
     746        // (1a) if we get here, src2 is also a number cell
     747        m_jit.movsd_mr(OBJECT_OFFSET(JSNumberCell, m_value), X86::edx, X86::xmm1);
     748        X86Assembler::JmpSrc loadedDouble = m_jit.emitUnlinkedJmp();
     749        // (1b) if we get here, src2 is an immediate
     750        m_jit.link(op2imm, m_jit.label());
     751        emitFastArithImmToInt(X86::edx);
     752        m_jit.cvtsi2sd_rr(X86::edx, X86::xmm1);
     753        // (1c)
     754        m_jit.link(loadedDouble, m_jit.label());
     755        m_jit.movsd_mr(OBJECT_OFFSET(JSNumberCell, m_value), X86::eax, X86::xmm0);
     756        if (opcodeID == op_add)
     757            m_jit.addsd_rr(X86::xmm1, X86::xmm0);
     758        else if (opcodeID == op_sub)
     759            m_jit.subsd_rr(X86::xmm1, X86::xmm0);
     760        else {
     761            ASSERT(opcodeID == op_mul);
     762            m_jit.mulsd_rr(X86::xmm1, X86::xmm0);
     763        }
     764        m_jit.movsd_rm(X86::xmm0, OBJECT_OFFSET(JSNumberCell, m_value), X86::eax);
     765        emitPutResult(dst);
     766
     767        putDoubleResultToJSNumberCellOrJSImmediate(X86::xmm0, X86::eax, dst, &wasJSNumberCell1, X86::xmm1, X86::ecx, X86::edx);
     768        wasJSNumberCell1b = m_jit.emitUnlinkedJmp();
     769
     770        // (2) This handles cases where src1 is an immediate number.
     771        //     Two slow cases - either src2 isn't an immediate, or the subtract overflows.
     772        m_jit.link(op1imm, m_jit.label());
     773        emitJumpSlowCaseIfNotImmNum(X86::edx, i);
     774    } else
     775        emitJumpSlowCaseIfNotImmNums(X86::eax, X86::edx, i);
     776
     777    if (opcodeID == op_add) {
     778        emitFastArithDeTagImmediate(X86::eax);
     779        m_jit.addl_rr(X86::edx, X86::eax);
     780        m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
     781    } else  if (opcodeID == op_sub) {
     782        m_jit.subl_rr(X86::edx, X86::eax);
     783        m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
     784        emitFastArithReTagImmediate(X86::eax);
     785    } else {
     786        ASSERT(opcodeID == op_mul);
     787        emitFastArithDeTagImmediate(X86::eax);
     788        emitFastArithImmToInt(X86::edx);
     789        m_jit.imull_rr(X86::edx, X86::eax);
     790        m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
     791        emitFastArithReTagImmediate(X86::eax);
     792    }
     793    emitPutResult(dst);
     794
     795    if (types.second().isReusable() && isSSE3Present()) {
     796        m_jit.link(wasJSNumberCell2, m_jit.label());
     797        m_jit.link(wasJSNumberCell2b, m_jit.label());
     798    }
     799    else if (types.first().isReusable() && isSSE3Present()) {
     800        m_jit.link(wasJSNumberCell1, m_jit.label());
     801        m_jit.link(wasJSNumberCell1b, m_jit.label());
     802    }
     803}
     804
     805void CTI::compileBinaryArithOpSlowCase(OpcodeID opcodeID, Vector<SlowCaseEntry>::iterator& iter, unsigned dst, unsigned src1, unsigned src2, OperandTypes types, unsigned i)
     806{
     807    X86Assembler::JmpDst here = m_jit.label();
     808    m_jit.link(iter->from, here);
     809    if (types.second().isReusable() && isSSE3Present()) {
     810        if (!types.first().definitelyIsNumber()) {
     811            m_jit.link((++iter)->from, here);
     812            m_jit.link((++iter)->from, here);
     813        }
     814        if (!types.second().definitelyIsNumber()) {
     815            m_jit.link((++iter)->from, here);
     816            m_jit.link((++iter)->from, here);
     817        }
     818        m_jit.link((++iter)->from, here);
     819    } else if (types.first().isReusable() && isSSE3Present()) {
     820        if (!types.first().definitelyIsNumber()) {
     821            m_jit.link((++iter)->from, here);
     822            m_jit.link((++iter)->from, here);
     823        }
     824        if (!types.second().definitelyIsNumber()) {
     825            m_jit.link((++iter)->from, here);
     826            m_jit.link((++iter)->from, here);
     827        }
     828        m_jit.link((++iter)->from, here);
     829    } else
     830        m_jit.link((++iter)->from, here);
     831
     832    emitGetPutArg(src1, 0, X86::ecx);
     833    emitGetPutArg(src2, 4, X86::ecx);
     834    if (opcodeID == op_add)
     835        emitCall(i, Machine::cti_op_add);
     836    else if (opcodeID == op_sub)
     837        emitCall(i, Machine::cti_op_sub);
     838    else {
     839        ASSERT(opcodeID == op_mul);
     840        emitCall(i, Machine::cti_op_mul);
     841    }
     842    emitPutResult(dst);
     843}
     844
    604845void CTI::privateCompileMainPass()
    605846{
     
    633874            unsigned src1 = instruction[i + 2].u.operand;
    634875            unsigned src2 = instruction[i + 3].u.operand;
    635             if (isConstant(src2)) {
    636                 JSValue* value = getConstant(m_exec, src2);
    637                 if (JSImmediate::isNumber(value)) {
    638                     emitGetArg(src1, X86::eax);
    639                     emitJumpSlowCaseIfNotImmNum(X86::eax, i);
    640                     m_jit.addl_i32r(getDeTaggedConstantImmediate(value), X86::eax);
    641                     m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
    642                     emitPutResult(dst);
    643                     i += 4;
    644                     break;
    645                 }
    646             } else if (!isConstant(src1)) {
     876
     877            if (JSValue* value = getConstantImmediateNumericArg(src1)) {
     878                emitGetArg(src2, X86::edx);
     879                emitJumpSlowCaseIfNotImmNum(X86::edx, i);
     880                m_jit.addl_i32r(getDeTaggedConstantImmediate(value), X86::edx);
     881                m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
     882                emitPutResult(dst, X86::edx);
     883            } else if (JSValue* value = getConstantImmediateNumericArg(src2)) {
    647884                emitGetArg(src1, X86::eax);
    648                 emitGetArg(src2, X86::edx);
    649                 emitJumpSlowCaseIfNotImmNums(X86::eax, X86::edx, i);
    650                 emitFastArithDeTagImmediate(X86::eax);
    651                 m_jit.addl_rr(X86::edx, X86::eax);
     885                emitJumpSlowCaseIfNotImmNum(X86::eax, i);
     886                m_jit.addl_i32r(getDeTaggedConstantImmediate(value), X86::eax);
    652887                m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
    653888                emitPutResult(dst);
    654                 i += 4;
    655                 break;
     889            } else {
     890                OperandTypes types = OperandTypes::fromInt(instruction[i + 4].u.operand);
     891                if (types.first().mightBeNumber() && types.second().mightBeNumber())
     892                    compileBinaryArithOp(op_add, instruction[i + 1].u.operand, instruction[i + 2].u.operand, instruction[i + 3].u.operand, OperandTypes::fromInt(instruction[i + 4].u.operand), i);
     893                else {
     894                    emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
     895                    emitGetPutArg(instruction[i + 3].u.operand, 4, X86::ecx);
     896                    emitCall(i, Machine::cti_op_add);
     897                    emitPutResult(instruction[i + 1].u.operand);
     898                }
    656899            }
    657             emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
    658             emitGetPutArg(instruction[i + 3].u.operand, 4, X86::ecx);
    659             emitCall(i, Machine::cti_op_add);
    660             emitPutResult(instruction[i + 1].u.operand);
    661             i += 4;
     900
     901            i += 5;
    662902            break;
    663903        }
     
    8761116            unsigned src1 = instruction[i + 2].u.operand;
    8771117            unsigned src2 = instruction[i + 3].u.operand;
    878             if (isConstant(src1) || isConstant(src2)) {
    879                 unsigned constant = src1;
    880                 unsigned nonconstant = src2;
    881                 if (!isConstant(src1)) {
    882                     constant = src2;
    883                     nonconstant = src1;
    884                 }
    885                 JSValue* value = getConstant(m_exec, constant);
    886                 if (JSImmediate::isNumber(value)) {
    887                     emitGetArg(nonconstant, X86::eax);
    888                     emitJumpSlowCaseIfNotImmNum(X86::eax, i);
    889                     emitFastArithImmToInt(X86::eax);
    890                     m_jit.imull_i32r( X86::eax, getDeTaggedConstantImmediate(value), X86::eax);
    891                     m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
    892                     emitFastArithPotentiallyReTagImmediate(X86::eax);
    893                     emitPutResult(dst);
    894                     i += 4;
    895                     break;
    896                 }
    897             }
    898 
    899             emitGetArg(src1, X86::eax);
    900             emitGetArg(src2, X86::edx);
    901             emitJumpSlowCaseIfNotImmNums(X86::eax, X86::edx, i);
    902             emitFastArithDeTagImmediate(X86::eax);
    903             emitFastArithImmToInt(X86::edx);
    904             m_jit.imull_rr(X86::edx, X86::eax);
    905             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
    906             emitFastArithPotentiallyReTagImmediate(X86::eax);
    907             emitPutResult(dst);
    908             i += 4;
     1118
     1119            if (JSValue* src1Value = getConstantImmediateNumericArg(src1)) {
     1120                emitGetArg(src2, X86::eax);
     1121                emitJumpSlowCaseIfNotImmNum(X86::eax, i);
     1122                emitFastArithImmToInt(X86::eax);
     1123                m_jit.imull_i32r(X86::eax, getDeTaggedConstantImmediate(src1Value), X86::eax);
     1124                m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
     1125                emitFastArithReTagImmediate(X86::eax);
     1126                emitPutResult(dst);
     1127            } else if (JSValue* src2Value = getConstantImmediateNumericArg(src2)) {
     1128                emitGetArg(src1, X86::eax);
     1129                emitJumpSlowCaseIfNotImmNum(X86::eax, i);
     1130                emitFastArithImmToInt(X86::eax);
     1131                m_jit.imull_i32r(X86::eax, getDeTaggedConstantImmediate(src2Value), X86::eax);
     1132                m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
     1133                emitFastArithReTagImmediate(X86::eax);
     1134                emitPutResult(dst);
     1135            } else
     1136                compileBinaryArithOp(op_mul, instruction[i + 1].u.operand, instruction[i + 2].u.operand, instruction[i + 3].u.operand, OperandTypes::fromInt(instruction[i + 4].u.operand), i);
     1137
     1138            i += 5;
    9091139            break;
    9101140        }
     
    10871317        }
    10881318        case op_sub: {
    1089             emitGetArg(instruction[i + 2].u.operand, X86::eax);
    1090             emitGetArg(instruction[i + 3].u.operand, X86::edx);
    1091             emitJumpSlowCaseIfNotImmNums(X86::eax, X86::edx, i);
    1092             m_jit.subl_rr(X86::edx, X86::eax);
    1093             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
    1094             emitFastArithReTagImmediate(X86::eax);
    1095             emitPutResult(instruction[i + 1].u.operand);
    1096             i += 4;
     1319            compileBinaryArithOp(op_sub, instruction[i + 1].u.operand, instruction[i + 2].u.operand, instruction[i + 3].u.operand, OperandTypes::fromInt(instruction[i + 4].u.operand), i);
     1320            i += 5;
    10971321            break;
    10981322        }
     
    13441568                emitPutResult(dst);
    13451569            }
    1346             i += 4;
     1570            i += 5;
    13471571            break;
    13481572        }
     
    14551679            emitFastArithReTagImmediate(X86::eax);
    14561680            emitPutResult(instruction[i + 1].u.operand);
    1457             i += 4;
     1681            i += 5;
    14581682            break;
    14591683        }
     
    14721696            m_jit.orl_rr(X86::edx, X86::eax);
    14731697            emitPutResult(instruction[i + 1].u.operand);
    1474             i += 4;
     1698            i += 5;
    14751699            break;
    14761700        }
     
    18122036        case op_add: {
    18132037            unsigned dst = instruction[i + 1].u.operand;
     2038            unsigned src1 = instruction[i + 2].u.operand;
    18142039            unsigned src2 = instruction[i + 3].u.operand;
    1815             if (isConstant(src2)) {
    1816                 JSValue* value = getConstant(m_exec, src2);
    1817                 if (JSImmediate::isNumber(value)) {
    1818                     X86Assembler::JmpSrc notImm = iter->from;
    1819                     m_jit.link((++iter)->from, m_jit.label());
    1820                     m_jit.subl_i32r(getDeTaggedConstantImmediate(value), X86::eax);
    1821                     m_jit.link(notImm, m_jit.label());
    1822                     emitPutArg(X86::eax, 0);
    1823                     emitGetPutArg(src2, 4, X86::ecx);
    1824                     emitCall(i, Machine::cti_op_add);
    1825                     emitPutResult(dst);
    1826                     i += 4;
    1827                     break;
    1828                 }
     2040            if (JSValue* value = getConstantImmediateNumericArg(src1)) {
     2041                X86Assembler::JmpSrc notImm = iter->from;
     2042                m_jit.link((++iter)->from, m_jit.label());
     2043                m_jit.subl_i32r(getDeTaggedConstantImmediate(value), X86::edx);
     2044                m_jit.link(notImm, m_jit.label());
     2045                emitGetPutArg(src1, 0, X86::ecx);
     2046                emitPutArg(X86::edx, 4);
     2047                emitCall(i, Machine::cti_op_add);
     2048                emitPutResult(dst);
     2049            } else if (JSValue* value = getConstantImmediateNumericArg(src2)) {
     2050                X86Assembler::JmpSrc notImm = iter->from;
     2051                m_jit.link((++iter)->from, m_jit.label());
     2052                m_jit.subl_i32r(getDeTaggedConstantImmediate(value), X86::eax);
     2053                m_jit.link(notImm, m_jit.label());
     2054                emitPutArg(X86::eax, 0);
     2055                emitGetPutArg(src2, 4, X86::ecx);
     2056                emitCall(i, Machine::cti_op_add);
     2057                emitPutResult(dst);
     2058            } else {
     2059                OperandTypes types = OperandTypes::fromInt(instruction[i + 4].u.operand);
     2060                if (types.first().mightBeNumber() && types.second().mightBeNumber())
     2061                    compileBinaryArithOpSlowCase(op_add, iter, dst, src1, src2, types, i);
     2062                else
     2063                    ASSERT_NOT_REACHED();
    18292064            }
    18302065
    1831             ASSERT(!isConstant(instruction[i + 2].u.operand));
    1832 
    1833             X86Assembler::JmpSrc notImm = iter->from;
    1834             m_jit.link((++iter)->from, m_jit.label());
    1835             m_jit.subl_rr(X86::edx, X86::eax);
    1836             emitFastArithReTagImmediate(X86::eax);
    1837             m_jit.link(notImm, m_jit.label());
    1838             emitPutArg(X86::eax, 0);
    1839             emitPutArg(X86::edx, 4);
    1840             emitCall(i, Machine::cti_op_add);
    1841             emitPutResult(dst);
    1842             i += 4;
     2066            i += 5;
    18432067            break;
    18442068        }
     
    18752099        }
    18762100        case op_sub: {
    1877             X86Assembler::JmpSrc notImm = iter->from;
    1878             m_jit.link((++iter)->from, m_jit.label());
    1879             m_jit.addl_rr(X86::edx, X86::eax);
    1880             m_jit.link(notImm, m_jit.label());
    1881             emitPutArg(X86::eax, 0);
    1882             emitPutArg(X86::edx, 4);
    1883             emitCall(i, Machine::cti_op_sub);
    1884             emitPutResult(instruction[i + 1].u.operand);
    1885             i += 4;
     2101            compileBinaryArithOpSlowCase(op_sub, iter, instruction[i + 1].u.operand, instruction[i + 2].u.operand, instruction[i + 3].u.operand, OperandTypes::fromInt(instruction[i + 4].u.operand), i);
     2102            i += 5;
    18862103            break;
    18872104        }
     
    19572174            // so that we only need track one pointer into the slow case code - we track a pointer to the location
    19582175            // of the call (which we can use to look up the repatch information), but should a array-length or
    1959             // prototype access tramopile fail we want to bail out back to here.  To do so we can subtract back
     2176            // prototype access trampoline fail we want to bail out back to here.  To do so we can subtract back
    19602177            // the distance from the call to the head of the slow case.
    19612178
     
    21562373                emitPutResult(dst);
    21572374            }
    2158             i += 4;
     2375            i += 5;
    21592376            break;
    21602377        }
     
    21872404            emitCall(i, Machine::cti_op_bitxor);
    21882405            emitPutResult(instruction[i + 1].u.operand);
    2189             i += 4;
     2406            i += 5;
    21902407            break;
    21912408        }
     
    21962413            emitCall(i, Machine::cti_op_bitor);
    21972414            emitPutResult(instruction[i + 1].u.operand);
    2198             i += 4;
     2415            i += 5;
    21992416            break;
    22002417        }
     
    22442461            break;
    22452462        }
    2246         CTI_COMPILE_BINARY_OP_SLOW_CASE(op_mul);
     2463        case op_mul: {
     2464            int dst = instruction[i + 1].u.operand;
     2465            int src1 = instruction[i + 2].u.operand;
     2466            int src2 = instruction[i + 3].u.operand;
     2467            if (getConstantImmediateNumericArg(src1) || getConstantImmediateNumericArg(src2)) {
     2468                m_jit.link(iter->from, m_jit.label());
     2469                emitGetPutArg(src1, 0, X86::ecx);
     2470                emitGetPutArg(src2, 4, X86::ecx);
     2471                emitCall(i, Machine::cti_op_mul);
     2472                emitPutResult(dst);
     2473            } else
     2474                compileBinaryArithOpSlowCase(op_mul, iter, dst, src1, src2, OperandTypes::fromInt(instruction[i + 4].u.operand), i);
     2475            i += 5;
     2476            break;
     2477        }
     2478
    22472479        case op_call:
    22482480        case op_call_eval:
Note: See TracChangeset for help on using the changeset viewer.