Changeset 95754 in webkit
- Timestamp:
- Sep 22, 2011 3:02:24 PM (13 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r95753 r95754 1 2011-09-22 Filip Pizlo <fpizlo@apple.com> 2 3 DFG JIT should support integer division 4 https://bugs.webkit.org/show_bug.cgi?id=68597 5 6 Reviewed by Darin Adler. 7 8 This adds support for ArithDiv speculating integer, and speculating 9 that the result is integer (i.e. remainder = 0). 10 11 This is a 4% win on Kraken and a 1% loss on V8. 12 13 * bytecode/CodeBlock.h: 14 * dfg/DFGByteCodeParser.cpp: 15 (JSC::DFG::ByteCodeParser::makeDivSafe): 16 (JSC::DFG::ByteCodeParser::parseBlock): 17 * dfg/DFGNode.h: 18 (JSC::DFG::Node::hasArithNodeFlags): 19 * dfg/DFGPropagator.cpp: 20 (JSC::DFG::Propagator::propagateArithNodeFlags): 21 (JSC::DFG::Propagator::propagateNodePredictions): 22 (JSC::DFG::Propagator::fixupNode): 23 * dfg/DFGSpeculativeJIT.cpp: 24 (JSC::DFG::SpeculativeJIT::compile): 25 * jit/JITArithmetic.cpp: 26 (JSC::JIT::emit_op_div): 27 1 28 2011-09-22 Oliver Hunt <oliver@apple.com> 2 29 -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.h
r95681 r95754 538 538 } 539 539 540 bool likelyToTakeSpecialFastCase(int bytecodeOffset) 541 { 542 unsigned specialFastCaseCount = specialFastCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter; 543 return specialFastCaseCount >= slowCaseThreshold(); 544 } 545 540 546 bool likelyToTakeDeepestSlowCase(int bytecodeOffset) 541 547 { … … 543 549 unsigned specialFastCaseCount = specialFastCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter; 544 550 return (slowCaseCount - specialFastCaseCount) >= slowCaseThreshold(); 551 } 552 553 bool likelyToTakeAnySlowCase(int bytecodeOffset) 554 { 555 unsigned slowCaseCount = rareCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter; 556 unsigned specialFastCaseCount = specialFastCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter; 557 return (slowCaseCount + specialFastCaseCount) >= slowCaseThreshold(); 545 558 } 546 559 -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r95753 r95754 537 537 break; 538 538 } 539 540 return nodeIndex; 541 } 542 543 NodeIndex makeDivSafe(NodeIndex nodeIndex) 544 { 545 ASSERT(m_graph[nodeIndex].op == ArithDiv); 546 547 // The main slow case counter for op_div in the old JIT counts only when 548 // the operands are not numbers. We don't care about that since we already 549 // have speculations in place that take care of that separately. We only 550 // care about when the outcome of the division is not an integer, which 551 // is what the special fast case counter tells us. 552 553 if (!m_profiledBlock->likelyToTakeSpecialFastCase(m_currentIndex)) 554 return nodeIndex; 555 556 m_graph[nodeIndex].mergeArithNodeFlags(NodeMayOverflow | NodeMayNegZero); 539 557 540 558 return nodeIndex; … … 917 935 NodeIndex op1 = getToNumber(currentInstruction[2].u.operand); 918 936 NodeIndex op2 = getToNumber(currentInstruction[3].u.operand); 919 set(currentInstruction[1].u.operand, addToGraph(ArithDiv, op1, op2));937 set(currentInstruction[1].u.operand, makeDivSafe(addToGraph(ArithDiv, OpInfo(NodeUseBottom), op1, op2))); 920 938 NEXT_OPCODE(op_div); 921 939 } -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r95753 r95754 491 491 case ArithMax: 492 492 case ArithMod: 493 case ArithDiv: 493 494 case ValueAdd: 494 495 return true; -
trunk/Source/JavaScriptCore/dfg/DFGPropagator.cpp
r95753 r95754 212 212 } 213 213 214 case ArithMul: { 214 case ArithMul: 215 case ArithDiv: { 215 216 // As soon as a multiply happens, we can easily end up in the part 216 217 // of the double domain where the point at which you do truncation … … 423 424 case ArithMul: 424 425 case ArithMin: 425 case ArithMax: { 426 case ArithMax: 427 case ArithDiv: { 426 428 PredictedType left = m_predictions[node.child1()]; 427 429 PredictedType right = m_predictions[node.child2()]; … … 436 438 } 437 439 438 case ArithDiv:439 440 case ArithSqrt: { 440 441 changed |= setPrediction(makePrediction(PredictDouble, StrongPrediction)); … … 650 651 case ArithMin: 651 652 case ArithMax: 652 case ArithMod: { 653 case ArithMod: 654 case ArithDiv: { 653 655 if (!nodeCanSpeculateInteger(node.arithNodeFlags())) { 654 656 toDouble(node.child1()); … … 666 668 toDouble(node.child1()); 667 669 } 668 break;669 }670 671 case ArithDiv: {672 toDouble(node.child1());673 toDouble(node.child2());674 670 break; 675 671 } -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r95753 r95754 1099 1099 1100 1100 case ArithDiv: { 1101 if (shouldSpeculateInteger(node.child1(), node.child2()) && nodeCanSpeculateInteger(node.arithNodeFlags())) { 1102 SpeculateIntegerOperand op1(this, node.child1()); 1103 SpeculateIntegerOperand op2(this, node.child2()); 1104 GPRTemporary eax(this, X86Registers::eax); 1105 GPRTemporary edx(this, X86Registers::edx); 1106 GPRReg op1GPR = op1.gpr(); 1107 GPRReg op2GPR = op2.gpr(); 1108 1109 speculationCheck(m_jit.branchTest32(JITCompiler::Zero, op2GPR)); 1110 1111 // If the user cares about negative zero, then speculate that we're not about 1112 // to produce negative zero. 1113 if (!nodeCanIgnoreNegativeZero(node.arithNodeFlags())) { 1114 MacroAssembler::Jump numeratorNonZero = m_jit.branchTest32(MacroAssembler::NonZero, op1GPR); 1115 speculationCheck(m_jit.branch32(MacroAssembler::LessThan, op2GPR, TrustedImm32(0))); 1116 numeratorNonZero.link(&m_jit); 1117 } 1118 1119 GPRReg temp2 = InvalidGPRReg; 1120 if (op2GPR == X86Registers::eax || op2GPR == X86Registers::edx) { 1121 temp2 = allocate(); 1122 m_jit.move(op2GPR, temp2); 1123 op2GPR = temp2; 1124 } 1125 1126 m_jit.move(op1GPR, eax.gpr()); 1127 m_jit.assembler().cdq(); 1128 m_jit.assembler().idivl_r(op2GPR); 1129 1130 // Check that there was no remainder. If there had been, then we'd be obligated to 1131 // produce a double result instead. 1132 speculationCheck(m_jit.branchTest32(JITCompiler::NonZero, edx.gpr())); 1133 1134 integerResult(eax.gpr(), m_compileIndex); 1135 break; 1136 } 1137 1101 1138 SpeculateDoubleOperand op1(this, node.child1()); 1102 1139 SpeculateDoubleOperand op2(this, node.child2()); -
trunk/Source/JavaScriptCore/jit/JITArithmetic.cpp
r95563 r95754 1048 1048 } 1049 1049 divDouble(fpRegT1, fpRegT0); 1050 1050 1051 #if ENABLE(DFG_JIT) 1052 // Is the result actually an integer? The DFG JIT would really like to know. If it's 1053 // not an integer, we increment a count. If this together with the slow case counter 1054 // are below threshold then the DFG JIT will compile this division with a specualtion 1055 // that the remainder is zero. 1056 1057 // As well, there are cases where a double result here would cause an important field 1058 // in the heap to sometimes have doubles in it, resulting in double predictions getting 1059 // propagated to a use site where it might cause damage (such as the index to an array 1060 // access). So if we are DFG compiling anything in the program, we want this code to 1061 // ensure that it produces integers whenever possible. 1062 1063 // FIXME: This will fail to convert to integer if the result is zero. We should 1064 // distinguish between positive zero and negative zero here. 1065 1066 JumpList notInteger; 1067 branchConvertDoubleToInt32(fpRegT0, regT0, notInteger, fpRegT1); 1068 // If we've got an integer, we might as well make that the result of the division. 1069 emitFastArithReTagImmediate(regT0, regT0); 1070 Jump isInteger = jump(); 1071 notInteger.link(this); 1072 add32(Imm32(1), AbsoluteAddress(&m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset)->m_counter)); 1073 moveDoubleToPtr(fpRegT0, regT0); 1074 subPtr(tagTypeNumberRegister, regT0); 1075 isInteger.link(this); 1076 #else 1051 1077 // Double result. 1052 1078 moveDoubleToPtr(fpRegT0, regT0); 1053 1079 subPtr(tagTypeNumberRegister, regT0); 1080 #endif 1054 1081 1055 1082 emitPutVirtualRegister(dst, regT0);
Note: See TracChangeset
for help on using the changeset viewer.