Changeset 97218 in webkit
- Timestamp:
- Oct 11, 2011 7:05:53 PM (13 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 6 added
- 1 deleted
- 22 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r97216 r97218 1 2011-10-08 Filip Pizlo <fpizlo@apple.com> 2 3 DFG does not have flow-sensitive intraprocedural control flow analysis 4 https://bugs.webkit.org/show_bug.cgi?id=69690 5 6 Reviewed by Gavin Barraclough. 7 8 Implemented a control flow analysis (CFA). It currently propagates type 9 proofs only. For example, if all predecessors to a basic block have 10 checks that variable X is a JSFinalObject with structure 0xabcdef, then 11 this basic block will now know this fact and will know that it does not 12 have to emit either JSFinalObject checks or any structure checks since 13 the structure is precisely known. The CFA takes heap side-effects into 14 account (though somewhat conservatively), so that if the object pointed 15 to by variable X could have possibly undergone a structure transition 16 then this is reflected: the analysis may simply say that X's structure 17 is unknown. 18 19 This also propagates a wealth of other type information which is 20 currently not being used. For example, we now know when a variable can 21 only hold doubles. Even if a variable may hold other types at different 22 points in its live range, we can still prove exactly when it will only 23 be double. 24 25 There's a bunch of stuff that the CFA could do that it still does not 26 do, like precise handling of PutStructure (i.e. structure transitions), 27 precise handling of CheckFunction and CheckMethod, etc. So this is 28 very much intended to be a starting point rather than an end unto 29 itself. 30 31 This is a 1% win on V8 (mostly due to a 3% win on richards and deltablue) 32 and a 1% win on Kraken (mostly due to a 6% win on imaging-desaturate). 33 Neutral on SunSpider. 34 35 * GNUmakefile.list.am: 36 * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: 37 * JavaScriptCore.xcodeproj/project.pbxproj: 38 * bytecode/ActionablePrediction.h: Removed. 39 * bytecode/PredictedType.cpp: 40 (JSC::predictionToString): 41 * bytecode/PredictedType.h: 42 * dfg/DFGAbstractState.cpp: Added. 43 (JSC::DFG::AbstractState::AbstractState): 44 (JSC::DFG::AbstractState::~AbstractState): 45 (JSC::DFG::AbstractState::beginBasicBlock): 46 (JSC::DFG::AbstractState::initialize): 47 (JSC::DFG::AbstractState::endBasicBlock): 48 (JSC::DFG::AbstractState::reset): 49 (JSC::DFG::AbstractState::execute): 50 (JSC::DFG::AbstractState::clobberStructures): 51 (JSC::DFG::AbstractState::mergeStateAtTail): 52 (JSC::DFG::AbstractState::merge): 53 (JSC::DFG::AbstractState::mergeToSuccessors): 54 (JSC::DFG::AbstractState::mergeVariableBetweenBlocks): 55 (JSC::DFG::AbstractState::dump): 56 * dfg/DFGAbstractState.h: Added. 57 (JSC::DFG::AbstractState::forNode): 58 (JSC::DFG::AbstractState::isValid): 59 * dfg/DFGAbstractValue.h: Added. 60 (JSC::DFG::StructureAbstractValue::StructureAbstractValue): 61 (JSC::DFG::StructureAbstractValue::clear): 62 (JSC::DFG::StructureAbstractValue::makeTop): 63 (JSC::DFG::StructureAbstractValue::top): 64 (JSC::DFG::StructureAbstractValue::add): 65 (JSC::DFG::StructureAbstractValue::addAll): 66 (JSC::DFG::StructureAbstractValue::contains): 67 (JSC::DFG::StructureAbstractValue::isSubsetOf): 68 (JSC::DFG::StructureAbstractValue::doesNotContainAnyOtherThan): 69 (JSC::DFG::StructureAbstractValue::isSupersetOf): 70 (JSC::DFG::StructureAbstractValue::filter): 71 (JSC::DFG::StructureAbstractValue::isClear): 72 (JSC::DFG::StructureAbstractValue::isTop): 73 (JSC::DFG::StructureAbstractValue::size): 74 (JSC::DFG::StructureAbstractValue::at): 75 (JSC::DFG::StructureAbstractValue::operator[]): 76 (JSC::DFG::StructureAbstractValue::last): 77 (JSC::DFG::StructureAbstractValue::predictionFromStructures): 78 (JSC::DFG::StructureAbstractValue::operator==): 79 (JSC::DFG::StructureAbstractValue::dump): 80 (JSC::DFG::AbstractValue::AbstractValue): 81 (JSC::DFG::AbstractValue::clear): 82 (JSC::DFG::AbstractValue::isClear): 83 (JSC::DFG::AbstractValue::makeTop): 84 (JSC::DFG::AbstractValue::clobberStructures): 85 (JSC::DFG::AbstractValue::isTop): 86 (JSC::DFG::AbstractValue::top): 87 (JSC::DFG::AbstractValue::set): 88 (JSC::DFG::AbstractValue::operator==): 89 (JSC::DFG::AbstractValue::merge): 90 (JSC::DFG::AbstractValue::filter): 91 (JSC::DFG::AbstractValue::validate): 92 (JSC::DFG::AbstractValue::dump): 93 * dfg/DFGBasicBlock.h: Added. 94 (JSC::DFG::BasicBlock::BasicBlock): 95 (JSC::DFG::BasicBlock::getBytecodeBegin): 96 * dfg/DFGByteCodeParser.cpp: 97 (JSC::DFG::ByteCodeParser::getLocal): 98 (JSC::DFG::ByteCodeParser::setLocal): 99 (JSC::DFG::ByteCodeParser::getArgument): 100 (JSC::DFG::ByteCodeParser::setArgument): 101 (JSC::DFG::ByteCodeParser::parseBlock): 102 (JSC::DFG::ByteCodeParser::processPhiStack): 103 (JSC::DFG::ByteCodeParser::setupPredecessors): 104 * dfg/DFGGraph.cpp: 105 (JSC::DFG::Graph::dump): 106 * dfg/DFGGraph.h: 107 * dfg/DFGJITCodeGenerator.h: 108 (JSC::DFG::block): 109 * dfg/DFGJITCodeGenerator32_64.cpp: 110 (JSC::DFG::JITCodeGenerator::nonSpeculativePeepholeBranchNull): 111 (JSC::DFG::JITCodeGenerator::nonSpeculativePeepholeBranch): 112 (JSC::DFG::JITCodeGenerator::nonSpeculativePeepholeStrictEq): 113 * dfg/DFGJITCodeGenerator64.cpp: 114 (JSC::DFG::JITCodeGenerator::nonSpeculativePeepholeBranchNull): 115 (JSC::DFG::JITCodeGenerator::nonSpeculativePeepholeBranch): 116 (JSC::DFG::JITCodeGenerator::nonSpeculativePeepholeStrictEq): 117 * dfg/DFGJITCompiler.h: 118 (JSC::DFG::JITCompiler::noticeOSREntry): 119 * dfg/DFGNode.h: 120 (JSC::DFG::NodeIndexTraits::defaultValue): 121 (JSC::DFG::Node::variableAccessData): 122 (JSC::DFG::Node::takenBytecodeOffsetDuringParsing): 123 (JSC::DFG::Node::notTakenBytecodeOffsetDuringParsing): 124 (JSC::DFG::Node::setTakenBlockIndex): 125 (JSC::DFG::Node::setNotTakenBlockIndex): 126 (JSC::DFG::Node::takenBlockIndex): 127 (JSC::DFG::Node::notTakenBlockIndex): 128 * dfg/DFGOSREntry.cpp: 129 (JSC::DFG::prepareOSREntry): 130 * dfg/DFGOSREntry.h: 131 * dfg/DFGOperands.h: Added. 132 (JSC::DFG::operandIsArgument): 133 (JSC::DFG::OperandValueTraits::defaultValue): 134 (JSC::DFG::Operands::Operands): 135 (JSC::DFG::Operands::numberOfArguments): 136 (JSC::DFG::Operands::numberOfLocals): 137 (JSC::DFG::Operands::argument): 138 (JSC::DFG::Operands::local): 139 (JSC::DFG::Operands::setLocal): 140 (JSC::DFG::Operands::setArgumentFirstTime): 141 (JSC::DFG::Operands::setLocalFirstTime): 142 (JSC::DFG::Operands::operand): 143 (JSC::DFG::Operands::setOperand): 144 (JSC::DFG::Operands::clear): 145 (JSC::DFG::dumpOperands): 146 * dfg/DFGPropagator.cpp: 147 (JSC::DFG::Propagator::fixpoint): 148 (JSC::DFG::Propagator::propagateArithNodeFlags): 149 (JSC::DFG::Propagator::propagateNodePredictions): 150 (JSC::DFG::Propagator::propagatePredictions): 151 (JSC::DFG::Propagator::performBlockCFA): 152 (JSC::DFG::Propagator::performForwardCFA): 153 (JSC::DFG::Propagator::globalCFA): 154 * dfg/DFGSpeculativeJIT.cpp: 155 (JSC::DFG::SpeculativeJIT::compilePeepHoleDoubleBranch): 156 (JSC::DFG::SpeculativeJIT::compilePeepHoleObjectEquality): 157 (JSC::DFG::SpeculativeJIT::compilePeepHoleIntegerBranch): 158 (JSC::DFG::SpeculativeJIT::compilePeepHoleBranch): 159 (JSC::DFG::SpeculativeJIT::compile): 160 (JSC::DFG::SpeculativeJIT::compileGetCharCodeAt): 161 (JSC::DFG::SpeculativeJIT::compileGetByValOnString): 162 * dfg/DFGSpeculativeJIT.h: 163 (JSC::DFG::SpeculativeJIT::SpeculativeJIT): 164 * dfg/DFGSpeculativeJIT32_64.cpp: 165 (JSC::DFG::SpeculativeJIT::compileObjectEquality): 166 (JSC::DFG::SpeculativeJIT::compare): 167 (JSC::DFG::SpeculativeJIT::compileObjectOrOtherLogicalNot): 168 (JSC::DFG::SpeculativeJIT::compileLogicalNot): 169 (JSC::DFG::SpeculativeJIT::emitObjectOrOtherBranch): 170 (JSC::DFG::SpeculativeJIT::emitBranch): 171 (JSC::DFG::SpeculativeJIT::compile): 172 * dfg/DFGSpeculativeJIT64.cpp: 173 (JSC::DFG::SpeculativeJIT::compileObjectEquality): 174 (JSC::DFG::SpeculativeJIT::compare): 175 (JSC::DFG::SpeculativeJIT::compileObjectOrOtherLogicalNot): 176 (JSC::DFG::SpeculativeJIT::compileLogicalNot): 177 (JSC::DFG::SpeculativeJIT::emitObjectOrOtherBranch): 178 (JSC::DFG::SpeculativeJIT::emitBranch): 179 (JSC::DFG::SpeculativeJIT::compile): 180 * dfg/DFGStructureSet.h: 181 (JSC::DFG::StructureSet::clear): 182 (JSC::DFG::StructureSet::predictionFromStructures): 183 (JSC::DFG::StructureSet::operator==): 184 (JSC::DFG::StructureSet::dump): 185 * dfg/DFGVariableAccessData.h: Added. 186 1 187 2011-10-11 Gavin Barraclough <baraclough@apple.com> 2 188 -
trunk/Source/JavaScriptCore/GNUmakefile.list.am
r96527 r97218 82 82 Source/JavaScriptCore/assembler/SH4Assembler.h \ 83 83 Source/JavaScriptCore/assembler/X86Assembler.h \ 84 Source/JavaScriptCore/bytecode/ActionablePrediction.h \85 84 Source/JavaScriptCore/bytecode/CodeBlock.cpp \ 86 85 Source/JavaScriptCore/bytecode/CodeBlock.h \ … … 106 105 Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp \ 107 106 Source/JavaScriptCore/bytecompiler/RegisterID.h \ 107 Source/JavaScriptCore/dfg/DFGAbstractState.cpp \ 108 Source/JavaScriptCore/dfg/DFGAbstractState.h \ 109 Source/JavaScriptCore/dfg/DFGAbstractValue.h \ 110 Source/JavaScriptCoer/dfg/DFGBasicBlock.h \ 108 111 Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp \ 109 112 Source/JavaScriptCore/dfg/DFGByteCodeParser.h \ … … 123 126 Source/JavaScriptCore/dfg/DFGJITCompiler.h \ 124 127 Source/JavaScriptCore/dfg/DFGNode.h \ 128 Source/JavaScriptCore/dfg/DFGOperands.h \ 125 129 Source/JavaScriptCore/dfg/DFGOperations.cpp \ 126 130 Source/JavaScriptCore/dfg/DFGOperations.h \ … … 136 140 Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h \ 137 141 Source/JavaScriptCore/dfg/DFGStructureSet.h \ 142 Source/JavaScriptCore/dfg/DFGVariableAccessData.h \ 138 143 Source/JavaScriptCore/heap/AllocationSpace.cpp \ 139 144 Source/JavaScriptCore/heap/AllocationSpace.h \ -
trunk/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
r96465 r97218 1439 1439 > 1440 1440 <File 1441 RelativePath="..\..\bytecode\ActionablePrediction.h"1442 >1443 </File>1444 <File1445 1441 RelativePath="..\..\bytecode\CodeBlock.cpp" 1446 1442 > … … 1586 1582 > 1587 1583 </File> 1584 <File 1585 RelativePath="..\..\dfg\DFGOSREntry.h" 1586 > 1587 </File> 1588 1588 </Filter> 1589 1589 <Filter -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r96881 r97218 52 52 0F16D726142C39C000CF784A /* BitVector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F16D724142C39A200CF784A /* BitVector.cpp */; }; 53 53 0F242DA713F3B1E8007ADD4C /* WeakReferenceHarvester.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F242DA513F3B1BB007ADD4C /* WeakReferenceHarvester.h */; settings = {ATTRIBUTES = (Private, ); }; }; 54 0F620174143FCD330068B77C /* DFGVariableAccessData.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F620172143FCD2F0068B77C /* DFGVariableAccessData.h */; settings = {ATTRIBUTES = (Private, ); }; }; 55 0F620175143FCD370068B77C /* DFGOperands.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F620171143FCD2F0068B77C /* DFGOperands.h */; settings = {ATTRIBUTES = (Private, ); }; }; 56 0F620176143FCD3B0068B77C /* DFGBasicBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F620170143FCD2F0068B77C /* DFGBasicBlock.h */; settings = {ATTRIBUTES = (Private, ); }; }; 57 0F620177143FCD3F0068B77C /* DFGAbstractValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F62016F143FCD2F0068B77C /* DFGAbstractValue.h */; settings = {ATTRIBUTES = (Private, ); }; }; 58 0F620178143FCD440068B77C /* DFGAbstractState.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F62016E143FCD2F0068B77C /* DFGAbstractState.h */; settings = {ATTRIBUTES = (Private, ); }; }; 59 0F620179143FCD480068B77C /* DFGAbstractState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F62016D143FCD2F0068B77C /* DFGAbstractState.cpp */; }; 54 60 0F636DA0142D27D700B2E66A /* PackedIntVector.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F636D9F142D27D200B2E66A /* PackedIntVector.h */; }; 55 0F636DA2142D27F000B2E66A /* ActionablePrediction.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F636DA1142D27ED00B2E66A /* ActionablePrediction.h */; };56 61 0F7700921402FF3C0078EB39 /* SamplingCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F7700911402FF280078EB39 /* SamplingCounter.cpp */; }; 57 62 0F963B2713F753BB0002D9B2 /* RedBlackTree.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F963B2613F753990002D9B2 /* RedBlackTree.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 810 815 0F16D724142C39A200CF784A /* BitVector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BitVector.cpp; sourceTree = "<group>"; }; 811 816 0F242DA513F3B1BB007ADD4C /* WeakReferenceHarvester.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakReferenceHarvester.h; sourceTree = "<group>"; }; 817 0F62016D143FCD2F0068B77C /* DFGAbstractState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGAbstractState.cpp; path = dfg/DFGAbstractState.cpp; sourceTree = "<group>"; }; 818 0F62016E143FCD2F0068B77C /* DFGAbstractState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAbstractState.h; path = dfg/DFGAbstractState.h; sourceTree = "<group>"; }; 819 0F62016F143FCD2F0068B77C /* DFGAbstractValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAbstractValue.h; path = dfg/DFGAbstractValue.h; sourceTree = "<group>"; }; 820 0F620170143FCD2F0068B77C /* DFGBasicBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGBasicBlock.h; path = dfg/DFGBasicBlock.h; sourceTree = "<group>"; }; 821 0F620171143FCD2F0068B77C /* DFGOperands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGOperands.h; path = dfg/DFGOperands.h; sourceTree = "<group>"; }; 822 0F620172143FCD2F0068B77C /* DFGVariableAccessData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGVariableAccessData.h; path = dfg/DFGVariableAccessData.h; sourceTree = "<group>"; }; 812 823 0F636D9F142D27D200B2E66A /* PackedIntVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PackedIntVector.h; sourceTree = "<group>"; }; 813 0F636DA1142D27ED00B2E66A /* ActionablePrediction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ActionablePrediction.h; sourceTree = "<group>"; };814 824 0F77008E1402FDD60078EB39 /* SamplingCounter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SamplingCounter.h; sourceTree = "<group>"; }; 815 825 0F7700911402FF280078EB39 /* SamplingCounter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SamplingCounter.cpp; sourceTree = "<group>"; }; … … 2284 2294 isa = PBXGroup; 2285 2295 children = ( 2296 0F62016D143FCD2F0068B77C /* DFGAbstractState.cpp */, 2297 0F62016E143FCD2F0068B77C /* DFGAbstractState.h */, 2298 0F62016F143FCD2F0068B77C /* DFGAbstractValue.h */, 2299 0F620170143FCD2F0068B77C /* DFGBasicBlock.h */, 2300 0F620171143FCD2F0068B77C /* DFGOperands.h */, 2301 0F620172143FCD2F0068B77C /* DFGVariableAccessData.h */, 2286 2302 0FFF4BB2143955E600655BC0 /* DFGStructureSet.h */, 2287 2303 86EC9DB41328DF82002B2AD7 /* DFGByteCodeParser.cpp */, … … 2385 2401 isa = PBXGroup; 2386 2402 children = ( 2387 0F636DA1142D27ED00B2E66A /* ActionablePrediction.h */,2388 2403 0FD82E8E14207A5100179C94 /* ValueProfile.cpp */, 2389 2404 0FD82E84141F3FDA00179C94 /* PredictedType.cpp */, … … 2871 2886 86FA9E92142BBB2E001773B7 /* JSBoundFunction.h in Headers */, 2872 2887 0F636DA0142D27D700B2E66A /* PackedIntVector.h in Headers */, 2873 0F636DA2142D27F000B2E66A /* ActionablePrediction.h in Headers */,2874 2888 A7521E131429169A003C8D0C /* CardSet.h in Headers */, 2875 2889 0FD52AAE143035A00026DC9F /* UnionFind.h in Headers */, … … 2878 2892 0FFF4BB4143955E900655BC0 /* DFGStructureSet.h in Headers */, 2879 2893 8604F505143CE1C200B295F5 /* JSGlobalThis.h in Headers */, 2894 0F620174143FCD330068B77C /* DFGVariableAccessData.h in Headers */, 2895 0F620175143FCD370068B77C /* DFGOperands.h in Headers */, 2896 0F620176143FCD3B0068B77C /* DFGBasicBlock.h in Headers */, 2897 0F620177143FCD3F0068B77C /* DFGAbstractValue.h in Headers */, 2898 0F620178143FCD440068B77C /* DFGAbstractState.h in Headers */, 2880 2899 ); 2881 2900 runOnlyForDeploymentPostprocessing = 0; … … 3409 3428 86880F4D14353B2100B08D42 /* DFGSpeculativeJIT64.cpp in Sources */, 3410 3429 0FE228EE1436AB2C00196C48 /* Heuristics.cpp in Sources */, 3430 0F620179143FCD480068B77C /* DFGAbstractState.cpp in Sources */, 3411 3431 ); 3412 3432 runOnlyForDeploymentPostprocessing = 0; -
trunk/Source/JavaScriptCore/bytecode/PredictedType.cpp
r96894 r97218 45 45 BoundsCheckedPointer<char> ptr(description, size); 46 46 47 bool isTop = true; 48 47 49 if (value & PredictCellOther) 48 50 ptr.strcat("Othercell"); 51 else 52 isTop = false; 49 53 50 54 if (value & PredictObjectOther) 51 55 ptr.strcat("Otherobj"); 56 else 57 isTop = false; 52 58 53 59 if (value & PredictFinalObject) 54 60 ptr.strcat("Final"); 61 else 62 isTop = false; 55 63 56 64 if (value & PredictArray) 57 65 ptr.strcat("Array"); 66 else 67 isTop = false; 58 68 59 69 if (value & PredictString) 60 70 ptr.strcat("String"); 71 else 72 isTop = false; 61 73 62 74 if (value & PredictInt32) 63 75 ptr.strcat("Int"); 76 else 77 isTop = false; 64 78 65 79 if (value & PredictDouble) 66 80 ptr.strcat("Double"); 81 else 82 isTop = false; 67 83 68 84 if (value & PredictBoolean) 69 85 ptr.strcat("Bool"); 86 else 87 isTop = false; 70 88 71 89 if (value & PredictOther) 72 90 ptr.strcat("Other"); 91 else 92 isTop = false; 93 94 if (isTop) 95 return "Top"; 73 96 74 97 *ptr++ = 0; -
trunk/Source/JavaScriptCore/bytecode/PredictedType.h
r96894 r97218 51 51 static const PredictedType PredictOther = 0x4000; // It's definitely none of the above. 52 52 static const PredictedType PredictTop = 0x7fff; // It can be any of the above. 53 54 typedef bool (*PredictionChecker)(PredictedType); 53 55 54 56 inline bool isCellPrediction(PredictedType value) … … 116 118 #endif 117 119 120 // Merge two predictions. Note that currently this just does left | right. It may 121 // seem tempting to do so directly, but you would be doing so at your own peril, 122 // since the merging protocol PredictedType may change at any time (and has already 123 // changed several times in its history). 118 124 inline PredictedType mergePredictions(PredictedType left, PredictedType right) 119 125 { -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r97197 r97218 129 129 NodeIndex getLocal(unsigned operand) 130 130 { 131 NodeIndex nodeIndex = m_currentBlock-> m_localsAtTail[operand].value;131 NodeIndex nodeIndex = m_currentBlock->variablesAtTail.local(operand); 132 132 133 133 if (nodeIndex != NoNode) { … … 148 148 m_localPhiStack.append(PhiStackEntry(m_currentBlock, phi, operand)); 149 149 nodeIndex = addToGraph(GetLocal, OpInfo(variableAccessData), phi); 150 m_currentBlock-> m_localsAtTail[operand].value= nodeIndex;151 152 m_currentBlock-> m_localsAtHead[operand].setFirstTime(nodeIndex);150 m_currentBlock->variablesAtTail.local(operand) = nodeIndex; 151 152 m_currentBlock->variablesAtHead.setLocalFirstTime(operand, nodeIndex); 153 153 154 154 return nodeIndex; … … 156 156 void setLocal(unsigned operand, NodeIndex value) 157 157 { 158 m_currentBlock-> m_localsAtTail[operand].value= addToGraph(SetLocal, OpInfo(newVariableAccessData(operand)), value);158 m_currentBlock->variablesAtTail.local(operand) = addToGraph(SetLocal, OpInfo(newVariableAccessData(operand)), value); 159 159 } 160 160 … … 165 165 ASSERT(argument < m_numArguments); 166 166 167 NodeIndex nodeIndex = m_currentBlock-> m_argumentsAtTail[argument].value;167 NodeIndex nodeIndex = m_currentBlock->variablesAtTail.argument(argument); 168 168 169 169 if (nodeIndex != NoNode) { … … 174 174 ASSERT(node.local() == static_cast<VirtualRegister>(operand)); 175 175 nodeIndex = addToGraph(GetLocal, OpInfo(node.variableAccessData()), nodeIndex); 176 m_currentBlock-> m_argumentsAtTail[argument].value= nodeIndex;176 m_currentBlock->variablesAtTail.argument(argument) = nodeIndex; 177 177 return nodeIndex; 178 178 } … … 190 190 m_argumentPhiStack.append(PhiStackEntry(m_currentBlock, phi, argument)); 191 191 nodeIndex = addToGraph(GetLocal, OpInfo(variableAccessData), phi); 192 m_currentBlock-> m_argumentsAtTail[argument].value= nodeIndex;193 194 m_currentBlock-> m_argumentsAtHead[argument].setFirstTime(nodeIndex);192 m_currentBlock->variablesAtTail.argument(argument) = nodeIndex; 193 194 m_currentBlock->variablesAtHead.setArgumentFirstTime(argument, nodeIndex); 195 195 196 196 return nodeIndex; … … 201 201 ASSERT(argument < m_numArguments); 202 202 203 m_currentBlock-> m_argumentsAtTail[argument].value= addToGraph(SetLocal, OpInfo(newVariableAccessData(operand)), value);203 m_currentBlock->variablesAtTail.argument(argument) = addToGraph(SetLocal, OpInfo(newVariableAccessData(operand)), value); 204 204 } 205 205 … … 787 787 NodeIndex setArgument = addToGraph(SetArgument, OpInfo(newVariableAccessData(argument - m_codeBlock->m_numParameters - RegisterFile::CallFrameHeaderSize))); 788 788 m_graph.m_arguments[argument] = setArgument; 789 m_currentBlock-> m_argumentsAtHead[argument].setFirstTime(setArgument);790 m_currentBlock-> m_argumentsAtTail[argument].setFirstTime(setArgument);789 m_currentBlock->variablesAtHead.setArgumentFirstTime(argument, setArgument); 790 m_currentBlock->variablesAtTail.setArgumentFirstTime(argument, setArgument); 791 791 } 792 792 } … … 1693 1693 BasicBlock* predecessorBlock = m_graph.m_blocks[predecessors[i]].get(); 1694 1694 1695 VariableRecord& var = (stackType == ArgumentPhiStack) ? predecessorBlock->m_argumentsAtTail[varNo] : predecessorBlock->m_localsAtTail[varNo];1696 1697 NodeIndex valueInPredecessor = var .value;1695 NodeIndex& var = (stackType == ArgumentPhiStack) ? predecessorBlock->variablesAtTail.argument(varNo) : predecessorBlock->variablesAtTail.local(varNo); 1696 1697 NodeIndex valueInPredecessor = var; 1698 1698 if (valueInPredecessor == NoNode) { 1699 1699 valueInPredecessor = addToGraph(Phi, OpInfo(newVariableAccessData(stackType == ArgumentPhiStack ? varNo - m_codeBlock->m_numParameters - RegisterFile::CallFrameHeaderSize : varNo))); 1700 var .setFirstTime(valueInPredecessor);1700 var = valueInPredecessor; 1701 1701 if (stackType == ArgumentPhiStack) 1702 predecessorBlock-> m_argumentsAtHead[varNo].setFirstTime(valueInPredecessor);1702 predecessorBlock->variablesAtHead.setArgumentFirstTime(varNo, valueInPredecessor); 1703 1703 else 1704 predecessorBlock-> m_localsAtHead[varNo].setFirstTime(valueInPredecessor);1704 predecessorBlock->variablesAtHead.setLocalFirstTime(varNo, valueInPredecessor); 1705 1705 phiStack.append(PhiStackEntry(predecessorBlock, valueInPredecessor, varNo)); 1706 1706 } else if (m_graph[valueInPredecessor].op == GetLocal) { … … 1762 1762 ASSERT(node.isTerminal()); 1763 1763 1764 if (node.isJump()) 1765 m_graph.blockForBytecodeOffset(node.takenBytecodeOffset()).m_predecessors.append(index); 1766 else if (node.isBranch()) { 1767 m_graph.blockForBytecodeOffset(node.takenBytecodeOffset()).m_predecessors.append(index); 1768 m_graph.blockForBytecodeOffset(node.notTakenBytecodeOffset()).m_predecessors.append(index); 1764 if (node.isJump()) { 1765 node.setTakenBlockIndex(m_graph.blockIndexForBytecodeOffset(node.takenBytecodeOffsetDuringParsing())); 1766 m_graph.m_blocks[node.takenBlockIndex()]->m_predecessors.append(index); 1767 } else if (node.isBranch()) { 1768 node.setTakenBlockIndex(m_graph.blockIndexForBytecodeOffset(node.takenBytecodeOffsetDuringParsing())); 1769 node.setNotTakenBlockIndex(m_graph.blockIndexForBytecodeOffset(node.notTakenBytecodeOffsetDuringParsing())); 1770 m_graph.m_blocks[node.takenBlockIndex()]->m_predecessors.append(index); 1771 m_graph.m_blocks[node.notTakenBlockIndex()]->m_predecessors.append(index); 1769 1772 } 1770 1773 } -
trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp
r96567 r97218 189 189 } 190 190 if (node.isBranch() || node.isJump()) { 191 printf("%sT:#%u", hasPrinted ? ", " : "", blockIndexForBytecodeOffset(node.takenBytecodeOffset()));191 printf("%sT:#%u", hasPrinted ? ", " : "", node.takenBlockIndex()); 192 192 hasPrinted = true; 193 193 } 194 194 if (node.isBranch()) { 195 printf("%sF:#%u", hasPrinted ? ", " : "", blockIndexForBytecodeOffset(node.notTakenBytecodeOffset()));195 printf("%sF:#%u", hasPrinted ? ", " : "", node.notTakenBlockIndex()); 196 196 hasPrinted = true; 197 197 } … … 240 240 { 241 241 for (size_t b = 0; b < m_blocks.size(); ++b) { 242 printf("Block #%u (bc#%u): %s\n", (int)b, m_blocks[b]->bytecodeBegin, m_blocks[b]->isOSRTarget ? " (OSR target)" : ""); 243 for (size_t i = m_blocks[b]->begin; i < m_blocks[b]->end; ++i) 242 BasicBlock* block = m_blocks[b].get(); 243 printf("Block #%u (bc#%u): %s\n", (int)b, block->bytecodeBegin, block->isOSRTarget ? " (OSR target)" : ""); 244 printf(" vars: "); 245 if (block->cfaHasVisited) 246 dumpOperands(block->valuesAtHead, stdout); 247 else 248 printf("<empty>"); 249 printf("\n"); 250 for (size_t i = block->begin; i < block->end; ++i) 244 251 dump(i, codeBlock); 245 252 } -
trunk/Source/JavaScriptCore/dfg/DFGGraph.h
r97197 r97218 30 30 31 31 #include "CodeBlock.h" 32 #include "DFGBasicBlock.h" 32 33 #include "DFGNode.h" 33 34 #include "PredictionTracker.h" … … 45 46 namespace DFG { 46 47 47 // helper function to distinguish vars & temporaries from arguments.48 inline bool operandIsArgument(int operand) { return operand < 0; }49 50 typedef uint32_t BlockIndex;51 52 // For every local variable we track any existing get or set of the value.53 // We track the get so that these may be shared, and we track the set to54 // retrieve the current value, and to reference the final definition.55 struct VariableRecord {56 VariableRecord()57 : value(NoNode)58 {59 }60 61 void setFirstTime(NodeIndex nodeIndex)62 {63 ASSERT(value == NoNode);64 value = nodeIndex;65 }66 67 NodeIndex value;68 };69 70 48 struct MethodCheckData { 71 49 // It is safe to refer to these directly because they are shadowed by … … 111 89 unsigned identifierNumber; 112 90 unsigned resolveInfoIndex; 113 };114 115 typedef Vector <BlockIndex, 2> PredecessorList;116 117 struct BasicBlock {118 BasicBlock(unsigned bytecodeBegin, NodeIndex begin, unsigned numArguments, unsigned numLocals)119 : bytecodeBegin(bytecodeBegin)120 , begin(begin)121 , end(NoNode)122 , isOSRTarget(false)123 , m_argumentsAtHead(numArguments)124 , m_localsAtHead(numLocals)125 , m_argumentsAtTail(numArguments)126 , m_localsAtTail(numLocals)127 {128 }129 130 static inline BlockIndex getBytecodeBegin(OwnPtr<BasicBlock>* block)131 {132 return (*block)->bytecodeBegin;133 }134 135 unsigned bytecodeBegin;136 NodeIndex begin;137 NodeIndex end;138 bool isOSRTarget;139 140 PredecessorList m_predecessors;141 142 Vector<VariableRecord, 8> m_argumentsAtHead;143 Vector<VariableRecord, 16> m_localsAtHead;144 145 Vector<VariableRecord, 8> m_argumentsAtTail;146 Vector<VariableRecord, 16> m_localsAtTail;147 91 }; 148 92 -
trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.h
r97216 r97218 1516 1516 } 1517 1517 1518 BasicBlock* block() 1519 { 1520 return m_jit.graph().m_blocks[m_block].get(); 1521 } 1522 1518 1523 #ifndef NDEBUG 1519 1524 void dump(const char* label = 0); -
trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator32_64.cpp
r97189 r97218 966 966 { 967 967 Node& branchNode = at(branchNodeIndex); 968 BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());969 BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());968 BlockIndex taken = branchNode.takenBlockIndex(); 969 BlockIndex notTaken = branchNode.notTakenBlockIndex(); 970 970 971 971 if (taken == (m_block + 1)) { … … 1029 1029 { 1030 1030 Node& branchNode = at(branchNodeIndex); 1031 BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());1032 BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());1031 BlockIndex taken = branchNode.takenBlockIndex(); 1032 BlockIndex notTaken = branchNode.notTakenBlockIndex(); 1033 1033 1034 1034 JITCompiler::ResultCondition callResultCondition = JITCompiler::NonZero; … … 1158 1158 { 1159 1159 Node& branchNode = at(branchNodeIndex); 1160 BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());1161 BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());1160 BlockIndex taken = branchNode.takenBlockIndex(); 1161 BlockIndex notTaken = branchNode.notTakenBlockIndex(); 1162 1162 1163 1163 // The branch instruction will branch to the taken block. -
trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator64.cpp
r97153 r97218 928 928 { 929 929 Node& branchNode = at(branchNodeIndex); 930 BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());931 BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());930 BlockIndex taken = branchNode.takenBlockIndex(); 931 BlockIndex notTaken = branchNode.notTakenBlockIndex(); 932 932 933 933 if (taken == (m_block + 1)) { … … 989 989 { 990 990 Node& branchNode = at(branchNodeIndex); 991 BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());992 BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());991 BlockIndex taken = branchNode.takenBlockIndex(); 992 BlockIndex notTaken = branchNode.notTakenBlockIndex(); 993 993 994 994 JITCompiler::ResultCondition callResultCondition = JITCompiler::NonZero; … … 1111 1111 { 1112 1112 Node& branchNode = at(branchNodeIndex); 1113 BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());1114 BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());1113 BlockIndex taken = branchNode.takenBlockIndex(); 1114 BlockIndex notTaken = branchNode.notTakenBlockIndex(); 1115 1115 1116 1116 // The branch instruction will branch to the taken block. -
trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h
r97071 r97218 405 405 OSREntryData* entry = codeBlock()->appendDFGOSREntryData(basicBlock.bytecodeBegin, differenceBetween(m_startOfCode, label())); 406 406 407 ActionablePredictions actionablePredictions(basicBlock.m_argumentsAtHead.size(), basicBlock.m_localsAtHead.size()); 408 409 for (unsigned i = 0; i < basicBlock.m_argumentsAtHead.size(); ++i) { 410 NodeIndex nodeIndex = basicBlock.m_argumentsAtHead[i].value; 411 if (nodeIndex != NoNode) 412 actionablePredictions.setArgument(i, actionablePredictionFromPredictedType(m_graph[nodeIndex].variableAccessData()->prediction())); 413 } 407 entry->m_expectedValues = basicBlock.valuesAtHead; 414 408 415 for (unsigned i = 0; i < basicBlock.m_localsAtHead.size(); ++i) { 416 NodeIndex nodeIndex = basicBlock.m_localsAtHead[i].value; 417 if (nodeIndex != NoNode) 418 actionablePredictions.setVariable(i, actionablePredictionFromPredictedType(m_graph[nodeIndex].variableAccessData()->prediction())); 419 } 420 421 actionablePredictions.pack(); 422 423 entry->m_predictions = actionablePredictions; 409 // Fix the expected values: in our protocol, a dead variable will have an expected 410 // value of (None, []). But the old JIT may stash some values there. So we really 411 // need (Top, TOP). 412 for (size_t argument = 0; argument < basicBlock.variablesAtHead.numberOfArguments(); ++argument) { 413 if (basicBlock.variablesAtHead.argument(argument) == NoNode) 414 entry->m_expectedValues.argument(argument).makeTop(); 415 } 416 for (size_t local = 0; local < basicBlock.variablesAtHead.numberOfLocals(); ++local) { 417 if (basicBlock.variablesAtHead.local(local) == NoNode) 418 entry->m_expectedValues.local(local).makeTop(); 419 } 424 420 #else 425 421 UNUSED_PARAM(basicBlock); -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r97030 r97218 27 27 #define DFGNode_h 28 28 29 #include "DFGStructureSet.h"30 29 #include <wtf/BoundsCheckedPointer.h> 31 30 #include <wtf/Platform.h> 32 #include <wtf/UnionFind.h>33 31 34 32 // Emit various logging information for debugging, including dumping the dataflow graphs. … … 68 66 69 67 #include "CodeBlock.h" 68 #include "DFGOperands.h" 69 #include "DFGVariableAccessData.h" 70 70 #include "JSValue.h" 71 71 #include "PredictedType.h" … … 75 75 namespace JSC { namespace DFG { 76 76 77 // Type for a virtual register number (spill location).78 // Using an enum to make this type-checked at compile time, to avert programmer errors.79 enum VirtualRegister { InvalidVirtualRegister = -1 };80 COMPILE_ASSERT(sizeof(VirtualRegister) == sizeof(int), VirtualRegister_is_32bit);81 82 77 // Type for a reference to another node in the graph. 83 78 typedef uint32_t NodeIndex; 84 79 static const NodeIndex NoNode = UINT_MAX; 80 81 typedef uint32_t BlockIndex; 82 83 struct NodeIndexTraits { 84 static NodeIndex defaultValue() { return NoNode; } 85 }; 85 86 86 87 // Information used to map back from an exception to any handler/source information, … … 109 110 private: 110 111 uint32_t m_bytecodeIndex; 111 };112 113 class VariableAccessData: public UnionFind<VariableAccessData> {114 public:115 VariableAccessData()116 : m_local(static_cast<VirtualRegister>(std::numeric_limits<int>::min()))117 , m_prediction(PredictNone)118 {119 }120 121 VariableAccessData(VirtualRegister local)122 : m_local(local)123 , m_prediction(PredictNone)124 {125 }126 127 VirtualRegister local()128 {129 ASSERT(m_local == find()->m_local);130 return m_local;131 }132 133 int operand()134 {135 return static_cast<int>(local());136 }137 138 bool predict(PredictedType prediction)139 {140 return mergePrediction(find()->m_prediction, prediction);141 }142 143 PredictedType prediction()144 {145 return find()->m_prediction;146 }147 148 private:149 // This is slightly space-inefficient, since anything we're unified with150 // will have the same operand and should have the same prediction. But151 // putting them here simplifies the code, and we don't expect DFG space152 // usage for variable access nodes do be significant.153 154 VirtualRegister m_local;155 PredictedType m_prediction;156 112 }; 157 113 … … 565 521 VariableAccessData* variableAccessData() 566 522 { 523 ASSERT(hasVariableAccessData()); 567 524 return reinterpret_cast<VariableAccessData*>(m_opInfo)->find(); 568 525 } … … 756 713 } 757 714 758 unsigned takenBytecodeOffset ()715 unsigned takenBytecodeOffsetDuringParsing() 759 716 { 760 717 ASSERT(isBranch() || isJump()); … … 762 719 } 763 720 764 unsigned notTakenBytecodeOffset() 721 unsigned notTakenBytecodeOffsetDuringParsing() 722 { 723 ASSERT(isBranch()); 724 return m_opInfo2; 725 } 726 727 void setTakenBlockIndex(BlockIndex blockIndex) 728 { 729 ASSERT(isBranch() || isJump()); 730 m_opInfo = blockIndex; 731 } 732 733 void setNotTakenBlockIndex(BlockIndex blockIndex) 734 { 735 ASSERT(isBranch()); 736 m_opInfo2 = blockIndex; 737 } 738 739 BlockIndex takenBlockIndex() 740 { 741 ASSERT(isBranch() || isJump()); 742 return m_opInfo; 743 } 744 745 BlockIndex notTakenBlockIndex() 765 746 { 766 747 ASSERT(isBranch()); -
trunk/Source/JavaScriptCore/dfg/DFGOSREntry.cpp
r96375 r97218 78 78 // OSR at this time. 79 79 80 for (unsigned i = 1; i < entry->m_predictions.argumentUpperBound(); ++i) { 81 ActionablePrediction prediction = entry->m_predictions.argument(i); 82 if (prediction == NoActionablePrediction) 83 continue; 84 85 if (i >= exec->argumentCountIncludingThis()) { 80 for (size_t argument = 0; argument < entry->m_expectedValues.numberOfArguments(); ++argument) { 81 if (argument >= exec->argumentCountIncludingThis()) { 86 82 #if ENABLE(JIT_VERBOSE_OSR) 87 printf(" OSR failed because argument %u was not passed, expected %s.\n", i, actionablePredictionToString(prediction)); 83 printf(" OSR failed because argument %lu was not passed, expected ", argument); 84 entry->m_expectedValues.argument(argument).dump(stdout); 85 printf(".\n"); 88 86 #endif 89 87 return 0; 90 88 } 91 89 92 if (!valueObeysPrediction(globalData, exec->argument(i - 1), prediction)) { 90 JSValue value; 91 if (!argument) 92 value = exec->hostThisValue(); 93 else 94 value = exec->argument(argument - 1); 95 96 if (!entry->m_expectedValues.argument(argument).validate(value)) { 93 97 #if ENABLE(JIT_VERBOSE_OSR) 94 printf(" OSR failed because argument %u is %s, expected %s.\n", i, exec->argument(i - 1).description(), actionablePredictionToString(prediction)); 98 printf(" OSR failed because argument %lu is %s, expected ", argument, value.description()); 99 entry->m_expectedValues.argument(argument).dump(stdout); 100 printf(".\n"); 95 101 #endif 96 102 return 0; … … 98 104 } 99 105 100 for (unsigned i = 0; i < entry->m_predictions.variableUpperBound(); ++i) { 101 ActionablePrediction prediction = entry->m_predictions.variable(i); 102 if (prediction == NoActionablePrediction) 103 continue; 104 105 if (!valueObeysPrediction(globalData, exec->registers()[i].jsValue(), prediction)) { 106 for (size_t local = 0; local < entry->m_expectedValues.numberOfLocals(); ++local) { 107 if (!entry->m_expectedValues.local(local).validate(exec->registers()[local].jsValue())) { 106 108 #if ENABLE(JIT_VERBOSE_OSR) 107 printf(" OSR failed because variable %u is %s, expected %s.\n", i, exec->registers()[i].jsValue().description(), actionablePredictionToString(prediction)); 109 printf(" OSR failed because variable %lu is %s, expected ", local, exec->registers()[local].jsValue().description()); 110 entry->m_expectedValues.local(local).dump(stdout); 111 printf(".\n"); 108 112 #endif 109 113 return 0; -
trunk/Source/JavaScriptCore/dfg/DFGOSREntry.h
r96375 r97218 27 27 #define DFGOSREntry_h 28 28 29 #include "ActionablePrediction.h" 29 #include "DFGAbstractValue.h" 30 #include "DFGOperands.h" 30 31 31 32 namespace JSC { … … 40 41 unsigned m_bytecodeIndex; 41 42 unsigned m_machineCodeOffset; 42 ActionablePredictions m_predictions;43 Operands<AbstractValue> m_expectedValues; 43 44 }; 44 45 -
trunk/Source/JavaScriptCore/dfg/DFGPropagator.cpp
r97197 r97218 29 29 #if ENABLE(DFG_JIT) 30 30 31 #include "DFGAbstractState.h" 31 32 #include "DFGGraph.h" 32 33 #include "DFGScoreBoard.h" … … 56 57 { 57 58 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 58 m_graph.dump(m_codeBlock); 59 #endif 60 61 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 62 m_count = 0; 63 #endif 64 do { 65 m_changed = false; 66 67 // Up here we start with a backward pass because we suspect that to be 68 // more profitable. 69 propagateArithNodeFlagsBackward(); 70 if (!m_changed) 71 break; 72 73 m_changed = false; 74 propagateArithNodeFlagsForward(); 75 } while (m_changed); 76 77 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 78 m_count = 0; 79 #endif 80 do { 81 m_changed = false; 82 83 // Forward propagation is near-optimal for both topologically-sorted and 84 // DFS-sorted code. 85 propagatePredictionsForward(); 86 if (!m_changed) 87 break; 88 89 // Backward propagation reduces the likelihood that pathological code will 90 // cause slowness. Loops (especially nested ones) resemble backward flow. 91 // This pass captures two cases: (1) it detects if the forward fixpoint 92 // found a sound solution and (2) short-circuits backward flow. 93 m_changed = false; 94 propagatePredictionsBackward(); 95 } while (m_changed); 96 59 m_graph.dump(m_codeBlock); 60 #endif 61 62 propagateArithNodeFlags(); 63 propagatePredictions(); 97 64 fixup(); 98 65 … … 110 77 111 78 allocateVirtualRegisters(); 79 80 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 81 printf("Graph after virtual register allocation:\n"); 82 m_graph.dump(m_codeBlock); 83 #endif 84 85 globalCFA(); 112 86 113 87 #if ENABLE(DFG_DEBUG_VERBOSE) … … 273 247 for (m_compileIndex = m_graph.size(); m_compileIndex-- > 0;) 274 248 propagateArithNodeFlags(m_graph[m_compileIndex]); 249 } 250 251 void propagateArithNodeFlags() 252 { 253 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 254 m_count = 0; 255 #endif 256 do { 257 m_changed = false; 258 259 // Up here we start with a backward pass because we suspect that to be 260 // more profitable. 261 propagateArithNodeFlagsBackward(); 262 if (!m_changed) 263 break; 264 265 m_changed = false; 266 propagateArithNodeFlagsForward(); 267 } while (m_changed); 275 268 } 276 269 … … 609 602 610 603 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 611 printf("%s 604 printf("%s\n", predictionToString(m_graph[m_compileIndex].prediction())); 612 605 #endif 613 606 … … 631 624 for (m_compileIndex = m_graph.size(); m_compileIndex-- > 0;) 632 625 propagateNodePredictions(m_graph[m_compileIndex]); 626 } 627 628 void propagatePredictions() 629 { 630 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 631 m_count = 0; 632 #endif 633 do { 634 m_changed = false; 635 636 // Forward propagation is near-optimal for both topologically-sorted and 637 // DFS-sorted code. 638 propagatePredictionsForward(); 639 if (!m_changed) 640 break; 641 642 // Backward propagation reduces the likelihood that pathological code will 643 // cause slowness. Loops (especially nested ones) resemble backward flow. 644 // This pass captures two cases: (1) it detects if the forward fixpoint 645 // found a sound solution and (2) short-circuits backward flow. 646 m_changed = false; 647 propagatePredictionsBackward(); 648 } while (m_changed); 633 649 } 634 650 … … 1454 1470 } 1455 1471 1472 void performBlockCFA(AbstractState& state, BlockIndex blockIndex) 1473 { 1474 BasicBlock* block = m_graph.m_blocks[blockIndex].get(); 1475 if (!block->cfaShouldRevisit) 1476 return; 1477 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 1478 printf(" Block #%u (bc#%u):\n", blockIndex, block->bytecodeBegin); 1479 #endif 1480 state.beginBasicBlock(block); 1481 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 1482 printf(" head vars: "); 1483 dumpOperands(block->valuesAtHead, stdout); 1484 printf("\n"); 1485 #endif 1486 for (NodeIndex nodeIndex = block->begin; nodeIndex < block->end; ++nodeIndex) { 1487 if (!m_graph[nodeIndex].shouldGenerate()) 1488 continue; 1489 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 1490 printf(" %s @%u: ", Graph::opName(m_graph[nodeIndex].op), nodeIndex); 1491 state.dump(stdout); 1492 printf("\n"); 1493 #endif 1494 if (!state.execute(nodeIndex)) 1495 break; 1496 } 1497 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 1498 printf(" tail regs: "); 1499 state.dump(stdout); 1500 printf("\n"); 1501 #endif 1502 m_changed |= state.endBasicBlock(AbstractState::MergeToSuccessors); 1503 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 1504 printf(" tail vars: "); 1505 dumpOperands(block->valuesAtTail, stdout); 1506 printf("\n"); 1507 #endif 1508 } 1509 1510 void performForwardCFA(AbstractState& state) 1511 { 1512 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 1513 printf("CFA [%u]\n", ++m_count); 1514 #endif 1515 1516 for (BlockIndex block = 0; block < m_graph.m_blocks.size(); ++block) 1517 performBlockCFA(state, block); 1518 } 1519 1520 void globalCFA() 1521 { 1522 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE) 1523 m_count = 0; 1524 #endif 1525 1526 // This implements a pseudo-worklist-based forward CFA, except that the visit order 1527 // of blocks is the bytecode program order (which is nearly topological), and 1528 // instead of a worklist we just walk all basic blocks checking if cfaShouldRevisit 1529 // is set to true. This is likely to balance the efficiency properties of both 1530 // worklist-based and forward fixpoint-based approaches. Like a worklist-based 1531 // approach, it won't visit code if it's meaningless to do so (nothing changed at 1532 // the head of the block or the predecessors have not been visited). Like a forward 1533 // fixpoint-based approach, it has a high probability of only visiting a block 1534 // after all predecessors have been visited. Only loops will cause this analysis to 1535 // revisit blocks, and the amount of revisiting is proportional to loop depth. 1536 1537 AbstractState::initialize(m_graph); 1538 1539 AbstractState state(m_codeBlock, m_graph); 1540 1541 do { 1542 m_changed = false; 1543 performForwardCFA(state); 1544 } while (m_changed); 1545 } 1546 1456 1547 Graph& m_graph; 1457 1548 JSGlobalData& m_globalData; -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r97197 r97218 132 132 { 133 133 Node& branchNode = at(branchNodeIndex); 134 BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());135 BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());134 BlockIndex taken = branchNode.takenBlockIndex(); 135 BlockIndex notTaken = branchNode.notTakenBlockIndex(); 136 136 137 137 SpeculateDoubleOperand op1(this, node.child1()); … … 144 144 } 145 145 146 void SpeculativeJIT::compilePeepHoleObjectEquality(Node& node, NodeIndex branchNodeIndex, void* vptr )146 void SpeculativeJIT::compilePeepHoleObjectEquality(Node& node, NodeIndex branchNodeIndex, void* vptr, PredictionChecker predictionCheck) 147 147 { 148 148 Node& branchNode = at(branchNodeIndex); 149 BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());150 BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());149 BlockIndex taken = branchNode.takenBlockIndex(); 150 BlockIndex notTaken = branchNode.notTakenBlockIndex(); 151 151 152 152 MacroAssembler::RelationalCondition condition = MacroAssembler::Equal; … … 165 165 GPRReg op2GPR = op2.gpr(); 166 166 167 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR), MacroAssembler::TrustedImmPtr(vptr))); 168 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR), MacroAssembler::TrustedImmPtr(vptr))); 167 if (!predictionCheck(m_state.forNode(node.child1()).m_type)) 168 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR), MacroAssembler::TrustedImmPtr(vptr))); 169 if (!predictionCheck(m_state.forNode(node.child2()).m_type)) 170 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR), MacroAssembler::TrustedImmPtr(vptr))); 169 171 170 172 addBranch(m_jit.branchPtr(condition, op1GPR, op2GPR), taken); … … 176 178 { 177 179 Node& branchNode = at(branchNodeIndex); 178 BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());179 BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());180 BlockIndex taken = branchNode.takenBlockIndex(); 181 BlockIndex notTaken = branchNode.notTakenBlockIndex(); 180 182 181 183 // The branch instruction will branch to the taken block. … … 226 228 use(node.child2()); 227 229 } else if (node.op == CompareEq && Node::shouldSpeculateFinalObject(at(node.child1()), at(node.child2()))) { 228 compilePeepHoleObjectEquality(node, branchNodeIndex, m_jit.globalData()->jsFinalObjectVPtr );230 compilePeepHoleObjectEquality(node, branchNodeIndex, m_jit.globalData()->jsFinalObjectVPtr, isFinalObjectPrediction); 229 231 use(node.child1()); 230 232 use(node.child2()); 231 233 } else if (node.op == CompareEq && Node::shouldSpeculateArray(at(node.child1()), at(node.child2()))) { 232 compilePeepHoleObjectEquality(node, branchNodeIndex, m_jit.globalData()->jsArrayVPtr );234 compilePeepHoleObjectEquality(node, branchNodeIndex, m_jit.globalData()->jsArrayVPtr, isArrayPrediction); 233 235 use(node.child1()); 234 236 use(node.child2()); … … 263 265 #endif 264 266 265 ASSERT(m_arguments.size() == block. m_argumentsAtHead.size());267 ASSERT(m_arguments.size() == block.variablesAtHead.numberOfArguments()); 266 268 for (size_t i = 0; i < m_arguments.size(); ++i) { 267 NodeIndex nodeIndex = block. m_argumentsAtHead[i].value;269 NodeIndex nodeIndex = block.variablesAtHead.argument(i); 268 270 if (nodeIndex == NoNode) 269 271 m_arguments[i] = ValueSource(ValueInRegisterFile); … … 272 274 } 273 275 274 ASSERT(m_variables.size() == block.m_localsAtHead.size()); 276 m_state.reset(); 277 m_state.beginBasicBlock(&block); 278 279 ASSERT(m_variables.size() == block.variablesAtHead.numberOfLocals()); 275 280 for (size_t i = 0; i < m_variables.size(); ++i) { 276 NodeIndex nodeIndex = block. m_localsAtHead[i].value;281 NodeIndex nodeIndex = block.variablesAtHead.local(i); 277 282 if (nodeIndex == NoNode) 278 283 m_variables[i] = ValueSource(ValueInRegisterFile); … … 343 348 fprintf(stderr, "\n"); 344 349 #endif 350 351 // Make sure that the abstract state is rematerialized for the next node. 352 m_state.execute(m_compileIndex); 345 353 346 354 if (node.shouldGenerate()) … … 544 552 GPRReg indexReg = index.gpr(); 545 553 546 if (!is KnownString(node.child1()))554 if (!isStringPrediction(m_state.forNode(node.child1()).m_type)) 547 555 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(stringReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr))); 548 556 … … 573 581 GPRReg propertyReg = property.gpr(); 574 582 575 if (!is KnownString(node.child1()))583 if (!isStringPrediction(m_state.forNode(node.child1()).m_type)) 576 584 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr))); 577 585 -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r97153 r97218 29 29 #if ENABLE(DFG_JIT) 30 30 31 #include <dfg/DFGAbstractState.h> 31 32 #include <dfg/DFGJITCodeGenerator.h> 32 33 … … 434 435 } 435 436 436 bool isKnownArray(NodeIndex op1)437 {438 Node& node = at(op1);439 switch (node.op) {440 case GetLocal:441 return isArrayPrediction(node.variableAccessData()->prediction());442 443 case NewArray:444 case NewArrayBuffer:445 return true;446 447 default:448 return false;449 }450 }451 452 bool isKnownString(NodeIndex op1)453 {454 switch (at(op1).op) {455 case StrCat:456 return true;457 458 default:459 return false;460 }461 }462 463 437 bool compare(Node&, MacroAssembler::RelationalCondition, MacroAssembler::DoubleCondition, S_DFGOperation_EJJ); 464 438 bool compilePeepHoleBranch(Node&, MacroAssembler::RelationalCondition, MacroAssembler::DoubleCondition, S_DFGOperation_EJJ); 465 439 void compilePeepHoleIntegerBranch(Node&, NodeIndex branchNodeIndex, JITCompiler::RelationalCondition); 466 440 void compilePeepHoleDoubleBranch(Node&, NodeIndex branchNodeIndex, JITCompiler::DoubleCondition); 467 void compilePeepHoleObjectEquality(Node&, NodeIndex branchNodeIndex, void* vptr );468 void compileObjectEquality(Node&, void* vptr );441 void compilePeepHoleObjectEquality(Node&, NodeIndex branchNodeIndex, void* vptr, PredictionChecker); 442 void compileObjectEquality(Node&, void* vptr, PredictionChecker); 469 443 void compileValueAdd(Node&); 470 void compileObjectOrOtherLogicalNot(NodeIndex value, void* vptr );444 void compileObjectOrOtherLogicalNot(NodeIndex value, void* vptr, bool needSpeculationCheck); 471 445 void compileLogicalNot(Node&); 472 void emitObjectOrOtherBranch(NodeIndex value, BlockIndex taken, BlockIndex notTaken, void *vptr );446 void emitObjectOrOtherBranch(NodeIndex value, BlockIndex taken, BlockIndex notTaken, void *vptr, bool needSpeculationCheck); 473 447 void emitBranch(Node&); 474 448 … … 592 566 uint32_t m_bytecodeIndexForOSR; 593 567 568 AbstractState m_state; 569 594 570 ValueRecovery computeValueRecoveryFor(const ValueSource&); 595 571 … … 824 800 , m_lastSetOperand(std::numeric_limits<int>::max()) 825 801 , m_bytecodeIndexForOSR(std::numeric_limits<uint32_t>::max()) 802 , m_state(m_jit.codeBlock(), m_jit.graph()) 826 803 { 827 804 } -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r97189 r97218 359 359 } 360 360 361 void SpeculativeJIT::compileObjectEquality(Node& node, void* vptr )361 void SpeculativeJIT::compileObjectEquality(Node& node, void* vptr, PredictionChecker predictionCheck) 362 362 { 363 363 SpeculateCellOperand op1(this, node.child1()); … … 371 371 GPRReg resultPayloadGPR = resultPayload.gpr(); 372 372 373 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR), MacroAssembler::TrustedImmPtr(vptr))); 374 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR), MacroAssembler::TrustedImmPtr(vptr))); 373 if (!predictionCheck(m_state.forNode(node.child1()).m_type)) 374 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR), MacroAssembler::TrustedImmPtr(vptr))); 375 if (!predictionCheck(m_state.forNode(node.child2()).m_type)) 376 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR), MacroAssembler::TrustedImmPtr(vptr))); 375 377 376 378 MacroAssembler::Jump falseCase = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, op2GPR); … … 392 394 393 395 if (Node::shouldSpeculateFinalObject(at(node.child1()), at(node.child2()))) 394 compileObjectEquality(node, m_jit.globalData()->jsFinalObjectVPtr );396 compileObjectEquality(node, m_jit.globalData()->jsFinalObjectVPtr, isFinalObjectPrediction); 395 397 else if (Node::shouldSpeculateArray(at(node.child1()), at(node.child2()))) 396 compileObjectEquality(node, m_jit.globalData()->jsArrayVPtr );398 compileObjectEquality(node, m_jit.globalData()->jsArrayVPtr, isArrayPrediction); 397 399 else if (!at(node.child1()).shouldSpeculateNumber() && !at(node.child2()).shouldSpeculateNumber()) 398 400 nonSpeculativeNonPeepholeCompare(node, condition, operation); … … 450 452 } 451 453 452 void SpeculativeJIT::compileObjectOrOtherLogicalNot(NodeIndex nodeIndex, void* vptr )454 void SpeculativeJIT::compileObjectOrOtherLogicalNot(NodeIndex nodeIndex, void* vptr, bool needSpeculationCheck) 453 455 { 454 456 JSValueOperand value(this, nodeIndex); … … 463 465 464 466 MacroAssembler::Jump notCell = m_jit.branch32(MacroAssembler::NotEqual, valueTagGPR, TrustedImm32(JSValue::CellTag)); 465 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valuePayloadGPR), MacroAssembler::TrustedImmPtr(vptr))); 467 if (needSpeculationCheck) 468 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valuePayloadGPR), MacroAssembler::TrustedImmPtr(vptr))); 466 469 m_jit.move(TrustedImm32(0), resultPayloadGPR); 467 470 MacroAssembler::Jump done = m_jit.jump(); … … 470 473 471 474 COMPILE_ASSERT((JSValue::UndefinedTag | 1) == JSValue::NullTag, UndefinedTag_OR_1_EQUALS_NullTag); 472 m_jit.move(valueTagGPR, resultPayloadGPR); 473 m_jit.or32(TrustedImm32(1), resultPayloadGPR); 474 speculationCheck(m_jit.branch32(MacroAssembler::NotEqual, resultPayloadGPR, TrustedImm32(JSValue::NullTag))); 475 if (needSpeculationCheck) { 476 m_jit.move(valueTagGPR, resultPayloadGPR); 477 m_jit.or32(TrustedImm32(1), resultPayloadGPR); 478 speculationCheck(m_jit.branch32(MacroAssembler::NotEqual, resultPayloadGPR, TrustedImm32(JSValue::NullTag))); 479 } 475 480 m_jit.move(TrustedImm32(1), resultPayloadGPR); 476 481 … … 485 490 486 491 if (at(node.child1()).shouldSpeculateFinalObjectOrOther()) { 487 compileObjectOrOtherLogicalNot(node.child1(), m_jit.globalData()->jsFinalObjectVPtr );492 compileObjectOrOtherLogicalNot(node.child1(), m_jit.globalData()->jsFinalObjectVPtr, !isFinalObjectOrOtherPrediction(m_state.forNode(node.child1()).m_type)); 488 493 return; 489 494 } 490 495 if (at(node.child1()).shouldSpeculateArrayOrOther()) { 491 compileObjectOrOtherLogicalNot(node.child1(), m_jit.globalData()->jsArrayVPtr );496 compileObjectOrOtherLogicalNot(node.child1(), m_jit.globalData()->jsArrayVPtr, !isArrayOrOtherPrediction(m_state.forNode(node.child1()).m_type)); 492 497 return; 493 498 } … … 555 560 } 556 561 557 void SpeculativeJIT::emitObjectOrOtherBranch(NodeIndex nodeIndex, BlockIndex taken, BlockIndex notTaken, void *vptr )562 void SpeculativeJIT::emitObjectOrOtherBranch(NodeIndex nodeIndex, BlockIndex taken, BlockIndex notTaken, void *vptr, bool needSpeculationCheck) 558 563 { 559 564 JSValueOperand value(this, nodeIndex); … … 564 569 565 570 MacroAssembler::Jump notCell = m_jit.branch32(MacroAssembler::NotEqual, valueTagGPR, TrustedImm32(JSValue::CellTag)); 566 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valuePayloadGPR), MacroAssembler::TrustedImmPtr(vptr))); 571 if (needSpeculationCheck) 572 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valuePayloadGPR), MacroAssembler::TrustedImmPtr(vptr))); 567 573 addBranch(m_jit.jump(), taken); 568 574 … … 570 576 571 577 COMPILE_ASSERT((JSValue::UndefinedTag | 1) == JSValue::NullTag, UndefinedTag_OR_1_EQUALS_NullTag); 572 m_jit.move(valueTagGPR, scratchGPR); 573 m_jit.or32(TrustedImm32(1), scratchGPR); 574 speculationCheck(m_jit.branch32(MacroAssembler::NotEqual, scratchGPR, TrustedImm32(JSValue::NullTag))); 578 if (needSpeculationCheck) { 579 m_jit.move(valueTagGPR, scratchGPR); 580 m_jit.or32(TrustedImm32(1), scratchGPR); 581 speculationCheck(m_jit.branch32(MacroAssembler::NotEqual, scratchGPR, TrustedImm32(JSValue::NullTag))); 582 } 575 583 576 584 if (notTaken != (m_block + 1)) … … 582 590 void SpeculativeJIT::emitBranch(Node& node) 583 591 { 584 BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());585 BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(node.notTakenBytecodeOffset());592 BlockIndex taken = node.takenBlockIndex(); 593 BlockIndex notTaken = node.notTakenBlockIndex(); 586 594 587 595 // FIXME: Add fast cases for known Boolean! 588 596 589 597 if (at(node.child1()).shouldSpeculateFinalObjectOrOther()) { 590 emitObjectOrOtherBranch(node.child1(), taken, notTaken, m_jit.globalData()->jsFinalObjectVPtr );598 emitObjectOrOtherBranch(node.child1(), taken, notTaken, m_jit.globalData()->jsFinalObjectVPtr, !isFinalObjectOrOtherPrediction(m_state.forNode(node.child1()).m_type)); 591 599 } else if (at(node.child1()).shouldSpeculateArrayOrOther()) { 592 emitObjectOrOtherBranch(node.child1(), taken, notTaken, m_jit.globalData()->jsArrayVPtr );600 emitObjectOrOtherBranch(node.child1(), taken, notTaken, m_jit.globalData()->jsArrayVPtr, !isArrayOrOtherPrediction(m_state.forNode(node.child1()).m_type)); 593 601 } else if (at(node.child1()).shouldSpeculateNumber()) { 594 602 if (at(node.child1()).shouldSpeculateInteger()) { … … 656 664 case GetLocal: { 657 665 PredictedType prediction = node.variableAccessData()->prediction(); 666 AbstractValue& value = block()->valuesAtHead.operand(node.local()); 658 667 659 668 // If we have no prediction for this local, then don't attempt to compile. … … 696 705 m_gprs.retain(tag.gpr(), virtualRegister, SpillOrderJS); 697 706 698 DataFormat format = isBooleanPrediction(prediction) ? DataFormatJSBoolean : DataFormatJS; 707 DataFormat format; 708 if (isCellPrediction(value.m_type)) 709 format = DataFormatJSCell; 710 else if (isBooleanPrediction(value.m_type)) 711 format = DataFormatJSBoolean; 712 else 713 format = DataFormatJS; 714 699 715 m_generationInfo[virtualRegister].initJSValue(m_compileIndex, node.refCount(), tag.gpr(), result.gpr(), format); 700 716 break; … … 725 741 SpeculateCellOperand cell(this, node.child1()); 726 742 GPRReg cellGPR = cell.gpr(); 727 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr))); 743 if (!isArrayPrediction(m_state.forNode(node.child1()).m_type)) 744 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr))); 728 745 m_jit.storePtr(cellGPR, JITCompiler::payloadFor(node.local())); 729 746 noResult(m_compileIndex); … … 1328 1345 // Check that base is an array, and that property is contained within m_vector (< m_vectorLength). 1329 1346 // If we have predicted the base to be type array, we can skip the check. 1330 if (!is KnownArray(node.child1()))1347 if (!isArrayPrediction(m_state.forNode(node.child1()).m_type)) 1331 1348 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr))); 1332 1349 speculationCheck(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset()))); … … 1381 1398 // Check that base is an array, and that property is contained within m_vector (< m_vectorLength). 1382 1399 // If we have predicted the base to be type array, we can skip the check. 1383 if (!is KnownArray(node.child1()))1400 if (!isArrayPrediction(m_state.forNode(node.child1()).m_type)) 1384 1401 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr))); 1385 1402 … … 1463 1480 writeBarrier(baseGPR, valueTagGPR, node.child2(), WriteBarrierForPropertyAccess, storageGPR, storageLengthGPR); 1464 1481 1465 if (!is KnownArray(node.child1()))1482 if (!isArrayPrediction(m_state.forNode(node.child1()).m_type)) 1466 1483 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr))); 1467 1484 … … 1509 1526 GPRReg storageLengthGPR = storageLength.gpr(); 1510 1527 1511 if (!is KnownArray(node.child1()))1528 if (!isArrayPrediction(m_state.forNode(node.child1()).m_type)) 1512 1529 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr))); 1513 1530 … … 1556 1573 1557 1574 case DFG::Jump: { 1558 BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());1575 BlockIndex taken = node.takenBlockIndex(); 1559 1576 if (taken != (m_block + 1)) 1560 1577 addBranch(m_jit.jump(), taken); … … 1567 1584 SpeculateIntegerOperand op(this, node.child1()); 1568 1585 1569 BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());1570 BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(node.notTakenBytecodeOffset());1586 BlockIndex taken = node.takenBlockIndex(); 1587 BlockIndex notTaken = node.notTakenBlockIndex(); 1571 1588 1572 1589 MacroAssembler::ResultCondition condition = MacroAssembler::NonZero; … … 1780 1797 SpeculateCellOperand thisValue(this, node.child1()); 1781 1798 1782 speculationCheck(m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(thisValue.gpr()), JITCompiler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr))); 1799 if (!isObjectPrediction(m_state.forNode(node.child1()).m_type)) 1800 speculationCheck(m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(thisValue.gpr()), JITCompiler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr))); 1783 1801 1784 1802 cellResult(thisValue.gpr(), m_compileIndex); … … 1822 1840 // that it's a FinalObject then we speculate on that directly. Otherwise we 1823 1841 // do the slow (structure-based) check. 1824 if (at(node.child1()).shouldSpeculateFinalObject()) 1825 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(protoGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsFinalObjectVPtr))); 1826 else { 1842 if (at(node.child1()).shouldSpeculateFinalObject()) { 1843 if (!isFinalObjectPrediction(m_state.forNode(node.child1()).m_type)) 1844 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(protoGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsFinalObjectVPtr))); 1845 } else { 1827 1846 m_jit.loadPtr(MacroAssembler::Address(protoGPR, JSCell::structureOffset()), scratchGPR); 1828 1847 slowPath.append(m_jit.branch8(MacroAssembler::Below, MacroAssembler::Address(scratchGPR, Structure::typeInfoTypeOffset()), MacroAssembler::TrustedImm32(ObjectType))); … … 1960 1979 GPRReg resultGPR = result.gpr(); 1961 1980 1962 if (!is KnownArray(node.child1()))1981 if (!isArrayPrediction(m_state.forNode(node.child1()).m_type)) 1963 1982 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr))); 1964 1983 … … 1979 1998 GPRReg resultGPR = result.gpr(); 1980 1999 1981 if (!is KnownString(node.child1()))2000 if (!isStringPrediction(m_state.forNode(node.child1()).m_type)) 1982 2001 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr))); 1983 2002 … … 1996 2015 1997 2016 case CheckStructure: { 2017 if (m_state.forNode(node.child1()).m_structure.isSubsetOf(node.structureSet())) { 2018 noResult(m_compileIndex); 2019 break; 2020 } 2021 1998 2022 SpeculateCellOperand base(this, node.child1()); 1999 2023 … … 2122 2146 GPRReg scratchGPR = scratch.gpr(); 2123 2147 2124 speculationCheck(m_jit.branchPtr(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), JITCompiler::TrustedImmPtr(methodCheckData.structure))); 2148 if (!m_state.forNode(node.child1()).m_structure.doesNotContainAnyOtherThan(methodCheckData.structure)) 2149 speculationCheck(m_jit.branchPtr(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), JITCompiler::TrustedImmPtr(methodCheckData.structure))); 2125 2150 if (methodCheckData.prototype != m_jit.codeBlock()->globalObject()->methodCallDummy()) { 2126 2151 m_jit.move(JITCompiler::TrustedImmPtr(methodCheckData.prototype->structureAddress()), scratchGPR); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r97153 r97218 490 490 } 491 491 492 void SpeculativeJIT::compileObjectEquality(Node& node, void* vptr )492 void SpeculativeJIT::compileObjectEquality(Node& node, void* vptr, PredictionChecker predictionCheck) 493 493 { 494 494 SpeculateCellOperand op1(this, node.child1()); … … 500 500 GPRReg resultGPR = result.gpr(); 501 501 502 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR), MacroAssembler::TrustedImmPtr(vptr))); 503 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR), MacroAssembler::TrustedImmPtr(vptr))); 502 if (!predictionCheck(m_state.forNode(node.child1()).m_type)) 503 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR), MacroAssembler::TrustedImmPtr(vptr))); 504 if (!predictionCheck(m_state.forNode(node.child2()).m_type)) 505 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR), MacroAssembler::TrustedImmPtr(vptr))); 504 506 505 507 MacroAssembler::Jump falseCase = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, op2GPR); … … 541 543 jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean); 542 544 } else if (node.op == CompareEq && Node::shouldSpeculateFinalObject(at(node.child1()), at(node.child2()))) 543 compileObjectEquality(node, m_jit.globalData()->jsFinalObjectVPtr );545 compileObjectEquality(node, m_jit.globalData()->jsFinalObjectVPtr, isFinalObjectPrediction); 544 546 else if (node.op == CompareEq && Node::shouldSpeculateArray(at(node.child1()), at(node.child2()))) 545 compileObjectEquality(node, m_jit.globalData()->jsArrayVPtr );547 compileObjectEquality(node, m_jit.globalData()->jsArrayVPtr, isArrayPrediction); 546 548 else 547 549 nonSpeculativeNonPeepholeCompare(node, condition, operation); … … 569 571 } 570 572 571 void SpeculativeJIT::compileObjectOrOtherLogicalNot(NodeIndex nodeIndex, void *vptr )573 void SpeculativeJIT::compileObjectOrOtherLogicalNot(NodeIndex nodeIndex, void *vptr, bool needSpeculationCheck) 572 574 { 573 575 JSValueOperand value(this, nodeIndex); … … 577 579 578 580 MacroAssembler::Jump notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, valueGPR, GPRInfo::tagMaskRegister); 579 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valueGPR), MacroAssembler::TrustedImmPtr(vptr))); 581 if (needSpeculationCheck) 582 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valueGPR), MacroAssembler::TrustedImmPtr(vptr))); 580 583 m_jit.move(TrustedImm32(static_cast<int32_t>(ValueFalse)), resultGPR); 581 584 MacroAssembler::Jump done = m_jit.jump(); … … 583 586 notCell.link(&m_jit); 584 587 585 m_jit.move(valueGPR, resultGPR); 586 m_jit.andPtr(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR); 587 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, resultGPR, MacroAssembler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull)))); 588 if (needSpeculationCheck) { 589 m_jit.move(valueGPR, resultGPR); 590 m_jit.andPtr(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR); 591 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, resultGPR, MacroAssembler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull)))); 592 } 588 593 m_jit.move(TrustedImm32(static_cast<int32_t>(ValueTrue)), resultGPR); 589 594 … … 606 611 } 607 612 if (at(node.child1()).shouldSpeculateFinalObjectOrOther()) { 608 compileObjectOrOtherLogicalNot(node.child1(), m_jit.globalData()->jsFinalObjectVPtr );613 compileObjectOrOtherLogicalNot(node.child1(), m_jit.globalData()->jsFinalObjectVPtr, !isFinalObjectOrOtherPrediction(m_state.forNode(node.child1()).m_type)); 609 614 return; 610 615 } 611 616 if (at(node.child1()).shouldSpeculateArrayOrOther()) { 612 compileObjectOrOtherLogicalNot(node.child1(), m_jit.globalData()->jsArrayVPtr );617 compileObjectOrOtherLogicalNot(node.child1(), m_jit.globalData()->jsArrayVPtr, !isArrayOrOtherPrediction(m_state.forNode(node.child1()).m_type)); 613 618 return; 614 619 } … … 670 675 } 671 676 672 void SpeculativeJIT::emitObjectOrOtherBranch(NodeIndex nodeIndex, BlockIndex taken, BlockIndex notTaken, void *vptr )677 void SpeculativeJIT::emitObjectOrOtherBranch(NodeIndex nodeIndex, BlockIndex taken, BlockIndex notTaken, void *vptr, bool needSpeculationCheck) 673 678 { 674 679 JSValueOperand value(this, nodeIndex); … … 676 681 677 682 MacroAssembler::Jump notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, valueGPR, GPRInfo::tagMaskRegister); 678 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valueGPR), MacroAssembler::TrustedImmPtr(vptr))); 683 if (needSpeculationCheck) 684 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valueGPR), MacroAssembler::TrustedImmPtr(vptr))); 679 685 addBranch(m_jit.jump(), taken); 680 686 681 687 notCell.link(&m_jit); 682 688 683 m_jit.andPtr(MacroAssembler::TrustedImm32(~TagBitUndefined), valueGPR); 684 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, valueGPR, MacroAssembler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull)))); 689 if (needSpeculationCheck) { 690 m_jit.andPtr(MacroAssembler::TrustedImm32(~TagBitUndefined), valueGPR); 691 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, valueGPR, MacroAssembler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull)))); 692 } 685 693 if (notTaken != (m_block + 1)) 686 694 addBranch(m_jit.jump(), notTaken); … … 694 702 GPRReg valueGPR = value.gpr(); 695 703 696 BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());697 BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(node.notTakenBytecodeOffset());704 BlockIndex taken = node.takenBlockIndex(); 705 BlockIndex notTaken = node.notTakenBlockIndex(); 698 706 699 707 if (isKnownBoolean(node.child1())) { … … 713 721 noResult(m_compileIndex); 714 722 } else if (at(node.child1()).shouldSpeculateFinalObjectOrOther()) { 715 emitObjectOrOtherBranch(node.child1(), taken, notTaken, m_jit.globalData()->jsFinalObjectVPtr );723 emitObjectOrOtherBranch(node.child1(), taken, notTaken, m_jit.globalData()->jsFinalObjectVPtr, !isFinalObjectOrOtherPrediction(m_state.forNode(node.child1()).m_type)); 716 724 } else if (at(node.child1()).shouldSpeculateArrayOrOther()) { 717 emitObjectOrOtherBranch(node.child1(), taken, notTaken, m_jit.globalData()->jsArrayVPtr );725 emitObjectOrOtherBranch(node.child1(), taken, notTaken, m_jit.globalData()->jsArrayVPtr, !isArrayOrOtherPrediction(m_state.forNode(node.child1()).m_type)); 718 726 } else if (at(node.child1()).shouldSpeculateNumber()) { 719 727 if (at(node.child1()).shouldSpeculateInteger()) { … … 748 756 addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(false)))), notTaken); 749 757 addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(true)))), taken); 750 } 751 752 if (predictBoolean) { 758 753 759 speculationCheck(m_jit.jump()); 754 760 value.use(); … … 788 794 case GetLocal: { 789 795 PredictedType prediction = node.variableAccessData()->prediction(); 796 AbstractValue& value = block()->valuesAtHead.operand(node.local()); 790 797 791 798 // If we have no prediction for this local, then don't attempt to compile. 792 if (prediction == PredictNone ) {799 if (prediction == PredictNone || value.isClear()) { 793 800 terminateSpeculativeExecution(); 794 801 break; … … 796 803 797 804 GPRTemporary result(this); 798 if (isInt32Prediction( prediction)) {805 if (isInt32Prediction(value.m_type)) { 799 806 m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr()); 800 807 … … 815 822 816 823 DataFormat format; 817 if (is ArrayPrediction(prediction))824 if (isCellPrediction(value.m_type)) 818 825 format = DataFormatJSCell; 819 else if (isBooleanPrediction( prediction))826 else if (isBooleanPrediction(value.m_type)) 820 827 format = DataFormatJSBoolean; 821 828 else … … 860 867 SpeculateCellOperand cell(this, node.child1()); 861 868 GPRReg cellGPR = cell.gpr(); 862 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr))); 869 if (!isArrayPrediction(m_state.forNode(node.child1()).m_type)) 870 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr))); 863 871 m_jit.storePtr(cellGPR, JITCompiler::addressFor(node.local())); 864 872 noResult(m_compileIndex); … … 1463 1471 // Check that base is an array, and that property is contained within m_vector (< m_vectorLength). 1464 1472 // If we have predicted the base to be type array, we can skip the check. 1465 if (!is KnownArray(node.child1()))1473 if (!isArrayPrediction(m_state.forNode(node.child1()).m_type)) 1466 1474 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr))); 1467 1475 speculationCheck(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset()))); … … 1513 1521 // Check that base is an array, and that property is contained within m_vector (< m_vectorLength). 1514 1522 // If we have predicted the base to be type array, we can skip the check. 1515 if (!is KnownArray(node.child1()))1523 if (!isArrayPrediction(m_state.forNode(node.child1()).m_type)) 1516 1524 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr))); 1517 1525 … … 1596 1604 writeBarrier(baseGPR, valueGPR, node.child2(), WriteBarrierForPropertyAccess, storageGPR, storageLengthGPR); 1597 1605 1598 if (!is KnownArray(node.child1()))1606 if (!isArrayPrediction(m_state.forNode(node.child1()).m_type)) 1599 1607 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr))); 1600 1608 … … 1639 1647 GPRReg storageLengthGPR = storageLength.gpr(); 1640 1648 1641 if (!is KnownArray(node.child1()))1649 if (!isArrayPrediction(m_state.forNode(node.child1()).m_type)) 1642 1650 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr))); 1643 1651 … … 1682 1690 1683 1691 case DFG::Jump: { 1684 BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());1692 BlockIndex taken = node.takenBlockIndex(); 1685 1693 if (taken != (m_block + 1)) 1686 1694 addBranch(m_jit.jump(), taken); … … 1693 1701 SpeculateIntegerOperand op(this, node.child1()); 1694 1702 1695 BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());1696 BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(node.notTakenBytecodeOffset());1703 BlockIndex taken = node.takenBlockIndex(); 1704 BlockIndex notTaken = node.notTakenBlockIndex(); 1697 1705 1698 1706 MacroAssembler::ResultCondition condition = MacroAssembler::NonZero; … … 1867 1875 GPRReg scratchGPR = scratch.gpr(); 1868 1876 1869 m_jit.move(thisValueGPR, scratchGPR); 1870 m_jit.andPtr(MacroAssembler::TrustedImm32(~TagBitUndefined), scratchGPR); 1871 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, scratchGPR, MacroAssembler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull)))); 1877 if (!isOtherPrediction(m_state.forNode(node.child1()).m_type)) { 1878 m_jit.move(thisValueGPR, scratchGPR); 1879 m_jit.andPtr(MacroAssembler::TrustedImm32(~TagBitUndefined), scratchGPR); 1880 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, scratchGPR, MacroAssembler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull)))); 1881 } 1872 1882 1873 1883 m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.codeBlock()->globalObject()), scratchGPR); … … 1879 1889 SpeculateCellOperand thisValue(this, node.child1()); 1880 1890 1881 speculationCheck(m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(thisValue.gpr()), JITCompiler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr))); 1891 if (!isObjectPrediction(m_state.forNode(node.child1()).m_type)) 1892 speculationCheck(m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(thisValue.gpr()), JITCompiler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr))); 1882 1893 1883 1894 cellResult(thisValue.gpr(), m_compileIndex); … … 1919 1930 // that it's a FinalObject then we speculate on that directly. Otherwise we 1920 1931 // do the slow (structure-based) check. 1921 if (at(node.child1()).shouldSpeculateFinalObject()) 1922 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(protoGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsFinalObjectVPtr))); 1923 else { 1932 if (at(node.child1()).shouldSpeculateFinalObject()) { 1933 if (!isFinalObjectPrediction(m_state.forNode(node.child1()).m_type)) 1934 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(protoGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsFinalObjectVPtr))); 1935 } else { 1924 1936 m_jit.loadPtr(MacroAssembler::Address(protoGPR, JSCell::structureOffset()), scratchGPR); 1925 1937 slowPath.append(m_jit.branch8(MacroAssembler::Below, MacroAssembler::Address(scratchGPR, Structure::typeInfoTypeOffset()), MacroAssembler::TrustedImm32(ObjectType))); … … 2050 2062 GPRReg resultGPR = result.gpr(); 2051 2063 2052 if (!is KnownArray(node.child1()))2064 if (!isArrayPrediction(m_state.forNode(node.child1()).m_type)) 2053 2065 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr))); 2054 2066 … … 2069 2081 GPRReg resultGPR = result.gpr(); 2070 2082 2071 if (!is KnownString(node.child1()))2083 if (!isStringPrediction(m_state.forNode(node.child1()).m_type)) 2072 2084 speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr))); 2073 2085 … … 2084 2096 } 2085 2097 case CheckStructure: { 2098 if (m_state.forNode(node.child1()).m_structure.isSubsetOf(node.structureSet())) { 2099 noResult(m_compileIndex); 2100 break; 2101 } 2102 2086 2103 SpeculateCellOperand base(this, node.child1()); 2087 2104 … … 2203 2220 GPRReg scratchGPR = scratch.gpr(); 2204 2221 2205 speculationCheck(m_jit.branchPtr(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), JITCompiler::TrustedImmPtr(methodCheckData.structure))); 2222 if (!m_state.forNode(node.child1()).m_structure.doesNotContainAnyOtherThan(methodCheckData.structure)) 2223 speculationCheck(m_jit.branchPtr(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), JITCompiler::TrustedImmPtr(methodCheckData.structure))); 2206 2224 if (methodCheckData.prototype != m_jit.codeBlock()->globalObject()->methodCallDummy()) { 2207 2225 m_jit.move(JITCompiler::TrustedImmPtr(methodCheckData.prototype->structureAddress()), scratchGPR); -
trunk/Source/JavaScriptCore/dfg/DFGStructureSet.h
r96527 r97218 27 27 #define DFGStructureSet_h 28 28 29 #include <wtf/Platform.h> 30 31 #if ENABLE(DFG_JIT) 32 33 #include "PredictedType.h" 34 #include <stdio.h> 29 35 #include <wtf/Vector.h> 30 36 … … 35 41 namespace DFG { 36 42 43 class StructureAbstractValue; 44 37 45 class StructureSet { 38 46 public: … … 42 50 { 43 51 m_structures.append(structure); 52 } 53 54 void clear() 55 { 56 m_structures.clear(); 44 57 } 45 58 … … 105 118 Structure* last() const { return m_structures.last(); } 106 119 120 PredictedType predictionFromStructures() const 121 { 122 PredictedType result = PredictNone; 123 124 for (size_t i = 0; i < m_structures.size(); ++i) 125 mergePrediction(result, predictionFromStructure(m_structures[i])); 126 127 return result; 128 } 129 130 bool operator==(const StructureSet& other) const 131 { 132 if (m_structures.size() != other.m_structures.size()) 133 return false; 134 135 for (size_t i = 0; i < m_structures.size(); ++i) { 136 if (!other.contains(m_structures[i])) 137 return false; 138 } 139 140 return true; 141 } 142 143 #ifndef NDEBUG 144 void dump(FILE* out) 145 { 146 fprintf(out, "["); 147 for (size_t i = 0; i < m_structures.size(); ++i) { 148 if (i) 149 fprintf(out, ", "); 150 fprintf(out, "%p", m_structures[i]); 151 } 152 fprintf(out, "]"); 153 } 154 #endif 155 107 156 private: 157 friend class StructureAbstractValue; 158 108 159 Vector<Structure*, 2> m_structures; 109 160 }; … … 111 162 } } // namespace JSC::DFG 112 163 164 #endif // ENABLE(DFG_JIT) 165 113 166 #endif // DFGStructureSet_h
Note: See TracChangeset
for help on using the changeset viewer.