Changeset 167600 in webkit
- Timestamp:
- Apr 21, 2014, 11:43:01 AM (11 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 1 added
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/CMakeLists.txt
r167530 r167600 198 198 dfg/DFGValidate.cpp 199 199 dfg/DFGValueSource.cpp 200 dfg/DFGVariableAccessData.cpp 200 201 dfg/DFGVariableAccessDataDump.cpp 201 202 dfg/DFGVariableEvent.cpp -
trunk/Source/JavaScriptCore/ChangeLog
r167599 r167600 1 2014-04-19 Filip Pizlo <fpizlo@apple.com> 2 3 Take block execution count estimates into account when voting double 4 https://bugs.webkit.org/show_bug.cgi?id=131906 5 6 Reviewed by Geoffrey Garen. 7 8 This was a drama in three acts. 9 10 Act I: Slurp in BasicBlock::executionCount and use it as a weight when counting the 11 number of uses of a variable that want double or non-double. Easy as pie. This 12 gave me a huge speed-up on FloatMM and a huge slow-down on basically everything 13 else. 14 15 Act II: Realize that there were some programs where our previous double voting was 16 just on the edge of disaster and making it more precise tipped it over. In 17 particular, if you had an integer variable that would infrequently be used in a 18 computation that resulted in a variable that was frequently used as an array index, 19 the outer infrequentness would be the thing we'd use in the vote. So, an array 20 index would become double. We fix this by reviving global backwards propagation 21 and introducing the concept of ReallyWantsInt, which is used just for array 22 indices. Any variable transitively flagged as ReallyWantsInt will never be forced 23 double. We need that flag to be separate from UsedAsInt, since UsedAsInt needs to 24 be set in bitops for RageConversion but using it for double forcing is too much. 25 Basically, it's cheaper to have to convert a double to an int for a bitop than it 26 is to convert a double to an int for an array index; also a variable being used as 27 an array index is a much stronger hint that it ought to be an int. This recovered 28 performance on everything except programs that used FTL OSR entry. 29 30 Act III: Realize that OSR entrypoint creation creates blocks that have NaN execution 31 count, which then completely pollutes the weighting - essentially all votes go 32 NaN. Fix this with some surgical defenses. Basically, any client of execution 33 counts should allow for them to be NaN and shouldn't completely fall off a cliff 34 when it happens. 35 36 This is awesome. 75% speed-up on FloatMM. 11% speed-up on audio-dft. This leads to 37 7% speed-up on AsmBench and 2% speed-up on Kraken. 38 39 * CMakeLists.txt: 40 * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj: 41 * JavaScriptCore.xcodeproj/project.pbxproj: 42 * dfg/DFGBackwardsPropagationPhase.cpp: 43 (JSC::DFG::BackwardsPropagationPhase::run): 44 (JSC::DFG::BackwardsPropagationPhase::propagate): 45 * dfg/DFGGraph.cpp: 46 (JSC::DFG::Graph::dumpBlockHeader): 47 * dfg/DFGGraph.h: 48 (JSC::DFG::Graph::voteNode): 49 (JSC::DFG::Graph::voteChildren): 50 * dfg/DFGNodeFlags.cpp: 51 (JSC::DFG::dumpNodeFlags): 52 * dfg/DFGNodeFlags.h: 53 * dfg/DFGOSREntrypointCreationPhase.cpp: 54 (JSC::DFG::OSREntrypointCreationPhase::run): 55 * dfg/DFGPlan.cpp: 56 (JSC::DFG::Plan::compileInThreadImpl): 57 * dfg/DFGPredictionPropagationPhase.cpp: 58 (JSC::DFG::PredictionPropagationPhase::doDoubleVoting): 59 (JSC::DFG::PredictionPropagationPhase::doRoundOfDoubleVoting): 60 * dfg/DFGVariableAccessData.cpp: Added. 61 (JSC::DFG::VariableAccessData::VariableAccessData): 62 (JSC::DFG::VariableAccessData::mergeIsCaptured): 63 (JSC::DFG::VariableAccessData::mergeShouldNeverUnbox): 64 (JSC::DFG::VariableAccessData::predict): 65 (JSC::DFG::VariableAccessData::mergeArgumentAwarePrediction): 66 (JSC::DFG::VariableAccessData::shouldUseDoubleFormatAccordingToVote): 67 (JSC::DFG::VariableAccessData::tallyVotesForShouldUseDoubleFormat): 68 (JSC::DFG::VariableAccessData::mergeDoubleFormatState): 69 (JSC::DFG::VariableAccessData::makePredictionForDoubleFormat): 70 (JSC::DFG::VariableAccessData::flushFormat): 71 * dfg/DFGVariableAccessData.h: 72 (JSC::DFG::VariableAccessData::vote): 73 (JSC::DFG::VariableAccessData::VariableAccessData): Deleted. 74 (JSC::DFG::VariableAccessData::mergeIsCaptured): Deleted. 75 (JSC::DFG::VariableAccessData::mergeShouldNeverUnbox): Deleted. 76 (JSC::DFG::VariableAccessData::predict): Deleted. 77 (JSC::DFG::VariableAccessData::mergeArgumentAwarePrediction): Deleted. 78 (JSC::DFG::VariableAccessData::shouldUseDoubleFormatAccordingToVote): Deleted. 79 (JSC::DFG::VariableAccessData::tallyVotesForShouldUseDoubleFormat): Deleted. 80 (JSC::DFG::VariableAccessData::mergeDoubleFormatState): Deleted. 81 (JSC::DFG::VariableAccessData::makePredictionForDoubleFormat): Deleted. 82 (JSC::DFG::VariableAccessData::flushFormat): Deleted. 83 1 84 2014-04-21 Michael Saboff <msaboff@apple.com> 2 85 -
trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
r167530 r167600 451 451 <ClCompile Include="..\dfg\DFGValidate.cpp" /> 452 452 <ClCompile Include="..\dfg\DFGValueSource.cpp" /> 453 <ClCompile Include="..\dfg\DFGVariableAccessData.cpp" /> 453 454 <ClCompile Include="..\dfg\DFGVariableAccessDataDump.cpp" /> 454 455 <ClCompile Include="..\dfg\DFGVariableEvent.cpp" /> -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r167530 r167600 326 326 0F6B1CC918641DF800845D97 /* ArityCheckFailReturnThunks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F6B1CC718641DF800845D97 /* ArityCheckFailReturnThunks.cpp */; }; 327 327 0F6B1CCA18641DF800845D97 /* ArityCheckFailReturnThunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6B1CC818641DF800845D97 /* ArityCheckFailReturnThunks.h */; settings = {ATTRIBUTES = (Private, ); }; }; 328 0F6E845A19030BEF00562741 /* DFGVariableAccessData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F6E845919030BEF00562741 /* DFGVariableAccessData.cpp */; }; 328 329 0F7025A91714B0FA00382C0E /* DFGOSRExitCompilerCommon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F7025A71714B0F800382C0E /* DFGOSRExitCompilerCommon.cpp */; }; 329 330 0F7025AA1714B0FC00382C0E /* DFGOSRExitCompilerCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7025A81714B0F800382C0E /* DFGOSRExitCompilerCommon.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 2128 2129 0F6B1CC718641DF800845D97 /* ArityCheckFailReturnThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArityCheckFailReturnThunks.cpp; sourceTree = "<group>"; }; 2129 2130 0F6B1CC818641DF800845D97 /* ArityCheckFailReturnThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArityCheckFailReturnThunks.h; sourceTree = "<group>"; }; 2131 0F6E845919030BEF00562741 /* DFGVariableAccessData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGVariableAccessData.cpp; path = dfg/DFGVariableAccessData.cpp; sourceTree = "<group>"; }; 2130 2132 0F7025A71714B0F800382C0E /* DFGOSRExitCompilerCommon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGOSRExitCompilerCommon.cpp; path = dfg/DFGOSRExitCompilerCommon.cpp; sourceTree = "<group>"; }; 2131 2133 0F7025A81714B0F800382C0E /* DFGOSRExitCompilerCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGOSRExitCompilerCommon.h; path = dfg/DFGOSRExitCompilerCommon.h; sourceTree = "<group>"; }; … … 4811 4813 0F2BDC4E15228BE700CD8910 /* DFGValueSource.cpp */, 4812 4814 0F2BDC401522801700CD8910 /* DFGValueSource.h */, 4815 0F6E845919030BEF00562741 /* DFGVariableAccessData.cpp */, 4813 4816 0F620172143FCD2F0068B77C /* DFGVariableAccessData.h */, 4814 4817 0FDDBFB21666EED500C55FEF /* DFGVariableAccessDataDump.cpp */, … … 7089 7092 BCDD51EB0FB8DF74004A8BDC /* JITOpcodes.cpp in Sources */, 7090 7093 A71236E51195F33C00BD2174 /* JITOpcodes32_64.cpp in Sources */, 7094 0F6E845A19030BEF00562741 /* DFGVariableAccessData.cpp in Sources */, 7091 7095 0F24E54C17EE274900ABB217 /* JITOperations.cpp in Sources */, 7092 7096 86CC85C40EE7A89400288682 /* JITPropertyAccess.cpp in Sources */, -
trunk/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp
r167325 r167600 45 45 bool run() 46 46 { 47 for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) { 48 BasicBlock* block = m_graph.block(blockIndex); 49 if (!block) 50 continue; 51 52 // Prevent a tower of overflowing additions from creating a value that is out of the 53 // safe 2^48 range. 54 m_allowNestedOverflowingAdditions = block->size() < (1 << 16); 55 56 for (unsigned indexInBlock = block->size(); indexInBlock--;) 57 propagate(block->at(indexInBlock)); 47 m_changed = true; 48 while (m_changed) { 49 m_changed = false; 50 for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) { 51 BasicBlock* block = m_graph.block(blockIndex); 52 if (!block) 53 continue; 54 55 // Prevent a tower of overflowing additions from creating a value that is out of the 56 // safe 2^48 range. 57 m_allowNestedOverflowingAdditions = block->size() < (1 << 16); 58 59 for (unsigned indexInBlock = block->size(); indexInBlock--;) 60 propagate(block->at(indexInBlock)); 61 } 58 62 } 59 63 … … 175 179 case GetLocal: { 176 180 VariableAccessData* variableAccessData = node->variableAccessData(); 177 variableAccessData->mergeFlags(flags); 181 flags &= ~NodeBytecodeUsesAsInt; // We don't care about cross-block uses-as-int. 182 m_changed |= variableAccessData->mergeFlags(flags); 178 183 break; 179 184 } … … 183 188 if (!variableAccessData->isLoadedFrom()) 184 189 break; 185 node->child1()->mergeFlags(NodeBytecodeUsesAsValue); 190 flags = variableAccessData->flags(); 191 RELEASE_ASSERT(!(flags & ~NodeBytecodeBackPropMask)); 192 flags |= NodeBytecodeUsesAsNumber; // Account for the fact that control flow may cause overflows that our modeling can't handle. 193 node->child1()->mergeFlags(flags); 194 break; 195 } 196 197 case Flush: { 198 VariableAccessData* variableAccessData = node->variableAccessData(); 199 m_changed |= variableAccessData->mergeFlags(NodeBytecodeUsesAsValue); 186 200 break; 187 201 } … … 200 214 flags |= NodeBytecodeUsesAsInt; 201 215 flags &= ~(NodeBytecodeUsesAsNumber | NodeBytecodeNeedsNegZero | NodeBytecodeUsesAsOther); 216 flags &= ~NodeBytecodeUsesAsArrayIndex; 202 217 node->child1()->mergeFlags(flags); 203 218 node->child2()->mergeFlags(flags); … … 207 222 case StringCharCodeAt: { 208 223 node->child1()->mergeFlags(NodeBytecodeUsesAsValue); 209 node->child2()->mergeFlags(NodeBytecodeUsesAsValue | NodeBytecodeUsesAsInt );224 node->child2()->mergeFlags(NodeBytecodeUsesAsValue | NodeBytecodeUsesAsInt | NodeBytecodeUsesAsArrayIndex); 210 225 break; 211 226 } … … 306 321 case GetByVal: { 307 322 node->child1()->mergeFlags(NodeBytecodeUsesAsValue); 308 node->child2()->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther | NodeBytecodeUsesAsInt );323 node->child2()->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther | NodeBytecodeUsesAsInt | NodeBytecodeUsesAsArrayIndex); 309 324 break; 310 325 } 311 326 312 327 case GetMyArgumentByValSafe: { 313 node->child1()->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther | NodeBytecodeUsesAsInt );328 node->child1()->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther | NodeBytecodeUsesAsInt | NodeBytecodeUsesAsArrayIndex); 314 329 break; 315 330 } 316 331 317 332 case NewArrayWithSize: { 318 node->child1()->mergeFlags(NodeBytecodeUsesAsValue | NodeBytecodeUsesAsInt );333 node->child1()->mergeFlags(NodeBytecodeUsesAsValue | NodeBytecodeUsesAsInt | NodeBytecodeUsesAsArrayIndex); 319 334 break; 320 335 } … … 324 339 // in that you would get a different exception message. So, like, whatever: we 325 340 // claim here that NaN v. undefined is observable. 326 node->child1()->mergeFlags(NodeBytecodeUsesAsInt | NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther );341 node->child1()->mergeFlags(NodeBytecodeUsesAsInt | NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther | NodeBytecodeUsesAsArrayIndex); 327 342 break; 328 343 } … … 330 345 case StringCharAt: { 331 346 node->child1()->mergeFlags(NodeBytecodeUsesAsValue); 332 node->child2()->mergeFlags(NodeBytecodeUsesAsValue | NodeBytecodeUsesAsInt );347 node->child2()->mergeFlags(NodeBytecodeUsesAsValue | NodeBytecodeUsesAsInt | NodeBytecodeUsesAsArrayIndex); 333 348 break; 334 349 } … … 347 362 case PutByVal: { 348 363 m_graph.varArgChild(node, 0)->mergeFlags(NodeBytecodeUsesAsValue); 349 m_graph.varArgChild(node, 1)->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther | NodeBytecodeUsesAsInt );364 m_graph.varArgChild(node, 1)->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther | NodeBytecodeUsesAsInt | NodeBytecodeUsesAsArrayIndex); 350 365 m_graph.varArgChild(node, 2)->mergeFlags(NodeBytecodeUsesAsValue); 351 366 break; … … 397 412 398 413 bool m_allowNestedOverflowingAdditions; 414 bool m_changed; 399 415 }; 400 416 -
trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp
r167467 r167600 358 358 { 359 359 out.print(prefix, "Block ", *block, " (", inContext(block->at(0)->origin.semantic, context), "): ", block->isReachable ? "" : "(skipped)", block->isOSRTarget ? " (OSR target)" : "", "\n"); 360 if (block->executionCount == block->executionCount) 361 out.print(prefix, " Execution count: ", block->executionCount, "\n"); 360 362 out.print(prefix, " Predecessors:"); 361 363 for (size_t i = 0; i < block->predecessors.size(); ++i) -
trunk/Source/JavaScriptCore/dfg/DFGGraph.h
r167467 r167600 702 702 } 703 703 704 void voteNode(Node* node, unsigned ballot )704 void voteNode(Node* node, unsigned ballot, float weight = 1) 705 705 { 706 706 switch (node->op()) { … … 714 714 715 715 if (node->op() == GetLocal) 716 node->variableAccessData()->vote(ballot );717 } 718 719 void voteNode(Edge edge, unsigned ballot )720 { 721 voteNode(edge.node(), ballot );722 } 723 724 void voteChildren(Node* node, unsigned ballot )716 node->variableAccessData()->vote(ballot, weight); 717 } 718 719 void voteNode(Edge edge, unsigned ballot, float weight = 1) 720 { 721 voteNode(edge.node(), ballot, weight); 722 } 723 724 void voteChildren(Node* node, unsigned ballot, float weight = 1) 725 725 { 726 726 if (node->flags() & NodeHasVarArgs) { … … 729 729 childIdx++) { 730 730 if (!!m_varArgChildren[childIdx]) 731 voteNode(m_varArgChildren[childIdx], ballot );731 voteNode(m_varArgChildren[childIdx], ballot, weight); 732 732 } 733 733 return; … … 736 736 if (!node->child1()) 737 737 return; 738 voteNode(node->child1(), ballot );738 voteNode(node->child1(), ballot, weight); 739 739 if (!node->child2()) 740 740 return; 741 voteNode(node->child2(), ballot );741 voteNode(node->child2(), ballot, weight); 742 742 if (!node->child3()) 743 743 return; 744 voteNode(node->child3(), ballot );744 voteNode(node->child3(), ballot, weight); 745 745 } 746 746 -
trunk/Source/JavaScriptCore/dfg/DFGNodeFlags.cpp
r167325 r167600 100 100 if (flags & NodeBytecodeUsesAsInt) 101 101 out.print(comma, "UseAsInt"); 102 103 if (flags & NodeBytecodeUsesAsArrayIndex) 104 out.print(comma, "ReallyWantsInt"); 102 105 103 106 if (!(flags & NodeDoesNotExit)) -
trunk/Source/JavaScriptCore/dfg/DFGNodeFlags.h
r167325 r167600 54 54 #define NodeMayNegZero 0x0100 55 55 56 #define NodeBytecodeBackPropMask 0x 1E0056 #define NodeBytecodeBackPropMask 0x3E00 57 57 #define NodeBytecodeUseBottom 0x0000 58 58 #define NodeBytecodeUsesAsNumber 0x0200 // The result of this computation may be used in a context that observes fractional, or bigger-than-int32, results. … … 61 61 #define NodeBytecodeUsesAsValue (NodeBytecodeUsesAsNumber | NodeBytecodeNeedsNegZero | NodeBytecodeUsesAsOther) 62 62 #define NodeBytecodeUsesAsInt 0x1000 // The result of this computation is known to be used in a context that prefers, but does not require, integer values. 63 #define NodeBytecodeUsesAsArrayIndex 0x2000 // The result of this computation is known to be used in a context that strongly prefers integer values, to the point that we should avoid using doubles if at all possible. 63 64 64 65 #define NodeArithFlagsMask (NodeBehaviorMask | NodeBytecodeBackPropMask) 65 66 66 #define NodeDoesNotExit 0x 2000 // This flag is negated to make it natural for the default to be that a node does exit.67 #define NodeDoesNotExit 0x4000 // This flag is negated to make it natural for the default to be that a node does exit. 67 68 68 #define NodeRelevantToOSR 0x 400069 #define NodeRelevantToOSR 0x8000 69 70 70 #define NodeIsFlushed 0x8000 // Used by Graph::computeIsFlushed(), will tell you which local nodes are backwards-reachable from a Flush.71 #define NodeIsFlushed 0x10000 // Used by Graph::computeIsFlushed(), will tell you which local nodes are backwards-reachable from a Flush. 71 72 72 73 typedef uint32_t NodeFlags; -
trunk/Source/JavaScriptCore/dfg/DFGOSREntrypointCreationPhase.cpp
r167394 r167600 84 84 BlockInsertionSet insertionSet(m_graph); 85 85 86 BasicBlock* newRoot = insertionSet.insert(0, PNaN); 86 // We say that the execution count of the entry block is 1, because we know for sure 87 // that this must be the case. Under our definition of executionCount, "1" means "once 88 // per invocation". We could have said NaN here, since that would ask any clients of 89 // executionCount to use best judgement - but that seems unnecessary since we know for 90 // sure what the executionCount should be in this case. 91 BasicBlock* newRoot = insertionSet.insert(0, 1); 87 92 NodeOrigin origin = target->at(0)->origin; 88 93 -
trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp
r167467 r167600 210 210 performPredictionInjection(dfg); 211 211 212 if (isFTL(mode)) 213 performStaticExecutionCountEstimation(dfg); 212 performStaticExecutionCountEstimation(dfg); 214 213 215 214 if (mode == FTLForOSREntryMode) { -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r167455 r167600 642 642 } 643 643 644 void doDoubleVoting(Node* node) 645 { 644 void doDoubleVoting(Node* node, float weight) 645 { 646 // Loop pre-headers created by OSR entrypoint creation may have NaN weight to indicate 647 // that we actually don't know they weight. Assume that they execute once. This turns 648 // out to be an OK assumption since the pre-header doesn't have any meaningful code. 649 if (weight != weight) 650 weight = 1; 651 646 652 switch (node->op()) { 647 653 case ValueAdd: … … 660 666 ballot = VoteValue; 661 667 662 m_graph.voteNode(node->child1(), ballot );663 m_graph.voteNode(node->child2(), ballot );668 m_graph.voteNode(node->child1(), ballot, weight); 669 m_graph.voteNode(node->child2(), ballot, weight); 664 670 break; 665 671 } … … 678 684 ballot = VoteValue; 679 685 680 m_graph.voteNode(node->child1(), ballot );681 m_graph.voteNode(node->child2(), ballot );686 m_graph.voteNode(node->child1(), ballot, weight); 687 m_graph.voteNode(node->child2(), ballot, weight); 682 688 break; 683 689 } … … 698 704 ballot = VoteValue; 699 705 700 m_graph.voteNode(node->child1(), ballot );701 m_graph.voteNode(node->child2(), ballot );706 m_graph.voteNode(node->child1(), ballot, weight); 707 m_graph.voteNode(node->child2(), ballot, weight); 702 708 break; 703 709 } … … 710 716 ballot = VoteValue; 711 717 712 m_graph.voteNode(node->child1(), ballot );718 m_graph.voteNode(node->child1(), ballot, weight); 713 719 break; 714 720 … … 716 722 case ArithCos: 717 723 case ArithSin: 718 m_graph.voteNode(node->child1(), VoteDouble );724 m_graph.voteNode(node->child1(), VoteDouble, weight); 719 725 break; 720 726 … … 722 728 SpeculatedType prediction = node->child1()->prediction(); 723 729 if (isDoubleSpeculation(prediction)) 724 node->variableAccessData()->vote(VoteDouble );730 node->variableAccessData()->vote(VoteDouble, weight); 725 731 else if ( 726 732 !isFullNumberSpeculation(prediction) 727 733 || isInt32Speculation(prediction) || isMachineIntSpeculation(prediction)) 728 node->variableAccessData()->vote(VoteValue );734 node->variableAccessData()->vote(VoteValue, weight); 729 735 break; 730 736 } … … 736 742 Edge child2 = m_graph.varArgChild(node, 1); 737 743 Edge child3 = m_graph.varArgChild(node, 2); 738 m_graph.voteNode(child1, VoteValue );739 m_graph.voteNode(child2, VoteValue );744 m_graph.voteNode(child1, VoteValue, weight); 745 m_graph.voteNode(child2, VoteValue, weight); 740 746 switch (node->arrayMode().type()) { 741 747 case Array::Double: 742 m_graph.voteNode(child3, VoteDouble );748 m_graph.voteNode(child3, VoteDouble, weight); 743 749 break; 744 750 default: 745 m_graph.voteNode(child3, VoteValue );751 m_graph.voteNode(child3, VoteValue, weight); 746 752 break; 747 753 } … … 754 760 755 761 default: 756 m_graph.voteChildren(node, VoteValue );762 m_graph.voteChildren(node, VoteValue, weight); 757 763 break; 758 764 } … … 770 776 for (unsigned i = 0; i < block->size(); ++i) { 771 777 m_currentNode = block->at(i); 772 doDoubleVoting(m_currentNode );778 doDoubleVoting(m_currentNode, block->executionCount); 773 779 } 774 780 } -
trunk/Source/JavaScriptCore/dfg/DFGVariableAccessData.h
r167394 r167600 1 1 /* 2 * Copyright (C) 2011 , 2012, 2013Apple Inc. All rights reserved.2 * Copyright (C) 2011-2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 27 27 #define DFGVariableAccessData_h 28 28 29 #if ENABLE(DFG_JIT) 30 29 31 #include "DFGCommon.h" 30 32 #include "DFGDoubleFormatState.h" … … 46 48 class VariableAccessData : public UnionFind<VariableAccessData> { 47 49 public: 48 VariableAccessData() 49 : m_local(static_cast<VirtualRegister>(std::numeric_limits<int>::min())) 50 , m_prediction(SpecNone) 51 , m_argumentAwarePrediction(SpecNone) 52 , m_flags(0) 53 , m_isCaptured(false) 54 , m_shouldNeverUnbox(false) 55 , m_isArgumentsAlias(false) 56 , m_structureCheckHoistingFailed(false) 57 , m_checkArrayHoistingFailed(false) 58 , m_isProfitableToUnbox(false) 59 , m_isLoadedFrom(false) 60 , m_doubleFormatState(EmptyDoubleFormatState) 61 { 62 clearVotes(); 63 } 64 65 VariableAccessData(VirtualRegister local, bool isCaptured) 66 : m_local(local) 67 , m_prediction(SpecNone) 68 , m_argumentAwarePrediction(SpecNone) 69 , m_flags(0) 70 , m_isCaptured(isCaptured) 71 , m_shouldNeverUnbox(isCaptured) 72 , m_isArgumentsAlias(false) 73 , m_structureCheckHoistingFailed(false) 74 , m_checkArrayHoistingFailed(false) 75 , m_isProfitableToUnbox(false) 76 , m_isLoadedFrom(false) 77 , m_doubleFormatState(EmptyDoubleFormatState) 78 { 79 clearVotes(); 80 } 50 VariableAccessData(); 51 VariableAccessData(VirtualRegister local, bool isCaptured); 81 52 82 53 VirtualRegister local() … … 92 63 } 93 64 94 bool mergeIsCaptured(bool isCaptured) 95 { 96 return checkAndSet(m_shouldNeverUnbox, m_shouldNeverUnbox | isCaptured) 97 | checkAndSet(m_isCaptured, m_isCaptured | isCaptured); 98 } 65 bool mergeIsCaptured(bool isCaptured); 99 66 100 67 bool isCaptured() … … 113 80 } 114 81 115 bool mergeShouldNeverUnbox(bool shouldNeverUnbox) 116 { 117 bool newShouldNeverUnbox = m_shouldNeverUnbox | shouldNeverUnbox; 118 if (newShouldNeverUnbox == m_shouldNeverUnbox) 119 return false; 120 m_shouldNeverUnbox = newShouldNeverUnbox; 121 return true; 122 } 82 bool mergeShouldNeverUnbox(bool shouldNeverUnbox); 123 83 124 84 // Returns true if it would be unsound to store the value in an unboxed fashion. … … 184 144 } 185 145 186 bool predict(SpeculatedType prediction) 187 { 188 VariableAccessData* self = find(); 189 bool result = mergeSpeculation(self->m_prediction, prediction); 190 if (result) 191 mergeSpeculation(m_argumentAwarePrediction, m_prediction); 192 return result; 193 } 146 bool predict(SpeculatedType prediction); 194 147 195 148 SpeculatedType nonUnifiedPrediction() … … 208 161 } 209 162 210 bool mergeArgumentAwarePrediction(SpeculatedType prediction) 211 { 212 return mergeSpeculation(find()->m_argumentAwarePrediction, prediction); 213 } 163 bool mergeArgumentAwarePrediction(SpeculatedType prediction); 214 164 215 165 void clearVotes() … … 220 170 } 221 171 222 void vote(unsigned ballot )172 void vote(unsigned ballot, float weight = 1) 223 173 { 224 174 ASSERT(ballot < 2); 225 m_votes[ballot] ++;175 m_votes[ballot] += weight; 226 176 } 227 177 … … 232 182 } 233 183 234 bool shouldUseDoubleFormatAccordingToVote() 235 { 236 // We don't support this facility for arguments, yet. 237 // FIXME: make this work for arguments. 238 if (local().isArgument()) 239 return false; 240 241 // If the variable is not a number prediction, then this doesn't 242 // make any sense. 243 if (!isFullNumberSpeculation(prediction())) { 244 // FIXME: we may end up forcing a local in inlined argument position to be a double even 245 // if it is sometimes not even numeric, since this never signals the fact that it doesn't 246 // want doubles. https://bugs.webkit.org/show_bug.cgi?id=109511 247 return false; 248 } 249 250 // If the variable is predicted to hold only doubles, then it's a 251 // no-brainer: it should be formatted as a double. 252 if (isDoubleSpeculation(prediction())) 253 return true; 254 255 // If the variable is known to be used as an integer, then be safe - 256 // don't force it to be a double. 257 if (flags() & NodeBytecodeUsesAsInt) 258 return false; 259 260 // If the variable has been voted to become a double, then make it a 261 // double. 262 if (voteRatio() >= Options::doubleVoteRatioForDoubleFormat()) 263 return true; 264 265 return false; 266 } 184 bool shouldUseDoubleFormatAccordingToVote(); 267 185 268 186 DoubleFormatState doubleFormatState() … … 280 198 } 281 199 282 bool tallyVotesForShouldUseDoubleFormat() 283 { 284 ASSERT(isRoot()); 285 286 if (local().isArgument() || shouldNeverUnbox()) 287 return DFG::mergeDoubleFormatState(m_doubleFormatState, NotUsingDoubleFormat); 288 289 if (m_doubleFormatState == CantUseDoubleFormat) 290 return false; 291 292 bool newValueOfShouldUseDoubleFormat = shouldUseDoubleFormatAccordingToVote(); 293 if (!newValueOfShouldUseDoubleFormat) { 294 // We monotonically convert to double. Hence, if the fixpoint leads us to conclude that we should 295 // switch back to int, we instead ignore this and stick with double. 296 return false; 297 } 298 299 if (m_doubleFormatState == UsingDoubleFormat) 300 return false; 301 302 return DFG::mergeDoubleFormatState(m_doubleFormatState, UsingDoubleFormat); 303 } 304 305 bool mergeDoubleFormatState(DoubleFormatState doubleFormatState) 306 { 307 return DFG::mergeDoubleFormatState(find()->m_doubleFormatState, doubleFormatState); 308 } 309 310 bool makePredictionForDoubleFormat() 311 { 312 ASSERT(isRoot()); 313 314 if (m_doubleFormatState != UsingDoubleFormat) 315 return false; 316 317 SpeculatedType type = m_prediction; 318 if (type & ~SpecBytecodeNumber) 319 type |= SpecDoublePureNaN; 320 if (type & SpecMachineInt) 321 type |= SpecInt52AsDouble; 322 return checkAndSet(m_prediction, type); 323 } 200 bool tallyVotesForShouldUseDoubleFormat(); 201 202 bool mergeDoubleFormatState(DoubleFormatState); 203 204 bool makePredictionForDoubleFormat(); 324 205 325 206 NodeFlags flags() const { return m_flags; } … … 330 211 } 331 212 332 FlushFormat flushFormat() 333 { 334 ASSERT(find() == this); 335 336 if (isArgumentsAlias()) 337 return FlushedArguments; 338 339 if (!shouldUnboxIfPossible()) 340 return FlushedJSValue; 341 342 if (shouldUseDoubleFormat()) 343 return FlushedDouble; 344 345 SpeculatedType prediction = argumentAwarePrediction(); 346 if (isInt32Speculation(prediction)) 347 return FlushedInt32; 348 349 if (enableInt52() && !m_local.isArgument() && isMachineIntSpeculation(prediction)) 350 return FlushedInt52; 351 352 if (isCellSpeculation(prediction)) 353 return FlushedCell; 354 355 if (isBooleanSpeculation(prediction)) 356 return FlushedBoolean; 357 358 return FlushedJSValue; 359 } 213 FlushFormat flushFormat(); 360 214 361 215 FlushedAt flushedAt() … … 390 244 } } // namespace JSC::DFG 391 245 246 #endif // ENABLE(DFG_JIT) 247 392 248 #endif // DFGVariableAccessData_h
Note:
See TracChangeset
for help on using the changeset viewer.