Ignore:
Timestamp:
Jan 1, 2009, 7:06:10 PM (16 years ago)
Author:
[email protected]
Message:

2009-01-01 Gavin Barraclough <[email protected]>

Reviewed by Darin Adler.

Allow 32-bit integers to be stored in JSImmediates, on x64-bit.
Presently the top 32-bits of a 64-bit JSImmediate serve as a sign extension of a 31-bit
int stored in the low word (shifted left by one, to make room for a tag). In the new
format, the top 31-bits serve as a sign extension of a 32-bit int, still shifted left by
one.

The new behavior is enabled using a flag in Platform.h, 'WTF_USE_ALTERNATE_JSIMMEDIATE'.
When this is set the constants defining the range of ints allowed to be stored as
JSImmediate values is extended. The code in JSImmediate.h can safely operate on either
format. This patch updates the JIT so that it can also operate with the new format.

~2% progression on x86-64, with & without the JIT, on sunspider & v8 tests.

  • assembler/MacroAssembler.h: (JSC::MacroAssembler::addPtr): (JSC::MacroAssembler::orPtr): (JSC::MacroAssembler::or32): (JSC::MacroAssembler::rshiftPtr): (JSC::MacroAssembler::rshift32): (JSC::MacroAssembler::subPtr): (JSC::MacroAssembler::xorPtr): (JSC::MacroAssembler::xor32): (JSC::MacroAssembler::move): (JSC::MacroAssembler::compareImm64ForBranch): (JSC::MacroAssembler::compareImm64ForBranchEquality): (JSC::MacroAssembler::jePtr): (JSC::MacroAssembler::jgePtr): (JSC::MacroAssembler::jlPtr): (JSC::MacroAssembler::jlePtr): (JSC::MacroAssembler::jnePtr): (JSC::MacroAssembler::jnzSubPtr): (JSC::MacroAssembler::joAddPtr): (JSC::MacroAssembler::jzSubPtr):
  • assembler/X86Assembler.h: (JSC::X86Assembler::addq_rr): (JSC::X86Assembler::orq_ir): (JSC::X86Assembler::subq_ir): (JSC::X86Assembler::xorq_rr): (JSC::X86Assembler::sarq_CLr): (JSC::X86Assembler::sarq_i8r): (JSC::X86Assembler::cmpq_ir):
  • jit/JIT.cpp: (JSC::JIT::compileOpStrictEq): (JSC::JIT::privateCompileMainPass): (JSC::JIT::privateCompileSlowCases): (JSC::JIT::privateCompileCTIMachineTrampolines):
  • jit/JIT.h:
  • jit/JITArithmetic.cpp: (JSC::JIT::compileFastArith_op_lshift): (JSC::JIT::compileFastArithSlow_op_lshift): (JSC::JIT::compileFastArith_op_rshift): (JSC::JIT::compileFastArithSlow_op_rshift): (JSC::JIT::compileFastArith_op_bitand): (JSC::JIT::compileFastArithSlow_op_bitand): (JSC::JIT::compileFastArith_op_mod): (JSC::JIT::compileFastArithSlow_op_mod): (JSC::JIT::compileFastArith_op_add): (JSC::JIT::compileFastArithSlow_op_add): (JSC::JIT::compileFastArith_op_mul): (JSC::JIT::compileFastArithSlow_op_mul): (JSC::JIT::compileFastArith_op_post_inc): (JSC::JIT::compileFastArithSlow_op_post_inc): (JSC::JIT::compileFastArith_op_post_dec): (JSC::JIT::compileFastArithSlow_op_post_dec): (JSC::JIT::compileFastArith_op_pre_inc): (JSC::JIT::compileFastArithSlow_op_pre_inc): (JSC::JIT::compileFastArith_op_pre_dec): (JSC::JIT::compileFastArithSlow_op_pre_dec): (JSC::JIT::compileBinaryArithOp):
  • jit/JITInlineMethods.h: (JSC::JIT::getConstantOperand): (JSC::JIT::getConstantOperandImmediateInt): (JSC::JIT::isOperandConstantImmediateInt): (JSC::JIT::isOperandConstant31BitImmediateInt): (JSC::JIT::emitFastArithDeTagImmediate): (JSC::JIT::emitFastArithDeTagImmediateJumpIfZero): (JSC::JIT::emitFastArithReTagImmediate): (JSC::JIT::emitFastArithImmToInt): (JSC::JIT::emitFastArithIntToImmNoCheck):
  • runtime/JSImmediate.h: (JSC::JSImmediate::isPositiveNumber): (JSC::JSImmediate::isNegative): (JSC::JSImmediate::rightShiftImmediateNumbers): (JSC::JSImmediate::canDoFastAdditiveOperations): (JSC::JSImmediate::makeValue): (JSC::JSImmediate::makeInt): (JSC::JSImmediate::makeBool): (JSC::JSImmediate::intValue): (JSC::JSImmediate::rawValue): (JSC::JSImmediate::toBoolean): (JSC::JSImmediate::from):
  • wtf/Platform.h:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/assembler/MacroAssembler.h

    r39440 r39540  
    399399 
    400400
     401    // ImmPtr:
     402    //
     403    // A pointer sized immediate operand to an instruction - this is wrapped
     404    // in a class requiring explicit construction in order to differentiate
     405    // from pointers used as absolute addresses to memory operations
     406    struct ImmPtr {
     407        explicit ImmPtr(void* value)
     408            : m_value(value)
     409        {
     410        }
     411
     412        intptr_t asIntptr()
     413        {
     414            return reinterpret_cast<intptr_t>(m_value);
     415        }
     416
     417        void* m_value;
     418    };
     419
     420
    401421    // Imm32:
    402422    //
     
    411431        }
    412432
     433#if PLATFORM(X86)
     434        explicit Imm32(ImmPtr ptr)
     435            : m_value(ptr.asIntptr())
     436        {
     437        }
     438#endif
     439
    413440        int32_t m_value;
    414441    };
    415 
    416     // ImmPtr:
    417     //
    418     // A pointer sized immediate operand to an instruction - this is wrapped
    419     // in a class requiring explicit construction in order to differentiate
    420     // from pointers used as absolute addresses to memory operations
    421     struct ImmPtr {
    422         explicit ImmPtr(void* value)
    423             : m_value(value)
    424         {
    425         }
    426 
    427         void* m_value;
    428     };
    429 
    430442
    431443    // Integer arithmetic operations:
     
    435447    // may often be a memory location (explictly described using an Address
    436448    // object).
     449
     450    void addPtr(RegisterID src, RegisterID dest)
     451    {
     452#if PLATFORM(X86_64)
     453        m_assembler.addq_rr(src, dest);
     454#else
     455        add32(src, dest);
     456#endif
     457    }
    437458
    438459    void addPtr(Imm32 imm, RegisterID srcDest)
     
    559580    }
    560581   
     582    void orPtr(RegisterID src, RegisterID dest)
     583    {
     584#if PLATFORM(X86_64)
     585        m_assembler.orq_rr(src, dest);
     586#else
     587        or32(src, dest);
     588#endif
     589    }
     590
     591    void orPtr(Imm32 imm, RegisterID dest)
     592    {
     593#if PLATFORM(X86_64)
     594        m_assembler.orq_ir(imm.m_value, dest);
     595#else
     596        or32(imm, dest);
     597#endif
     598    }
     599
    561600    void or32(RegisterID src, RegisterID dest)
    562601    {
     
    564603    }
    565604
    566     void orPtr(RegisterID src, RegisterID dest)
    567     {
    568 #if PLATFORM(X86_64)
    569         m_assembler.orq_rr(src, dest);
    570 #else
    571         or32(src, dest);
    572 #endif
    573     }
    574 
    575605    void or32(Imm32 imm, RegisterID dest)
    576606    {
     
    578608    }
    579609
    580     void rshift32(Imm32 imm, RegisterID dest)
    581     {
    582         m_assembler.sarl_i8r(imm.m_value, dest);
     610    void rshiftPtr(RegisterID shift_amount, RegisterID dest)
     611    {
     612#if PLATFORM(X86_64)
     613        // On x86 we can only shift by ecx; if asked to shift by another register we'll
     614        // need rejig the shift amount into ecx first, and restore the registers afterwards.
     615        if (shift_amount != X86::ecx) {
     616            swap(shift_amount, X86::ecx);
     617
     618            // E.g. transform "shll %eax, %eax" -> "xchgl %eax, %ecx; shll %ecx, %ecx; xchgl %eax, %ecx"
     619            if (dest == shift_amount)
     620                m_assembler.sarq_CLr(X86::ecx);
     621            // E.g. transform "shll %eax, %ecx" -> "xchgl %eax, %ecx; shll %ecx, %eax; xchgl %eax, %ecx"
     622            else if (dest == X86::ecx)
     623                m_assembler.sarq_CLr(shift_amount);
     624            // E.g. transform "shll %eax, %ebx" -> "xchgl %eax, %ecx; shll %ecx, %ebx; xchgl %eax, %ecx"
     625            else
     626                m_assembler.sarq_CLr(dest);
     627       
     628            swap(shift_amount, X86::ecx);
     629        } else
     630            m_assembler.sarq_CLr(dest);
     631#else
     632        rshift32(shift_amount, dest);
     633#endif
     634    }
     635
     636    void rshiftPtr(Imm32 imm, RegisterID dest)
     637    {
     638#if PLATFORM(X86_64)
     639        m_assembler.sarq_i8r(imm.m_value, dest);
     640#else
     641        rshift32(imm, dest);
     642#endif
    583643    }
    584644
     
    605665    }
    606666
     667    void rshift32(Imm32 imm, RegisterID dest)
     668    {
     669        m_assembler.sarl_i8r(imm.m_value, dest);
     670    }
     671
     672    void subPtr(Imm32 imm, RegisterID dest)
     673    {
     674#if PLATFORM(X86_64)
     675        m_assembler.subq_ir(imm.m_value, dest);
     676#else
     677        sub32(imm, dest);
     678#endif
     679    }
     680   
    607681    void sub32(Imm32 imm, RegisterID dest)
    608682    {
     
    630704    }
    631705
     706    void xorPtr(RegisterID src, RegisterID dest)
     707    {
     708#if PLATFORM(X86_64)
     709        m_assembler.xorq_rr(src, dest);
     710#else
     711        xor32(src, dest);
     712#endif
     713    }
     714
     715    void xorPtr(Imm32 imm, RegisterID srcDest)
     716    {
     717#if PLATFORM(X86_64)
     718        m_assembler.xorq_ir(imm.m_value, srcDest);
     719#else
     720        xor32(imm, srcDest);
     721#endif
     722    }
     723
    632724    void xor32(RegisterID src, RegisterID dest)
    633725    {
     
    640732    }
    641733   
    642     void xorPtr(Imm32 imm, RegisterID srcDest)
    643     {
    644 #if PLATFORM(X86_64)
    645         m_assembler.xorq_ir(imm.m_value, srcDest);
    646 #else
    647         xor32(imm, srcDest);
    648 #endif
    649     }
    650 
    651734
    652735    // Memory access operations:
     
    766849        storePtr(scratchRegister, address);
    767850#else
    768         m_assembler.movl_i32m(reinterpret_cast<unsigned>(imm.m_value), address.offset, address.base);
     851        m_assembler.movl_i32m(imm.asIntptr(), address.offset, address.base);
    769852#endif
    770853    }
     
    892975    {
    893976#if PLATFORM(X86_64)
    894         m_assembler.movq_i64r(reinterpret_cast<int64_t>(imm.m_value), dest);
    895 #else
    896         m_assembler.movl_i32r(reinterpret_cast<int32_t>(imm.m_value), dest);
     977        if (CAN_SIGN_EXTEND_U32_64(imm.asIntptr()))
     978            m_assembler.movl_i32r(static_cast<int32_t>(imm.asIntptr()), dest);
     979        else
     980            m_assembler.movq_i64r(imm.asIntptr(), dest);
     981#else
     982        m_assembler.movl_i32r(imm.asIntptr(), dest);
    897983#endif
    898984    }
     
    9841070
    9851071#if PLATFORM(X86_64)
     1072    void compareImm64ForBranch(RegisterID left, int32_t right)
     1073    {
     1074        m_assembler.cmpq_ir(right, left);
     1075    }
     1076
     1077    void compareImm64ForBranchEquality(RegisterID reg, int32_t imm)
     1078    {
     1079        if (!imm)
     1080            m_assembler.testq_rr(reg, reg);
     1081        else
     1082            m_assembler.cmpq_ir(imm, reg);
     1083    }
     1084
    9861085    void testImm64(RegisterID reg, Imm32 mask)
    9871086    {
     
    10631162    }
    10641163
    1065     Jump jePtr(RegisterID reg, ImmPtr imm)
    1066     {
    1067 #if PLATFORM(X86_64)
    1068         move(imm, scratchRegister);
    1069         return jePtr(scratchRegister, reg);
    1070 #else
    1071         return je32(reg, Imm32(reinterpret_cast<int32_t>(imm.m_value)));
     1164    Jump jePtr(RegisterID reg, ImmPtr ptr)
     1165    {
     1166#if PLATFORM(X86_64)
     1167        intptr_t imm = ptr.asIntptr();
     1168        if (CAN_SIGN_EXTEND_32_64(imm)) {
     1169            compareImm64ForBranchEquality(reg, imm);
     1170            return Jump(m_assembler.je());
     1171        } else {
     1172            move(ptr, scratchRegister);
     1173            return jePtr(scratchRegister, reg);
     1174        }
     1175#else
     1176        return je32(reg, Imm32(ptr));
    10721177#endif
    10731178    }
     
    10791184        return jePtr(scratchRegister, address);
    10801185#else
    1081         return je32(address, Imm32(reinterpret_cast<int32_t>(imm.m_value)));
     1186        return je32(address, Imm32(imm));
    10821187#endif
    10831188    }
     
    11251230    }
    11261231
     1232    Jump jgePtr(RegisterID left, RegisterID right)
     1233    {
     1234#if PLATFORM(X86_64)
     1235        m_assembler.cmpq_rr(right, left);
     1236        return Jump(m_assembler.jge());
     1237#else
     1238        return jge32(left, right);
     1239#endif
     1240    }
     1241
     1242    Jump jgePtr(RegisterID reg, ImmPtr ptr)
     1243    {
     1244#if PLATFORM(X86_64)
     1245        intptr_t imm = ptr.asIntptr();
     1246        if (CAN_SIGN_EXTEND_32_64(imm)) {
     1247            compareImm64ForBranch(reg, imm);
     1248            return Jump(m_assembler.jge());
     1249        } else {
     1250            move(ptr, scratchRegister);
     1251            return jgePtr(reg, scratchRegister);
     1252        }
     1253#else
     1254        return jge32(reg, Imm32(ptr));
     1255#endif
     1256    }
     1257
    11271258    Jump jge32(RegisterID left, RegisterID right)
    11281259    {
     
    11371268    }
    11381269
     1270    Jump jlPtr(RegisterID left, RegisterID right)
     1271    {
     1272#if PLATFORM(X86_64)
     1273        m_assembler.cmpq_rr(right, left);
     1274        return Jump(m_assembler.jl());
     1275#else
     1276        return jl32(left, right);
     1277#endif
     1278    }
     1279
     1280    Jump jlPtr(RegisterID reg, ImmPtr ptr)
     1281    {
     1282#if PLATFORM(X86_64)
     1283        intptr_t imm = ptr.asIntptr();
     1284        if (CAN_SIGN_EXTEND_32_64(imm)) {
     1285            compareImm64ForBranch(reg, imm);
     1286            return Jump(m_assembler.jl());
     1287        } else {
     1288            move(ptr, scratchRegister);
     1289            return jlPtr(reg, scratchRegister);
     1290        }
     1291#else
     1292        return jl32(reg, Imm32(ptr));
     1293#endif
     1294    }
     1295
    11391296    Jump jl32(RegisterID left, RegisterID right)
    11401297    {
     
    11491306    }
    11501307
     1308    Jump jlePtr(RegisterID left, RegisterID right)
     1309    {
     1310#if PLATFORM(X86_64)
     1311        m_assembler.cmpq_rr(right, left);
     1312        return Jump(m_assembler.jle());
     1313#else
     1314        return jle32(left, right);
     1315#endif
     1316    }
     1317
     1318    Jump jlePtr(RegisterID reg, ImmPtr ptr)
     1319    {
     1320#if PLATFORM(X86_64)
     1321        intptr_t imm = ptr.asIntptr();
     1322        if (CAN_SIGN_EXTEND_32_64(imm)) {
     1323            compareImm64ForBranch(reg, imm);
     1324            return Jump(m_assembler.jle());
     1325        } else {
     1326            move(ptr, scratchRegister);
     1327            return jlePtr(reg, scratchRegister);
     1328        }
     1329#else
     1330        return jle32(reg, Imm32(ptr));
     1331#endif
     1332    }
     1333
    11511334    Jump jle32(RegisterID left, RegisterID right)
    11521335    {
     
    11921375    }
    11931376
    1194     Jump jnePtr(RegisterID reg, ImmPtr imm)
    1195     {
    1196 #if PLATFORM(X86_64)
    1197         move(imm, scratchRegister);
    1198         return jnePtr(scratchRegister, reg);
    1199 #else
    1200         return jne32(reg, Imm32(reinterpret_cast<int32_t>(imm.m_value)));
     1377    Jump jnePtr(RegisterID reg, ImmPtr ptr)
     1378    {
     1379#if PLATFORM(X86_64)
     1380        intptr_t imm = ptr.asIntptr();
     1381        if (CAN_SIGN_EXTEND_32_64(imm)) {
     1382            compareImm64ForBranchEquality(reg, imm);
     1383            return Jump(m_assembler.jne());
     1384        } else {
     1385            move(ptr, scratchRegister);
     1386            return jnePtr(scratchRegister, reg);
     1387        }
     1388#else
     1389        return jne32(reg, Imm32(ptr));
    12011390#endif
    12021391    }
     
    12081397        return jnePtr(scratchRegister, address);
    12091398#else
    1210         return jne32(address, Imm32(reinterpret_cast<int32_t>(imm.m_value)));
     1399        return jne32(address, Imm32(imm));
    12111400#endif
    12121401    }
     
    12151404    Jump jnePtr(AbsoluteAddress address, ImmPtr imm)
    12161405    {
    1217         m_assembler.cmpl_im(reinterpret_cast<uint32_t>(imm.m_value), address.m_ptr);
     1406        m_assembler.cmpl_im(imm.asIntptr(), address.m_ptr);
    12181407        return Jump(m_assembler.jne());
    12191408    }
     
    12231412    {
    12241413#if PLATFORM(X86_64)
    1225         m_assembler.movq_i64r(reinterpret_cast<int64_t>(initialValue.m_value), scratchRegister);
     1414        m_assembler.movq_i64r(initialValue.asIntptr(), scratchRegister);
    12261415        dataLabel = DataLabelPtr(this);
    12271416        return jnePtr(scratchRegister, reg);
    12281417#else
    1229         m_assembler.cmpl_ir_force32(reinterpret_cast<int32_t>(initialValue.m_value), reg);
     1418        m_assembler.cmpl_ir_force32(initialValue.asIntptr(), reg);
    12301419        dataLabel = DataLabelPtr(this);
    12311420        return Jump(m_assembler.jne());
     
    12361425    {
    12371426#if PLATFORM(X86_64)
    1238         m_assembler.movq_i64r(reinterpret_cast<int64_t>(initialValue.m_value), scratchRegister);
     1427        m_assembler.movq_i64r(initialValue.asIntptr(), scratchRegister);
    12391428        dataLabel = DataLabelPtr(this);
    12401429        return jnePtr(scratchRegister, address);
    12411430#else
    1242         m_assembler.cmpl_im_force32(reinterpret_cast<int32_t>(initialValue.m_value), address.offset, address.base);
     1431        m_assembler.cmpl_im_force32(initialValue.asIntptr(), address.offset, address.base);
    12431432        dataLabel = DataLabelPtr(this);
    12441433        return Jump(m_assembler.jne());
     
    14011590    }
    14021591   
     1592    void jnePtr(RegisterID op1, ImmPtr imm, Label target)
     1593    {
     1594        jnePtr(op1, imm).linkTo(target, this);
     1595    }
     1596
    14031597    void jne32(RegisterID op1, RegisterID op2, Label target)
    14041598    {
     
    14431637    //   operation caused an overflow to occur.
    14441638
     1639    Jump jnzSubPtr(Imm32 imm, RegisterID dest)
     1640    {
     1641        subPtr(imm, dest);
     1642        return Jump(m_assembler.jne());
     1643    }
     1644   
    14451645    Jump jnzSub32(Imm32 imm, RegisterID dest)
    14461646    {
     
    14491649    }
    14501650   
     1651    Jump joAddPtr(RegisterID src, RegisterID dest)
     1652    {
     1653        addPtr(src, dest);
     1654        return Jump(m_assembler.jo());
     1655    }
     1656   
    14511657    Jump joAdd32(RegisterID src, RegisterID dest)
    14521658    {
     
    14711677        sub32(imm, dest);
    14721678        return Jump(m_assembler.jo());
     1679    }
     1680   
     1681    Jump jzSubPtr(Imm32 imm, RegisterID dest)
     1682    {
     1683        subPtr(imm, dest);
     1684        return Jump(m_assembler.je());
    14731685    }
    14741686   
Note: See TracChangeset for help on using the changeset viewer.