Changeset 206289 in webkit
- Timestamp:
- Sep 22, 2016 8:50:22 PM (8 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 26 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r206281 r206289 1 2016-09-22 Benjamin Poulain <bpoulain@apple.com> 2 3 [JSC] Use an inline cache to generate op_negate 4 https://bugs.webkit.org/show_bug.cgi?id=162371 5 6 Reviewed by Saam Barati. 7 8 * stress/op-negate-inline-cache.js: Added. 9 1 10 2016-09-22 Mark Lam <mark.lam@apple.com> 2 11 -
trunk/Source/JavaScriptCore/ChangeLog
r206284 r206289 1 2016-09-22 Benjamin Poulain <bpoulain@apple.com> 2 3 [JSC] Use an inline cache to generate op_negate 4 https://bugs.webkit.org/show_bug.cgi?id=162371 5 6 Reviewed by Saam Barati. 7 8 Use an inline cache to reduce the amount of code 9 required to implement op_negate. 10 11 For pure integer negate, the generated asm shrinks 12 from 147 bytes to 125 bytes (14%). 13 For double negate, the generated asm shrinks 14 to 130 bytes (11%). 15 The average size on Sunspider is 100bytes, this is due 16 to the op_negates that are never executed and do not 17 generate much. 18 19 * bytecode/ArithProfile.h: 20 (JSC::ArithProfile::ArithProfile): 21 (JSC::ArithProfile::observeLHS): 22 (JSC::ArithProfile::observeLHSAndRHS): 23 * bytecode/BytecodeList.json: 24 * bytecode/CodeBlock.cpp: 25 (JSC::CodeBlock::addJITNegIC): 26 * bytecode/CodeBlock.h: 27 * bytecompiler/BytecodeGenerator.cpp: 28 (JSC::BytecodeGenerator::emitUnaryOp): 29 * bytecompiler/BytecodeGenerator.h: 30 * bytecompiler/NodesCodegen.cpp: 31 (JSC::UnaryOpNode::emitBytecode): 32 * dfg/DFGSpeculativeJIT.cpp: 33 (JSC::DFG::SpeculativeJIT::compileMathIC): 34 * dfg/DFGSpeculativeJIT.h: 35 * ftl/FTLLowerDFGToB3.cpp: 36 (JSC::FTL::DFG::LowerDFGToB3::compileMathIC): 37 * jit/CCallHelpers.h: 38 (JSC::CCallHelpers::setupArgumentsWithExecState): 39 * jit/JIT.h: 40 * jit/JITArithmetic.cpp: 41 (JSC::JIT::emit_op_negate): 42 (JSC::JIT::emitSlow_op_negate): 43 (JSC::JIT::emitMathICFast): 44 (JSC::JIT::emitMathICSlow): 45 * jit/JITInlines.h: 46 (JSC::JIT::callOperation): 47 * jit/JITMathIC.h: 48 (JSC::JITMathIC::generateInline): 49 (JSC::canGenerateWithBinaryProfile): 50 (JSC::canGenerateWithUnaryProfile): 51 * jit/JITMathICForwards.h: 52 * jit/JITNegGenerator.cpp: 53 (JSC::JITNegGenerator::generateInline): 54 (JSC::JITNegGenerator::generateFastPath): 55 * jit/JITNegGenerator.h: 56 (JSC::JITNegGenerator::JITNegGenerator): 57 (JSC::JITNegGenerator::arithProfile): 58 (JSC::JITNegGenerator::didEmitFastPath): Deleted. 59 (JSC::JITNegGenerator::endJumpList): Deleted. 60 (JSC::JITNegGenerator::slowPathJumpList): Deleted. 61 * jit/JITOperations.cpp: 62 * jit/JITOperations.h: 63 * llint/LowLevelInterpreter.asm: 64 * llint/LowLevelInterpreter32_64.asm: 65 * llint/LowLevelInterpreter64.asm: 66 * runtime/CommonSlowPaths.cpp: 67 (JSC::updateArithProfileForUnaryArithOp): 68 (JSC::SLOW_PATH_DECL): 69 1 70 2016-09-22 Mark Lam <mark.lam@apple.com> 2 71 -
trunk/Source/JavaScriptCore/bytecode/ArithProfile.h
r204373 r206289 88 88 static_assert(specialFastPathBit > ~clearLhsObservedTypeBitMask, "These bits should not intersect and specialFastPathBit should be a higher bit."); 89 89 90 ArithProfile(ResultType arg) 91 { 92 m_bits = (arg.bits() << lhsResultTypeShift); 93 ASSERT(lhsResultType().bits() == arg.bits()); 94 ASSERT(lhsObservedType().isEmpty()); 95 ASSERT(rhsObservedType().isEmpty()); 96 } 97 90 98 ArithProfile(ResultType lhs, ResultType rhs) 91 99 { … … 95 103 ASSERT(rhsObservedType().isEmpty()); 96 104 } 97 ArithProfile() { }105 ArithProfile() = default; 98 106 99 107 static ArithProfile fromInt(uint32_t bits) … … 171 179 void rhsSawNonNumber() { setRhsObservedType(rhsObservedType().withNonNumber()); } 172 180 173 void observeLHS AndRHS(JSValue lhs, JSValue rhs)181 void observeLHS(JSValue lhs) 174 182 { 175 183 ArithProfile newProfile = *this; … … 182 190 newProfile.lhsSawNonNumber(); 183 191 192 m_bits = newProfile.bits(); 193 } 194 195 void observeLHSAndRHS(JSValue lhs, JSValue rhs) 196 { 197 observeLHS(lhs); 198 199 ArithProfile newProfile = *this; 184 200 if (rhs.isNumber()) { 185 201 if (rhs.isInt32()) -
trunk/Source/JavaScriptCore/bytecode/BytecodeList.json
r206098 r206289 34 34 { "name" : "op_to_number", "length" : 4 }, 35 35 { "name" : "op_to_string", "length" : 3 }, 36 { "name" : "op_negate", "length" : 3},36 { "name" : "op_negate", "length" : 4 }, 37 37 { "name" : "op_add", "length" : 5 }, 38 38 { "name" : "op_mul", "length" : 5 }, -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r206098 r206289 3014 3014 { 3015 3015 return m_subICs.add(); 3016 } 3017 3018 JITNegIC* CodeBlock::addJITNegIC() 3019 { 3020 return m_negICs.add(); 3016 3021 } 3017 3022 … … 4355 4360 ArithProfile* CodeBlock::arithProfileForBytecodeOffset(int bytecodeOffset) 4356 4361 { 4357 auto opcodeID = vm()->interpreter->getOpcodeID(instructions()[bytecodeOffset].u.opcode); 4362 return arithProfileForPC(instructions().begin() + bytecodeOffset); 4363 } 4364 4365 ArithProfile* CodeBlock::arithProfileForPC(Instruction* pc) 4366 { 4367 auto opcodeID = vm()->interpreter->getOpcodeID(pc[0].u.opcode); 4358 4368 switch (opcodeID) { 4369 case op_negate: 4370 return bitwise_cast<ArithProfile*>(&pc[3].u.operand); 4359 4371 case op_bitor: 4360 4372 case op_bitand: … … 4364 4376 case op_sub: 4365 4377 case op_div: 4378 return bitwise_cast<ArithProfile*>(&pc[4].u.operand); 4379 default: 4366 4380 break; 4367 default: 4368 return nullptr; 4369 } 4370 4371 return &arithProfileForPC(instructions().begin() + bytecodeOffset); 4372 } 4373 4374 ArithProfile& CodeBlock::arithProfileForPC(Instruction* pc) 4375 { 4376 if (!ASSERT_DISABLED) { 4377 ASSERT(pc >= instructions().begin() && pc < instructions().end()); 4378 auto opcodeID = vm()->interpreter->getOpcodeID(pc[0].u.opcode); 4379 switch (opcodeID) { 4380 case op_bitor: 4381 case op_bitand: 4382 case op_bitxor: 4383 case op_add: 4384 case op_mul: 4385 case op_sub: 4386 case op_div: 4387 break; 4388 default: 4389 ASSERT_NOT_REACHED(); 4390 } 4391 } 4392 4393 return *bitwise_cast<ArithProfile*>(&pc[4].u.operand); 4381 } 4382 4383 return nullptr; 4394 4384 } 4395 4385 … … 4563 4553 double numMuls = 0.0; 4564 4554 double totalMulSize = 0.0; 4555 double numNegs = 0.0; 4556 double totalNegSize = 0.0; 4565 4557 double numSubs = 0.0; 4566 4558 double totalSubSize = 0.0; … … 4575 4567 numMuls++; 4576 4568 totalMulSize += mulIC->codeSize(); 4569 } 4570 4571 for (JITNegIC* negIC : codeBlock->m_negICs) { 4572 numNegs++; 4573 totalNegSize += negIC->codeSize(); 4577 4574 } 4578 4575 … … 4594 4591 dataLog("Average Mul size: ", totalMulSize / numMuls, "\n"); 4595 4592 dataLog("\n"); 4593 dataLog("Num Negs: ", numNegs, "\n"); 4594 dataLog("Total Neg size in bytes: ", totalNegSize, "\n"); 4595 dataLog("Average Neg size: ", totalNegSize / numNegs, "\n"); 4596 dataLog("\n"); 4596 4597 dataLog("Num Subs: ", numSubs, "\n"); 4597 4598 dataLog("Total Sub size in bytes: ", totalSubSize, "\n"); -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.h
r206267 r206289 246 246 JITAddIC* addJITAddIC(); 247 247 JITMulIC* addJITMulIC(); 248 JITNegIC* addJITNegIC(); 248 249 JITSubIC* addJITSubIC(); 249 250 Bag<StructureStubInfo>::iterator stubInfoBegin() { return m_stubInfos.begin(); } … … 448 449 449 450 ArithProfile* arithProfileForBytecodeOffset(int bytecodeOffset); 450 ArithProfile &arithProfileForPC(Instruction*);451 ArithProfile* arithProfileForPC(Instruction*); 451 452 452 453 bool couldTakeSpecialFastCase(int bytecodeOffset); … … 998 999 Bag<JITAddIC> m_addICs; 999 1000 Bag<JITMulIC> m_mulICs; 1001 Bag<JITNegIC> m_negICs; 1000 1002 Bag<JITSubIC> m_subICs; 1001 1003 Bag<ByValInfo> m_byValInfos; -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r206147 r206289 1580 1580 RegisterID* BytecodeGenerator::emitUnaryOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src) 1581 1581 { 1582 ASSERT_WITH_MESSAGE(op_to_number != opcodeID, "op_to_number is profiled."); 1582 ASSERT_WITH_MESSAGE(op_to_number != opcodeID, "op_to_number has a Value Profile."); 1583 ASSERT_WITH_MESSAGE(op_negate != opcodeID, "op_negate has an Arith Profile."); 1583 1584 emitOpcode(opcodeID); 1584 1585 instructions().append(dst->index()); 1585 1586 instructions().append(src->index()); 1587 1588 return dst; 1589 } 1590 1591 RegisterID* BytecodeGenerator::emitUnaryOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src, OperandTypes types) 1592 { 1593 ASSERT_WITH_MESSAGE(op_to_number != opcodeID, "op_to_number has a Value Profile."); 1594 emitOpcode(opcodeID); 1595 instructions().append(dst->index()); 1596 instructions().append(src->index()); 1597 1598 if (opcodeID == op_negate) 1599 instructions().append(ArithProfile(types.first()).bits()); 1586 1600 return dst; 1587 1601 } -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
r206104 r206289 512 512 513 513 RegisterID* emitUnaryOp(OpcodeID, RegisterID* dst, RegisterID* src); 514 RegisterID* emitUnaryOp(OpcodeID, RegisterID* dst, RegisterID* src, OperandTypes); 514 515 RegisterID* emitUnaryOpProfiled(OpcodeID, RegisterID* dst, RegisterID* src); 515 516 RegisterID* emitBinaryOp(OpcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes); -
trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
r206267 r206289 1607 1607 RefPtr<RegisterID> src = generator.emitNode(m_expr); 1608 1608 generator.emitExpressionInfo(position(), position(), position()); 1609 return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src.get() );1609 return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src.get(), OperandTypes(m_expr->resultDescriptor())); 1610 1610 } 1611 1611 -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r206134 r206289 3433 3433 3434 3434 template <typename Generator, typename RepatchingFunction, typename NonRepatchingFunction> 3435 void SpeculativeJIT::compileMathIC(Node* node, JIT MathIC<Generator>* mathIC, bool needsScratchGPRReg, bool needsScratchFPRReg, RepatchingFunction repatchingFunction, NonRepatchingFunction nonRepatchingFunction)3435 void SpeculativeJIT::compileMathIC(Node* node, JITBinaryMathIC<Generator>* mathIC, bool needsScratchGPRReg, bool needsScratchFPRReg, RepatchingFunction repatchingFunction, NonRepatchingFunction nonRepatchingFunction) 3436 3436 { 3437 3437 Edge& leftChild = node->child1(); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r206136 r206289 2516 2516 2517 2517 template <typename Generator, typename RepatchingFunction, typename NonRepatchingFunction> 2518 void compileMathIC(Node*, JIT MathIC<Generator>*, bool needsScratchGPRReg, bool needsScratchFPRReg, RepatchingFunction, NonRepatchingFunction);2518 void compileMathIC(Node*, JITBinaryMathIC<Generator>*, bool needsScratchGPRReg, bool needsScratchFPRReg, RepatchingFunction, NonRepatchingFunction); 2519 2519 2520 2520 void compileArithDoubleUnaryOp(Node*, double (*doubleFunction)(double), double (*operation)(ExecState*, EncodedJSValue)); -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
r206212 r206289 1561 1561 1562 1562 template <typename Generator> 1563 void compileMathIC(JIT MathIC<Generator>* mathIC, FunctionPtr repatchingFunction, FunctionPtr nonRepatchingFunction)1563 void compileMathIC(JITBinaryMathIC<Generator>* mathIC, FunctionPtr repatchingFunction, FunctionPtr nonRepatchingFunction) 1564 1564 { 1565 1565 Node* node = m_node; -
trunk/Source/JavaScriptCore/jit/CCallHelpers.h
r205462 r206289 353 353 354 354 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImmPtr arg3, TrustedImm32 arg4) 355 { 356 resetCallArguments(); 357 addCallArgument(GPRInfo::callFrameRegister); 358 addCallArgument(arg1); 359 addCallArgument(arg2); 360 addCallArgument(arg3); 361 addCallArgument(arg4); 362 } 363 364 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImmPtr arg3, TrustedImmPtr arg4) 355 365 { 356 366 resetCallArguments(); … … 2267 2277 } 2268 2278 #endif 2279 2280 void setupArgumentsWithExecState(JSValueRegs arg) 2281 { 2282 #if USE(JSVALUE64) 2283 setupArgumentsWithExecState(arg.gpr()); 2284 #else 2285 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg.payloadGPR(), arg.tagGPR()); 2286 #endif 2287 } 2269 2288 2270 2289 void setupArgumentsWithExecState(JSValueRegs arg1, JSValueRegs arg2) … … 2277 2296 } 2278 2297 2298 void setupArgumentsWithExecState(JSValueRegs arg1, TrustedImmPtr arg2) 2299 { 2300 #if USE(JSVALUE64) 2301 setupArgumentsWithExecState(arg1.gpr(), arg2); 2302 #else 2303 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1.payloadGPR(), arg1.tagGPR(), arg2); 2304 #endif 2305 } 2306 2279 2307 void setupArgumentsWithExecState(JSValueRegs arg1, JSValueRegs arg2, TrustedImmPtr arg3) 2280 2308 { … … 2292 2320 #else 2293 2321 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1.payloadGPR(), arg1.tagGPR(), arg2.payloadGPR(), arg2.tagGPR(), arg3, arg4); 2322 #endif 2323 } 2324 2325 void setupArgumentsWithExecState(JSValueRegs arg1, TrustedImmPtr arg2, TrustedImmPtr arg3) 2326 { 2327 #if USE(JSVALUE64) 2328 setupArgumentsWithExecState(arg1.gpr(), arg2, arg3); 2329 #else 2330 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1.payloadGPR(), arg1.tagGPR(), arg2, arg3); 2294 2331 #endif 2295 2332 } -
trunk/Source/JavaScriptCore/jit/JIT.h
r206267 r206289 698 698 699 699 template <typename Generator, typename ProfiledFunction, typename NonProfiledFunction> 700 void emitMathICFast(JITMathIC<Generator>*, Instruction*, ProfiledFunction, NonProfiledFunction); 700 void emitMathICFast(JITUnaryMathIC<Generator>*, Instruction*, ProfiledFunction, NonProfiledFunction); 701 template <typename Generator, typename ProfiledFunction, typename NonProfiledFunction> 702 void emitMathICFast(JITBinaryMathIC<Generator>*, Instruction*, ProfiledFunction, NonProfiledFunction); 701 703 702 704 template <typename Generator, typename ProfiledRepatchFunction, typename ProfiledFunction, typename RepatchFunction> 703 void emitMathICSlow(JITMathIC<Generator>*, Instruction*, ProfiledRepatchFunction, ProfiledFunction, RepatchFunction); 705 void emitMathICSlow(JITBinaryMathIC<Generator>*, Instruction*, ProfiledRepatchFunction, ProfiledFunction, RepatchFunction); 706 template <typename Generator, typename ProfiledRepatchFunction, typename ProfiledFunction, typename RepatchFunction> 707 void emitMathICSlow(JITUnaryMathIC<Generator>*, Instruction*, ProfiledRepatchFunction, ProfiledFunction, RepatchFunction); 704 708 705 709 Jump getSlowCase(Vector<SlowCaseEntry>::iterator& iter) … … 746 750 MacroAssembler::Call callOperation(V_JITOperation_EC, JSCell*); 747 751 MacroAssembler::Call callOperation(J_JITOperation_EJ, int, GPRReg); 752 MacroAssembler::Call callOperation(J_JITOperation_EJ, JSValueRegs, JSValueRegs); 748 753 #if USE(JSVALUE64) 749 754 MacroAssembler::Call callOperation(J_JITOperation_ESsiJI, int, StructureStubInfo*, GPRReg, UniquedStringImpl*); … … 755 760 MacroAssembler::Call callOperation(J_JITOperation_EJI, int, GPRReg, UniquedStringImpl*); 756 761 MacroAssembler::Call callOperation(J_JITOperation_EJJ, int, GPRReg, GPRReg); 762 MacroAssembler::Call callOperation(J_JITOperation_EJArp, JSValueRegs, JSValueRegs, ArithProfile*); 757 763 MacroAssembler::Call callOperation(J_JITOperation_EJJArp, JSValueRegs, JSValueRegs, JSValueRegs, ArithProfile*); 758 764 MacroAssembler::Call callOperation(J_JITOperation_EJJ, JSValueRegs, JSValueRegs, JSValueRegs); 759 765 MacroAssembler::Call callOperation(J_JITOperation_EJJArpMic, JSValueRegs, JSValueRegs, JSValueRegs, ArithProfile*, TrustedImmPtr); 766 MacroAssembler::Call callOperation(J_JITOperation_EJMic, JSValueRegs, JSValueRegs, TrustedImmPtr); 760 767 MacroAssembler::Call callOperation(J_JITOperation_EJJMic, JSValueRegs, JSValueRegs, JSValueRegs, TrustedImmPtr); 761 768 MacroAssembler::Call callOperation(J_JITOperation_EJJAp, int, GPRReg, GPRReg, ArrayProfile*); -
trunk/Source/JavaScriptCore/jit/JITArithmetic.cpp
r205364 r206289 470 470 void JIT::emit_op_negate(Instruction* currentInstruction) 471 471 { 472 int result = currentInstruction[1].u.operand; 473 int src = currentInstruction[2].u.operand; 474 475 #if USE(JSVALUE64) 476 JSValueRegs srcRegs = JSValueRegs(regT0); 477 JSValueRegs resultRegs = srcRegs; 478 GPRReg scratchGPR = regT2; 479 #else 480 JSValueRegs srcRegs = JSValueRegs(regT1, regT0); 481 JSValueRegs resultRegs = srcRegs; 482 GPRReg scratchGPR = regT4; 483 #endif 484 485 emitGetVirtualRegister(src, srcRegs); 486 487 JITNegGenerator gen(resultRegs, srcRegs, scratchGPR); 488 gen.generateFastPath(*this); 489 490 ASSERT(gen.didEmitFastPath()); 491 gen.endJumpList().link(this); 492 emitPutVirtualRegister(result, resultRegs); 493 494 addSlowCase(gen.slowPathJumpList()); 472 JITNegIC* negateIC = m_codeBlock->addJITNegIC(); 473 m_instructionToMathIC.add(currentInstruction, negateIC); 474 emitMathICFast(negateIC, currentInstruction, operationArithNegateProfiled, operationArithNegate); 495 475 } 496 476 … … 499 479 linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset); 500 480 501 JIT SlowPathCall slowPathCall(this, currentInstruction, slow_path_negate);502 slowPathCall.call();481 JITNegIC* negIC = bitwise_cast<JITNegIC*>(m_instructionToMathIC.get(currentInstruction)); 482 emitMathICSlow(negIC, currentInstruction, operationArithNegateProfiledOptimize, operationArithNegateProfiled, operationArithNegateOptimize); 503 483 } 504 484 … … 699 679 700 680 template <typename Generator, typename ProfiledFunction, typename NonProfiledFunction> 701 void JIT::emitMathICFast(JITMathIC<Generator>* mathIC, Instruction* currentInstruction, ProfiledFunction profiledFunction, NonProfiledFunction nonProfiledFunction) 681 void JIT::emitMathICFast(JITUnaryMathIC<Generator>* mathIC, Instruction* currentInstruction, ProfiledFunction profiledFunction, NonProfiledFunction nonProfiledFunction) 682 { 683 int result = currentInstruction[1].u.operand; 684 int operand = currentInstruction[2].u.operand; 685 686 #if USE(JSVALUE64) 687 // ArithNegate benefits from using the same register as src and dst. 688 // Since regT1==argumentGPR1, using regT1 avoid shuffling register to call the slow path. 689 JSValueRegs srcRegs = JSValueRegs(regT1); 690 JSValueRegs resultRegs = JSValueRegs(regT1); 691 GPRReg scratchGPR = regT2; 692 #else 693 JSValueRegs srcRegs = JSValueRegs(regT1, regT0); 694 JSValueRegs resultRegs = JSValueRegs(regT3, regT2); 695 GPRReg scratchGPR = regT4; 696 #endif 697 698 #if ENABLE(MATH_IC_STATS) 699 auto inlineStart = label(); 700 #endif 701 702 ArithProfile& arithProfile = *bitwise_cast<ArithProfile*>(¤tInstruction[3].u.operand); 703 mathIC->m_generator = Generator(resultRegs, srcRegs, scratchGPR, arithProfile); 704 705 emitGetVirtualRegister(operand, srcRegs); 706 707 MathICGenerationState& mathICGenerationState = m_instructionToMathICGenerationState.add(currentInstruction, MathICGenerationState()).iterator->value; 708 709 bool generatedInlineCode = mathIC->generateInline(*this, mathICGenerationState); 710 if (!generatedInlineCode) { 711 if (shouldEmitProfiling()) 712 callOperation(profiledFunction, resultRegs, srcRegs, &arithProfile); 713 else 714 callOperation(nonProfiledFunction, resultRegs, srcRegs); 715 } else 716 addSlowCase(mathICGenerationState.slowPathJumps); 717 718 #if ENABLE(MATH_IC_STATS) 719 auto inlineEnd = label(); 720 addLinkTask([=] (LinkBuffer& linkBuffer) { 721 size_t size = static_cast<char*>(linkBuffer.locationOf(inlineEnd).executableAddress()) - static_cast<char*>(linkBuffer.locationOf(inlineStart).executableAddress()); 722 mathIC->m_generatedCodeSize += size; 723 }); 724 #endif 725 726 emitPutVirtualRegister(result, resultRegs); 727 } 728 729 template <typename Generator, typename ProfiledFunction, typename NonProfiledFunction> 730 void JIT::emitMathICFast(JITBinaryMathIC<Generator>* mathIC, Instruction* currentInstruction, ProfiledFunction profiledFunction, NonProfiledFunction nonProfiledFunction) 702 731 { 703 732 int result = currentInstruction[1].u.operand; … … 723 752 ArithProfile* arithProfile = nullptr; 724 753 if (shouldEmitProfiling()) 725 arithProfile = &m_codeBlock->arithProfileForPC(currentInstruction);754 arithProfile = m_codeBlock->arithProfileForPC(currentInstruction); 726 755 727 756 SnippetOperand leftOperand(types.first()); … … 775 804 776 805 template <typename Generator, typename ProfiledRepatchFunction, typename ProfiledFunction, typename RepatchFunction> 777 void JIT::emitMathICSlow(JITMathIC<Generator>* mathIC, Instruction* currentInstruction, ProfiledRepatchFunction profiledRepatchFunction, ProfiledFunction profiledFunction, RepatchFunction repatchFunction) 806 void JIT::emitMathICSlow(JITUnaryMathIC<Generator>* mathIC, Instruction* currentInstruction, ProfiledRepatchFunction profiledRepatchFunction, ProfiledFunction profiledFunction, RepatchFunction repatchFunction) 807 { 808 MathICGenerationState& mathICGenerationState = m_instructionToMathICGenerationState.find(currentInstruction)->value; 809 mathICGenerationState.slowPathStart = label(); 810 811 int result = currentInstruction[1].u.operand; 812 813 #if USE(JSVALUE64) 814 JSValueRegs srcRegs = JSValueRegs(regT1); 815 JSValueRegs resultRegs = JSValueRegs(regT0); 816 #else 817 JSValueRegs srcRegs = JSValueRegs(regT1, regT0); 818 JSValueRegs resultRegs = JSValueRegs(regT3, regT2); 819 #endif 820 821 #if ENABLE(MATH_IC_STATS) 822 auto slowPathStart = label(); 823 #endif 824 825 if (shouldEmitProfiling()) { 826 ArithProfile* arithProfile = bitwise_cast<ArithProfile*>(¤tInstruction[3].u.operand); 827 if (mathICGenerationState.shouldSlowPathRepatch) 828 mathICGenerationState.slowPathCall = callOperation(reinterpret_cast<J_JITOperation_EJMic>(profiledRepatchFunction), resultRegs, srcRegs, TrustedImmPtr(mathIC)); 829 else 830 mathICGenerationState.slowPathCall = callOperation(profiledFunction, resultRegs, srcRegs, arithProfile); 831 } else 832 mathICGenerationState.slowPathCall = callOperation(reinterpret_cast<J_JITOperation_EJMic>(repatchFunction), resultRegs, srcRegs, TrustedImmPtr(mathIC)); 833 834 #if ENABLE(MATH_IC_STATS) 835 auto slowPathEnd = label(); 836 addLinkTask([=] (LinkBuffer& linkBuffer) { 837 size_t size = static_cast<char*>(linkBuffer.locationOf(slowPathEnd).executableAddress()) - static_cast<char*>(linkBuffer.locationOf(slowPathStart).executableAddress()); 838 mathIC->m_generatedCodeSize += size; 839 }); 840 #endif 841 842 emitPutVirtualRegister(result, resultRegs); 843 844 addLinkTask([=] (LinkBuffer& linkBuffer) { 845 MathICGenerationState& mathICGenerationState = m_instructionToMathICGenerationState.find(currentInstruction)->value; 846 mathIC->finalizeInlineCode(mathICGenerationState, linkBuffer); 847 }); 848 } 849 850 template <typename Generator, typename ProfiledRepatchFunction, typename ProfiledFunction, typename RepatchFunction> 851 void JIT::emitMathICSlow(JITBinaryMathIC<Generator>* mathIC, Instruction* currentInstruction, ProfiledRepatchFunction profiledRepatchFunction, ProfiledFunction profiledFunction, RepatchFunction repatchFunction) 778 852 { 779 853 MathICGenerationState& mathICGenerationState = m_instructionToMathICGenerationState.find(currentInstruction)->value; … … 816 890 817 891 if (shouldEmitProfiling()) { 818 ArithProfile& arithProfile = m_codeBlock->arithProfileForPC(currentInstruction);892 ArithProfile& arithProfile = *m_codeBlock->arithProfileForPC(currentInstruction); 819 893 if (mathICGenerationState.shouldSlowPathRepatch) 820 894 mathICGenerationState.slowPathCall = callOperation(bitwise_cast<J_JITOperation_EJJArpMic>(profiledRepatchFunction), resultRegs, leftRegs, rightRegs, &arithProfile, TrustedImmPtr(mathIC)); … … 863 937 ArithProfile* arithProfile = nullptr; 864 938 if (shouldEmitProfiling()) 865 arithProfile = &m_codeBlock->arithProfileForPC(currentInstruction);939 arithProfile = m_codeBlock->arithProfileForPC(currentInstruction); 866 940 867 941 SnippetOperand leftOperand(types.first()); -
trunk/Source/JavaScriptCore/jit/JITInlines.h
r204840 r206289 417 417 } 418 418 419 ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJ operation, JSValueRegs result, JSValueRegs arg) 420 { 421 setupArgumentsWithExecState(arg); 422 Call call = appendCallWithExceptionCheck(operation); 423 setupResults(result); 424 return call; 425 } 426 419 427 ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJJ operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2) 420 428 { … … 425 433 } 426 434 435 ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJArp operation, JSValueRegs result, JSValueRegs operand, ArithProfile* arithProfile) 436 { 437 setupArgumentsWithExecState(operand, TrustedImmPtr(arithProfile)); 438 Call call = appendCallWithExceptionCheck(operation); 439 setupResults(result); 440 return call; 441 } 442 427 443 ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJJArp operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2, ArithProfile* arithProfile) 428 444 { … … 436 452 { 437 453 setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(arithProfile), mathIC); 454 Call call = appendCallWithExceptionCheck(operation); 455 setupResults(result); 456 return call; 457 } 458 459 ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJMic operation, JSValueRegs result, JSValueRegs arg, TrustedImmPtr mathIC) 460 { 461 setupArgumentsWithExecState(arg, mathIC); 438 462 Call call = appendCallWithExceptionCheck(operation); 439 463 setupResults(result); -
trunk/Source/JavaScriptCore/jit/JITMathIC.h
r205364 r206289 33 33 #include "JITMathICInlineResult.h" 34 34 #include "JITMulGenerator.h" 35 #include "JITNegGenerator.h" 35 36 #include "JITSubGenerator.h" 36 37 #include "LinkBuffer.h" … … 53 54 #define ENABLE_MATH_IC_STATS 0 54 55 55 template <typename GeneratorType >56 template <typename GeneratorType, bool(*isProfileEmpty)(ArithProfile*)> 56 57 class JITMathIC { 57 58 public: … … 73 74 74 75 if (ArithProfile* arithProfile = m_generator.arithProfile()) { 75 if ( arithProfile->lhsObservedType().isEmpty() || arithProfile->rhsObservedType().isEmpty()) {76 if (!isProfileEmpty(arithProfile)) { 76 77 // It looks like the MathIC has yet to execute. We don't want to emit code in this 77 78 // case for a couple reasons. First, the operation may never execute, so if we don't emit 78 79 // code, it's a win. Second, if the operation does execute, we can emit better code 79 // once we have an idea about the types of lhs and rhs.80 // once we have an idea about the types. 80 81 state.slowPathJumps.append(jit.patchableJump()); 81 82 size_t inlineSize = jit.m_assembler.buffer().codeSize() - startSize; … … 83 84 state.shouldSlowPathRepatch = true; 84 85 state.fastPathEnd = jit.label(); 85 ASSERT(!m_generateFastPathOnRepatch); // We should have gathered some observed type info for lhs and rhs before trying to regenerate again.86 ASSERT(!m_generateFastPathOnRepatch); // We should have gathered some observed type info about the types before trying to regenerate again. 86 87 m_generateFastPathOnRepatch = true; 87 88 return true; … … 244 245 }; 245 246 246 typedef JITMathIC<JITAddGenerator> JITAddIC; 247 typedef JITMathIC<JITMulGenerator> JITMulIC; 248 typedef JITMathIC<JITSubGenerator> JITSubIC; 247 inline bool canGenerateWithBinaryProfile(ArithProfile* arithProfile) 248 { 249 return !arithProfile->lhsObservedType().isEmpty() && !arithProfile->rhsObservedType().isEmpty(); 250 } 251 template <typename GeneratorType> 252 class JITBinaryMathIC : public JITMathIC<GeneratorType, canGenerateWithBinaryProfile> { }; 253 254 typedef JITBinaryMathIC<JITAddGenerator> JITAddIC; 255 typedef JITBinaryMathIC<JITMulGenerator> JITMulIC; 256 typedef JITBinaryMathIC<JITSubGenerator> JITSubIC; 257 258 259 inline bool canGenerateWithUnaryProfile(ArithProfile* arithProfile) 260 { 261 return !arithProfile->lhsObservedType().isEmpty(); 262 } 263 template <typename GeneratorType> 264 class JITUnaryMathIC : public JITMathIC<GeneratorType, canGenerateWithUnaryProfile> { }; 265 266 typedef JITUnaryMathIC<JITNegGenerator> JITNegIC; 249 267 250 268 } // namespace JSC -
trunk/Source/JavaScriptCore/jit/JITMathICForwards.h
r203979 r206289 30 30 namespace JSC { 31 31 32 template <typename Generator> class JITMathIC; 32 template <typename Generator> class JITBinaryMathIC; 33 template <typename Generator> class JITUnaryMathIC; 33 34 class JITAddGenerator; 34 35 class JITMulGenerator; 36 class JITNegGenerator; 35 37 class JITSubGenerator; 36 38 37 typedef JITMathIC<JITAddGenerator> JITAddIC; 38 typedef JITMathIC<JITMulGenerator> JITMulIC; 39 typedef JITMathIC<JITSubGenerator> JITSubIC; 39 typedef JITBinaryMathIC<JITAddGenerator> JITAddIC; 40 typedef JITBinaryMathIC<JITMulGenerator> JITMulIC; 41 typedef JITUnaryMathIC<JITNegGenerator> JITNegIC; 42 typedef JITBinaryMathIC<JITSubGenerator> JITSubIC; 40 43 41 44 } // namespace JSC -
trunk/Source/JavaScriptCore/jit/JITNegGenerator.cpp
r194363 r206289 1 1 /* 2 * Copyright (C) 2015 Apple Inc. All rights reserved.2 * Copyright (C) 2015, 2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 27 27 #include "JITNegGenerator.h" 28 28 29 #include "ArithProfile.h" 30 29 31 #if ENABLE(JIT) 30 32 31 33 namespace JSC { 32 34 33 void JITNegGenerator::generateFastPath(CCallHelpers& jit) 35 JITMathICInlineResult JITNegGenerator::generateInline(CCallHelpers& jit, MathICGenerationState& state) 36 { 37 ASSERT(m_scratchGPR != InvalidGPRReg); 38 ASSERT(m_scratchGPR != m_src.payloadGPR()); 39 ASSERT(m_scratchGPR != m_result.payloadGPR()); 40 #if USE(JSVALUE32_64) 41 ASSERT(m_scratchGPR != m_src.tagGPR()); 42 ASSERT(m_scratchGPR != m_result.tagGPR()); 43 #endif 44 45 ObservedType observedTypes = m_arithProfile->lhsObservedType(); 46 ASSERT_WITH_MESSAGE(!observedTypes.isEmpty(), "We should not attempt to generate anything if we do not have a profile."); 47 48 if (observedTypes.isOnlyNonNumber()) 49 return JITMathICInlineResult::DontGenerate; 50 51 if (observedTypes.isOnlyInt32()) { 52 jit.moveValueRegs(m_src, m_result); 53 state.slowPathJumps.append(jit.branchIfNotInt32(m_src)); 54 state.slowPathJumps.append(jit.branchTest32(CCallHelpers::Zero, m_src.payloadGPR(), CCallHelpers::TrustedImm32(0x7fffffff))); 55 jit.neg32(m_result.payloadGPR()); 56 #if USE(JSVALUE64) 57 jit.boxInt32(m_result.payloadGPR(), m_result); 58 #endif 59 60 return JITMathICInlineResult::GeneratedFastPath; 61 } 62 if (observedTypes.isOnlyNumber()) { 63 state.slowPathJumps.append(jit.branchIfInt32(m_src)); 64 state.slowPathJumps.append(jit.branchIfNotNumber(m_src, m_scratchGPR)); 65 #if USE(JSVALUE64) 66 if (m_src.payloadGPR() != m_result.payloadGPR()) { 67 jit.move(CCallHelpers::TrustedImm64(static_cast<int64_t>(1ull << 63)), m_result.payloadGPR()); 68 jit.xor64(m_src.payloadGPR(), m_result.payloadGPR()); 69 } else { 70 jit.move(CCallHelpers::TrustedImm64(static_cast<int64_t>(1ull << 63)), m_scratchGPR); 71 jit.xor64(m_scratchGPR, m_result.payloadGPR()); 72 } 73 #else 74 jit.moveValueRegs(m_src, m_result); 75 jit.xor32(CCallHelpers::TrustedImm32(1 << 31), m_result.tagGPR()); 76 #endif 77 return JITMathICInlineResult::GeneratedFastPath; 78 } 79 return JITMathICInlineResult::GenerateFullSnippet; 80 } 81 82 bool JITNegGenerator::generateFastPath(CCallHelpers& jit, CCallHelpers::JumpList& endJumpList, CCallHelpers::JumpList& slowPathJumpList, bool) 34 83 { 35 84 ASSERT(m_scratchGPR != m_src.payloadGPR()); … … 41 90 #endif 42 91 43 m_didEmitFastPath = true;44 45 92 jit.moveValueRegs(m_src, m_result); 46 93 CCallHelpers::Jump srcNotInt = jit.branchIfNotInt32(m_src); … … 48 95 // -0 should produce a double, and hence cannot be negated as an int. 49 96 // The negative int32 0x80000000 doesn't have a positive int32 representation, and hence cannot be negated as an int. 50 m_slowPathJumpList.append(jit.branchTest32(CCallHelpers::Zero, m_src.payloadGPR(), CCallHelpers::TrustedImm32(0x7fffffff)));97 slowPathJumpList.append(jit.branchTest32(CCallHelpers::Zero, m_src.payloadGPR(), CCallHelpers::TrustedImm32(0x7fffffff))); 51 98 52 99 jit.neg32(m_result.payloadGPR()); … … 54 101 jit.boxInt32(m_result.payloadGPR(), m_result); 55 102 #endif 56 m_endJumpList.append(jit.jump());103 endJumpList.append(jit.jump()); 57 104 58 105 srcNotInt.link(&jit); 59 m_slowPathJumpList.append(jit.branchIfNotNumber(m_src, m_scratchGPR));106 slowPathJumpList.append(jit.branchIfNotNumber(m_src, m_scratchGPR)); 60 107 61 108 // For a double, all we need to do is to invert the sign bit. … … 66 113 jit.xor32(CCallHelpers::TrustedImm32(1 << 31), m_result.tagGPR()); 67 114 #endif 115 return true; 68 116 } 69 117 -
trunk/Source/JavaScriptCore/jit/JITNegGenerator.h
r194363 r206289 1 1 /* 2 * Copyright (C) 2015 Apple Inc. All rights reserved.2 * Copyright (C) 2015, 2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 30 30 31 31 #include "CCallHelpers.h" 32 #include "SnippetOperand.h" 32 #include "JITMathIC.h" 33 #include "JITMathICInlineResult.h" 33 34 34 35 namespace JSC { … … 36 37 class JITNegGenerator { 37 38 public: 38 JITNegGenerator(JSValueRegs result, JSValueRegs src, GPRReg scratchGPR) 39 : m_result(result) 39 JITNegGenerator() = default; 40 41 JITNegGenerator(JSValueRegs result, JSValueRegs src, GPRReg scratchGPR, ArithProfile& arithProfile) 42 : m_arithProfile(&arithProfile) 43 , m_result(result) 40 44 , m_src(src) 41 45 , m_scratchGPR(scratchGPR) 42 46 { } 43 47 44 void generateFastPath(CCallHelpers&); 48 JITMathICInlineResult generateInline(CCallHelpers&, MathICGenerationState&); 49 bool generateFastPath(CCallHelpers&, CCallHelpers::JumpList& endJumpList, CCallHelpers::JumpList& slowPathJumpList, bool shouldEmitProfiling); 45 50 46 bool didEmitFastPath() const { return m_didEmitFastPath; } 47 CCallHelpers::JumpList& endJumpList() { return m_endJumpList; } 48 CCallHelpers::JumpList& slowPathJumpList() { return m_slowPathJumpList; } 51 ArithProfile* arithProfile() const { return m_arithProfile; } 49 52 50 53 private: 54 ArithProfile* m_arithProfile { nullptr }; 51 55 JSValueRegs m_result; 52 56 JSValueRegs m_src; 53 57 GPRReg m_scratchGPR; 54 bool m_didEmitFastPath { false };55 56 CCallHelpers::JumpList m_endJumpList;57 CCallHelpers::JumpList m_slowPathJumpList;58 58 }; 59 59 -
trunk/Source/JavaScriptCore/jit/JITOperations.cpp
r206267 r206289 2470 2470 } 2471 2471 2472 ALWAYS_INLINE static EncodedJSValue unprofiledNegate(ExecState* exec, EncodedJSValue encodedOperand) 2473 { 2474 VM& vm = exec->vm(); 2475 auto scope = DECLARE_THROW_SCOPE(vm); 2476 NativeCallFrameTracer tracer(&vm, exec); 2477 2478 JSValue operand = JSValue::decode(encodedOperand); 2479 double number = operand.toNumber(exec); 2480 if (UNLIKELY(scope.exception())) 2481 return JSValue::encode(JSValue()); 2482 return JSValue::encode(jsNumber(-number)); 2483 } 2484 2485 ALWAYS_INLINE static EncodedJSValue profiledNegate(ExecState* exec, EncodedJSValue encodedOperand, ArithProfile* arithProfile) 2486 { 2487 ASSERT(arithProfile); 2488 VM& vm = exec->vm(); 2489 auto scope = DECLARE_THROW_SCOPE(vm); 2490 NativeCallFrameTracer tracer(&vm, exec); 2491 2492 JSValue operand = JSValue::decode(encodedOperand); 2493 arithProfile->observeLHS(operand); 2494 double number = operand.toNumber(exec); 2495 if (UNLIKELY(scope.exception())) 2496 return JSValue::encode(JSValue()); 2497 return JSValue::encode(jsNumber(-number)); 2498 } 2499 2500 EncodedJSValue JIT_OPERATION operationArithNegate(ExecState* exec, EncodedJSValue operand) 2501 { 2502 return unprofiledNegate(exec, operand); 2503 } 2504 2505 EncodedJSValue JIT_OPERATION operationArithNegateProfiled(ExecState* exec, EncodedJSValue operand, ArithProfile* arithProfile) 2506 { 2507 return profiledNegate(exec, operand, arithProfile); 2508 } 2509 2510 EncodedJSValue JIT_OPERATION operationArithNegateProfiledOptimize(ExecState* exec, EncodedJSValue encodedOperand, JITNegIC* negIC) 2511 { 2512 VM& vm = exec->vm(); 2513 auto scope = DECLARE_THROW_SCOPE(vm); 2514 NativeCallFrameTracer tracer(&vm, exec); 2515 2516 JSValue operand = JSValue::decode(encodedOperand); 2517 2518 ArithProfile* arithProfile = negIC->m_generator.arithProfile(); 2519 ASSERT(arithProfile); 2520 arithProfile->observeLHS(operand); 2521 negIC->generateOutOfLine(vm, exec->codeBlock(), operationArithNegateProfiled); 2522 2523 #if ENABLE(MATH_IC_STATS) 2524 exec->codeBlock()->dumpMathICStats(); 2525 #endif 2526 2527 double number = operand.toNumber(exec); 2528 if (UNLIKELY(scope.exception())) 2529 return JSValue::encode(JSValue()); 2530 return JSValue::encode(jsNumber(-number)); 2531 } 2532 2533 EncodedJSValue JIT_OPERATION operationArithNegateOptimize(ExecState* exec, EncodedJSValue encodedOperand, JITNegIC* negIC) 2534 { 2535 VM& vm = exec->vm(); 2536 auto scope = DECLARE_THROW_SCOPE(vm); 2537 NativeCallFrameTracer tracer(&vm, exec); 2538 2539 JSValue operand = JSValue::decode(encodedOperand); 2540 2541 ArithProfile* arithProfile = negIC->m_generator.arithProfile(); 2542 ASSERT(arithProfile); 2543 arithProfile->observeLHS(operand); 2544 negIC->generateOutOfLine(vm, exec->codeBlock(), operationArithNegate); 2545 2546 #if ENABLE(MATH_IC_STATS) 2547 exec->codeBlock()->dumpMathICStats(); 2548 #endif 2549 2550 double number = operand.toNumber(exec); 2551 if (UNLIKELY(scope.exception())) 2552 return JSValue::encode(JSValue()); 2553 return JSValue::encode(jsNumber(-number)); 2554 } 2555 2472 2556 ALWAYS_INLINE static EncodedJSValue unprofiledSub(VM& vm, ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) 2473 2557 { -
trunk/Source/JavaScriptCore/jit/JITOperations.h
r206136 r206289 141 141 typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJC)(ExecState*, EncodedJSValue, JSCell*); 142 142 typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJA)(ExecState*, EncodedJSValue, JSArray*); 143 typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJArp)(ExecState*, EncodedJSValue, ArithProfile*); 143 144 typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJI)(ExecState*, EncodedJSValue, UniquedStringImpl*); 144 145 typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJJ)(ExecState*, EncodedJSValue, EncodedJSValue); … … 150 151 typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJJArpMic)(ExecState*, EncodedJSValue, EncodedJSValue, ArithProfile*, void*); 151 152 typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJJMic)(ExecState*, EncodedJSValue, EncodedJSValue, void*); 153 typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJMic)(ExecState*, EncodedJSValue, void*); 152 154 typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJssZ)(ExecState*, JSString*, int32_t); 153 155 typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJssReo)(ExecState*, JSString*, RegExpObject*); … … 438 440 EncodedJSValue JIT_OPERATION operationValueMulProfiledNoOptimize(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile*, JITMulIC*) WTF_INTERNAL; 439 441 EncodedJSValue JIT_OPERATION operationValueMulProfiled(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile*) WTF_INTERNAL; 442 EncodedJSValue JIT_OPERATION operationArithNegate(ExecState*, EncodedJSValue operand); 443 EncodedJSValue JIT_OPERATION operationArithNegateProfiled(ExecState*, EncodedJSValue operand, ArithProfile*); 444 EncodedJSValue JIT_OPERATION operationArithNegateProfiledOptimize(ExecState*, EncodedJSValue encodedOperand, JITNegIC*); 445 EncodedJSValue JIT_OPERATION operationArithNegateOptimize(ExecState*, EncodedJSValue encodedOperand, JITNegIC*); 440 446 EncodedJSValue JIT_OPERATION operationValueSub(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL; 441 447 EncodedJSValue JIT_OPERATION operationValueSubProfiled(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile*) WTF_INTERNAL; -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm
r206065 r206289 254 254 255 255 # ArithProfile data 256 const ArithProfileInt = 0x100000 256 257 const ArithProfileIntInt = 0x120000 258 const ArithProfileNumber = 0x200000 257 259 const ArithProfileNumberInt = 0x220000 258 260 const ArithProfileNumberNumber = 0x240000 -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
r206098 r206289 949 949 loadi 4[PC], t3 950 950 loadConstantOrVariable(t0, t1, t2) 951 loadisFromInstruction(3, t0) 951 952 bineq t1, Int32Tag, .opNegateSrcNotInt 952 953 btiz t2, 0x7fffffff, .opNegateSlow 953 954 negi t2 955 ori ArithProfileInt, t0 954 956 storei Int32Tag, TagOffset[cfr, t3, 8] 957 storeisToInstruction(t0, 3) 955 958 storei t2, PayloadOffset[cfr, t3, 8] 956 dispatch( 3)959 dispatch(4) 957 960 .opNegateSrcNotInt: 958 961 bia t1, LowestTag, .opNegateSlow 959 962 xori 0x80000000, t1 963 ori ArithProfileNumber, t0 964 storei t2, PayloadOffset[cfr, t3, 8] 965 storeisToInstruction(t0, 3) 960 966 storei t1, TagOffset[cfr, t3, 8] 961 storei t2, PayloadOffset[cfr, t3, 8] 962 dispatch(3) 967 dispatch(4) 963 968 964 969 .opNegateSlow: 965 970 callOpcodeSlowPath(_slow_path_negate) 966 dispatch( 3)971 dispatch(4) 967 972 968 973 -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
r206128 r206289 828 828 loadisFromInstruction(2, t0) 829 829 loadisFromInstruction(1, t1) 830 loadConstantOrVariable(t0, t2) 831 bqb t2, tagTypeNumber, .opNegateNotInt 832 btiz t2, 0x7fffffff, .opNegateSlow 833 negi t2 834 orq tagTypeNumber, t2 835 storeq t2, [cfr, t1, 8] 836 dispatch(3) 830 loadConstantOrVariable(t0, t3) 831 loadisFromInstruction(3, t2) 832 bqb t3, tagTypeNumber, .opNegateNotInt 833 btiz t3, 0x7fffffff, .opNegateSlow 834 negi t3 835 ori ArithProfileInt, t2 836 orq tagTypeNumber, t3 837 storeisToInstruction(t2, 3) 838 storeq t3, [cfr, t1, 8] 839 dispatch(4) 837 840 .opNegateNotInt: 838 btqz t2, tagTypeNumber, .opNegateSlow 839 xorq 0x8000000000000000, t2 840 storeq t2, [cfr, t1, 8] 841 dispatch(3) 841 btqz t3, tagTypeNumber, .opNegateSlow 842 xorq 0x8000000000000000, t3 843 ori ArithProfileNumber, t2 844 storeq t3, [cfr, t1, 8] 845 storeisToInstruction(t2, 3) 846 dispatch(4) 842 847 843 848 .opNegateSlow: 844 849 callOpcodeSlowPath(_slow_path_negate) 845 dispatch( 3)850 dispatch(4) 846 851 847 852 -
trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
r205569 r206289 351 351 } 352 352 353 #if ENABLE(JIT) 354 static void updateArithProfileForUnaryArithOp(Instruction* pc, JSValue result, JSValue operand) 355 { 356 ArithProfile& profile = *bitwise_cast<ArithProfile*>(&pc[3].u.operand); 357 profile.observeLHS(operand); 358 ASSERT(result.isNumber()); 359 if (!result.isInt32()) { 360 if (operand.isInt32()) 361 profile.setObservedInt32Overflow(); 362 363 double doubleVal = result.asNumber(); 364 if (!doubleVal && std::signbit(doubleVal)) 365 profile.setObservedNegZeroDouble(); 366 else { 367 profile.setObservedNonNegZeroDouble(); 368 369 // The Int52 overflow check here intentionally omits 1ll << 51 as a valid negative Int52 value. 370 // Therefore, we will get a false positive if the result is that value. This is intentionally 371 // done to simplify the checking algorithm. 372 static const int64_t int52OverflowPoint = (1ll << 51); 373 int64_t int64Val = static_cast<int64_t>(std::abs(doubleVal)); 374 if (int64Val >= int52OverflowPoint) 375 profile.setObservedInt52Overflow(); 376 } 377 } 378 } 379 #else 380 static void updateArithProfileForUnaryArithOp(Instruction*, JSValue, JSValue) { } 381 #endif 382 353 383 SLOW_PATH_DECL(slow_path_negate) 354 384 { 355 385 BEGIN(); 356 RETURN(jsNumber(-OP_C(2).jsValue().toNumber(exec))); 386 JSValue operand = OP_C(2).jsValue(); 387 JSValue result = jsNumber(-operand.toNumber(exec)); 388 RETURN_WITH_PROFILING(result, { 389 updateArithProfileForUnaryArithOp(pc, result, operand); 390 }); 357 391 } 358 392 … … 361 395 { 362 396 CodeBlock* codeBlock = exec->codeBlock(); 363 ArithProfile& profile = codeBlock->arithProfileForPC(pc);397 ArithProfile& profile = *codeBlock->arithProfileForPC(pc); 364 398 365 399 if (result.isNumber()) { … … 405 439 JSValue result; 406 440 407 ArithProfile& arithProfile = exec->codeBlock()->arithProfileForPC(pc);441 ArithProfile& arithProfile = *exec->codeBlock()->arithProfileForPC(pc); 408 442 arithProfile.observeLHSAndRHS(v1, v2); 409 443
Note: See TracChangeset
for help on using the changeset viewer.