Changeset 90529 in webkit
- Timestamp:
- Jul 6, 2011, 8:42:02 PM (14 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 17 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r90502 r90529 1 2011-07-06 Filip Pizlo <fpizlo@apple.com> 2 3 DFG JIT does not support method_check 4 https://bugs.webkit.org/show_bug.cgi?id=63972 5 6 Reviewed by Gavin Barraclough. 7 8 * assembler/CodeLocation.h: 9 (JSC::CodeLocationPossiblyNearCall::CodeLocationPossiblyNearCall): 10 * bytecode/CodeBlock.cpp: 11 (JSC::CodeBlock::visitAggregate): 12 * bytecode/CodeBlock.h: 13 (JSC::MethodCallLinkInfo::MethodCallLinkInfo): 14 (JSC::MethodCallLinkInfo::seenOnce): 15 (JSC::MethodCallLinkInfo::setSeen): 16 * dfg/DFGAliasTracker.h: 17 (JSC::DFG::AliasTracker::recordGetMethod): 18 * dfg/DFGByteCodeParser.cpp: 19 (JSC::DFG::ByteCodeParser::parseBlock): 20 * dfg/DFGJITCodeGenerator.cpp: 21 (JSC::DFG::JITCodeGenerator::cachedGetById): 22 (JSC::DFG::JITCodeGenerator::cachedGetMethod): 23 * dfg/DFGJITCodeGenerator.h: 24 * dfg/DFGJITCompiler.cpp: 25 (JSC::DFG::JITCompiler::compileFunction): 26 * dfg/DFGJITCompiler.h: 27 (JSC::DFG::JITCompiler::addMethodGet): 28 (JSC::DFG::JITCompiler::MethodGetRecord::MethodGetRecord): 29 * dfg/DFGNode.h: 30 (JSC::DFG::Node::hasIdentifier): 31 * dfg/DFGNonSpeculativeJIT.cpp: 32 (JSC::DFG::NonSpeculativeJIT::compile): 33 * dfg/DFGOperations.cpp: 34 * dfg/DFGOperations.h: 35 * dfg/DFGRepatch.cpp: 36 (JSC::DFG::dfgRepatchGetMethodFast): 37 (JSC::DFG::tryCacheGetMethod): 38 (JSC::DFG::dfgRepatchGetMethod): 39 * dfg/DFGRepatch.h: 40 * dfg/DFGSpeculativeJIT.cpp: 41 (JSC::DFG::SpeculativeJIT::compile): 42 * jit/JITWriteBarrier.h: 43 (JSC::JITWriteBarrier::set): 44 1 45 2011-07-06 Filip Pizlo <fpizlo@apple.com> 2 46 -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r90423 r90529 1566 1566 for (size_t size = m_methodCallLinkInfos.size(), i = 0; i < size; ++i) { 1567 1567 if (m_methodCallLinkInfos[i].cachedStructure) { 1568 // Both members must be filled at the same time 1568 // These members must be filled at the same time, and only after 1569 // the MethodCallLinkInfo is set as seen. 1570 ASSERT(m_methodCallLinkInfos[i].seenOnce()); 1569 1571 visitor.append(&m_methodCallLinkInfos[i].cachedStructure); 1570 1572 ASSERT(!!m_methodCallLinkInfos[i].cachedPrototypeStructure); -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.h
r90423 r90529 130 130 struct MethodCallLinkInfo { 131 131 MethodCallLinkInfo() 132 : seen(false) 132 133 { 133 134 } … … 135 136 bool seenOnce() 136 137 { 137 ASSERT(!cachedStructure); 138 return cachedPrototypeStructure.isFlagged(); 138 return seen; 139 139 } 140 140 141 141 void setSeen() 142 142 { 143 ASSERT(!cachedStructure && !cachedPrototypeStructure); 144 // We use the values of cachedStructure & cachedPrototypeStructure to indicate the 145 // current state. 146 // - In the initial state, both are null. 147 // - Once this transition has been taken once, cachedStructure is 148 // null and cachedPrototypeStructure is set to a nun-null value. 149 // - Once the call is linked both structures are set to non-null values. 150 cachedPrototypeStructure.setFlagOnBarrier(); 143 seen = true; 151 144 } 152 145 … … 156 149 JITWriteBarrier<JSFunction> cachedFunction; 157 150 JITWriteBarrier<JSObject> cachedPrototype; 151 bool seen; 158 152 }; 159 153 -
trunk/Source/JavaScriptCore/dfg/DFGAliasTracker.h
r90423 r90529 83 83 m_candidateAliasGetByVal = NoNode; 84 84 } 85 86 void recordGetMethod(NodeIndex getMethod) 87 { 88 ASSERT_UNUSED(getMethod, m_graph[getMethod].op == GetMethod); 89 m_candidateAliasGetByVal = NoNode; 90 } 85 91 86 92 void recordPutById(NodeIndex putById) -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r90423 r90529 853 853 NEXT_OPCODE(op_put_by_val); 854 854 } 855 856 case op_method_check: { 857 Instruction* getInstruction = currentInstruction + OPCODE_LENGTH(op_method_check); 858 859 ASSERT(interpreter->getOpcodeID(getInstruction->u.opcode) == op_get_by_id); 860 861 NodeIndex base = get(getInstruction[2].u.operand); 862 unsigned identifier = getInstruction[3].u.operand; 863 864 NodeIndex getMethod = addToGraph(GetMethod, OpInfo(identifier), base); 865 set(getInstruction[1].u.operand, getMethod); 866 aliases.recordGetMethod(getMethod); 867 868 m_currentIndex += OPCODE_LENGTH(op_method_check) + OPCODE_LENGTH(op_get_by_id); 869 continue; 870 } 855 871 856 872 case op_get_by_id: { … … 858 874 NodeIndex base = get(currentInstruction[2].u.operand); 859 875 unsigned identifier = currentInstruction[3].u.operand; 860 876 861 877 NodeIndex getById = addToGraph(GetById, OpInfo(identifier), base); 862 878 set(currentInstruction[1].u.operand, getById); -
trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.cpp
r90502 r90529 326 326 } 327 327 328 void JITCodeGenerator::cachedGetById(GPRReg baseGPR, GPRReg resultGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget)328 JITCompiler::Call JITCodeGenerator::cachedGetById(GPRReg baseGPR, GPRReg resultGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget, NodeType nodeType) 329 329 { 330 330 GPRReg scratchGPR; … … 354 354 m_jit.move(JITCompiler::ImmPtr(identifier(identifierNumber)), GPRInfo::argumentGPR2); 355 355 m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); 356 JITCompiler::Call functionCall = appendCallWithExceptionCheck(operationGetByIdOptimize); 356 JITCompiler::Call functionCall; 357 switch (nodeType) { 358 case GetById: 359 functionCall = appendCallWithExceptionCheck(operationGetByIdOptimize); 360 break; 361 362 case GetMethod: 363 functionCall = appendCallWithExceptionCheck(operationGetMethodOptimize); 364 break; 365 366 default: 367 ASSERT_NOT_REACHED(); 368 return JITCompiler::Call(); 369 } 357 370 m_jit.move(GPRInfo::returnValueGPR, resultGPR); 358 371 silentFillAllRegisters(resultGPR); … … 372 385 if (scratchGPR != resultGPR && scratchGPR != InvalidGPRReg) 373 386 unlock(scratchGPR); 387 388 return functionCall; 374 389 } 375 390 … … 429 444 430 445 m_jit.addPropertyAccess(functionCall, checkImmToCall, callToCheck, callToStore, callToSlowCase, callToDone, static_cast<int8_t>(baseGPR), static_cast<int8_t>(valueGPR), static_cast<int8_t>(scratchGPR)); 446 } 447 448 void JITCodeGenerator::cachedGetMethod(GPRReg baseGPR, GPRReg resultGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget) 449 { 450 JITCompiler::Call slowCall; 451 JITCompiler::DataLabelPtr structToCompare, protoObj, protoStructToCompare, putFunction; 452 453 JITCompiler::Jump wrongStructure = m_jit.branchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1))); 454 protoObj = m_jit.moveWithPatch(JITCompiler::TrustedImmPtr(0), resultGPR); 455 JITCompiler::Jump wrongProtoStructure = m_jit.branchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(resultGPR, JSCell::structureOffset()), protoStructToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1))); 456 457 putFunction = m_jit.moveWithPatch(JITCompiler::TrustedImmPtr(0), resultGPR); 458 459 JITCompiler::Jump done = m_jit.jump(); 460 461 wrongStructure.link(&m_jit); 462 wrongProtoStructure.link(&m_jit); 463 464 slowCall = cachedGetById(baseGPR, resultGPR, identifierNumber, slowPathTarget, GetMethod); 465 466 done.link(&m_jit); 467 468 m_jit.addMethodGet(slowCall, structToCompare, protoObj, protoStructToCompare, putFunction); 431 469 } 432 470 -
trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.h
r90502 r90529 523 523 } 524 524 525 void cachedGetById(GPRReg baseGPR, GPRReg resultGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget = JITCompiler::Jump());525 JITCompiler::Call cachedGetById(GPRReg baseGPR, GPRReg resultGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget = JITCompiler::Jump(), NodeType = GetById); 526 526 void cachedPutById(GPRReg baseGPR, GPRReg valueGPR, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump()); 527 void cachedGetMethod(GPRReg baseGPR, GPRReg resultGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget = JITCompiler::Jump()); 527 528 528 529 MacroAssembler::Address addressOfCallData(int idx) -
trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
r90423 r90529 296 296 m_propertyAccesses.clear(); 297 297 m_jsCalls.clear(); 298 m_methodGets.clear(); 298 299 rewindToLabel(speculativePathBegin); 299 300 … … 410 411 } 411 412 413 m_codeBlock->addMethodCallLinkInfos(m_methodGets.size()); 414 for (unsigned i = 0; i < m_methodGets.size(); ++i) { 415 MethodCallLinkInfo& info = m_codeBlock->methodCallLinkInfo(i); 416 info.cachedStructure.setLocation(linkBuffer.locationOf(m_methodGets[i].m_structToCompare)); 417 info.cachedPrototypeStructure.setLocation(linkBuffer.locationOf(m_methodGets[i].m_protoStructToCompare)); 418 info.cachedFunction.setLocation(linkBuffer.locationOf(m_methodGets[i].m_putFunction)); 419 info.cachedPrototype.setLocation(linkBuffer.locationOf(m_methodGets[i].m_protoObj)); 420 info.callReturnLocation = linkBuffer.locationOf(m_methodGets[i].m_slowCall); 421 } 422 412 423 // FIXME: switch the register file check & arity check over to DFGOpertaion style calls, not JIT stubs. 413 424 linkBuffer.link(callRegisterFileCheck, cti_register_file_check); -
trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h
r90423 r90529 269 269 } 270 270 271 void addMethodGet(Call slowCall, DataLabelPtr structToCompare, DataLabelPtr protoObj, DataLabelPtr protoStructToCompare, DataLabelPtr putFunction) 272 { 273 m_methodGets.append(MethodGetRecord(slowCall, structToCompare, protoObj, protoStructToCompare, putFunction)); 274 } 275 271 276 void addJSCall(Call fastCall, Call slowCall, DataLabelPtr targetToCheck, bool isCall, unsigned exceptionInfo) 272 277 { … … 317 322 int8_t m_valueGPR; 318 323 int8_t m_scratchGPR; 324 }; 325 326 struct MethodGetRecord { 327 MethodGetRecord(Call slowCall, DataLabelPtr structToCompare, DataLabelPtr protoObj, DataLabelPtr protoStructToCompare, DataLabelPtr putFunction) 328 : m_slowCall(slowCall) 329 , m_structToCompare(structToCompare) 330 , m_protoObj(protoObj) 331 , m_protoStructToCompare(protoStructToCompare) 332 , m_putFunction(putFunction) 333 { 334 } 335 336 Call m_slowCall; 337 DataLabelPtr m_structToCompare; 338 DataLabelPtr m_protoObj; 339 DataLabelPtr m_protoStructToCompare; 340 DataLabelPtr m_putFunction; 319 341 }; 320 342 … … 337 359 338 360 Vector<PropertyAccessRecord, 4> m_propertyAccesses; 361 Vector<MethodGetRecord, 4> m_methodGets; 339 362 Vector<JSCallRecord, 4> m_jsCalls; 340 363 }; -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r90423 r90529 129 129 macro(PutById, NodeMustGenerate) \ 130 130 macro(PutByIdDirect, NodeMustGenerate) \ 131 macro(GetMethod, NodeResultJS | NodeMustGenerate) \ 131 132 macro(GetGlobalVar, NodeResultJS | NodeMustGenerate) \ 132 133 macro(PutGlobalVar, NodeMustGenerate) \ … … 267 268 bool hasIdentifier() 268 269 { 269 return op == GetById || op == PutById || op == PutByIdDirect ;270 return op == GetById || op == PutById || op == PutByIdDirect || op == GetMethod; 270 271 } 271 272 -
trunk/Source/JavaScriptCore/dfg/DFGNonSpeculativeJIT.cpp
r90502 r90529 839 839 } 840 840 841 case GetMethod: { 842 JSValueOperand base(this, node.child1()); 843 GPRReg baseGPR = base.gpr(); 844 GPRTemporary result(this, base); 845 GPRReg resultGPR = result.gpr(); 846 847 JITCompiler::Jump notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, baseGPR, GPRInfo::tagMaskRegister); 848 849 cachedGetMethod(baseGPR, resultGPR, node.identifierNumber(), notCell); 850 851 jsValueResult(resultGPR, m_compileIndex); 852 break; 853 } 854 841 855 case PutById: { 842 856 JSValueOperand base(this, node.child1()); -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r90437 r90529 229 229 } 230 230 231 EncodedJSValue operationGetMethodOptimizeWithReturnAddress(ExecState*, EncodedJSValue, Identifier*, ReturnAddressPtr); 232 FUNCTION_WRAPPER_WITH_ARG4_RETURN_ADDRESS(operationGetMethodOptimize); 233 EncodedJSValue operationGetMethodOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue encodedBase, Identifier* propertyName, ReturnAddressPtr returnAddress) 234 { 235 JSValue baseValue = JSValue::decode(encodedBase); 236 PropertySlot slot(baseValue); 237 JSValue result = baseValue.get(exec, *propertyName, slot); 238 239 MethodCallLinkInfo& methodInfo = exec->codeBlock()->getMethodCallLinkInfo(returnAddress); 240 if (methodInfo.seenOnce()) 241 dfgRepatchGetMethod(exec, baseValue, *propertyName, slot, methodInfo); 242 else 243 methodInfo.setSeen(); 244 245 return JSValue::encode(result); 246 } 247 248 EncodedJSValue operationGetByIdBuildListWithReturnAddress(ExecState*, EncodedJSValue, Identifier*, ReturnAddressPtr); 249 FUNCTION_WRAPPER_WITH_ARG4_RETURN_ADDRESS(operationGetByIdBuildList); 250 EncodedJSValue operationGetByIdBuildListWithReturnAddress(ExecState* exec, EncodedJSValue encodedBase, Identifier* propertyName, ReturnAddressPtr returnAddress) 251 { 252 JSValue baseValue = JSValue::decode(encodedBase); 253 PropertySlot slot(baseValue); 254 JSValue result = baseValue.get(exec, *propertyName, slot); 255 256 StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress); 257 dfgBuildGetByIDList(exec, baseValue, *propertyName, slot, stubInfo); 258 259 return JSValue::encode(result); 260 } 261 231 262 EncodedJSValue operationGetByIdOptimizeWithReturnAddress(ExecState*, EncodedJSValue, Identifier*, ReturnAddressPtr); 232 263 FUNCTION_WRAPPER_WITH_ARG4_RETURN_ADDRESS(operationGetByIdOptimize); … … 242 273 else 243 274 stubInfo.seen = true; 244 245 return JSValue::encode(result);246 }247 248 EncodedJSValue operationGetByIdBuildListWithReturnAddress(ExecState*, EncodedJSValue, Identifier*, ReturnAddressPtr);249 FUNCTION_WRAPPER_WITH_ARG4_RETURN_ADDRESS(operationGetByIdBuildList);250 EncodedJSValue operationGetByIdBuildListWithReturnAddress(ExecState* exec, EncodedJSValue encodedBase, Identifier* propertyName, ReturnAddressPtr returnAddress)251 {252 JSValue baseValue = JSValue::decode(encodedBase);253 PropertySlot slot(baseValue);254 JSValue result = baseValue.get(exec, *propertyName, slot);255 256 StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);257 dfgBuildGetByIDList(exec, baseValue, *propertyName, slot, stubInfo);258 275 259 276 return JSValue::encode(result); -
trunk/Source/JavaScriptCore/dfg/DFGOperations.h
r90423 r90529 62 62 EncodedJSValue operationGetByIdBuildList(ExecState*, EncodedJSValue encodedBase, Identifier*); 63 63 EncodedJSValue operationGetByIdOptimize(ExecState*, EncodedJSValue encodedBase, Identifier*); 64 EncodedJSValue operationGetMethodOptimize(ExecState*, EncodedJSValue encodedBase, Identifier*); 64 65 EncodedJSValue operationInstanceOf(ExecState*, EncodedJSValue value, EncodedJSValue base, EncodedJSValue prototype); 65 66 void operationThrowHasInstanceError(ExecState*, EncodedJSValue base); -
trunk/Source/JavaScriptCore/dfg/DFGRepatch.cpp
r90423 r90529 162 162 } 163 163 164 static void dfgRepatchGetMethodFast(JSGlobalData* globalData, CodeBlock* codeBlock, MethodCallLinkInfo& methodInfo, JSFunction* callee, Structure* structure, JSObject* slotBaseObject) 165 { 166 ScriptExecutable* owner = codeBlock->ownerExecutable(); 167 168 RepatchBuffer repatchBuffer(codeBlock); 169 170 // Only optimize once! 171 repatchBuffer.relink(methodInfo.callReturnLocation, operationGetById); 172 173 methodInfo.cachedStructure.set(*globalData, owner, structure); 174 methodInfo.cachedPrototypeStructure.set(*globalData, owner, slotBaseObject->structure()); 175 methodInfo.cachedPrototype.set(*globalData, owner, slotBaseObject); 176 methodInfo.cachedFunction.set(*globalData, owner, callee); 177 } 178 179 static bool tryCacheGetMethod(ExecState* exec, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, MethodCallLinkInfo& methodInfo) 180 { 181 CodeBlock* codeBlock = exec->codeBlock(); 182 JSGlobalData* globalData = &exec->globalData(); 183 184 Structure* structure; 185 JSCell* specific; 186 JSObject* slotBaseObject; 187 if (baseValue.isCell() 188 && slot.isCacheableValue() 189 && !(structure = baseValue.asCell()->structure())->isUncacheableDictionary() 190 && (slotBaseObject = asObject(slot.slotBase()))->getPropertySpecificValue(exec, propertyName, specific) 191 && specific) { 192 193 JSFunction* callee = (JSFunction*)specific; 194 195 // Since we're accessing a prototype in a loop, it's a good bet that it 196 // should not be treated as a dictionary. 197 if (slotBaseObject->structure()->isDictionary()) 198 slotBaseObject->flattenDictionaryObject(exec->globalData()); 199 200 if (slot.slotBase() == structure->prototypeForLookup(exec)) { 201 dfgRepatchGetMethodFast(globalData, codeBlock, methodInfo, callee, structure, slotBaseObject); 202 return true; 203 } 204 205 if (slot.slotBase() == baseValue) { 206 dfgRepatchGetMethodFast(globalData, codeBlock, methodInfo, callee, structure, exec->scopeChain()->globalObject->methodCallDummy()); 207 return true; 208 } 209 } 210 211 return false; 212 } 213 214 void dfgRepatchGetMethod(ExecState* exec, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, MethodCallLinkInfo& methodInfo) 215 { 216 bool cached = tryCacheGetMethod(exec, baseValue, propertyName, slot, methodInfo); 217 if (!cached) 218 dfgRepatchCall(exec->codeBlock(), methodInfo.callReturnLocation, operationGetByIdOptimize); 219 } 220 164 221 static bool tryBuildGetByIDList(ExecState* exec, JSValue baseValue, const Identifier&, const PropertySlot& slot, StructureStubInfo& stubInfo) 165 222 { -
trunk/Source/JavaScriptCore/dfg/DFGRepatch.h
r90423 r90529 35 35 36 36 void dfgRepatchGetByID(ExecState*, JSValue, const Identifier&, const PropertySlot&, StructureStubInfo&); 37 void dfgRepatchGetMethod(ExecState*, JSValue, const Identifier&, const PropertySlot&, MethodCallLinkInfo&); 37 38 void dfgBuildGetByIDList(ExecState*, JSValue, const Identifier&, const PropertySlot&, StructureStubInfo&); 38 39 void dfgRepatchPutByID(ExecState*, JSValue, const Identifier&, const PutPropertySlot&, StructureStubInfo&, PutKind); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r90502 r90529 1020 1020 break; 1021 1021 } 1022 1023 case GetMethod: { 1024 SpeculateCellOperand base(this, node.child1()); 1025 GPRTemporary result(this, base); 1026 1027 GPRReg resultGPR = result.gpr(); 1028 1029 cachedGetMethod(base.gpr(), resultGPR, node.identifierNumber()); 1030 1031 jsValueResult(resultGPR, m_compileIndex); 1032 break; 1033 } 1022 1034 1023 1035 case PutById: { -
trunk/Source/JavaScriptCore/jit/JITWriteBarrier.h
r89885 r90529 122 122 JITWriteBarrierBase::set(globalData, location, owner, value); 123 123 } 124 void set(JSGlobalData& globalData, JSCell* owner, T* value) 125 { 126 set(globalData, location(), owner, value); 127 } 124 128 T* get() const 125 129 {
Note:
See TracChangeset
for help on using the changeset viewer.