Changeset 95273 in webkit
- Timestamp:
- Sep 15, 2011 11:33:55 PM (13 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 20 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r95271 r95273 1 2011-09-15 Filip Pizlo <fpizlo@apple.com> 2 3 DFG JIT does not optimize method_check 4 https://bugs.webkit.org/show_bug.cgi?id=68215 5 6 Reviewed by Oliver Hunt. 7 8 MethodCallLinkInfo and StructureStubInfo are now searchable by 9 bytecodeIndex, so that DFG::ByteCodeParser can use that information 10 to determine how to optimize GetMethod. 11 12 A new node op has been added to DFG: CheckMethod. This is a variant 13 of GetMethod that has been optimized for the case that GetMethod 14 always takes the fast path. CheckMethod results in only a very 15 small amount of code (two loads and two branches in the worst case, 16 one load and one branch in the best case). CheckMethod behaves as 17 if it were a constant. 18 19 Introduced the notion that a DFG node that is not JSConstant 20 behaves as a constant. CheckMethod uses this functionality. 21 22 This is a 3% speed-up on Kraken, and a small speed-up on V8. 23 Appears to be neutral on SunSpider. 24 25 * bytecode/CodeBlock.h: 26 (JSC::getStructureStubInfoBytecodeIndex): 27 (JSC::getMethodCallLinkInfoBytecodeIndex): 28 * bytecode/PredictedType.cpp: 29 (JSC::predictionFromCell): 30 (JSC::predictionFromValue): 31 * bytecode/PredictedType.h: 32 * bytecode/StructureStubInfo.h: 33 * dfg/DFGAliasTracker.h: 34 (JSC::DFG::AliasTracker::recordGetMethod): 35 * dfg/DFGByteCodeParser.cpp: 36 (JSC::DFG::ByteCodeParser::parseBlock): 37 * dfg/DFGGraph.cpp: 38 (JSC::DFG::Graph::dump): 39 * dfg/DFGGraph.h: 40 (JSC::DFG::Graph::getMethodCheckPrediction): 41 (JSC::DFG::Graph::getPrediction): 42 (JSC::DFG::Graph::isConstant): 43 (JSC::DFG::Graph::isJSConstant): 44 (JSC::DFG::Graph::valueOfJSConstant): 45 (JSC::DFG::Graph::valueOfInt32Constant): 46 (JSC::DFG::Graph::valueOfNumberConstant): 47 (JSC::DFG::Graph::valueOfBooleanConstant): 48 (JSC::DFG::Graph::valueOfJSConstantNode): 49 * dfg/DFGJITCodeGenerator.cpp: 50 (JSC::DFG::JITCodeGenerator::fillInteger): 51 (JSC::DFG::JITCodeGenerator::fillDouble): 52 (JSC::DFG::JITCodeGenerator::fillJSValue): 53 (JSC::DFG::JITCodeGenerator::isKnownNotInteger): 54 (JSC::DFG::JITCodeGenerator::isKnownNotNumber): 55 * dfg/DFGJITCodeGenerator.h: 56 (JSC::DFG::JITCodeGenerator::silentSpillFPR): 57 (JSC::DFG::JITCodeGenerator::silentFillGPR): 58 (JSC::DFG::JITCodeGenerator::silentFillFPR): 59 * dfg/DFGJITCompiler.cpp: 60 (JSC::DFG::JITCompiler::fillNumericToDouble): 61 (JSC::DFG::JITCompiler::fillInt32ToInteger): 62 (JSC::DFG::JITCompiler::fillToJS): 63 * dfg/DFGNode.h: 64 (JSC::DFG::Node::hasConstant): 65 (JSC::DFG::Node::hasIdentifier): 66 (JSC::DFG::Node::hasMethodCheckData): 67 (JSC::DFG::Node::methodCheckDataIndex): 68 (JSC::DFG::Node::valueOfJSConstant): 69 * dfg/DFGPropagator.cpp: 70 (JSC::DFG::Propagator::propagateNode): 71 * dfg/DFGSpeculativeJIT.cpp: 72 (JSC::DFG::SpeculativeJIT::fillSpeculateIntInternal): 73 (JSC::DFG::SpeculativeJIT::fillSpeculateDouble): 74 (JSC::DFG::SpeculativeJIT::fillSpeculateCell): 75 (JSC::DFG::SpeculativeJIT::fillSpeculateBoolean): 76 (JSC::DFG::SpeculativeJIT::compile): 77 * jit/JIT.cpp: 78 (JSC::JIT::privateCompile): 79 * jit/JIT.h: 80 (JSC::PropertyStubCompilationInfo::PropertyStubCompilationInfo): 81 (JSC::MethodCallCompilationInfo::MethodCallCompilationInfo): 82 * jit/JITPropertyAccess.cpp: 83 (JSC::JIT::emit_op_method_check): 84 (JSC::JIT::compileGetByIdHotPath): 85 (JSC::JIT::emit_op_put_by_id): 86 * jit/JITPropertyAccess32_64.cpp: 87 (JSC::JIT::emit_op_method_check): 88 (JSC::JIT::compileGetByIdHotPath): 89 (JSC::JIT::emit_op_put_by_id): 90 * runtime/JSCell.h: 91 (JSC::JSCell::JSCell::structureAddress): 92 1 93 2011-09-15 Adam Barth <abarth@webkit.org> 2 94 -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.h
r95240 r95273 154 154 } 155 155 156 unsigned bytecodeIndex; 156 157 CodeLocationCall callReturnLocation; 157 158 JITWriteBarrier<Structure> cachedStructure; … … 198 199 } 199 200 201 inline unsigned getStructureStubInfoBytecodeIndex(StructureStubInfo* structureStubInfo) 202 { 203 return structureStubInfo->bytecodeIndex; 204 } 205 200 206 inline void* getCallLinkInfoReturnLocation(CallLinkInfo* callLinkInfo) 201 207 { … … 206 212 { 207 213 return methodCallLinkInfo->callReturnLocation.executableAddress(); 214 } 215 216 inline unsigned getMethodCallLinkInfoBytecodeIndex(MethodCallLinkInfo* methodCallLinkInfo) 217 { 218 return methodCallLinkInfo->bytecodeIndex; 208 219 } 209 220 … … 272 283 } 273 284 285 StructureStubInfo& getStubInfo(unsigned bytecodeIndex) 286 { 287 return *(binarySearch<StructureStubInfo, unsigned, getStructureStubInfoBytecodeIndex>(m_structureStubInfos.begin(), m_structureStubInfos.size(), bytecodeIndex)); 288 } 289 274 290 CallLinkInfo& getCallLinkInfo(ReturnAddressPtr returnAddress) 275 291 { … … 280 296 { 281 297 return *(binarySearch<MethodCallLinkInfo, void*, getMethodCallLinkInfoReturnLocation>(m_methodCallLinkInfos.begin(), m_methodCallLinkInfos.size(), returnAddress.value())); 298 } 299 300 MethodCallLinkInfo& getMethodCallLinkInfo(unsigned bytecodeIndex) 301 { 302 return *(binarySearch<MethodCallLinkInfo, unsigned, getMethodCallLinkInfoBytecodeIndex>(m_methodCallLinkInfos.begin(), m_methodCallLinkInfos.size(), bytecodeIndex)); 282 303 } 283 304 -
trunk/Source/JavaScriptCore/bytecode/PredictedType.cpp
r95134 r95273 83 83 #endif 84 84 85 PredictedType predictionFromCell(JSCell* cell) 86 { 87 const ClassInfo* classInfo = cell->structure()->classInfo(); 88 89 if (classInfo == &JSFinalObject::s_info) 90 return PredictFinalObject; 91 92 if (classInfo == &JSArray::s_info) 93 return PredictArray; 94 95 if (classInfo == &JSString::s_info) 96 return PredictString; 97 98 if (classInfo->isSubClassOf(&JSObject::s_info)) 99 return PredictObjectOther; 100 101 return PredictCellOther; 102 } 103 85 104 PredictedType predictionFromValue(JSValue value) 86 105 { … … 89 108 if (value.isDouble()) 90 109 return PredictDouble; 91 if (value.isCell()) { 92 const ClassInfo* classInfo = value.asCell()->structure()->classInfo(); 93 94 if (classInfo == &JSFinalObject::s_info) 95 return PredictFinalObject; 96 97 if (classInfo == &JSArray::s_info) 98 return PredictArray; 99 100 if (classInfo == &JSString::s_info) 101 return PredictString; 102 103 if (classInfo->isSubClassOf(&JSObject::s_info)) 104 return PredictObjectOther; 105 106 return PredictCellOther; 107 } 110 if (value.isCell()) 111 return predictionFromCell(value.asCell()); 108 112 if (value.isBoolean()) 109 113 return PredictBoolean; -
trunk/Source/JavaScriptCore/bytecode/PredictedType.h
r95134 r95273 151 151 } 152 152 153 PredictedType predictionFromCell(JSCell*); 153 154 PredictedType predictionFromValue(JSValue); 154 155 -
trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.h
r94920 r95273 127 127 seen = true; 128 128 } 129 130 unsigned bytecodeIndex; 129 131 130 132 int8_t accessType; -
trunk/Source/JavaScriptCore/dfg/DFGAliasTracker.h
r91607 r95273 86 86 void recordGetMethod(NodeIndex getMethod) 87 87 { 88 ASSERT_UNUSED(getMethod, m_graph[getMethod].op == GetMethod );88 ASSERT_UNUSED(getMethod, m_graph[getMethod].op == GetMethod || m_graph[getMethod].op == CheckMethod); 89 89 m_candidateAliasGetByVal = NoNode; 90 90 } -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r95240 r95273 921 921 NodeIndex base = get(getInstruction[2].u.operand); 922 922 unsigned identifier = getInstruction[3].u.operand; 923 924 NodeIndex getMethod = addToGraph(GetMethod, OpInfo(identifier), OpInfo(PredictNone), base); 925 set(getInstruction[1].u.operand, getMethod); 926 stronglyPredict(getMethod); 927 aliases.recordGetMethod(getMethod); 923 924 // Check if the method_check was monomorphic. If so, emit a CheckXYZMethod 925 // node, which is a lot more efficient. 926 StructureStubInfo& stubInfo = m_profiledBlock->getStubInfo(m_currentIndex); 927 MethodCallLinkInfo& methodCall = m_profiledBlock->getMethodCallLinkInfo(m_currentIndex); 928 929 if (methodCall.seen && !!methodCall.cachedStructure && !stubInfo.seen) { 930 // It's monomorphic as far as we can tell, since the method_check was linked 931 // but the slow path (i.e. the normal get_by_id) never fired. 932 933 NodeIndex checkMethod = addToGraph(CheckMethod, OpInfo(identifier), OpInfo(m_graph.m_methodCheckData.size()), base); 934 set(getInstruction[1].u.operand, checkMethod); 935 936 MethodCheckData methodCheckData; 937 methodCheckData.structure = methodCall.cachedStructure.get(); 938 methodCheckData.prototypeStructure = methodCall.cachedPrototypeStructure.get(); 939 methodCheckData.function = methodCall.cachedFunction.get(); 940 methodCheckData.prototype = methodCall.cachedPrototype.get(); 941 m_graph.m_methodCheckData.append(methodCheckData); 942 943 aliases.recordGetMethod(checkMethod); 944 } else { 945 NodeIndex getMethod = addToGraph(GetMethod, OpInfo(identifier), OpInfo(PredictNone), base); 946 set(getInstruction[1].u.operand, getMethod); 947 stronglyPredict(getMethod); 948 aliases.recordGetMethod(getMethod); 949 } 928 950 929 951 m_currentIndex += OPCODE_LENGTH(op_method_check) + OPCODE_LENGTH(op_get_by_id); -
trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp
r95240 r95273 124 124 printf("%s$%u", hasPrinted ? ", " : "", node.constantNumber()); 125 125 if (codeBlock) { 126 JSValue value = node.valueOfJSConstant(codeBlock);126 JSValue value = valueOfJSConstant(codeBlock, nodeIndex); 127 127 printf(" = %s", value.description()); 128 128 } … … 144 144 if (node.hasLocal()) 145 145 printf(" predicting %s", predictionToString(getPrediction(node.local()))); 146 if (node.hasVarNumber())146 else if (node.hasVarNumber()) 147 147 printf(" predicting %s", predictionToString(getGlobalVarPrediction(node.varNumber()))); 148 if (node.hasPrediction())148 else if (node.hasPrediction()) 149 149 printf(" predicting %s", predictionToString(node.getPrediction())); 150 else if (node.hasMethodCheckData()) { 151 MethodCheckData& methodCheckData = m_methodCheckData[node.methodCheckDataIndex()]; 152 printf(" predicting function %p", methodCheckData.function); 153 } 150 154 } 151 155 -
trunk/Source/JavaScriptCore/dfg/DFGGraph.h
r95060 r95273 58 58 }; 59 59 60 struct MethodCheckData { 61 // It is safe to refer to these directly because they are shadowed by 62 // the old JIT's CodeBlock's MethodCallLinkInfo. 63 Structure* structure; 64 Structure* prototypeStructure; 65 JSObject* function; 66 JSObject* prototype; 67 }; 68 60 69 typedef Vector <BlockIndex, 2> PredecessorList; 61 70 … … 172 181 } 173 182 183 PredictedType getMethodCheckPrediction(Node& node) 184 { 185 return makePrediction(predictionFromCell(m_methodCheckData[node.methodCheckDataIndex()].function), StrongPrediction); 186 } 187 174 188 PredictedType getPrediction(Node& node) 175 189 { … … 193 207 case Construct: 194 208 return nodePtr->getPrediction(); 209 case CheckMethod: 210 return getMethodCheckPrediction(*nodePtr); 195 211 default: 196 212 return PredictNone; … … 201 217 bool isConstant(NodeIndex nodeIndex) 202 218 { 203 return at(nodeIndex). isConstant();219 return at(nodeIndex).hasConstant(); 204 220 } 205 221 bool isJSConstant(NodeIndex nodeIndex) 206 222 { 207 return at(nodeIndex). isConstant();223 return at(nodeIndex).hasConstant(); 208 224 } 209 225 bool isInt32Constant(CodeBlock* codeBlock, NodeIndex nodeIndex) … … 226 242 JSValue valueOfJSConstant(CodeBlock* codeBlock, NodeIndex nodeIndex) 227 243 { 228 return at(nodeIndex).valueOfJSConstant(codeBlock); 244 if (at(nodeIndex).hasMethodCheckData()) 245 return JSValue(m_methodCheckData[at(nodeIndex).methodCheckDataIndex()].function); 246 return valueOfJSConstantNode(codeBlock, nodeIndex); 229 247 } 230 248 int32_t valueOfInt32Constant(CodeBlock* codeBlock, NodeIndex nodeIndex) 231 249 { 232 return at(nodeIndex).valueOfInt32Constant(codeBlock);250 return valueOfJSConstantNode(codeBlock, nodeIndex).asInt32(); 233 251 } 234 252 double valueOfNumberConstant(CodeBlock* codeBlock, NodeIndex nodeIndex) 235 253 { 236 return at(nodeIndex).valueOfNumberConstant(codeBlock);254 return valueOfJSConstantNode(codeBlock, nodeIndex).uncheckedGetNumber(); 237 255 } 238 256 bool valueOfBooleanConstant(CodeBlock* codeBlock, NodeIndex nodeIndex) 239 257 { 240 return at(nodeIndex).valueOfBooleanConstant(codeBlock);258 return valueOfJSConstantNode(codeBlock, nodeIndex).getBoolean(); 241 259 } 242 260 … … 249 267 Vector< OwnPtr<BasicBlock> , 8> m_blocks; 250 268 Vector<NodeIndex, 16> m_varArgChildren; 269 Vector<MethodCheckData> m_methodCheckData; 251 270 private: 271 272 JSValue valueOfJSConstantNode(CodeBlock* codeBlock, NodeIndex nodeIndex) 273 { 274 return codeBlock->constantRegister(FirstConstantRegisterIndex + at(nodeIndex).constantNumber()).get(); 275 } 252 276 253 277 // When a node's refCount goes from 0 to 1, it must (logically) recursively ref all of its children, and vice versa. -
trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.cpp
r95240 r95273 53 53 GPRReg gpr = allocate(); 54 54 55 if (node. isConstant()) {55 if (node.hasConstant()) { 56 56 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); 57 57 if (isInt32Constant(nodeIndex)) { … … 125 125 GPRReg gpr = allocate(); 126 126 127 if (node. isConstant()) {127 if (node.hasConstant()) { 128 128 if (isInt32Constant(nodeIndex)) { 129 129 // FIXME: should not be reachable? … … 250 250 GPRReg gpr = allocate(); 251 251 252 if (node. isConstant()) {252 if (node.hasConstant()) { 253 253 if (isInt32Constant(nodeIndex)) { 254 254 info.fillJSValue(gpr, DataFormatJSInteger); … … 405 405 406 406 return info.isJSDouble() || info.isJSCell() || info.isJSBoolean() 407 || (node. isConstant() && !valueOfJSConstant(nodeIndex).isInt32());407 || (node.hasConstant() && !valueOfJSConstant(nodeIndex).isInt32()); 408 408 } 409 409 … … 415 415 416 416 return (!info.isJSDouble() && !info.isJSInteger() && !info.isUnknownJS()) 417 || (node. isConstant() && !isNumberConstant(nodeIndex));417 || (node.hasConstant() && !isNumberConstant(nodeIndex)); 418 418 } 419 419 -
trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.h
r95230 r95273 239 239 if (!info.needsSpill()) { 240 240 // it's either a constant or it's already been spilled 241 ASSERT(m_jit.graph()[info.nodeIndex()]. isConstant() || info.spillFormat() != DataFormatNone);241 ASSERT(m_jit.graph()[info.nodeIndex()].hasConstant() || info.spillFormat() != DataFormatNone); 242 242 return; 243 243 } 244 244 245 245 // it's neither a constant nor has it been spilled. 246 ASSERT(!m_jit.graph()[info.nodeIndex()]. isConstant());246 ASSERT(!m_jit.graph()[info.nodeIndex()].hasConstant()); 247 247 ASSERT(info.spillFormat() == DataFormatNone); 248 248 … … 263 263 264 264 if (registerFormat == DataFormatInteger) { 265 if (node. isConstant()) {265 if (node.hasConstant()) { 266 266 ASSERT(isInt32Constant(nodeIndex)); 267 267 m_jit.move(Imm32(valueOfInt32Constant(nodeIndex)), info.gpr()); … … 271 271 } 272 272 273 if (node. isConstant())273 if (node.hasConstant()) 274 274 m_jit.move(valueOfJSConstantAsImmPtr(nodeIndex), info.gpr()); 275 275 else { … … 288 288 ASSERT(info.registerFormat() == DataFormatDouble); 289 289 290 if (node. isConstant()) {290 if (node.hasConstant()) { 291 291 ASSERT(isNumberConstant(nodeIndex)); 292 292 m_jit.move(JITCompiler::ImmPtr(bitwise_cast<void*>(valueOfNumberConstant(nodeIndex))), canTrample); -
trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
r95240 r95273 44 44 Node& node = graph()[nodeIndex]; 45 45 46 if (node. isConstant()) {46 if (node.hasConstant()) { 47 47 ASSERT(isNumberConstant(nodeIndex)); 48 48 move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfNumberConstant(nodeIndex)))), temporary); … … 64 64 Node& node = graph()[nodeIndex]; 65 65 66 if (node. isConstant()) {66 if (node.hasConstant()) { 67 67 ASSERT(isInt32Constant(nodeIndex)); 68 68 move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr); … … 82 82 Node& node = graph()[nodeIndex]; 83 83 84 if (node. isConstant()) {84 if (node.hasConstant()) { 85 85 if (isInt32Constant(nodeIndex)) { 86 86 JSValue jsValue = jsNumber(valueOfInt32Constant(nodeIndex)); -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r95240 r95273 172 172 macro(PutByIdDirect, NodeMustGenerate) \ 173 173 macro(GetMethod, NodeResultJS | NodeMustGenerate) \ 174 macro(CheckMethod, NodeResultJS | NodeMustGenerate) \ 174 175 macro(GetGlobalVar, NodeResultJS | NodeMustGenerate) \ 175 176 macro(PutGlobalVar, NodeMustGenerate) \ … … 298 299 return op == JSConstant; 299 300 } 301 302 bool hasConstant() 303 { 304 return isConstant() || hasMethodCheckData(); 305 } 300 306 301 307 unsigned constantNumber() … … 303 309 ASSERT(isConstant()); 304 310 return m_opInfo; 305 }306 307 JSValue valueOfJSConstant(CodeBlock* codeBlock)308 {309 return codeBlock->constantRegister(FirstConstantRegisterIndex + constantNumber()).get();310 311 } 311 312 … … 335 336 } 336 337 337 int32_t valueOfInt32Constant(CodeBlock* codeBlock)338 {339 ASSERT(isInt32Constant(codeBlock));340 return valueOfJSConstant(codeBlock).asInt32();341 }342 343 double valueOfNumberConstant(CodeBlock* codeBlock)344 {345 ASSERT(isNumberConstant(codeBlock));346 return valueOfJSConstant(codeBlock).uncheckedGetNumber();347 }348 349 bool valueOfBooleanConstant(CodeBlock* codeBlock)350 {351 ASSERT(isBooleanConstant(codeBlock));352 return valueOfJSConstant(codeBlock).getBoolean();353 }354 355 338 bool hasLocal() 356 339 { … … 365 348 366 349 #if !ASSERT_DISABLED 367 // If we want to use this in production code, should make it faster -368 // e.g. make hasIdentifier a flag in the bitfield.369 350 bool hasIdentifier() 370 351 { 371 return op == GetById || op == PutById || op == PutByIdDirect || op == GetMethod 372 || op == Resolve || op == ResolveBase || op == ResolveBaseStrictPut; 352 switch (op) { 353 case GetById: 354 case PutById: 355 case PutByIdDirect: 356 case GetMethod: 357 case CheckMethod: 358 case Resolve: 359 case ResolveBase: 360 case ResolveBaseStrictPut: 361 return true; 362 default: 363 return false; 364 } 373 365 } 374 366 #endif … … 379 371 return m_opInfo; 380 372 } 381 373 382 374 bool hasVarNumber() 383 375 { … … 481 473 } 482 474 475 bool hasMethodCheckData() 476 { 477 return op == CheckMethod; 478 } 479 480 unsigned methodCheckDataIndex() 481 { 482 ASSERT(hasMethodCheckData()); 483 return m_opInfo2; 484 } 485 483 486 VirtualRegister virtualRegister() 484 487 { … … 570 573 571 574 private: 575 // This is private because it only works for the JSConstant op. The DFG is written under the 576 // assumption that "valueOfJSConstant" can correctly return a constant for any DFG node for 577 // which hasConstant() is true. 578 JSValue valueOfJSConstant(CodeBlock* codeBlock) 579 { 580 return codeBlock->constantRegister(FirstConstantRegisterIndex + constantNumber()).get(); 581 } 582 572 583 // The virtual register number (spill location) associated with this . 573 584 VirtualRegister m_virtualRegister; -
trunk/Source/JavaScriptCore/dfg/DFGPropagator.cpp
r95240 r95273 131 131 switch (op) { 132 132 case JSConstant: { 133 changed |= setPrediction(makePrediction(predictionFromValue( node.valueOfJSConstant(m_codeBlock)), StrongPrediction));133 changed |= setPrediction(makePrediction(predictionFromValue(m_graph.valueOfJSConstant(m_codeBlock, m_compileIndex)), StrongPrediction)); 134 134 break; 135 135 } … … 237 237 break; 238 238 } 239 240 case CheckMethod: { 241 changed |= mergeUse(node.child1(), PredictObjectUnknown | StrongPredictionTag); 242 changed |= setPrediction(m_graph.getMethodCheckPrediction(node)); 243 break; 244 } 239 245 240 246 case Call: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r95240 r95273 43 43 switch (info.registerFormat()) { 44 44 case DataFormatNone: { 45 if (node. isConstant() && !isInt32Constant(nodeIndex)) {45 if (node.hasConstant() && !isInt32Constant(nodeIndex)) { 46 46 terminateSpeculativeExecution(); 47 47 returnFormat = DataFormatInteger; … … 51 51 GPRReg gpr = allocate(); 52 52 53 if (node. isConstant()) {53 if (node.hasConstant()) { 54 54 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); 55 55 ASSERT(isInt32Constant(nodeIndex)); … … 58 58 returnFormat = DataFormatInteger; 59 59 return gpr; 60 } else { 61 DataFormat spillFormat = info.spillFormat(); 62 ASSERT(spillFormat & DataFormatJS); 63 64 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); 65 66 if (spillFormat == DataFormatJSInteger) { 67 // If we know this was spilled as an integer we can fill without checking. 68 if (strict) { 69 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr); 70 info.fillInteger(gpr); 71 returnFormat = DataFormatInteger; 72 return gpr; 73 } 74 m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr); 75 info.fillJSValue(gpr, DataFormatJSInteger); 76 returnFormat = DataFormatJSInteger; 60 } 61 62 DataFormat spillFormat = info.spillFormat(); 63 ASSERT(spillFormat & DataFormatJS); 64 65 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); 66 67 if (spillFormat == DataFormatJSInteger) { 68 // If we know this was spilled as an integer we can fill without checking. 69 if (strict) { 70 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr); 71 info.fillInteger(gpr); 72 returnFormat = DataFormatInteger; 77 73 return gpr; 78 74 } 79 75 m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr); 80 } 76 info.fillJSValue(gpr, DataFormatJSInteger); 77 returnFormat = DataFormatJSInteger; 78 return gpr; 79 } 80 m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr); 81 81 82 82 // Fill as JSValue, and fall through. … … 237 237 GPRReg gpr = allocate(); 238 238 239 if (node. isConstant()) {239 if (node.hasConstant()) { 240 240 if (isInt32Constant(nodeIndex)) { 241 241 FPRReg fpr = fprAllocate(); … … 260 260 terminateSpeculativeExecution(); 261 261 return fprAllocate(); 262 } else {263 DataFormat spillFormat = info.spillFormat();264 ASSERT(spillFormat & DataFormatJS);265 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);266 m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);267 info.fillJSValue(gpr, spillFormat);268 unlock(gpr);269 }262 } 263 264 DataFormat spillFormat = info.spillFormat(); 265 ASSERT(spillFormat & DataFormatJS); 266 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); 267 m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr); 268 info.fillJSValue(gpr, spillFormat); 269 unlock(gpr); 270 270 } 271 271 … … 361 361 GPRReg gpr = allocate(); 362 362 363 if (node. isConstant()) {363 if (node.hasConstant()) { 364 364 JSValue jsValue = valueOfJSConstant(nodeIndex); 365 365 if (jsValue.isCell()) { … … 426 426 GPRReg gpr = allocate(); 427 427 428 if (node. isConstant()) {428 if (node.hasConstant()) { 429 429 JSValue jsValue = valueOfJSConstant(nodeIndex); 430 430 if (jsValue.isBoolean()) { … … 1395 1395 1396 1396 jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly); 1397 break; 1398 } 1399 1400 case CheckMethod: { 1401 MethodCheckData& methodCheckData = m_jit.graph().m_methodCheckData[node.methodCheckDataIndex()]; 1402 1403 SpeculateCellOperand base(this, node.child1()); 1404 GPRTemporary scratch(this); // this needs to be a separate register, unfortunately. 1405 GPRReg baseGPR = base.gpr(); 1406 GPRReg scratchGPR = scratch.gpr(); 1407 1408 speculationCheck(m_jit.branchPtr(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), JITCompiler::TrustedImmPtr(methodCheckData.structure))); 1409 if (methodCheckData.prototype != m_jit.codeBlock()->globalObject()->methodCallDummy()) { 1410 m_jit.move(JITCompiler::TrustedImmPtr(methodCheckData.prototype->structureAddress()), scratchGPR); 1411 speculationCheck(m_jit.branchPtr(JITCompiler::NotEqual, JITCompiler::Address(scratchGPR), JITCompiler::TrustedImmPtr(methodCheckData.prototypeStructure))); 1412 } 1413 1414 useChildren(node); 1415 initConstantInfo(m_compileIndex); 1397 1416 break; 1398 1417 } -
trunk/Source/JavaScriptCore/jit/JIT.cpp
r95240 r95273 629 629 for (unsigned i = 0; i < m_propertyAccessCompilationInfo.size(); ++i) { 630 630 StructureStubInfo& info = m_codeBlock->structureStubInfo(i); 631 ASSERT(m_propertyAccessCompilationInfo[i].bytecodeIndex != std::numeric_limits<unsigned>::max()); 632 info.bytecodeIndex = m_propertyAccessCompilationInfo[i].bytecodeIndex; 631 633 info.callReturnLocation = patchBuffer.locationOf(m_propertyAccessCompilationInfo[i].callReturnLocation); 632 634 info.hotPathBegin = patchBuffer.locationOf(m_propertyAccessCompilationInfo[i].hotPathBegin); … … 644 646 for (unsigned i = 0; i < methodCallCount; ++i) { 645 647 MethodCallLinkInfo& info = m_codeBlock->methodCallLinkInfo(i); 648 info.bytecodeIndex = m_methodCallCompilationInfo[i].bytecodeIndex; 646 649 info.cachedStructure.setLocation(patchBuffer.locationOf(m_methodCallCompilationInfo[i].structureToCompare)); 647 650 info.callReturnLocation = m_codeBlock->structureStubInfo(m_methodCallCompilationInfo[i].propertyAccessIndex).callReturnLocation; -
trunk/Source/JavaScriptCore/jit/JIT.h
r95240 r95273 147 147 148 148 struct PropertyStubCompilationInfo { 149 unsigned bytecodeIndex; 149 150 MacroAssembler::Call callReturnLocation; 150 151 MacroAssembler::Label hotPathBegin; 152 153 #if !ASSERT_DISABLED 154 PropertyStubCompilationInfo() 155 : bytecodeIndex(std::numeric_limits<unsigned>::max()) 156 { 157 } 158 #endif 151 159 }; 152 160 … … 159 167 160 168 struct MethodCallCompilationInfo { 161 MethodCallCompilationInfo(unsigned propertyAccessIndex) 162 : propertyAccessIndex(propertyAccessIndex) 163 { 164 } 165 169 MethodCallCompilationInfo(unsigned bytecodeIndex, unsigned propertyAccessIndex) 170 : bytecodeIndex(bytecodeIndex) 171 , propertyAccessIndex(propertyAccessIndex) 172 { 173 } 174 175 unsigned bytecodeIndex; 166 176 MacroAssembler::DataLabelPtr structureToCompare; 167 177 unsigned propertyAccessIndex; -
trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp
r95219 r95273 290 290 291 291 // Do the method check - check the object & its prototype's structure inline (this is the common case). 292 m_methodCallCompilationInfo.append(MethodCallCompilationInfo(m_ propertyAccessCompilationInfo.size()));292 m_methodCallCompilationInfo.append(MethodCallCompilationInfo(m_bytecodeOffset, m_propertyAccessCompilationInfo.size())); 293 293 MethodCallCompilationInfo& info = m_methodCallCompilationInfo.last(); 294 294 … … 367 367 Label hotPathBegin(this); 368 368 m_propertyAccessCompilationInfo.append(PropertyStubCompilationInfo()); 369 m_propertyAccessCompilationInfo.last().bytecodeIndex = m_bytecodeOffset; 369 370 m_propertyAccessCompilationInfo.last().hotPathBegin = hotPathBegin; 370 371 … … 445 446 Label hotPathBegin(this); 446 447 m_propertyAccessCompilationInfo.append(PropertyStubCompilationInfo()); 448 m_propertyAccessCompilationInfo.last().bytecodeIndex = m_bytecodeOffset; 447 449 m_propertyAccessCompilationInfo.last().hotPathBegin = hotPathBegin; 448 450 -
trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
r94920 r95273 109 109 110 110 // Do the method check - check the object & its prototype's structure inline (this is the common case). 111 m_methodCallCompilationInfo.append(MethodCallCompilationInfo(m_ propertyAccessCompilationInfo.size()));111 m_methodCallCompilationInfo.append(MethodCallCompilationInfo(m_bytecodeOffset, m_propertyAccessCompilationInfo.size())); 112 112 MethodCallCompilationInfo& info = m_methodCallCompilationInfo.last(); 113 113 … … 326 326 Label hotPathBegin(this); 327 327 m_propertyAccessCompilationInfo.append(PropertyStubCompilationInfo()); 328 m_propertyAccessCompilationInfo.last().bytecodeIndex = m_bytecodeOffset; 328 329 m_propertyAccessCompilationInfo.last().hotPathBegin = hotPathBegin; 329 330 … … 402 403 Label hotPathBegin(this); 403 404 m_propertyAccessCompilationInfo.append(PropertyStubCompilationInfo()); 405 m_propertyAccessCompilationInfo.last().bytecodeIndex = m_bytecodeOffset; 404 406 m_propertyAccessCompilationInfo.last().hotPathBegin = hotPathBegin; 405 407 -
trunk/Source/JavaScriptCore/runtime/JSCell.h
r95229 r95273 139 139 return OBJECT_OFFSETOF(JSCell, m_structure); 140 140 } 141 142 void* structureAddress() 143 { 144 return &m_structure; 145 } 141 146 142 147 #if ENABLE(GC_VALIDATION)
Note: See TracChangeset
for help on using the changeset viewer.