Changeset 143654 in webkit
- Timestamp:
- Feb 21, 2013 2:59:02 PM (11 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 2 added
- 31 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/CMakeLists.txt
r143147 r143654 114 114 dfg/DFGThunks.cpp 115 115 dfg/DFGUnificationPhase.cpp 116 dfg/DFGUseKind.cpp 116 117 dfg/DFGValueSource.cpp 117 118 dfg/DFGVariableAccessDataDump.cpp -
trunk/Source/JavaScriptCore/ChangeLog
r143637 r143654 1 2013-02-20 Filip Pizlo <fpizlo@apple.com> 2 3 DFG should not change its mind about what type speculations a node does, by encoding the checks in the NodeType, UseKind, and ArrayMode 4 https://bugs.webkit.org/show_bug.cgi?id=109371 5 6 Reviewed by Oliver Hunt. 7 8 FixupPhase now locks in the speculations that each node will do. The DFG then 9 remembers those speculations, and doesn't change its mind about them even if the 10 graph is transformed - for example if a node's child is repointed to a different 11 node as part of CSE, CFG simplification, or folding. Each node ensures that it 12 executes the speculations promised by its edges. This is true even for Phantom 13 nodes. 14 15 This still leaves some craziness on the table for future work, like the 16 elimination of speculating SetLocal's due to CFG simplification 17 (webkit.org/b/109388) and elimination of nodes via DCE (webkit.org/b/109389). 18 19 In all, this allows for a huge simplification of the DFG. Instead of having to 20 execute the right speculation heuristic each time you want to decide what a node 21 does (for example Node::shouldSpeculateInteger(child1, child2) && 22 node->canSpeculateInteger()), you just ask for the use kinds of its children 23 (typically node->binaryUseKind() == Int32Use). Because the use kinds are 24 discrete, you can often just switch over them. This makes many parts of the code 25 more clear than they were before. 26 27 Having UseKinds describe the speculations being performed also makes it far 28 easier to perform analyses that need to know what speculations are done. This is 29 so far only used to simplify large parts of the CFA. 30 31 To have a larger vocabulary of UseKinds, this also changes the node allocator to 32 be able to round up Node sizes to the nearest multiple of 16. 33 34 This appears to be neutral on benchmarks, except for some goofy speed-ups, like 35 8% on Octane/box2d. 36 37 * CMakeLists.txt: 38 * GNUmakefile.list.am: 39 * JavaScriptCore.xcodeproj/project.pbxproj: 40 * Target.pri: 41 * dfg/DFGAbstractState.cpp: 42 (JSC::DFG::AbstractState::startExecuting): 43 (DFG): 44 (JSC::DFG::AbstractState::executeEdges): 45 (JSC::DFG::AbstractState::verifyEdge): 46 (JSC::DFG::AbstractState::verifyEdges): 47 (JSC::DFG::AbstractState::executeEffects): 48 (JSC::DFG::AbstractState::execute): 49 * dfg/DFGAbstractState.h: 50 (AbstractState): 51 (JSC::DFG::AbstractState::filterEdgeByUse): 52 (JSC::DFG::AbstractState::filterByType): 53 * dfg/DFGAbstractValue.h: 54 (JSC::DFG::AbstractValue::filter): 55 * dfg/DFGAdjacencyList.h: 56 (JSC::DFG::AdjacencyList::AdjacencyList): 57 (JSC::DFG::AdjacencyList::child): 58 (JSC::DFG::AdjacencyList::setChild): 59 (JSC::DFG::AdjacencyList::reset): 60 (JSC::DFG::AdjacencyList::firstChild): 61 (JSC::DFG::AdjacencyList::setFirstChild): 62 (JSC::DFG::AdjacencyList::numChildren): 63 (JSC::DFG::AdjacencyList::setNumChildren): 64 (AdjacencyList): 65 * dfg/DFGAllocator.h: 66 (DFG): 67 (Allocator): 68 (JSC::DFG::Allocator::cellSize): 69 (JSC::DFG::Allocator::Region::headerSize): 70 (JSC::DFG::Allocator::Region::numberOfThingsPerRegion): 71 (JSC::DFG::Allocator::Region::payloadSize): 72 (JSC::DFG::Allocator::Region::payloadBegin): 73 (JSC::DFG::Allocator::Region::payloadEnd): 74 (JSC::DFG::Allocator::Region::isInThisRegion): 75 (JSC::DFG::::Allocator): 76 (JSC::DFG::::~Allocator): 77 (JSC::DFG::::allocate): 78 (JSC::DFG::::free): 79 (JSC::DFG::::freeAll): 80 (JSC::DFG::::reset): 81 (JSC::DFG::::indexOf): 82 (JSC::DFG::::allocatorOf): 83 (JSC::DFG::::bumpAllocate): 84 (JSC::DFG::::freeListAllocate): 85 (JSC::DFG::::allocateSlow): 86 (JSC::DFG::::freeRegionsStartingAt): 87 (JSC::DFG::::startBumpingIn): 88 * dfg/DFGByteCodeParser.cpp: 89 (JSC::DFG::ByteCodeParser::addToGraph): 90 (JSC::DFG::ByteCodeParser::handleMinMax): 91 * dfg/DFGCSEPhase.cpp: 92 (JSC::DFG::CSEPhase::setLocalStoreElimination): 93 (JSC::DFG::CSEPhase::eliminateIrrelevantPhantomChildren): 94 (JSC::DFG::CSEPhase::setReplacement): 95 (JSC::DFG::CSEPhase::performNodeCSE): 96 * dfg/DFGCommon.h: 97 (DFG): 98 * dfg/DFGConstantFoldingPhase.cpp: 99 (JSC::DFG::ConstantFoldingPhase::foldConstants): 100 (JSC::DFG::ConstantFoldingPhase::addStructureTransitionCheck): 101 * dfg/DFGDriver.cpp: 102 (JSC::DFG::compile): 103 * dfg/DFGEdge.cpp: 104 (JSC::DFG::Edge::dump): 105 * dfg/DFGEdge.h: 106 (JSC::DFG::Edge::useKindUnchecked): 107 (JSC::DFG::Edge::useKind): 108 (JSC::DFG::Edge::shift): 109 * dfg/DFGFixupPhase.cpp: 110 (JSC::DFG::FixupPhase::run): 111 (JSC::DFG::FixupPhase::fixupNode): 112 (JSC::DFG::FixupPhase::checkArray): 113 (JSC::DFG::FixupPhase::blessArrayOperation): 114 (JSC::DFG::FixupPhase::fixIntEdge): 115 (JSC::DFG::FixupPhase::fixDoubleEdge): 116 (JSC::DFG::FixupPhase::injectInt32ToDoubleNode): 117 (FixupPhase): 118 (JSC::DFG::FixupPhase::truncateConstantToInt32): 119 (JSC::DFG::FixupPhase::truncateConstantsIfNecessary): 120 (JSC::DFG::FixupPhase::attemptToMakeIntegerAdd): 121 * dfg/DFGGraph.cpp: 122 (DFG): 123 (JSC::DFG::Graph::refChildren): 124 (JSC::DFG::Graph::derefChildren): 125 * dfg/DFGGraph.h: 126 (JSC::DFG::Graph::ref): 127 (JSC::DFG::Graph::deref): 128 (JSC::DFG::Graph::performSubstitution): 129 (JSC::DFG::Graph::isPredictedNumerical): 130 (JSC::DFG::Graph::addImmediateShouldSpeculateInteger): 131 (DFG): 132 * dfg/DFGNode.h: 133 (JSC::DFG::Node::Node): 134 (JSC::DFG::Node::convertToGetByOffset): 135 (JSC::DFG::Node::convertToPutByOffset): 136 (JSC::DFG::Node::willHaveCodeGenOrOSR): 137 (JSC::DFG::Node::child1): 138 (JSC::DFG::Node::child2): 139 (JSC::DFG::Node::child3): 140 (JSC::DFG::Node::binaryUseKind): 141 (Node): 142 (JSC::DFG::Node::isBinaryUseKind): 143 * dfg/DFGNodeAllocator.h: 144 (DFG): 145 * dfg/DFGNodeFlags.cpp: 146 (JSC::DFG::nodeFlagsAsString): 147 * dfg/DFGNodeType.h: 148 (DFG): 149 * dfg/DFGPredictionPropagationPhase.cpp: 150 (JSC::DFG::PredictionPropagationPhase::propagate): 151 * dfg/DFGSpeculativeJIT.cpp: 152 (JSC::DFG::SpeculativeJIT::speculationCheck): 153 (DFG): 154 (JSC::DFG::SpeculativeJIT::speculationWatchpoint): 155 (JSC::DFG::SpeculativeJIT::forwardSpeculationCheck): 156 (JSC::DFG::SpeculativeJIT::terminateSpeculativeExecution): 157 (JSC::DFG::SpeculativeJIT::typeCheck): 158 (JSC::DFG::SpeculativeJIT::forwardTypeCheck): 159 (JSC::DFG::SpeculativeJIT::fillStorage): 160 (JSC::DFG::SpeculativeJIT::compilePeepHoleBranch): 161 (JSC::DFG::SpeculativeJIT::compile): 162 (JSC::DFG::SpeculativeJIT::compileDoublePutByVal): 163 (JSC::DFG::SpeculativeJIT::compileValueToInt32): 164 (JSC::DFG::SpeculativeJIT::compileInt32ToDouble): 165 (JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray): 166 (JSC::DFG::SpeculativeJIT::compileInstanceOf): 167 (JSC::DFG::SpeculativeJIT::compileAdd): 168 (JSC::DFG::SpeculativeJIT::compileArithSub): 169 (JSC::DFG::SpeculativeJIT::compileArithNegate): 170 (JSC::DFG::SpeculativeJIT::compileArithMul): 171 (JSC::DFG::SpeculativeJIT::compileArithMod): 172 (JSC::DFG::SpeculativeJIT::compare): 173 (JSC::DFG::SpeculativeJIT::compileStrictEq): 174 (JSC::DFG::SpeculativeJIT::speculateInt32): 175 (JSC::DFG::SpeculativeJIT::speculateNumber): 176 (JSC::DFG::SpeculativeJIT::speculateRealNumber): 177 (JSC::DFG::SpeculativeJIT::speculateBoolean): 178 (JSC::DFG::SpeculativeJIT::speculateCell): 179 (JSC::DFG::SpeculativeJIT::speculateObject): 180 (JSC::DFG::SpeculativeJIT::speculateObjectOrOther): 181 (JSC::DFG::SpeculativeJIT::speculateString): 182 (JSC::DFG::SpeculativeJIT::speculateNotCell): 183 (JSC::DFG::SpeculativeJIT::speculateOther): 184 (JSC::DFG::SpeculativeJIT::speculate): 185 * dfg/DFGSpeculativeJIT.h: 186 (SpeculativeJIT): 187 (JSC::DFG::SpeculativeJIT::valueOfNumberConstant): 188 (JSC::DFG::SpeculativeJIT::needsTypeCheck): 189 (JSC::DFG::IntegerOperand::IntegerOperand): 190 (JSC::DFG::IntegerOperand::edge): 191 (IntegerOperand): 192 (JSC::DFG::IntegerOperand::node): 193 (JSC::DFG::IntegerOperand::gpr): 194 (JSC::DFG::IntegerOperand::use): 195 (JSC::DFG::JSValueOperand::JSValueOperand): 196 (JSValueOperand): 197 (JSC::DFG::JSValueOperand::edge): 198 (JSC::DFG::JSValueOperand::node): 199 (JSC::DFG::JSValueOperand::gpr): 200 (JSC::DFG::JSValueOperand::fill): 201 (JSC::DFG::JSValueOperand::use): 202 (JSC::DFG::StorageOperand::StorageOperand): 203 (JSC::DFG::StorageOperand::edge): 204 (StorageOperand): 205 (JSC::DFG::StorageOperand::node): 206 (JSC::DFG::StorageOperand::gpr): 207 (JSC::DFG::StorageOperand::use): 208 (JSC::DFG::SpeculateIntegerOperand::SpeculateIntegerOperand): 209 (SpeculateIntegerOperand): 210 (JSC::DFG::SpeculateIntegerOperand::edge): 211 (JSC::DFG::SpeculateIntegerOperand::node): 212 (JSC::DFG::SpeculateIntegerOperand::gpr): 213 (JSC::DFG::SpeculateIntegerOperand::use): 214 (JSC::DFG::SpeculateStrictInt32Operand::SpeculateStrictInt32Operand): 215 (SpeculateStrictInt32Operand): 216 (JSC::DFG::SpeculateStrictInt32Operand::edge): 217 (JSC::DFG::SpeculateStrictInt32Operand::node): 218 (JSC::DFG::SpeculateStrictInt32Operand::gpr): 219 (JSC::DFG::SpeculateStrictInt32Operand::use): 220 (JSC::DFG::SpeculateDoubleOperand::SpeculateDoubleOperand): 221 (SpeculateDoubleOperand): 222 (JSC::DFG::SpeculateDoubleOperand::edge): 223 (JSC::DFG::SpeculateDoubleOperand::node): 224 (JSC::DFG::SpeculateDoubleOperand::fpr): 225 (JSC::DFG::SpeculateDoubleOperand::use): 226 (JSC::DFG::SpeculateCellOperand::SpeculateCellOperand): 227 (SpeculateCellOperand): 228 (JSC::DFG::SpeculateCellOperand::edge): 229 (JSC::DFG::SpeculateCellOperand::node): 230 (JSC::DFG::SpeculateCellOperand::gpr): 231 (JSC::DFG::SpeculateCellOperand::use): 232 (JSC::DFG::SpeculateBooleanOperand::SpeculateBooleanOperand): 233 (JSC::DFG::SpeculateBooleanOperand::edge): 234 (SpeculateBooleanOperand): 235 (JSC::DFG::SpeculateBooleanOperand::node): 236 (JSC::DFG::SpeculateBooleanOperand::gpr): 237 (JSC::DFG::SpeculateBooleanOperand::use): 238 (DFG): 239 * dfg/DFGSpeculativeJIT32_64.cpp: 240 (JSC::DFG::SpeculativeJIT::fillInteger): 241 (JSC::DFG::SpeculativeJIT::fillJSValue): 242 (JSC::DFG::SpeculativeJIT::fillSpeculateIntInternal): 243 (JSC::DFG::SpeculativeJIT::fillSpeculateInt): 244 (JSC::DFG::SpeculativeJIT::fillSpeculateIntStrict): 245 (JSC::DFG::SpeculativeJIT::fillSpeculateDouble): 246 (JSC::DFG::SpeculativeJIT::fillSpeculateCell): 247 (JSC::DFG::SpeculativeJIT::fillSpeculateBoolean): 248 (JSC::DFG::SpeculativeJIT::compileObjectEquality): 249 (JSC::DFG::SpeculativeJIT::compileObjectToObjectOrOtherEquality): 250 (JSC::DFG::SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality): 251 (JSC::DFG::SpeculativeJIT::compileObjectOrOtherLogicalNot): 252 (JSC::DFG::SpeculativeJIT::compileLogicalNot): 253 (JSC::DFG::SpeculativeJIT::emitObjectOrOtherBranch): 254 (JSC::DFG::SpeculativeJIT::emitBranch): 255 (JSC::DFG::SpeculativeJIT::compile): 256 * dfg/DFGSpeculativeJIT64.cpp: 257 (JSC::DFG::SpeculativeJIT::fillInteger): 258 (JSC::DFG::SpeculativeJIT::fillJSValue): 259 (JSC::DFG::SpeculativeJIT::fillSpeculateIntInternal): 260 (JSC::DFG::SpeculativeJIT::fillSpeculateInt): 261 (JSC::DFG::SpeculativeJIT::fillSpeculateIntStrict): 262 (JSC::DFG::SpeculativeJIT::fillSpeculateDouble): 263 (JSC::DFG::SpeculativeJIT::fillSpeculateCell): 264 (JSC::DFG::SpeculativeJIT::fillSpeculateBoolean): 265 (JSC::DFG::SpeculativeJIT::compileObjectEquality): 266 (JSC::DFG::SpeculativeJIT::compileObjectToObjectOrOtherEquality): 267 (JSC::DFG::SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality): 268 (JSC::DFG::SpeculativeJIT::compileObjectOrOtherLogicalNot): 269 (JSC::DFG::SpeculativeJIT::compileLogicalNot): 270 (JSC::DFG::SpeculativeJIT::emitObjectOrOtherBranch): 271 (JSC::DFG::SpeculativeJIT::emitBranch): 272 (JSC::DFG::SpeculativeJIT::compile): 273 * dfg/DFGStructureCheckHoistingPhase.cpp: 274 (JSC::DFG::StructureCheckHoistingPhase::run): 275 * dfg/DFGUseKind.cpp: Added. 276 (WTF): 277 (WTF::printInternal): 278 * dfg/DFGUseKind.h: Added. 279 (DFG): 280 (JSC::DFG::typeFilterFor): 281 (JSC::DFG::isNumerical): 282 (WTF): 283 * dfg/DFGValidate.cpp: 284 (JSC::DFG::Validate::reportValidationContext): 285 1 286 2013-02-20 Mark Hahnenberg <mhahnenberg@apple.com> 2 287 -
trunk/Source/JavaScriptCore/GNUmakefile.list.am
r143392 r143654 273 273 Source/JavaScriptCore/dfg/DFGUnificationPhase.cpp \ 274 274 Source/JavaScriptCore/dfg/DFGUnificationPhase.h \ 275 Source/JavaScriptCore/dfg/DFGUseKind.cpp \ 276 Source/JavaScriptCore/dfg/DFGUseKind.h \ 275 277 Source/JavaScriptCore/dfg/DFGValueRecoveryOverride.h \ 276 278 Source/JavaScriptCore/dfg/DFGValueSource.cpp \ -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r143637 r143654 110 110 0F2E892C16D028AD009E4FD2 /* UnusedPointer.h in Headers */ = {isa = PBXBuildFile; fileRef = 65987F2F16828A7E003C2F8D /* UnusedPointer.h */; settings = {ATTRIBUTES = (Private, ); }; }; 111 111 0F2E892D16D02BAF009E4FD2 /* DFGMinifiedID.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB4B51016B3A964003F696B /* DFGMinifiedID.h */; settings = {ATTRIBUTES = (Private, ); }; }; 112 0F34B14916D42010001CDA5A /* DFGUseKind.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F34B14716D4200E001CDA5A /* DFGUseKind.cpp */; }; 113 0F34B14A16D42013001CDA5A /* DFGUseKind.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F34B14816D4200E001CDA5A /* DFGUseKind.h */; settings = {ATTRIBUTES = (Private, ); }; }; 112 114 0F34B14C16D43E0D001CDA5A /* PolymorphicAccessStructureList.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F34B14B16D43E0C001CDA5A /* PolymorphicAccessStructureList.h */; settings = {ATTRIBUTES = (Private, ); }; }; 113 115 0F3B3A1A153E68F2003ED0FF /* DFGConstantFoldingPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F3B3A17153E68EF003ED0FF /* DFGConstantFoldingPhase.cpp */; }; … … 1002 1004 0F2C556D14738F2E00121E4F /* DFGCodeBlocks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DFGCodeBlocks.cpp; sourceTree = "<group>"; }; 1003 1005 0F2C556E14738F2E00121E4F /* DFGCodeBlocks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DFGCodeBlocks.h; sourceTree = "<group>"; }; 1006 0F34B14716D4200E001CDA5A /* DFGUseKind.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGUseKind.cpp; path = dfg/DFGUseKind.cpp; sourceTree = "<group>"; }; 1007 0F34B14816D4200E001CDA5A /* DFGUseKind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGUseKind.h; path = dfg/DFGUseKind.h; sourceTree = "<group>"; }; 1004 1008 0F34B14B16D43E0C001CDA5A /* PolymorphicAccessStructureList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolymorphicAccessStructureList.h; sourceTree = "<group>"; }; 1005 1009 0F3B3A17153E68EF003ED0FF /* DFGConstantFoldingPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGConstantFoldingPhase.cpp; path = dfg/DFGConstantFoldingPhase.cpp; sourceTree = "<group>"; }; … … 2710 2714 0FBE0F6F16C1DB010082C5E8 /* DFGUnificationPhase.cpp */, 2711 2715 0FBE0F7016C1DB010082C5E8 /* DFGUnificationPhase.h */, 2716 0F34B14716D4200E001CDA5A /* DFGUseKind.cpp */, 2717 0F34B14816D4200E001CDA5A /* DFGUseKind.h */, 2712 2718 0F3B3A2915474FF4003ED0FF /* DFGValidate.cpp */, 2713 2719 0F3B3A2A15474FF4003ED0FF /* DFGValidate.h */, … … 3252 3258 BC18C4500E16F5CD00B34460 /* Profile.h in Headers */, 3253 3259 95CD45770E1C4FDD0085358E /* ProfileGenerator.h in Headers */, 3260 0F34B14A16D42013001CDA5A /* DFGUseKind.h in Headers */, 3254 3261 BC18C4510E16F5CD00B34460 /* ProfileNode.h in Headers */, 3255 3262 0FF729A5166AD351000F5BA3 /* ProfilerBytecode.h in Headers */, … … 3958 3965 0FF729B1166AD35C000F5BA3 /* ProfilerCompiledBytecode.cpp in Sources */, 3959 3966 0FF729B2166AD35C000F5BA3 /* ProfilerDatabase.cpp in Sources */, 3967 0F34B14916D42010001CDA5A /* DFGUseKind.cpp in Sources */, 3960 3968 0FF729B3166AD35C000F5BA3 /* ProfilerOrigin.cpp in Sources */, 3961 3969 0FF729B4166AD35C000F5BA3 /* ProfilerOriginStack.cpp in Sources */, -
trunk/Source/JavaScriptCore/Target.pri
r143147 r143654 150 150 dfg/DFGThunks.cpp \ 151 151 dfg/DFGUnificationPhase.cpp \ 152 dfg/DFGUseKind.cpp \ 152 153 dfg/DFGValueSource.cpp \ 153 154 dfg/DFGVariableAccessDataDump.cpp \ -
trunk/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
r143241 r143654 235 235 } 236 236 237 bool AbstractState:: execute(unsigned indexInBlock)237 bool AbstractState::startExecuting(Node* node) 238 238 { 239 239 ASSERT(m_block); … … 242 242 m_didClobber = false; 243 243 244 Node* node = m_block->at(indexInBlock);245 244 node->setCanExit(false); 245 246 246 if (!node->shouldGenerate()) 247 return true; 248 247 return false; 248 249 return true; 250 } 251 252 bool AbstractState::startExecuting(unsigned indexInBlock) 253 { 254 return startExecuting(m_block->at(indexInBlock)); 255 } 256 257 void AbstractState::executeEdges(Node* node) 258 { 259 DFG_NODE_DO_TO_CHILDREN(m_graph, node, filterEdgeByUse); 260 } 261 262 void AbstractState::executeEdges(unsigned indexInBlock) 263 { 264 executeEdges(m_block->at(indexInBlock)); 265 } 266 267 void AbstractState::verifyEdge(Node*, Edge edge) 268 { 269 RELEASE_ASSERT(!(forNode(edge).m_type & ~typeFilterFor(edge.useKind()))); 270 } 271 272 void AbstractState::verifyEdges(Node* node) 273 { 274 DFG_NODE_DO_TO_CHILDREN(m_graph, node, verifyEdge); 275 } 276 277 bool AbstractState::executeEffects(unsigned indexInBlock, Node* node) 278 { 279 if (!ASSERT_DISABLED) 280 verifyEdges(node); 281 249 282 switch (node->op()) { 250 283 case JSConstant: … … 252 285 case PhantomArguments: { 253 286 forNode(node).set(m_graph.valueOfJSConstant(node)); 254 node->setCanExit(false);255 287 break; 256 288 } … … 258 290 case Identity: { 259 291 forNode(node) = forNode(node->child1()); 260 node->setCanExit(false);261 292 break; 262 293 } … … 266 297 if (variableAccessData->prediction() == SpecNone) { 267 298 m_isValid = false; 268 node->setCanExit(true); 269 break; 270 } 271 bool canExit = false; 299 break; 300 } 272 301 AbstractValue value = m_variables.operand(variableAccessData->local()); 273 302 if (!variableAccessData->isCaptured()) { 274 303 if (value.isClear()) 275 canExit |= true;304 node->setCanExit(true); 276 305 } 277 306 if (value.value()) 278 307 m_foundConstants = true; 279 308 forNode(node) = value; 280 node->setCanExit(canExit);281 309 break; 282 310 } … … 287 315 m_foundConstants = true; 288 316 forNode(node) = value; 289 node->setCanExit(false);290 317 break; 291 318 } 292 319 293 320 case SetLocal: { 294 if (node->variableAccessData()->isCaptured()295 || m_graph.isCreatedThisArgument(node->local())) {296 m_variables.operand(node->local()) = forNode(node->child1());297 node->setCanExit(false);298 break;299 }300 301 if (node->variableAccessData()->shouldUseDoubleFormat()) {302 speculateNumberUnary(node);303 m_variables.operand(node->local()).set(SpecDouble);304 break;305 }306 307 SpeculatedType predictedType = node->variableAccessData()->argumentAwarePrediction();308 if (isInt32Speculation(predictedType))309 speculateInt32Unary(node);310 else if (isCellSpeculation(predictedType)) {311 node->setCanExit(!isCellSpeculation(forNode(node->child1()).m_type));312 forNode(node->child1()).filter(SpecCell);313 } else if (isBooleanSpeculation(predictedType))314 speculateBooleanUnary(node);315 else316 node->setCanExit(false);317 318 321 m_variables.operand(node->local()) = forNode(node->child1()); 319 322 break; … … 323 326 // Assert that the state of arguments has been set. 324 327 ASSERT(!m_block->valuesAtHead.operand(node->local()).isClear()); 325 node->setCanExit(false);326 328 break; 327 329 … … 363 365 if (constantWasSet) { 364 366 m_foundConstants = true; 365 node->setCanExit(false);366 367 break; 367 368 } 368 369 } 369 speculateInt32Binary(node);370 370 forNode(node).set(SpecInt32); 371 371 break; … … 378 378 if (trySetConstant(node, JSValue(child.asUInt32()))) { 379 379 m_foundConstants = true; 380 node->setCanExit(false);381 380 break; 382 381 } 383 382 } 384 if (!node->canSpeculateInteger()) {383 if (!node->canSpeculateInteger()) 385 384 forNode(node).set(SpecDouble); 386 node->setCanExit(false); 387 } else { 385 else { 388 386 forNode(node).set(SpecInt32); 389 387 node->setCanExit(true); … … 391 389 break; 392 390 } 393 394 391 395 392 case DoubleAsInt32: { … … 405 402 } 406 403 node->setCanExit(true); 407 forNode(node->child1()).filter(SpecNumber);408 404 forNode(node).set(SpecInt32); 409 405 break; … … 420 416 if (constantWasSet) { 421 417 m_foundConstants = true; 422 node->setCanExit(false);423 418 break; 424 419 } 425 }426 if (node->child1()->shouldSpeculateInteger())427 speculateInt32Unary(node);428 else if (node->child1()->shouldSpeculateBoolean())429 speculateBooleanUnary(node);430 else if (node->child1()->shouldSpeculateNumber())431 speculateNumberUnary(node);432 else {433 node->setCanExit(forNode(node->child1()).m_type & SpecCell);434 forNode(node->child1()).filter(~SpecCell);435 420 } 436 421 … … 445 430 && trySetConstant(node, JSValue(JSValue::EncodeAsDouble, child.asNumber()))) { 446 431 m_foundConstants = true; 447 node->setCanExit(false); 448 break; 449 } 450 speculateNumberUnary(node); 432 break; 433 } 451 434 if (isInt32Speculation(forNode(node->child1()).m_type)) 452 435 forNode(node).set(SpecDoubleReal); … … 456 439 } 457 440 458 case CheckNumber:459 forNode(node->child1()).filter(SpecNumber);460 break;461 462 441 case ValueAdd: 463 442 case ArithAdd: { … … 467 446 && trySetConstant(node, JSValue(left.asNumber() + right.asNumber()))) { 468 447 m_foundConstants = true; 469 node->setCanExit(false); 470 break; 471 } 472 if (m_graph.addShouldSpeculateInteger(node)) { 473 speculateInt32Binary( 474 node, !nodeCanTruncateInteger(node->arithNodeFlags())); 448 break; 449 } 450 switch (node->binaryUseKind()) { 451 case Int32Use: 475 452 forNode(node).set(SpecInt32); 476 break;477 }478 if (Node::shouldSpeculateNumberExpectingDefined(node->child1().node(), node->child2().node())) {479 speculateNumberBinary(node);453 if (!nodeCanTruncateInteger(node->arithNodeFlags())) 454 node->setCanExit(true); 455 break; 456 case NumberUse: 480 457 if (isRealNumberSpeculation(forNode(node->child1()).m_type) 481 458 && isRealNumberSpeculation(forNode(node->child2()).m_type)) … … 484 461 forNode(node).set(SpecDouble); 485 462 break; 486 }487 if (node->op() == ValueAdd) {463 default: 464 RELEASE_ASSERT(node->op() == ValueAdd); 488 465 clobberWorld(node->codeOrigin, indexInBlock); 489 466 forNode(node).set(SpecString | SpecInt32 | SpecNumber); 490 node->setCanExit(false); 491 break; 492 } 493 // We don't handle this yet. :-( 494 m_isValid = false; 495 node->setCanExit(true); 467 break; 468 } 496 469 break; 497 470 } … … 503 476 && trySetConstant(node, JSValue(left.asNumber() - right.asNumber()))) { 504 477 m_foundConstants = true; 505 node->setCanExit(false); 506 break; 507 } 508 if (m_graph.addShouldSpeculateInteger(node)) { 509 speculateInt32Binary( 510 node, !nodeCanTruncateInteger(node->arithNodeFlags())); 478 break; 479 } 480 switch (node->binaryUseKind()) { 481 case Int32Use: 511 482 forNode(node).set(SpecInt32); 512 break; 513 } 514 speculateNumberBinary(node); 515 forNode(node).set(SpecDouble); 483 if (!nodeCanTruncateInteger(node->arithNodeFlags())) 484 node->setCanExit(true); 485 break; 486 case NumberUse: 487 forNode(node).set(SpecDouble); 488 break; 489 default: 490 RELEASE_ASSERT_NOT_REACHED(); 491 break; 492 } 516 493 break; 517 494 } … … 522 499 && trySetConstant(node, JSValue(-child.asNumber()))) { 523 500 m_foundConstants = true; 524 node->setCanExit(false); 525 break; 526 } 527 if (m_graph.negateShouldSpeculateInteger(node)) { 528 speculateInt32Unary( 529 node, !nodeCanTruncateInteger(node->arithNodeFlags())); 501 break; 502 } 503 switch (node->child1().useKind()) { 504 case Int32Use: 530 505 forNode(node).set(SpecInt32); 531 break; 532 } 533 speculateNumberUnary(node); 534 forNode(node).set(SpecDouble); 506 if (!nodeCanTruncateInteger(node->arithNodeFlags())) 507 node->setCanExit(true); 508 break; 509 case NumberUse: 510 forNode(node).set(SpecDouble); 511 break; 512 default: 513 RELEASE_ASSERT_NOT_REACHED(); 514 break; 515 } 535 516 break; 536 517 } … … 542 523 && trySetConstant(node, JSValue(left.asNumber() * right.asNumber()))) { 543 524 m_foundConstants = true; 544 node->setCanExit(false); 545 break; 546 } 547 if (m_graph.mulShouldSpeculateInteger(node)) { 548 speculateInt32Binary( 549 node, 550 !nodeCanTruncateInteger(node->arithNodeFlags()) 551 || !nodeCanIgnoreNegativeZero(node->arithNodeFlags())); 525 break; 526 } 527 switch (node->binaryUseKind()) { 528 case Int32Use: 552 529 forNode(node).set(SpecInt32); 553 break; 554 } 555 speculateNumberBinary(node); 556 if (isRealNumberSpeculation(forNode(node->child1()).m_type) 557 || isRealNumberSpeculation(forNode(node->child2()).m_type)) 558 forNode(node).set(SpecDoubleReal); 559 else 560 forNode(node).set(SpecDouble); 530 if (!nodeCanTruncateInteger(node->arithNodeFlags()) 531 || !nodeCanIgnoreNegativeZero(node->arithNodeFlags())) 532 node->setCanExit(true); 533 break; 534 case NumberUse: 535 if (isRealNumberSpeculation(forNode(node->child1()).m_type) 536 || isRealNumberSpeculation(forNode(node->child2()).m_type)) 537 forNode(node).set(SpecDoubleReal); 538 else 539 forNode(node).set(SpecDouble); 540 break; 541 default: 542 RELEASE_ASSERT_NOT_REACHED(); 543 break; 544 } 561 545 break; 562 546 } … … 592 576 if (constantWasSet) { 593 577 m_foundConstants = true; 594 node->setCanExit(false);595 578 break; 596 579 } 597 580 } 598 if (Node::shouldSpeculateIntegerForArithmetic(node->child1().node(), node->child2().node()) 599 && node->canSpeculateInteger()) { 600 speculateInt32Binary(node, true); // forcing can-exit, which is a bit on the conservative side. 581 switch (node->binaryUseKind()) { 582 case Int32Use: 601 583 forNode(node).set(SpecInt32); 602 break; 603 } 604 speculateNumberBinary(node); 605 forNode(node).set(SpecDouble); 584 node->setCanExit(true); 585 break; 586 case NumberUse: 587 forNode(node).set(SpecDouble); 588 break; 589 default: 590 RELEASE_ASSERT_NOT_REACHED(); 591 break; 592 } 606 593 break; 607 594 } … … 612 599 && trySetConstant(node, JSValue(fabs(child.asNumber())))) { 613 600 m_foundConstants = true; 614 node->setCanExit(false); 615 break; 616 } 617 if (node->child1()->shouldSpeculateIntegerForArithmetic() 618 && node->canSpeculateInteger()) { 619 speculateInt32Unary(node, true); 601 break; 602 } 603 switch (node->child1().useKind()) { 604 case Int32Use: 620 605 forNode(node).set(SpecInt32); 621 break; 622 } 623 speculateNumberUnary(node); 624 forNode(node).set(SpecDouble); 606 node->setCanExit(true); 607 break; 608 case NumberUse: 609 forNode(node).set(SpecDouble); 610 break; 611 default: 612 RELEASE_ASSERT_NOT_REACHED(); 613 break; 614 } 625 615 break; 626 616 } … … 631 621 && trySetConstant(node, JSValue(sqrt(child.asNumber())))) { 632 622 m_foundConstants = true; 633 node->setCanExit(false); 634 break; 635 } 636 speculateNumberUnary(node); 623 break; 624 } 637 625 forNode(node).set(SpecDouble); 638 626 break; … … 653 641 if (didSetConstant) { 654 642 m_foundConstants = true; 655 node->setCanExit(false); 656 break; 657 } 658 Node* child = node->child1().node(); 659 if (isBooleanSpeculation(child->prediction())) 660 speculateBooleanUnary(node); 661 else if (child->shouldSpeculateObjectOrOther()) { 643 break; 644 } 645 switch (node->child1().useKind()) { 646 case BooleanUse: 647 case Int32Use: 648 case NumberUse: 649 case UntypedUse: 650 break; 651 case ObjectOrOtherUse: 662 652 node->setCanExit(true); 663 forNode(child).filter((SpecCell & ~SpecString) | SpecOther); 664 } else if (child->shouldSpeculateInteger()) 665 speculateInt32Unary(node); 666 else if (child->shouldSpeculateNumber()) 667 speculateNumberUnary(node); 668 else 669 node->setCanExit(false); 653 break; 654 default: 655 RELEASE_ASSERT_NOT_REACHED(); 656 break; 657 } 670 658 forNode(node).set(SpecBoolean); 671 659 break; … … 765 753 } 766 754 } 767 768 Node* childNode = node->child1().node(); 769 if (isCellSpeculation(childNode->prediction())) { 770 if (isStringSpeculation(childNode->prediction())) 771 forNode(childNode).filter(SpecString); 772 else 773 forNode(childNode).filter(SpecCell); 755 756 switch (node->child1().useKind()) { 757 case StringUse: 758 case CellUse: 774 759 node->setCanExit(true); 760 break; 761 case UntypedUse: 762 break; 763 default: 764 RELEASE_ASSERT_NOT_REACHED(); 765 break; 775 766 } 776 767 forNode(node).set(SpecString); … … 824 815 if (constantWasSet) { 825 816 m_foundConstants = true; 826 node->setCanExit(false);827 817 break; 828 818 } … … 830 820 forNode(node).set(SpecBoolean); 831 821 832 if (node->op() == CompareEqConstant) { 833 // We can exit if we haven't fired the MasqueradesAsUndefind watchpoint yet. 834 node->setCanExit(m_codeBlock->globalObjectFor(node->codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()); 835 break; 836 } 837 838 Node* left = node->child1().node(); 839 Node* right = node->child2().node(); 840 SpeculatedType filter; 841 SpeculatedTypeChecker checker; 842 if (Node::shouldSpeculateInteger(left, right)) { 843 filter = SpecInt32; 844 checker = isInt32Speculation; 845 } else if (Node::shouldSpeculateNumber(left, right)) { 846 filter = SpecNumber; 847 checker = isNumberSpeculation; 848 } else if (node->op() == CompareEq) { 849 if (left->shouldSpeculateString() || right->shouldSpeculateString()) { 850 node->setCanExit(false); 851 break; 852 } 853 if (left->shouldSpeculateObject() && right->shouldSpeculateObject()) { 854 node->setCanExit(true); 855 forNode(left).filter(SpecObject); 856 forNode(right).filter(SpecObject); 857 break; 858 } 859 if (left->shouldSpeculateObject() && right->shouldSpeculateObjectOrOther()) { 860 node->setCanExit(true); 861 forNode(left).filter(SpecObject); 862 forNode(right).filter(SpecObject | SpecOther); 863 break; 864 } 865 if (left->shouldSpeculateObjectOrOther() && right->shouldSpeculateObject()) { 866 node->setCanExit(true); 867 forNode(left).filter(SpecObject | SpecOther); 868 forNode(right).filter(SpecObject); 869 break; 870 } 871 872 filter = SpecTop; 873 checker = isAnySpeculation; 874 clobberWorld(node->codeOrigin, indexInBlock); 875 } else { 876 filter = SpecTop; 877 checker = isAnySpeculation; 878 clobberWorld(node->codeOrigin, indexInBlock); 879 } 880 node->setCanExit( 881 !checker(forNode(left).m_type) 882 || !checker(forNode(right).m_type)); 883 forNode(left).filter(filter); 884 forNode(right).filter(filter); 822 // This is overly conservative. But the only thing this prevents is store elimination, 823 // and how likely is it, really, that you'll have redundant stores across a comparison 824 // operation? Comparison operations are typically at the end of basic blocks, so 825 // unless we have global store elimination (super unlikely given how unprofitable that 826 // optimization is to begin with), you aren't going to be wanting to store eliminate 827 // across an equality op. 828 node->setCanExit(true); 885 829 break; 886 830 } … … 895 839 && trySetConstant(node, jsBoolean(left.asNumber() == right.asNumber()))) { 896 840 m_foundConstants = true; 897 node->setCanExit(false);898 841 break; 899 842 } 900 843 forNode(node).set(SpecBoolean); 901 if (node->op() == CompareStrictEqConstant) { 902 node->setCanExit(false); 903 break; 904 } 905 if (Node::shouldSpeculateInteger(leftNode, rightNode)) { 906 speculateInt32Binary(node); 907 break; 908 } 909 if (Node::shouldSpeculateNumber(leftNode, rightNode)) { 910 speculateNumberBinary(node); 911 break; 912 } 913 if (leftNode->shouldSpeculateString() || rightNode->shouldSpeculateString()) { 914 node->setCanExit(false); 915 break; 916 } 917 if (leftNode->shouldSpeculateObject() && rightNode->shouldSpeculateObject()) { 918 node->setCanExit(true); 919 forNode(leftNode).filter(SpecObject); 920 forNode(rightNode).filter(SpecObject); 921 break; 922 } 923 node->setCanExit(false); 844 node->setCanExit(true); // This is overly conservative. 924 845 break; 925 846 } … … 927 848 case StringCharCodeAt: 928 849 node->setCanExit(true); 929 forNode(node->child1()).filter(SpecString);930 forNode(node->child2()).filter(SpecInt32);931 850 forNode(node).set(SpecInt32); 932 851 break; … … 934 853 case StringCharAt: 935 854 node->setCanExit(true); 936 forNode(node->child1()).filter(SpecString);937 forNode(node->child2()).filter(SpecInt32);938 855 forNode(node).set(SpecString); 939 856 break; … … 955 872 break; 956 873 case Array::String: 957 forNode(node->child2()).filter(SpecInt32);958 874 forNode(node).set(SpecString); 959 875 break; 960 876 case Array::Arguments: 961 forNode(node->child2()).filter(SpecInt32);962 877 forNode(node).makeTop(); 963 878 break; 964 879 case Array::Int32: 965 forNode(node->child2()).filter(SpecInt32);966 880 if (node->arrayMode().isOutOfBounds()) { 967 881 clobberWorld(node->codeOrigin, indexInBlock); … … 971 885 break; 972 886 case Array::Double: 973 forNode(node->child2()).filter(SpecInt32);974 887 if (node->arrayMode().isOutOfBounds()) { 975 888 clobberWorld(node->codeOrigin, indexInBlock); … … 983 896 case Array::ArrayStorage: 984 897 case Array::SlowPutArrayStorage: 985 forNode(node->child2()).filter(SpecInt32);986 898 if (node->arrayMode().isOutOfBounds()) 987 899 clobberWorld(node->codeOrigin, indexInBlock); … … 989 901 break; 990 902 case Array::Int8Array: 991 forNode(node->child2()).filter(SpecInt32);992 903 forNode(node).set(SpecInt32); 993 904 break; 994 905 case Array::Int16Array: 995 forNode(node->child2()).filter(SpecInt32);996 906 forNode(node).set(SpecInt32); 997 907 break; 998 908 case Array::Int32Array: 999 forNode(node->child2()).filter(SpecInt32);1000 909 forNode(node).set(SpecInt32); 1001 910 break; 1002 911 case Array::Uint8Array: 1003 forNode(node->child2()).filter(SpecInt32);1004 912 forNode(node).set(SpecInt32); 1005 913 break; 1006 914 case Array::Uint8ClampedArray: 1007 forNode(node->child2()).filter(SpecInt32);1008 915 forNode(node).set(SpecInt32); 1009 916 break; 1010 917 case Array::Uint16Array: 1011 forNode(node->child2()).filter(SpecInt32);1012 918 forNode(node).set(SpecInt32); 1013 919 break; 1014 920 case Array::Uint32Array: 1015 forNode(node->child2()).filter(SpecInt32);1016 921 if (node->shouldSpeculateInteger()) 1017 922 forNode(node).set(SpecInt32); … … 1020 925 break; 1021 926 case Array::Float32Array: 1022 forNode(node->child2()).filter(SpecInt32);1023 927 forNode(node).set(SpecDouble); 1024 928 break; 1025 929 case Array::Float64Array: 1026 forNode(node->child2()).filter(SpecInt32);1027 930 forNode(node).set(SpecDouble); 1028 931 break; … … 1037 940 case PutByValAlias: { 1038 941 node->setCanExit(true); 1039 Edge child1 = m_graph.varArgChild(node, 0);1040 Edge child2 = m_graph.varArgChild(node, 1);1041 Edge child3 = m_graph.varArgChild(node, 2);1042 942 switch (node->arrayMode().modeForPut().type()) { 1043 943 case Array::ForceExit: … … 1048 948 break; 1049 949 case Array::Int32: 1050 forNode(child1).filter(SpecCell);1051 forNode(child2).filter(SpecInt32);1052 forNode(child3).filter(SpecInt32);1053 950 if (node->arrayMode().isOutOfBounds()) 1054 951 clobberWorld(node->codeOrigin, indexInBlock); 1055 952 break; 1056 953 case Array::Double: 1057 forNode(child1).filter(SpecCell);1058 forNode(child2).filter(SpecInt32);1059 forNode(child3).filter(SpecRealNumber);1060 954 if (node->arrayMode().isOutOfBounds()) 1061 955 clobberWorld(node->codeOrigin, indexInBlock); … … 1063 957 case Array::Contiguous: 1064 958 case Array::ArrayStorage: 1065 forNode(child1).filter(SpecCell);1066 forNode(child2).filter(SpecInt32);1067 959 if (node->arrayMode().isOutOfBounds()) 1068 960 clobberWorld(node->codeOrigin, indexInBlock); 1069 961 break; 1070 962 case Array::SlowPutArrayStorage: 1071 forNode(child1).filter(SpecCell);1072 forNode(child2).filter(SpecInt32);1073 963 if (node->arrayMode().mayStoreToHole()) 1074 964 clobberWorld(node->codeOrigin, indexInBlock); 1075 965 break; 1076 case Array::Arguments:1077 forNode(child1).filter(SpecCell);1078 forNode(child2).filter(SpecInt32);1079 break;1080 case Array::Int8Array:1081 forNode(child1).filter(SpecCell);1082 forNode(child2).filter(SpecInt32);1083 if (child3->shouldSpeculateInteger())1084 forNode(child3).filter(SpecInt32);1085 else1086 forNode(child3).filter(SpecNumber);1087 break;1088 case Array::Int16Array:1089 forNode(child1).filter(SpecCell);1090 forNode(child2).filter(SpecInt32);1091 if (child3->shouldSpeculateInteger())1092 forNode(child3).filter(SpecInt32);1093 else1094 forNode(child3).filter(SpecNumber);1095 break;1096 case Array::Int32Array:1097 forNode(child1).filter(SpecCell);1098 forNode(child2).filter(SpecInt32);1099 if (child3->shouldSpeculateInteger())1100 forNode(child3).filter(SpecInt32);1101 else1102 forNode(child3).filter(SpecNumber);1103 break;1104 case Array::Uint8Array:1105 forNode(child1).filter(SpecCell);1106 forNode(child2).filter(SpecInt32);1107 if (child3->shouldSpeculateInteger())1108 forNode(child3).filter(SpecInt32);1109 else1110 forNode(child3).filter(SpecNumber);1111 break;1112 case Array::Uint8ClampedArray:1113 forNode(child1).filter(SpecCell);1114 forNode(child2).filter(SpecInt32);1115 if (child3->shouldSpeculateInteger())1116 forNode(child3).filter(SpecInt32);1117 else1118 forNode(child3).filter(SpecNumber);1119 break;1120 case Array::Uint16Array:1121 forNode(child1).filter(SpecCell);1122 forNode(child2).filter(SpecInt32);1123 if (child3->shouldSpeculateInteger())1124 forNode(child3).filter(SpecInt32);1125 else1126 forNode(child3).filter(SpecNumber);1127 break;1128 case Array::Uint32Array:1129 forNode(child1).filter(SpecCell);1130 forNode(child2).filter(SpecInt32);1131 if (child3->shouldSpeculateInteger())1132 forNode(child3).filter(SpecInt32);1133 else1134 forNode(child3).filter(SpecNumber);1135 break;1136 case Array::Float32Array:1137 forNode(child1).filter(SpecCell);1138 forNode(child2).filter(SpecInt32);1139 forNode(child3).filter(SpecNumber);1140 break;1141 case Array::Float64Array:1142 forNode(child1).filter(SpecCell);1143 forNode(child2).filter(SpecInt32);1144 forNode(child3).filter(SpecNumber);1145 break;1146 966 default: 1147 CRASH();1148 967 break; 1149 968 } … … 1153 972 case ArrayPush: 1154 973 node->setCanExit(true); 1155 switch (node->arrayMode().type()) {1156 case Array::Int32:1157 forNode(node->child2()).filter(SpecInt32);1158 break;1159 case Array::Double:1160 forNode(node->child2()).filter(SpecRealNumber);1161 break;1162 default:1163 break;1164 }1165 974 clobberWorld(node->codeOrigin, indexInBlock); 1166 975 forNode(node).set(SpecNumber); … … 1175 984 case RegExpExec: 1176 985 case RegExpTest: 1177 node->setCanExit(1178 !isCellSpeculation(forNode(node->child1()).m_type)1179 || !isCellSpeculation(forNode(node->child2()).m_type));1180 forNode(node->child1()).filter(SpecCell);1181 forNode(node->child2()).filter(SpecCell);1182 986 forNode(node).makeTop(); 1183 987 break; 1184 988 1185 989 case Jump: 1186 node->setCanExit(false);1187 990 break; 1188 991 … … 1192 995 if (result == DefinitelyTrue) { 1193 996 m_branchDirection = TakeTrue; 1194 node->setCanExit(false);1195 997 break; 1196 998 } 1197 999 if (result == DefinitelyFalse) { 1198 1000 m_branchDirection = TakeFalse; 1199 node->setCanExit(false);1200 1001 break; 1201 1002 } … … 1204 1005 // We can specialize the source variable's value on each direction of 1205 1006 // the branch. 1206 if (child->shouldSpeculateBoolean()) 1207 speculateBooleanUnary(node); 1208 else if (child->shouldSpeculateObjectOrOther()) { 1209 node->setCanExit(true); 1210 forNode(child).filter(SpecObject | SpecOther); 1211 } else if (child->shouldSpeculateInteger()) 1212 speculateInt32Unary(node); 1213 else if (child->shouldSpeculateNumber()) 1214 speculateNumberUnary(node); 1215 else 1216 node->setCanExit(false); 1007 node->setCanExit(true); // This is overly conservative. 1217 1008 m_branchDirection = TakeBoth; 1218 1009 break; … … 1221 1012 case Return: 1222 1013 m_isValid = false; 1223 node->setCanExit(false);1224 1014 break; 1225 1015 … … 1231 1021 1232 1022 case ToPrimitive: { 1233 Node* child = node->child1().node(); 1234 1235 JSValue childConst = forNode(child).value(); 1023 JSValue childConst = forNode(node->child1()).value(); 1236 1024 if (childConst && childConst.isNumber() && trySetConstant(node, childConst)) { 1237 1025 m_foundConstants = true; 1238 node->setCanExit(false); 1239 break; 1240 } 1241 1242 if (child->shouldSpeculateInteger()) { 1243 speculateInt32Unary(node); 1026 break; 1027 } 1028 1029 if (node->child1().useKind() == Int32Use) { 1244 1030 forNode(node).set(SpecInt32); 1245 1031 break; 1246 1032 } 1247 1033 1248 AbstractValue& source = forNode( child);1034 AbstractValue& source = forNode(node->child1()); 1249 1035 AbstractValue& destination = forNode(node); 1250 1036 … … 1276 1062 } 1277 1063 destination.set(type); 1278 node->setCanExit(false);1279 1064 break; 1280 1065 } 1281 1066 1282 1067 case StrCat: 1283 node->setCanExit(false);1284 1068 forNode(node).set(SpecString); 1285 1069 break; … … 1287 1071 case NewArray: 1288 1072 node->setCanExit(true); 1289 switch (node->indexingType()) {1290 case ALL_BLANK_INDEXING_TYPES:1291 CRASH();1292 break;1293 case ALL_UNDECIDED_INDEXING_TYPES:1294 ASSERT(!node->numChildren());1295 break;1296 case ALL_INT32_INDEXING_TYPES:1297 for (unsigned operandIndex = 0; operandIndex < node->numChildren(); ++operandIndex)1298 forNode(m_graph.m_varArgChildren[node->firstChild() + operandIndex]).filter(SpecInt32);1299 break;1300 case ALL_DOUBLE_INDEXING_TYPES:1301 for (unsigned operandIndex = 0; operandIndex < node->numChildren(); ++operandIndex)1302 forNode(m_graph.m_varArgChildren[node->firstChild() + operandIndex]).filter(SpecRealNumber);1303 break;1304 case ALL_CONTIGUOUS_INDEXING_TYPES:1305 case ALL_ARRAY_STORAGE_INDEXING_TYPES:1306 break;1307 default:1308 CRASH();1309 break;1310 }1311 1073 forNode(node).set(m_graph.globalObjectFor(node->codeOrigin)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType())); 1312 1074 m_haveStructures = true; … … 1321 1083 case NewArrayWithSize: 1322 1084 node->setCanExit(true); 1323 forNode(node->child1()).filter(SpecInt32);1324 1085 forNode(node).set(SpecArray); 1325 1086 m_haveStructures = true; … … 1327 1088 1328 1089 case NewRegexp: 1329 node->setCanExit(false);1330 1090 forNode(node).set(m_graph.globalObjectFor(node->codeOrigin)->regExpStructure()); 1331 1091 m_haveStructures = true; … … 1333 1093 1334 1094 case ConvertThis: { 1335 Node* child = node->child1().node();1336 1095 AbstractValue& source = forNode(node->child1()); 1337 1096 AbstractValue& destination = forNode(node); … … 1342 1101 // be hit, but then again, you never know. 1343 1102 destination = source; 1344 node->setCanExit(false);1345 1103 m_foundConstants = true; // Tell the constant folder to turn this into Identity. 1346 1104 break; … … 1348 1106 1349 1107 node->setCanExit(true); 1350 1351 if (isOtherSpeculation(child->prediction())) { 1352 source.filter(SpecOther); 1108 switch (node->child1().useKind()) { 1109 case OtherUse: 1353 1110 destination.set(SpecObjectOther); 1354 1111 break; 1355 } 1356 1357 if (isObjectSpeculation(child->prediction())) { 1358 source.filter(SpecObject); 1112 case ObjectUse: 1359 1113 destination = source; 1360 1114 break; 1361 } 1362 1363 destination = source; 1364 destination.merge(SpecObjectOther); 1115 case UntypedUse: 1116 destination = source; 1117 destination.merge(SpecObjectOther); 1118 break; 1119 default: 1120 RELEASE_ASSERT_NOT_REACHED(); 1121 break; 1122 } 1365 1123 break; 1366 1124 } 1367 1125 1368 1126 case CreateThis: { 1369 AbstractValue& source = forNode(node->child1()); 1370 AbstractValue& destination = forNode(node); 1371 1372 node->setCanExit(!isCellSpeculation(source.m_type)); 1373 1374 source.filter(SpecFunction); 1375 destination.set(SpecFinalObject); 1127 forNode(node).set(SpecFinalObject); 1376 1128 break; 1377 1129 } … … 1382 1134 1383 1135 case NewObject: 1384 node->setCanExit(false);1385 1136 forNode(node).set(node->structure()); 1386 1137 m_haveStructures = true; … … 1388 1139 1389 1140 case CreateActivation: 1390 node->setCanExit(false);1391 1141 forNode(node).set(m_codeBlock->globalObjectFor(node->codeOrigin)->activationStructure()); 1392 1142 m_haveStructures = true; … … 1394 1144 1395 1145 case CreateArguments: 1396 node->setCanExit(false);1397 1146 forNode(node).set(m_codeBlock->globalObjectFor(node->codeOrigin)->argumentsStructure()); 1398 1147 m_haveStructures = true; … … 1401 1150 case TearOffActivation: 1402 1151 case TearOffArguments: 1403 node->setCanExit(false);1404 1152 // Does nothing that is user-visible. 1405 1153 break; … … 1408 1156 if (isEmptySpeculation( 1409 1157 m_variables.operand( 1410 m_graph.argumentsRegisterFor(node->codeOrigin)).m_type)) { 1411 node->setCanExit(false); 1412 m_foundConstants = true; 1413 } else 1158 m_graph.argumentsRegisterFor(node->codeOrigin)).m_type)) 1159 m_foundConstants = true; 1160 else 1414 1161 node->setCanExit(true); 1415 1162 break; … … 1431 1178 1432 1179 case GetMyArgumentsLengthSafe: 1433 node->setCanExit(false);1434 1180 // This potentially clobbers all structures if the arguments object had a getter 1435 1181 // installed on the length property. … … 1445 1191 // the arguments a bit. Note that this ends up being further optimized by the 1446 1192 // ArgumentsSimplificationPhase. 1447 forNode(node->child1()).filter(SpecInt32);1448 1193 forNode(node).makeTop(); 1449 1194 break; … … 1454 1199 // a getter. We don't speculate against this. 1455 1200 clobberWorld(node->codeOrigin, indexInBlock); 1456 // But we do speculate that the index is an integer.1457 forNode(node->child1()).filter(SpecInt32);1458 1201 // And the result is unknown. 1459 1202 forNode(node).makeTop(); … … 1463 1206 case NewFunctionExpression: 1464 1207 case NewFunctionNoCheck: 1465 node->setCanExit(false);1466 1208 forNode(node).set(m_codeBlock->globalObjectFor(node->codeOrigin)->functionStructure()); 1467 1209 break; 1468 1210 1469 1211 case GetCallee: 1470 node->setCanExit(false);1471 1212 forNode(node).set(SpecFunction); 1472 1213 break; … … 1474 1215 case SetCallee: 1475 1216 case SetMyScope: 1476 node->setCanExit(false);1477 1217 break; 1478 1218 … … 1480 1220 case GetMyScope: 1481 1221 case SkipTopScope: 1482 node->setCanExit(false);1483 1222 forNode(node).set(SpecCellOther); 1484 1223 break; 1485 1224 1486 1225 case SkipScope: { 1487 node->setCanExit(false);1488 1226 JSValue child = forNode(node->child1()).value(); 1489 1227 if (child && trySetConstant(node, JSValue(jsCast<JSScope*>(child.asCell())->next()))) { … … 1496 1234 1497 1235 case GetScopeRegisters: 1498 node->setCanExit(false);1499 forNode(node->child1()).filter(SpecCell);1500 1236 forNode(node).clear(); // The result is not a JS value. 1501 1237 break; 1502 1238 1503 1239 case GetScopedVar: 1504 node->setCanExit(false);1505 1240 forNode(node).makeTop(); 1506 1241 break; 1507 1242 1508 1243 case PutScopedVar: 1509 node->setCanExit(false);1510 1244 clobberCapturedVars(node->codeOrigin); 1511 1245 break; … … 1519 1253 } 1520 1254 if (isCellSpeculation(node->child1()->prediction())) { 1521 forNode(node->child1()).filter(SpecCell);1522 1523 1255 if (Structure* structure = forNode(node->child1()).bestProvenStructure()) { 1524 1256 GetByIdStatus status = GetByIdStatus::computeFor( … … 1556 1288 // FIXME: We could eliminate these entirely if we know the exact value that flows into this. 1557 1289 // https://bugs.webkit.org/show_bug.cgi?id=106201 1558 forNode(node->child1()).filter(SpecCell);1559 1290 node->setCanExit(true); 1560 1291 break; … … 1565 1296 // FIXME: We should be able to propagate the structure sets of constants (i.e. prototypes). 1566 1297 AbstractValue& value = forNode(node->child1()); 1298 ASSERT(!(value.m_type & ~SpecCell)); // Edge filtering should have already ensured this. 1567 1299 // If this structure check is attempting to prove knowledge already held in 1568 1300 // the futurePossibleStructure set then the constant folding phase should … … 1572 1304 || value.m_currentKnownStructure.isSubsetOf(set)) 1573 1305 m_foundConstants = true; 1574 node->setCanExit( 1575 !value.m_currentKnownStructure.isSubsetOf(set) 1576 || !isCellSpeculation(value.m_type)); 1306 if (!value.m_currentKnownStructure.isSubsetOf(set)) 1307 node->setCanExit(true); 1577 1308 value.filter(set); 1578 1309 m_haveStructures = true; … … 1592 1323 ASSERT(value.m_futurePossibleStructure.isSubsetOf(StructureSet(node->structure()))); 1593 1324 1594 ASSERT(value.isClear() || isCellSpeculation(value.m_type)); // Value could be clear if we've proven must-exit due to a speculation statically known to be bad.1595 1325 value.filter(node->structure()); 1596 1326 m_haveStructures = true; … … 1601 1331 case PutStructure: 1602 1332 case PhantomPutStructure: 1603 node->setCanExit(false);1604 1333 if (!forNode(node->child1()).m_currentKnownStructure.isClear()) { 1605 1334 clobberStructures(indexInBlock); … … 1611 1340 case AllocatePropertyStorage: 1612 1341 case ReallocatePropertyStorage: 1613 node->setCanExit(!isCellSpeculation(forNode(node->child1()).m_type));1614 forNode(node->child1()).filter(SpecCell);1615 1342 forNode(node).clear(); // The result is not a JS value. 1616 1343 break; … … 1618 1345 if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) { 1619 1346 m_foundConstants = true; 1620 node->setCanExit(false);1621 1347 break; 1622 1348 } … … 1631 1357 case Array::ArrayStorage: 1632 1358 case Array::SlowPutArrayStorage: 1633 forNode(node->child1()).filter(SpecCell);1634 1359 break; 1635 1360 case Array::Arguments: … … 1674 1399 if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) { 1675 1400 m_foundConstants = true; 1676 node->setCanExit(false);1677 1401 break; 1678 1402 } … … 1680 1404 || node->arrayMode().conversion() == Array::RageConvert); 1681 1405 node->setCanExit(true); 1682 forNode(node->child1()).filter(SpecCell);1683 if (node->child2())1684 forNode(node->child2()).filter(SpecInt32);1685 1406 clobberStructures(indexInBlock); 1686 1407 forNode(node->child1()).filterArrayModes(node->arrayMode().arrayModesThatPassFiltering()); … … 1695 1416 m_foundConstants = true; 1696 1417 node->setCanExit(true); 1697 if (node->child2())1698 forNode(node->child2()).filter(SpecInt32);1699 1418 clobberStructures(indexInBlock); 1700 1419 value.filter(set); … … 1703 1422 } 1704 1423 case GetIndexedPropertyStorage: { 1705 node->setCanExit(false);1706 1424 forNode(node).clear(); 1707 1425 break; 1708 1426 } 1709 case GetByOffset: 1710 if (!node->child1()->hasStorageResult()) { 1711 node->setCanExit(!isCellSpeculation(forNode(node->child1()).m_type)); 1712 forNode(node->child1()).filter(SpecCell); 1713 } 1427 case GetByOffset: { 1714 1428 forNode(node).makeTop(); 1715 1429 break; 1430 } 1716 1431 1717 1432 case PutByOffset: { 1718 bool canExit = false;1719 if (!node->child1()->hasStorageResult()) {1720 canExit |= !isCellSpeculation(forNode(node->child1()).m_type);1721 forNode(node->child1()).filter(SpecCell);1722 }1723 canExit |= !isCellSpeculation(forNode(node->child2()).m_type);1724 forNode(node->child2()).filter(SpecCell);1725 node->setCanExit(canExit);1726 1433 break; 1727 1434 } … … 1732 1439 m_foundConstants = true; 1733 1440 ASSERT(value); 1734 node->setCanExit(false);1735 1441 break; 1736 1442 } … … 1767 1473 } 1768 1474 } 1769 forNode(node->child1()).filter(SpecCell);1770 1475 clobberWorld(node->codeOrigin, indexInBlock); 1771 1476 break; 1772 1477 1773 1478 case GetGlobalVar: 1774 node->setCanExit(false);1775 1479 forNode(node).makeTop(); 1776 1480 break; … … 1782 1486 case PutGlobalVar: 1783 1487 case PutGlobalVarCheck: 1784 node->setCanExit(false);1785 1488 break; 1786 1489 1787 1490 case CheckHasInstance: 1788 1491 node->setCanExit(true); 1789 forNode(node->child1()).filter(SpecCell);1790 1492 // Sadly, we don't propagate the fact that we've done CheckHasInstance 1791 1493 break; … … 1794 1496 node->setCanExit(true); 1795 1497 // Again, sadly, we don't propagate the fact that we've done InstanceOf 1796 // FIXME: This appears broken: CheckHasInstance already does an unconditional cell1797 // check. https://bugs.webkit.org/show_bug.cgi?id=1074791798 if (!(node->child1()->prediction() & ~SpecCell) && !(forNode(node->child1()).m_type & ~SpecCell))1799 forNode(node->child1()).filter(SpecCell);1800 forNode(node->child2()).filter(SpecCell);1801 1498 forNode(node).set(SpecBoolean); 1802 1499 break; … … 1805 1502 case Flush: 1806 1503 case PhantomLocal: 1807 node->setCanExit(false);1808 break;1809 1810 1504 case Breakpoint: 1811 node->setCanExit(false);1812 1505 break; 1813 1506 … … 1837 1530 case Nop: 1838 1531 case CountExecution: 1839 node->setCanExit(false);1840 1532 break; 1841 1533 … … 1846 1538 1847 1539 return m_isValid; 1540 } 1541 1542 bool AbstractState::executeEffects(unsigned indexInBlock) 1543 { 1544 return executeEffects(indexInBlock, m_block->at(indexInBlock)); 1545 } 1546 1547 bool AbstractState::execute(unsigned indexInBlock) 1548 { 1549 Node* node = m_block->at(indexInBlock); 1550 if (!startExecuting(node)) 1551 return true; 1552 1553 executeEdges(node); 1554 return executeEffects(indexInBlock, node); 1848 1555 } 1849 1556 -
trunk/Source/JavaScriptCore/dfg/DFGAbstractState.h
r141069 r143654 159 159 // for block terminals, so long as those terminals are not Return or variants 160 160 // of Throw. 161 bool execute(unsigned); 161 // 162 // This is guaranteed to be equivalent to doing: 163 // 164 // if (state.startExecuting(index)) { 165 // state.executeEdges(index); 166 // result = state.executeEffects(index); 167 // } else 168 // result = true; 169 bool execute(unsigned indexInBlock); 170 171 // Indicate the start of execution of the node. It resets any state in the node, 172 // that is progressively built up by executeEdges() and executeEffects(). In 173 // particular, this resets canExit(), so if you want to "know" between calls of 174 // startExecuting() and executeEdges()/Effects() whether the last run of the 175 // analysis concluded that the node can exit, you should probably set that 176 // information aside prior to calling startExecuting(). 177 bool startExecuting(Node*); 178 bool startExecuting(unsigned indexInBlock); 179 180 // Abstractly execute the edges of the given node. This runs filterEdgeByUse() 181 // on all edges of the node. You can skip this step, if you have already used 182 // filterEdgeByUse() (or some equivalent) on each edge. 183 void executeEdges(Node*); 184 void executeEdges(unsigned indexInBlock); 185 186 ALWAYS_INLINE void filterEdgeByUse(Node* node, Edge edge) 187 { 188 #if !ASSERT_DISABLED 189 switch (edge.useKind()) { 190 case KnownInt32Use: 191 case KnownNumberUse: 192 case KnownCellUse: 193 ASSERT(!(forNode(edge).m_type & ~typeFilterFor(edge.useKind()))); 194 break; 195 default: 196 break; 197 } 198 #endif // !ASSERT_DISABLED 199 200 filterByType(node, edge.node(), typeFilterFor(edge.useKind())); 201 } 202 203 // Abstractly execute the effects of the given node. This changes the abstract 204 // state assuming that edges have already been filtered. 205 bool executeEffects(unsigned indexInBlock); 206 bool executeEffects(unsigned indexInBlock, Node*); 162 207 163 208 // Did the last executed node clobber the world? … … 191 236 192 237 static bool mergeVariableBetweenBlocks(AbstractValue& destination, AbstractValue& source, Node* destinationNode, Node* sourceNode); 193 194 void speculateInt32Unary(Node* node, bool forceCanExit = false)195 {196 AbstractValue& childValue = forNode(node->child1());197 node->setCanExit(forceCanExit || !isInt32Speculation(childValue.m_type));198 childValue.filter(SpecInt32);199 }200 201 void speculateNumberUnary(Node* node)202 {203 AbstractValue& childValue = forNode(node->child1());204 node->setCanExit(!isNumberSpeculation(childValue.m_type));205 childValue.filter(SpecNumber);206 }207 208 void speculateBooleanUnary(Node* node)209 {210 AbstractValue& childValue = forNode(node->child1());211 node->setCanExit(!isBooleanSpeculation(childValue.m_type));212 childValue.filter(SpecBoolean);213 }214 215 void speculateInt32Binary(Node* node, bool forceCanExit = false)216 {217 AbstractValue& childValue1 = forNode(node->child1());218 AbstractValue& childValue2 = forNode(node->child2());219 node->setCanExit(220 forceCanExit221 || !isInt32Speculation(childValue1.m_type)222 || !isInt32Speculation(childValue2.m_type));223 childValue1.filter(SpecInt32);224 childValue2.filter(SpecInt32);225 }226 227 void speculateNumberBinary(Node* node)228 {229 AbstractValue& childValue1 = forNode(node->child1());230 AbstractValue& childValue2 = forNode(node->child2());231 node->setCanExit(232 !isNumberSpeculation(childValue1.m_type)233 || !isNumberSpeculation(childValue2.m_type));234 childValue1.filter(SpecNumber);235 childValue2.filter(SpecNumber);236 }237 238 238 239 enum BooleanResult { … … 260 261 } 261 262 263 ALWAYS_INLINE void filterByType(Node* node, Node* child, SpeculatedType type) 264 { 265 AbstractValue& value = forNode(child); 266 if (value.m_type & ~type) 267 node->setCanExit(true); 268 value.filter(type); 269 } 270 271 void verifyEdge(Node*, Edge); 272 void verifyEdges(Node*); 273 262 274 CodeBlock* m_codeBlock; 263 275 Graph& m_graph; -
trunk/Source/JavaScriptCore/dfg/DFGAbstractValue.h
r141069 r143654 235 235 void filter(const StructureSet& other) 236 236 { 237 // FIXME: This could be optimized for the common case of m_type not 238 // having structures, array modes, or a specific value. 239 // https://bugs.webkit.org/show_bug.cgi?id=109663 237 240 m_type &= other.speculationFromStructures(); 238 241 m_arrayModes &= other.arrayModesFromStructures(); -
trunk/Source/JavaScriptCore/dfg/DFGAdjacencyList.h
r141069 r143654 48 48 49 49 AdjacencyList(Kind kind) 50 #if !ASSERT_DISABLED51 : m_kind(kind)52 #endif53 50 { 54 51 if (kind == Variable) { … … 58 55 } 59 56 60 AdjacencyList(Kind kind, Node* child1, Node* child2, Node* child3) 61 #if !ASSERT_DISABLED 62 : m_kind(Fixed) 63 #endif 57 AdjacencyList(Kind kind, Edge child1, Edge child2, Edge child3) 64 58 { 65 59 ASSERT_UNUSED(kind, kind == Fixed); … … 68 62 69 63 AdjacencyList(Kind kind, unsigned firstChild, unsigned numChildren) 70 #if !ASSERT_DISABLED71 : m_kind(Variable)72 #endif73 64 { 74 65 ASSERT_UNUSED(kind, kind == Variable); … … 80 71 { 81 72 ASSERT(i < Size); 82 ASSERT(m_kind == Fixed);83 73 return m_words[i]; 84 74 } … … 87 77 { 88 78 ASSERT(i < Size); 89 ASSERT(m_kind == Fixed);90 79 return m_words[i]; 91 80 } … … 94 83 { 95 84 ASSERT(i < Size); 96 ASSERT(m_kind == Fixed);97 85 m_words[i] = nodeUse; 98 86 } … … 126 114 void reset() 127 115 { 128 #if !ASSERT_DISABLED129 m_kind = Fixed;130 #endif131 116 initialize(); 132 117 } … … 143 128 unsigned firstChild() const 144 129 { 145 ASSERT(m_kind == Variable);146 130 return m_words[0].m_encodedWord; 147 131 } 148 132 void setFirstChild(unsigned firstChild) 149 133 { 150 ASSERT(m_kind == Variable);151 134 m_words[0].m_encodedWord = firstChild; 152 135 } … … 154 137 unsigned numChildren() const 155 138 { 156 ASSERT(m_kind == Variable);157 139 return m_words[1].m_encodedWord; 158 140 } 159 141 void setNumChildren(unsigned numChildren) 160 142 { 161 ASSERT(m_kind == Variable);162 143 m_words[1].m_encodedWord = numChildren; 163 144 } 164 145 165 #if !ASSERT_DISABLED166 Kind kind() const { return m_kind; }167 #endif168 146 private: 169 147 Edge m_words[Size]; 170 #if !ASSERT_DISABLED171 Kind m_kind;172 #endif173 148 }; 174 149 -
trunk/Source/JavaScriptCore/dfg/DFGAllocator.h
r142377 r143654 44 44 // - You call free() on all T's that you allocated, and never use freeAll(). 45 45 46 template<typename T> 46 // forcedCellSize: set this to 0 if you're happy with the default alignment, or set it 47 // to a non-zero value if you want to forcibly align the allocations to a certain 48 // value. When you do this, Allocator will ASSERT that forcedCellAlignment >= sizeof(T). 49 50 template<typename T, unsigned forcedCellAlignment> 47 51 class Allocator { 48 52 public: … … 64 68 void* freeListAllocate(); 65 69 void* allocateSlow(); 66 70 71 static size_t cellSize() 72 { 73 if (!forcedCellAlignment) 74 return sizeof(T); 75 76 ASSERT(forcedCellAlignment >= sizeof(T)); 77 return forcedCellAlignment; 78 } 79 67 80 struct Region { 68 81 static size_t size() { return 64 * KB; } 69 static size_t headerSize() { return std::max(sizeof(Region), sizeof(T)); } 70 static unsigned numberOfThingsPerRegion() { return (size() - headerSize()) / sizeof(T); } 71 T* data() { return bitwise_cast<T*>(bitwise_cast<char*>(this) + headerSize()); } 72 bool isInThisRegion(const T* pointer) { return static_cast<unsigned>(pointer - data()) < numberOfThingsPerRegion(); } 82 static size_t headerSize() { return std::max(sizeof(Region), cellSize()); } 83 static unsigned numberOfThingsPerRegion() { return (size() - headerSize()) / cellSize(); } 84 static size_t payloadSize() { return numberOfThingsPerRegion() * cellSize(); } 85 char* payloadBegin() { return bitwise_cast<char*>(this) + headerSize(); } 86 char* payloadEnd() { return payloadBegin() + payloadSize(); } 87 bool isInThisRegion(const T* pointer) { return static_cast<size_t>(bitwise_cast<char*>(pointer) - payloadBegin()) < payloadSize(); } 73 88 static Region* regionFor(const T* pointer) { return bitwise_cast<Region*>(bitwise_cast<uintptr_t>(pointer) & ~(size() - 1)); } 74 89 … … 83 98 Region* m_regionHead; 84 99 void** m_freeListHead; 85 T* m_bumpEnd;86 unsignedm_bumpRemaining;100 char* m_bumpEnd; 101 size_t m_bumpRemaining; 87 102 }; 88 103 89 template<typename T >90 inline Allocator<T >::Allocator()104 template<typename T, unsigned forcedCellAlignment> 105 inline Allocator<T, forcedCellAlignment>::Allocator() 91 106 : m_regionHead(0) 92 107 , m_freeListHead(0) … … 95 110 } 96 111 97 template<typename T >98 inline Allocator<T >::~Allocator()112 template<typename T, unsigned forcedCellAlignment> 113 inline Allocator<T, forcedCellAlignment>::~Allocator() 99 114 { 100 115 reset(); 101 116 } 102 117 103 template<typename T >104 ALWAYS_INLINE void* Allocator<T >::allocate()118 template<typename T, unsigned forcedCellAlignment> 119 ALWAYS_INLINE void* Allocator<T, forcedCellAlignment>::allocate() 105 120 { 106 121 void* result = bumpAllocate(); … … 110 125 } 111 126 112 template<typename T >113 void Allocator<T >::free(T* object)127 template<typename T, unsigned forcedCellAlignment> 128 void Allocator<T, forcedCellAlignment>::free(T* object) 114 129 { 115 130 object->~T(); … … 120 135 } 121 136 122 template<typename T >123 void Allocator<T >::freeAll()137 template<typename T, unsigned forcedCellAlignment> 138 void Allocator<T, forcedCellAlignment>::freeAll() 124 139 { 125 140 if (!m_regionHead) { … … 143 158 } 144 159 145 template<typename T >146 void Allocator<T >::reset()160 template<typename T, unsigned forcedCellAlignment> 161 void Allocator<T, forcedCellAlignment>::reset() 147 162 { 148 163 freeRegionsStartingAt(m_regionHead); … … 153 168 } 154 169 155 template<typename T >156 unsigned Allocator<T >::indexOf(const T* object)170 template<typename T, unsigned forcedCellAlignment> 171 unsigned Allocator<T, forcedCellAlignment>::indexOf(const T* object) 157 172 { 158 173 unsigned baseIndex = 0; 159 174 for (Region* region = m_regionHead; region; region = region->m_next) { 160 175 if (region->isInThisRegion(object)) 161 return baseIndex + ( object - region->data());176 return baseIndex + (bitwise_cast<char*>(object) - region->payloadBegin()) / cellSize(); 162 177 baseIndex += Region::numberOfThingsPerRegion(); 163 178 } … … 166 181 } 167 182 168 template<typename T >169 Allocator<T >* Allocator<T>::allocatorOf(const T* object)183 template<typename T, unsigned forcedCellAlignment> 184 Allocator<T, forcedCellAlignment>* Allocator<T, forcedCellAlignment>::allocatorOf(const T* object) 170 185 { 171 186 return Region::regionFor(object)->m_allocator; 172 187 } 173 188 174 template<typename T >175 ALWAYS_INLINE void* Allocator<T >::bumpAllocate()176 { 177 if ( unsignedremaining = m_bumpRemaining) {178 remaining --;189 template<typename T, unsigned forcedCellAlignment> 190 ALWAYS_INLINE void* Allocator<T, forcedCellAlignment>::bumpAllocate() 191 { 192 if (size_t remaining = m_bumpRemaining) { 193 remaining -= cellSize(); 179 194 m_bumpRemaining = remaining; 180 return m_bumpEnd - (remaining + 1);195 return m_bumpEnd - (remaining + cellSize()); 181 196 } 182 197 return 0; 183 198 } 184 199 185 template<typename T >186 void* Allocator<T >::freeListAllocate()200 template<typename T, unsigned forcedCellAlignment> 201 void* Allocator<T, forcedCellAlignment>::freeListAllocate() 187 202 { 188 203 void** result = m_freeListHead; … … 193 208 } 194 209 195 template<typename T >196 void* Allocator<T >::allocateSlow()210 template<typename T, unsigned forcedCellAlignment> 211 void* Allocator<T, forcedCellAlignment>::allocateSlow() 197 212 { 198 213 ASSERT(!m_freeListHead); … … 217 232 } 218 233 219 template<typename T >220 void Allocator<T >::freeRegionsStartingAt(typename Allocator<T>::Region* region)234 template<typename T, unsigned forcedCellAlignment> 235 void Allocator<T, forcedCellAlignment>::freeRegionsStartingAt(typename Allocator<T, forcedCellAlignment>::Region* region) 221 236 { 222 237 while (region) { … … 227 242 } 228 243 229 template<typename T >230 void Allocator<T >::startBumpingIn(typename Allocator<T>::Region* region)231 { 232 m_bumpEnd = region-> data() + Region::numberOfThingsPerRegion();233 m_bumpRemaining = Region:: numberOfThingsPerRegion();244 template<typename T, unsigned forcedCellAlignment> 245 void Allocator<T, forcedCellAlignment>::startBumpingIn(typename Allocator<T, forcedCellAlignment>::Region* region) 246 { 247 m_bumpEnd = region->payloadEnd(); 248 m_bumpRemaining = Region::payloadSize(); 234 249 } 235 250 -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r143165 r143654 699 699 Node* result = m_graph.addNode( 700 700 DontRefChildren, DontRefNode, SpecNone, 701 op, currentCodeOrigin(), Edge(child1), Edge(child2), Edge(child3)); 702 ASSERT(op != Phi); 703 m_currentBlock->append(result); 704 705 if (defaultFlags(op) & NodeMustGenerate) 706 m_graph.refChildren(result); 707 return result; 708 } 709 Node* addToGraph(NodeType op, Edge child1, Edge child2 = Edge(), Edge child3 = Edge()) 710 { 711 Node* result = m_graph.addNode( 712 DontRefChildren, DontRefNode, SpecNone, 701 713 op, currentCodeOrigin(), child1, child2, child3); 702 714 ASSERT(op != Phi); … … 711 723 Node* result = m_graph.addNode( 712 724 DontRefChildren, DontRefNode, SpecNone, 713 op, currentCodeOrigin(), info, child1, child2, child3);725 op, currentCodeOrigin(), info, Edge(child1), Edge(child2), Edge(child3)); 714 726 if (op == Phi) 715 727 m_currentBlock->phis.append(result); … … 725 737 Node* result = m_graph.addNode( 726 738 DontRefChildren, DontRefNode, SpecNone, 727 op, currentCodeOrigin(), info1, info2, child1, child2, child3);739 op, currentCodeOrigin(), info1, info2, Edge(child1), Edge(child2), Edge(child3)); 728 740 ASSERT(op != Phi); 729 741 m_currentBlock->append(result); … … 1466 1478 if (argumentCountIncludingThis == 2) { // Math.min(x) 1467 1479 Node* result = get(registerOffset + argumentToOperand(1)); 1468 addToGraph( CheckNumber, result);1480 addToGraph(Phantom, Edge(result, NumberUse)); 1469 1481 setIntrinsicResult(usesResult, resultOperand, result); 1470 1482 return true; -
trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
r143241 r143654 970 970 case GetByVal: 971 971 // If this is accessing arguments then it's potentially accessing locals. 972 if (node-> child1()->shouldSpeculateArguments())972 if (node->arrayMode().type() == Array::Arguments) 973 973 result.mayBeAccessed = true; 974 974 break; … … 1003 1003 if (!edge) 1004 1004 continue; 1005 if (edge.useKind() != UntypedUse) 1006 continue; // Keep the type check. 1005 1007 if (edge->flags() & NodeRelevantToOSR) 1006 1008 continue; … … 1015 1017 } 1016 1018 1017 enum PredictionHandlingMode { RequireSamePrediction, AllowPredictionMismatch }; 1018 bool setReplacement(Node* replacement, PredictionHandlingMode predictionHandlingMode = RequireSamePrediction) 1019 bool setReplacement(Node* replacement) 1019 1020 { 1020 1021 if (!replacement) 1021 return false;1022 1023 // Be safe. Don't try to perform replacements if the predictions don't1024 // agree.1025 if (predictionHandlingMode == RequireSamePrediction1026 && m_currentNode->prediction() != replacement->prediction())1027 1022 return false; 1028 1023 … … 1231 1226 // This is strange, but necessary. Some phases will convert nodes to constants, 1232 1227 // which may result in duplicated constants. We use CSE to clean this up. 1233 setReplacement(constantCSE(node) , AllowPredictionMismatch);1228 setReplacement(constantCSE(node)); 1234 1229 break; 1235 1230 -
trunk/Source/JavaScriptCore/dfg/DFGCommon.h
r142544 r143654 84 84 }; 85 85 86 enum UseKind {87 UntypedUse,88 DoubleUse,89 LastUseKind // Must always be the last entry in the enum, as it is used to denote the number of enum elements.90 };91 92 86 // Use RefChildren if the child ref counts haven't already been adjusted using 93 87 // other means and either of the following is true: … … 106 100 DontRefNode 107 101 }; 108 109 inline const char* useKindToString(UseKind useKind)110 {111 switch (useKind) {112 case UntypedUse:113 return "";114 case DoubleUse:115 return "d";116 default:117 RELEASE_ASSERT_NOT_REACHED();118 return 0;119 }120 }121 102 122 103 inline bool isARMv7s() … … 237 218 }; 238 219 220 enum OperandSpeculationMode { AutomaticOperandSpeculation, ManualOperandSpeculation }; 221 239 222 enum SpeculationDirection { ForwardSpeculation, BackwardSpeculation }; 240 223 -
trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
r142377 r143654 104 104 else 105 105 set = node->structureSet(); 106 if (!isCellSpeculation(value.m_type))107 break;108 106 if (value.m_currentKnownStructure.isSubsetOf(set)) { 109 107 ASSERT(node->refCount() == 1); 108 m_state.execute(indexInBlock); // Catch the fact that we may filter on cell. 110 109 node->setOpAndDefaultFlags(Phantom); 111 110 eliminated = true; … … 115 114 if (structureValue.isSubsetOf(set) 116 115 && structureValue.hasSingleton()) { 117 node->convertToStructureTransitionWatchpoint(structureValue.singleton()); 118 changed = true; 116 Structure* structure = structureValue.singleton(); 117 m_state.execute(indexInBlock); // Catch the fact that we may filter on cell. 118 node->convertToStructureTransitionWatchpoint(structure); 119 eliminated = true; 120 break; 119 121 } 120 122 break; … … 150 152 case GetByIdFlush: { 151 153 CodeOrigin codeOrigin = node->codeOrigin; 152 Node* child = node->child1().node(); 154 Edge childEdge = node->child1(); 155 Node* child = childEdge.node(); 153 156 unsigned identifierNumber = node->identifierNumber(); 154 157 155 if ( !isCellSpeculation(child->prediction()))158 if (childEdge.useKind() != CellUse) 156 159 break; 157 160 … … 165 168 globalData(), structure, codeBlock()->identifier(identifierNumber)); 166 169 167 if (!status.isSimple()) 168 break; 170 if (!status.isSimple()) { 171 // FIXME: We could handle prototype cases. 172 // https://bugs.webkit.org/show_bug.cgi?id=110386 173 break; 174 } 169 175 170 176 ASSERT(status.structureSet().size() == 1); … … 182 188 m_insertionSet.insertNode( 183 189 indexInBlock, RefChildren, DontRefNode, SpecNone, 184 StructureTransitionWatchpoint, codeOrigin, OpInfo(structure), child); 185 } 186 187 Node* propertyStorage; 190 StructureTransitionWatchpoint, codeOrigin, OpInfo(structure), childEdge); 191 } else if (m_state.forNode(child).m_type & ~SpecCell) { 192 m_insertionSet.insertNode( 193 indexInBlock, RefChildren, DontRefNode, SpecNone, 194 Phantom, codeOrigin, childEdge); 195 } 196 197 childEdge.setUseKind(KnownCellUse); 198 199 Edge propertyStorage; 188 200 189 201 child->ref(); 190 202 if (isInlineOffset(status.offset())) 191 propertyStorage = child ;203 propertyStorage = childEdge; 192 204 else { 193 propertyStorage = m_insertionSet.insertNode(205 propertyStorage = Edge(m_insertionSet.insertNode( 194 206 indexInBlock, DontRefChildren, RefNode, SpecNone, GetButterfly, codeOrigin, 195 child );207 childEdge)); 196 208 } 197 209 … … 208 220 case PutByIdDirect: { 209 221 CodeOrigin codeOrigin = node->codeOrigin; 210 Node* child = node->child1().node(); 222 Edge childEdge = node->child1(); 223 Node* child = childEdge.node(); 211 224 unsigned identifierNumber = node->identifierNumber(); 225 226 ASSERT(childEdge.useKind() == CellUse); 212 227 213 228 Structure* structure = m_state.forNode(child).bestProvenStructure(); … … 239 254 m_insertionSet.insertNode( 240 255 indexInBlock, RefChildren, DontRefNode, SpecNone, 241 StructureTransitionWatchpoint, codeOrigin, OpInfo(structure), child); 242 } 256 StructureTransitionWatchpoint, codeOrigin, OpInfo(structure), childEdge); 257 } else if (m_state.forNode(child).m_type & ~SpecCell) { 258 m_insertionSet.insertNode( 259 indexInBlock, RefChildren, DontRefNode, SpecNone, 260 Phantom, codeOrigin, childEdge); 261 } 262 263 childEdge.setUseKind(KnownCellUse); 243 264 244 265 StructureTransitionData* transitionData = 0; … … 265 286 } 266 287 267 Node*propertyStorage;288 Edge propertyStorage; 268 289 269 290 if (isInlineOffset(status.offset())) { 270 291 child->ref(); // The child will be used as the property index, so ref it to reflect the double use. 271 propertyStorage = child ;292 propertyStorage = childEdge; 272 293 } else if (status.isSimpleReplace() || structure->outOfLineCapacity() == status.newStructure()->outOfLineCapacity()) { 273 propertyStorage = m_insertionSet.insertNode(274 indexInBlock, RefChildren, RefNode, SpecNone, GetButterfly, codeOrigin, child );294 propertyStorage = Edge(m_insertionSet.insertNode( 295 indexInBlock, RefChildren, RefNode, SpecNone, GetButterfly, codeOrigin, childEdge)); 275 296 } else if (!structure->outOfLineCapacity()) { 276 297 ASSERT(status.newStructure()->outOfLineCapacity()); 277 298 ASSERT(!isInlineOffset(status.offset())); 278 propertyStorage = m_insertionSet.insertNode(299 propertyStorage = Edge(m_insertionSet.insertNode( 279 300 indexInBlock, RefChildren, RefNode, SpecNone, AllocatePropertyStorage, 280 codeOrigin, OpInfo(transitionData), child );301 codeOrigin, OpInfo(transitionData), childEdge)); 281 302 } else { 282 303 ASSERT(structure->outOfLineCapacity()); … … 284 305 ASSERT(!isInlineOffset(status.offset())); 285 306 286 propertyStorage = m_insertionSet.insertNode(307 propertyStorage = Edge(m_insertionSet.insertNode( 287 308 indexInBlock, RefChildren, RefNode, SpecNone, ReallocatePropertyStorage, 288 309 codeOrigin, OpInfo(transitionData), 289 child ,290 m_insertionSet.insertNode(310 childEdge, 311 Edge(m_insertionSet.insertNode( 291 312 indexInBlock, DontRefChildren, DontRefNode, SpecNone, GetButterfly, 292 codeOrigin, child ));313 codeOrigin, childEdge)))); 293 314 } 294 315 … … 296 317 m_insertionSet.insertNode( 297 318 indexInBlock, RefChildren, DontRefNode, SpecNone, PutStructure, codeOrigin, 298 OpInfo(transitionData), child );319 OpInfo(transitionData), childEdge); 299 320 } 300 321 … … 341 362 Node* phantom = m_insertionSet.insertNode( 342 363 indexInBlock, DontRefChildren, DontRefNode, SpecNone, PhantomLocal, 343 codeOrigin, OpInfo(variable), phi);364 codeOrigin, OpInfo(variable), Edge(phi)); 344 365 block->variablesAtHead.operand(variable->local()) = phantom; 345 366 block->variablesAtTail.operand(variable->local()) = phantom; … … 392 413 m_insertionSet.insertNode( 393 414 indexInBlock, RefChildren, DontRefNode, SpecNone, StructureTransitionWatchpoint, 394 codeOrigin, OpInfo(cell->structure()), weakConstant);415 codeOrigin, OpInfo(cell->structure()), Edge(weakConstant, CellUse)); 395 416 return; 396 417 } … … 398 419 m_insertionSet.insertNode( 399 420 indexInBlock, RefChildren, DontRefNode, SpecNone, CheckStructure, codeOrigin, 400 OpInfo(m_graph.addStructureSet(cell->structure())), weakConstant);421 OpInfo(m_graph.addStructureSet(cell->structure())), Edge(weakConstant, CellUse)); 401 422 } 402 423 -
trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp
r142377 r143654 145 145 break; 146 146 147 dfg.resetExitStates();148 performFixup(dfg);149 147 performCPSRethreading(dfg); 150 148 } -
trunk/Source/JavaScriptCore/dfg/DFGEdge.cpp
r141069 r143654 35 35 void Edge::dump(PrintStream& out) const 36 36 { 37 out.print(useKindToString(useKind()), node()); 37 if (useKind() != UntypedUse) 38 out.print(useKind(), ":"); 39 out.print(node()); 38 40 } 39 41 -
trunk/Source/JavaScriptCore/dfg/DFGEdge.h
r141069 r143654 32 32 33 33 #include "DFGCommon.h" 34 #include "DFGUseKind.h" 34 35 35 36 namespace JSC { namespace DFG { … … 63 64 } 64 65 66 UseKind useKindUnchecked() const 67 { 68 unsigned masked = m_encodedWord & (((1 << shift()) - 1)); 69 ASSERT(masked < LastUseKind); 70 UseKind result = static_cast<UseKind>(masked); 71 ASSERT(node() || result == UntypedUse); 72 return result; 73 } 65 74 UseKind useKind() const 66 75 { 67 76 ASSERT(node()); 68 unsigned masked = m_encodedWord & (((1 << shift()) - 1)); 69 ASSERT(masked < LastUseKind); 70 return static_cast<UseKind>(masked); 77 return useKindUnchecked(); 71 78 } 72 79 void setUseKind(UseKind useKind) … … 97 104 friend class AdjacencyList; 98 105 99 static uint32_t shift() { return 2; }106 static uint32_t shift() { return 4; } 100 107 101 108 static uintptr_t makeWord(Node* node, UseKind useKind) -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r143241 r143654 46 46 bool run() 47 47 { 48 ASSERT(m_graph.m_fixpointState == BeforeFixpoint); 49 ASSERT(m_graph.m_form == ThreadedCPS); 50 48 51 for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) 49 52 fixupBlock(m_graph.m_blocks[blockIndex].get()); … … 77 80 78 81 switch (op) { 79 case GetById: { 80 if (m_graph.m_fixpointState > BeforeFixpoint) 81 break; 82 83 if (!isInt32Speculation(node->prediction())) 84 break; 85 if (codeBlock()->identifier(node->identifierNumber()) != globalData().propertyNames->length) 86 break; 87 ArrayProfile* arrayProfile = 88 m_graph.baselineCodeBlockFor(node->codeOrigin)->getArrayProfile( 89 node->codeOrigin.bytecodeIndex); 90 ArrayMode arrayMode = ArrayMode(Array::SelectUsingPredictions); 91 if (arrayProfile) { 92 arrayProfile->computeUpdatedPrediction(m_graph.baselineCodeBlockFor(node->codeOrigin)); 93 arrayMode = ArrayMode::fromObserved(arrayProfile, Array::Read, false); 94 arrayMode = arrayMode.refine( 95 node->child1()->prediction(), node->prediction()); 96 if (arrayMode.supportsLength() && arrayProfile->hasDefiniteStructure()) { 97 m_insertionSet.insertNode( 98 m_indexInBlock, RefChildren, DontRefNode, SpecNone, CheckStructure, 99 node->codeOrigin, OpInfo(m_graph.addStructureSet(arrayProfile->expectedStructure())), 100 node->child1().node()); 82 case SetLocal: { 83 VariableAccessData* variable = node->variableAccessData(); 84 85 if (variable->isCaptured() 86 || m_graph.isCreatedThisArgument(variable->local())) 87 break; 88 89 if (variable->shouldUseDoubleFormat()) { 90 fixDoubleEdge(node->child1(), NumberUse, ForwardSpeculation); 91 break; 92 } 93 94 SpeculatedType predictedType = variable->argumentAwarePrediction(); 95 if (isInt32Speculation(predictedType)) 96 node->child1().setUseKind(Int32Use); 97 else if (isCellSpeculation(predictedType)) 98 node->child1().setUseKind(CellUse); 99 else if (isBooleanSpeculation(predictedType)) 100 node->child1().setUseKind(BooleanUse); 101 break; 102 } 103 104 case BitAnd: 105 case BitOr: 106 case BitXor: 107 case BitRShift: 108 case BitLShift: 109 case BitURShift: { 110 fixIntEdge(node->child1()); 111 fixIntEdge(node->child2()); 112 break; 113 } 114 115 case UInt32ToNumber: { 116 node->child1().setUseKind(KnownInt32Use); 117 break; 118 } 119 120 case DoubleAsInt32: { 121 RELEASE_ASSERT_NOT_REACHED(); 122 break; 123 } 124 125 case ValueToInt32: { 126 if (node->child1()->shouldSpeculateInteger()) { 127 node->child1().setUseKind(Int32Use); 128 break; 129 } 130 131 if (node->child1()->shouldSpeculateNumber()) { 132 node->child1().setUseKind(NumberUse); 133 break; 134 } 135 136 if (node->child1()->shouldSpeculateBoolean()) { 137 node->child1().setUseKind(BooleanUse); 138 break; 139 } 140 141 node->child1().setUseKind(NotCellUse); 142 break; 143 } 144 145 case Int32ToDouble: { 146 RELEASE_ASSERT_NOT_REACHED(); 147 break; 148 } 149 150 case ValueAdd: { 151 if (attemptToMakeIntegerAdd(node)) 152 break; 153 if (Node::shouldSpeculateNumberExpectingDefined(node->child1().node(), node->child2().node())) { 154 fixDoubleEdge(node->child1()); 155 fixDoubleEdge(node->child2()); 156 break; 157 } 158 break; 159 } 160 161 case ArithAdd: 162 case ArithSub: { 163 if (attemptToMakeIntegerAdd(node)) 164 break; 165 fixDoubleEdge(node->child1()); 166 fixDoubleEdge(node->child2()); 167 break; 168 } 169 170 case ArithNegate: { 171 if (m_graph.negateShouldSpeculateInteger(node)) { 172 node->child1().setUseKind(Int32Use); 173 break; 174 } 175 fixDoubleEdge(node->child1()); 176 break; 177 } 178 179 case ArithMul: { 180 if (m_graph.mulShouldSpeculateInteger(node)) { 181 node->child1().setUseKind(Int32Use); 182 node->child2().setUseKind(Int32Use); 183 break; 184 } 185 fixDoubleEdge(node->child1()); 186 fixDoubleEdge(node->child2()); 187 break; 188 } 189 190 case ArithDiv: { 191 if (Node::shouldSpeculateIntegerForArithmetic(node->child1().node(), node->child2().node()) 192 && node->canSpeculateInteger()) { 193 if (isX86() || isARMv7s()) { 194 node->child1().setUseKind(Int32Use); 195 node->child2().setUseKind(Int32Use); 196 break; 101 197 } 102 } else 103 arrayMode = arrayMode.refine(node->child1()->prediction(), node->prediction()); 104 if (!arrayMode.supportsLength()) 105 break; 106 node->setOp(GetArrayLength); 107 ASSERT(node->flags() & NodeMustGenerate); 108 node->clearFlags(NodeMustGenerate | NodeClobbersWorld); 109 m_graph.deref(node); 110 node->setArrayMode(arrayMode); 111 112 Node* storage = checkArray(arrayMode, node->codeOrigin, node->child1().node(), 0, lengthNeedsStorage, node->shouldGenerate()); 113 if (!storage) 114 break; 115 116 node->children.child2() = Edge(storage); 117 break; 118 } 119 case GetIndexedPropertyStorage: { 120 ASSERT(node->arrayMode().canCSEStorage()); 121 break; 122 } 198 injectInt32ToDoubleNode(node->child1()); 199 injectInt32ToDoubleNode(node->child2()); 200 201 // We don't need to do ref'ing on the children because we're stealing them from 202 // the original division. 203 Node* newDivision = m_insertionSet.insertNode( 204 m_indexInBlock, DontRefChildren, RefNode, SpecDouble, *node); 205 206 node->setOp(DoubleAsInt32); 207 node->children.initialize(Edge(newDivision, KnownNumberUse), Edge(), Edge()); 208 break; 209 } 210 fixDoubleEdge(node->child1()); 211 fixDoubleEdge(node->child2()); 212 break; 213 } 214 215 case ArithMin: 216 case ArithMax: 217 case ArithMod: { 218 if (Node::shouldSpeculateIntegerForArithmetic(node->child1().node(), node->child2().node()) 219 && node->canSpeculateInteger()) { 220 node->child1().setUseKind(Int32Use); 221 node->child2().setUseKind(Int32Use); 222 break; 223 } 224 fixDoubleEdge(node->child1()); 225 fixDoubleEdge(node->child2()); 226 break; 227 } 228 229 case ArithAbs: { 230 if (node->child1()->shouldSpeculateIntegerForArithmetic() 231 && node->canSpeculateInteger()) { 232 node->child1().setUseKind(Int32Use); 233 break; 234 } 235 fixDoubleEdge(node->child1()); 236 break; 237 } 238 239 case ArithSqrt: { 240 fixDoubleEdge(node->child1()); 241 break; 242 } 243 244 case LogicalNot: { 245 if (node->child1()->shouldSpeculateBoolean()) 246 node->child1().setUseKind(BooleanUse); 247 else if (node->child1()->shouldSpeculateObjectOrOther()) 248 node->child1().setUseKind(ObjectOrOtherUse); 249 else if (node->child1()->shouldSpeculateInteger()) 250 node->child1().setUseKind(Int32Use); 251 else if (node->child1()->shouldSpeculateNumber()) 252 fixDoubleEdge(node->child1()); 253 break; 254 } 255 256 case TypeOf: { 257 if (node->child1()->shouldSpeculateString()) 258 node->child1().setUseKind(StringUse); 259 else if (node->child1()->shouldSpeculateCell()) 260 node->child1().setUseKind(CellUse); 261 break; 262 } 263 264 case CompareEq: 265 case CompareEqConstant: 266 case CompareLess: 267 case CompareLessEq: 268 case CompareGreater: 269 case CompareGreaterEq: { 270 if (node->op() == CompareEqConstant) 271 break; 272 if (Node::shouldSpeculateInteger(node->child1().node(), node->child2().node())) { 273 node->child1().setUseKind(Int32Use); 274 node->child2().setUseKind(Int32Use); 275 break; 276 } 277 if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) { 278 fixDoubleEdge(node->child1()); 279 fixDoubleEdge(node->child2()); 280 break; 281 } 282 if (node->op() != CompareEq) 283 break; 284 if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString()) 285 break; 286 if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) { 287 node->child1().setUseKind(ObjectUse); 288 node->child2().setUseKind(ObjectUse); 289 break; 290 } 291 if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObjectOrOther()) { 292 node->child1().setUseKind(ObjectUse); 293 node->child2().setUseKind(ObjectOrOtherUse); 294 break; 295 } 296 if (node->child1()->shouldSpeculateObjectOrOther() && node->child2()->shouldSpeculateObject()) { 297 node->child1().setUseKind(ObjectOrOtherUse); 298 node->child2().setUseKind(ObjectUse); 299 break; 300 } 301 break; 302 } 303 304 case CompareStrictEq: 305 case CompareStrictEqConstant: { 306 if (node->op() == CompareStrictEqConstant) 307 break; 308 if (Node::shouldSpeculateInteger(node->child1().node(), node->child2().node())) { 309 node->child1().setUseKind(Int32Use); 310 node->child2().setUseKind(Int32Use); 311 break; 312 } 313 if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) { 314 fixDoubleEdge(node->child1()); 315 fixDoubleEdge(node->child2()); 316 break; 317 } 318 if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString()) 319 break; 320 if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) { 321 node->child1().setUseKind(ObjectUse); 322 node->child2().setUseKind(ObjectUse); 323 break; 324 } 325 break; 326 } 327 328 case StringCharAt: 329 case StringCharCodeAt: { 330 // Currently we have no good way of refining these. 331 ASSERT(node->arrayMode() == ArrayMode(Array::String)); 332 blessArrayOperation(node->child1(), node->child2(), node->child3()); 333 node->child1().setUseKind(KnownCellUse); 334 node->child2().setUseKind(Int32Use); 335 break; 336 } 337 123 338 case GetByVal: { 124 339 node->setArrayMode( … … 128 343 SpecNone, node->flags())); 129 344 130 blessArrayOperation(node->child1(), node->child2(), 2);345 blessArrayOperation(node->child1(), node->child2(), node->child3()); 131 346 132 347 ArrayMode arrayMode = node->arrayMode(); … … 139 354 node->setArrayMode(arrayMode.withSpeculation(Array::SaneChain)); 140 355 141 break; 142 } 143 case StringCharAt: 144 case StringCharCodeAt: { 145 // Currently we have no good way of refining these. 146 ASSERT(node->arrayMode() == ArrayMode(Array::String)); 147 blessArrayOperation(node->child1(), node->child2(), 2); 356 switch (node->arrayMode().type()) { 357 case Array::SelectUsingPredictions: 358 case Array::Unprofiled: 359 case Array::Undecided: 360 RELEASE_ASSERT_NOT_REACHED(); 361 break; 362 case Array::Generic: 363 #if USE(JSVALUE32_64) 364 node->child1().setUseKind(CellUse); // Speculating cell due to register pressure on 32-bit. 365 #endif 366 break; 367 case Array::ForceExit: 368 break; 369 default: 370 node->child1().setUseKind(KnownCellUse); 371 node->child2().setUseKind(Int32Use); 372 break; 373 } 374 375 break; 376 } 377 378 case PutByVal: 379 case PutByValAlias: { 380 Edge& child1 = m_graph.varArgChild(node, 0); 381 Edge& child2 = m_graph.varArgChild(node, 1); 382 Edge& child3 = m_graph.varArgChild(node, 2); 383 384 node->setArrayMode( 385 node->arrayMode().refine( 386 child1->prediction(), 387 child2->prediction(), 388 child3->prediction())); 389 390 blessArrayOperation(child1, child2, m_graph.varArgChild(node, 3)); 391 392 switch (node->arrayMode().modeForPut().type()) { 393 case Array::SelectUsingPredictions: 394 case Array::Unprofiled: 395 case Array::Undecided: 396 RELEASE_ASSERT_NOT_REACHED(); 397 break; 398 case Array::ForceExit: 399 case Array::Generic: 400 #if USE(JSVALUE32_64) 401 // Due to register pressure on 32-bit, we speculate cell and 402 // ignore the base-is-not-cell case entirely by letting the 403 // baseline JIT handle it. 404 child1.setUseKind(CellUse); 405 #endif 406 break; 407 case Array::Int32: 408 child1.setUseKind(KnownCellUse); 409 child2.setUseKind(Int32Use); 410 child3.setUseKind(Int32Use); 411 break; 412 case Array::Double: 413 child1.setUseKind(KnownCellUse); 414 child2.setUseKind(Int32Use); 415 fixDoubleEdge(child3, RealNumberUse); 416 break; 417 case Array::Int8Array: 418 case Array::Int16Array: 419 case Array::Int32Array: 420 case Array::Uint8Array: 421 case Array::Uint8ClampedArray: 422 case Array::Uint16Array: 423 case Array::Uint32Array: 424 child1.setUseKind(KnownCellUse); 425 child2.setUseKind(Int32Use); 426 if (child3->shouldSpeculateInteger()) 427 child3.setUseKind(Int32Use); 428 else 429 fixDoubleEdge(child3); 430 break; 431 case Array::Float32Array: 432 case Array::Float64Array: 433 child1.setUseKind(KnownCellUse); 434 child2.setUseKind(Int32Use); 435 fixDoubleEdge(child3); 436 break; 437 default: 438 child1.setUseKind(KnownCellUse); 439 child2.setUseKind(Int32Use); 440 break; 441 } 148 442 break; 149 443 } … … 164 458 SpecInt32, 165 459 node->child2()->prediction())); 166 blessArrayOperation(node->child1(), Edge(), 2); 460 blessArrayOperation(node->child1(), Edge(), node->child3()); 461 node->child1().setUseKind(KnownCellUse); 167 462 168 463 switch (node->arrayMode().type()) { 464 case Array::Int32: 465 node->child2().setUseKind(Int32Use); 466 break; 169 467 case Array::Double: 170 fixDoubleEdge( 1);468 fixDoubleEdge(node->child2()); 171 469 break; 172 470 default: … … 177 475 178 476 case ArrayPop: { 179 blessArrayOperation(node->child1(), Edge(), 1); 180 break; 181 } 182 183 case BitAnd: 184 case BitOr: 185 case BitXor: 186 case BitRShift: 187 case BitLShift: 188 case BitURShift: { 189 fixIntEdge(node->children.child1()); 190 fixIntEdge(node->children.child2()); 191 break; 192 } 193 194 case CompareEq: 195 case CompareLess: 196 case CompareLessEq: 197 case CompareGreater: 198 case CompareGreaterEq: 199 case CompareStrictEq: { 200 if (Node::shouldSpeculateInteger(node->child1().node(), node->child2().node())) 201 break; 202 if (!Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) 203 break; 204 fixDoubleEdge(0); 205 fixDoubleEdge(1); 206 break; 207 } 208 209 case LogicalNot: { 210 if (node->child1()->shouldSpeculateInteger()) 211 break; 212 if (!node->child1()->shouldSpeculateNumber()) 213 break; 214 fixDoubleEdge(0); 477 blessArrayOperation(node->child1(), Edge(), node->child2()); 478 node->child1().setUseKind(KnownCellUse); 479 break; 480 } 481 482 case RegExpExec: 483 case RegExpTest: { 484 node->child1().setUseKind(CellUse); 485 node->child2().setUseKind(CellUse); 215 486 break; 216 487 } 217 488 218 489 case Branch: { 219 if (!node->child1()->shouldSpeculateInteger() 220 && node->child1()->shouldSpeculateNumber()) 221 fixDoubleEdge(0); 490 if (node->child1()->shouldSpeculateBoolean()) 491 node->child1().setUseKind(BooleanUse); 492 else if (node->child1()->shouldSpeculateObjectOrOther()) 493 node->child1().setUseKind(ObjectOrOtherUse); 494 else if (node->child1()->shouldSpeculateInteger()) 495 node->child1().setUseKind(Int32Use); 496 else if (node->child1()->shouldSpeculateNumber()) 497 fixDoubleEdge(node->child1()); 222 498 223 499 Node* logicalNot = node->child1().node(); … … 262 538 } 263 539 264 case SetLocal: { 265 if (node->variableAccessData()->isCaptured()) 266 break; 267 if (!node->variableAccessData()->shouldUseDoubleFormat()) 268 break; 269 fixDoubleEdge(0, ForwardSpeculation); 270 break; 271 } 272 273 case ArithAdd: 274 case ValueAdd: { 275 if (m_graph.addShouldSpeculateInteger(node)) 276 break; 277 if (!Node::shouldSpeculateNumberExpectingDefined(node->child1().node(), node->child2().node())) 278 break; 279 fixDoubleEdge(0); 280 fixDoubleEdge(1); 281 break; 282 } 283 284 case ArithSub: { 285 if (m_graph.addShouldSpeculateInteger(node) 286 && node->canSpeculateInteger()) 287 break; 288 fixDoubleEdge(0); 289 fixDoubleEdge(1); 290 break; 291 } 292 293 case ArithNegate: { 294 if (m_graph.negateShouldSpeculateInteger(node)) 295 break; 296 fixDoubleEdge(0); 297 break; 298 } 299 300 case ArithMin: 301 case ArithMax: 302 case ArithMod: { 303 if (Node::shouldSpeculateIntegerForArithmetic(node->child1().node(), node->child2().node()) 304 && node->canSpeculateInteger()) 305 break; 306 fixDoubleEdge(0); 307 fixDoubleEdge(1); 308 break; 309 } 310 311 case ArithMul: { 312 if (m_graph.mulShouldSpeculateInteger(node)) 313 break; 314 fixDoubleEdge(0); 315 fixDoubleEdge(1); 316 break; 317 } 318 319 case ArithDiv: { 320 if (Node::shouldSpeculateIntegerForArithmetic(node->child1().node(), node->child2().node()) 321 && node->canSpeculateInteger()) { 322 if (isX86() || isARMv7s()) 323 break; 324 injectInt32ToDoubleNode(0); 325 injectInt32ToDoubleNode(1); 326 327 // We don't need to do ref'ing on the children because we're stealing them from 328 // the original division. 329 Node* newDivision = m_insertionSet.insertNode( 330 m_indexInBlock, DontRefChildren, RefNode, SpecDouble, *node); 331 332 node->setOp(DoubleAsInt32); 333 node->children.initialize(Edge(newDivision, DoubleUse), Edge(), Edge()); 334 break; 335 } 336 fixDoubleEdge(0); 337 fixDoubleEdge(1); 338 break; 339 } 340 341 case ArithAbs: { 342 if (node->child1()->shouldSpeculateIntegerForArithmetic() 343 && node->canSpeculateInteger()) 344 break; 345 fixDoubleEdge(0); 346 break; 347 } 348 349 case ArithSqrt: { 350 fixDoubleEdge(0); 351 break; 352 } 353 354 case PutByVal: 355 case PutByValAlias: { 356 Edge child1 = m_graph.varArgChild(node, 0); 357 Edge child2 = m_graph.varArgChild(node, 1); 358 Edge child3 = m_graph.varArgChild(node, 2); 359 360 node->setArrayMode( 361 node->arrayMode().refine( 362 child1->prediction(), 363 child2->prediction(), 364 child3->prediction())); 365 366 blessArrayOperation(child1, child2, 3); 367 368 switch (node->arrayMode().modeForPut().type()) { 369 case Array::Double: 370 fixDoubleEdge(2); 371 break; 372 case Array::Int8Array: 373 case Array::Int16Array: 374 case Array::Int32Array: 375 case Array::Uint8Array: 376 case Array::Uint8ClampedArray: 377 case Array::Uint16Array: 378 case Array::Uint32Array: 379 if (!child3->shouldSpeculateInteger()) 380 fixDoubleEdge(2); 381 break; 382 case Array::Float32Array: 383 case Array::Float64Array: 384 fixDoubleEdge(2); 385 break; 386 default: 387 break; 388 } 540 case ToPrimitive: { 541 if (node->child1()->shouldSpeculateInteger()) 542 node->child1().setUseKind(Int32Use); 543 // FIXME: Add string speculation here. 544 // https://bugs.webkit.org/show_bug.cgi?id=110175 389 545 break; 390 546 } … … 396 552 node->indexingType(), m_graph.varArgChild(node, i)->prediction())); 397 553 } 398 if (node->indexingType() == ArrayWithDouble) { 399 for (unsigned i = m_graph.varArgNumChildren(node); i--;) 400 fixDoubleEdge(i); 401 } 402 break; 403 } 404 554 switch (node->indexingType()) { 555 case ALL_BLANK_INDEXING_TYPES: 556 CRASH(); 557 break; 558 case ALL_UNDECIDED_INDEXING_TYPES: 559 if (node->numChildren()) { 560 // This will only happen if the children have no type predictions. We 561 // would have already exited by now, but insert a forced exit just to 562 // be safe. 563 m_insertionSet.insertNode( 564 m_indexInBlock, DontRefChildren, DontRefNode, SpecNone, ForceOSRExit, 565 node->codeOrigin); 566 } 567 break; 568 case ALL_INT32_INDEXING_TYPES: 569 for (unsigned operandIndex = 0; operandIndex < node->numChildren(); ++operandIndex) 570 m_graph.m_varArgChildren[node->firstChild() + operandIndex].setUseKind(Int32Use); 571 break; 572 case ALL_DOUBLE_INDEXING_TYPES: 573 for (unsigned operandIndex = 0; operandIndex < node->numChildren(); ++operandIndex) 574 m_graph.m_varArgChildren[node->firstChild() + operandIndex].setUseKind(RealNumberUse); 575 break; 576 case ALL_CONTIGUOUS_INDEXING_TYPES: 577 case ALL_ARRAY_STORAGE_INDEXING_TYPES: 578 break; 579 default: 580 CRASH(); 581 break; 582 } 583 break; 584 } 585 586 case NewArrayWithSize: { 587 node->child1().setUseKind(Int32Use); 588 break; 589 } 590 591 case ConvertThis: { 592 // FIXME: Use Phantom(type check) and Identity instead. 593 // https://bugs.webkit.org/show_bug.cgi?id=110395 594 if (isOtherSpeculation(node->child1()->prediction())) 595 node->child1().setUseKind(OtherUse); 596 else if (isObjectSpeculation(node->child1()->prediction())) 597 node->child1().setUseKind(ObjectUse); 598 break; 599 } 600 601 case CreateThis: { 602 node->child1().setUseKind(CellUse); 603 break; 604 } 605 606 case GetMyArgumentByVal: 607 case GetMyArgumentByValSafe: { 608 node->child1().setUseKind(Int32Use); 609 break; 610 } 611 612 case GetScopeRegisters: 613 case PutScopedVar: 614 case SkipTopScope: 615 case SkipScope: 616 case SetCallee: 617 case SetMyScope: 618 case PutStructure: 619 case AllocatePropertyStorage: 620 case ReallocatePropertyStorage: 621 case GetScope: 622 case GetButterfly: { 623 node->child1().setUseKind(KnownCellUse); 624 break; 625 } 626 627 case GetById: { 628 if (!node->child1()->shouldSpeculateCell()) 629 break; 630 node->child1().setUseKind(CellUse); 631 if (!isInt32Speculation(node->prediction())) 632 break; 633 if (codeBlock()->identifier(node->identifierNumber()) != globalData().propertyNames->length) 634 break; 635 ArrayProfile* arrayProfile = 636 m_graph.baselineCodeBlockFor(node->codeOrigin)->getArrayProfile( 637 node->codeOrigin.bytecodeIndex); 638 ArrayMode arrayMode = ArrayMode(Array::SelectUsingPredictions); 639 if (arrayProfile) { 640 arrayProfile->computeUpdatedPrediction(m_graph.baselineCodeBlockFor(node->codeOrigin)); 641 arrayMode = ArrayMode::fromObserved(arrayProfile, Array::Read, false); 642 arrayMode = arrayMode.refine( 643 node->child1()->prediction(), node->prediction()); 644 if (arrayMode.supportsLength() && arrayProfile->hasDefiniteStructure()) { 645 m_insertionSet.insertNode( 646 m_indexInBlock, RefChildren, DontRefNode, SpecNone, CheckStructure, 647 node->codeOrigin, OpInfo(m_graph.addStructureSet(arrayProfile->expectedStructure())), 648 node->child1()); 649 } 650 } else 651 arrayMode = arrayMode.refine(node->child1()->prediction(), node->prediction()); 652 if (!arrayMode.supportsLength()) 653 break; 654 node->setOp(GetArrayLength); 655 ASSERT(node->flags() & NodeMustGenerate); 656 node->clearFlags(NodeMustGenerate | NodeClobbersWorld); 657 node->child1().setUseKind(KnownCellUse); 658 m_graph.deref(node); 659 node->setArrayMode(arrayMode); 660 661 Node* storage = checkArray(arrayMode, node->codeOrigin, node->child1().node(), 0, lengthNeedsStorage, node->shouldGenerate()); 662 if (!storage) 663 break; 664 665 node->child2() = Edge(storage); 666 break; 667 } 668 669 case GetByIdFlush: { 670 if (node->child1()->shouldSpeculateCell()) 671 node->child1().setUseKind(CellUse); 672 break; 673 } 674 675 case CheckExecutable: 676 case CheckStructure: 677 case ForwardCheckStructure: 678 case StructureTransitionWatchpoint: 679 case ForwardStructureTransitionWatchpoint: 680 case CheckFunction: 681 case PutById: 682 case PutByIdDirect: 683 case CheckHasInstance: { 684 node->child1().setUseKind(CellUse); 685 break; 686 } 687 688 case CheckArray: { 689 switch (node->arrayMode().type()) { 690 case Array::String: 691 node->child1().setUseKind(StringUse); 692 break; 693 default: 694 node->child1().setUseKind(CellUse); 695 break; 696 } 697 break; 698 } 699 700 case Arrayify: 701 case ArrayifyToStructure: { 702 node->child1().setUseKind(CellUse); 703 if (node->child2()) 704 node->child2().setUseKind(Int32Use); 705 break; 706 } 707 708 case GetByOffset: { 709 if (!node->child1()->hasStorageResult()) 710 node->child1().setUseKind(KnownCellUse); 711 break; 712 } 713 714 case PutByOffset: { 715 if (!node->child1()->hasStorageResult()) 716 node->child1().setUseKind(KnownCellUse); 717 node->child2().setUseKind(KnownCellUse); 718 break; 719 } 720 721 case InstanceOf: { 722 // FIXME: This appears broken: CheckHasInstance already does an unconditional cell 723 // check. https://bugs.webkit.org/show_bug.cgi?id=107479 724 if (!(node->child1()->prediction() & ~SpecCell)) 725 node->child1().setUseKind(CellUse); 726 node->child2().setUseKind(CellUse); 727 break; 728 } 729 730 case GetArrayLength: 731 case Identity: 732 case Nop: 733 case Phi: 734 case ForwardInt32ToDouble: 735 case PhantomPutStructure: 736 case GetIndexedPropertyStorage: 737 case LastNodeType: 738 RELEASE_ASSERT_NOT_REACHED(); 739 break; 740 741 #if !ASSERT_DISABLED 742 // Have these no-op cases here to ensure that nobody forgets to add handlers for new opcodes. 743 case SetArgument: 744 case Phantom: 745 case JSConstant: 746 case WeakJSConstant: 747 case GetLocal: 748 case GetCallee: 749 case Flush: 750 case PhantomLocal: 751 case GetLocalUnlinked: 752 case InlineStart: 753 case GetMyScope: 754 case GetScopedVar: 755 case GetGlobalVar: 756 case PutGlobalVar: 757 case GlobalVarWatchpoint: 758 case PutGlobalVarCheck: 759 case AllocationProfileWatchpoint: 760 case Call: 761 case Construct: 762 case NewObject: 763 case NewArrayBuffer: 764 case NewRegexp: 765 case Resolve: 766 case ResolveBase: 767 case ResolveBaseStrictPut: 768 case ResolveGlobal: 769 case Breakpoint: 770 case IsUndefined: 771 case IsBoolean: 772 case IsNumber: 773 case IsString: 774 case IsObject: 775 case IsFunction: 776 case StrCat: 777 case CreateActivation: 778 case TearOffActivation: 779 case CreateArguments: 780 case PhantomArguments: 781 case TearOffArguments: 782 case GetMyArgumentsLength: 783 case GetMyArgumentsLengthSafe: 784 case CheckArgumentsNotCreated: 785 case NewFunction: 786 case NewFunctionNoCheck: 787 case NewFunctionExpression: 788 case Jump: 789 case Return: 790 case Throw: 791 case ThrowReferenceError: 792 case GarbageValue: 793 case CountExecution: 794 case ForceOSRExit: 795 break; 796 #else 405 797 default: 406 798 break; 799 #endif 407 800 } 408 801 … … 421 814 422 815 Structure* structure = arrayMode.originalArrayStructure(m_graph, codeOrigin); 816 817 Edge indexEdge = index ? Edge(index, Int32Use) : Edge(); 423 818 424 819 if (arrayMode.doesConversion()) { … … 436 831 m_insertionSet.insertNode( 437 832 m_indexInBlock, RefChildren, DontRefNode, SpecNone, ArrayifyToStructure, codeOrigin, 438 OpInfo(structure), OpInfo(arrayMode.asWord()), array, index);833 OpInfo(structure), OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge); 439 834 } else { 440 835 m_insertionSet.insertNode( 441 836 m_indexInBlock, RefChildren, DontRefNode, SpecNone, Arrayify, codeOrigin, 442 OpInfo(arrayMode.asWord()), array, index);837 OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge); 443 838 } 444 839 } else { … … 446 841 m_insertionSet.insertNode( 447 842 m_indexInBlock, RefChildren, DontRefNode, SpecNone, CheckStructure, codeOrigin, 448 OpInfo(m_graph.addStructureSet(structure)), array);843 OpInfo(m_graph.addStructureSet(structure)), Edge(array, CellUse)); 449 844 } else { 450 845 m_insertionSet.insertNode( 451 846 m_indexInBlock, RefChildren, DontRefNode, SpecNone, CheckArray, codeOrigin, 452 OpInfo(arrayMode.asWord()), array);847 OpInfo(arrayMode.asWord()), Edge(array, CellUse)); 453 848 } 454 849 } … … 462 857 shouldGenerate ? RefChildren : DontRefChildren, 463 858 shouldGenerate ? RefNode : DontRefNode, 464 SpecNone, GetButterfly, codeOrigin, array);859 SpecNone, GetButterfly, codeOrigin, Edge(array, KnownCellUse)); 465 860 } 466 861 … … 469 864 shouldGenerate ? RefChildren : DontRefChildren, 470 865 shouldGenerate ? RefNode : DontRefNode, 471 SpecNone, GetIndexedPropertyStorage, codeOrigin, OpInfo(arrayMode.asWord()), array);866 SpecNone, GetIndexedPropertyStorage, codeOrigin, OpInfo(arrayMode.asWord()), Edge(array, KnownCellUse)); 472 867 } 473 868 474 void blessArrayOperation(Edge base, Edge index, unsigned storageChildIdx) 475 { 476 if (m_graph.m_fixpointState > BeforeFixpoint) 477 return; 478 869 void blessArrayOperation(Edge base, Edge index, Edge& storageChild) 870 { 479 871 Node* node = m_currentNode; 480 872 … … 500 892 return; 501 893 502 m_graph.child(node, storageChildIdx)= Edge(storage);894 storageChild = Edge(storage); 503 895 return; 504 896 } } … … 508 900 { 509 901 Node* node = edge.node(); 510 if (node->op() != ValueToInt32) 902 if (node->op() != ValueToInt32) { 903 edge.setUseKind(KnownInt32Use); 511 904 return; 512 513 if (!node->child1()->shouldSpeculateInteger()) 514 return; 905 } 515 906 516 907 Edge oldEdge = edge; 517 908 Edge newEdge = node->child1(); 518 909 910 if (newEdge.useKind() != Int32Use) { 911 edge.setUseKind(KnownInt32Use); 912 return; 913 } 914 915 ASSERT(newEdge->shouldSpeculateInteger()); 916 519 917 m_graph.ref(newEdge); 520 918 m_graph.deref(oldEdge); … … 523 921 } 524 922 525 void fixDoubleEdge(unsigned childIndex, SpeculationDirection direction = BackwardSpeculation) 526 { 527 Node* source = m_currentNode; 528 Edge& edge = m_graph.child(source, childIndex); 529 923 void fixDoubleEdge(Edge& edge, UseKind useKind = NumberUse, SpeculationDirection direction = BackwardSpeculation) 924 { 530 925 if (edge->prediction() & SpecDouble) { 531 edge.setUseKind( DoubleUse);926 edge.setUseKind(useKind); 532 927 return; 533 928 } 534 929 535 injectInt32ToDoubleNode( childIndex, direction);536 } 537 538 void injectInt32ToDoubleNode( unsigned childIndex, SpeculationDirection direction = BackwardSpeculation)930 injectInt32ToDoubleNode(edge, useKind, direction); 931 } 932 933 void injectInt32ToDoubleNode(Edge& edge, UseKind useKind = NumberUse, SpeculationDirection direction = BackwardSpeculation) 539 934 { 540 935 Node* result = m_insertionSet.insertNode( 541 936 m_indexInBlock, DontRefChildren, RefNode, SpecDouble, 542 937 direction == BackwardSpeculation ? Int32ToDouble : ForwardInt32ToDouble, 543 m_currentNode->codeOrigin, m_graph.child(m_currentNode, childIndex).node());938 m_currentNode->codeOrigin, Edge(edge.node(), NumberUse)); 544 939 545 940 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) 546 941 dataLogF( 547 942 "(replacing @%u->@%u with @%u->@%u) ", 548 m_currentNode->index(), m_graph.child(m_currentNode, childIndex)->index(), m_currentNode->index(), result->index());943 m_currentNode->index(), edge->index(), m_currentNode->index(), result->index()); 549 944 #endif 550 945 551 m_graph.child(m_currentNode, childIndex) = Edge(result, DoubleUse); 946 edge = Edge(result, useKind); 947 } 948 949 void truncateConstantToInt32(Edge& edge) 950 { 951 Node* oldNode = edge.node(); 952 953 ASSERT(oldNode->hasConstant()); 954 JSValue value = m_graph.valueOfJSConstant(oldNode); 955 if (value.isInt32()) 956 return; 957 958 value = jsNumber(JSC::toInt32(value.asNumber())); 959 ASSERT(value.isInt32()); 960 edge.setNode(m_insertionSet.insertNode( 961 m_indexInBlock, DontRefChildren, RefNode, SpecInt32, JSConstant, 962 m_currentNode->codeOrigin, OpInfo(codeBlock()->addOrFindConstant(value)))); 963 m_graph.deref(oldNode); 964 } 965 966 void truncateConstantsIfNecessary(Node* node, AddSpeculationMode mode) 967 { 968 if (mode != SpeculateIntegerAndTruncateConstants) 969 return; 970 971 ASSERT(node->child1()->hasConstant() || node->child2()->hasConstant()); 972 if (node->child1()->hasConstant()) 973 truncateConstantToInt32(node->child1()); 974 else 975 truncateConstantToInt32(node->child2()); 976 } 977 978 bool attemptToMakeIntegerAdd(Node* node) 979 { 980 AddSpeculationMode mode = m_graph.addSpeculationMode(node); 981 if (mode == DontSpeculateInteger) 982 return false; 983 984 truncateConstantsIfNecessary(node, mode); 985 node->child1().setUseKind(Int32Use); 986 node->child2().setUseKind(Int32Use); 987 return true; 552 988 } 553 989 -
trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp
r142377 r143654 347 347 } 348 348 349 // FIXME: Convert this to be iterative, not recursive.350 #define DO_TO_CHILDREN(node, thingToDo) do { \351 Node* _node = (node); \352 if (_node->flags() & NodeHasVarArgs) { \353 for (unsigned _childIdx = _node->firstChild(); \354 _childIdx < _node->firstChild() + _node->numChildren(); \355 _childIdx++) { \356 if (!!m_varArgChildren[_childIdx]) \357 thingToDo(m_varArgChildren[_childIdx]); \358 } \359 } else { \360 if (!_node->child1()) { \361 ASSERT( \362 !_node->child2() \363 && !_node->child3()); \364 break; \365 } \366 thingToDo(_node->child1()); \367 \368 if (!_node->child2()) { \369 ASSERT(!_node->child3()); \370 break; \371 } \372 thingToDo(_node->child2()); \373 \374 if (!_node->child3()) \375 break; \376 thingToDo(_node->child3()); \377 } \378 } while (false)379 380 349 void Graph::refChildren(Node* op) 381 350 { 382 D O_TO_CHILDREN(op, ref);351 DFG_NODE_DO_TO_CHILDREN(*this, op, ref); 383 352 } 384 353 385 354 void Graph::derefChildren(Node* op) 386 355 { 387 D O_TO_CHILDREN(op, deref);356 DFG_NODE_DO_TO_CHILDREN(*this, op, deref); 388 357 } 389 358 -
trunk/Source/JavaScriptCore/dfg/DFGGraph.h
r142769 r143654 78 78 enum AddSpeculationMode { 79 79 DontSpeculateInteger, 80 SpeculateInteger ButAlwaysWatchOverflow,80 SpeculateIntegerAndTruncateConstants, 81 81 SpeculateInteger 82 82 }; … … 101 101 return node; 102 102 } 103 Edge ref(Edge nodeUse) 104 { 105 ref(nodeUse.node()); 106 return nodeUse; 103 Edge ref(Edge edge) 104 { 105 ref(edge.node()); 106 return edge; 107 } 108 Edge ref(Node*, Edge edge) 109 { 110 return ref(edge); 107 111 } 108 112 … … 116 120 derefChildren(node); 117 121 } 118 void deref(Edge nodeUse) 119 { 120 deref(nodeUse.node()); 122 void deref(Edge edge) 123 { 124 deref(edge.node()); 125 } 126 void deref(Node*, Edge edge) 127 { 128 deref(edge); 121 129 } 122 130 … … 175 183 performSubstitutionForEdge(m_varArgChildren[childIdx], shouldGenerate); 176 184 } else { 177 performSubstitutionForEdge(node->child ren.child1(), shouldGenerate);178 performSubstitutionForEdge(node->child ren.child2(), shouldGenerate);179 performSubstitutionForEdge(node->child ren.child3(), shouldGenerate);185 performSubstitutionForEdge(node->child1(), shouldGenerate); 186 performSubstitutionForEdge(node->child2(), shouldGenerate); 187 performSubstitutionForEdge(node->child3(), shouldGenerate); 180 188 } 181 189 } … … 531 539 bool isPredictedNumerical(Node* node) 532 540 { 533 SpeculatedType left = node->child1()->prediction(); 534 SpeculatedType right = node->child2()->prediction(); 535 return isNumberSpeculation(left) && isNumberSpeculation(right); 541 return isNumerical(node->child1().useKind()) && isNumerical(node->child2().useKind()); 536 542 } 537 543 … … 782 788 return DontSpeculateInteger; 783 789 784 return nodeCanTruncateInteger(add->arithNodeFlags()) ? SpeculateInteger ButAlwaysWatchOverflow: DontSpeculateInteger;790 return nodeCanTruncateInteger(add->arithNodeFlags()) ? SpeculateIntegerAndTruncateConstants : DontSpeculateInteger; 785 791 } 786 792 … … 831 837 } 832 838 839 #define DFG_NODE_DO_TO_CHILDREN(graph, node, thingToDo) do { \ 840 Node* _node = (node); \ 841 if (_node->flags() & NodeHasVarArgs) { \ 842 for (unsigned _childIdx = _node->firstChild(); \ 843 _childIdx < _node->firstChild() + _node->numChildren(); \ 844 _childIdx++) { \ 845 if (!!(graph).m_varArgChildren[_childIdx]) \ 846 thingToDo(_node, (graph).m_varArgChildren[_childIdx]); \ 847 } \ 848 } else { \ 849 if (!_node->child1()) { \ 850 ASSERT( \ 851 !_node->child2() \ 852 && !_node->child3()); \ 853 break; \ 854 } \ 855 thingToDo(_node, _node->child1()); \ 856 \ 857 if (!_node->child2()) { \ 858 ASSERT(!_node->child3()); \ 859 break; \ 860 } \ 861 thingToDo(_node, _node->child2()); \ 862 \ 863 if (!_node->child3()) \ 864 break; \ 865 thingToDo(_node, _node->child3()); \ 866 } \ 867 } while (false) 868 833 869 } } // namespace JSC::DFG 834 870 -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r142544 r143654 96 96 { 97 97 setOpAndDefaultFlags(op); 98 ASSERT(!!(m_flags & NodeHasVarArgs) == (children.kind() == AdjacencyList::Variable));99 98 } 100 99 101 100 // Construct a node with up to 3 children, no immediate value. 102 Node(NodeType op, CodeOrigin codeOrigin, Node* child1 = 0, Node* child2 = 0, Node* child3 = 0)101 Node(NodeType op, CodeOrigin codeOrigin, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge()) 103 102 : codeOrigin(codeOrigin) 104 103 , children(AdjacencyList::Fixed, child1, child2, child3) … … 112 111 113 112 // Construct a node with up to 3 children and an immediate value. 114 Node(NodeType op, CodeOrigin codeOrigin, OpInfo imm, Node* child1 = 0, Node* child2 = 0, Node* child3 = 0)113 Node(NodeType op, CodeOrigin codeOrigin, OpInfo imm, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge()) 115 114 : codeOrigin(codeOrigin) 116 115 , children(AdjacencyList::Fixed, child1, child2, child3) … … 125 124 126 125 // Construct a node with up to 3 children and two immediate values. 127 Node(NodeType op, CodeOrigin codeOrigin, OpInfo imm1, OpInfo imm2, Node* child1 = 0, Node* child2 = 0, Node* child3 = 0)126 Node(NodeType op, CodeOrigin codeOrigin, OpInfo imm1, OpInfo imm2, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge()) 128 127 : codeOrigin(codeOrigin) 129 128 , children(AdjacencyList::Fixed, child1, child2, child3) … … 295 294 } 296 295 297 void convertToGetByOffset(unsigned storageAccessDataIndex, Node*storage)296 void convertToGetByOffset(unsigned storageAccessDataIndex, Edge storage) 298 297 { 299 298 ASSERT(m_op == GetById || m_op == GetByIdFlush); 300 299 m_opInfo = storageAccessDataIndex; 301 children.setChild1( Edge(storage));300 children.setChild1(storage); 302 301 m_op = GetByOffset; 303 302 m_flags &= ~NodeClobbersWorld; 304 303 } 305 304 306 void convertToPutByOffset(unsigned storageAccessDataIndex, Node*storage)305 void convertToPutByOffset(unsigned storageAccessDataIndex, Edge storage) 307 306 { 308 307 ASSERT(m_op == PutById || m_op == PutByIdDirect); … … 310 309 children.setChild3(children.child2()); 311 310 children.setChild2(children.child1()); 312 children.setChild1( Edge(storage));311 children.setChild1(storage); 313 312 m_op = PutByOffset; 314 313 m_flags &= ~NodeClobbersWorld; … … 950 949 case PhantomArguments: 951 950 return true; 951 case Nop: 952 return false; 952 953 case Phantom: 953 case Nop: 954 return false; 954 return child1().useKindUnchecked() != UntypedUse || child2().useKindUnchecked() != UntypedUse || child3().useKindUnchecked() != UntypedUse; 955 955 default: 956 956 return shouldGenerate(); … … 996 996 } 997 997 998 Edge child1()998 Edge& child1() 999 999 { 1000 1000 ASSERT(!(m_flags & NodeHasVarArgs)); … … 1010 1010 } 1011 1011 1012 Edge child2()1012 Edge& child2() 1013 1013 { 1014 1014 ASSERT(!(m_flags & NodeHasVarArgs)); … … 1016 1016 } 1017 1017 1018 Edge child3()1018 Edge& child3() 1019 1019 { 1020 1020 ASSERT(!(m_flags & NodeHasVarArgs)); … … 1032 1032 ASSERT(m_flags & NodeHasVarArgs); 1033 1033 return children.numChildren(); 1034 } 1035 1036 UseKind binaryUseKind() 1037 { 1038 ASSERT(child1().useKind() == child2().useKind()); 1039 return child1().useKind(); 1040 } 1041 1042 bool isBinaryUseKind(UseKind useKind) 1043 { 1044 return child1().useKind() == useKind && child2().useKind() == useKind; 1034 1045 } 1035 1046 -
trunk/Source/JavaScriptCore/dfg/DFGNodeAllocator.h
r141069 r143654 36 36 namespace JSC { namespace DFG { 37 37 38 typedef Allocator<Node> NodeAllocator; 38 // The second template argument to Allocator is the expected size of Node rounded up to 39 // 16 bytes. This is baked in to give us assertion coverage for when Node increases in 40 // size. We don't want its size to increase for no good reason. The multiple-of-16 41 // property is asserted by DFG::Edge, which expects to never see any of the low 4 bits 42 // of a Node* being non-zero. 43 #if USE(JSVALUE64) 44 typedef Allocator<Node, 112> NodeAllocator; 45 #else 46 typedef Allocator<Node, 80> NodeAllocator; 47 #endif 39 48 40 49 } } // namespace JSC::DFG -
trunk/Source/JavaScriptCore/dfg/DFGNodeFlags.cpp
r140594 r143654 35 35 const char* nodeFlagsAsString(NodeFlags flags) 36 36 { 37 if (! flags)37 if (!(flags ^ NodeDoesNotExit)) 38 38 return "<empty>"; 39 39 -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r143241 r143654 97 97 /* Used to speculate that a double value is actually an integer. */\ 98 98 macro(DoubleAsInt32, NodeResultInt32) \ 99 /* Used to record places where we must check if a value is a number. */\100 macro(CheckNumber, NodeMustGenerate) \101 99 \ 102 100 /* Nodes for arithmetic operations. */\ -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r142695 r143654 806 806 case TearOffActivation: 807 807 case TearOffArguments: 808 case CheckNumber:809 808 case CheckArgumentsNotCreated: 810 809 case GlobalVarWatchpoint: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r143562 r143654 109 109 if (!m_compileOkay) 110 110 return; 111 ASSERT(m_isCheckingArgumentTypes || m_c urrentNode->canExit());111 ASSERT(m_isCheckingArgumentTypes || m_canExit); 112 112 m_jit.appendExitInfo(jumpToFail); 113 113 m_jit.codeBlock()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(node), this, m_stream->size())); … … 116 116 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail) 117 117 { 118 ASSERT(m_isCheckingArgumentTypes || m_c urrentNode->canExit());118 ASSERT(m_isCheckingArgumentTypes || m_canExit); 119 119 speculationCheck(kind, jsValueSource, nodeUse.node(), jumpToFail); 120 120 } … … 124 124 if (!m_compileOkay) 125 125 return OSRExitJumpPlaceholder(); 126 ASSERT(m_isCheckingArgumentTypes || m_c urrentNode->canExit());126 ASSERT(m_isCheckingArgumentTypes || m_canExit); 127 127 unsigned index = m_jit.codeBlock()->numberOfOSRExits(); 128 128 m_jit.appendExitInfo(); … … 133 133 OSRExitJumpPlaceholder SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse) 134 134 { 135 ASSERT(m_isCheckingArgumentTypes || m_c urrentNode->canExit());135 ASSERT(m_isCheckingArgumentTypes || m_canExit); 136 136 return speculationCheck(kind, jsValueSource, nodeUse.node()); 137 137 } … … 141 141 if (!m_compileOkay) 142 142 return; 143 ASSERT(m_isCheckingArgumentTypes || m_c urrentNode->canExit());143 ASSERT(m_isCheckingArgumentTypes || m_canExit); 144 144 m_jit.appendExitInfo(jumpsToFail); 145 145 m_jit.codeBlock()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(node), this, m_stream->size())); … … 148 148 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, const MacroAssembler::JumpList& jumpsToFail) 149 149 { 150 ASSERT(m_isCheckingArgumentTypes || m_c urrentNode->canExit());150 ASSERT(m_isCheckingArgumentTypes || m_canExit); 151 151 speculationCheck(kind, jsValueSource, nodeUse.node(), jumpsToFail); 152 152 } … … 156 156 if (!m_compileOkay) 157 157 return; 158 ASSERT(m_isCheckingArgumentTypes || m_c urrentNode->canExit());158 ASSERT(m_isCheckingArgumentTypes || m_canExit); 159 159 m_jit.codeBlock()->appendSpeculationRecovery(recovery); 160 160 m_jit.appendExitInfo(jumpToFail); … … 164 164 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery) 165 165 { 166 ASSERT(m_isCheckingArgumentTypes || m_c urrentNode->canExit());166 ASSERT(m_isCheckingArgumentTypes || m_canExit); 167 167 speculationCheck(kind, jsValueSource, nodeUse.node(), jumpToFail, recovery); 168 168 } … … 175 175 } 176 176 177 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge edge, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery, SpeculationDirection direction) 178 { 179 speculationCheck(kind, jsValueSource, edge.node(), jumpToFail, recovery, direction); 180 } 181 177 182 JumpReplacementWatchpoint* SpeculativeJIT::speculationWatchpoint(ExitKind kind, JSValueSource jsValueSource, Node* node) 178 183 { 179 184 if (!m_compileOkay) 180 185 return 0; 181 ASSERT(m_isCheckingArgumentTypes || m_c urrentNode->canExit());186 ASSERT(m_isCheckingArgumentTypes || m_canExit); 182 187 m_jit.appendExitInfo(JITCompiler::JumpList()); 183 188 OSRExit& exit = m_jit.codeBlock()->osrExit( … … 281 286 void SpeculativeJIT::forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, MacroAssembler::Jump jumpToFail, const ValueRecovery& valueRecovery) 282 287 { 283 ASSERT(m_isCheckingArgumentTypes || m_c urrentNode->canExit());288 ASSERT(m_isCheckingArgumentTypes || m_canExit); 284 289 speculationCheck(kind, jsValueSource, node, jumpToFail); 285 290 convertLastOSRExitToForward(valueRecovery); … … 288 293 void SpeculativeJIT::forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, const MacroAssembler::JumpList& jumpsToFail, const ValueRecovery& valueRecovery) 289 294 { 290 ASSERT(m_isCheckingArgumentTypes || m_c urrentNode->canExit());295 ASSERT(m_isCheckingArgumentTypes || m_canExit); 291 296 speculationCheck(kind, jsValueSource, node, jumpsToFail); 292 297 convertLastOSRExitToForward(valueRecovery); … … 301 306 } 302 307 308 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge edge, MacroAssembler::Jump jumpToFail, SpeculationDirection direction) 309 { 310 speculationCheck(kind, jsValueSource, edge.node(), jumpToFail, direction); 311 } 312 303 313 void SpeculativeJIT::terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, Node* node) 304 314 { 305 ASSERT(m_isCheckingArgumentTypes || m_c urrentNode->canExit());315 ASSERT(m_isCheckingArgumentTypes || m_canExit); 306 316 #if DFG_ENABLE(DEBUG_VERBOSE) 307 317 dataLogF("SpeculativeJIT was terminated.\n"); … … 315 325 void SpeculativeJIT::terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, Edge nodeUse) 316 326 { 317 ASSERT(m_isCheckingArgumentTypes || m_c urrentNode->canExit());327 ASSERT(m_isCheckingArgumentTypes || m_canExit); 318 328 terminateSpeculativeExecution(kind, jsValueRegs, nodeUse.node()); 319 329 } … … 321 331 void SpeculativeJIT::terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, Node* node, SpeculationDirection direction) 322 332 { 323 ASSERT(m_isCheckingArgumentTypes || m_c urrentNode->canExit());333 ASSERT(m_isCheckingArgumentTypes || m_canExit); 324 334 #if DFG_ENABLE(DEBUG_VERBOSE) 325 335 dataLogF("SpeculativeJIT was terminated.\n"); … … 329 339 speculationCheck(kind, jsValueRegs, node, m_jit.jump(), direction); 330 340 m_compileOkay = false; 341 } 342 343 void SpeculativeJIT::typeCheck(JSValueSource source, Edge edge, SpeculatedType typesPassedThrough, MacroAssembler::Jump jumpToFail) 344 { 345 ASSERT(needsTypeCheck(edge, typesPassedThrough)); 346 m_state.forNode(edge).filter(typesPassedThrough); 347 speculationCheck(BadType, source, edge, jumpToFail); 348 } 349 350 void SpeculativeJIT::forwardTypeCheck(JSValueSource source, Edge edge, SpeculatedType typesPassedThrough, MacroAssembler::Jump jumpToFail, const ValueRecovery& valueRecovery) 351 { 352 typeCheck(source, edge, typesPassedThrough, jumpToFail); 353 convertLastOSRExitToForward(valueRecovery); 354 } 355 356 void SpeculativeJIT::typeCheck(JSValueSource source, Edge edge, SpeculatedType typesPassedThrough, MacroAssembler::Jump jumpToFail, SpeculationDirection direction) 357 { 358 typeCheck(source, edge, typesPassedThrough, jumpToFail); 359 if (direction == ForwardSpeculation) 360 convertLastOSRExitToForward(); 331 361 } 332 362 … … 873 903 } 874 904 875 GPRReg SpeculativeJIT::fillStorage( Node* node)876 { 877 VirtualRegister virtualRegister = node->virtualRegister();905 GPRReg SpeculativeJIT::fillStorage(Edge edge) 906 { 907 VirtualRegister virtualRegister = edge->virtualRegister(); 878 908 GenerationInfo& info = m_generationInfo[virtualRegister]; 879 909 … … 889 919 890 920 // Must be a cell; fill it as a cell and then return the pointer. 891 return fillSpeculateCell( node, BackwardSpeculation);921 return fillSpeculateCell(edge, BackwardSpeculation); 892 922 } 893 923 … … 899 929 900 930 default: 901 return fillSpeculateCell( node, BackwardSpeculation);931 return fillSpeculateCell(edge, BackwardSpeculation); 902 932 } 903 933 } … … 1510 1540 ASSERT(node->adjustedRefCount() == 1); 1511 1541 1512 if ( Node::shouldSpeculateInteger(node->child1().node(), node->child2().node()))1542 if (node->isBinaryUseKind(Int32Use)) 1513 1543 compilePeepHoleIntegerBranch(node, branchNode, condition); 1514 else if ( Node::shouldSpeculateNumber(node->child1().node(), node->child2().node()))1544 else if (node->isBinaryUseKind(NumberUse)) 1515 1545 compilePeepHoleDoubleBranch(node, branchNode, doubleCondition); 1516 1546 else if (node->op() == CompareEq) { 1517 if (node-> child1()->shouldSpeculateString() || node->child2()->shouldSpeculateString()) {1547 if (node->isBinaryUseKind(StringUse)) { 1518 1548 nonSpeculativePeepholeBranch(node, branchNode, condition, operation); 1519 1549 return true; 1520 1550 } 1521 if (node-> child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject())1551 if (node->isBinaryUseKind(ObjectUse)) 1522 1552 compilePeepHoleObjectEquality(node, branchNode); 1523 else if (node->child1() ->shouldSpeculateObject() && node->child2()->shouldSpeculateObjectOrOther())1553 else if (node->child1().useKind() == ObjectUse && node->child2().useKind() == ObjectOrOtherUse) 1524 1554 compilePeepHoleObjectToObjectOrOtherEquality(node->child1(), node->child2(), branchNode); 1525 else if (node->child1() ->shouldSpeculateObjectOrOther() && node->child2()->shouldSpeculateObject())1555 else if (node->child1().useKind() == ObjectOrOtherUse && node->child2().useKind() == ObjectUse) 1526 1556 compilePeepHoleObjectToObjectOrOtherEquality(node->child2(), node->child1(), branchNode); 1527 1557 else { … … 1646 1676 for (m_indexInBlock = 0; m_indexInBlock < block.size(); ++m_indexInBlock) { 1647 1677 m_currentNode = block[m_indexInBlock]; 1678 #if !ASSERT_DISABLED 1679 m_canExit = m_currentNode->canExit(); 1680 #endif 1681 bool shouldExecuteEffects = m_state.startExecuting(m_currentNode); 1648 1682 m_jit.setForNode(m_currentNode); 1649 1683 m_codeOriginForOSR = m_currentNode->codeOrigin; … … 1712 1746 } else { 1713 1747 1748 if (verboseCompilationEnabled()) { 1749 dataLogF( 1750 "SpeculativeJIT generating Node @%d (bc#%u) at JIT offset 0x%x", 1751 (int)m_currentNode->index(), 1752 m_currentNode->codeOrigin.bytecodeIndex, m_jit.debugOffset()); 1714 1753 #if DFG_ENABLE(DEBUG_VERBOSE) 1715 dataLogF("SpeculativeJIT generating Node @%d (bc#%u) at JIT offset 0x%x ", (int)m_currentNode->index(), m_currentNode->codeOrigin.bytecodeIndex, m_jit.debugOffset()); 1716 #endif 1754 dataLog(" "); 1755 #else 1756 dataLog("\n"); 1757 #endif 1758 } 1717 1759 #if DFG_ENABLE(JIT_BREAK_ON_EVERY_NODE) 1718 1760 m_jit.breakpoint(); … … 1760 1802 1761 1803 // Make sure that the abstract state is rematerialized for the next node. 1762 m_state.execute(m_indexInBlock); 1804 if (shouldExecuteEffects) 1805 m_state.executeEffects(m_indexInBlock); 1763 1806 1764 1807 if (m_currentNode->shouldGenerate()) … … 1907 1950 FPRReg valueReg = value.fpr(); 1908 1951 1909 if (!isRealNumberSpeculation(m_state.forNode(child3).m_type)) { 1910 // FIXME: We need a way of profiling these, and we need to hoist them into 1911 // SpeculateDoubleOperand. 1912 speculationCheck( 1913 BadType, JSValueRegs(), 0, 1914 m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, valueReg, valueReg)); 1915 } 1952 DFG_TYPE_CHECK( 1953 JSValueRegs(), child3, SpecRealNumber, 1954 m_jit.branchDouble( 1955 MacroAssembler::DoubleNotEqualOrUnordered, valueReg, valueReg)); 1916 1956 1917 1957 if (!m_compileOkay) … … 2105 2145 void SpeculativeJIT::compileValueToInt32(Node* node) 2106 2146 { 2107 if (node->child1()->shouldSpeculateInteger()) { 2147 switch (node->child1().useKind()) { 2148 case Int32Use: { 2108 2149 SpeculateIntegerOperand op1(this, node->child1()); 2109 2150 GPRTemporary result(this, op1); … … 2113 2154 } 2114 2155 2115 if (node->child1()->shouldSpeculateBoolean()) { 2116 SpeculateBooleanOperand op1(this, node->child1()); 2117 GPRTemporary result(this, op1); 2118 2119 m_jit.move(op1.gpr(), result.gpr()); 2120 m_jit.and32(JITCompiler::TrustedImm32(1), result.gpr()); 2121 2122 integerResult(result.gpr(), node); 2123 return; 2124 } 2125 2126 switch (checkGeneratedTypeForToInt32(node->child1().node())) { 2127 case GeneratedOperandInteger: { 2128 SpeculateIntegerOperand op1(this, node->child1()); 2129 GPRTemporary result(this, op1); 2130 m_jit.move(op1.gpr(), result.gpr()); 2131 integerResult(result.gpr(), node, op1.format()); 2132 return; 2133 } 2134 case GeneratedOperandDouble: { 2135 GPRTemporary result(this); 2136 SpeculateDoubleOperand op1(this, Edge(node->child1().node(), DoubleUse)); // SpeculateDoubleOperand will assert that this is a double use. We force it to think that it was a double use, since we are inferring that we ought to emit a double use quite late. 2137 FPRReg fpr = op1.fpr(); 2138 GPRReg gpr = result.gpr(); 2139 JITCompiler::Jump notTruncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateFailed); 2156 case NumberUse: 2157 case NotCellUse: { 2158 switch (checkGeneratedTypeForToInt32(node->child1().node())) { 2159 case GeneratedOperandInteger: { 2160 SpeculateIntegerOperand op1(this, node->child1(), BackwardSpeculation, ManualOperandSpeculation); 2161 GPRTemporary result(this, op1); 2162 m_jit.move(op1.gpr(), result.gpr()); 2163 integerResult(result.gpr(), node, op1.format()); 2164 return; 2165 } 2166 case GeneratedOperandDouble: { 2167 GPRTemporary result(this); 2168 SpeculateDoubleOperand op1(this, node->child1(), BackwardSpeculation, ManualOperandSpeculation); 2169 FPRReg fpr = op1.fpr(); 2170 GPRReg gpr = result.gpr(); 2171 JITCompiler::Jump notTruncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateFailed); 2140 2172 2141 addSlowPathGenerator(slowPathCall(notTruncatedToInteger, this, toInt32, gpr, fpr));2142 2143 integerResult(gpr, node);2144 return;2145 }2146 case GeneratedOperandJSValue: {2147 GPRTemporary result(this);2173 addSlowPathGenerator(slowPathCall(notTruncatedToInteger, this, toInt32, gpr, fpr)); 2174 2175 integerResult(gpr, node); 2176 return; 2177 } 2178 case GeneratedOperandJSValue: { 2179 GPRTemporary result(this); 2148 2180 #if USE(JSVALUE64) 2149 JSValueOperand op1(this, node->child1()); 2150 2151 GPRReg gpr = op1.gpr(); 2152 GPRReg resultGpr = result.gpr(); 2153 FPRTemporary tempFpr(this); 2154 FPRReg fpr = tempFpr.fpr(); 2155 2156 JITCompiler::Jump isInteger = m_jit.branch64(MacroAssembler::AboveOrEqual, gpr, GPRInfo::tagTypeNumberRegister); 2157 JITCompiler::JumpList converted; 2158 2159 if (!isNumberSpeculation(m_state.forNode(node->child1()).m_type)) { 2160 if (node->child1()->shouldSpeculateNumber()) 2161 speculationCheck(BadType, JSValueRegs(gpr), node->child1(), m_jit.branchTest64(MacroAssembler::Zero, gpr, GPRInfo::tagTypeNumberRegister)); 2162 else { 2181 JSValueOperand op1(this, node->child1(), ManualOperandSpeculation); 2182 2183 GPRReg gpr = op1.gpr(); 2184 GPRReg resultGpr = result.gpr(); 2185 FPRTemporary tempFpr(this); 2186 FPRReg fpr = tempFpr.fpr(); 2187 2188 JITCompiler::Jump isInteger = m_jit.branch64(MacroAssembler::AboveOrEqual, gpr, GPRInfo::tagTypeNumberRegister); 2189 JITCompiler::JumpList converted; 2190 2191 if (node->child1().useKind() == NumberUse) { 2192 DFG_TYPE_CHECK( 2193 JSValueRegs(gpr), node->child1(), SpecNumber, 2194 m_jit.branchTest64( 2195 MacroAssembler::Zero, gpr, GPRInfo::tagTypeNumberRegister)); 2196 } else { 2163 2197 JITCompiler::Jump isNumber = m_jit.branchTest64(MacroAssembler::NonZero, gpr, GPRInfo::tagTypeNumberRegister); 2164 2198 2165 if (m_state.forNode(node->child1()).m_type & SpecCell) 2166 speculationCheck(BadType, JSValueRegs(gpr), node->child1(), m_jit.branchTest64(JITCompiler::Zero, gpr, GPRInfo::tagMaskRegister)); 2199 DFG_TYPE_CHECK( 2200 JSValueRegs(gpr), node->child1(), ~SpecCell, 2201 m_jit.branchTest64( 2202 JITCompiler::Zero, gpr, GPRInfo::tagMaskRegister)); 2167 2203 2168 2204 // It's not a cell: so true turns into 1 and all else turns into 0. … … 2172 2208 isNumber.link(&m_jit); 2173 2209 } 2174 } 2175 2176 // First, if we get here we have a double encoded as a JSValue 2177 m_jit.move(gpr, resultGpr); 2178 unboxDouble(resultGpr, fpr); 2179 2180 silentSpillAllRegisters(resultGpr); 2181 callOperation(toInt32, resultGpr, fpr); 2182 silentFillAllRegisters(resultGpr); 2183 2184 converted.append(m_jit.jump()); 2185 2186 isInteger.link(&m_jit); 2187 m_jit.zeroExtend32ToPtr(gpr, resultGpr); 2188 2189 converted.link(&m_jit); 2210 2211 // First, if we get here we have a double encoded as a JSValue 2212 m_jit.move(gpr, resultGpr); 2213 unboxDouble(resultGpr, fpr); 2214 2215 silentSpillAllRegisters(resultGpr); 2216 callOperation(toInt32, resultGpr, fpr); 2217 silentFillAllRegisters(resultGpr); 2218 2219 converted.append(m_jit.jump()); 2220 2221 isInteger.link(&m_jit); 2222 m_jit.zeroExtend32ToPtr(gpr, resultGpr); 2223 2224 converted.link(&m_jit); 2190 2225 #else 2191 Node* childNode = node->child1().node(); 2192 VirtualRegister virtualRegister = childNode->virtualRegister(); 2193 GenerationInfo& info = m_generationInfo[virtualRegister]; 2194 2195 JSValueOperand op1(this, node->child1()); 2196 2197 GPRReg payloadGPR = op1.payloadGPR(); 2198 GPRReg resultGpr = result.gpr(); 2199 2200 JITCompiler::JumpList converted; 2201 2202 if (info.registerFormat() == DataFormatJSInteger) 2203 m_jit.move(payloadGPR, resultGpr); 2204 else { 2205 GPRReg tagGPR = op1.tagGPR(); 2206 FPRTemporary tempFpr(this); 2207 FPRReg fpr = tempFpr.fpr(); 2208 FPRTemporary scratch(this); 2209 2210 JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, tagGPR, TrustedImm32(JSValue::Int32Tag)); 2211 2212 if (!isNumberSpeculation(m_state.forNode(node->child1()).m_type)) { 2213 if (node->child1()->shouldSpeculateNumber()) 2214 speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), node->child1(), m_jit.branch32(MacroAssembler::AboveOrEqual, tagGPR, TrustedImm32(JSValue::LowestTag))); 2215 else { 2226 Node* childNode = node->child1().node(); 2227 VirtualRegister virtualRegister = childNode->virtualRegister(); 2228 GenerationInfo& info = m_generationInfo[virtualRegister]; 2229 2230 JSValueOperand op1(this, node->child1(), ManualOperandSpeculation); 2231 2232 GPRReg payloadGPR = op1.payloadGPR(); 2233 GPRReg resultGpr = result.gpr(); 2234 2235 JITCompiler::JumpList converted; 2236 2237 if (info.registerFormat() == DataFormatJSInteger) 2238 m_jit.move(payloadGPR, resultGpr); 2239 else { 2240 GPRReg tagGPR = op1.tagGPR(); 2241 FPRTemporary tempFpr(this); 2242 FPRReg fpr = tempFpr.fpr(); 2243 FPRTemporary scratch(this); 2244 2245 JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, tagGPR, TrustedImm32(JSValue::Int32Tag)); 2246 2247 if (node->child1().useKind() == NumberUse) { 2248 DFG_TYPE_CHECK( 2249 JSValueRegs(tagGPR, payloadGPR), node->child1(), SpecNumber, 2250 m_jit.branch32( 2251 MacroAssembler::AboveOrEqual, tagGPR, 2252 TrustedImm32(JSValue::LowestTag))); 2253 } else { 2216 2254 JITCompiler::Jump isNumber = m_jit.branch32(MacroAssembler::Below, tagGPR, TrustedImm32(JSValue::LowestTag)); 2217 2255 2218 if (m_state.forNode(node->child1()).m_type & SpecCell) 2219 speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), node->child1(), m_jit.branch32(JITCompiler::Equal, tagGPR, TrustedImm32(JSValue::CellTag))); 2256 DFG_TYPE_CHECK( 2257 JSValueRegs(tagGPR, payloadGPR), node->child1(), ~SpecCell, 2258 m_jit.branch32( 2259 JITCompiler::Equal, tagGPR, TrustedImm32(JSValue::CellTag))); 2220 2260 2221 2261 // It's not a cell: so true turns into 1 and all else turns into 0. … … 2230 2270 isNumber.link(&m_jit); 2231 2271 } 2272 2273 unboxDouble(tagGPR, payloadGPR, fpr, scratch.fpr()); 2274 2275 silentSpillAllRegisters(resultGpr); 2276 callOperation(toInt32, resultGpr, fpr); 2277 silentFillAllRegisters(resultGpr); 2278 2279 converted.append(m_jit.jump()); 2280 2281 isInteger.link(&m_jit); 2282 m_jit.move(payloadGPR, resultGpr); 2283 2284 converted.link(&m_jit); 2232 2285 } 2233 2234 unboxDouble(tagGPR, payloadGPR, fpr, scratch.fpr()); 2235 2236 silentSpillAllRegisters(resultGpr); 2237 callOperation(toInt32, resultGpr, fpr); 2238 silentFillAllRegisters(resultGpr); 2239 2240 converted.append(m_jit.jump()); 2241 2242 isInteger.link(&m_jit); 2243 m_jit.move(payloadGPR, resultGpr); 2244 2245 converted.link(&m_jit); 2246 } 2247 #endif 2248 integerResult(resultGpr, node); 2249 return; 2250 } 2251 case GeneratedOperandTypeUnknown: 2286 #endif 2287 integerResult(resultGpr, node); 2288 return; 2289 } 2290 case GeneratedOperandTypeUnknown: 2291 RELEASE_ASSERT_NOT_REACHED(); 2292 return; 2293 } 2294 RELEASE_ASSERT_NOT_REACHED(); 2295 return; 2296 } 2297 2298 case BooleanUse: { 2299 SpeculateBooleanOperand op1(this, node->child1()); 2300 GPRTemporary result(this, op1); 2301 2302 m_jit.move(op1.gpr(), result.gpr()); 2303 m_jit.and32(JITCompiler::TrustedImm32(1), result.gpr()); 2304 2305 integerResult(result.gpr(), node); 2306 return; 2307 } 2308 2309 default: 2252 2310 ASSERT(!m_compileOkay); 2253 break;2311 return; 2254 2312 } 2255 2313 } … … 2314 2372 2315 2373 if (isInt32Speculation(m_state.forNode(node->child1()).m_type)) { 2316 SpeculateIntegerOperand op1(this, node->child1() );2374 SpeculateIntegerOperand op1(this, node->child1(), BackwardSpeculation, ManualOperandSpeculation); 2317 2375 FPRTemporary result(this); 2318 2376 m_jit.convertInt32ToDouble(op1.gpr(), result.fpr()); … … 2321 2379 } 2322 2380 2323 JSValueOperand op1(this, node->child1() );2381 JSValueOperand op1(this, node->child1(), ManualOperandSpeculation); 2324 2382 FPRTemporary result(this); 2325 2383 … … 2334 2392 MacroAssembler::AboveOrEqual, op1GPR, GPRInfo::tagTypeNumberRegister); 2335 2393 2336 if ( !isNumberSpeculation(m_state.forNode(node->child1()).m_type)) {2394 if (needsTypeCheck(node->child1(), SpecNumber)) { 2337 2395 if (node->op() == ForwardInt32ToDouble) { 2338 forward SpeculationCheck(2339 BadType, JSValueRegs(op1GPR), node->child1().node(),2396 forwardTypeCheck( 2397 JSValueRegs(op1GPR), node->child1(), SpecNumber, 2340 2398 m_jit.branchTest64(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister), 2341 2399 ValueRecovery::inGPR(op1GPR, DataFormatJS)); 2342 2400 } else { 2343 speculationCheck(2344 BadType, JSValueRegs(op1GPR), node->child1(),2401 typeCheck( 2402 JSValueRegs(op1GPR), node->child1(), SpecNumber, 2345 2403 m_jit.branchTest64(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister)); 2346 2404 } … … 2365 2423 MacroAssembler::Equal, op1TagGPR, TrustedImm32(JSValue::Int32Tag)); 2366 2424 2367 if ( !isNumberSpeculation(m_state.forNode(node->child1()).m_type)) {2425 if (needsTypeCheck(node->child1(), SpecNumber)) { 2368 2426 if (node->op() == ForwardInt32ToDouble) { 2369 forward SpeculationCheck(2370 BadType, JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1().node(),2427 forwardTypeCheck( 2428 JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1(), SpecNumber, 2371 2429 m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag)), 2372 2430 ValueRecovery::inPair(op1TagGPR, op1PayloadGPR)); 2373 2431 } else { 2374 speculationCheck(2375 BadType, JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1(),2432 typeCheck( 2433 JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1(), SpecNumber, 2376 2434 m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag))); 2377 2435 } … … 2526 2584 value.adopt(scratch); 2527 2585 valueGPR = scratchReg; 2528 } else if (valueUse->shouldSpeculateInteger()) {2529 SpeculateIntegerOperand valueOp(this, valueUse);2530 GPRTemporary scratch(this);2531 GPRReg scratchReg = scratch.gpr();2532 m_jit.move(valueOp.gpr(), scratchReg);2533 if (rounding == ClampRounding) {2534 ASSERT(elementSize == 1);2535 compileClampIntegerToByte(m_jit, scratchReg);2536 }2537 value.adopt(scratch);2538 valueGPR = scratchReg;2539 } else if (rounding == ClampRounding) {2540 ASSERT(elementSize == 1);2541 SpeculateDoubleOperand valueOp(this, valueUse);2542 GPRTemporary result(this);2543 FPRTemporary floatScratch(this);2544 FPRReg fpr = valueOp.fpr();2545 GPRReg gpr = result.gpr();2546 compileClampDoubleToByte(m_jit, gpr, fpr, floatScratch.fpr());2547 value.adopt(result);2548 valueGPR = gpr;2549 2586 } else { 2550 SpeculateDoubleOperand valueOp(this, valueUse); 2551 GPRTemporary result(this); 2552 FPRReg fpr = valueOp.fpr(); 2553 GPRReg gpr = result.gpr(); 2554 MacroAssembler::Jump notNaN = m_jit.branchDouble(MacroAssembler::DoubleEqual, fpr, fpr); 2555 m_jit.xorPtr(gpr, gpr); 2556 MacroAssembler::Jump fixed = m_jit.jump(); 2557 notNaN.link(&m_jit); 2558 2559 MacroAssembler::Jump failed; 2560 if (signedness == SignedTypedArray) 2561 failed = m_jit.branchTruncateDoubleToInt32(fpr, gpr, MacroAssembler::BranchIfTruncateFailed); 2562 else 2563 failed = m_jit.branchTruncateDoubleToUint32(fpr, gpr, MacroAssembler::BranchIfTruncateFailed); 2564 2565 addSlowPathGenerator(slowPathCall(failed, this, toInt32, gpr, fpr)); 2566 2567 fixed.link(&m_jit); 2568 value.adopt(result); 2569 valueGPR = gpr; 2570 } 2587 switch (valueUse.useKind()) { 2588 case Int32Use: { 2589 SpeculateIntegerOperand valueOp(this, valueUse); 2590 GPRTemporary scratch(this); 2591 GPRReg scratchReg = scratch.gpr(); 2592 m_jit.move(valueOp.gpr(), scratchReg); 2593 if (rounding == ClampRounding) { 2594 ASSERT(elementSize == 1); 2595 compileClampIntegerToByte(m_jit, scratchReg); 2596 } 2597 value.adopt(scratch); 2598 valueGPR = scratchReg; 2599 break; 2600 } 2601 2602 case NumberUse: { 2603 if (rounding == ClampRounding) { 2604 ASSERT(elementSize == 1); 2605 SpeculateDoubleOperand valueOp(this, valueUse); 2606 GPRTemporary result(this); 2607 FPRTemporary floatScratch(this); 2608 FPRReg fpr = valueOp.fpr(); 2609 GPRReg gpr = result.gpr(); 2610 compileClampDoubleToByte(m_jit, gpr, fpr, floatScratch.fpr()); 2611 value.adopt(result); 2612 valueGPR = gpr; 2613 } else { 2614 SpeculateDoubleOperand valueOp(this, valueUse); 2615 GPRTemporary result(this); 2616 FPRReg fpr = valueOp.fpr(); 2617 GPRReg gpr = result.gpr(); 2618 MacroAssembler::Jump notNaN = m_jit.branchDouble(MacroAssembler::DoubleEqual, fpr, fpr); 2619 m_jit.xorPtr(gpr, gpr); 2620 MacroAssembler::Jump fixed = m_jit.jump(); 2621 notNaN.link(&m_jit); 2622 2623 MacroAssembler::Jump failed; 2624 if (signedness == SignedTypedArray) 2625 failed = m_jit.branchTruncateDoubleToInt32(fpr, gpr, MacroAssembler::BranchIfTruncateFailed); 2626 else 2627 failed = m_jit.branchTruncateDoubleToUint32(fpr, gpr, MacroAssembler::BranchIfTruncateFailed); 2628 2629 addSlowPathGenerator(slowPathCall(failed, this, toInt32, gpr, fpr)); 2630 2631 fixed.link(&m_jit); 2632 value.adopt(result); 2633 valueGPR = gpr; 2634 } 2635 break; 2636 } 2637 2638 default: 2639 RELEASE_ASSERT_NOT_REACHED(); 2640 break; 2641 } 2642 } 2643 2571 2644 ASSERT_UNUSED(valueGPR, valueGPR != property); 2572 2645 ASSERT(valueGPR != base); … … 2710 2783 void SpeculativeJIT::compileInstanceOf(Node* node) 2711 2784 { 2712 if ((!!(node->child1()->prediction() & ~SpecCell) && !!(m_state.forNode(node->child1()).m_type & ~SpecCell)) 2713 || node->child1()->adjustedRefCount() == 1) { 2785 if (node->child1().useKind() == UntypedUse) { 2714 2786 // It might not be a cell. Speculate less aggressively. 2715 2787 // Or: it might only be used once (i.e. by us), so we get zero benefit … … 2949 3021 void SpeculativeJIT::compileAdd(Node* node) 2950 3022 { 2951 if (m_jit.graph().addShouldSpeculateInteger(node)) { 3023 switch (node->binaryUseKind()) { 3024 case Int32Use: { 2952 3025 if (isNumberConstant(node->child1().node())) { 2953 int32_t imm1 = valueOf NumberConstantAsInt32(node->child1().node());3026 int32_t imm1 = valueOfInt32Constant(node->child1().node()); 2954 3027 SpeculateIntegerOperand op2(this, node->child2()); 2955 3028 GPRTemporary result(this); … … 2967 3040 if (isNumberConstant(node->child2().node())) { 2968 3041 SpeculateIntegerOperand op1(this, node->child1()); 2969 int32_t imm2 = valueOf NumberConstantAsInt32(node->child2().node());3042 int32_t imm2 = valueOfInt32Constant(node->child2().node()); 2970 3043 GPRTemporary result(this); 2971 3044 … … 3009 3082 return; 3010 3083 } 3011 3012 if (Node::shouldSpeculateNumberExpectingDefined(node->child1().node(), node->child2().node())){3084 3085 case NumberUse: { 3013 3086 SpeculateDoubleOperand op1(this, node->child1()); 3014 3087 SpeculateDoubleOperand op2(this, node->child2()); … … 3022 3095 return; 3023 3096 } 3024 3025 if (node->op() == ValueAdd) { 3097 3098 case UntypedUse: { 3099 RELEASE_ASSERT(node->op() == ValueAdd); 3026 3100 compileValueAdd(node); 3027 3101 return; 3028 3102 } 3029 3030 // We don't handle this yet. :-( 3031 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0); 3103 3104 default: 3105 RELEASE_ASSERT_NOT_REACHED(); 3106 break; 3107 } 3032 3108 } 3033 3109 3034 3110 void SpeculativeJIT::compileArithSub(Node* node) 3035 3111 { 3036 if (m_jit.graph().addShouldSpeculateInteger(node)) { 3112 switch (node->binaryUseKind()) { 3113 case Int32Use: { 3037 3114 if (isNumberConstant(node->child2().node())) { 3038 3115 SpeculateIntegerOperand op1(this, node->child1()); 3039 int32_t imm2 = valueOf NumberConstantAsInt32(node->child2().node());3116 int32_t imm2 = valueOfInt32Constant(node->child2().node()); 3040 3117 GPRTemporary result(this); 3041 3118 … … 3057 3134 3058 3135 if (isNumberConstant(node->child1().node())) { 3059 int32_t imm1 = valueOf NumberConstantAsInt32(node->child1().node());3136 int32_t imm1 = valueOfInt32Constant(node->child1().node()); 3060 3137 SpeculateIntegerOperand op2(this, node->child2()); 3061 3138 GPRTemporary result(this); … … 3085 3162 } 3086 3163 3087 SpeculateDoubleOperand op1(this, node->child1()); 3088 SpeculateDoubleOperand op2(this, node->child2()); 3089 FPRTemporary result(this, op1); 3090 3091 FPRReg reg1 = op1.fpr(); 3092 FPRReg reg2 = op2.fpr(); 3093 m_jit.subDouble(reg1, reg2, result.fpr()); 3094 3095 doubleResult(result.fpr(), node); 3164 case NumberUse: { 3165 SpeculateDoubleOperand op1(this, node->child1()); 3166 SpeculateDoubleOperand op2(this, node->child2()); 3167 FPRTemporary result(this, op1); 3168 3169 FPRReg reg1 = op1.fpr(); 3170 FPRReg reg2 = op2.fpr(); 3171 m_jit.subDouble(reg1, reg2, result.fpr()); 3172 3173 doubleResult(result.fpr(), node); 3174 return; 3175 } 3176 3177 default: 3178 RELEASE_ASSERT_NOT_REACHED(); 3179 return; 3180 } 3096 3181 } 3097 3182 3098 3183 void SpeculativeJIT::compileArithNegate(Node* node) 3099 3184 { 3100 if (m_jit.graph().negateShouldSpeculateInteger(node)) { 3185 switch (node->child1().useKind()) { 3186 case Int32Use: { 3101 3187 SpeculateIntegerOperand op1(this, node->child1()); 3102 3188 GPRTemporary result(this); … … 3116 3202 } 3117 3203 3118 SpeculateDoubleOperand op1(this, node->child1()); 3119 FPRTemporary result(this); 3120 3121 m_jit.negateDouble(op1.fpr(), result.fpr()); 3122 3123 doubleResult(result.fpr(), node); 3204 case NumberUse: { 3205 SpeculateDoubleOperand op1(this, node->child1()); 3206 FPRTemporary result(this); 3207 3208 m_jit.negateDouble(op1.fpr(), result.fpr()); 3209 3210 doubleResult(result.fpr(), node); 3211 return; 3212 } 3213 3214 default: 3215 RELEASE_ASSERT_NOT_REACHED(); 3216 return; 3217 } 3124 3218 } 3125 3219 3126 3220 void SpeculativeJIT::compileArithMul(Node* node) 3127 3221 { 3128 if (m_jit.graph().mulShouldSpeculateInteger(node)) { 3222 switch (node->binaryUseKind()) { 3223 case Int32Use: { 3129 3224 SpeculateIntegerOperand op1(this, node->child1()); 3130 3225 SpeculateIntegerOperand op2(this, node->child2()); … … 3157 3252 return; 3158 3253 } 3159 3160 SpeculateDoubleOperand op1(this, node->child1()); 3161 SpeculateDoubleOperand op2(this, node->child2()); 3162 FPRTemporary result(this, op1, op2); 3163 3164 FPRReg reg1 = op1.fpr(); 3165 FPRReg reg2 = op2.fpr(); 3166 3167 m_jit.mulDouble(reg1, reg2, result.fpr()); 3168 3169 doubleResult(result.fpr(), node); 3254 3255 case NumberUse: { 3256 SpeculateDoubleOperand op1(this, node->child1()); 3257 SpeculateDoubleOperand op2(this, node->child2()); 3258 FPRTemporary result(this, op1, op2); 3259 3260 FPRReg reg1 = op1.fpr(); 3261 FPRReg reg2 = op2.fpr(); 3262 3263 m_jit.mulDouble(reg1, reg2, result.fpr()); 3264 3265 doubleResult(result.fpr(), node); 3266 return; 3267 } 3268 3269 default: 3270 RELEASE_ASSERT_NOT_REACHED(); 3271 return; 3272 } 3170 3273 } 3171 3274 … … 3277 3380 void SpeculativeJIT::compileArithMod(Node* node) 3278 3381 { 3279 if (Node::shouldSpeculateIntegerForArithmetic(node->child1().node(), node->child2().node())3280 && node->canSpeculateInteger()){3382 switch (node->binaryUseKind()) { 3383 case Int32Use: { 3281 3384 compileSoftModulo(node); 3282 3385 return; 3283 3386 } 3284 3387 3285 SpeculateDoubleOperand op1(this, node->child1()); 3286 SpeculateDoubleOperand op2(this, node->child2()); 3287 3288 FPRReg op1FPR = op1.fpr(); 3289 FPRReg op2FPR = op2.fpr(); 3290 3291 flushRegisters(); 3292 3293 FPRResult result(this); 3294 3295 callOperation(fmodAsDFGOperation, result.fpr(), op1FPR, op2FPR); 3296 3297 doubleResult(result.fpr(), node); 3388 case NumberUse: { 3389 SpeculateDoubleOperand op1(this, node->child1()); 3390 SpeculateDoubleOperand op2(this, node->child2()); 3391 3392 FPRReg op1FPR = op1.fpr(); 3393 FPRReg op2FPR = op2.fpr(); 3394 3395 flushRegisters(); 3396 3397 FPRResult result(this); 3398 3399 callOperation(fmodAsDFGOperation, result.fpr(), op1FPR, op2FPR); 3400 3401 doubleResult(result.fpr(), node); 3402 return; 3403 } 3404 3405 default: 3406 RELEASE_ASSERT_NOT_REACHED(); 3407 return; 3408 } 3298 3409 } 3299 3410 … … 3304 3415 return true; 3305 3416 3306 if ( Node::shouldSpeculateInteger(node->child1().node(), node->child2().node())) {3417 if (node->isBinaryUseKind(Int32Use)) { 3307 3418 compileIntegerCompare(node, condition); 3308 3419 return false; 3309 3420 } 3310 3311 if ( Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) {3421 3422 if (node->isBinaryUseKind(NumberUse)) { 3312 3423 compileDoubleCompare(node, doubleCondition); 3313 3424 return false; … … 3315 3426 3316 3427 if (node->op() == CompareEq) { 3317 if (node-> child1()->shouldSpeculateString() || node->child2()->shouldSpeculateString()) {3428 if (node->isBinaryUseKind(StringUse)) { 3318 3429 nonSpeculativeNonPeepholeCompare(node, condition, operation); 3319 3430 return false; 3320 3431 } 3321 3322 if (node-> child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) {3432 3433 if (node->isBinaryUseKind(ObjectUse)) { 3323 3434 compileObjectEquality(node); 3324 3435 return false; 3325 3436 } 3326 3437 3327 if (node->child1() ->shouldSpeculateObject() && node->child2()->shouldSpeculateObjectOrOther()) {3438 if (node->child1().useKind() == ObjectUse && node->child2().useKind() == ObjectOrOtherUse) { 3328 3439 compileObjectToObjectOrOtherEquality(node->child1(), node->child2()); 3329 3440 return false; 3330 3441 } 3331 3442 3332 if (node->child1() ->shouldSpeculateObjectOrOther() && node->child2()->shouldSpeculateObject()) {3443 if (node->child1().useKind() == ObjectOrOtherUse && node->child2().useKind() == ObjectUse) { 3333 3444 compileObjectToObjectOrOtherEquality(node->child2(), node->child1()); 3334 3445 return false; … … 3418 3529 bool SpeculativeJIT::compileStrictEq(Node* node) 3419 3530 { 3420 if (Node::shouldSpeculateInteger(node->child1().node(), node->child2().node())) { 3531 switch (node->binaryUseKind()) { 3532 case Int32Use: { 3421 3533 unsigned branchIndexInBlock = detectPeepHoleBranch(); 3422 3534 if (branchIndexInBlock != UINT_MAX) { … … 3432 3544 return false; 3433 3545 } 3434 3435 if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())){3546 3547 case NumberUse: { 3436 3548 unsigned branchIndexInBlock = detectPeepHoleBranch(); 3437 3549 if (branchIndexInBlock != UINT_MAX) { … … 3447 3559 return false; 3448 3560 } 3449 3450 if (node->child1()->shouldSpeculateString() || node->child2()->shouldSpeculateString())3561 3562 case StringUse: { 3451 3563 return nonSpeculativeStrictEq(node); 3452 if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) { 3564 } 3565 3566 case ObjectUse: { 3453 3567 unsigned branchIndexInBlock = detectPeepHoleBranch(); 3454 3568 if (branchIndexInBlock != UINT_MAX) { … … 3464 3578 return false; 3465 3579 } 3466 3467 return nonSpeculativeStrictEq(node); 3580 3581 case UntypedUse: { 3582 return nonSpeculativeStrictEq(node); 3583 } 3584 3585 default: 3586 RELEASE_ASSERT_NOT_REACHED(); 3587 return false; 3588 } 3468 3589 } 3469 3590 … … 3803 3924 } 3804 3925 3926 void SpeculativeJIT::speculateInt32(Edge edge) 3927 { 3928 if (!needsTypeCheck(edge, SpecInt32)) 3929 return; 3930 3931 (SpeculateIntegerOperand(this, edge)).gpr(); 3932 } 3933 3934 void SpeculativeJIT::speculateNumber(Edge edge) 3935 { 3936 if (!needsTypeCheck(edge, SpecNumber)) 3937 return; 3938 3939 JSValueOperand operand(this, edge, ManualOperandSpeculation); 3940 #if USE(JSVALUE64) 3941 JITCompiler::Jump isInteger = m_jit.branch64(MacroAssembler::AboveOrEqual, operand.gpr(), GPRInfo::tagTypeNumberRegister); 3942 typeCheck( 3943 JSValueRegs(operand.gpr()), edge, SpecNumber, 3944 m_jit.branchTest64(MacroAssembler::Zero, operand.gpr(), GPRInfo::tagTypeNumberRegister)); 3945 isInteger.link(&m_jit); 3946 #else 3947 JSValueOperand op1(this, edge); 3948 JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, operand.tagGPR(), TrustedImm32(JSValue::Int32Tag)); 3949 typeCheck( 3950 JSValueRegs(operand.tagGPR(), op1.payloadGPR()), edge, SpecNumber, 3951 m_jit.branch32(MacroAssembler::AboveOrEqual, operand.tagGPR(), TrustedImm32(JSValue::LowestTag))); 3952 isInteger.link(&m_jit); 3953 #endif 3954 } 3955 3956 void SpeculativeJIT::speculateRealNumber(Edge edge) 3957 { 3958 if (!needsTypeCheck(edge, SpecRealNumber)) 3959 return; 3960 3961 SpeculateDoubleOperand operand(this, edge); 3962 FPRReg fpr = operand.fpr(); 3963 DFG_TYPE_CHECK( 3964 JSValueRegs(), edge, SpecRealNumber, 3965 m_jit.branchDouble( 3966 MacroAssembler::DoubleNotEqualOrUnordered, fpr, fpr)); 3967 } 3968 3969 void SpeculativeJIT::speculateBoolean(Edge edge) 3970 { 3971 if (!needsTypeCheck(edge, SpecBoolean)) 3972 return; 3973 3974 (SpeculateBooleanOperand(this, edge)).gpr(); 3975 } 3976 3977 void SpeculativeJIT::speculateCell(Edge edge) 3978 { 3979 if (!needsTypeCheck(edge, SpecCell)) 3980 return; 3981 3982 (SpeculateCellOperand(this, edge)).gpr(); 3983 } 3984 3985 void SpeculativeJIT::speculateObject(Edge edge) 3986 { 3987 if (!needsTypeCheck(edge, SpecObject)) 3988 return; 3989 3990 SpeculateCellOperand operand(this, edge); 3991 DFG_TYPE_CHECK( 3992 JSValueSource::unboxedCell(operand.gpr()), edge, SpecObject, m_jit.branchPtr( 3993 MacroAssembler::Equal, 3994 MacroAssembler::Address(operand.gpr(), JSCell::structureOffset()), 3995 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 3996 } 3997 3998 void SpeculativeJIT::speculateObjectOrOther(Edge edge) 3999 { 4000 if (!needsTypeCheck(edge, SpecObject | SpecOther)) 4001 return; 4002 4003 JSValueOperand operand(this, edge, ManualOperandSpeculation); 4004 GPRTemporary temp(this); 4005 GPRReg tempGPR = temp.gpr(); 4006 #if USE(JSVALUE64) 4007 GPRReg gpr = operand.gpr(); 4008 MacroAssembler::Jump notCell = m_jit.branchTest64( 4009 MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister); 4010 DFG_TYPE_CHECK( 4011 JSValueRegs(operand.gpr()), edge, (~SpecCell) | SpecObject, m_jit.branchPtr( 4012 MacroAssembler::Equal, 4013 MacroAssembler::Address(gpr, JSCell::structureOffset()), 4014 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 4015 MacroAssembler::Jump done = m_jit.jump(); 4016 notCell.link(&m_jit); 4017 if (needsTypeCheck(edge, SpecCell | SpecOther)) { 4018 m_jit.move(gpr, tempGPR); 4019 m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), tempGPR); 4020 4021 typeCheck( 4022 JSValueRegs(gpr), edge, SpecCell | SpecOther, 4023 m_jit.branch64( 4024 MacroAssembler::NotEqual, tempGPR, 4025 MacroAssembler::TrustedImm64(ValueNull))); 4026 } 4027 done.link(&m_jit); 4028 #else 4029 GPRReg tagGPR = operand.tagGPR(); 4030 GPRReg payloadGPR = operand.payloadGPR(); 4031 MacroAssembler::Jump notCell = 4032 m_jit.branch32(MacroAssembler::NotEqual, tagGPR, TrustedImm32(JSValue::CellTag)); 4033 DFG_TYPE_CHECK( 4034 JSValueRegs(tagGPR, payloadGPR), edge, (~SpecCell) | SpecObject, m_jit.branchPtr( 4035 MacroAssembler::Equal, 4036 MacroAssembler::Address(payloadGPR, JSCell::structureOffset()), 4037 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 4038 MacroAssembler::Jump done = m_jit.jump(); 4039 notCell.link(&m_jit); 4040 if (needsTypeCheck(edge, SpecCell | SpecOther)) { 4041 m_jit.move(tagGPR, tempGPR); 4042 m_jit.or32(TrustedImm32(1), tempGPR); 4043 4044 typeCheck( 4045 JSValueRegs(tagGPR, payloadGPR), edge, SpecCell | SpecOther, 4046 m_jit.branch32( 4047 MacroAssembler::NotEqual, tempGPR, 4048 MacroAssembler::TrustedImm32(JSValue::NullTag))); 4049 } 4050 done.link(&m_jit); 4051 #endif 4052 } 4053 4054 void SpeculativeJIT::speculateString(Edge edge) 4055 { 4056 if (!needsTypeCheck(edge, SpecString)) 4057 return; 4058 4059 SpeculateCellOperand operand(this, edge); 4060 DFG_TYPE_CHECK( 4061 JSValueSource::unboxedCell(operand.gpr()), edge, SpecString, m_jit.branchPtr( 4062 MacroAssembler::NotEqual, 4063 MacroAssembler::Address(operand.gpr(), JSCell::structureOffset()), 4064 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 4065 } 4066 4067 void SpeculativeJIT::speculateNotCell(Edge edge) 4068 { 4069 if (!needsTypeCheck(edge, ~SpecCell)) 4070 return; 4071 4072 JSValueOperand operand(this, edge, ManualOperandSpeculation); 4073 #if USE(JSVALUE64) 4074 typeCheck( 4075 JSValueRegs(operand.gpr()), edge, ~SpecCell, 4076 m_jit.branchTest64( 4077 JITCompiler::Zero, operand.gpr(), GPRInfo::tagMaskRegister)); 4078 #else 4079 typeCheck( 4080 JSValueRegs(operand.tagGPR(), operand.payloadGPR()), edge, ~SpecCell, 4081 m_jit.branch32( 4082 JITCompiler::Equal, operand.tagGPR(), TrustedImm32(JSValue::CellTag))); 4083 #endif 4084 } 4085 4086 void SpeculativeJIT::speculateOther(Edge edge) 4087 { 4088 if (!needsTypeCheck(edge, SpecOther)) 4089 return; 4090 4091 JSValueOperand operand(this, edge, ManualOperandSpeculation); 4092 GPRTemporary temp(this); 4093 GPRReg tempGPR = temp.gpr(); 4094 #if USE(JSVALUE64) 4095 m_jit.move(operand.gpr(), tempGPR); 4096 m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), tempGPR); 4097 typeCheck( 4098 JSValueRegs(operand.gpr()), edge, SpecOther, 4099 m_jit.branch64( 4100 MacroAssembler::NotEqual, tempGPR, 4101 MacroAssembler::TrustedImm64(ValueNull))); 4102 #else 4103 m_jit.move(operand.tagGPR(), tempGPR); 4104 m_jit.or32(TrustedImm32(1), tempGPR); 4105 typeCheck( 4106 JSValueRegs(operand.tagGPR(), operand.payloadGPR()), edge, SpecOther, 4107 m_jit.branch32(MacroAssembler::NotEqual, tempGPR, TrustedImm32(JSValue::NullTag))); 4108 #endif 4109 } 4110 4111 void SpeculativeJIT::speculate(Node*, Edge edge) 4112 { 4113 switch (edge.useKind()) { 4114 case UntypedUse: 4115 break; 4116 case KnownInt32Use: 4117 ASSERT(!needsTypeCheck(edge, SpecInt32)); 4118 break; 4119 case KnownNumberUse: 4120 ASSERT(!needsTypeCheck(edge, SpecNumber)); 4121 break; 4122 case KnownCellUse: 4123 ASSERT(!needsTypeCheck(edge, SpecCell)); 4124 break; 4125 case Int32Use: 4126 speculateInt32(edge); 4127 break; 4128 case RealNumberUse: 4129 speculateRealNumber(edge); 4130 break; 4131 case NumberUse: 4132 speculateNumber(edge); 4133 break; 4134 case BooleanUse: 4135 speculateBoolean(edge); 4136 break; 4137 case CellUse: 4138 speculateCell(edge); 4139 break; 4140 case ObjectUse: 4141 speculateObject(edge); 4142 break; 4143 case ObjectOrOtherUse: 4144 speculateObjectOrOther(edge); 4145 break; 4146 case StringUse: 4147 speculateString(edge); 4148 break; 4149 case NotCellUse: 4150 speculateNotCell(edge); 4151 break; 4152 case OtherUse: 4153 speculateOther(edge); 4154 break; 4155 default: 4156 RELEASE_ASSERT_NOT_REACHED(); 4157 break; 4158 } 4159 } 4160 3805 4161 } } // namespace JSC::DFG 3806 4162 -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r143247 r143654 122 122 } 123 123 124 GPRReg fillInteger( Node*, DataFormat& returnFormat);124 GPRReg fillInteger(Edge, DataFormat& returnFormat); 125 125 #if USE(JSVALUE64) 126 GPRReg fillJSValue( Node*);126 GPRReg fillJSValue(Edge); 127 127 #elif USE(JSVALUE32_64) 128 bool fillJSValue( Node*, GPRReg&, GPRReg&, FPRReg&);129 #endif 130 GPRReg fillStorage( Node*);128 bool fillJSValue(Edge, GPRReg&, GPRReg&, FPRReg&); 129 #endif 130 GPRReg fillStorage(Edge); 131 131 132 132 // lock and unlock GPR & FPR registers. … … 296 296 // Called by the speculative operand types, below, to fill operand to 297 297 // machine registers, implicitly generating speculation checks as needed. 298 GPRReg fillSpeculateInt( Node*, DataFormat& returnFormat, SpeculationDirection);299 GPRReg fillSpeculateIntStrict( Node*);300 FPRReg fillSpeculateDouble( Node*, SpeculationDirection);301 GPRReg fillSpeculateCell( Node*, SpeculationDirection);302 GPRReg fillSpeculateBoolean( Node*, SpeculationDirection);298 GPRReg fillSpeculateInt(Edge, DataFormat& returnFormat, SpeculationDirection); 299 GPRReg fillSpeculateIntStrict(Edge); 300 FPRReg fillSpeculateDouble(Edge, SpeculationDirection); 301 GPRReg fillSpeculateCell(Edge, SpeculationDirection); 302 GPRReg fillSpeculateBoolean(Edge, SpeculationDirection); 303 303 GeneratedOperandType checkGeneratedTypeForToInt32(Node*); 304 304 … … 541 541 int32_t valueOfInt32Constant(Node* node) { return m_jit.graph().valueOfInt32Constant(node); } 542 542 double valueOfNumberConstant(Node* node) { return m_jit.graph().valueOfNumberConstant(node); } 543 int32_t valueOfNumberConstantAsInt32(Node* node)544 {545 if (isInt32Constant(node))546 return valueOfInt32Constant(node);547 return JSC::toInt32(valueOfNumberConstant(node));548 }549 543 #if USE(JSVALUE32_64) 550 544 void* addressOfDoubleConstant(Node* node) { return m_jit.addressOfDoubleConstant(node); } … … 2024 2018 void compileObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild); 2025 2019 void compileValueAdd(Node*); 2026 void compileObjectOrOtherLogicalNot(Edge value , bool needSpeculationCheck);2020 void compileObjectOrOtherLogicalNot(Edge value); 2027 2021 void compileLogicalNot(Node*); 2028 void emitObjectOrOtherBranch(Edge value, BlockIndex taken, BlockIndex notTaken , bool needSpeculationCheck);2022 void emitObjectOrOtherBranch(Edge value, BlockIndex taken, BlockIndex notTaken); 2029 2023 void emitBranch(Node*); 2030 2024 … … 2179 2173 void forwardSpeculationCheck(ExitKind, JSValueSource, Node*, const MacroAssembler::JumpList& jumpsToFail, const ValueRecovery& = ValueRecovery()); 2180 2174 void speculationCheck(ExitKind, JSValueSource, Node*, MacroAssembler::Jump jumpToFail, SpeculationDirection); 2175 void speculationCheck(ExitKind, JSValueSource, Edge, MacroAssembler::Jump jumpToFail, SpeculationDirection); 2181 2176 void speculationCheck(ExitKind, JSValueSource, Node*, MacroAssembler::Jump jumpToFail, const SpeculationRecovery&, SpeculationDirection); 2177 void speculationCheck(ExitKind, JSValueSource, Edge, MacroAssembler::Jump jumpToFail, const SpeculationRecovery&, SpeculationDirection); 2182 2178 // Called when we statically determine that a speculation will fail. 2183 2179 void terminateSpeculativeExecution(ExitKind, JSValueRegs, Node*); … … 2189 2185 JumpReplacementWatchpoint* speculationWatchpoint(ExitKind, SpeculationDirection); 2190 2186 2187 // Helpers for performing type checks on an edge stored in the given registers. 2188 bool needsTypeCheck(Edge edge, SpeculatedType typesPassedThrough) { return m_state.forNode(edge).m_type & ~typesPassedThrough; } 2189 void typeCheck(JSValueSource, Edge, SpeculatedType typesPassedThrough, MacroAssembler::Jump jumpToFail); 2190 void forwardTypeCheck(JSValueSource, Edge, SpeculatedType typesPassedThrough, MacroAssembler::Jump jumpToFail, const ValueRecovery&); 2191 void typeCheck(JSValueSource, Edge, SpeculatedType typesPassedThrough, MacroAssembler::Jump jumpToFail, SpeculationDirection); 2192 2193 void speculateInt32(Edge); 2194 void speculateNumber(Edge); 2195 void speculateRealNumber(Edge); 2196 void speculateBoolean(Edge); 2197 void speculateCell(Edge); 2198 void speculateObject(Edge); 2199 void speculateObjectOrOther(Edge); 2200 void speculateString(Edge); 2201 void speculateNotCell(Edge); 2202 void speculateOther(Edge); 2203 void speculate(Node*, Edge); 2204 2191 2205 const TypedArrayDescriptor* typedArrayDescriptor(ArrayMode); 2192 2206 … … 2198 2212 2199 2213 template<bool strict> 2200 GPRReg fillSpeculateIntInternal( Node*, DataFormat& returnFormat, SpeculationDirection);2214 GPRReg fillSpeculateIntInternal(Edge, DataFormat& returnFormat, SpeculationDirection); 2201 2215 2202 2216 // It is possible, during speculative generation, to reach a situation in which we … … 2248 2262 BlockIndex m_block; 2249 2263 Node* m_currentNode; 2264 #if !ASSERT_DISABLED 2265 bool m_canExit; 2266 #endif 2250 2267 unsigned m_indexInBlock; 2251 2268 // Virtual and physical register maps. … … 2306 2323 class IntegerOperand { 2307 2324 public: 2308 explicit IntegerOperand(SpeculativeJIT* jit, Edge use)2325 explicit IntegerOperand(SpeculativeJIT* jit, Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation) 2309 2326 : m_jit(jit) 2310 , m_ node(use.node())2327 , m_edge(edge) 2311 2328 , m_gprOrInvalid(InvalidGPRReg) 2312 2329 #ifndef NDEBUG … … 2315 2332 { 2316 2333 ASSERT(m_jit); 2317 ASSERT (use.useKind() != DoubleUse);2318 if (jit->isFilled( m_node))2334 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == KnownInt32Use); 2335 if (jit->isFilled(edge.node())) 2319 2336 gpr(); 2320 2337 } … … 2326 2343 } 2327 2344 2345 Edge edge() const 2346 { 2347 return m_edge; 2348 } 2349 2328 2350 Node* node() const 2329 2351 { 2330 return m_node;2352 return edge().node(); 2331 2353 } 2332 2354 … … 2341 2363 { 2342 2364 if (m_gprOrInvalid == InvalidGPRReg) 2343 m_gprOrInvalid = m_jit->fillInteger( node(), m_format);2365 m_gprOrInvalid = m_jit->fillInteger(m_edge, m_format); 2344 2366 return m_gprOrInvalid; 2345 2367 } … … 2347 2369 void use() 2348 2370 { 2349 m_jit->use( m_node);2371 m_jit->use(node()); 2350 2372 } 2351 2373 2352 2374 private: 2353 2375 SpeculativeJIT* m_jit; 2354 Node* m_node;2376 Edge m_edge; 2355 2377 GPRReg m_gprOrInvalid; 2356 2378 DataFormat m_format; … … 2359 2381 class JSValueOperand { 2360 2382 public: 2361 explicit JSValueOperand(SpeculativeJIT* jit, Edge use)2383 explicit JSValueOperand(SpeculativeJIT* jit, Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation) 2362 2384 : m_jit(jit) 2363 , m_ node(use.node())2385 , m_edge(edge) 2364 2386 #if USE(JSVALUE64) 2365 2387 , m_gprOrInvalid(InvalidGPRReg) … … 2369 2391 { 2370 2392 ASSERT(m_jit); 2371 ASSERT (use.useKind() != DoubleUse);2393 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == UntypedUse); 2372 2394 #if USE(JSVALUE64) 2373 if (jit->isFilled( m_node))2395 if (jit->isFilled(node())) 2374 2396 gpr(); 2375 2397 #elif USE(JSVALUE32_64) 2376 2398 m_register.pair.tagGPR = InvalidGPRReg; 2377 2399 m_register.pair.payloadGPR = InvalidGPRReg; 2378 if (jit->isFilled( m_node))2400 if (jit->isFilled(node())) 2379 2401 fill(); 2380 2402 #endif … … 2397 2419 #endif 2398 2420 } 2421 2422 Edge edge() const 2423 { 2424 return m_edge; 2425 } 2399 2426 2400 2427 Node* node() const 2401 2428 { 2402 return m_node;2429 return edge().node(); 2403 2430 } 2404 2431 … … 2407 2434 { 2408 2435 if (m_gprOrInvalid == InvalidGPRReg) 2409 m_gprOrInvalid = m_jit->fillJSValue( node());2436 m_gprOrInvalid = m_jit->fillJSValue(m_edge); 2410 2437 return m_gprOrInvalid; 2411 2438 } … … 2420 2447 { 2421 2448 if (m_register.pair.tagGPR == InvalidGPRReg && m_register.pair.payloadGPR == InvalidGPRReg) 2422 m_isDouble = !m_jit->fillJSValue( node(), m_register.pair.tagGPR, m_register.pair.payloadGPR, m_register.fpr);2449 m_isDouble = !m_jit->fillJSValue(m_edge, m_register.pair.tagGPR, m_register.pair.payloadGPR, m_register.fpr); 2423 2450 } 2424 2451 … … 2452 2479 void use() 2453 2480 { 2454 m_jit->use( m_node);2481 m_jit->use(node()); 2455 2482 } 2456 2483 2457 2484 private: 2458 2485 SpeculativeJIT* m_jit; 2459 Node* m_node;2486 Edge m_edge; 2460 2487 #if USE(JSVALUE64) 2461 2488 GPRReg m_gprOrInvalid; … … 2474 2501 class StorageOperand { 2475 2502 public: 2476 explicit StorageOperand(SpeculativeJIT* jit, Edge use)2503 explicit StorageOperand(SpeculativeJIT* jit, Edge edge) 2477 2504 : m_jit(jit) 2478 , m_ node(use.node())2505 , m_edge(edge) 2479 2506 , m_gprOrInvalid(InvalidGPRReg) 2480 2507 { 2481 2508 ASSERT(m_jit); 2482 ASSERT( use.useKind() != DoubleUse);2483 if (jit->isFilled( m_node))2509 ASSERT(edge.useKind() == UntypedUse || edge.useKind() == KnownCellUse); 2510 if (jit->isFilled(node())) 2484 2511 gpr(); 2485 2512 } … … 2491 2518 } 2492 2519 2520 Edge edge() const 2521 { 2522 return m_edge; 2523 } 2524 2493 2525 Node* node() const 2494 2526 { 2495 return m_node;2527 return edge().node(); 2496 2528 } 2497 2529 … … 2499 2531 { 2500 2532 if (m_gprOrInvalid == InvalidGPRReg) 2501 m_gprOrInvalid = m_jit->fillStorage( node());2533 m_gprOrInvalid = m_jit->fillStorage(edge()); 2502 2534 return m_gprOrInvalid; 2503 2535 } … … 2505 2537 void use() 2506 2538 { 2507 m_jit->use( m_node);2539 m_jit->use(node()); 2508 2540 } 2509 2541 2510 2542 private: 2511 2543 SpeculativeJIT* m_jit; 2512 Node* m_node;2544 Edge m_edge; 2513 2545 GPRReg m_gprOrInvalid; 2514 2546 }; … … 2642 2674 class SpeculateIntegerOperand { 2643 2675 public: 2644 explicit SpeculateIntegerOperand(SpeculativeJIT* jit, Edge use, SpeculationDirection direction = BackwardSpeculation)2676 explicit SpeculateIntegerOperand(SpeculativeJIT* jit, Edge edge, SpeculationDirection direction = BackwardSpeculation, OperandSpeculationMode mode = AutomaticOperandSpeculation) 2645 2677 : m_jit(jit) 2646 , m_ node(use.node())2678 , m_edge(edge) 2647 2679 , m_gprOrInvalid(InvalidGPRReg) 2648 2680 #ifndef NDEBUG … … 2652 2684 { 2653 2685 ASSERT(m_jit); 2654 ASSERT (use.useKind() != DoubleUse);2655 if (jit->isFilled( m_node))2686 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || (edge.useKind() == Int32Use || edge.useKind() == KnownInt32Use)); 2687 if (jit->isFilled(node())) 2656 2688 gpr(); 2657 2689 } … … 2662 2694 m_jit->unlock(m_gprOrInvalid); 2663 2695 } 2696 2697 Edge edge() const 2698 { 2699 return m_edge; 2700 } 2664 2701 2665 2702 Node* node() const 2666 2703 { 2667 return m_node;2704 return edge().node(); 2668 2705 } 2669 2706 … … 2678 2715 { 2679 2716 if (m_gprOrInvalid == InvalidGPRReg) 2680 m_gprOrInvalid = m_jit->fillSpeculateInt( node(), m_format, m_direction);2717 m_gprOrInvalid = m_jit->fillSpeculateInt(edge(), m_format, m_direction); 2681 2718 return m_gprOrInvalid; 2682 2719 } … … 2684 2721 void use() 2685 2722 { 2686 m_jit->use( m_node);2723 m_jit->use(node()); 2687 2724 } 2688 2725 2689 2726 private: 2690 2727 SpeculativeJIT* m_jit; 2691 Node* m_node;2728 Edge m_edge; 2692 2729 GPRReg m_gprOrInvalid; 2693 2730 DataFormat m_format; … … 2697 2734 class SpeculateStrictInt32Operand { 2698 2735 public: 2699 explicit SpeculateStrictInt32Operand(SpeculativeJIT* jit, Edge use)2736 explicit SpeculateStrictInt32Operand(SpeculativeJIT* jit, Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation) 2700 2737 : m_jit(jit) 2701 , m_ node(use.node())2738 , m_edge(edge) 2702 2739 , m_gprOrInvalid(InvalidGPRReg) 2703 2740 { 2704 2741 ASSERT(m_jit); 2705 ASSERT (use.useKind() != DoubleUse);2706 if (jit->isFilled( m_node))2742 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || (edge.useKind() == Int32Use || edge.useKind() == KnownInt32Use)); 2743 if (jit->isFilled(node())) 2707 2744 gpr(); 2708 2745 } … … 2713 2750 m_jit->unlock(m_gprOrInvalid); 2714 2751 } 2752 2753 Edge edge() const 2754 { 2755 return m_edge; 2756 } 2715 2757 2716 2758 Node* node() const 2717 2759 { 2718 return m_node;2760 return edge().node(); 2719 2761 } 2720 2762 … … 2722 2764 { 2723 2765 if (m_gprOrInvalid == InvalidGPRReg) 2724 m_gprOrInvalid = m_jit->fillSpeculateIntStrict( node());2766 m_gprOrInvalid = m_jit->fillSpeculateIntStrict(edge()); 2725 2767 return m_gprOrInvalid; 2726 2768 } … … 2728 2770 void use() 2729 2771 { 2730 m_jit->use( m_node);2772 m_jit->use(node()); 2731 2773 } 2732 2774 2733 2775 private: 2734 2776 SpeculativeJIT* m_jit; 2735 Node* m_node;2777 Edge m_edge; 2736 2778 GPRReg m_gprOrInvalid; 2737 2779 }; … … 2739 2781 class SpeculateDoubleOperand { 2740 2782 public: 2741 explicit SpeculateDoubleOperand(SpeculativeJIT* jit, Edge use, SpeculationDirection direction = BackwardSpeculation)2783 explicit SpeculateDoubleOperand(SpeculativeJIT* jit, Edge edge, SpeculationDirection direction = BackwardSpeculation, OperandSpeculationMode mode = AutomaticOperandSpeculation) 2742 2784 : m_jit(jit) 2743 , m_ node(use.node())2785 , m_edge(edge) 2744 2786 , m_fprOrInvalid(InvalidFPRReg) 2745 2787 , m_direction(direction) 2746 2788 { 2747 2789 ASSERT(m_jit); 2748 ASSERT (use.useKind() == DoubleUse);2749 if (jit->isFilled( m_node))2790 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || (edge.useKind() == NumberUse || edge.useKind() == KnownNumberUse || edge.useKind() == RealNumberUse)); 2791 if (jit->isFilled(node())) 2750 2792 fpr(); 2751 2793 } … … 2756 2798 m_jit->unlock(m_fprOrInvalid); 2757 2799 } 2800 2801 Edge edge() const 2802 { 2803 return m_edge; 2804 } 2758 2805 2759 2806 Node* node() const 2760 2807 { 2761 return m_node;2808 return edge().node(); 2762 2809 } 2763 2810 … … 2765 2812 { 2766 2813 if (m_fprOrInvalid == InvalidFPRReg) 2767 m_fprOrInvalid = m_jit->fillSpeculateDouble( node(), m_direction);2814 m_fprOrInvalid = m_jit->fillSpeculateDouble(edge(), m_direction); 2768 2815 return m_fprOrInvalid; 2769 2816 } … … 2771 2818 void use() 2772 2819 { 2773 m_jit->use( m_node);2820 m_jit->use(node()); 2774 2821 } 2775 2822 2776 2823 private: 2777 2824 SpeculativeJIT* m_jit; 2778 Node* m_node;2825 Edge m_edge; 2779 2826 FPRReg m_fprOrInvalid; 2780 2827 SpeculationDirection m_direction; … … 2783 2830 class SpeculateCellOperand { 2784 2831 public: 2785 explicit SpeculateCellOperand(SpeculativeJIT* jit, Edge use, SpeculationDirection direction = BackwardSpeculation)2832 explicit SpeculateCellOperand(SpeculativeJIT* jit, Edge edge, SpeculationDirection direction = BackwardSpeculation, OperandSpeculationMode mode = AutomaticOperandSpeculation) 2786 2833 : m_jit(jit) 2787 , m_ node(use.node())2834 , m_edge(edge) 2788 2835 , m_gprOrInvalid(InvalidGPRReg) 2789 2836 , m_direction(direction) 2790 2837 { 2791 2838 ASSERT(m_jit); 2792 ASSERT (use.useKind() != DoubleUse);2793 if (jit->isFilled( m_node))2839 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || (edge.useKind() == CellUse || edge.useKind() == KnownCellUse || edge.useKind() == ObjectUse || edge.useKind() == StringUse)); 2840 if (jit->isFilled(node())) 2794 2841 gpr(); 2795 2842 } … … 2800 2847 m_jit->unlock(m_gprOrInvalid); 2801 2848 } 2849 2850 Edge edge() const 2851 { 2852 return m_edge; 2853 } 2802 2854 2803 2855 Node* node() const 2804 2856 { 2805 return m_node;2857 return edge().node(); 2806 2858 } 2807 2859 … … 2809 2861 { 2810 2862 if (m_gprOrInvalid == InvalidGPRReg) 2811 m_gprOrInvalid = m_jit->fillSpeculateCell( node(), m_direction);2863 m_gprOrInvalid = m_jit->fillSpeculateCell(edge(), m_direction); 2812 2864 return m_gprOrInvalid; 2813 2865 } … … 2815 2867 void use() 2816 2868 { 2817 m_jit->use( m_node);2869 m_jit->use(node()); 2818 2870 } 2819 2871 2820 2872 private: 2821 2873 SpeculativeJIT* m_jit; 2822 Node* m_node;2874 Edge m_edge; 2823 2875 GPRReg m_gprOrInvalid; 2824 2876 SpeculationDirection m_direction; … … 2827 2879 class SpeculateBooleanOperand { 2828 2880 public: 2829 explicit SpeculateBooleanOperand(SpeculativeJIT* jit, Edge use, SpeculationDirection direction = BackwardSpeculation)2881 explicit SpeculateBooleanOperand(SpeculativeJIT* jit, Edge edge, SpeculationDirection direction = BackwardSpeculation, OperandSpeculationMode mode = AutomaticOperandSpeculation) 2830 2882 : m_jit(jit) 2831 , m_ node(use.node())2883 , m_edge(edge) 2832 2884 , m_gprOrInvalid(InvalidGPRReg) 2833 2885 , m_direction(direction) 2834 2886 { 2835 2887 ASSERT(m_jit); 2836 ASSERT (use.useKind() != DoubleUse);2837 if (jit->isFilled( m_node))2888 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == BooleanUse); 2889 if (jit->isFilled(node())) 2838 2890 gpr(); 2839 2891 } … … 2845 2897 } 2846 2898 2899 Edge edge() const 2900 { 2901 return m_edge; 2902 } 2903 2847 2904 Node* node() const 2848 2905 { 2849 return m_node;2906 return edge().node(); 2850 2907 } 2851 2908 … … 2853 2910 { 2854 2911 if (m_gprOrInvalid == InvalidGPRReg) 2855 m_gprOrInvalid = m_jit->fillSpeculateBoolean( node(), m_direction);2912 m_gprOrInvalid = m_jit->fillSpeculateBoolean(edge(), m_direction); 2856 2913 return m_gprOrInvalid; 2857 2914 } … … 2859 2916 void use() 2860 2917 { 2861 m_jit->use( m_node);2918 m_jit->use(node()); 2862 2919 } 2863 2920 2864 2921 private: 2865 2922 SpeculativeJIT* m_jit; 2866 Node* m_node;2923 Edge m_edge; 2867 2924 GPRReg m_gprOrInvalid; 2868 2925 SpeculationDirection m_direction; 2869 2926 }; 2870 2927 2928 #define DFG_TYPE_CHECK(source, edge, typesPassedThrough, jumpToFail) do { \ 2929 if (!needsTypeCheck((edge), (typesPassedThrough))) \ 2930 break; \ 2931 typeCheck((source), (edge), (typesPassedThrough), (jumpToFail)); \ 2932 } while (0) 2933 2871 2934 } } // namespace JSC::DFG 2872 2935 -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r143314 r143654 41 41 #if USE(JSVALUE32_64) 42 42 43 GPRReg SpeculativeJIT::fillInteger( Node* node, DataFormat& returnFormat)43 GPRReg SpeculativeJIT::fillInteger(Edge edge, DataFormat& returnFormat) 44 44 { 45 VirtualRegister virtualRegister = node->virtualRegister(); 45 ASSERT(!needsTypeCheck(edge, SpecInt32)); 46 47 VirtualRegister virtualRegister = edge->virtualRegister(); 46 48 GenerationInfo& info = m_generationInfo[virtualRegister]; 47 49 … … 49 51 GPRReg gpr = allocate(); 50 52 51 if ( node->hasConstant()) {53 if (edge->hasConstant()) { 52 54 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); 53 if (isInt32Constant( node))54 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant( node)), gpr);55 else if (isNumberConstant( node))55 if (isInt32Constant(edge.node())) 56 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(edge.node())), gpr); 57 else if (isNumberConstant(edge.node())) 56 58 RELEASE_ASSERT_NOT_REACHED(); 57 59 else { 58 ASSERT(isJSConstant( node));59 JSValue jsValue = valueOfJSConstant( node);60 ASSERT(isJSConstant(edge.node())); 61 JSValue jsValue = valueOfJSConstant(edge.node()); 60 62 m_jit.move(MacroAssembler::Imm32(jsValue.payload()), gpr); 61 63 } … … 114 116 } 115 117 116 bool SpeculativeJIT::fillJSValue( Node* node, GPRReg& tagGPR, GPRReg& payloadGPR, FPRReg& fpr)118 bool SpeculativeJIT::fillJSValue(Edge edge, GPRReg& tagGPR, GPRReg& payloadGPR, FPRReg& fpr) 117 119 { 118 120 // FIXME: For double we could fill with a FPR. 119 121 UNUSED_PARAM(fpr); 120 122 121 VirtualRegister virtualRegister = node->virtualRegister();123 VirtualRegister virtualRegister = edge->virtualRegister(); 122 124 GenerationInfo& info = m_generationInfo[virtualRegister]; 123 125 … … 125 127 case DataFormatNone: { 126 128 127 if ( node->hasConstant()) {129 if (edge->hasConstant()) { 128 130 tagGPR = allocate(); 129 131 payloadGPR = allocate(); 130 m_jit.move(Imm32(valueOfJSConstant( node).tag()), tagGPR);131 m_jit.move(Imm32(valueOfJSConstant( node).payload()), payloadGPR);132 m_jit.move(Imm32(valueOfJSConstant(edge.node()).tag()), tagGPR); 133 m_jit.move(Imm32(valueOfJSConstant(edge.node()).payload()), payloadGPR); 132 134 m_gprs.retain(tagGPR, virtualRegister, SpillOrderConstant); 133 135 m_gprs.retain(payloadGPR, virtualRegister, SpillOrderConstant); 134 info.fillJSValue(*m_stream, tagGPR, payloadGPR, isInt32Constant( node) ? DataFormatJSInteger : DataFormatJS);136 info.fillJSValue(*m_stream, tagGPR, payloadGPR, isInt32Constant(edge.node()) ? DataFormatJSInteger : DataFormatJS); 135 137 } else { 136 138 DataFormat spillFormat = info.spillFormat(); … … 845 847 846 848 template<bool strict> 847 GPRReg SpeculativeJIT::fillSpeculateIntInternal( Node* node, DataFormat& returnFormat, SpeculationDirection direction)849 GPRReg SpeculativeJIT::fillSpeculateIntInternal(Edge edge, DataFormat& returnFormat, SpeculationDirection direction) 848 850 { 849 851 #if DFG_ENABLE(DEBUG_VERBOSE) 850 dataLogF("SpecInt@%d ", node->index());852 dataLogF("SpecInt@%d ", edge->index()); 851 853 #endif 852 SpeculatedType type = m_state.forNode(node).m_type; 853 VirtualRegister virtualRegister = node->virtualRegister(); 854 AbstractValue& value = m_state.forNode(edge); 855 SpeculatedType type = value.m_type; 856 ASSERT(edge.useKind() != KnownInt32Use || !(value.m_type & ~SpecInt32)); 857 value.filter(SpecInt32); 858 VirtualRegister virtualRegister = edge->virtualRegister(); 854 859 GenerationInfo& info = m_generationInfo[virtualRegister]; 855 860 856 861 switch (info.registerFormat()) { 857 862 case DataFormatNone: { 858 if (( node->hasConstant() && !isInt32Constant(node)) || info.spillFormat() == DataFormatDouble) {863 if ((edge->hasConstant() && !isInt32Constant(edge.node())) || info.spillFormat() == DataFormatDouble) { 859 864 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0, direction); 860 865 returnFormat = DataFormatInteger; … … 862 867 } 863 868 864 if ( node->hasConstant()) {865 ASSERT(isInt32Constant( node));869 if (edge->hasConstant()) { 870 ASSERT(isInt32Constant(edge.node())); 866 871 GPRReg gpr = allocate(); 867 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant( node)), gpr);872 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(edge.node())), gpr); 868 873 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); 869 874 info.fillInteger(*m_stream, gpr); … … 876 881 877 882 // If we know this was spilled as an integer we can fill without checking. 878 if ( !isInt32Speculation(type))879 speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), node, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag)), direction);883 if (type & ~SpecInt32) 884 speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), edge, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag)), direction); 880 885 881 886 GPRReg gpr = allocate(); … … 894 899 m_gprs.lock(tagGPR); 895 900 m_gprs.lock(payloadGPR); 896 if ( !isInt32Speculation(type))897 speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), node, m_jit.branch32(MacroAssembler::NotEqual, tagGPR, TrustedImm32(JSValue::Int32Tag)), direction);901 if (type & ~SpecInt32) 902 speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), edge, m_jit.branch32(MacroAssembler::NotEqual, tagGPR, TrustedImm32(JSValue::Int32Tag)), direction); 898 903 m_gprs.unlock(tagGPR); 899 904 m_gprs.release(tagGPR); … … 930 935 } 931 936 932 GPRReg SpeculativeJIT::fillSpeculateInt( Node* node, DataFormat& returnFormat, SpeculationDirection direction)937 GPRReg SpeculativeJIT::fillSpeculateInt(Edge edge, DataFormat& returnFormat, SpeculationDirection direction) 933 938 { 934 return fillSpeculateIntInternal<false>( node, returnFormat, direction);939 return fillSpeculateIntInternal<false>(edge, returnFormat, direction); 935 940 } 936 941 937 GPRReg SpeculativeJIT::fillSpeculateIntStrict( Node* node)942 GPRReg SpeculativeJIT::fillSpeculateIntStrict(Edge edge) 938 943 { 939 944 DataFormat mustBeDataFormatInteger; 940 GPRReg result = fillSpeculateIntInternal<true>( node, mustBeDataFormatInteger, BackwardSpeculation);945 GPRReg result = fillSpeculateIntInternal<true>(edge, mustBeDataFormatInteger, BackwardSpeculation); 941 946 ASSERT(mustBeDataFormatInteger == DataFormatInteger); 942 947 return result; 943 948 } 944 949 945 FPRReg SpeculativeJIT::fillSpeculateDouble( Node* node, SpeculationDirection direction)950 FPRReg SpeculativeJIT::fillSpeculateDouble(Edge edge, SpeculationDirection direction) 946 951 { 947 952 #if DFG_ENABLE(DEBUG_VERBOSE) 948 dataLogF("SpecDouble@%d ", node->index());953 dataLogF("SpecDouble@%d ", edge->index()); 949 954 #endif 950 SpeculatedType type = m_state.forNode(node).m_type; 951 VirtualRegister virtualRegister = node->virtualRegister(); 955 AbstractValue& value = m_state.forNode(edge); 956 SpeculatedType type = value.m_type; 957 ASSERT(edge.useKind() != KnownNumberUse || !(value.m_type & ~SpecNumber)); 958 value.filter(SpecNumber); 959 VirtualRegister virtualRegister = edge->virtualRegister(); 952 960 GenerationInfo& info = m_generationInfo[virtualRegister]; 953 961 954 962 if (info.registerFormat() == DataFormatNone) { 955 963 956 if ( node->hasConstant()) {957 if (isInt32Constant( node)) {964 if (edge->hasConstant()) { 965 if (isInt32Constant(edge.node())) { 958 966 GPRReg gpr = allocate(); 959 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant( node)), gpr);967 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(edge.node())), gpr); 960 968 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); 961 969 info.fillInteger(*m_stream, gpr); 962 970 unlock(gpr); 963 } else if (isNumberConstant( node)) {971 } else if (isNumberConstant(edge.node())) { 964 972 FPRReg fpr = fprAllocate(); 965 m_jit.loadDouble(addressOfDoubleConstant( node), fpr);973 m_jit.loadDouble(addressOfDoubleConstant(edge.node()), fpr); 966 974 m_fprs.retain(fpr, virtualRegister, SpillOrderConstant); 967 975 info.fillDouble(*m_stream, fpr); … … 987 995 if (spillFormat != DataFormatJSInteger && spillFormat != DataFormatInteger) { 988 996 JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag)); 989 if ( !isNumberSpeculation(type))990 speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), node, m_jit.branch32(MacroAssembler::AboveOrEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::LowestTag)), direction);997 if (type & ~SpecNumber) 998 speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), edge, m_jit.branch32(MacroAssembler::AboveOrEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::LowestTag)), direction); 991 999 m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr); 992 1000 hasUnboxedDouble = m_jit.jump(); … … 1022 1030 FPRTemporary scratch(this); 1023 1031 JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, tagGPR, TrustedImm32(JSValue::Int32Tag)); 1024 if ( !isNumberSpeculation(type))1025 speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), node, m_jit.branch32(MacroAssembler::AboveOrEqual, tagGPR, TrustedImm32(JSValue::LowestTag)), direction);1032 if (type & ~SpecNumber) 1033 speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), edge, m_jit.branch32(MacroAssembler::AboveOrEqual, tagGPR, TrustedImm32(JSValue::LowestTag)), direction); 1026 1034 unboxDouble(tagGPR, payloadGPR, fpr, scratch.fpr()); 1027 1035 hasUnboxedDouble = m_jit.jump(); … … 1077 1085 } 1078 1086 1079 GPRReg SpeculativeJIT::fillSpeculateCell( Node* node, SpeculationDirection direction)1087 GPRReg SpeculativeJIT::fillSpeculateCell(Edge edge, SpeculationDirection direction) 1080 1088 { 1081 1089 #if DFG_ENABLE(DEBUG_VERBOSE) 1082 dataLogF("SpecCell@%d ", node->index());1090 dataLogF("SpecCell@%d ", edge->index()); 1083 1091 #endif 1084 SpeculatedType type = m_state.forNode(node).m_type; 1085 VirtualRegister virtualRegister = node->virtualRegister(); 1092 AbstractValue& value = m_state.forNode(edge); 1093 SpeculatedType type = value.m_type; 1094 ASSERT(edge.useKind() != KnownCellUse || !(value.m_type & ~SpecCell)); 1095 value.filter(SpecCell); 1096 VirtualRegister virtualRegister = edge->virtualRegister(); 1086 1097 GenerationInfo& info = m_generationInfo[virtualRegister]; 1087 1098 … … 1089 1100 case DataFormatNone: { 1090 1101 1091 if ( node->hasConstant()) {1092 JSValue jsValue = valueOfJSConstant( node);1102 if (edge->hasConstant()) { 1103 JSValue jsValue = valueOfJSConstant(edge.node()); 1093 1104 GPRReg gpr = allocate(); 1094 1105 if (jsValue.isCell()) { … … 1103 1114 1104 1115 ASSERT((info.spillFormat() & DataFormatJS) || info.spillFormat() == DataFormatCell); 1105 if ( !isCellSpeculation(type))1106 speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), node, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::CellTag)), direction);1116 if (type & ~SpecCell) 1117 speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), edge, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::CellTag)), direction); 1107 1118 GPRReg gpr = allocate(); 1108 1119 m_jit.load32(JITCompiler::payloadFor(virtualRegister), gpr); … … 1124 1135 m_gprs.lock(tagGPR); 1125 1136 m_gprs.lock(payloadGPR); 1126 if ( !isCellSpeculation(type))1127 speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), node, m_jit.branch32(MacroAssembler::NotEqual, tagGPR, TrustedImm32(JSValue::CellTag)), direction);1137 if (type & ~SpecCell) 1138 speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), edge, m_jit.branch32(MacroAssembler::NotEqual, tagGPR, TrustedImm32(JSValue::CellTag)), direction); 1128 1139 m_gprs.unlock(tagGPR); 1129 1140 m_gprs.release(tagGPR); … … 1152 1163 } 1153 1164 1154 GPRReg SpeculativeJIT::fillSpeculateBoolean( Node* node, SpeculationDirection direction)1165 GPRReg SpeculativeJIT::fillSpeculateBoolean(Edge edge, SpeculationDirection direction) 1155 1166 { 1156 1167 #if DFG_ENABLE(DEBUG_VERBOSE) 1157 1168 dataLogF("SpecBool@%d ", node->index()); 1158 1169 #endif 1159 SpeculatedType type = m_state.forNode(node).m_type; 1160 VirtualRegister virtualRegister = node->virtualRegister(); 1170 AbstractValue& value = m_state.forNode(edge); 1171 SpeculatedType type = value.m_type; 1172 value.filter(SpecBoolean); 1173 VirtualRegister virtualRegister = edge->virtualRegister(); 1161 1174 GenerationInfo& info = m_generationInfo[virtualRegister]; 1162 1175 … … 1168 1181 } 1169 1182 1170 if ( node->hasConstant()) {1171 JSValue jsValue = valueOfJSConstant( node);1183 if (edge->hasConstant()) { 1184 JSValue jsValue = valueOfJSConstant(edge.node()); 1172 1185 GPRReg gpr = allocate(); 1173 1186 if (jsValue.isBoolean()) { … … 1183 1196 ASSERT((info.spillFormat() & DataFormatJS) || info.spillFormat() == DataFormatBoolean); 1184 1197 1185 if ( !isBooleanSpeculation(type))1186 speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), node, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::BooleanTag)), direction);1198 if (type & ~SpecBoolean) 1199 speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), edge, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::BooleanTag)), direction); 1187 1200 1188 1201 GPRReg gpr = allocate(); … … 1205 1218 m_gprs.lock(tagGPR); 1206 1219 m_gprs.lock(payloadGPR); 1207 if ( !isBooleanSpeculation(type))1208 speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), node, m_jit.branch32(MacroAssembler::NotEqual, tagGPR, TrustedImm32(JSValue::BooleanTag)), direction);1220 if (type & ~SpecBoolean) 1221 speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), edge, m_jit.branch32(MacroAssembler::NotEqual, tagGPR, TrustedImm32(JSValue::BooleanTag)), direction); 1209 1222 1210 1223 m_gprs.unlock(tagGPR); … … 1260 1273 1261 1274 if (m_jit.graph().globalObjectFor(node->codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) { 1262 m_jit.graph().globalObjectFor(node->codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint()); 1263 if (m_state.forNode(node->child1()).m_type & ~SpecObject) { 1264 speculationCheck( 1265 BadType, JSValueSource::unboxedCell(op1GPR), node->child1(), 1266 m_jit.branchPtr( 1267 MacroAssembler::Equal, 1268 MacroAssembler::Address(op1GPR, JSCell::structureOffset()), 1269 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1270 } 1271 if (m_state.forNode(node->child2()).m_type & ~SpecObject) { 1272 speculationCheck( 1273 BadType, JSValueSource::unboxedCell(op2GPR), node->child2(), 1274 m_jit.branchPtr( 1275 MacroAssembler::Equal, 1276 MacroAssembler::Address(op2GPR, JSCell::structureOffset()), 1277 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1278 } 1275 m_jit.graph().globalObjectFor(node->codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint()); 1276 DFG_TYPE_CHECK( 1277 JSValueSource::unboxedCell(op1GPR), node->child1(), SpecObject, m_jit.branchPtr( 1278 MacroAssembler::Equal, 1279 MacroAssembler::Address(op1GPR, JSCell::structureOffset()), 1280 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1281 DFG_TYPE_CHECK( 1282 JSValueSource::unboxedCell(op2GPR), node->child2(), SpecObject, m_jit.branchPtr( 1283 MacroAssembler::Equal, 1284 MacroAssembler::Address(op2GPR, JSCell::structureOffset()), 1285 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1279 1286 } else { 1280 1287 GPRTemporary structure(this); … … 1282 1289 1283 1290 m_jit.loadPtr(MacroAssembler::Address(op1GPR, JSCell::structureOffset()), structureGPR); 1284 if (m_state.forNode(node->child1()).m_type & ~SpecObject) { 1285 speculationCheck( 1286 BadType, JSValueSource::unboxedCell(op1GPR), node->child1(), 1287 m_jit.branchPtr( 1288 MacroAssembler::Equal, 1289 structureGPR, 1290 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1291 } 1291 DFG_TYPE_CHECK( 1292 JSValueSource::unboxedCell(op1GPR), node->child1(), SpecObject, m_jit.branchPtr( 1293 MacroAssembler::Equal, 1294 structureGPR, 1295 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1292 1296 speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node->child1(), 1293 1297 m_jit.branchTest8( … … 1297 1301 1298 1302 m_jit.loadPtr(MacroAssembler::Address(op2GPR, JSCell::structureOffset()), structureGPR); 1299 if (m_state.forNode(node->child2()).m_type & ~SpecObject) { 1300 speculationCheck( 1301 BadType, JSValueSource::unboxedCell(op2GPR), node->child2(), 1302 m_jit.branchPtr( 1303 MacroAssembler::Equal, 1304 structureGPR, 1305 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1306 } 1303 DFG_TYPE_CHECK( 1304 JSValueSource::unboxedCell(op2GPR), node->child2(), SpecObject, m_jit.branchPtr( 1305 MacroAssembler::Equal, 1306 structureGPR, 1307 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1307 1308 speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node->child2(), 1308 1309 m_jit.branchTest8( … … 1328 1329 { 1329 1330 SpeculateCellOperand op1(this, leftChild); 1330 JSValueOperand op2(this, rightChild );1331 JSValueOperand op2(this, rightChild, ManualOperandSpeculation); 1331 1332 GPRTemporary result(this); 1332 1333 … … 1338 1339 if (m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) { 1339 1340 m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint()); 1340 if (m_state.forNode(leftChild).m_type & ~SpecObject) { 1341 speculationCheck( 1342 BadType, JSValueSource::unboxedCell(op1GPR), leftChild, 1343 m_jit.branchPtr( 1344 MacroAssembler::Equal, 1345 MacroAssembler::Address(op1GPR, JSCell::structureOffset()), 1346 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1347 } 1341 DFG_TYPE_CHECK( 1342 JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchPtr( 1343 MacroAssembler::Equal, 1344 MacroAssembler::Address(op1GPR, JSCell::structureOffset()), 1345 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1348 1346 } else { 1349 1347 GPRTemporary structure(this); … … 1351 1349 1352 1350 m_jit.loadPtr(MacroAssembler::Address(op1GPR, JSCell::structureOffset()), structureGPR); 1353 if (m_state.forNode(leftChild).m_type & ~SpecObject) { 1354 speculationCheck( 1355 BadType, JSValueSource::unboxedCell(op1GPR), leftChild, 1356 m_jit.branchPtr( 1357 MacroAssembler::Equal, 1358 structureGPR, 1359 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1360 } 1351 DFG_TYPE_CHECK( 1352 JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchPtr( 1353 MacroAssembler::Equal, 1354 structureGPR, 1355 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1361 1356 speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), leftChild, 1362 1357 m_jit.branchTest8( … … 1375 1370 if (m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) { 1376 1371 m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint()); 1377 if ((m_state.forNode(rightChild).m_type & SpecCell) & ~SpecObject) { 1378 speculationCheck( 1379 BadType, JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, 1380 m_jit.branchPtr( 1381 MacroAssembler::Equal, 1382 MacroAssembler::Address(op2PayloadGPR, JSCell::structureOffset()), 1383 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1384 } 1372 DFG_TYPE_CHECK( 1373 JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, (~SpecCell) | SpecObject, 1374 m_jit.branchPtr( 1375 MacroAssembler::Equal, 1376 MacroAssembler::Address(op2PayloadGPR, JSCell::structureOffset()), 1377 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1385 1378 } else { 1386 1379 GPRTemporary structure(this); … … 1388 1381 1389 1382 m_jit.loadPtr(MacroAssembler::Address(op2PayloadGPR, JSCell::structureOffset()), structureGPR); 1390 if ((m_state.forNode(rightChild).m_type & SpecCell) & ~SpecObject) { 1391 speculationCheck( 1392 BadType, JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, 1393 m_jit.branchPtr( 1394 MacroAssembler::Equal, 1395 structureGPR, 1396 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1397 } 1383 DFG_TYPE_CHECK( 1384 JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, (~SpecCell) | SpecObject, 1385 m_jit.branchPtr( 1386 MacroAssembler::Equal, 1387 structureGPR, 1388 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1398 1389 speculationCheck(BadType, JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, 1399 1390 m_jit.branchTest8( … … 1413 1404 // We know that within this branch, rightChild must not be a cell. Check if that is enough to 1414 1405 // prove that it is either null or undefined. 1415 if ( (m_state.forNode(rightChild).m_type & ~SpecCell) & ~SpecOther) {1406 if (needsTypeCheck(rightChild, SpecCell | SpecOther)) { 1416 1407 m_jit.move(op2TagGPR, resultGPR); 1417 1408 m_jit.or32(TrustedImm32(1), resultGPR); 1418 1409 1419 speculationCheck(1420 BadType, JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild,1410 typeCheck( 1411 JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, SpecCell | SpecOther, 1421 1412 m_jit.branch32( 1422 1413 MacroAssembler::NotEqual, resultGPR, … … 1440 1431 1441 1432 SpeculateCellOperand op1(this, leftChild); 1442 JSValueOperand op2(this, rightChild );1433 JSValueOperand op2(this, rightChild, ManualOperandSpeculation); 1443 1434 GPRTemporary result(this); 1444 1435 … … 1450 1441 if (m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) { 1451 1442 m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint()); 1452 if (m_state.forNode(leftChild).m_type & ~SpecObject) { 1453 speculationCheck( 1454 BadType, JSValueSource::unboxedCell(op1GPR), leftChild, 1455 m_jit.branchPtr( 1456 MacroAssembler::Equal, 1457 MacroAssembler::Address(op1GPR, JSCell::structureOffset()), 1458 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1459 } 1443 DFG_TYPE_CHECK( 1444 JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchPtr( 1445 MacroAssembler::Equal, 1446 MacroAssembler::Address(op1GPR, JSCell::structureOffset()), 1447 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1460 1448 } else { 1461 1449 GPRTemporary structure(this); … … 1463 1451 1464 1452 m_jit.loadPtr(MacroAssembler::Address(op1GPR, JSCell::structureOffset()), structureGPR); 1465 if (m_state.forNode(leftChild).m_type & ~SpecObject) { 1466 speculationCheck( 1467 BadType, JSValueSource::unboxedCell(op1GPR), leftChild, 1468 m_jit.branchPtr( 1469 MacroAssembler::Equal, 1470 structureGPR, 1471 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1472 } 1453 DFG_TYPE_CHECK( 1454 JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchPtr( 1455 MacroAssembler::Equal, 1456 structureGPR, 1457 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1473 1458 speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), leftChild, 1474 1459 m_jit.branchTest8( … … 1486 1471 if (m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) { 1487 1472 m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint()); 1488 if ((m_state.forNode(rightChild).m_type & SpecCell) & ~SpecObject) { 1489 speculationCheck( 1490 BadType, JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, 1491 m_jit.branchPtr( 1492 MacroAssembler::Equal, 1493 MacroAssembler::Address(op2PayloadGPR, JSCell::structureOffset()), 1494 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1495 } 1473 DFG_TYPE_CHECK( 1474 JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, (~SpecCell) | SpecObject, 1475 m_jit.branchPtr( 1476 MacroAssembler::Equal, 1477 MacroAssembler::Address(op2PayloadGPR, JSCell::structureOffset()), 1478 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1496 1479 } else { 1497 1480 GPRTemporary structure(this); … … 1499 1482 1500 1483 m_jit.loadPtr(MacroAssembler::Address(op2PayloadGPR, JSCell::structureOffset()), structureGPR); 1501 if ((m_state.forNode(rightChild).m_type & SpecCell) & ~SpecObject) { 1502 speculationCheck( 1503 BadType, JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, 1504 m_jit.branchPtr( 1505 MacroAssembler::Equal, 1506 structureGPR, 1507 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1508 } 1484 DFG_TYPE_CHECK( 1485 JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, (~SpecCell) | SpecObject, 1486 m_jit.branchPtr( 1487 MacroAssembler::Equal, 1488 structureGPR, 1489 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1509 1490 speculationCheck(BadType, JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, 1510 1491 m_jit.branchTest8( … … 1521 1502 // We know that within this branch, rightChild must not be a cell. Check if that is enough to 1522 1503 // prove that it is either null or undefined. 1523 if ( (m_state.forNode(rightChild).m_type & ~SpecCell) & ~SpecOther)1504 if (!needsTypeCheck(rightChild, SpecCell | SpecOther)) 1524 1505 rightNotCell.link(&m_jit); 1525 1506 else { … … 1530 1511 m_jit.or32(TrustedImm32(1), resultGPR); 1531 1512 1532 speculationCheck(1533 BadType, JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild,1513 typeCheck( 1514 JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, SpecCell | SpecOther, 1534 1515 m_jit.branch32( 1535 1516 MacroAssembler::NotEqual, resultGPR, … … 1588 1569 } 1589 1570 1590 void SpeculativeJIT::compileObjectOrOtherLogicalNot(Edge nodeUse , bool needSpeculationCheck)1571 void SpeculativeJIT::compileObjectOrOtherLogicalNot(Edge nodeUse) 1591 1572 { 1592 JSValueOperand value(this, nodeUse );1573 JSValueOperand value(this, nodeUse, ManualOperandSpeculation); 1593 1574 GPRTemporary resultPayload(this); 1594 1575 GPRReg valueTagGPR = value.tagGPR(); … … 1600 1581 m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint()); 1601 1582 1602 if (needSpeculationCheck) { 1603 speculationCheck(BadType, JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, 1604 m_jit.branchPtr( 1605 MacroAssembler::Equal, 1606 MacroAssembler::Address(valuePayloadGPR, JSCell::structureOffset()), 1607 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1608 } 1583 DFG_TYPE_CHECK( 1584 JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, (~SpecCell) | SpecObject, 1585 m_jit.branchPtr( 1586 MacroAssembler::Equal, 1587 MacroAssembler::Address(valuePayloadGPR, JSCell::structureOffset()), 1588 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1609 1589 } else { 1610 1590 GPRTemporary structure(this); … … 1613 1593 m_jit.loadPtr(MacroAssembler::Address(valuePayloadGPR, JSCell::structureOffset()), structureGPR); 1614 1594 1615 if (needSpeculationCheck) { 1616 speculationCheck(BadType, JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, 1617 m_jit.branchPtr( 1618 MacroAssembler::Equal, 1619 structureGPR, 1620 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1621 } 1595 DFG_TYPE_CHECK( 1596 JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, (~SpecCell) | SpecObject, 1597 m_jit.branchPtr( 1598 MacroAssembler::Equal, 1599 structureGPR, 1600 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1622 1601 1623 1602 MacroAssembler::Jump isNotMasqueradesAsUndefined = … … 1641 1620 1642 1621 COMPILE_ASSERT((JSValue::UndefinedTag | 1) == JSValue::NullTag, UndefinedTag_OR_1_EQUALS_NullTag); 1643 if (need SpeculationCheck) {1622 if (needsTypeCheck(nodeUse, SpecCell | SpecOther)) { 1644 1623 m_jit.move(valueTagGPR, resultPayloadGPR); 1645 1624 m_jit.or32(TrustedImm32(1), resultPayloadGPR); 1646 speculationCheck(BadType, JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, 1625 typeCheck( 1626 JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, SpecCell | SpecOther, 1647 1627 m_jit.branch32( 1648 1628 MacroAssembler::NotEqual, … … 1659 1639 void SpeculativeJIT::compileLogicalNot(Node* node) 1660 1640 { 1661 if (node->child1()->shouldSpeculateBoolean()) { 1641 switch (node->child1().useKind()) { 1642 case BooleanUse: { 1662 1643 SpeculateBooleanOperand value(this, node->child1()); 1663 1644 GPRTemporary result(this, value); … … 1666 1647 return; 1667 1648 } 1668 if (node->child1()->shouldSpeculateObjectOrOther()) {1669 compileObjectOrOtherLogicalNot(node->child1(),1670 !isObjectOrOtherSpeculation(m_state.forNode(node->child1()).m_type));1649 1650 case ObjectOrOtherUse: { 1651 compileObjectOrOtherLogicalNot(node->child1()); 1671 1652 return; 1672 1653 } 1673 if (node->child1()->shouldSpeculateInteger()) { 1654 1655 case Int32Use: { 1674 1656 SpeculateIntegerOperand value(this, node->child1()); 1675 1657 GPRTemporary resultPayload(this, value); … … 1678 1660 return; 1679 1661 } 1680 if (node->child1()->shouldSpeculateNumber()) { 1662 1663 case NumberUse: { 1681 1664 SpeculateDoubleOperand value(this, node->child1()); 1682 1665 FPRTemporary scratch(this); … … 1690 1673 } 1691 1674 1692 JSValueOperand arg1(this, node->child1()); 1693 GPRTemporary resultPayload(this, arg1, false); 1694 GPRReg arg1TagGPR = arg1.tagGPR(); 1695 GPRReg arg1PayloadGPR = arg1.payloadGPR(); 1696 GPRReg resultPayloadGPR = resultPayload.gpr(); 1697 1698 arg1.use(); 1699 1700 JITCompiler::Jump slowCase = m_jit.branch32(JITCompiler::NotEqual, arg1TagGPR, TrustedImm32(JSValue::BooleanTag)); 1701 1702 m_jit.move(arg1PayloadGPR, resultPayloadGPR); 1703 1704 addSlowPathGenerator( 1705 slowPathCall( 1706 slowCase, this, dfgConvertJSValueToBoolean, resultPayloadGPR, arg1TagGPR, 1707 arg1PayloadGPR)); 1708 1709 m_jit.xor32(TrustedImm32(1), resultPayloadGPR); 1710 booleanResult(resultPayloadGPR, node, UseChildrenCalledExplicitly); 1675 case UntypedUse: { 1676 JSValueOperand arg1(this, node->child1()); 1677 GPRTemporary resultPayload(this, arg1, false); 1678 GPRReg arg1TagGPR = arg1.tagGPR(); 1679 GPRReg arg1PayloadGPR = arg1.payloadGPR(); 1680 GPRReg resultPayloadGPR = resultPayload.gpr(); 1681 1682 arg1.use(); 1683 1684 JITCompiler::Jump slowCase = m_jit.branch32(JITCompiler::NotEqual, arg1TagGPR, TrustedImm32(JSValue::BooleanTag)); 1685 1686 m_jit.move(arg1PayloadGPR, resultPayloadGPR); 1687 1688 addSlowPathGenerator( 1689 slowPathCall( 1690 slowCase, this, dfgConvertJSValueToBoolean, resultPayloadGPR, arg1TagGPR, 1691 arg1PayloadGPR)); 1692 1693 m_jit.xor32(TrustedImm32(1), resultPayloadGPR); 1694 booleanResult(resultPayloadGPR, node, UseChildrenCalledExplicitly); 1695 return; 1696 } 1697 1698 default: 1699 RELEASE_ASSERT_NOT_REACHED(); 1700 break; 1701 } 1711 1702 } 1712 1703 1713 void SpeculativeJIT::emitObjectOrOtherBranch(Edge nodeUse, BlockIndex taken, BlockIndex notTaken , bool needSpeculationCheck)1704 void SpeculativeJIT::emitObjectOrOtherBranch(Edge nodeUse, BlockIndex taken, BlockIndex notTaken) 1714 1705 { 1715 JSValueOperand value(this, nodeUse );1706 JSValueOperand value(this, nodeUse, ManualOperandSpeculation); 1716 1707 GPRTemporary scratch(this); 1717 1708 GPRReg valueTagGPR = value.tagGPR(); … … 1723 1714 m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint()); 1724 1715 1725 if (needSpeculationCheck) { 1726 speculationCheck(BadType, JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, 1727 m_jit.branchPtr( 1728 MacroAssembler::Equal, 1729 MacroAssembler::Address(valuePayloadGPR, JSCell::structureOffset()), 1730 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1731 } 1716 DFG_TYPE_CHECK( 1717 JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, (~SpecCell) | SpecObject, 1718 m_jit.branchPtr( 1719 MacroAssembler::Equal, 1720 MacroAssembler::Address(valuePayloadGPR, JSCell::structureOffset()), 1721 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1732 1722 } else { 1733 1723 m_jit.loadPtr(MacroAssembler::Address(valuePayloadGPR, JSCell::structureOffset()), scratchGPR); 1734 1724 1735 if (needSpeculationCheck) { 1736 speculationCheck(BadType, JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, 1737 m_jit.branchPtr( 1738 MacroAssembler::Equal, 1739 scratchGPR, 1740 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1741 } 1725 DFG_TYPE_CHECK( 1726 JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, (~SpecCell) | SpecObject, 1727 m_jit.branchPtr( 1728 MacroAssembler::Equal, 1729 scratchGPR, 1730 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1742 1731 1743 1732 JITCompiler::Jump isNotMasqueradesAsUndefined = m_jit.branchTest8(JITCompiler::Zero, MacroAssembler::Address(scratchGPR, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined)); … … 1756 1745 1757 1746 COMPILE_ASSERT((JSValue::UndefinedTag | 1) == JSValue::NullTag, UndefinedTag_OR_1_EQUALS_NullTag); 1758 if (need SpeculationCheck) {1747 if (needsTypeCheck(nodeUse, SpecCell | SpecOther)) { 1759 1748 m_jit.move(valueTagGPR, scratchGPR); 1760 1749 m_jit.or32(TrustedImm32(1), scratchGPR); 1761 speculationCheck(BadType, JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, m_jit.branch32(MacroAssembler::NotEqual, scratchGPR, TrustedImm32(JSValue::NullTag))); 1750 typeCheck( 1751 JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, SpecCell | SpecOther, 1752 m_jit.branch32(MacroAssembler::NotEqual, scratchGPR, TrustedImm32(JSValue::NullTag))); 1762 1753 } 1763 1754 … … 1772 1763 BlockIndex notTaken = node->notTakenBlockIndex(); 1773 1764 1774 if (node->shouldSpeculateBoolean()) { 1765 switch (node->child1().useKind()) { 1766 case BooleanUse: { 1775 1767 SpeculateBooleanOperand value(this, node->child1()); 1776 1768 MacroAssembler::ResultCondition condition = MacroAssembler::NonZero; … … 1790 1782 } 1791 1783 1792 if (node->child1()->shouldSpeculateObjectOrOther()) { 1793 emitObjectOrOtherBranch(node->child1(), taken, notTaken, 1794 !isObjectOrOtherSpeculation(m_state.forNode(node->child1()).m_type)); 1784 case ObjectOrOtherUse: { 1785 emitObjectOrOtherBranch(node->child1(), taken, notTaken); 1795 1786 return; 1796 1787 } 1797 1788 1798 if (node->child1()->shouldSpeculateNumber()) { 1799 if (node->child1()->shouldSpeculateInteger()) { 1789 case NumberUse: 1790 case Int32Use: { 1791 if (node->child1().useKind() == Int32Use) { 1800 1792 bool invert = false; 1801 1793 … … 1821 1813 } 1822 1814 1823 JSValueOperand value(this, node->child1()); 1824 value.fill(); 1825 GPRReg valueTagGPR = value.tagGPR(); 1826 GPRReg valuePayloadGPR = value.payloadGPR(); 1827 1828 GPRTemporary result(this); 1829 GPRReg resultGPR = result.gpr(); 1830 1831 use(node->child1()); 1832 1833 JITCompiler::Jump fastPath = m_jit.branch32(JITCompiler::Equal, valueTagGPR, JITCompiler::TrustedImm32(JSValue::Int32Tag)); 1834 JITCompiler::Jump slowPath = m_jit.branch32(JITCompiler::NotEqual, valueTagGPR, JITCompiler::TrustedImm32(JSValue::BooleanTag)); 1835 1836 fastPath.link(&m_jit); 1837 branchTest32(JITCompiler::Zero, valuePayloadGPR, notTaken); 1838 jump(taken, ForceJump); 1839 1840 slowPath.link(&m_jit); 1841 silentSpillAllRegisters(resultGPR); 1842 callOperation(dfgConvertJSValueToBoolean, resultGPR, valueTagGPR, valuePayloadGPR); 1843 silentFillAllRegisters(resultGPR); 1844 1845 branchTest32(JITCompiler::NonZero, resultGPR, taken); 1846 jump(notTaken); 1847 1848 noResult(node, UseChildrenCalledExplicitly); 1815 case UntypedUse: { 1816 JSValueOperand value(this, node->child1()); 1817 value.fill(); 1818 GPRReg valueTagGPR = value.tagGPR(); 1819 GPRReg valuePayloadGPR = value.payloadGPR(); 1820 1821 GPRTemporary result(this); 1822 GPRReg resultGPR = result.gpr(); 1823 1824 use(node->child1()); 1825 1826 JITCompiler::Jump fastPath = m_jit.branch32(JITCompiler::Equal, valueTagGPR, JITCompiler::TrustedImm32(JSValue::Int32Tag)); 1827 JITCompiler::Jump slowPath = m_jit.branch32(JITCompiler::NotEqual, valueTagGPR, JITCompiler::TrustedImm32(JSValue::BooleanTag)); 1828 1829 fastPath.link(&m_jit); 1830 branchTest32(JITCompiler::Zero, valuePayloadGPR, notTaken); 1831 jump(taken, ForceJump); 1832 1833 slowPath.link(&m_jit); 1834 silentSpillAllRegisters(resultGPR); 1835 callOperation(dfgConvertJSValueToBoolean, resultGPR, valueTagGPR, valuePayloadGPR); 1836 silentFillAllRegisters(resultGPR); 1837 1838 branchTest32(JITCompiler::NonZero, resultGPR, taken); 1839 jump(notTaken); 1840 1841 noResult(node, UseChildrenCalledExplicitly); 1842 return; 1843 } 1844 1845 default: 1846 RELEASE_ASSERT_NOT_REACHED(); 1847 break; 1848 } 1849 1849 } 1850 1850 … … 1931 1931 1932 1932 case Identity: { 1933 // This could be done a lot better. We take the cheap way out because Identity 1934 // is only going to stick around after CSE if we had prediction weirdness. 1935 JSValueOperand operand(this, node->child1()); 1936 GPRTemporary resultTag(this); 1937 GPRTemporary resultPayload(this); 1938 m_jit.move(operand.tagGPR(), resultTag.gpr()); 1939 m_jit.move(operand.payloadGPR(), resultPayload.gpr()); 1940 jsValueResult(resultTag.gpr(), resultPayload.gpr(), node); 1933 RELEASE_ASSERT_NOT_REACHED(); 1941 1934 break; 1942 1935 } … … 1956 1949 // cannot have been assigned, then don't attempt to proceed. 1957 1950 if (value.isClear()) { 1951 // FIXME: We should trap instead. 1952 // https://bugs.webkit.org/show_bug.cgi?id=110383 1958 1953 terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0); 1959 1954 break; … … 2056 2051 SpeculatedType predictedType = node->variableAccessData()->argumentAwarePrediction(); 2057 2052 if (m_generationInfo[node->child1()->virtualRegister()].registerFormat() == DataFormatDouble) { 2058 SpeculateDoubleOperand value(this, Edge(node->child1().node(), DoubleUse));2053 SpeculateDoubleOperand value(this, node->child1(), BackwardSpeculation, ManualOperandSpeculation); 2059 2054 m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node->local())); 2060 2055 noResult(node); … … 2184 2179 } 2185 2180 2186 case CheckNumber: {2187 if (!isNumberSpeculation(m_state.forNode(node->child1()).m_type)) {2188 JSValueOperand op1(this, node->child1());2189 JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, op1.tagGPR(), TrustedImm32(JSValue::Int32Tag));2190 speculationCheck(2191 BadType, JSValueRegs(op1.tagGPR(), op1.payloadGPR()), node->child1(),2192 m_jit.branch32(MacroAssembler::AboveOrEqual, op1.tagGPR(), TrustedImm32(JSValue::LowestTag)));2193 isInteger.link(&m_jit);2194 }2195 noResult(node);2196 break;2197 }2198 2199 2181 case ValueAdd: 2200 2182 case ArithAdd: … … 2215 2197 2216 2198 case ArithDiv: { 2217 if (Node::shouldSpeculateIntegerForArithmetic(node->child1().node(), node->child2().node())2218 && node->canSpeculateInteger()){2199 switch (node->binaryUseKind()) { 2200 case Int32Use: { 2219 2201 #if CPU(X86) 2220 2202 compileIntegerArithDivForX86(node); … … 2226 2208 break; 2227 2209 } 2228 2229 SpeculateDoubleOperand op1(this, node->child1()); 2230 SpeculateDoubleOperand op2(this, node->child2()); 2231 FPRTemporary result(this, op1); 2232 2233 FPRReg reg1 = op1.fpr(); 2234 FPRReg reg2 = op2.fpr(); 2235 m_jit.divDouble(reg1, reg2, result.fpr()); 2236 2237 doubleResult(result.fpr(), node); 2210 2211 case NumberUse: { 2212 SpeculateDoubleOperand op1(this, node->child1()); 2213 SpeculateDoubleOperand op2(this, node->child2()); 2214 FPRTemporary result(this, op1); 2215 2216 FPRReg reg1 = op1.fpr(); 2217 FPRReg reg2 = op2.fpr(); 2218 m_jit.divDouble(reg1, reg2, result.fpr()); 2219 2220 doubleResult(result.fpr(), node); 2221 break; 2222 } 2223 2224 default: 2225 RELEASE_ASSERT_NOT_REACHED(); 2226 break; 2227 } 2238 2228 break; 2239 2229 } … … 2245 2235 2246 2236 case ArithAbs: { 2247 if (node->child1()->shouldSpeculateIntegerForArithmetic()2248 && node->canSpeculateInteger()){2237 switch (node->child1().useKind()) { 2238 case Int32Use: { 2249 2239 SpeculateIntegerOperand op1(this, node->child1()); 2250 2240 GPRTemporary result(this, op1); … … 2260 2250 } 2261 2251 2262 SpeculateDoubleOperand op1(this, node->child1()); 2263 FPRTemporary result(this); 2264 2265 m_jit.absDouble(op1.fpr(), result.fpr()); 2266 doubleResult(result.fpr(), node); 2252 2253 case NumberUse: { 2254 SpeculateDoubleOperand op1(this, node->child1()); 2255 FPRTemporary result(this); 2256 2257 m_jit.absDouble(op1.fpr(), result.fpr()); 2258 doubleResult(result.fpr(), node); 2259 break; 2260 } 2261 2262 default: 2263 RELEASE_ASSERT_NOT_REACHED(); 2264 break; 2265 } 2267 2266 break; 2268 2267 } … … 2270 2269 case ArithMin: 2271 2270 case ArithMax: { 2272 if (Node::shouldSpeculateIntegerForArithmetic(node->child1().node(), node->child2().node())2273 && node->canSpeculateInteger()){2271 switch (node->binaryUseKind()) { 2272 case Int32Use: { 2274 2273 SpeculateStrictInt32Operand op1(this, node->child1()); 2275 2274 SpeculateStrictInt32Operand op2(this, node->child2()); … … 2290 2289 } 2291 2290 2292 SpeculateDoubleOperand op1(this, node->child1()); 2293 SpeculateDoubleOperand op2(this, node->child2()); 2294 FPRTemporary result(this, op1); 2295 2296 MacroAssembler::JumpList done; 2297 2298 MacroAssembler::Jump op1Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleLessThan : MacroAssembler::DoubleGreaterThan, op1.fpr(), op2.fpr()); 2299 2300 // op2 is eather the lesser one or one of then is NaN 2301 MacroAssembler::Jump op2Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleGreaterThanOrEqual : MacroAssembler::DoubleLessThanOrEqual, op1.fpr(), op2.fpr()); 2302 2303 // Unordered case. We don't know which of op1, op2 is NaN. Manufacture NaN by adding 2304 // op1 + op2 and putting it into result. 2305 m_jit.addDouble(op1.fpr(), op2.fpr(), result.fpr()); 2306 done.append(m_jit.jump()); 2307 2308 op2Less.link(&m_jit); 2309 m_jit.moveDouble(op2.fpr(), result.fpr()); 2310 2311 if (op1.fpr() != result.fpr()) { 2291 case NumberUse: { 2292 SpeculateDoubleOperand op1(this, node->child1()); 2293 SpeculateDoubleOperand op2(this, node->child2()); 2294 FPRTemporary result(this, op1); 2295 2296 MacroAssembler::JumpList done; 2297 2298 MacroAssembler::Jump op1Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleLessThan : MacroAssembler::DoubleGreaterThan, op1.fpr(), op2.fpr()); 2299 2300 // op2 is eather the lesser one or one of then is NaN 2301 MacroAssembler::Jump op2Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleGreaterThanOrEqual : MacroAssembler::DoubleLessThanOrEqual, op1.fpr(), op2.fpr()); 2302 2303 // Unordered case. We don't know which of op1, op2 is NaN. Manufacture NaN by adding 2304 // op1 + op2 and putting it into result. 2305 m_jit.addDouble(op1.fpr(), op2.fpr(), result.fpr()); 2312 2306 done.append(m_jit.jump()); 2313 2314 op1Less.link(&m_jit); 2315 m_jit.moveDouble(op1.fpr(), result.fpr()); 2316 } else 2317 op1Less.link(&m_jit); 2318 2319 done.link(&m_jit); 2320 2321 doubleResult(result.fpr(), node); 2307 2308 op2Less.link(&m_jit); 2309 m_jit.moveDouble(op2.fpr(), result.fpr()); 2310 2311 if (op1.fpr() != result.fpr()) { 2312 done.append(m_jit.jump()); 2313 2314 op1Less.link(&m_jit); 2315 m_jit.moveDouble(op1.fpr(), result.fpr()); 2316 } else 2317 op1Less.link(&m_jit); 2318 2319 done.link(&m_jit); 2320 2321 doubleResult(result.fpr(), node); 2322 break; 2323 } 2324 2325 default: 2326 RELEASE_ASSERT_NOT_REACHED(); 2327 break; 2328 } 2322 2329 break; 2323 2330 } … … 2982 2989 FPRReg valueFPR = value.fpr(); 2983 2990 2984 if (!isRealNumberSpeculation(m_state.forNode(node->child2()).m_type)) { 2985 // FIXME: We need a way of profiling these, and we need to hoist them into 2986 // SpeculateDoubleOperand. 2987 speculationCheck( 2988 BadType, JSValueRegs(), 0, 2989 m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, valueFPR, valueFPR)); 2990 } 2991 DFG_TYPE_CHECK( 2992 JSValueRegs(), node->child2(), SpecRealNumber, 2993 m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, valueFPR, valueFPR)); 2991 2994 2992 2995 m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR); … … 3236 3239 3237 3240 case ToPrimitive: { 3238 if (node->child1()->shouldSpeculateInteger()) { 3241 switch (node->child1().useKind()) { 3242 case Int32Use: { 3239 3243 // It's really profitable to speculate integer, since it's really cheap, 3240 3244 // it means we don't have to do any real work, and we emit a lot less code. … … 3249 3253 break; 3250 3254 } 3251 3252 // FIXME: Add string speculation here. 3253 3254 JSValueOperand op1(this, node->child1()); 3255 GPRTemporary resultTag(this, op1); 3256 GPRTemporary resultPayload(this, op1, false); 3257 3258 GPRReg op1TagGPR = op1.tagGPR(); 3259 GPRReg op1PayloadGPR = op1.payloadGPR(); 3260 GPRReg resultTagGPR = resultTag.gpr(); 3261 GPRReg resultPayloadGPR = resultPayload.gpr(); 3262 3263 op1.use(); 3264 3265 if (!(m_state.forNode(node->child1()).m_type & ~(SpecNumber | SpecBoolean))) { 3266 m_jit.move(op1TagGPR, resultTagGPR); 3267 m_jit.move(op1PayloadGPR, resultPayloadGPR); 3268 } else { 3269 MacroAssembler::Jump alreadyPrimitive = m_jit.branch32(MacroAssembler::NotEqual, op1TagGPR, TrustedImm32(JSValue::CellTag)); 3270 MacroAssembler::Jump notPrimitive = m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1PayloadGPR, JSCell::structureOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())); 3271 3272 alreadyPrimitive.link(&m_jit); 3273 m_jit.move(op1TagGPR, resultTagGPR); 3274 m_jit.move(op1PayloadGPR, resultPayloadGPR); 3275 3276 addSlowPathGenerator( 3277 slowPathCall( 3278 notPrimitive, this, operationToPrimitive, 3279 JSValueRegs(resultTagGPR, resultPayloadGPR), op1TagGPR, op1PayloadGPR)); 3280 } 3281 3282 jsValueResult(resultTagGPR, resultPayloadGPR, node, UseChildrenCalledExplicitly); 3255 3256 case UntypedUse: { 3257 JSValueOperand op1(this, node->child1()); 3258 GPRTemporary resultTag(this, op1); 3259 GPRTemporary resultPayload(this, op1, false); 3260 3261 GPRReg op1TagGPR = op1.tagGPR(); 3262 GPRReg op1PayloadGPR = op1.payloadGPR(); 3263 GPRReg resultTagGPR = resultTag.gpr(); 3264 GPRReg resultPayloadGPR = resultPayload.gpr(); 3265 3266 op1.use(); 3267 3268 if (!(m_state.forNode(node->child1()).m_type & ~(SpecNumber | SpecBoolean))) { 3269 m_jit.move(op1TagGPR, resultTagGPR); 3270 m_jit.move(op1PayloadGPR, resultPayloadGPR); 3271 } else { 3272 MacroAssembler::Jump alreadyPrimitive = m_jit.branch32(MacroAssembler::NotEqual, op1TagGPR, TrustedImm32(JSValue::CellTag)); 3273 MacroAssembler::Jump notPrimitive = m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1PayloadGPR, JSCell::structureOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())); 3274 3275 alreadyPrimitive.link(&m_jit); 3276 m_jit.move(op1TagGPR, resultTagGPR); 3277 m_jit.move(op1PayloadGPR, resultPayloadGPR); 3278 3279 addSlowPathGenerator( 3280 slowPathCall( 3281 notPrimitive, this, operationToPrimitive, 3282 JSValueRegs(resultTagGPR, resultPayloadGPR), op1TagGPR, op1PayloadGPR)); 3283 } 3284 3285 jsValueResult(resultTagGPR, resultPayloadGPR, node, UseChildrenCalledExplicitly); 3286 break; 3287 } 3288 3289 default: 3290 RELEASE_ASSERT_NOT_REACHED(); 3291 break; 3292 } 3283 3293 break; 3284 3294 } … … 3364 3374 SpeculateDoubleOperand operand(this, use); 3365 3375 FPRReg opFPR = operand.fpr(); 3366 if (!isRealNumberSpeculation(m_state.forNode(use).m_type)) { 3367 // FIXME: We need a way of profiling these, and we need to hoist them into 3368 // SpeculateDoubleOperand. 3369 speculationCheck( 3370 BadType, JSValueRegs(), 0, 3371 m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, opFPR, opFPR)); 3372 } 3376 DFG_TYPE_CHECK( 3377 JSValueRegs(), use, SpecRealNumber, 3378 m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, opFPR, opFPR)); 3373 3379 3374 3380 m_jit.storeDouble(opFPR, MacroAssembler::Address(storageGPR, sizeof(double) * operandIdx)); … … 3433 3439 SpeculateDoubleOperand operand(this, use); 3434 3440 FPRReg opFPR = operand.fpr(); 3435 if (!isRealNumberSpeculation(m_state.forNode(use).m_type)) { 3436 // FIXME: We need a way of profiling these, and we need to hoist them into 3437 // SpeculateDoubleOperand. 3438 speculationCheck( 3439 BadType, JSValueRegs(), 0, 3440 m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, opFPR, opFPR)); 3441 } 3441 DFG_TYPE_CHECK( 3442 JSValueRegs(), use, SpecRealNumber, 3443 m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, opFPR, opFPR)); 3442 3444 3443 3445 m_jit.storeDouble(opFPR, reinterpret_cast<char*>(buffer + operandIdx)); … … 3640 3642 3641 3643 case ConvertThis: { 3642 if (isObjectSpeculation(m_state.forNode(node->child1()).m_type)) { 3643 SpeculateCellOperand thisValue(this, node->child1()); 3644 GPRTemporary result(this, thisValue); 3645 m_jit.move(thisValue.gpr(), result.gpr()); 3646 cellResult(result.gpr(), node); 3647 break; 3648 } 3649 3650 if (isOtherSpeculation(node->child1()->prediction())) { 3651 JSValueOperand thisValue(this, node->child1()); 3644 switch (node->child1().useKind()) { 3645 case OtherUse: { 3646 JSValueOperand thisValue(this, node->child1(), ManualOperandSpeculation); 3652 3647 GPRTemporary scratch(this); 3653 3648 … … 3656 3651 3657 3652 COMPILE_ASSERT((JSValue::UndefinedTag | 1) == JSValue::NullTag, UndefinedTag_OR_1_EQUALS_NullTag); 3658 m_jit.move(thisValueTagGPR, scratchGPR); 3659 m_jit.or32(TrustedImm32(1), scratchGPR); 3660 // This is hard. It would be better to save the value, but we can't quite do it, 3661 // since this operation does not otherwise get the payload. 3662 speculationCheck(BadType, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::NotEqual, scratchGPR, TrustedImm32(JSValue::NullTag))); 3653 if (needsTypeCheck(node->child1(), SpecOther)) { 3654 m_jit.move(thisValueTagGPR, scratchGPR); 3655 m_jit.or32(TrustedImm32(1), scratchGPR); 3656 // This is hard. It would be better to save the value, but we can't quite do it, 3657 // since this operation does not otherwise get the payload. 3658 typeCheck( 3659 JSValueRegs(), node->child1(), SpecOther, 3660 m_jit.branch32( 3661 MacroAssembler::NotEqual, scratchGPR, TrustedImm32(JSValue::NullTag))); 3662 } 3663 3663 3664 3664 m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.globalThisObjectFor(node->codeOrigin)), scratchGPR); … … 3667 3667 } 3668 3668 3669 if (isObjectSpeculation(node->child1()->prediction())){3669 case ObjectUse: { 3670 3670 SpeculateCellOperand thisValue(this, node->child1()); 3671 3671 GPRReg thisValueGPR = thisValue.gpr(); 3672 3672 3673 if (!isObjectSpeculation(m_state.forNode(node->child1()).m_type)) 3674 speculationCheck(BadType, JSValueSource::unboxedCell(thisValueGPR), node->child1(), m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(thisValueGPR, JSCell::structureOffset()), JITCompiler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 3673 DFG_TYPE_CHECK( 3674 JSValueSource::unboxedCell(thisValueGPR), node->child1(), SpecObject, 3675 m_jit.branchPtr( 3676 JITCompiler::Equal, 3677 JITCompiler::Address(thisValueGPR, JSCell::structureOffset()), 3678 JITCompiler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 3675 3679 3676 3680 GPRTemporary result(this, thisValue); … … 3681 3685 } 3682 3686 3683 JSValueOperand thisValue(this, node->child1()); 3684 GPRReg thisValueTagGPR = thisValue.tagGPR(); 3685 GPRReg thisValuePayloadGPR = thisValue.payloadGPR(); 3686 3687 flushRegisters(); 3688 3689 GPRResult2 resultTag(this); 3690 GPRResult resultPayload(this); 3691 callOperation(operationConvertThis, resultTag.gpr(), resultPayload.gpr(), thisValueTagGPR, thisValuePayloadGPR); 3692 3693 cellResult(resultPayload.gpr(), node); 3687 case UntypedUse: { 3688 JSValueOperand thisValue(this, node->child1()); 3689 GPRReg thisValueTagGPR = thisValue.tagGPR(); 3690 GPRReg thisValuePayloadGPR = thisValue.payloadGPR(); 3691 3692 flushRegisters(); 3693 3694 GPRResult2 resultTag(this); 3695 GPRResult resultPayload(this); 3696 callOperation(operationConvertThis, resultTag.gpr(), resultPayload.gpr(), thisValueTagGPR, thisValuePayloadGPR); 3697 3698 cellResult(resultPayload.gpr(), node); 3699 break; 3700 } 3701 3702 default: 3703 RELEASE_ASSERT_NOT_REACHED(); 3704 break; 3705 } 3694 3706 break; 3695 3707 } … … 3907 3919 } 3908 3920 3909 if (isCellSpeculation(node->child1()->prediction())) { 3921 switch (node->child1().useKind()) { 3922 case CellUse: { 3910 3923 SpeculateCellOperand base(this, node->child1()); 3911 3924 … … 3927 3940 } 3928 3941 3929 JSValueOperand base(this, node->child1()); 3930 GPRReg baseTagGPR = base.tagGPR(); 3931 GPRReg basePayloadGPR = base.payloadGPR(); 3932 3933 GPRResult resultTag(this); 3934 GPRResult2 resultPayload(this); 3935 GPRReg resultTagGPR = resultTag.gpr(); 3936 GPRReg resultPayloadGPR = resultPayload.gpr(); 3937 3938 base.use(); 3939 3940 flushRegisters(); 3941 3942 JITCompiler::Jump notCell = m_jit.branch32(JITCompiler::NotEqual, baseTagGPR, TrustedImm32(JSValue::CellTag)); 3943 3944 cachedGetById(node->codeOrigin, baseTagGPR, basePayloadGPR, resultTagGPR, resultPayloadGPR, node->identifierNumber(), notCell, DontSpill); 3945 3946 jsValueResult(resultTagGPR, resultPayloadGPR, node, UseChildrenCalledExplicitly); 3942 case UntypedUse: { 3943 JSValueOperand base(this, node->child1()); 3944 GPRReg baseTagGPR = base.tagGPR(); 3945 GPRReg basePayloadGPR = base.payloadGPR(); 3946 3947 GPRResult resultTag(this); 3948 GPRResult2 resultPayload(this); 3949 GPRReg resultTagGPR = resultTag.gpr(); 3950 GPRReg resultPayloadGPR = resultPayload.gpr(); 3951 3952 base.use(); 3953 3954 flushRegisters(); 3955 3956 JITCompiler::Jump notCell = m_jit.branch32(JITCompiler::NotEqual, baseTagGPR, TrustedImm32(JSValue::CellTag)); 3957 3958 cachedGetById(node->codeOrigin, baseTagGPR, basePayloadGPR, resultTagGPR, resultPayloadGPR, node->identifierNumber(), notCell, DontSpill); 3959 3960 jsValueResult(resultTagGPR, resultPayloadGPR, node, UseChildrenCalledExplicitly); 3961 break; 3962 } 3963 3964 default: 3965 RELEASE_ASSERT_NOT_REACHED(); 3966 break; 3967 } 3947 3968 break; 3948 3969 } … … 3968 3989 case CheckStructure: 3969 3990 case ForwardCheckStructure: { 3970 AbstractValue& value = m_state.forNode(node->child1());3971 if (value.m_currentKnownStructure.isSubsetOf(node->structureSet())3972 && isCellSpeculation(value.m_type)) {3973 noResult(node);3974 break;3975 }3976 3977 3991 SpeculationDirection direction = node->op() == ForwardCheckStructure ? ForwardSpeculation : BackwardSpeculation; 3978 3992 SpeculateCellOperand base(this, node->child1(), direction); … … 4033 4047 m_jit.breakpoint(); 4034 4048 isOK.link(&m_jit); 4049 #else 4050 speculaceCell(node->child1()); 4035 4051 #endif 4036 4052 … … 4040 4056 4041 4057 case PhantomPutStructure: { 4058 ASSERT(isKnownCell(node->child1().node())); 4042 4059 ASSERT(node->structureTransitionData().previousStructure->transitionWatchpointSetHasBeenInvalidated()); 4043 4060 m_jit.addWeakReferenceTransition( … … 4391 4408 flushRegisters(); 4392 4409 4410 ASSERT(node->child1().useKind() == UntypedUse || node->child1().useKind() == CellUse || node->child1().useKind() == StringUse); 4411 4393 4412 JITCompiler::Jump isNotCell = m_jit.branch32(JITCompiler::NotEqual, tagGPR, JITCompiler::TrustedImm32(JSValue::CellTag)); 4394 if (node->child1() ->shouldSpeculateCell())4413 if (node->child1().useKind() != UntypedUse) 4395 4414 speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), node->child1(), isNotCell); 4396 4415 4397 if (!node->child1()->shouldSpeculateObject() ) {4416 if (!node->child1()->shouldSpeculateObject() || node->child1().useKind() == StringUse) { 4398 4417 m_jit.loadPtr(JITCompiler::Address(payloadGPR, JSCell::structureOffset()), tempGPR); 4399 4418 JITCompiler::Jump notString = m_jit.branch8(JITCompiler::NotEqual, JITCompiler::Address(tempGPR, Structure::typeInfoTypeOffset()), TrustedImm32(StringType)); 4400 if (node->child1() ->shouldSpeculateString())4401 speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), node->child1(), notString);4419 if (node->child1().useKind() == StringUse) 4420 DFG_TYPE_CHECK(JSValueRegs(tagGPR, payloadGPR), node->child1(), SpecString, notString); 4402 4421 m_jit.move(TrustedImmPtr(m_jit.globalData()->smallStrings.stringString()), resultGPR); 4403 4422 doneJumps.append(m_jit.jump()); 4404 if ( !node->child1()->shouldSpeculateString()) {4423 if (node->child1().useKind() != StringUse) { 4405 4424 notString.link(&m_jit); 4406 4425 callOperation(operationTypeOf, resultGPR, payloadGPR); … … 4412 4431 } 4413 4432 4414 if ( !node->child1()->shouldSpeculateCell()) {4433 if (node->child1().useKind() == UntypedUse) { 4415 4434 isNotCell.link(&m_jit); 4416 4435 … … 4929 4948 4930 4949 case Phantom: 4950 DFG_NODE_DO_TO_CHILDREN(m_jit.graph(), node, speculate); 4951 noResult(node); 4952 break; 4953 4931 4954 case PhantomLocal: 4932 4955 // This is a no-op. -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r143276 r143654 40 40 #if USE(JSVALUE64) 41 41 42 GPRReg SpeculativeJIT::fillInteger( Node* node, DataFormat& returnFormat)42 GPRReg SpeculativeJIT::fillInteger(Edge edge, DataFormat& returnFormat) 43 43 { 44 VirtualRegister virtualRegister = node->virtualRegister(); 44 ASSERT(!needsTypeCheck(edge, SpecInt32)); 45 46 VirtualRegister virtualRegister = edge->virtualRegister(); 45 47 GenerationInfo& info = m_generationInfo[virtualRegister]; 46 48 … … 48 50 GPRReg gpr = allocate(); 49 51 50 if ( node->hasConstant()) {52 if (edge->hasConstant()) { 51 53 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); 52 if (isInt32Constant( node)) {53 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant( node)), gpr);54 if (isInt32Constant(edge.node())) { 55 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(edge.node())), gpr); 54 56 info.fillInteger(*m_stream, gpr); 55 57 returnFormat = DataFormatInteger; 56 58 return gpr; 57 59 } 58 if (isNumberConstant( node)) {59 JSValue jsValue = jsNumber(valueOfNumberConstant( node));60 if (isNumberConstant(edge.node())) { 61 JSValue jsValue = jsNumber(valueOfNumberConstant(edge.node())); 60 62 m_jit.move(MacroAssembler::Imm64(JSValue::encode(jsValue)), gpr); 61 63 } else { 62 ASSERT(isJSConstant( node));63 JSValue jsValue = valueOfJSConstant( node);64 ASSERT(isJSConstant(edge.node())); 65 JSValue jsValue = valueOfJSConstant(edge.node()); 64 66 m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsValue)), gpr); 65 67 } … … 118 120 } 119 121 120 GPRReg SpeculativeJIT::fillJSValue( Node* node)122 GPRReg SpeculativeJIT::fillJSValue(Edge edge) 121 123 { 122 VirtualRegister virtualRegister = node->virtualRegister();124 VirtualRegister virtualRegister = edge->virtualRegister(); 123 125 GenerationInfo& info = m_generationInfo[virtualRegister]; 124 126 … … 127 129 GPRReg gpr = allocate(); 128 130 129 if ( node->hasConstant()) {130 if (isInt32Constant( node)) {131 if (edge->hasConstant()) { 132 if (isInt32Constant(edge.node())) { 131 133 info.fillJSValue(*m_stream, gpr, DataFormatJSInteger); 132 JSValue jsValue = jsNumber(valueOfInt32Constant( node));134 JSValue jsValue = jsNumber(valueOfInt32Constant(edge.node())); 133 135 m_jit.move(MacroAssembler::Imm64(JSValue::encode(jsValue)), gpr); 134 } else if (isNumberConstant( node)) {136 } else if (isNumberConstant(edge.node())) { 135 137 info.fillJSValue(*m_stream, gpr, DataFormatJSDouble); 136 JSValue jsValue(JSValue::EncodeAsDouble, valueOfNumberConstant( node));138 JSValue jsValue(JSValue::EncodeAsDouble, valueOfNumberConstant(edge.node())); 137 139 m_jit.move(MacroAssembler::Imm64(JSValue::encode(jsValue)), gpr); 138 140 } else { 139 ASSERT(isJSConstant( node));140 JSValue jsValue = valueOfJSConstant( node);141 ASSERT(isJSConstant(edge.node())); 142 JSValue jsValue = valueOfJSConstant(edge.node()); 141 143 m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsValue)), gpr); 142 144 info.fillJSValue(*m_stream, gpr, DataFormatJS); … … 803 805 804 806 template<bool strict> 805 GPRReg SpeculativeJIT::fillSpeculateIntInternal( Node* node, DataFormat& returnFormat, SpeculationDirection direction)807 GPRReg SpeculativeJIT::fillSpeculateIntInternal(Edge edge, DataFormat& returnFormat, SpeculationDirection direction) 806 808 { 807 809 #if DFG_ENABLE(DEBUG_VERBOSE) 808 dataLogF("SpecInt@%d ", node->index());810 dataLogF("SpecInt@%d ", edge->index()); 809 811 #endif 810 SpeculatedType type = m_state.forNode(node).m_type; 811 VirtualRegister virtualRegister = node->virtualRegister(); 812 AbstractValue& value = m_state.forNode(edge); 813 SpeculatedType type = value.m_type; 814 ASSERT(edge.useKind() != KnownInt32Use || !(value.m_type & ~SpecInt32)); 815 value.filter(SpecInt32); 816 VirtualRegister virtualRegister = edge->virtualRegister(); 812 817 GenerationInfo& info = m_generationInfo[virtualRegister]; 813 818 814 819 switch (info.registerFormat()) { 815 820 case DataFormatNone: { 816 if (( node->hasConstant() && !isInt32Constant(node)) || info.spillFormat() == DataFormatDouble) {821 if ((edge->hasConstant() && !isInt32Constant(edge.node())) || info.spillFormat() == DataFormatDouble) { 817 822 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0, direction); 818 823 returnFormat = DataFormatInteger; … … 822 827 GPRReg gpr = allocate(); 823 828 824 if ( node->hasConstant()) {829 if (edge->hasConstant()) { 825 830 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); 826 ASSERT(isInt32Constant( node));827 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant( node)), gpr);831 ASSERT(isInt32Constant(edge.node())); 832 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(edge.node())), gpr); 828 833 info.fillInteger(*m_stream, gpr); 829 834 returnFormat = DataFormatInteger; … … 865 870 GPRReg gpr = info.gpr(); 866 871 m_gprs.lock(gpr); 867 if ( !isInt32Speculation(type))868 speculationCheck(BadType, JSValueRegs(gpr), node, m_jit.branch64(MacroAssembler::Below, gpr, GPRInfo::tagTypeNumberRegister), direction);872 if (type & ~SpecInt32) 873 speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branch64(MacroAssembler::Below, gpr, GPRInfo::tagTypeNumberRegister), direction); 869 874 info.fillJSValue(*m_stream, gpr, DataFormatJSInteger); 870 875 // If !strict we're done, return. … … 911 916 case DataFormatDouble: 912 917 case DataFormatJSDouble: { 913 if ( node->hasConstant() && isInt32Constant(node)) {918 if (edge->hasConstant() && isInt32Constant(edge.node())) { 914 919 GPRReg gpr = allocate(); 915 ASSERT(isInt32Constant( node));916 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant( node)), gpr);920 ASSERT(isInt32Constant(edge.node())); 921 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(edge.node())), gpr); 917 922 returnFormat = DataFormatInteger; 918 923 return gpr; … … 937 942 } 938 943 939 GPRReg SpeculativeJIT::fillSpeculateInt( Node* node, DataFormat& returnFormat, SpeculationDirection direction)944 GPRReg SpeculativeJIT::fillSpeculateInt(Edge edge, DataFormat& returnFormat, SpeculationDirection direction) 940 945 { 941 return fillSpeculateIntInternal<false>( node, returnFormat, direction);946 return fillSpeculateIntInternal<false>(edge, returnFormat, direction); 942 947 } 943 948 944 GPRReg SpeculativeJIT::fillSpeculateIntStrict( Node* node)949 GPRReg SpeculativeJIT::fillSpeculateIntStrict(Edge edge) 945 950 { 946 951 DataFormat mustBeDataFormatInteger; 947 GPRReg result = fillSpeculateIntInternal<true>( node, mustBeDataFormatInteger, BackwardSpeculation);952 GPRReg result = fillSpeculateIntInternal<true>(edge, mustBeDataFormatInteger, BackwardSpeculation); 948 953 RELEASE_ASSERT(mustBeDataFormatInteger == DataFormatInteger); 949 954 return result; 950 955 } 951 956 952 FPRReg SpeculativeJIT::fillSpeculateDouble( Node* node, SpeculationDirection direction)957 FPRReg SpeculativeJIT::fillSpeculateDouble(Edge edge, SpeculationDirection direction) 953 958 { 954 959 #if DFG_ENABLE(DEBUG_VERBOSE) 955 dataLogF("SpecDouble@%d ", node->index());960 dataLogF("SpecDouble@%d ", edge->index()); 956 961 #endif 957 SpeculatedType type = m_state.forNode(node).m_type; 958 VirtualRegister virtualRegister = node->virtualRegister(); 962 AbstractValue& value = m_state.forNode(edge); 963 SpeculatedType type = value.m_type; 964 ASSERT(edge.useKind() != KnownNumberUse || !(value.m_type & ~SpecNumber)); 965 value.filter(SpecNumber); 966 VirtualRegister virtualRegister = edge->virtualRegister(); 959 967 GenerationInfo& info = m_generationInfo[virtualRegister]; 960 968 961 969 if (info.registerFormat() == DataFormatNone) { 962 if ( node->hasConstant()) {970 if (edge->hasConstant()) { 963 971 GPRReg gpr = allocate(); 964 972 965 if (isInt32Constant( node)) {973 if (isInt32Constant(edge.node())) { 966 974 FPRReg fpr = fprAllocate(); 967 m_jit.move(MacroAssembler::Imm64(reinterpretDoubleToInt64(static_cast<double>(valueOfInt32Constant( node)))), gpr);975 m_jit.move(MacroAssembler::Imm64(reinterpretDoubleToInt64(static_cast<double>(valueOfInt32Constant(edge.node())))), gpr); 968 976 m_jit.move64ToDouble(gpr, fpr); 969 977 unlock(gpr); … … 973 981 return fpr; 974 982 } 975 if (isNumberConstant( node)) {983 if (isNumberConstant(edge.node())) { 976 984 FPRReg fpr = fprAllocate(); 977 m_jit.move(MacroAssembler::Imm64(reinterpretDoubleToInt64(valueOfNumberConstant( node))), gpr);985 m_jit.move(MacroAssembler::Imm64(reinterpretDoubleToInt64(valueOfNumberConstant(edge.node()))), gpr); 978 986 m_jit.move64ToDouble(gpr, fpr); 979 987 unlock(gpr); … … 1039 1047 JITCompiler::Jump isInteger = m_jit.branch64(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister); 1040 1048 1041 if ( !isNumberSpeculation(type))1042 speculationCheck(BadType, JSValueRegs(jsValueGpr), node, m_jit.branchTest64(MacroAssembler::Zero, jsValueGpr, GPRInfo::tagTypeNumberRegister), direction);1049 if (type & ~SpecNumber) 1050 speculationCheck(BadType, JSValueRegs(jsValueGpr), edge, m_jit.branchTest64(MacroAssembler::Zero, jsValueGpr, GPRInfo::tagTypeNumberRegister), direction); 1043 1051 1044 1052 // First, if we get here we have a double encoded as a JSValue … … 1103 1111 } 1104 1112 1105 GPRReg SpeculativeJIT::fillSpeculateCell( Node* node, SpeculationDirection direction)1113 GPRReg SpeculativeJIT::fillSpeculateCell(Edge edge, SpeculationDirection direction) 1106 1114 { 1107 1115 #if DFG_ENABLE(DEBUG_VERBOSE) 1108 dataLogF("SpecCell@%d ", node->index());1116 dataLogF("SpecCell@%d ", edge->index()); 1109 1117 #endif 1110 SpeculatedType type = m_state.forNode(node).m_type; 1111 VirtualRegister virtualRegister = node->virtualRegister(); 1118 AbstractValue& value = m_state.forNode(edge); 1119 SpeculatedType type = value.m_type; 1120 ASSERT(edge.useKind() != KnownCellUse || !(value.m_type & ~SpecCell)); 1121 value.filter(SpecCell); 1122 VirtualRegister virtualRegister = edge->virtualRegister(); 1112 1123 GenerationInfo& info = m_generationInfo[virtualRegister]; 1113 1124 … … 1121 1132 GPRReg gpr = allocate(); 1122 1133 1123 if ( node->hasConstant()) {1124 JSValue jsValue = valueOfJSConstant( node);1134 if (edge->hasConstant()) { 1135 JSValue jsValue = valueOfJSConstant(edge.node()); 1125 1136 if (jsValue.isCell()) { 1126 1137 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); … … 1137 1148 1138 1149 info.fillJSValue(*m_stream, gpr, DataFormatJS); 1139 if ( !isCellSpeculation(type))1140 speculationCheck(BadType, JSValueRegs(gpr), node, m_jit.branchTest64(MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister), direction);1150 if (type & ~SpecCell) 1151 speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchTest64(MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister), direction); 1141 1152 info.fillJSValue(*m_stream, gpr, DataFormatJSCell); 1142 1153 return gpr; … … 1153 1164 GPRReg gpr = info.gpr(); 1154 1165 m_gprs.lock(gpr); 1155 if ( !isCellSpeculation(type))1156 speculationCheck(BadType, JSValueRegs(gpr), node, m_jit.branchTest64(MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister), direction);1166 if (type & ~SpecCell) 1167 speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchTest64(MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister), direction); 1157 1168 info.fillJSValue(*m_stream, gpr, DataFormatJSCell); 1158 1169 return gpr; … … 1178 1189 } 1179 1190 1180 GPRReg SpeculativeJIT::fillSpeculateBoolean( Node* node, SpeculationDirection direction)1191 GPRReg SpeculativeJIT::fillSpeculateBoolean(Edge edge, SpeculationDirection direction) 1181 1192 { 1182 1193 #if DFG_ENABLE(DEBUG_VERBOSE) 1183 dataLogF("SpecBool@%d ", node->index());1194 dataLogF("SpecBool@%d ", edge->index()); 1184 1195 #endif 1185 SpeculatedType type = m_state.forNode(node).m_type; 1186 VirtualRegister virtualRegister = node->virtualRegister(); 1196 AbstractValue& value = m_state.forNode(edge); 1197 SpeculatedType type = value.m_type; 1198 value.filter(SpecBoolean); 1199 VirtualRegister virtualRegister = edge->virtualRegister(); 1187 1200 GenerationInfo& info = m_generationInfo[virtualRegister]; 1188 1201 … … 1196 1209 GPRReg gpr = allocate(); 1197 1210 1198 if ( node->hasConstant()) {1199 JSValue jsValue = valueOfJSConstant( node);1211 if (edge->hasConstant()) { 1212 JSValue jsValue = valueOfJSConstant(edge.node()); 1200 1213 if (jsValue.isBoolean()) { 1201 1214 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); … … 1212 1225 1213 1226 info.fillJSValue(*m_stream, gpr, DataFormatJS); 1214 if ( !isBooleanSpeculation(type)) {1227 if (type & ~SpecBoolean) { 1215 1228 m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr); 1216 speculationCheck(BadType, JSValueRegs(gpr), node, m_jit.branchTest64(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg), direction);1229 speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchTest64(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg), direction); 1217 1230 m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr); 1218 1231 } … … 1231 1244 GPRReg gpr = info.gpr(); 1232 1245 m_gprs.lock(gpr); 1233 if ( !isBooleanSpeculation(type)) {1246 if (type & ~SpecBoolean) { 1234 1247 m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr); 1235 speculationCheck(BadType, JSValueRegs(gpr), node, m_jit.branchTest64(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg), direction);1248 speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchTest64(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg), direction); 1236 1249 m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr); 1237 1250 } … … 1291 1304 if (m_jit.graph().globalObjectFor(node->codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) { 1292 1305 m_jit.graph().globalObjectFor(node->codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint()); 1293 if (m_state.forNode(node->child1()).m_type & ~SpecObject) { 1294 speculationCheck( 1295 BadType, JSValueSource::unboxedCell(op1GPR), node->child1(), 1296 m_jit.branchPtr( 1297 MacroAssembler::Equal, 1298 MacroAssembler::Address(op1GPR, JSCell::structureOffset()), 1299 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1300 } 1301 if (m_state.forNode(node->child2()).m_type & ~SpecObject) { 1302 speculationCheck( 1303 BadType, JSValueSource::unboxedCell(op2GPR), node->child2(), 1304 m_jit.branchPtr( 1305 MacroAssembler::Equal, 1306 MacroAssembler::Address(op2GPR, JSCell::structureOffset()), 1307 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1308 } 1306 DFG_TYPE_CHECK( 1307 JSValueSource::unboxedCell(op1GPR), node->child1(), SpecObject, m_jit.branchPtr( 1308 MacroAssembler::Equal, 1309 MacroAssembler::Address(op1GPR, JSCell::structureOffset()), 1310 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1311 DFG_TYPE_CHECK( 1312 JSValueSource::unboxedCell(op2GPR), node->child2(), SpecObject, m_jit.branchPtr( 1313 MacroAssembler::Equal, 1314 MacroAssembler::Address(op2GPR, JSCell::structureOffset()), 1315 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1309 1316 } else { 1310 1317 GPRTemporary structure(this); … … 1312 1319 1313 1320 m_jit.loadPtr(MacroAssembler::Address(op1GPR, JSCell::structureOffset()), structureGPR); 1314 if (m_state.forNode(node->child1()).m_type & ~SpecObject) { 1315 speculationCheck( 1316 BadType, JSValueSource::unboxedCell(op1GPR), node->child1(), 1317 m_jit.branchPtr( 1318 MacroAssembler::Equal, 1319 structureGPR, 1320 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1321 } 1321 DFG_TYPE_CHECK( 1322 JSValueSource::unboxedCell(op1GPR), node->child1(), SpecObject, m_jit.branchPtr( 1323 MacroAssembler::Equal, 1324 structureGPR, 1325 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1322 1326 speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node->child1(), 1323 1327 m_jit.branchTest8( … … 1327 1331 1328 1332 m_jit.loadPtr(MacroAssembler::Address(op2GPR, JSCell::structureOffset()), structureGPR); 1329 if (m_state.forNode(node->child2()).m_type & ~SpecObject) { 1330 speculationCheck( 1331 BadType, JSValueSource::unboxedCell(op2GPR), node->child2(), 1332 m_jit.branchPtr( 1333 MacroAssembler::Equal, 1334 structureGPR, 1335 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1336 } 1333 DFG_TYPE_CHECK( 1334 JSValueSource::unboxedCell(op2GPR), node->child2(), SpecObject, m_jit.branchPtr( 1335 MacroAssembler::Equal, 1336 structureGPR, 1337 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1337 1338 speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node->child2(), 1338 1339 m_jit.branchTest8( … … 1355 1356 { 1356 1357 SpeculateCellOperand op1(this, leftChild); 1357 JSValueOperand op2(this, rightChild );1358 JSValueOperand op2(this, rightChild, ManualOperandSpeculation); 1358 1359 GPRTemporary result(this); 1359 1360 … … 1364 1365 if (m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) { 1365 1366 m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint()); 1366 if (m_state.forNode(leftChild).m_type & ~SpecObject) { 1367 speculationCheck( 1368 BadType, JSValueSource::unboxedCell(op1GPR), leftChild, 1369 m_jit.branchPtr( 1370 MacroAssembler::Equal, 1371 MacroAssembler::Address(op1GPR, JSCell::structureOffset()), 1372 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1373 } 1367 DFG_TYPE_CHECK( 1368 JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchPtr( 1369 MacroAssembler::Equal, 1370 MacroAssembler::Address(op1GPR, JSCell::structureOffset()), 1371 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1374 1372 } else { 1375 1373 GPRTemporary structure(this); … … 1377 1375 1378 1376 m_jit.loadPtr(MacroAssembler::Address(op1GPR, JSCell::structureOffset()), structureGPR); 1379 if (m_state.forNode(leftChild).m_type & ~SpecObject) { 1380 speculationCheck( 1381 BadType, JSValueSource::unboxedCell(op1GPR), leftChild, 1382 m_jit.branchPtr( 1383 MacroAssembler::Equal, 1384 structureGPR, 1385 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1386 } 1377 DFG_TYPE_CHECK( 1378 JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchPtr( 1379 MacroAssembler::Equal, 1380 structureGPR, 1381 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1387 1382 speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), leftChild, 1388 1383 m_jit.branchTest8( … … 1400 1395 if (m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) { 1401 1396 m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint()); 1402 if ((m_state.forNode(rightChild).m_type & SpecCell) & ~SpecObject) { 1403 speculationCheck( 1404 BadType, JSValueRegs(op2GPR), rightChild, 1405 m_jit.branchPtr( 1406 MacroAssembler::Equal, 1407 MacroAssembler::Address(op2GPR, JSCell::structureOffset()), 1408 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1409 } 1397 DFG_TYPE_CHECK( 1398 JSValueRegs(op2GPR), rightChild, (~SpecCell) | SpecObject, m_jit.branchPtr( 1399 MacroAssembler::Equal, 1400 MacroAssembler::Address(op2GPR, JSCell::structureOffset()), 1401 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1410 1402 } else { 1411 1403 GPRTemporary structure(this); … … 1413 1405 1414 1406 m_jit.loadPtr(MacroAssembler::Address(op2GPR, JSCell::structureOffset()), structureGPR); 1415 if ((m_state.forNode(rightChild).m_type & SpecCell) & ~SpecObject) { 1416 speculationCheck( 1417 BadType, JSValueRegs(op2GPR), rightChild, 1418 m_jit.branchPtr( 1419 MacroAssembler::Equal, 1420 structureGPR, 1421 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1422 } 1407 DFG_TYPE_CHECK( 1408 JSValueRegs(op2GPR), rightChild, (~SpecCell) | SpecObject, m_jit.branchPtr( 1409 MacroAssembler::Equal, 1410 structureGPR, 1411 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1423 1412 speculationCheck(BadType, JSValueRegs(op2GPR), rightChild, 1424 1413 m_jit.branchTest8( … … 1438 1427 // We know that within this branch, rightChild must not be a cell. Check if that is enough to 1439 1428 // prove that it is either null or undefined. 1440 if ( (m_state.forNode(rightChild).m_type & ~SpecCell) & ~SpecOther) {1429 if (needsTypeCheck(rightChild, SpecCell | SpecOther)) { 1441 1430 m_jit.move(op2GPR, resultGPR); 1442 1431 m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR); 1443 1432 1444 speculationCheck(1445 BadType, JSValueRegs(op2GPR), rightChild.node(),1433 typeCheck( 1434 JSValueRegs(op2GPR), rightChild, SpecCell | SpecOther, 1446 1435 m_jit.branch64( 1447 1436 MacroAssembler::NotEqual, resultGPR, … … 1465 1454 1466 1455 SpeculateCellOperand op1(this, leftChild); 1467 JSValueOperand op2(this, rightChild );1456 JSValueOperand op2(this, rightChild, ManualOperandSpeculation); 1468 1457 GPRTemporary result(this); 1469 1458 … … 1474 1463 if (m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) { 1475 1464 m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint()); 1476 if (m_state.forNode(leftChild).m_type & ~SpecObject) { 1477 speculationCheck( 1478 BadType, JSValueSource::unboxedCell(op1GPR), leftChild, 1479 m_jit.branchPtr( 1480 MacroAssembler::Equal, 1481 MacroAssembler::Address(op1GPR, JSCell::structureOffset()), 1482 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1483 } 1465 DFG_TYPE_CHECK( 1466 JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchPtr( 1467 MacroAssembler::Equal, 1468 MacroAssembler::Address(op1GPR, JSCell::structureOffset()), 1469 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1484 1470 } else { 1485 1471 GPRTemporary structure(this); … … 1487 1473 1488 1474 m_jit.loadPtr(MacroAssembler::Address(op1GPR, JSCell::structureOffset()), structureGPR); 1489 if (m_state.forNode(leftChild).m_type & ~SpecObject) { 1490 speculationCheck( 1491 BadType, JSValueSource::unboxedCell(op1GPR), leftChild, 1492 m_jit.branchPtr( 1493 MacroAssembler::Equal, 1494 structureGPR, 1495 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1496 } 1475 DFG_TYPE_CHECK( 1476 JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchPtr( 1477 MacroAssembler::Equal, 1478 structureGPR, 1479 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1497 1480 speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), leftChild, 1498 1481 m_jit.branchTest8( … … 1510 1493 if (m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) { 1511 1494 m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint()); 1512 if ((m_state.forNode(rightChild).m_type & SpecCell) & ~SpecObject) { 1513 speculationCheck( 1514 BadType, JSValueRegs(op2GPR), rightChild, 1515 m_jit.branchPtr( 1516 MacroAssembler::Equal, 1517 MacroAssembler::Address(op2GPR, JSCell::structureOffset()), 1518 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1519 } 1495 DFG_TYPE_CHECK( 1496 JSValueRegs(op2GPR), rightChild, (~SpecCell) | SpecObject, m_jit.branchPtr( 1497 MacroAssembler::Equal, 1498 MacroAssembler::Address(op2GPR, JSCell::structureOffset()), 1499 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1520 1500 } else { 1521 1501 GPRTemporary structure(this); … … 1523 1503 1524 1504 m_jit.loadPtr(MacroAssembler::Address(op2GPR, JSCell::structureOffset()), structureGPR); 1525 if ((m_state.forNode(rightChild).m_type & SpecCell) & ~SpecObject) { 1526 speculationCheck( 1527 BadType, JSValueRegs(op2GPR), rightChild, 1528 m_jit.branchPtr( 1529 MacroAssembler::Equal, 1530 structureGPR, 1531 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1532 } 1505 DFG_TYPE_CHECK( 1506 JSValueRegs(op2GPR), rightChild, (~SpecCell) | SpecObject, m_jit.branchPtr( 1507 MacroAssembler::Equal, 1508 structureGPR, 1509 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1533 1510 speculationCheck(BadType, JSValueRegs(op2GPR), rightChild, 1534 1511 m_jit.branchTest8( … … 1545 1522 // We know that within this branch, rightChild must not be a cell. Check if that is enough to 1546 1523 // prove that it is either null or undefined. 1547 if ( (m_state.forNode(rightChild).m_type & ~SpecCell) & ~SpecOther)1524 if (!needsTypeCheck(rightChild, SpecCell | SpecOther)) 1548 1525 rightNotCell.link(&m_jit); 1549 1526 else { … … 1554 1531 m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR); 1555 1532 1556 speculationCheck( 1557 BadType, JSValueRegs(op2GPR), rightChild, 1558 m_jit.branch64( 1533 typeCheck( 1534 JSValueRegs(op2GPR), rightChild, SpecCell | SpecOther, m_jit.branch64( 1559 1535 MacroAssembler::NotEqual, resultGPR, 1560 1536 MacroAssembler::TrustedImm64(ValueNull))); … … 1610 1586 } 1611 1587 1612 void SpeculativeJIT::compileObjectOrOtherLogicalNot(Edge nodeUse , bool needSpeculationCheck)1588 void SpeculativeJIT::compileObjectOrOtherLogicalNot(Edge nodeUse) 1613 1589 { 1614 JSValueOperand value(this, nodeUse );1590 JSValueOperand value(this, nodeUse, ManualOperandSpeculation); 1615 1591 GPRTemporary result(this); 1616 1592 GPRReg valueGPR = value.gpr(); … … 1620 1596 if (m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) { 1621 1597 m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint()); 1622 1623 if (needSpeculationCheck) { 1624 speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse, 1625 m_jit.branchPtr( 1626 MacroAssembler::Equal, 1627 MacroAssembler::Address(valueGPR, JSCell::structureOffset()), 1628 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1629 } 1598 DFG_TYPE_CHECK( 1599 JSValueRegs(valueGPR), nodeUse, (~SpecCell) | SpecObject, m_jit.branchPtr( 1600 MacroAssembler::Equal, 1601 MacroAssembler::Address(valueGPR, JSCell::structureOffset()), 1602 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1630 1603 } else { 1631 1604 GPRTemporary structure(this); … … 1634 1607 m_jit.loadPtr(MacroAssembler::Address(valueGPR, JSCell::structureOffset()), structureGPR); 1635 1608 1636 if (needSpeculationCheck) { 1637 speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse, 1638 m_jit.branchPtr( 1639 MacroAssembler::Equal, 1640 structureGPR, 1641 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1642 } 1609 DFG_TYPE_CHECK( 1610 JSValueRegs(valueGPR), nodeUse, (~SpecCell) | SpecObject, m_jit.branchPtr( 1611 MacroAssembler::Equal, 1612 structureGPR, 1613 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1643 1614 1644 1615 MacroAssembler::Jump isNotMasqueradesAsUndefined = … … 1661 1632 notCell.link(&m_jit); 1662 1633 1663 if (need SpeculationCheck) {1634 if (needsTypeCheck(nodeUse, SpecCell | SpecOther)) { 1664 1635 m_jit.move(valueGPR, resultGPR); 1665 1636 m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR); 1666 speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse,1667 m_jit.branch64(1637 typeCheck( 1638 JSValueRegs(valueGPR), nodeUse, SpecCell | SpecOther, m_jit.branch64( 1668 1639 MacroAssembler::NotEqual, 1669 1640 resultGPR, … … 1679 1650 void SpeculativeJIT::compileLogicalNot(Node* node) 1680 1651 { 1681 if (node->child1()->shouldSpeculateObjectOrOther()) {1682 compileObjectOrOtherLogicalNot(node->child1(),1683 !isObjectOrOtherSpeculation(m_state.forNode(node->child1()).m_type));1652 switch (node->child1().useKind()) { 1653 case ObjectOrOtherUse: { 1654 compileObjectOrOtherLogicalNot(node->child1()); 1684 1655 return; 1685 1656 } 1686 if (node->child1()->shouldSpeculateInteger()) { 1657 1658 case Int32Use: { 1687 1659 SpeculateIntegerOperand value(this, node->child1()); 1688 1660 GPRTemporary result(this, value); … … 1692 1664 return; 1693 1665 } 1694 if (node->child1()->shouldSpeculateNumber()) { 1666 1667 case NumberUse: { 1695 1668 SpeculateDoubleOperand value(this, node->child1()); 1696 1669 FPRTemporary scratch(this); … … 1704 1677 } 1705 1678 1706 SpeculatedType prediction = node->child1()->prediction(); 1707 if (isBooleanSpeculation(prediction)) { 1708 if (isBooleanSpeculation(m_state.forNode(node->child1()).m_type)) { 1679 case BooleanUse: { 1680 if (!needsTypeCheck(node->child1(), SpecBoolean)) { 1709 1681 SpeculateBooleanOperand value(this, node->child1()); 1710 1682 GPRTemporary result(this, value); … … 1717 1689 } 1718 1690 1719 JSValueOperand value(this, node->child1() );1691 JSValueOperand value(this, node->child1(), ManualOperandSpeculation); 1720 1692 GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add). 1721 1693 1722 1694 m_jit.move(value.gpr(), result.gpr()); 1723 1695 m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.gpr()); 1724 speculationCheck(BadType, JSValueRegs(value.gpr()), node->child1(), m_jit.branchTest64(JITCompiler::NonZero, result.gpr(), TrustedImm32(static_cast<int32_t>(~1)))); 1696 typeCheck( 1697 JSValueRegs(value.gpr()), node->child1(), SpecBoolean, m_jit.branchTest64( 1698 JITCompiler::NonZero, result.gpr(), TrustedImm32(static_cast<int32_t>(~1)))); 1725 1699 m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueTrue)), result.gpr()); 1726 1700 … … 1729 1703 return; 1730 1704 } 1731 1732 JSValueOperand arg1(this, node->child1()); 1733 GPRTemporary result(this); 1734 1735 GPRReg arg1GPR = arg1.gpr(); 1736 GPRReg resultGPR = result.gpr(); 1737 1738 arg1.use(); 1739 1740 m_jit.move(arg1GPR, resultGPR); 1741 m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), resultGPR); 1742 JITCompiler::Jump slowCase = m_jit.branchTest64(JITCompiler::NonZero, resultGPR, TrustedImm32(static_cast<int32_t>(~1))); 1743 1744 addSlowPathGenerator( 1745 slowPathCall(slowCase, this, dfgConvertJSValueToBoolean, resultGPR, arg1GPR)); 1746 1747 m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueTrue)), resultGPR); 1748 jsValueResult(resultGPR, node, DataFormatJSBoolean, UseChildrenCalledExplicitly); 1705 1706 case UntypedUse: { 1707 JSValueOperand arg1(this, node->child1()); 1708 GPRTemporary result(this); 1709 1710 GPRReg arg1GPR = arg1.gpr(); 1711 GPRReg resultGPR = result.gpr(); 1712 1713 arg1.use(); 1714 1715 m_jit.move(arg1GPR, resultGPR); 1716 m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), resultGPR); 1717 JITCompiler::Jump slowCase = m_jit.branchTest64(JITCompiler::NonZero, resultGPR, TrustedImm32(static_cast<int32_t>(~1))); 1718 1719 addSlowPathGenerator( 1720 slowPathCall(slowCase, this, dfgConvertJSValueToBoolean, resultGPR, arg1GPR)); 1721 1722 m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueTrue)), resultGPR); 1723 jsValueResult(resultGPR, node, DataFormatJSBoolean, UseChildrenCalledExplicitly); 1724 return; 1725 } 1726 1727 default: 1728 RELEASE_ASSERT_NOT_REACHED(); 1729 break; 1730 } 1749 1731 } 1750 1732 1751 void SpeculativeJIT::emitObjectOrOtherBranch(Edge nodeUse, BlockIndex taken, BlockIndex notTaken , bool needSpeculationCheck)1733 void SpeculativeJIT::emitObjectOrOtherBranch(Edge nodeUse, BlockIndex taken, BlockIndex notTaken) 1752 1734 { 1753 JSValueOperand value(this, nodeUse );1735 JSValueOperand value(this, nodeUse, ManualOperandSpeculation); 1754 1736 GPRTemporary scratch(this); 1755 1737 GPRReg valueGPR = value.gpr(); … … 1760 1742 m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint()); 1761 1743 1762 if (needSpeculationCheck) { 1763 speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse, 1764 m_jit.branchPtr( 1765 MacroAssembler::Equal, 1766 MacroAssembler::Address(valueGPR, JSCell::structureOffset()), 1767 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1768 } 1744 DFG_TYPE_CHECK( 1745 JSValueRegs(valueGPR), nodeUse, (~SpecCell) | SpecObject, m_jit.branchPtr( 1746 MacroAssembler::Equal, 1747 MacroAssembler::Address(valueGPR, JSCell::structureOffset()), 1748 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1769 1749 } else { 1770 1750 m_jit.loadPtr(MacroAssembler::Address(valueGPR, JSCell::structureOffset()), scratchGPR); 1771 1751 1772 if (needSpeculationCheck) { 1773 speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse, 1774 m_jit.branchPtr( 1775 MacroAssembler::Equal, 1776 scratchGPR, 1777 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1778 } 1752 DFG_TYPE_CHECK( 1753 JSValueRegs(valueGPR), nodeUse, (~SpecCell) | SpecObject, m_jit.branchPtr( 1754 MacroAssembler::Equal, 1755 scratchGPR, 1756 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 1779 1757 1780 1758 JITCompiler::Jump isNotMasqueradesAsUndefined = m_jit.branchTest8(JITCompiler::Zero, MacroAssembler::Address(scratchGPR, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined)); … … 1792 1770 notCell.link(&m_jit); 1793 1771 1794 if (need SpeculationCheck) {1772 if (needsTypeCheck(nodeUse, SpecCell | SpecOther)) { 1795 1773 m_jit.move(valueGPR, scratchGPR); 1796 1774 m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), scratchGPR); 1797 speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse, m_jit.branch64(MacroAssembler::NotEqual, scratchGPR, MacroAssembler::TrustedImm64(ValueNull))); 1775 typeCheck( 1776 JSValueRegs(valueGPR), nodeUse, SpecCell | SpecOther, m_jit.branch64( 1777 MacroAssembler::NotEqual, scratchGPR, MacroAssembler::TrustedImm64(ValueNull))); 1798 1778 } 1799 1779 jump(notTaken); … … 1807 1787 BlockIndex notTaken = node->notTakenBlockIndex(); 1808 1788 1809 if (node->child1()->shouldSpeculateObjectOrOther()) {1810 emitObjectOrOtherBranch(node->child1(), taken, notTaken,1811 !isObjectOrOtherSpeculation(m_state.forNode(node->child1()).m_type));1789 switch (node->child1().useKind()) { 1790 case ObjectOrOtherUse: { 1791 emitObjectOrOtherBranch(node->child1(), taken, notTaken); 1812 1792 return; 1813 1793 } 1814 1815 if (node->child1()->shouldSpeculateNumber()) { 1816 if (node->child1()->shouldSpeculateInteger()) { 1794 1795 case Int32Use: 1796 case NumberUse: { 1797 if (node->child1().useKind() == Int32Use) { 1817 1798 bool invert = false; 1818 1799 … … 1838 1819 } 1839 1820 1840 JSValueOperand value(this, node->child1());1841 GPRReg valueGPR = value.gpr();1842 1843 bool predictBoolean = isBooleanSpeculation(node->child1()->prediction());1844 1845 if (predictBoolean) {1846 if (isBooleanSpeculation(m_state.forNode(node->child1()).m_type)) {1847 MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;1821 case UntypedUse: 1822 case BooleanUse: { 1823 JSValueOperand value(this, node->child1(), ManualOperandSpeculation); 1824 GPRReg valueGPR = value.gpr(); 1825 1826 if (node->child1().useKind() == BooleanUse) { 1827 if (!needsTypeCheck(node->child1(), SpecBoolean)) { 1828 MacroAssembler::ResultCondition condition = MacroAssembler::NonZero; 1848 1829 1849 if (taken == nextBlock()) { 1850 condition = MacroAssembler::Zero; 1851 BlockIndex tmp = taken; 1852 taken = notTaken; 1853 notTaken = tmp; 1830 if (taken == nextBlock()) { 1831 condition = MacroAssembler::Zero; 1832 BlockIndex tmp = taken; 1833 taken = notTaken; 1834 notTaken = tmp; 1835 } 1836 1837 branchTest32(condition, valueGPR, TrustedImm32(true), taken); 1838 jump(notTaken); 1839 } else { 1840 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(false))), notTaken); 1841 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(true))), taken); 1842 1843 typeCheck(JSValueRegs(valueGPR), node->child1(), SpecBoolean, m_jit.jump()); 1854 1844 } 1855 1856 branchTest32(condition, valueGPR, TrustedImm32(true), taken); 1845 value.use(); 1846 } else { 1847 GPRTemporary result(this); 1848 GPRReg resultGPR = result.gpr(); 1849 1850 if (node->child1()->prediction() & SpecInt32) { 1851 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsNumber(0))), notTaken); 1852 branch64(MacroAssembler::AboveOrEqual, valueGPR, GPRInfo::tagTypeNumberRegister, taken); 1853 } 1854 1855 if (node->child1()->prediction() & SpecBoolean) { 1856 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(false))), notTaken); 1857 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(true))), taken); 1858 } 1859 1860 value.use(); 1861 1862 silentSpillAllRegisters(resultGPR); 1863 callOperation(dfgConvertJSValueToBoolean, resultGPR, valueGPR); 1864 silentFillAllRegisters(resultGPR); 1865 1866 branchTest32(MacroAssembler::NonZero, resultGPR, taken); 1857 1867 jump(notTaken); 1858 } else { 1859 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(false))), notTaken); 1860 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(true))), taken); 1861 1862 speculationCheck(BadType, JSValueRegs(valueGPR), node->child1(), m_jit.jump()); 1863 } 1864 value.use(); 1865 } else { 1866 GPRTemporary result(this); 1867 GPRReg resultGPR = result.gpr(); 1868 1869 if (node->child1()->prediction() & SpecInt32) { 1870 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsNumber(0))), notTaken); 1871 branch64(MacroAssembler::AboveOrEqual, valueGPR, GPRInfo::tagTypeNumberRegister, taken); 1872 } 1873 1874 if (node->child1()->prediction() & SpecBoolean) { 1875 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(false))), notTaken); 1876 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(true))), taken); 1877 } 1878 1879 value.use(); 1880 1881 silentSpillAllRegisters(resultGPR); 1882 callOperation(dfgConvertJSValueToBoolean, resultGPR, valueGPR); 1883 silentFillAllRegisters(resultGPR); 1884 1885 branchTest32(MacroAssembler::NonZero, resultGPR, taken); 1886 jump(notTaken); 1887 } 1888 1889 noResult(node, UseChildrenCalledExplicitly); 1868 } 1869 1870 noResult(node, UseChildrenCalledExplicitly); 1871 return; 1872 } 1873 1874 default: 1875 RELEASE_ASSERT_NOT_REACHED(); 1876 } 1890 1877 } 1891 1878 … … 1909 1896 1910 1897 case Identity: { 1911 // This could be done a lot better. We take the cheap way out because Identity 1912 // is only going to stick around after CSE if we had prediction weirdness. 1913 JSValueOperand operand(this, node->child1()); 1914 GPRTemporary result(this, operand); 1915 m_jit.move(operand.gpr(), result.gpr()); 1916 jsValueResult(result.gpr(), node); 1898 // CSE should always eliminate this. 1899 RELEASE_ASSERT_NOT_REACHED(); 1917 1900 break; 1918 1901 } … … 1932 1915 // cannot have been assigned, then don't attempt to proceed. 1933 1916 if (value.isClear()) { 1917 // FIXME: We should trap instead. 1918 // https://bugs.webkit.org/show_bug.cgi?id=110383 1934 1919 terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0); 1935 1920 break; … … 2132 2117 } 2133 2118 2134 case CheckNumber: {2135 if (!isNumberSpeculation(m_state.forNode(node->child1()).m_type)) {2136 JSValueOperand op1(this, node->child1());2137 JITCompiler::Jump isInteger = m_jit.branch64(MacroAssembler::AboveOrEqual, op1.gpr(), GPRInfo::tagTypeNumberRegister);2138 speculationCheck(2139 BadType, JSValueRegs(op1.gpr()), node->child1().node(),2140 m_jit.branchTest64(MacroAssembler::Zero, op1.gpr(), GPRInfo::tagTypeNumberRegister));2141 isInteger.link(&m_jit);2142 }2143 noResult(node);2144 break;2145 }2146 2147 2119 case ValueAdd: 2148 2120 case ArithAdd: … … 2163 2135 2164 2136 case ArithDiv: { 2165 if (Node::shouldSpeculateIntegerForArithmetic(node->child1().node(), node->child2().node())2166 && node->canSpeculateInteger()){2137 switch (node->binaryUseKind()) { 2138 case Int32Use: { 2167 2139 compileIntegerArithDivForX86(node); 2168 2140 break; 2169 2141 } 2170 2171 SpeculateDoubleOperand op1(this, node->child1()); 2172 SpeculateDoubleOperand op2(this, node->child2()); 2173 FPRTemporary result(this, op1); 2174 2175 FPRReg reg1 = op1.fpr(); 2176 FPRReg reg2 = op2.fpr(); 2177 m_jit.divDouble(reg1, reg2, result.fpr()); 2178 2179 doubleResult(result.fpr(), node); 2142 2143 case NumberUse: { 2144 SpeculateDoubleOperand op1(this, node->child1()); 2145 SpeculateDoubleOperand op2(this, node->child2()); 2146 FPRTemporary result(this, op1); 2147 2148 FPRReg reg1 = op1.fpr(); 2149 FPRReg reg2 = op2.fpr(); 2150 m_jit.divDouble(reg1, reg2, result.fpr()); 2151 2152 doubleResult(result.fpr(), node); 2153 break; 2154 } 2155 2156 default: 2157 RELEASE_ASSERT_NOT_REACHED(); 2158 break; 2159 } 2180 2160 break; 2181 2161 } … … 2187 2167 2188 2168 case ArithAbs: { 2189 if (node->child1()->shouldSpeculateIntegerForArithmetic()2190 && node->canSpeculateInteger()){2169 switch (node->child1().useKind()) { 2170 case Int32Use: { 2191 2171 SpeculateIntegerOperand op1(this, node->child1()); 2192 2172 GPRTemporary result(this); … … 2202 2182 } 2203 2183 2204 SpeculateDoubleOperand op1(this, node->child1()); 2205 FPRTemporary result(this); 2206 2207 m_jit.absDouble(op1.fpr(), result.fpr()); 2208 doubleResult(result.fpr(), node); 2184 case NumberUse: { 2185 SpeculateDoubleOperand op1(this, node->child1()); 2186 FPRTemporary result(this); 2187 2188 m_jit.absDouble(op1.fpr(), result.fpr()); 2189 doubleResult(result.fpr(), node); 2190 break; 2191 } 2192 2193 default: 2194 RELEASE_ASSERT_NOT_REACHED(); 2195 break; 2196 } 2209 2197 break; 2210 2198 } … … 2212 2200 case ArithMin: 2213 2201 case ArithMax: { 2214 if (Node::shouldSpeculateIntegerForArithmetic(node->child1().node(), node->child2().node())2215 && node->canSpeculateInteger()){2202 switch (node->binaryUseKind()) { 2203 case Int32Use: { 2216 2204 SpeculateStrictInt32Operand op1(this, node->child1()); 2217 2205 SpeculateStrictInt32Operand op2(this, node->child2()); … … 2232 2220 } 2233 2221 2234 SpeculateDoubleOperand op1(this, node->child1()); 2235 SpeculateDoubleOperand op2(this, node->child2()); 2236 FPRTemporary result(this, op1); 2237 2238 MacroAssembler::JumpList done; 2239 2240 MacroAssembler::Jump op1Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleLessThan : MacroAssembler::DoubleGreaterThan, op1.fpr(), op2.fpr()); 2241 2242 // op2 is eather the lesser one or one of then is NaN 2243 MacroAssembler::Jump op2Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleGreaterThanOrEqual : MacroAssembler::DoubleLessThanOrEqual, op1.fpr(), op2.fpr()); 2244 2245 // Unordered case. We don't know which of op1, op2 is NaN. Manufacture NaN by adding 2246 // op1 + op2 and putting it into result. 2247 m_jit.addDouble(op1.fpr(), op2.fpr(), result.fpr()); 2248 done.append(m_jit.jump()); 2249 2250 op2Less.link(&m_jit); 2251 m_jit.moveDouble(op2.fpr(), result.fpr()); 2252 2253 if (op1.fpr() != result.fpr()) { 2222 case NumberUse: { 2223 SpeculateDoubleOperand op1(this, node->child1()); 2224 SpeculateDoubleOperand op2(this, node->child2()); 2225 FPRTemporary result(this, op1); 2226 2227 MacroAssembler::JumpList done; 2228 2229 MacroAssembler::Jump op1Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleLessThan : MacroAssembler::DoubleGreaterThan, op1.fpr(), op2.fpr()); 2230 2231 // op2 is eather the lesser one or one of then is NaN 2232 MacroAssembler::Jump op2Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleGreaterThanOrEqual : MacroAssembler::DoubleLessThanOrEqual, op1.fpr(), op2.fpr()); 2233 2234 // Unordered case. We don't know which of op1, op2 is NaN. Manufacture NaN by adding 2235 // op1 + op2 and putting it into result. 2236 m_jit.addDouble(op1.fpr(), op2.fpr(), result.fpr()); 2254 2237 done.append(m_jit.jump()); 2255 2256 op1Less.link(&m_jit); 2257 m_jit.moveDouble(op1.fpr(), result.fpr()); 2258 } else 2259 op1Less.link(&m_jit); 2260 2261 done.link(&m_jit); 2262 2263 doubleResult(result.fpr(), node); 2238 2239 op2Less.link(&m_jit); 2240 m_jit.moveDouble(op2.fpr(), result.fpr()); 2241 2242 if (op1.fpr() != result.fpr()) { 2243 done.append(m_jit.jump()); 2244 2245 op1Less.link(&m_jit); 2246 m_jit.moveDouble(op1.fpr(), result.fpr()); 2247 } else 2248 op1Less.link(&m_jit); 2249 2250 done.link(&m_jit); 2251 2252 doubleResult(result.fpr(), node); 2253 break; 2254 } 2255 2256 default: 2257 RELEASE_ASSERT_NOT_REACHED(); 2258 break; 2259 } 2264 2260 break; 2265 2261 } … … 2618 2614 case Array::Int32: 2619 2615 case Array::Contiguous: { 2620 JSValueOperand value(this, child3 );2616 JSValueOperand value(this, child3, ManualOperandSpeculation); 2621 2617 2622 2618 GPRReg valueReg = value.gpr(); … … 2625 2621 return; 2626 2622 2627 if (arrayMode.type() == Array::Int32 2628 && !isInt32Speculation(m_state.forNode(child3).m_type)) {2629 speculationCheck(2630 BadType, JSValueRegs(valueReg), child3,2631 m_jit.branch64(MacroAssembler::Below, valueReg, GPRInfo::tagTypeNumberRegister));2623 if (arrayMode.type() == Array::Int32) { 2624 DFG_TYPE_CHECK( 2625 JSValueRegs(valueReg), child3, SpecInt32, 2626 m_jit.branch64( 2627 MacroAssembler::Below, valueReg, GPRInfo::tagTypeNumberRegister)); 2632 2628 } 2633 2629 … … 2929 2925 case Array::Int32: 2930 2926 case Array::Contiguous: { 2931 JSValueOperand value(this, node->child2() );2927 JSValueOperand value(this, node->child2(), ManualOperandSpeculation); 2932 2928 GPRReg valueGPR = value.gpr(); 2933 2929 2934 if (node->arrayMode().type() == Array::Int32 && !isInt32Speculation(m_state.forNode(node->child2()).m_type)) { 2935 speculationCheck( 2936 BadType, JSValueRegs(valueGPR), node->child2(), 2937 m_jit.branch64(MacroAssembler::Below, valueGPR, GPRInfo::tagTypeNumberRegister)); 2930 if (node->arrayMode().type() == Array::Int32) { 2931 DFG_TYPE_CHECK( 2932 JSValueRegs(valueGPR), node->child2(), SpecInt32, 2933 m_jit.branch64( 2934 MacroAssembler::Below, valueGPR, GPRInfo::tagTypeNumberRegister)); 2938 2935 } 2939 2936 … … 2963 2960 FPRReg valueFPR = value.fpr(); 2964 2961 2965 if (!isRealNumberSpeculation(m_state.forNode(node->child2()).m_type)) { 2966 // FIXME: We need a way of profiling these, and we need to hoist them into 2967 // SpeculateDoubleOperand. 2968 speculationCheck( 2969 BadType, JSValueRegs(), 0, 2970 m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, valueFPR, valueFPR)); 2971 } 2962 DFG_TYPE_CHECK( 2963 JSValueRegs(), node->child2(), SpecRealNumber, 2964 m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, valueFPR, valueFPR)); 2972 2965 2973 2966 m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR); … … 3172 3165 3173 3166 case ToPrimitive: { 3174 if (node->child1()->shouldSpeculateInteger()) { 3167 switch (node->child1().useKind()) { 3168 case Int32Use: { 3175 3169 // It's really profitable to speculate integer, since it's really cheap, 3176 3170 // it means we don't have to do any real work, and we emit a lot less code. … … 3187 3181 } 3188 3182 3189 // FIXME: Add string speculation here. 3190 3191 JSValueOperand op1(this, node->child1()); 3192 GPRTemporary result(this, op1); 3193 3194 GPRReg op1GPR = op1.gpr(); 3195 GPRReg resultGPR = result.gpr(); 3196 3197 op1.use(); 3198 3199 if (!(m_state.forNode(node->child1()).m_type & ~(SpecNumber | SpecBoolean))) 3200 m_jit.move(op1GPR, resultGPR); 3201 else { 3202 MacroAssembler::Jump alreadyPrimitive = m_jit.branchTest64(MacroAssembler::NonZero, op1GPR, GPRInfo::tagMaskRegister); 3203 MacroAssembler::Jump notPrimitive = m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR, JSCell::structureOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())); 3204 3205 alreadyPrimitive.link(&m_jit); 3206 m_jit.move(op1GPR, resultGPR); 3207 3208 addSlowPathGenerator( 3209 slowPathCall(notPrimitive, this, operationToPrimitive, resultGPR, op1GPR)); 3210 } 3211 3212 jsValueResult(resultGPR, node, UseChildrenCalledExplicitly); 3183 case UntypedUse: { 3184 JSValueOperand op1(this, node->child1()); 3185 GPRTemporary result(this, op1); 3186 3187 GPRReg op1GPR = op1.gpr(); 3188 GPRReg resultGPR = result.gpr(); 3189 3190 op1.use(); 3191 3192 if (!(m_state.forNode(node->child1()).m_type & ~(SpecNumber | SpecBoolean))) 3193 m_jit.move(op1GPR, resultGPR); 3194 else { 3195 MacroAssembler::Jump alreadyPrimitive = m_jit.branchTest64(MacroAssembler::NonZero, op1GPR, GPRInfo::tagMaskRegister); 3196 MacroAssembler::Jump notPrimitive = m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR, JSCell::structureOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())); 3197 3198 alreadyPrimitive.link(&m_jit); 3199 m_jit.move(op1GPR, resultGPR); 3200 3201 addSlowPathGenerator( 3202 slowPathCall(notPrimitive, this, operationToPrimitive, resultGPR, op1GPR)); 3203 } 3204 3205 jsValueResult(resultGPR, node, UseChildrenCalledExplicitly); 3206 break; 3207 } 3208 3209 default: 3210 RELEASE_ASSERT_NOT_REACHED(); 3211 break; 3212 } 3213 3213 break; 3214 3214 } … … 3252 3252 SpeculateDoubleOperand operand(this, use); 3253 3253 FPRReg opFPR = operand.fpr(); 3254 if (!isRealNumberSpeculation(m_state.forNode(use).m_type)) { 3255 // FIXME: We need a way of profiling these, and we need to hoist them into 3256 // SpeculateDoubleOperand. 3257 speculationCheck( 3258 BadType, JSValueRegs(), 0, 3259 m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, opFPR, opFPR)); 3260 } 3261 3254 DFG_TYPE_CHECK( 3255 JSValueRegs(), use, SpecRealNumber, 3256 m_jit.branchDouble( 3257 MacroAssembler::DoubleNotEqualOrUnordered, opFPR, opFPR)); 3262 3258 m_jit.storeDouble(opFPR, MacroAssembler::Address(storageGPR, sizeof(double) * operandIdx)); 3263 3259 break; … … 3265 3261 case ALL_INT32_INDEXING_TYPES: 3266 3262 case ALL_CONTIGUOUS_INDEXING_TYPES: { 3267 JSValueOperand operand(this, use );3263 JSValueOperand operand(this, use, ManualOperandSpeculation); 3268 3264 GPRReg opGPR = operand.gpr(); 3269 if (hasInt32(node->indexingType()) && !isInt32Speculation(m_state.forNode(use).m_type)) { 3270 speculationCheck( 3271 BadType, JSValueRegs(opGPR), use, 3272 m_jit.branch64(MacroAssembler::Below, opGPR, GPRInfo::tagTypeNumberRegister)); 3265 if (hasInt32(node->indexingType())) { 3266 DFG_TYPE_CHECK( 3267 JSValueRegs(opGPR), use, SpecInt32, 3268 m_jit.branch64( 3269 MacroAssembler::Below, opGPR, GPRInfo::tagTypeNumberRegister)); 3273 3270 } 3274 3271 m_jit.store64(opGPR, MacroAssembler::Address(storageGPR, sizeof(JSValue) * operandIdx)); … … 3320 3317 FPRReg opFPR = operand.fpr(); 3321 3318 GPRReg scratchGPR = scratch.gpr(); 3322 if (!isRealNumberSpeculation(m_state.forNode(use).m_type)) { 3323 // FIXME: We need a way of profiling these, and we need to hoist them into 3324 // SpeculateDoubleOperand. 3325 speculationCheck( 3326 BadType, JSValueRegs(), 0, 3327 m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, opFPR, opFPR)); 3328 } 3329 3319 DFG_TYPE_CHECK( 3320 JSValueRegs(), use, SpecRealNumber, 3321 m_jit.branchDouble( 3322 MacroAssembler::DoubleNotEqualOrUnordered, opFPR, opFPR)); 3330 3323 m_jit.boxDouble(opFPR, scratchGPR); 3331 3324 m_jit.store64(scratchGPR, buffer + operandIdx); … … 3333 3326 } 3334 3327 case ALL_INT32_INDEXING_TYPES: { 3335 JSValueOperand operand(this, use );3328 JSValueOperand operand(this, use, ManualOperandSpeculation); 3336 3329 GPRReg opGPR = operand.gpr(); 3337 if (hasInt32(node->indexingType()) && !isInt32Speculation(m_state.forNode(use).m_type)) { 3338 speculationCheck( 3339 BadType, JSValueRegs(opGPR), use, 3340 m_jit.branch64(MacroAssembler::Below, opGPR, GPRInfo::tagTypeNumberRegister)); 3330 if (hasInt32(node->indexingType())) { 3331 DFG_TYPE_CHECK( 3332 JSValueRegs(opGPR), use, SpecInt32, 3333 m_jit.branch64( 3334 MacroAssembler::Below, opGPR, GPRInfo::tagTypeNumberRegister)); 3341 3335 } 3342 3336 m_jit.store64(opGPR, buffer + operandIdx); … … 3560 3554 3561 3555 case ConvertThis: { 3562 if (isObjectSpeculation(m_state.forNode(node->child1()).m_type)) { 3563 SpeculateCellOperand thisValue(this, node->child1()); 3564 GPRTemporary result(this, thisValue); 3565 m_jit.move(thisValue.gpr(), result.gpr()); 3566 cellResult(result.gpr(), node); 3567 break; 3568 } 3569 3570 if (isOtherSpeculation(node->child1()->prediction())) { 3571 JSValueOperand thisValue(this, node->child1()); 3556 switch (node->child1().useKind()) { 3557 case OtherUse: { 3558 JSValueOperand thisValue(this, node->child1(), ManualOperandSpeculation); 3572 3559 GPRTemporary scratch(this); 3573 3560 GPRReg thisValueGPR = thisValue.gpr(); 3574 3561 GPRReg scratchGPR = scratch.gpr(); 3575 3562 3576 if ( !isOtherSpeculation(m_state.forNode(node->child1()).m_type)) {3563 if (needsTypeCheck(node->child1(), SpecOther)) { 3577 3564 m_jit.move(thisValueGPR, scratchGPR); 3578 3565 m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), scratchGPR); 3579 speculationCheck(BadType, JSValueRegs(thisValueGPR), node->child1(), m_jit.branch64(MacroAssembler::NotEqual, scratchGPR, MacroAssembler::TrustedImm64(ValueNull))); 3566 typeCheck( 3567 JSValueRegs(thisValueGPR), node->child1(), SpecOther, 3568 m_jit.branch64( 3569 MacroAssembler::NotEqual, scratchGPR, 3570 MacroAssembler::TrustedImm64(ValueNull))); 3580 3571 } 3581 3572 … … 3585 3576 } 3586 3577 3587 if (isObjectSpeculation(node->child1()->prediction())){3578 case ObjectUse: { 3588 3579 SpeculateCellOperand thisValue(this, node->child1()); 3589 3580 GPRTemporary result(this, thisValue); … … 3591 3582 GPRReg resultGPR = result.gpr(); 3592 3583 3593 if (!isObjectSpeculation(m_state.forNode(node->child1()).m_type)) 3594 speculationCheck(BadType, JSValueSource::unboxedCell(thisValueGPR), node->child1(), m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(thisValueGPR, JSCell::structureOffset()), JITCompiler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 3584 DFG_TYPE_CHECK( 3585 JSValueSource::unboxedCell(thisValueGPR), node->child1(), SpecObject, 3586 m_jit.branchPtr( 3587 JITCompiler::Equal, 3588 JITCompiler::Address(thisValueGPR, JSCell::structureOffset()), 3589 JITCompiler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); 3595 3590 3596 3591 m_jit.move(thisValueGPR, resultGPR); … … 3599 3594 break; 3600 3595 } 3601 3602 JSValueOperand thisValue(this, node->child1()); 3603 GPRReg thisValueGPR = thisValue.gpr(); 3604 3605 flushRegisters(); 3606 3607 GPRResult result(this); 3608 callOperation(operationConvertThis, result.gpr(), thisValueGPR); 3609 3610 cellResult(result.gpr(), node); 3596 3597 case UntypedUse: { 3598 JSValueOperand thisValue(this, node->child1()); 3599 GPRReg thisValueGPR = thisValue.gpr(); 3600 3601 flushRegisters(); 3602 3603 GPRResult result(this); 3604 callOperation(operationConvertThis, result.gpr(), thisValueGPR); 3605 3606 cellResult(result.gpr(), node); 3607 break; 3608 } 3609 3610 default: 3611 RELEASE_ASSERT_NOT_REACHED(); 3612 break; 3613 } 3611 3614 break; 3612 3615 } … … 3777 3780 break; 3778 3781 } 3779 3780 if (isCellSpeculation(node->child1()->prediction())) { 3782 3783 switch (node->child1().useKind()) { 3784 case CellUse: { 3781 3785 SpeculateCellOperand base(this, node->child1()); 3782 3786 GPRTemporary result(this, base); … … 3793 3797 } 3794 3798 3795 JSValueOperand base(this, node->child1()); 3796 GPRTemporary result(this, base); 3797 3798 GPRReg baseGPR = base.gpr(); 3799 GPRReg resultGPR = result.gpr(); 3800 3801 base.use(); 3802 3803 JITCompiler::Jump notCell = m_jit.branchTest64(JITCompiler::NonZero, baseGPR, GPRInfo::tagMaskRegister); 3804 3805 cachedGetById(node->codeOrigin, baseGPR, resultGPR, node->identifierNumber(), notCell); 3806 3807 jsValueResult(resultGPR, node, UseChildrenCalledExplicitly); 3808 3799 case UntypedUse: { 3800 JSValueOperand base(this, node->child1()); 3801 GPRTemporary result(this, base); 3802 3803 GPRReg baseGPR = base.gpr(); 3804 GPRReg resultGPR = result.gpr(); 3805 3806 base.use(); 3807 3808 JITCompiler::Jump notCell = m_jit.branchTest64(JITCompiler::NonZero, baseGPR, GPRInfo::tagMaskRegister); 3809 3810 cachedGetById(node->codeOrigin, baseGPR, resultGPR, node->identifierNumber(), notCell); 3811 3812 jsValueResult(resultGPR, node, UseChildrenCalledExplicitly); 3813 break; 3814 } 3815 3816 default: 3817 RELEASE_ASSERT_NOT_REACHED(); 3818 break; 3819 } 3809 3820 break; 3810 3821 } … … 3815 3826 break; 3816 3827 } 3817 3818 if (isCellSpeculation(node->child1()->prediction())) { 3828 3829 switch (node->child1().useKind()) { 3830 case CellUse: { 3819 3831 SpeculateCellOperand base(this, node->child1()); 3820 3832 GPRReg baseGPR = base.gpr(); … … 3834 3846 } 3835 3847 3836 JSValueOperand base(this, node->child1()); 3837 GPRReg baseGPR = base.gpr(); 3838 3839 GPRResult result(this); 3840 GPRReg resultGPR = result.gpr(); 3841 3842 base.use(); 3843 flushRegisters(); 3844 3845 JITCompiler::Jump notCell = m_jit.branchTest64(JITCompiler::NonZero, baseGPR, GPRInfo::tagMaskRegister); 3846 3847 cachedGetById(node->codeOrigin, baseGPR, resultGPR, node->identifierNumber(), notCell, DontSpill); 3848 3849 jsValueResult(resultGPR, node, UseChildrenCalledExplicitly); 3850 3848 case UntypedUse: { 3849 JSValueOperand base(this, node->child1()); 3850 GPRReg baseGPR = base.gpr(); 3851 3852 GPRResult result(this); 3853 GPRReg resultGPR = result.gpr(); 3854 3855 base.use(); 3856 flushRegisters(); 3857 3858 JITCompiler::Jump notCell = m_jit.branchTest64(JITCompiler::NonZero, baseGPR, GPRInfo::tagMaskRegister); 3859 3860 cachedGetById(node->codeOrigin, baseGPR, resultGPR, node->identifierNumber(), notCell, DontSpill); 3861 3862 jsValueResult(resultGPR, node, UseChildrenCalledExplicitly); 3863 break; 3864 } 3865 3866 default: 3867 RELEASE_ASSERT_NOT_REACHED(); 3868 break; 3869 } 3851 3870 break; 3852 3871 } … … 3872 3891 case CheckStructure: 3873 3892 case ForwardCheckStructure: { 3874 AbstractValue& value = m_state.forNode(node->child1());3875 if (value.m_currentKnownStructure.isSubsetOf(node->structureSet())3876 && isCellSpeculation(value.m_type)) {3877 noResult(node);3878 break;3879 }3880 3881 3893 SpeculationDirection direction = node->op() == ForwardCheckStructure ? ForwardSpeculation : BackwardSpeculation; 3882 3894 SpeculateCellOperand base(this, node->child1(), direction); … … 3943 3955 m_jit.breakpoint(); 3944 3956 isOK.link(&m_jit); 3957 #else 3958 speculateCell(node->child1()); 3945 3959 #endif 3946 3960 … … 3950 3964 3951 3965 case PhantomPutStructure: { 3966 ASSERT(isKnownCell(node->child1().node())); 3967 3952 3968 ASSERT(node->structureTransitionData().previousStructure->transitionWatchpointSetHasBeenInvalidated()); 3953 3969 m_jit.addWeakReferenceTransition( … … 4272 4288 4273 4289 case TypeOf: { 4274 JSValueOperand value(this, node->child1() );4290 JSValueOperand value(this, node->child1(), ManualOperandSpeculation); 4275 4291 GPRReg valueGPR = value.gpr(); 4276 4292 GPRTemporary temp(this); … … 4281 4297 4282 4298 flushRegisters(); 4299 4300 ASSERT(node->child1().useKind() == UntypedUse || node->child1().useKind() == CellUse || node->child1().useKind() == StringUse); 4283 4301 4284 4302 JITCompiler::Jump isNotCell = m_jit.branchTest64(JITCompiler::NonZero, valueGPR, GPRInfo::tagMaskRegister); 4285 if (node->child1() ->shouldSpeculateCell())4286 speculationCheck(BadType, JSValueSource(valueGPR), node->child1(), isNotCell);4287 4288 if (!node->child1()->shouldSpeculateObject() ) {4303 if (node->child1().useKind() != UntypedUse) 4304 DFG_TYPE_CHECK(JSValueSource(valueGPR), node->child1(), SpecCell, isNotCell); 4305 4306 if (!node->child1()->shouldSpeculateObject() || node->child1().useKind() == StringUse) { 4289 4307 m_jit.loadPtr(JITCompiler::Address(valueGPR, JSCell::structureOffset()), tempGPR); 4290 4308 JITCompiler::Jump notString = m_jit.branch8(JITCompiler::NotEqual, JITCompiler::Address(tempGPR, Structure::typeInfoTypeOffset()), TrustedImm32(StringType)); 4291 if (node->child1() ->shouldSpeculateString())4292 speculationCheck(BadType, JSValueSource(valueGPR), node->child1(), notString);4309 if (node->child1().useKind() == StringUse) 4310 DFG_TYPE_CHECK(JSValueSource(valueGPR), node->child1(), SpecString, notString); 4293 4311 m_jit.move(TrustedImmPtr(m_jit.globalData()->smallStrings.stringString()), resultGPR); 4294 4312 doneJumps.append(m_jit.jump()); 4295 if ( !node->child1()->shouldSpeculateString()) {4313 if (node->child1().useKind() != StringUse) { 4296 4314 notString.link(&m_jit); 4297 4315 callOperation(operationTypeOf, resultGPR, valueGPR); … … 4303 4321 } 4304 4322 4305 if ( !node->child1()->shouldSpeculateCell()) {4323 if (node->child1().useKind() == UntypedUse) { 4306 4324 isNotCell.link(&m_jit); 4307 4325 JITCompiler::Jump notNumber = m_jit.branchTest64(JITCompiler::Zero, valueGPR, GPRInfo::tagTypeNumberRegister); … … 4772 4790 4773 4791 case Phantom: 4792 DFG_NODE_DO_TO_CHILDREN(m_jit.graph(), node, speculate); 4793 noResult(node); 4794 break; 4795 4774 4796 case PhantomLocal: 4775 4797 // This is a no-op. -
trunk/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp
r142377 r143654 290 290 Node* getLocal = insertionSet.insertNode( 291 291 indexInBlock + 1, DontRefChildren, DontRefNode, variable->prediction(), 292 GetLocal, codeOrigin, OpInfo(variable), node);292 GetLocal, codeOrigin, OpInfo(variable), Edge(node)); 293 293 insertionSet.insertNode( 294 294 indexInBlock + 1, RefChildren, DontRefNode, SpecNone, CheckStructure, 295 295 codeOrigin, OpInfo(m_graph.addStructureSet(iter->value.m_structure)), 296 getLocal);296 Edge(getLocal, CellUse)); 297 297 298 298 if (block->variablesAtTail.operand(variable->local()) == node) … … 318 318 319 319 CodeOrigin codeOrigin = node->codeOrigin; 320 Node* child1 = node->child1().node();320 Edge child1 = node->child1(); 321 321 322 322 insertionSet.insertNode( … … 328 328 insertionSet.insertNode( 329 329 indexInBlock, RefChildren, DontRefNode, SpecNone, ForwardCheckStructure, 330 codeOrigin, OpInfo(m_graph.addStructureSet(iter->value.m_structure)), child1);330 codeOrigin, OpInfo(m_graph.addStructureSet(iter->value.m_structure)), Edge(child1.node(), CellUse)); 331 331 changed = true; 332 332 break; -
trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp
r142377 r143654 355 355 void reportValidationContext(Node* node, Edge edge) 356 356 { 357 dataLog F("@%u -> %s@%u", node->index(), useKindToString(edge.useKind()), edge->index());357 dataLog(node, " -> ", edge); 358 358 } 359 359 … … 390 390 Node* node, BlockIndex blockIndex, Node* expectedNode, Edge incomingEdge) 391 391 { 392 dataLog F("@%u in Block #%u, searching for @%u from @%u", node->index(), blockIndex, expectedNode->index(), incomingEdge->index());392 dataLog(node, " in Block #", blockIndex, ", searching for ", expectedNode, " from ", incomingEdge); 393 393 } 394 394
Note: See TracChangeset
for help on using the changeset viewer.