Changeset 46618 in webkit for trunk/JavaScriptCore/jit/JITStubs.cpp
- Timestamp:
- Jul 30, 2009, 7:20:11 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/jit/JITStubs.cpp
r46610 r46618 584 584 JITThunks::JITThunks(JSGlobalData* globalData) 585 585 { 586 JIT::compileCTIMachineTrampolines(globalData, &m_executablePool, &m_ctiStringLengthTrampoline, &m_ctiVirtualCall PreLink, &m_ctiVirtualCallLink, &m_ctiVirtualCall, &m_ctiNativeCallThunk);586 JIT::compileCTIMachineTrampolines(globalData, &m_executablePool, &m_ctiStringLengthTrampoline, &m_ctiVirtualCallLink, &m_ctiVirtualCall, &m_ctiNativeCallThunk); 587 587 588 588 #if PLATFORM_ARM_ARCH(7) … … 607 607 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) 608 608 609 NEVER_INLINE void JITThunks::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const PutPropertySlot& slot )609 NEVER_INLINE void JITThunks::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const PutPropertySlot& slot, StructureStubInfo* stubInfo) 610 610 { 611 611 // The interpreter checks for recursion here; I do not believe this can occur in CTI. … … 633 633 return; 634 634 } 635 636 StructureStubInfo* stubInfo = &codeBlock->getStubInfo(returnAddress);637 635 638 636 // Cache hit: Specialize instruction and ref Structures. … … 655 653 } 656 654 657 NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot )655 NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo* stubInfo) 658 656 { 659 657 // FIXME: Write a test that proves we need to check for recursion here just … … 693 691 return; 694 692 } 695 696 // In the interpreter the last structure is trapped here; in CTI we use the697 // *_second method to achieve a similar (but not quite the same) effect.698 699 StructureStubInfo* stubInfo = &codeBlock->getStubInfo(returnAddress);700 693 701 694 // Cache hit: Specialize instruction and ref Structures. … … 727 720 size_t count = countPrototypeChainEntriesAndCheckForProxies(callFrame, baseValue, slot); 728 721 if (!count) { 729 stubInfo-> opcodeID = op_get_by_id_generic;722 stubInfo->accessType = access_get_by_id_generic; 730 723 return; 731 724 } … … 1029 1022 CallFrame* callFrame = stackFrame.callFrame; 1030 1023 Identifier& ident = stackFrame.args[1].identifier(); 1031 1032 1024 PutPropertySlot slot; 1033 1025 stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot); 1034 1035 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_id_second)); 1036 1037 CHECK_FOR_EXCEPTION_AT_END(); 1038 } 1039 1040 DEFINE_STUB_FUNCTION(void, op_put_by_id_second) 1041 { 1042 STUB_INIT_STACK_FRAME(stackFrame); 1043 1044 PutPropertySlot slot; 1045 stackFrame.args[0].jsValue().put(stackFrame.callFrame, stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot); 1046 JITThunks::tryCachePutByID(stackFrame.callFrame, stackFrame.callFrame->codeBlock(), STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot); 1026 CodeBlock* codeBlock = stackFrame.callFrame->codeBlock(); 1027 StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS); 1028 1029 if (!stubInfo->seenOnce()) 1030 stubInfo->setSeen(); 1031 else 1032 JITThunks::tryCachePutByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot, stubInfo); 1033 1047 1034 CHECK_FOR_EXCEPTION_AT_END(); 1048 1035 } … … 1076 1063 } 1077 1064 1078 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id )1065 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check) 1079 1066 { 1080 1067 STUB_INIT_STACK_FRAME(stackFrame); … … 1082 1069 CallFrame* callFrame = stackFrame.callFrame; 1083 1070 Identifier& ident = stackFrame.args[1].identifier(); 1084 1085 1071 JSValue baseValue = stackFrame.args[0].jsValue(); 1086 1072 PropertySlot slot(baseValue); 1087 1073 JSValue result = baseValue.get(callFrame, ident, slot); 1088 1089 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_second)); 1090 1091 CHECK_FOR_EXCEPTION_AT_END(); 1092 return JSValue::encode(result); 1093 } 1094 1095 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check) 1074 CHECK_FOR_EXCEPTION(); 1075 MethodCallLinkInfo& methodCallLinkInfo = callFrame->codeBlock()->getMethodCallLinkInfo(STUB_RETURN_ADDRESS); 1076 1077 if (!methodCallLinkInfo.seenOnce()) 1078 methodCallLinkInfo.setSeen(); 1079 else { 1080 // If we successfully got something, then the base from which it is being accessed must 1081 // be an object. (Assertion to ensure asObject() call below is safe, which comes after 1082 // an isCacheable() chceck. 1083 ASSERT(!slot.isCacheable() || slot.slotBase().isObject()); 1084 1085 // Check that: 1086 // * We're dealing with a JSCell, 1087 // * the property is cachable, 1088 // * it's not a dictionary 1089 // * there is a function cached. 1090 Structure* structure; 1091 JSCell* specific; 1092 JSObject* slotBaseObject; 1093 if (baseValue.isCell() 1094 && slot.isCacheable() 1095 && !(structure = asCell(baseValue)->structure())->isDictionary() 1096 && (slotBaseObject = asObject(slot.slotBase()))->getPropertySpecificValue(callFrame, ident, specific) 1097 && specific 1098 ) { 1099 1100 JSFunction* callee = (JSFunction*)specific; 1101 1102 // Since we're accessing a prototype in a loop, it's a good bet that it 1103 // should not be treated as a dictionary. 1104 if (slotBaseObject->structure()->isDictionary()) 1105 slotBaseObject->setStructure(Structure::fromDictionaryTransition(slotBaseObject->structure())); 1106 1107 // The result fetched should always be the callee! 1108 ASSERT(result == JSValue(callee)); 1109 1110 // Check to see if the function is on the object's prototype. Patch up the code to optimize. 1111 if (slot.slotBase() == structure->prototypeForLookup(callFrame)) 1112 JIT::patchMethodCallProto(callFrame->codeBlock(), methodCallLinkInfo, callee, structure, slotBaseObject); 1113 // Check to see if the function is on the object itself. 1114 // Since we generate the method-check to check both the structure and a prototype-structure (since this 1115 // is the common case) we have a problem - we need to patch the prototype structure check to do something 1116 // useful. We could try to nop it out altogether, but that's a little messy, so lets do something simpler 1117 // for now. For now it performs a check on a special object on the global object only used for this 1118 // purpose. The object is in no way exposed, and as such the check will always pass. 1119 else if (slot.slotBase() == baseValue) 1120 JIT::patchMethodCallProto(callFrame->codeBlock(), methodCallLinkInfo, callee, structure, callFrame->scopeChain()->globalObject()->methodCallDummy()); 1121 1122 // For now let any other case be cached as a normal get_by_id. 1123 } 1124 1125 // Revert the get_by_id op back to being a regular get_by_id - allow it to cache like normal, if it needs to. 1126 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id)); 1127 } 1128 1129 return JSValue::encode(result); 1130 } 1131 1132 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id) 1096 1133 { 1097 1134 STUB_INIT_STACK_FRAME(stackFrame); … … 1099 1136 CallFrame* callFrame = stackFrame.callFrame; 1100 1137 Identifier& ident = stackFrame.args[1].identifier(); 1101 1102 1138 JSValue baseValue = stackFrame.args[0].jsValue(); 1103 1139 PropertySlot slot(baseValue); 1104 1140 JSValue result = baseValue.get(callFrame, ident, slot); 1105 1106 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_method_check_second)); 1107 1108 CHECK_FOR_EXCEPTION_AT_END(); 1109 return JSValue::encode(result); 1110 } 1111 1112 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check_second) 1113 { 1114 STUB_INIT_STACK_FRAME(stackFrame); 1115 1116 CallFrame* callFrame = stackFrame.callFrame; 1117 Identifier& ident = stackFrame.args[1].identifier(); 1118 1119 JSValue baseValue = stackFrame.args[0].jsValue(); 1120 PropertySlot slot(baseValue); 1121 JSValue result = baseValue.get(callFrame, ident, slot); 1122 1123 CHECK_FOR_EXCEPTION(); 1124 1125 // If we successfully got something, then the base from which it is being accessed must 1126 // be an object. (Assertion to ensure asObject() call below is safe, which comes after 1127 // an isCacheable() chceck. 1128 ASSERT(!slot.isCacheable() || slot.slotBase().isObject()); 1129 1130 // Check that: 1131 // * We're dealing with a JSCell, 1132 // * the property is cachable, 1133 // * it's not a dictionary 1134 // * there is a function cached. 1135 Structure* structure; 1136 JSCell* specific; 1137 JSObject* slotBaseObject; 1138 if (baseValue.isCell() 1139 && slot.isCacheable() 1140 && !(structure = asCell(baseValue)->structure())->isDictionary() 1141 && (slotBaseObject = asObject(slot.slotBase()))->getPropertySpecificValue(callFrame, ident, specific) 1142 && specific 1143 ) { 1144 1145 JSFunction* callee = (JSFunction*)specific; 1146 1147 // Since we're accessing a prototype in a loop, it's a good bet that it 1148 // should not be treated as a dictionary. 1149 if (slotBaseObject->structure()->isDictionary()) 1150 slotBaseObject->setStructure(Structure::fromDictionaryTransition(slotBaseObject->structure())); 1151 1152 // The result fetched should always be the callee! 1153 ASSERT(result == JSValue(callee)); 1154 MethodCallLinkInfo& methodCallLinkInfo = callFrame->codeBlock()->getMethodCallLinkInfo(STUB_RETURN_ADDRESS); 1155 1156 // Check to see if the function is on the object's prototype. Patch up the code to optimize. 1157 if (slot.slotBase() == structure->prototypeForLookup(callFrame)) 1158 JIT::patchMethodCallProto(callFrame->codeBlock(), methodCallLinkInfo, callee, structure, slotBaseObject); 1159 // Check to see if the function is on the object itself. 1160 // Since we generate the method-check to check both the structure and a prototype-structure (since this 1161 // is the common case) we have a problem - we need to patch the prototype structure check to do something 1162 // useful. We could try to nop it out altogether, but that's a little messy, so lets do something simpler 1163 // for now. For now it performs a check on a special object on the global object only used for this 1164 // purpose. The object is in no way exposed, and as such the check will always pass. 1165 else if (slot.slotBase() == baseValue) 1166 JIT::patchMethodCallProto(callFrame->codeBlock(), methodCallLinkInfo, callee, structure, callFrame->scopeChain()->globalObject()->methodCallDummy()); 1167 1168 // For now let any other case be cached as a normal get_by_id. 1169 } 1170 1171 // Revert the get_by_id op back to being a regular get_by_id - allow it to cache like normal, if it needs to. 1172 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id)); 1173 1174 return JSValue::encode(result); 1175 } 1176 1177 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_second) 1178 { 1179 STUB_INIT_STACK_FRAME(stackFrame); 1180 1181 CallFrame* callFrame = stackFrame.callFrame; 1182 Identifier& ident = stackFrame.args[1].identifier(); 1183 1184 JSValue baseValue = stackFrame.args[0].jsValue(); 1185 PropertySlot slot(baseValue); 1186 JSValue result = baseValue.get(callFrame, ident, slot); 1187 1188 JITThunks::tryCacheGetByID(callFrame, callFrame->codeBlock(), STUB_RETURN_ADDRESS, baseValue, ident, slot); 1141 CodeBlock* codeBlock = callFrame->codeBlock(); 1142 StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS); 1143 1144 if (!stubInfo->seenOnce()) 1145 stubInfo->setSeen(); 1146 else 1147 JITThunks::tryCacheGetByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, baseValue, ident, slot, stubInfo); 1189 1148 1190 1149 CHECK_FOR_EXCEPTION_AT_END(); … … 1218 1177 int listIndex = 1; 1219 1178 1220 if (stubInfo-> opcodeID == op_get_by_id_self) {1179 if (stubInfo->accessType == access_get_by_id_self) { 1221 1180 ASSERT(!stubInfo->stubRoutine); 1222 1181 polymorphicStructureList = new PolymorphicAccessStructureList(CodeLocationLabel(), stubInfo->u.getByIdSelf.baseObjectStructure); … … 1242 1201 listIndex = 1; 1243 1202 1244 switch (stubInfo-> opcodeID) {1245 case op_get_by_id_proto:1203 switch (stubInfo->accessType) { 1204 case access_get_by_id_proto: 1246 1205 prototypeStructureList = new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdProto.baseObjectStructure, stubInfo->u.getByIdProto.prototypeStructure); 1247 1206 stubInfo->stubRoutine = CodeLocationLabel(); 1248 1207 stubInfo->initGetByIdProtoList(prototypeStructureList, 2); 1249 1208 break; 1250 case op_get_by_id_chain:1209 case access_get_by_id_chain: 1251 1210 prototypeStructureList = new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure, stubInfo->u.getByIdChain.chain); 1252 1211 stubInfo->stubRoutine = CodeLocationLabel(); 1253 1212 stubInfo->initGetByIdProtoList(prototypeStructureList, 2); 1254 1213 break; 1255 case op_get_by_id_proto_list:1214 case access_get_by_id_proto_list: 1256 1215 prototypeStructureList = stubInfo->u.getByIdProtoList.structureList; 1257 1216 listIndex = stubInfo->u.getByIdProtoList.listSize; … … 1520 1479 1521 1480 #if ENABLE(JIT_OPTIMIZE_CALL) 1522 DEFINE_STUB_FUNCTION(void*, vm_ dontLazyLinkCall)1481 DEFINE_STUB_FUNCTION(void*, vm_lazyLinkCall) 1523 1482 { 1524 1483 STUB_INIT_STACK_FRAME(stackFrame); … … 1526 1485 JSGlobalData* globalData = stackFrame.globalData; 1527 1486 JSFunction* callee = asFunction(stackFrame.args[0].jsValue()); 1528 1529 ctiPatchNearCallByReturnAddress(stackFrame.callFrame->callerFrame()->codeBlock(), stackFrame.args[1].returnAddress(), globalData->jitStubs.ctiVirtualCallLink());1530 1531 return callee->body()->generatedJITCode().addressForCall().executableAddress();1532 }1533 1534 DEFINE_STUB_FUNCTION(void*, vm_lazyLinkCall)1535 {1536 STUB_INIT_STACK_FRAME(stackFrame);1537 1538 JSFunction* callee = asFunction(stackFrame.args[0].jsValue());1539 1487 JITCode& jitCode = callee->body()->generatedJITCode(); 1540 1541 CodeBlock* codeBlock = 0;1542 if (!callee->isHostFunction())1543 codeBlock = &callee->body()->bytecode(callee->scope().node());1544 else1545 codeBlock = &callee->body()->generatedBytecode();1546 1547 1488 CallLinkInfo* callLinkInfo = &stackFrame.callFrame->callerFrame()->codeBlock()->getCallLinkInfo(stackFrame.args[1].returnAddress()); 1548 JIT::linkCall(callee, stackFrame.callFrame->callerFrame()->codeBlock(), codeBlock, jitCode, callLinkInfo, stackFrame.args[2].int32(), stackFrame.globalData); 1489 1490 if (!callLinkInfo->seenOnce()) 1491 callLinkInfo->setSeen(); 1492 else { 1493 1494 CodeBlock* codeBlock = 0; 1495 if (!callee->isHostFunction()) 1496 codeBlock = &callee->body()->bytecode(callee->scope().node()); 1497 else 1498 codeBlock = &callee->body()->generatedBytecode(); 1499 JIT::linkCall(callee, stackFrame.callFrame->callerFrame()->codeBlock(), codeBlock, jitCode, callLinkInfo, stackFrame.args[2].int32(), globalData); 1500 1501 } 1549 1502 1550 1503 return jitCode.addressForCall().executableAddress();
Note:
See TracChangeset
for help on using the changeset viewer.