Changeset 37991 in webkit for trunk/JavaScriptCore
- Timestamp:
- Oct 29, 2008, 9:33:21 PM (17 years ago)
- Location:
- trunk/JavaScriptCore
- Files:
-
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r37990 r37991 1 2008-10-29 Oliver Hunt <[email protected]> 2 3 Reviewed by Geoff Garen. 4 5 Initial work to reduce cost of JSNumberCell allocation 6 7 This does the initial work needed to bring more of number 8 allocation into CTI code directly, rather than just falling 9 back onto the slow paths if we can't guarantee that a number 10 cell can be reused. 11 12 Initial implementation only used by op_negate to make sure 13 it all works. In a negate heavy (though not dominated) test 14 it results in a 10% win in the non-reusable cell case. 15 16 * VM/CTI.cpp: 17 (JSC::): 18 (JSC::CTI::emitAllocateNumber): 19 (JSC::CTI::emitNakedFastCall): 20 (JSC::CTI::emitArithIntToImmWithJump): 21 (JSC::CTI::privateCompileMainPass): 22 (JSC::CTI::privateCompileSlowCases): 23 * VM/CTI.h: 24 * VM/CodeBlock.cpp: 25 (JSC::CodeBlock::dump): 26 * VM/CodeGenerator.cpp: 27 (JSC::CodeGenerator::emitUnaryOp): 28 * VM/CodeGenerator.h: 29 (JSC::CodeGenerator::emitToJSNumber): 30 (JSC::CodeGenerator::emitTypeOf): 31 (JSC::CodeGenerator::emitGetPropertyNames): 32 * VM/Machine.cpp: 33 (JSC::Machine::privateExecute): 34 * VM/Machine.h: 35 * kjs/ResultType.h: 36 (JSC::ResultType::isReusableNumber): 37 (JSC::ResultType::toInt): 38 * kjs/nodes.cpp: 39 (JSC::UnaryOpNode::emitCode): 40 (JSC::BinaryOpNode::emitCode): 41 (JSC::EqualNode::emitCode): 42 * masm/X86Assembler.h: 43 (JSC::X86Assembler::): 44 (JSC::X86Assembler::negl_r): 45 (JSC::X86Assembler::xorpd_mr): 46 * runtime/JSNumberCell.h: 47 (JSC::JSNumberCell::JSNumberCell): 48 1 49 2008-10-29 Steve Falkenburg <[email protected]> 2 50 -
trunk/JavaScriptCore/VM/CTI.cpp
r37930 r37991 312 312 #endif 313 313 314 extern "C" { 315 static JSValue* FASTCALL allocateNumber(JSGlobalData* globalData) { 316 JSValue* result = new (globalData) JSNumberCell(globalData); 317 ASSERT(result); 318 return result; 319 } 320 } 321 322 ALWAYS_INLINE void CTI::emitAllocateNumber(JSGlobalData* globalData, unsigned opcodeIndex) 323 { 324 m_jit.movl_i32r(reinterpret_cast<intptr_t>(globalData), X86::ecx); 325 emitNakedFastCall(opcodeIndex, (void*)allocateNumber); 326 } 327 314 328 ALWAYS_INLINE X86Assembler::JmpSrc CTI::emitNakedCall(unsigned opcodeIndex, X86::RegisterID r) 315 329 { … … 321 335 322 336 ALWAYS_INLINE X86Assembler::JmpSrc CTI::emitNakedCall(unsigned opcodeIndex, void(*function)()) 337 { 338 X86Assembler::JmpSrc call = m_jit.emitCall(); 339 m_calls.append(CallRecord(call, reinterpret_cast<CTIHelper_v>(function), opcodeIndex)); 340 return call; 341 } 342 343 ALWAYS_INLINE X86Assembler::JmpSrc CTI::emitNakedFastCall(unsigned opcodeIndex, void* function) 323 344 { 324 345 X86Assembler::JmpSrc call = m_jit.emitCall(); … … 515 536 m_jit.addl_rr(reg, reg); 516 537 emitFastArithReTagImmediate(reg); 538 } 539 540 ALWAYS_INLINE X86Assembler::JmpSrc CTI::emitArithIntToImmWithJump(X86Assembler::RegisterID reg) 541 { 542 m_jit.addl_rr(reg, reg); 543 X86Assembler::JmpSrc jmp = m_jit.emitUnlinkedJo(); 544 emitFastArithReTagImmediate(reg); 545 return jmp; 517 546 } 518 547 … … 1481 1510 } 1482 1511 case op_negate: { 1483 emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx); 1484 emitCTICall(instruction + i, i, Machine::cti_op_negate); 1485 emitPutResult(instruction[i + 1].u.operand); 1486 i += 3; 1512 emitGetArg(instruction[i + 2].u.operand, X86::eax); 1513 m_jit.testl_i32r(JSImmediate::TagBitTypeInteger, X86::eax); 1514 X86Assembler::JmpSrc notImmediate = m_jit.emitUnlinkedJe(); 1515 1516 m_jit.cmpl_i32r(JSImmediate::TagBitTypeInteger, X86::eax); 1517 X86Assembler::JmpSrc zeroImmediate = m_jit.emitUnlinkedJe(); 1518 emitFastArithImmToInt(X86::eax); 1519 m_jit.negl_r(X86::eax); // This can't overflow as we only have a 31bit int at this point 1520 X86Assembler::JmpSrc overflow = emitArithIntToImmWithJump(X86::eax); 1521 emitPutResult(instruction[i + 1].u.operand); 1522 X86Assembler::JmpSrc immediateNegateSuccess = m_jit.emitUnlinkedJmp(); 1523 1524 if (!isSSE2Present()) { 1525 m_jit.link(zeroImmediate, m_jit.label()); 1526 m_jit.link(overflow, m_jit.label()); 1527 m_jit.link(notImmediate, m_jit.label()); 1528 emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx); 1529 emitCTICall(instruction + i, i, Machine::cti_op_negate); 1530 emitPutResult(instruction[i + 1].u.operand); 1531 } else { 1532 // Slow case immediates 1533 m_slowCases.append(SlowCaseEntry(zeroImmediate, i)); 1534 m_slowCases.append(SlowCaseEntry(overflow, i)); 1535 m_jit.link(notImmediate, m_jit.label()); 1536 ResultType resultType(instruction[i + 3].u.resultType); 1537 if (!resultType.definitelyIsNumber()) { 1538 emitJumpSlowCaseIfNotJSCell(X86::eax, i); 1539 StructureID* numberStructureID = m_callFrame->globalData().numberStructureID.get(); 1540 m_jit.cmpl_i32m(reinterpret_cast<unsigned>(numberStructureID), OBJECT_OFFSET(JSCell, m_structureID), X86::eax); 1541 m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i)); 1542 } 1543 m_jit.movsd_mr(OBJECT_OFFSET(JSNumberCell, m_value), X86::eax, X86::xmm0); 1544 // We need 3 copies of the sign bit mask so we can assure alignment and pad for the 128bit load 1545 static double doubleSignBit[] = { -0.0, -0.0, -0.0 }; 1546 m_jit.xorpd_mr((void*)((((uintptr_t)doubleSignBit)+15)&~15), X86::xmm0); 1547 X86Assembler::JmpSrc wasCell; 1548 if (!resultType.isReusableNumber()) 1549 emitAllocateNumber(&m_callFrame->globalData(), i); 1550 1551 putDoubleResultToJSNumberCellOrJSImmediate(X86::xmm0, X86::eax, instruction[i + 1].u.operand, &wasCell, 1552 X86::xmm1, X86::ecx, X86::edx); 1553 m_jit.link(wasCell, m_jit.label()); 1554 } 1555 m_jit.link(immediateNegateSuccess, m_jit.label()); 1556 i += 4; 1487 1557 break; 1488 1558 } … … 2318 2388 break; 2319 2389 } 2390 case op_negate: { 2391 m_jit.link(iter->from, m_jit.label()); 2392 emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx); 2393 emitCTICall(instruction + i, i, Machine::cti_op_negate); 2394 emitPutResult(instruction[i + 1].u.operand); 2395 i += 4; 2396 break; 2397 } 2320 2398 case op_rshift: { 2321 2399 m_jit.link(iter->from, m_jit.label()); -
trunk/JavaScriptCore/VM/CTI.h
r37891 r37991 84 84 #define CTI_RETURN_ADDRESS_SLOT (ARGS[-1]) 85 85 86 #if COMPILER(MSVC) 87 #define FASTCALL __fastcall 88 #elif COMPILER(GCC) 89 #define FASTCALL __attribute__ ((fastcall)) 90 #else 91 #error Need to support fastcall calling convention in this compiler 92 #endif 93 86 94 namespace JSC { 87 95 … … 406 414 void emitFastArithIntToImmOrSlowCase(X86Assembler::RegisterID, unsigned opcodeIndex); 407 415 void emitFastArithIntToImmNoCheck(X86Assembler::RegisterID); 416 X86Assembler::JmpSrc emitArithIntToImmWithJump(X86Assembler::RegisterID reg); 408 417 409 418 void emitTagAsBoolImmediate(X86Assembler::RegisterID reg); 419 420 void emitAllocateNumber(JSGlobalData*, unsigned); 410 421 411 422 X86Assembler::JmpSrc emitNakedCall(unsigned opcodeIndex, X86::RegisterID); 412 423 X86Assembler::JmpSrc emitNakedCall(unsigned opcodeIndex, void(*function)()); 424 X86Assembler::JmpSrc emitNakedFastCall(unsigned opcodeIndex, void*); 413 425 X86Assembler::JmpSrc emitCTICall(Instruction*, unsigned opcodeIndex, CTIHelper_j); 414 426 X86Assembler::JmpSrc emitCTICall(Instruction*, unsigned opcodeIndex, CTIHelper_o); -
trunk/JavaScriptCore/VM/CodeBlock.cpp
r37951 r37991 469 469 case op_negate: { 470 470 printUnaryOp(location, it, "negate"); 471 ++it; 471 472 break; 472 473 } -
trunk/JavaScriptCore/VM/CodeGenerator.cpp
r37845 r37991 710 710 } 711 711 712 RegisterID* CodeGenerator::emitUnaryOp(OpcodeID opcode, RegisterID* dst, RegisterID* src )712 RegisterID* CodeGenerator::emitUnaryOp(OpcodeID opcode, RegisterID* dst, RegisterID* src, ResultType type) 713 713 { 714 714 emitOpcode(opcode); 715 715 instructions().append(dst->index()); 716 716 instructions().append(src->index()); 717 if (opcode == op_negate) 718 instructions().append(type.toInt()); 717 719 return dst; 718 720 } -
trunk/JavaScriptCore/VM/CodeGenerator.h
r37845 r37991 234 234 RegisterID* emitUnexpectedLoad(RegisterID* dst, double); 235 235 236 RegisterID* emitUnaryOp(OpcodeID, RegisterID* dst, RegisterID* src );236 RegisterID* emitUnaryOp(OpcodeID, RegisterID* dst, RegisterID* src, ResultType); 237 237 RegisterID* emitBinaryOp(OpcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes); 238 238 RegisterID* emitEqualityOp(OpcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2); … … 248 248 RegisterID* emitMove(RegisterID* dst, RegisterID* src); 249 249 250 RegisterID* emitToJSNumber(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_to_jsnumber, dst, src ); }250 RegisterID* emitToJSNumber(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_to_jsnumber, dst, src, ResultType::unknown()); } 251 251 RegisterID* emitPreInc(RegisterID* srcDst); 252 252 RegisterID* emitPreDec(RegisterID* srcDst); … … 255 255 256 256 RegisterID* emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* base, RegisterID* basePrototype); 257 RegisterID* emitTypeOf(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_typeof, dst, src ); }257 RegisterID* emitTypeOf(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_typeof, dst, src, ResultType::unknown()); } 258 258 RegisterID* emitIn(RegisterID* dst, RegisterID* property, RegisterID* base) { return emitBinaryOp(op_in, dst, property, base, OperandTypes()); } 259 259 … … 293 293 void emitSubroutineReturn(RegisterID* retAddrSrc); 294 294 295 RegisterID* emitGetPropertyNames(RegisterID* dst, RegisterID* base) { return emitUnaryOp(op_get_pnames, dst, base ); }295 RegisterID* emitGetPropertyNames(RegisterID* dst, RegisterID* base) { return emitUnaryOp(op_get_pnames, dst, base, ResultType::unknown()); } 296 296 RegisterID* emitNextPropertyName(RegisterID* dst, RegisterID* iter, LabelID* target); 297 297 -
trunk/JavaScriptCore/VM/Instruction.h
r36972 r37991 31 31 32 32 #include "Opcode.h" 33 #include "ResultType.h" 33 34 #include <wtf/VectorTraits.h> 34 35 … … 59 60 StructureIDChain* structureIDChain; 60 61 JSCell* jsCell; 62 ResultType::Type resultType; 61 63 } u; 62 64 }; -
trunk/JavaScriptCore/VM/Machine.cpp
r37894 r37991 1845 1845 int dst = (++vPC)->u.operand; 1846 1846 JSValue* src = callFrame[(++vPC)->u.operand].jsValue(callFrame); 1847 ++vPC; 1847 1848 double v; 1848 1849 if (fastIsNumber(src, v)) -
trunk/JavaScriptCore/VM/Machine.h
r37891 r37991 260 260 static void SFX_CALL cti_op_debug(CTI_ARGS); 261 261 262 static JSValue* SFX_CALL cti_allocate_number(CTI_ARGS); 263 262 264 static JSValue* SFX_CALL cti_vm_throw(CTI_ARGS); 263 265 static void* SFX_CALL cti_vm_compile(CTI_ARGS); -
trunk/JavaScriptCore/kjs/ResultType.h
r36976 r37991 54 54 } 55 55 56 bool isReusableNumber() 57 { 58 return isReusable() && definitelyIsNumber(); 59 } 60 56 61 bool definitelyIsNumber() 57 62 { … … 69 74 } 70 75 76 int toInt() 77 { 78 return static_cast<int>(m_type); 79 } 80 71 81 static ResultType nullType() 72 82 { -
trunk/JavaScriptCore/kjs/nodes.cpp
r37972 r37991 716 716 { 717 717 RegisterID* src = generator.emitNode(m_expr.get()); 718 return generator.emitUnaryOp(opcode(), generator.finalDestination(dst), src );718 return generator.emitUnaryOp(opcode(), generator.finalDestination(dst), src, m_expr->resultDescriptor()); 719 719 } 720 720 … … 727 727 if (m_expr1->isNull() || m_expr2->isNull()) { 728 728 RefPtr<RegisterID> src = generator.emitNode(dst, m_expr1->isNull() ? m_expr2.get() : m_expr1.get()); 729 return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get() );729 return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get(), ResultType::unknown()); 730 730 } 731 731 } … … 740 740 if (m_expr1->isNull() || m_expr2->isNull()) { 741 741 RefPtr<RegisterID> src = generator.emitNode(dst, m_expr1->isNull() ? m_expr2.get() : m_expr1.get()); 742 return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get() );742 return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get(), ResultType::unknown()); 743 743 } 744 744 -
trunk/JavaScriptCore/masm/X86Assembler.h
r37804 r37991 229 229 OP2_CVTTSD2SI_GdWsd = 0x2C, 230 230 OP2_UCOMISD_VsdWsd = 0x2E, 231 OP2_XORPD_VsdWsd = 0x57, 231 232 OP2_ADDSD_VsdWsd = 0x58, 232 233 OP2_MULSD_VsdWsd = 0x59, … … 264 265 265 266 GROUP3_OP_TEST = 0, 267 GROUP3_OP_NEG = 3, 266 268 GROUP3_OP_IDIV = 7, 267 269 … … 606 608 } 607 609 610 void negl_r(RegisterID dst) 611 { 612 m_buffer->putByte(OP_GROUP3_Ev); 613 emitModRm_opr(GROUP3_OP_NEG, dst); 614 } 615 608 616 void cdq() 609 617 { … … 740 748 m_buffer->putByte(OP2_MOVSD_VsdWsd); 741 749 emitModRm_rm((RegisterID)dst, base, offset); 750 } 751 752 void xorpd_mr(void* addr, XMMRegisterID dst) 753 { 754 m_buffer->putByte(PRE_SSE_66); 755 m_buffer->putByte(OP_2BYTE_ESCAPE); 756 m_buffer->putByte(OP2_XORPD_VsdWsd); 757 emitModRm_rm((RegisterID)dst, addr); 742 758 } 743 759 -
trunk/JavaScriptCore/runtime/JSNumberCell.h
r37938 r37991 85 85 static PassRefPtr<StructureID> createStructureID(JSValue* proto) { return StructureID::create(proto, TypeInfo(NumberType, NeedsThisConversion)); } 86 86 87 JSNumberCell(JSGlobalData* globalData) 88 : JSCell(globalData->numberStructureID.get()) 89 { 90 } 91 87 92 private: 88 93 JSNumberCell(JSGlobalData* globalData, double value)
Note:
See TracChangeset
for help on using the changeset viewer.