Changeset 95563 in webkit
- Timestamp:
- Sep 20, 2011 1:10:56 PM (13 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r95559 r95563 1 2011-09-20 Filip Pizlo <fpizlo@apple.com> 2 3 DFG JIT performs too many negative zero checks, and too many 4 overflow checks 5 https://bugs.webkit.org/show_bug.cgi?id=68430 6 7 Reviewed by Oliver Hunt. 8 9 This adds comprehensive support for deciding how to perform an 10 arithmetic operations based on a combination of overflow profiling, 11 negative zero profiling, value profiling, and a static analysis of 12 how the results of these operations get used. 13 14 This is a 72% speed-up on stanford-crypto-sha256-iterative, and a 15 2.5% speed-up on the Kraken average, a 1.4% speed-up on the V8 16 geomean, and neutral on SunSpider. It's also an 8.5% speed-up on 17 V8-crypto, because apparenty everything we do speeds up crypto. 18 19 * dfg/DFGByteCodeParser.cpp: 20 (JSC::DFG::ByteCodeParser::toInt32): 21 (JSC::DFG::ByteCodeParser::toNumber): 22 (JSC::DFG::ByteCodeParser::isSmallInt32Constant): 23 (JSC::DFG::ByteCodeParser::valueOfInt32Constant): 24 (JSC::DFG::ByteCodeParser::weaklyPredictInt32): 25 (JSC::DFG::ByteCodeParser::makeSafe): 26 (JSC::DFG::ByteCodeParser::handleMinMax): 27 (JSC::DFG::ByteCodeParser::handleIntrinsic): 28 (JSC::DFG::ByteCodeParser::parseBlock): 29 (JSC::DFG::ByteCodeParser::processPhiStack): 30 (JSC::DFG::ByteCodeParser::parse): 31 * dfg/DFGGraph.cpp: 32 (JSC::DFG::Graph::dump): 33 * dfg/DFGJITCodeGenerator.cpp: 34 (JSC::DFG::JITCodeGenerator::nonSpeculativeBasicArithOp): 35 * dfg/DFGNode.h: 36 (JSC::DFG::nodeUsedAsNumber): 37 (JSC::DFG::nodeCanTruncateInteger): 38 (JSC::DFG::nodeCanIgnoreNegativeZero): 39 (JSC::DFG::nodeCanSpeculateInteger): 40 (JSC::DFG::arithNodeFlagsAsString): 41 (JSC::DFG::Node::Node): 42 (JSC::DFG::Node::hasArithNodeFlags): 43 (JSC::DFG::Node::rawArithNodeFlags): 44 (JSC::DFG::Node::arithNodeFlags): 45 (JSC::DFG::Node::arithNodeFlagsForCompare): 46 (JSC::DFG::Node::setArithNodeFlag): 47 (JSC::DFG::Node::mergeArithNodeFlags): 48 * dfg/DFGPropagator.cpp: 49 (JSC::DFG::Propagator::fixpoint): 50 (JSC::DFG::Propagator::isNotNegZero): 51 (JSC::DFG::Propagator::isNotZero): 52 (JSC::DFG::Propagator::propagateArithNodeFlags): 53 (JSC::DFG::Propagator::propagateArithNodeFlagsForward): 54 (JSC::DFG::Propagator::propagateArithNodeFlagsBackward): 55 (JSC::DFG::Propagator::propagateNodePredictions): 56 (JSC::DFG::Propagator::propagatePredictionsForward): 57 (JSC::DFG::Propagator::propagatePredictionsBackward): 58 (JSC::DFG::Propagator::toDouble): 59 (JSC::DFG::Propagator::fixupNode): 60 (JSC::DFG::Propagator::fixup): 61 (JSC::DFG::Propagator::startIndexForChildren): 62 (JSC::DFG::Propagator::endIndexForPureCSE): 63 (JSC::DFG::Propagator::pureCSE): 64 (JSC::DFG::Propagator::clobbersWorld): 65 (JSC::DFG::Propagator::setReplacement): 66 (JSC::DFG::Propagator::performNodeCSE): 67 (JSC::DFG::Propagator::localCSE): 68 * dfg/DFGSpeculativeJIT.cpp: 69 (JSC::DFG::SpeculativeJIT::compile): 70 (JSC::DFG::SpeculativeJIT::computeValueRecoveryFor): 71 1 72 2011-09-19 Oliver Hunt <oliver@apple.com> 2 73 -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r95523 r95563 194 194 return node.child1(); 195 195 196 if (node.op == UInt32ToNumberSafe)197 return node.child1();198 199 196 // Check for numeric constants boxed as JSValues. 200 197 if (node.op == JSConstant) { … … 222 219 } 223 220 224 return addToGraph(ValueToNumber, index);221 return addToGraph(ValueToNumber, OpInfo(NodeUseBottom), index); 225 222 } 226 223 … … 265 262 return intValue >= -5 && intValue <= 5; 266 263 } 267 bool isDoubleConstant(NodeIndex nodeIndex)268 {269 return isJSConstant(nodeIndex) && valueOfJSConstant(nodeIndex).isNumber();270 }271 264 // Convenience methods for getting constant values. 272 265 JSValue valueOfJSConstant(NodeIndex index) … … 279 272 ASSERT(isInt32Constant(nodeIndex)); 280 273 return valueOfJSConstant(nodeIndex).asInt32(); 281 }282 double valueOfDoubleConstant(NodeIndex nodeIndex)283 {284 ASSERT(isDoubleConstant(nodeIndex));285 double value;286 bool okay = valueOfJSConstant(nodeIndex).getNumber(value);287 ASSERT_UNUSED(okay, okay);288 return value;289 274 } 290 275 … … 487 472 case ArithAdd: 488 473 case ArithSub: 489 case ArithMulIgnoreZero: 490 case ArithMulSpecNotNegZero: 491 case ArithMulPossiblyNegZero: 492 case ArithMulSafe: 474 case ArithMul: 493 475 case ValueAdd: 494 476 m_reusableNodeStack.append(&m_graph[nodePtr->child1()]); … … 526 508 } 527 509 528 Node Type makeSafe(NodeType op)510 NodeIndex makeSafe(NodeIndex nodeIndex) 529 511 { 530 512 if (!m_profiledBlock->likelyToTakeSlowCase(m_currentIndex)) 531 return op;513 return nodeIndex; 532 514 533 515 #if ENABLE(DFG_DEBUG_VERBOSE) 534 printf("Making %s @% lu safe at bc#%u because slow-case counter is at %u\n", Graph::opName(op), m_graph.size(), m_currentIndex, m_profiledBlock->slowCaseProfileForBytecodeOffset(m_currentIndex)->m_counter);516 printf("Making %s @%u safe at bc#%u because slow-case counter is at %u\n", Graph::opName(m_graph[nodeIndex].op), nodeIndex, m_currentIndex, m_profiledBlock->slowCaseProfileForBytecodeOffset(m_currentIndex)->m_counter); 535 517 #endif 536 518 537 switch ( op) {519 switch (m_graph[nodeIndex].op) { 538 520 case UInt32ToNumber: 539 return UInt32ToNumberSafe;540 521 case ArithAdd: 541 return ArithAddSafe;542 522 case ArithSub: 543 return ArithSubSafe; 544 545 // We initialize ArithMul to ArithMulIgnoreZero and push it towards 546 // safer variants as we learn more, unless we already know that it 547 // can overflow. If it doesn't overflow, we first turn it into 548 // PossiblyNegZero if we see that it had been -0 during old JIT 549 // execution. 550 case ArithMulIgnoreZero: 523 case ValueAdd: 524 m_graph[nodeIndex].mergeArithNodeFlags(NodeMayOverflow); 525 break; 526 527 case ArithMul: 551 528 if (m_profiledBlock->likelyToTakeDeepestSlowCase(m_currentIndex)) 552 return ArithMulSafe;529 m_graph[nodeIndex].mergeArithNodeFlags(NodeMayOverflow | NodeMayNegZero); 553 530 else 554 return ArithMulPossiblyNegZero; 555 556 case ValueAdd: 557 return ValueAddSafe; 531 m_graph[nodeIndex].mergeArithNodeFlags(NodeMayNegZero); 532 break; 533 558 534 default: 559 535 ASSERT_NOT_REACHED(); 560 return Phantom; // Have to return something. 561 } 536 break; 537 } 538 539 return nodeIndex; 562 540 } 563 541 564 NodeIndex getTrueResult(NodeIndex nodeIndex)565 {566 switch (m_graph[nodeIndex].op) {567 case ArithMulIgnoreZero:568 m_graph[nodeIndex].op = ArithMulSpecNotNegZero;569 break;570 case ArithMulPossiblyNegZero:571 m_graph[nodeIndex].op = ArithMulSafe;572 break;573 default:574 break;575 }576 return nodeIndex;577 }578 579 bool isMultiply(NodeIndex nodeIndex)580 {581 switch (m_graph[nodeIndex].op) {582 case ArithMulSpecNotNegZero:583 case ArithMulIgnoreZero:584 case ArithMulPossiblyNegZero:585 case ArithMulSafe:586 return true;587 default:588 return false;589 }590 }591 592 542 JSGlobalData* m_globalData; 593 543 CodeBlock* m_codeBlock; … … 690 640 691 641 if (lastArg == firstArg + 2) { 692 set(resultOperand, addToGraph(op, getToNumber(firstArg + 1), getToNumber(firstArg + 2)));642 set(resultOperand, addToGraph(op, OpInfo(NodeUseBottom), getToNumber(firstArg + 1), getToNumber(firstArg + 2))); 693 643 return true; 694 644 } … … 714 664 set(resultOperand, constantNaN()); 715 665 else 716 set(resultOperand, addToGraph(ArithAbs, getToNumber(absArg)));666 set(resultOperand, addToGraph(ArithAbs, OpInfo(NodeUseBottom), getToNumber(absArg))); 717 667 return true; 718 668 } … … 858 808 result = addToGraph(BitURShift, op1, op2); 859 809 else 860 result = addToGraph(makeSafe(UInt32ToNumber), op1);810 result = makeSafe(addToGraph(UInt32ToNumber, OpInfo(NodeUseBottom), op1)); 861 811 } else { 862 812 // Cannot optimize at this stage; shift & potentially rebox as a double. 863 813 result = addToGraph(BitURShift, op1, op2); 864 result = addToGraph(makeSafe(UInt32ToNumber), result);814 result = makeSafe(addToGraph(UInt32ToNumber, OpInfo(NodeUseBottom), result)); 865 815 } 866 816 set(currentInstruction[1].u.operand, result, PredictInt32); … … 874 824 NodeIndex op = getToNumber(srcDst); 875 825 weaklyPredictInt32(op); 876 set(srcDst, addToGraph(makeSafe(ArithAdd), op, one()));826 set(srcDst, makeSafe(addToGraph(ArithAdd, OpInfo(NodeUseBottom), op, one()))); 877 827 NEXT_OPCODE(op_pre_inc); 878 828 } … … 884 834 weaklyPredictInt32(op); 885 835 set(result, op); 886 set(srcDst, addToGraph(makeSafe(ArithAdd), op, one()));836 set(srcDst, makeSafe(addToGraph(ArithAdd, OpInfo(NodeUseBottom), op, one()))); 887 837 NEXT_OPCODE(op_post_inc); 888 838 } … … 892 842 NodeIndex op = getToNumber(srcDst); 893 843 weaklyPredictInt32(op); 894 set(srcDst, addToGraph(makeSafe(ArithSub), op, one()));844 set(srcDst, makeSafe(addToGraph(ArithSub, OpInfo(NodeUseBottom), op, one()))); 895 845 NEXT_OPCODE(op_pre_dec); 896 846 } … … 902 852 weaklyPredictInt32(op); 903 853 set(result, op); 904 set(srcDst, addToGraph(makeSafe(ArithSub), op, one()));854 set(srcDst, makeSafe(addToGraph(ArithSub, OpInfo(NodeUseBottom), op, one()))); 905 855 NEXT_OPCODE(op_post_dec); 906 856 } … … 918 868 } 919 869 920 // If both inputs are multiplies, then we need to make sure to play921 // it safe with -0.922 if (isMultiply(op1) && isMultiply(op2)) {923 getTrueResult(op1);924 getTrueResult(op2);925 }926 927 870 if (m_graph[op1].hasNumberResult() && m_graph[op2].hasNumberResult()) 928 set(currentInstruction[1].u.operand, addToGraph(makeSafe(ArithAdd), toNumber(op1), toNumber(op2)));871 set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithAdd, OpInfo(NodeUseBottom), toNumber(op1), toNumber(op2)))); 929 872 else 930 set(currentInstruction[1].u.operand, addToGraph(makeSafe(ValueAdd), op1, op2));873 set(currentInstruction[1].u.operand, makeSafe(addToGraph(ValueAdd, OpInfo(NodeUseBottom), op1, op2))); 931 874 NEXT_OPCODE(op_add); 932 875 } … … 940 883 } 941 884 942 // For the left child we need to be careful about negative zero, 943 // since -0 - 0 is -0. If the right child is -0 then it doesn't 944 // matter, since 0 - -0 is 0 and 0 - 0 is 0. 945 getTrueResult(op1); 946 947 set(currentInstruction[1].u.operand, addToGraph(makeSafe(ArithSub), op1, op2)); 885 set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithSub, OpInfo(NodeUseBottom), op1, op2))); 948 886 NEXT_OPCODE(op_sub); 949 887 } 950 888 951 889 case op_mul: { 952 // We could be fancy here and skip the getTrueResult, instead making 953 // getTrueResult operate transitively. But we do this the simple way, for 954 // now. 955 NodeIndex op1 = getTrueResult(getToNumber(currentInstruction[2].u.operand)); 956 NodeIndex op2 = getTrueResult(getToNumber(currentInstruction[3].u.operand)); 957 set(currentInstruction[1].u.operand, addToGraph(makeSafe(ArithMulIgnoreZero), op1, op2)); 890 // Multiply requires that the inputs are not truncated, unfortunately. 891 NodeIndex op1 = getToNumber(currentInstruction[2].u.operand); 892 NodeIndex op2 = getToNumber(currentInstruction[3].u.operand); 893 set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithMul, OpInfo(NodeUseBottom), op1, op2))); 958 894 NEXT_OPCODE(op_mul); 959 895 } … … 1090 1026 NodeIndex base = get(currentInstruction[1].u.operand); 1091 1027 NodeIndex property = get(currentInstruction[2].u.operand); 1092 NodeIndex value = get TrueResult(get(currentInstruction[3].u.operand));1028 NodeIndex value = get(currentInstruction[3].u.operand); 1093 1029 weaklyPredictArray(base); 1094 1030 weaklyPredictInt32(property); … … 1167 1103 1168 1104 case op_put_by_id: { 1169 NodeIndex value = get TrueResult(get(currentInstruction[3].u.operand));1105 NodeIndex value = get(currentInstruction[3].u.operand); 1170 1106 NodeIndex base = get(currentInstruction[1].u.operand); 1171 1107 unsigned identifier = currentInstruction[2].u.operand; … … 1188 1124 1189 1125 case op_put_global_var: { 1190 NodeIndex value = get TrueResult(get(currentInstruction[2].u.operand));1126 NodeIndex value = get(currentInstruction[2].u.operand); 1191 1127 addToGraph(PutGlobalVar, OpInfo(currentInstruction[1].u.operand), value); 1192 1128 NEXT_OPCODE(op_put_global_var); … … 1470 1406 1471 1407 Node* phiNode = &m_graph[entry.m_phi]; 1472 if (phiNode->refCount()) { 1473 if (m_graph[valueInPredecessor].op == SetLocal) { 1474 // Any live SetLocal should ensure that it gets the true value. 1475 // Currently this means that ArithMuls distinguish between 1476 // negative zero and positive zero. 1477 getTrueResult(m_graph[valueInPredecessor].child1()); 1478 } 1408 if (phiNode->refCount()) 1479 1409 m_graph.ref(valueInPredecessor); 1480 }1481 1410 1482 1411 if (phiNode->child1() == NoNode) { … … 1563 1492 m_graph.m_parameterSlots = m_parameterSlots; 1564 1493 1565 #if ENABLE(DFG_DEBUG_VERBOSE)1566 m_graph.dump(m_codeBlock);1567 #endif1568 1569 1494 return true; 1570 1495 } -
trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp
r95389 r95563 102 102 } 103 103 104 if (node.hasArithNodeFlags()) { 105 printf("%s%s", hasPrinted ? ", " : "", arithNodeFlagsAsString(node.rawArithNodeFlags())); 106 hasPrinted = true; 107 } 104 108 if (node.hasVarNumber()) { 105 109 printf("%svar%u", hasPrinted ? ", " : "", node.varNumber()); -
trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.cpp
r95523 r95563 762 762 } 763 763 764 case ArithMulIgnoreZero: 765 case ArithMulPossiblyNegZero: 766 case ArithMulSpecNotNegZero: 767 case ArithMulSafe: { 764 case ArithMul: { 768 765 overflow.append(m_jit.branchMul32(MacroAssembler::Overflow, arg1GPR, arg2GPR, resultGPR)); 769 766 overflow.append(m_jit.branchTest32(MacroAssembler::Zero, resultGPR)); … … 856 853 break; 857 854 858 case ArithMulIgnoreZero: 859 case ArithMulPossiblyNegZero: 860 case ArithMulSpecNotNegZero: 861 case ArithMulSafe: 855 case ArithMul: 862 856 m_jit.mulDouble(tmp2FPR, tmp1FPR); 863 857 break; -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r95523 r95563 27 27 #define DFGNode_h 28 28 29 #include <wtf/BoundsCheckedPointer.h> 29 30 #include <wtf/Platform.h> 30 31 31 32 // Emit various logging information for debugging, including dumping the dataflow graphs. 32 33 #define ENABLE_DFG_DEBUG_VERBOSE 0 34 // Emit dumps during propagation, in addition to just after. 35 #define ENABLE_DFG_DEBUG_PROPAGATION_VERBOSE 0 33 36 // Emit logging for OSR exit value recoveries at every node, not just nodes that 34 37 // actually has speculation checks. … … 106 109 }; 107 110 111 typedef unsigned ArithNodeFlags; 112 #define NodeUseBottom 0x00 113 #define NodeUsedAsNumber 0x01 114 #define NodeNeedsNegZero 0x02 115 #define NodeUsedAsMask 0x03 116 #define NodeMayOverflow 0x04 117 #define NodeMayNegZero 0x08 118 #define NodeBehaviorMask 0x0c 119 120 static inline bool nodeUsedAsNumber(ArithNodeFlags flags) 121 { 122 return !!(flags & NodeUsedAsNumber); 123 } 124 125 static inline bool nodeCanTruncateInteger(ArithNodeFlags flags) 126 { 127 return !nodeUsedAsNumber(flags); 128 } 129 130 static inline bool nodeCanIgnoreNegativeZero(ArithNodeFlags flags) 131 { 132 return !(flags & NodeNeedsNegZero); 133 } 134 135 static inline bool nodeCanSpeculateInteger(ArithNodeFlags flags) 136 { 137 if (flags & NodeMayOverflow) 138 return !nodeUsedAsNumber(flags); 139 140 if (flags & NodeMayNegZero) 141 return nodeCanIgnoreNegativeZero(flags); 142 143 return true; 144 } 145 146 #ifndef NDEBUG 147 static inline const char* arithNodeFlagsAsString(ArithNodeFlags flags) 148 { 149 if (!flags) 150 return "<empty>"; 151 152 static const int size = 64; 153 static char description[size]; 154 BoundsCheckedPointer<char> ptr(description, size); 155 156 bool hasPrinted = false; 157 158 if (flags & NodeUsedAsNumber) { 159 ptr.strcat("UsedAsNum"); 160 hasPrinted = true; 161 } 162 163 if (flags & NodeNeedsNegZero) { 164 if (hasPrinted) 165 ptr.strcat("|"); 166 ptr.strcat("NeedsNegZero"); 167 hasPrinted = true; 168 } 169 170 if (flags & NodeMayOverflow) { 171 if (hasPrinted) 172 ptr.strcat("|"); 173 ptr.strcat("MayOverflow"); 174 hasPrinted = true; 175 } 176 177 if (flags & NodeMayNegZero) { 178 if (hasPrinted) 179 ptr.strcat("|"); 180 ptr.strcat("MayNegZero"); 181 hasPrinted = true; 182 } 183 184 *ptr++ = 0; 185 186 return description; 187 } 188 #endif 189 108 190 // Entries in the NodeType enum (below) are composed of an id, a result type (possibly none) 109 191 // and some additional informative flags (must generate, is constant, etc). … … 149 231 /* Used to box the result of URShift nodes (result has range 0..2^32-1). */\ 150 232 macro(UInt32ToNumber, NodeResultNumber) \ 151 macro(UInt32ToNumberSafe, NodeResultNumber) \152 233 \ 153 234 /* Nodes for arithmetic operations. */\ 154 235 macro(ArithAdd, NodeResultNumber) \ 155 236 macro(ArithSub, NodeResultNumber) \ 156 macro(ArithAddSafe, NodeResultNumber) /* Safe variants are those that are known to take old JIT slow path */\ 157 macro(ArithSubSafe, NodeResultNumber) \ 158 macro(ArithMulSpecNotNegZero, NodeResultNumber) /* Speculate that the result is not negative zero. */ \ 159 macro(ArithMulIgnoreZero, NodeResultNumber) /* If it's negative zero, ignore it. */ \ 160 macro(ArithMulPossiblyNegZero, NodeResultNumber) /* It definitely may be negative zero but we haven't decided what to do about it yet. No code generation for this node; it either turns into ArithMulIgnoreZero or ArithMulSafe. */ \ 161 macro(ArithMulSafe, NodeResultNumber) /* It may be negative zero, or it may produce other forms of double, so speculate double. */\ 237 macro(ArithMul, NodeResultNumber) \ 162 238 macro(ArithDiv, NodeResultNumber) \ 163 239 macro(ArithMod, NodeResultNumber) \ … … 174 250 /* Add of values may either be arithmetic, or result in string concatenation. */\ 175 251 macro(ValueAdd, NodeResultJS | NodeMustGenerate | NodeMightClobber) \ 176 macro(ValueAddSafe, NodeResultJS | NodeMustGenerate | NodeMightClobber) \177 252 \ 178 253 /* Property access. */\ … … 263 338 { 264 339 ASSERT(!(op & NodeHasVarArgs)); 340 ASSERT(!hasArithNodeFlags()); 265 341 children.fixed.child1 = child1; 266 342 children.fixed.child2 = child2; … … 391 467 ASSERT(hasIdentifier()); 392 468 return m_opInfo; 469 } 470 471 bool hasArithNodeFlags() 472 { 473 switch (op) { 474 case ValueToNumber: 475 case ValueToDouble: 476 case UInt32ToNumber: 477 case ArithAdd: 478 case ArithSub: 479 case ArithMul: 480 case ArithAbs: 481 case ArithMin: 482 case ArithMax: 483 case ValueAdd: 484 return true; 485 default: 486 return false; 487 } 488 } 489 490 ArithNodeFlags rawArithNodeFlags() 491 { 492 ASSERT(hasArithNodeFlags()); 493 return m_opInfo; 494 } 495 496 // This corrects the arithmetic node flags, so that irrelevant bits are 497 // ignored. In particular, anything other than ArithMul does not need 498 // to know if it can speculate on negative zero. 499 ArithNodeFlags arithNodeFlags() 500 { 501 ArithNodeFlags result = rawArithNodeFlags(); 502 if (op == ArithMul) 503 return result; 504 return result & ~NodeNeedsNegZero; 505 } 506 507 ArithNodeFlags arithNodeFlagsForCompare() 508 { 509 if (hasArithNodeFlags()) 510 return arithNodeFlags(); 511 return 0; 512 } 513 514 void setArithNodeFlag(ArithNodeFlags flags) 515 { 516 ASSERT(hasArithNodeFlags()); 517 m_opInfo = flags; 518 } 519 520 bool mergeArithNodeFlags(ArithNodeFlags flags) 521 { 522 if (!hasArithNodeFlags()) 523 return false; 524 ArithNodeFlags newFlags = m_opInfo | flags; 525 if (newFlags == m_opInfo) 526 return false; 527 m_opInfo = newFlags; 528 return true; 393 529 } 394 530 -
trunk/Source/JavaScriptCore/dfg/DFGPropagator.cpp
r95523 r95563 76 76 void fixpoint() 77 77 { 78 #if ENABLE(DFG_DEBUG_VERBOSE) 78 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 79 m_graph.dump(m_codeBlock); 80 #endif 81 82 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 79 83 m_count = 0; 80 84 #endif … … 82 86 m_changed = false; 83 87 88 // Up here we start with a backward pass because we suspect that to be 89 // more profitable. 90 propagateArithNodeFlagsBackward(); 91 if (!m_changed) 92 break; 93 94 m_changed = false; 95 propagateArithNodeFlagsForward(); 96 } while (m_changed); 97 98 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 99 m_count = 0; 100 #endif 101 do { 102 m_changed = false; 103 84 104 // Forward propagation is near-optimal for both topologically-sorted and 85 105 // DFS-sorted code. 86 propagate Forward();106 propagatePredictionsForward(); 87 107 if (!m_changed) 88 108 break; … … 93 113 // found a sound solution and (2) short-circuits backward flow. 94 114 m_changed = false; 95 propagate Backward();115 propagatePredictionsBackward(); 96 116 } while (m_changed); 97 117 98 118 fixup(); 99 119 100 #if ENABLE(DFG_DEBUG_ VERBOSE)120 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 101 121 printf("Graph after propagation fixup:\n"); 102 122 m_graph.dump(m_codeBlock); … … 105 125 localCSE(); 106 126 107 #if ENABLE(DFG_DEBUG_ VERBOSE)127 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 108 128 printf("Graph after CSE:\n"); 109 129 m_graph.dump(m_codeBlock); … … 113 133 114 134 #if ENABLE(DFG_DEBUG_VERBOSE) 115 printf("Graph after virtual register allocation:\n");135 printf("Graph after propagation:\n"); 116 136 m_graph.dump(m_codeBlock); 117 137 #endif … … 119 139 120 140 private: 141 bool isNotNegZero(NodeIndex nodeIndex) 142 { 143 if (!m_graph.isNumberConstant(m_codeBlock, nodeIndex)) 144 return false; 145 double value = m_graph.valueOfNumberConstant(m_codeBlock, nodeIndex); 146 return !value && 1.0 / value < 0.0; 147 } 148 149 bool isNotZero(NodeIndex nodeIndex) 150 { 151 if (!m_graph.isNumberConstant(m_codeBlock, nodeIndex)) 152 return false; 153 return !!m_graph.valueOfNumberConstant(m_codeBlock, nodeIndex); 154 } 155 156 void propagateArithNodeFlags(Node& node) 157 { 158 if (!node.shouldGenerate()) 159 return; 160 161 NodeType op = node.op; 162 ArithNodeFlags flags = 0; 163 164 if (node.hasArithNodeFlags()) 165 flags = node.rawArithNodeFlags(); 166 167 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 168 printf(" %s @%u: %s ", Graph::opName(op), m_compileIndex, arithNodeFlagsAsString(flags)); 169 #endif 170 171 flags &= NodeUsedAsMask; 172 173 bool changed = false; 174 175 switch (op) { 176 case ValueToInt32: 177 case BitAnd: 178 case BitOr: 179 case BitXor: 180 case BitLShift: 181 case BitRShift: 182 case BitURShift: { 183 // These operations are perfectly happy with truncated integers, 184 // so we don't want to propagate anything. 185 break; 186 } 187 188 case ValueToNumber: 189 case ValueToDouble: 190 case UInt32ToNumber: { 191 changed |= m_graph[node.child1()].mergeArithNodeFlags(flags); 192 break; 193 } 194 195 case ArithAdd: 196 case ValueAdd: { 197 if (isNotNegZero(node.child1()) || isNotNegZero(node.child2())) 198 flags &= ~NodeNeedsNegZero; 199 200 changed |= m_graph[node.child1()].mergeArithNodeFlags(flags); 201 changed |= m_graph[node.child2()].mergeArithNodeFlags(flags); 202 break; 203 } 204 205 case ArithSub: { 206 if (isNotZero(node.child1()) || isNotZero(node.child2())) 207 flags &= ~NodeNeedsNegZero; 208 209 changed |= m_graph[node.child1()].mergeArithNodeFlags(flags); 210 changed |= m_graph[node.child2()].mergeArithNodeFlags(flags); 211 break; 212 } 213 214 case ArithMul: { 215 // As soon as a multiply happens, we can easily end up in the part 216 // of the double domain where the point at which you do truncation 217 // can change the outcome. So, ArithMul always checks for overflow 218 // no matter what, and always forces its inputs to check as well. 219 220 flags |= NodeUsedAsNumber | NodeNeedsNegZero; 221 changed |= m_graph[node.child1()].mergeArithNodeFlags(flags); 222 changed |= m_graph[node.child2()].mergeArithNodeFlags(flags); 223 break; 224 } 225 226 case ArithMin: 227 case ArithMax: { 228 flags |= NodeUsedAsNumber; 229 changed |= m_graph[node.child1()].mergeArithNodeFlags(flags); 230 changed |= m_graph[node.child2()].mergeArithNodeFlags(flags); 231 break; 232 } 233 234 case ArithAbs: { 235 flags &= ~NodeNeedsNegZero; 236 changed |= m_graph[node.child1()].mergeArithNodeFlags(flags); 237 break; 238 } 239 240 case PutByVal: { 241 changed |= m_graph[node.child1()].mergeArithNodeFlags(flags | NodeUsedAsNumber | NodeNeedsNegZero); 242 changed |= m_graph[node.child2()].mergeArithNodeFlags(flags | NodeUsedAsNumber); 243 changed |= m_graph[node.child3()].mergeArithNodeFlags(flags | NodeUsedAsNumber | NodeNeedsNegZero); 244 break; 245 } 246 247 case GetByVal: { 248 changed |= m_graph[node.child1()].mergeArithNodeFlags(flags | NodeUsedAsNumber | NodeNeedsNegZero); 249 changed |= m_graph[node.child2()].mergeArithNodeFlags(flags | NodeUsedAsNumber); 250 break; 251 } 252 253 default: 254 flags |= NodeUsedAsNumber | NodeNeedsNegZero; 255 if (op & NodeHasVarArgs) { 256 for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++) 257 changed |= m_graph[m_graph.m_varArgChildren[childIdx]].mergeArithNodeFlags(flags); 258 } else { 259 if (node.child1() == NoNode) 260 break; 261 changed |= m_graph[node.child1()].mergeArithNodeFlags(flags); 262 if (node.child2() == NoNode) 263 break; 264 changed |= m_graph[node.child1()].mergeArithNodeFlags(flags); 265 if (node.child3() == NoNode) 266 break; 267 changed |= m_graph[node.child3()].mergeArithNodeFlags(flags); 268 } 269 break; 270 } 271 272 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 273 printf("%s\n", changed ? "CHANGED" : ""); 274 #endif 275 276 m_changed |= changed; 277 } 278 279 void propagateArithNodeFlagsForward() 280 { 281 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 282 printf("Propagating arithmetic node flags forward [%u]\n", ++m_count); 283 #endif 284 for (m_compileIndex = 0; m_compileIndex < m_graph.size(); ++m_compileIndex) 285 propagateArithNodeFlags(m_graph[m_compileIndex]); 286 } 287 288 void propagateArithNodeFlagsBackward() 289 { 290 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 291 printf("Propagating arithmetic node flags backward [%u]\n", ++m_count); 292 #endif 293 for (m_compileIndex = m_graph.size(); m_compileIndex-- > 0;) 294 propagateArithNodeFlags(m_graph[m_compileIndex]); 295 } 296 121 297 bool setPrediction(PredictedType prediction) 122 298 { … … 144 320 } 145 321 146 void propagateNode (Node& node)322 void propagateNodePredictions(Node& node) 147 323 { 148 324 if (!node.shouldGenerate()) … … 151 327 NodeType op = node.op; 152 328 153 #if ENABLE(DFG_DEBUG_ VERBOSE)154 printf(" %s [%u]: ", Graph::opName(op), m_compileIndex);329 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 330 printf(" %s @%u: ", Graph::opName(op), m_compileIndex); 155 331 #endif 156 332 … … 185 361 case BitLShift: 186 362 case BitURShift: 187 case UInt32ToNumber:188 363 case ValueToInt32: 189 364 case ArithMod: { … … 192 367 } 193 368 369 case UInt32ToNumber: { 370 if (nodeCanSpeculateInteger(node.arithNodeFlags())) 371 changed |= setPrediction(makePrediction(PredictInt32, StrongPrediction)); 372 else 373 changed |= setPrediction(makePrediction(PredictNumber, StrongPrediction)); 374 break; 375 } 376 194 377 case ValueToNumber: { 195 378 PredictedType prediction = m_predictions[node.child1()]; 196 379 197 380 if (isStrongPrediction(prediction)) { 198 if ( isNumberPrediction(prediction))199 changed |= mergePrediction( prediction);381 if (!(prediction & PredictDouble) && nodeCanSpeculateInteger(node.arithNodeFlags())) 382 changed |= mergePrediction(makePrediction(PredictInt32, StrongPrediction)); 200 383 else 201 384 changed |= mergePrediction(makePrediction(PredictNumber, StrongPrediction)); … … 211 394 if (isStrongPrediction(left) && isStrongPrediction(right)) { 212 395 if (isNumberPrediction(left) && isNumberPrediction(right)) { 213 if (isInt32Prediction(mergePredictions(left, right)) )396 if (isInt32Prediction(mergePredictions(left, right)) && nodeCanSpeculateInteger(node.arithNodeFlags())) 214 397 changed |= mergePrediction(makePrediction(PredictInt32, StrongPrediction)); 215 398 else … … 226 409 case ArithAdd: 227 410 case ArithSub: 228 case ArithMulIgnoreZero: 229 case ArithMulPossiblyNegZero: 230 case ArithMulSpecNotNegZero: 411 case ArithMul: 231 412 case ArithMin: 232 413 case ArithMax: { … … 235 416 236 417 if (isStrongPrediction(left) && isStrongPrediction(right)) { 237 if (isInt32Prediction(mergePredictions(left, right)) )418 if (isInt32Prediction(mergePredictions(left, right)) && nodeCanSpeculateInteger(node.arithNodeFlags())) 238 419 changed |= mergePrediction(makePrediction(PredictInt32, StrongPrediction)); 239 420 else … … 251 432 case ArithAbs: { 252 433 PredictedType child = m_predictions[node.child1()]; 253 if (isStrongPrediction(child)) 254 changed |= mergePrediction(child); 255 break; 256 } 257 258 case ArithAddSafe: 259 case ArithSubSafe: 260 case ArithMulSafe: 261 case UInt32ToNumberSafe: { 262 changed |= setPrediction(makePrediction(PredictDouble, StrongPrediction)); 263 break; 264 } 265 266 case ValueAddSafe: { 267 PredictedType left = m_predictions[node.child1()]; 268 PredictedType right = m_predictions[node.child2()]; 269 270 if (isStrongPrediction(left) && isStrongPrediction(right)) { 271 if (isNumberPrediction(left) && isNumberPrediction(right)) 272 changed |= mergePrediction(makePrediction(PredictDouble, StrongPrediction)); 273 else if (!(left & PredictNumber) || !(right & PredictNumber)) { 274 // left or right is definitely something other than a number. 275 changed |= mergePrediction(makePrediction(PredictString, StrongPrediction)); 276 } else 277 changed |= mergePrediction(makePrediction(PredictString | PredictInt32 | PredictDouble, StrongPrediction)); 434 if (isStrongPrediction(child)) { 435 if (nodeCanSpeculateInteger(node.arithNodeFlags())) 436 changed |= mergePrediction(child); 437 else 438 changed |= setPrediction(makePrediction(PredictDouble, StrongPrediction)); 278 439 } 279 440 break; … … 390 551 } 391 552 392 #if ENABLE(DFG_DEBUG_ VERBOSE)553 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 393 554 printf("expect(%s) ", predictionToString(m_predictions[m_compileIndex])); 394 555 printf("use(%s) %s\n", predictionToString(m_uses[m_compileIndex]), changed ? "CHANGED" : ""); … … 398 559 } 399 560 400 void propagate Forward()401 { 402 #if ENABLE(DFG_DEBUG_ VERBOSE)403 printf("Propagating forward [%u]\n", ++m_count);561 void propagatePredictionsForward() 562 { 563 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 564 printf("Propagating predictions forward [%u]\n", ++m_count); 404 565 #endif 405 566 for (m_compileIndex = 0; m_compileIndex < m_graph.size(); ++m_compileIndex) 406 propagateNode (m_graph[m_compileIndex]);407 } 408 409 void propagate Backward()410 { 411 #if ENABLE(DFG_DEBUG_ VERBOSE)412 printf("Propagating backward [%u]\n", ++m_count);567 propagateNodePredictions(m_graph[m_compileIndex]); 568 } 569 570 void propagatePredictionsBackward() 571 { 572 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 573 printf("Propagating predictions backward [%u]\n", ++m_count); 413 574 #endif 414 575 for (m_compileIndex = m_graph.size(); m_compileIndex-- > 0;) 415 propagateNode (m_graph[m_compileIndex]);576 propagateNodePredictions(m_graph[m_compileIndex]); 416 577 } 417 578 … … 419 580 { 420 581 if (m_graph[nodeIndex].op == ValueToNumber) { 421 #if ENABLE(DFG_DEBUG_ VERBOSE)582 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 422 583 printf(" @%u -> ValueToDouble", nodeIndex); 423 584 #endif … … 433 594 NodeType op = node.op; 434 595 435 #if ENABLE(DFG_DEBUG_ VERBOSE)436 printf(" %s [%u]: ", Graph::opName(op), m_compileIndex);596 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 597 printf(" %s @%u: ", Graph::opName(op), m_compileIndex); 437 598 #endif 438 599 439 600 switch (op) { 440 601 case ValueAdd: { 602 if (!nodeCanSpeculateInteger(node.arithNodeFlags())) { 603 toDouble(node.child1()); 604 toDouble(node.child2()); 605 break; 606 } 607 441 608 PredictedType left = m_predictions[node.child1()]; 442 609 PredictedType right = m_predictions[node.child2()]; … … 453 620 case ArithAdd: 454 621 case ArithSub: 455 case ArithMulIgnoreZero: 456 case ArithMulPossiblyNegZero: 457 case ArithMulSpecNotNegZero: 622 case ArithMul: 458 623 case ArithMin: 459 624 case ArithMax: { 625 if (!nodeCanSpeculateInteger(node.arithNodeFlags())) { 626 toDouble(node.child1()); 627 toDouble(node.child2()); 628 break; 629 } 630 460 631 PredictedType left = m_predictions[node.child1()]; 461 632 PredictedType right = m_predictions[node.child2()]; … … 477 648 478 649 case ArithAbs: { 650 if (!nodeCanSpeculateInteger(node.arithNodeFlags())) { 651 toDouble(node.child1()); 652 break; 653 } 654 479 655 PredictedType prediction = m_predictions[node.child1()]; 480 656 if (isStrongPrediction(prediction) && (prediction & PredictDouble)) … … 488 664 } 489 665 490 case ArithAddSafe:491 case ArithSubSafe:492 case ArithMulSafe: {493 toDouble(node.child1());494 toDouble(node.child2());495 break;496 }497 498 case ValueAddSafe: {499 PredictedType left = m_predictions[node.child1()];500 PredictedType right = m_predictions[node.child2()];501 502 if (isStrongPrediction(left) && isStrongPrediction(right) && isNumberPrediction(left) && isNumberPrediction(right)) {503 toDouble(node.child2());504 toDouble(node.child1());505 }506 break;507 }508 509 666 default: 510 667 break; 511 668 } 512 669 513 #if ENABLE(DFG_DEBUG_ VERBOSE)670 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 514 671 printf("\n"); 515 672 #endif … … 518 675 void fixup() 519 676 { 520 #if ENABLE(DFG_DEBUG_ VERBOSE)677 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 521 678 printf("Performing Fixup\n"); 522 679 #endif … … 578 735 { 579 736 NodeIndex result = computeStartIndexForChildren(child1, child2, child3); 580 #if ENABLE(DFG_DEBUG_ VERBOSE)737 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 581 738 printf(" lookback %u: ", result); 582 739 #endif … … 598 755 result++; 599 756 ASSERT(result <= m_compileIndex); 600 #if ENABLE(DFG_DEBUG_ VERBOSE)757 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 601 758 printf(" limit %u: ", result); 602 759 #endif … … 614 771 Node& otherNode = m_graph[index]; 615 772 if (node.op != otherNode.op) 773 continue; 774 775 if (node.arithNodeFlagsForCompare() != otherNode.arithNodeFlagsForCompare()) 616 776 continue; 617 777 … … 662 822 switch (node.op) { 663 823 case ValueAdd: 664 case ValueAddSafe:665 824 case CompareLess: 666 825 case CompareLessEq: … … 799 958 return; 800 959 801 #if ENABLE(DFG_DEBUG_ VERBOSE)960 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 802 961 printf(" Replacing @%u -> @%u", m_compileIndex, replacement); 803 962 #endif … … 825 984 return; 826 985 827 #if ENABLE(DFG_DEBUG_ VERBOSE)828 printf(" %s [%u]: ", Graph::opName(m_graph[m_compileIndex].op), m_compileIndex);986 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 987 printf(" %s @%u: ", Graph::opName(m_graph[m_compileIndex].op), m_compileIndex); 829 988 #endif 830 989 … … 840 999 case ArithAdd: 841 1000 case ArithSub: 842 case ArithMulIgnoreZero: 843 case ArithMulPossiblyNegZero: 844 case ArithMulSpecNotNegZero: 1001 case ArithMul: 845 1002 case ArithMod: 846 1003 case ArithDiv: … … 849 1006 case ArithMax: 850 1007 case ArithSqrt: 851 case ArithAddSafe:852 case ArithSubSafe:853 case ArithMulSafe:854 1008 setReplacement(pureCSE(node)); 855 1009 break; … … 913 1067 914 1068 m_lastSeen[node.op & NodeIdMask] = m_compileIndex; 915 #if ENABLE(DFG_DEBUG_ VERBOSE)1069 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 916 1070 printf("\n"); 917 1071 #endif … … 928 1082 void localCSE() 929 1083 { 930 #if ENABLE(DFG_DEBUG_ VERBOSE)1084 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 931 1085 printf("Performing local CSE:"); 932 1086 #endif … … 993 1147 PredictionTracker m_variableUses; 994 1148 995 #if ENABLE(DFG_DEBUG_ VERBOSE)1149 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 996 1150 unsigned m_count; 997 1151 #endif -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r95523 r95563 841 841 842 842 case UInt32ToNumber: { 843 if (!nodeCanSpeculateInteger(node.arithNodeFlags())) { 844 // We know that this sometimes produces doubles. So produce a double every 845 // time. This at least allows subsequent code to not have weird conditionals. 846 847 IntegerOperand op1(this, node.child1()); 848 FPRTemporary result(this); 849 850 GPRReg inputGPR = op1.gpr(); 851 FPRReg outputFPR = result.fpr(); 852 853 m_jit.convertInt32ToDouble(inputGPR, outputFPR); 854 855 JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, inputGPR, TrustedImm32(0)); 856 m_jit.addDouble(JITCompiler::AbsoluteAddress(&twoToThe32), outputFPR); 857 positive.link(&m_jit); 858 859 doubleResult(outputFPR, m_compileIndex); 860 } 861 843 862 IntegerOperand op1(this, node.child1()); 844 863 GPRTemporary result(this, op1); … … 852 871 } 853 872 854 case UInt32ToNumberSafe: {855 // We know that this sometimes produces doubles. So produce a double every856 // time. This at least allows subsequent code to not have weird conditionals.857 858 IntegerOperand op1(this, node.child1());859 FPRTemporary result(this);860 861 GPRReg inputGPR = op1.gpr();862 FPRReg outputFPR = result.fpr();863 864 m_jit.convertInt32ToDouble(inputGPR, outputFPR);865 866 JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, inputGPR, TrustedImm32(0));867 m_jit.addDouble(JITCompiler::AbsoluteAddress(&twoToThe32), outputFPR);868 positive.link(&m_jit);869 870 doubleResult(outputFPR, m_compileIndex);871 break;872 }873 874 873 case ValueToInt32: { 874 if (shouldNotSpeculateInteger(node.child1())) { 875 // Do it the safe way. 876 nonSpeculativeValueToInt32(node); 877 break; 878 } 879 875 880 SpeculateIntegerOperand op1(this, node.child1()); 876 881 GPRTemporary result(this, op1); … … 881 886 882 887 case ValueToNumber: { 883 if (should SpeculateInteger(node.child1())) {884 Speculate IntegerOperand op1(this, node.child1());885 GPRTemporary result(this, op1);886 m_jit.move (op1.gpr(), result.gpr());887 integerResult(result.gpr(), m_compileIndex, op1.format());888 if (shouldNotSpeculateInteger(node.child1())) { 889 SpeculateDoubleOperand op1(this, node.child1()); 890 FPRTemporary result(this, op1); 891 m_jit.moveDouble(op1.fpr(), result.fpr()); 892 doubleResult(result.fpr(), m_compileIndex); 888 893 break; 889 894 } 890 SpeculateDoubleOperand op1(this, node.child1()); 891 FPRTemporary result(this, op1); 892 m_jit.moveDouble(op1.fpr(), result.fpr()); 893 doubleResult(result.fpr(), m_compileIndex); 895 896 SpeculateIntegerOperand op1(this, node.child1()); 897 GPRTemporary result(this, op1); 898 m_jit.move(op1.gpr(), result.gpr()); 899 integerResult(result.gpr(), m_compileIndex, op1.format()); 894 900 break; 895 901 } … … 905 911 case ValueAdd: 906 912 case ArithAdd: { 907 if (shouldSpeculateInteger(node.child1(), node.child2()) ) {913 if (shouldSpeculateInteger(node.child1(), node.child2()) && nodeCanSpeculateInteger(node.arithNodeFlags())) { 908 914 if (isInt32Constant(node.child1())) { 909 915 int32_t imm1 = valueOfInt32Constant(node.child1()); 910 916 SpeculateIntegerOperand op2(this, node.child2()); 911 917 GPRTemporary result(this); 912 913 speculationCheck(m_jit.branchAdd32(MacroAssembler::Overflow, op2.gpr(), Imm32(imm1), result.gpr())); 918 919 if (nodeCanTruncateInteger(node.arithNodeFlags())) { 920 m_jit.move(op2.gpr(), result.gpr()); 921 m_jit.add32(Imm32(imm1), result.gpr()); 922 } else 923 speculationCheck(m_jit.branchAdd32(MacroAssembler::Overflow, op2.gpr(), Imm32(imm1), result.gpr())); 914 924 915 925 integerResult(result.gpr(), m_compileIndex); … … 922 932 GPRTemporary result(this); 923 933 924 speculationCheck(m_jit.branchAdd32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr())); 934 if (nodeCanTruncateInteger(node.arithNodeFlags())) { 935 m_jit.move(op1.gpr(), result.gpr()); 936 m_jit.add32(Imm32(imm2), result.gpr()); 937 } else 938 speculationCheck(m_jit.branchAdd32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr())); 925 939 926 940 integerResult(result.gpr(), m_compileIndex); … … 935 949 GPRReg gpr2 = op2.gpr(); 936 950 GPRReg gprResult = result.gpr(); 937 MacroAssembler::Jump check = m_jit.branchAdd32(MacroAssembler::Overflow, gpr1, gpr2, gprResult); 938 939 if (gpr1 == gprResult) 940 speculationCheck(check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr2)); 941 else if (gpr2 == gprResult) 942 speculationCheck(check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr1)); 943 else 944 speculationCheck(check); 951 952 if (nodeCanTruncateInteger(node.arithNodeFlags())) { 953 if (gpr1 == gprResult) 954 m_jit.add32(gpr2, gprResult); 955 else { 956 m_jit.move(gpr2, gprResult); 957 m_jit.add32(gpr1, gprResult); 958 } 959 } else { 960 MacroAssembler::Jump check = m_jit.branchAdd32(MacroAssembler::Overflow, gpr1, gpr2, gprResult); 961 962 if (gpr1 == gprResult) 963 speculationCheck(check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr2)); 964 else if (gpr2 == gprResult) 965 speculationCheck(check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr1)); 966 else 967 speculationCheck(check); 968 } 945 969 946 970 integerResult(gprResult, m_compileIndex); … … 948 972 } 949 973 950 // Fall through to safe cases.951 }952 953 case ValueAddSafe:954 case ArithAddSafe: {955 974 if (shouldSpeculateNumber(node.child1(), node.child2())) { 956 975 SpeculateDoubleOperand op1(this, node.child1()); … … 966 985 } 967 986 968 ASSERT(op == ValueAdd || op == ValueAddSafe);987 ASSERT(op == ValueAdd); 969 988 970 989 JSValueOperand op1(this, node.child1()); … … 987 1006 988 1007 case ArithSub: { 989 if (shouldSpeculateInteger(node.child1(), node.child2()) ) {1008 if (shouldSpeculateInteger(node.child1(), node.child2()) && nodeCanSpeculateInteger(node.arithNodeFlags())) { 990 1009 if (isInt32Constant(node.child2())) { 991 1010 SpeculateIntegerOperand op1(this, node.child1()); … … 993 1012 GPRTemporary result(this); 994 1013 995 speculationCheck(m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr())); 1014 if (nodeCanTruncateInteger(node.arithNodeFlags())) { 1015 m_jit.move(op1.gpr(), result.gpr()); 1016 m_jit.sub32(Imm32(imm2), result.gpr()); 1017 } else 1018 speculationCheck(m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr())); 996 1019 997 1020 integerResult(result.gpr(), m_compileIndex); … … 1003 1026 GPRTemporary result(this); 1004 1027 1005 speculationCheck(m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), op2.gpr(), result.gpr())); 1028 if (nodeCanTruncateInteger(node.arithNodeFlags())) { 1029 m_jit.move(op1.gpr(), result.gpr()); 1030 m_jit.sub32(op2.gpr(), result.gpr()); 1031 } else 1032 speculationCheck(m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), op2.gpr(), result.gpr())); 1006 1033 1007 1034 integerResult(result.gpr(), m_compileIndex); … … 1009 1036 } 1010 1037 1011 // Fall through to safe case.1012 }1013 1014 case ArithSubSafe: {1015 1038 SpeculateDoubleOperand op1(this, node.child1()); 1016 1039 SpeculateDoubleOperand op2(this, node.child2()); … … 1025 1048 } 1026 1049 1027 case ArithMulSpecNotNegZero: 1028 case ArithMulPossiblyNegZero: 1029 case ArithMulIgnoreZero: { 1030 if (shouldSpeculateInteger(node.child1(), node.child2())) { 1050 case ArithMul: { 1051 if (shouldSpeculateInteger(node.child1(), node.child2()) && nodeCanSpeculateInteger(node.arithNodeFlags())) { 1031 1052 SpeculateIntegerOperand op1(this, node.child1()); 1032 1053 SpeculateIntegerOperand op2(this, node.child2()); … … 1035 1056 GPRReg reg1 = op1.gpr(); 1036 1057 GPRReg reg2 = op2.gpr(); 1058 1059 // What is unfortunate is that we cannot take advantage of nodeCanTruncateInteger() 1060 // here. A multiply on integers performed in the double domain and then truncated to 1061 // an integer will give a different result than a multiply performed in the integer 1062 // domain and then truncated, if the integer domain result would have resulted in 1063 // something bigger than what a 32-bit integer can hold. JavaScript mandates that 1064 // the semantics are always as if the multiply had been performed in the double 1065 // domain. 1066 1037 1067 speculationCheck(m_jit.branchMul32(MacroAssembler::Overflow, reg1, reg2, result.gpr())); 1038 1039 // Only the ArithMulSpecNotNegZero opcode requires that we actually turn 1040 // negative zero into a double. The other two mean that all users of this 1041 // result don't care if it's a positive or negative zero. 1042 if (op == ArithMulSpecNotNegZero) { 1068 1069 // Check for negative zero, if the users of this node care about such things. 1070 if (!nodeCanIgnoreNegativeZero(node.arithNodeFlags())) { 1043 1071 MacroAssembler::Jump resultNonZero = m_jit.branchTest32(MacroAssembler::NonZero, result.gpr()); 1044 1072 speculationCheck(m_jit.branch32(MacroAssembler::LessThan, reg1, TrustedImm32(0))); … … 1051 1079 } 1052 1080 1053 // Fall through to safe case.1054 }1055 1056 case ArithMulSafe: {1057 1081 SpeculateDoubleOperand op1(this, node.child1()); 1058 1082 SpeculateDoubleOperand op2(this, node.child2()); … … 1110 1134 1111 1135 case ArithAbs: { 1112 if (shouldSpeculateInteger(node.child1()) ) {1136 if (shouldSpeculateInteger(node.child1()) && nodeCanSpeculateInteger(node.arithNodeFlags())) { 1113 1137 SpeculateIntegerOperand op1(this, node.child1()); 1114 1138 GPRTemporary result(this, op1); … … 1137 1161 case ArithMin: 1138 1162 case ArithMax: { 1139 if (shouldSpeculateInteger(node.child1(), node.child2()) ) {1163 if (shouldSpeculateInteger(node.child1(), node.child2()) && nodeCanSpeculateInteger(node.arithNodeFlags())) { 1140 1164 SpeculateStrictInt32Operand op1(this, node.child1()); 1141 1165 SpeculateStrictInt32Operand op2(this, node.child2()); … … 1917 1941 bool found = false; 1918 1942 1919 if (nodePtr->op == UInt32ToNumber || nodePtr->op == UInt32ToNumberSafe) {1943 if (nodePtr->op == UInt32ToNumber) { 1920 1944 NodeIndex nodeIndex = nodePtr->child1(); 1921 1945 nodePtr = &m_jit.graph()[nodeIndex]; … … 1948 1972 break; 1949 1973 case UInt32ToNumber: 1950 case UInt32ToNumberSafe:1951 1974 uint32ToNumberIndex = info.nodeIndex(); 1952 1975 break; -
trunk/Source/JavaScriptCore/jit/JITArithmetic.cpp
r95484 r95563 779 779 emitJumpSlowCaseIfNotImmediateInteger(regT0); 780 780 emitJumpSlowCaseIfNotImmediateInteger(regT1); 781 #if ENABLE(VALUE_PROFILER) 782 RareCaseProfile* profile = m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset); 783 #endif 781 784 if (opcodeID == op_add) 782 785 addSlowCase(branchAdd32(Overflow, regT1, regT0)); … … 801 804 // so that the speculative JIT knows that we failed speculation 802 805 // because of a negative zero. 803 add32(Imm32(1), AbsoluteAddress(& m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset)->m_counter));806 add32(Imm32(1), AbsoluteAddress(&profile->m_counter)); 804 807 addSlowCase(jump()); 805 808 done.link(this); … … 965 968 int32_t value; 966 969 if (isOperandConstantImmediateInt(op1) && ((value = getConstantOperandImmediateInt(op1)) > 0)) { 970 #if ENABLE(VALUE_PROFILER) 971 // Add a special fast case profile because the DFG JIT will expect one. 972 m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset); 973 #endif 967 974 emitGetVirtualRegister(op2, regT0); 968 975 emitJumpSlowCaseIfNotImmediateInteger(regT0); … … 970 977 emitFastArithReTagImmediate(regT0, regT0); 971 978 } else if (isOperandConstantImmediateInt(op2) && ((value = getConstantOperandImmediateInt(op2)) > 0)) { 979 #if ENABLE(VALUE_PROFILER) 980 // Add a special fast case profile because the DFG JIT will expect one. 981 m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset); 982 #endif 972 983 emitGetVirtualRegister(op1, regT0); 973 984 emitJumpSlowCaseIfNotImmediateInteger(regT0);
Note: See TracChangeset
for help on using the changeset viewer.