Changeset 46620 in webkit for trunk/JavaScriptCore/jit/JITStubs.cpp
- Timestamp:
- Jul 30, 2009, 7:57:31 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/jit/JITStubs.cpp
r46618 r46620 584 584 JITThunks::JITThunks(JSGlobalData* globalData) 585 585 { 586 JIT::compileCTIMachineTrampolines(globalData, &m_executablePool, &m_ctiStringLengthTrampoline, &m_ctiVirtualCall Link, &m_ctiVirtualCall, &m_ctiNativeCallThunk);586 JIT::compileCTIMachineTrampolines(globalData, &m_executablePool, &m_ctiStringLengthTrampoline, &m_ctiVirtualCallPreLink, &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 , StructureStubInfo* stubInfo)609 NEVER_INLINE void JITThunks::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const PutPropertySlot& slot) 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); 635 637 636 638 // Cache hit: Specialize instruction and ref Structures. … … 653 655 } 654 656 655 NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot , StructureStubInfo* stubInfo)657 NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot) 656 658 { 657 659 // FIXME: Write a test that proves we need to check for recursion here just … … 691 693 return; 692 694 } 695 696 // In the interpreter the last structure is trapped here; in CTI we use the 697 // *_second method to achieve a similar (but not quite the same) effect. 698 699 StructureStubInfo* stubInfo = &codeBlock->getStubInfo(returnAddress); 693 700 694 701 // Cache hit: Specialize instruction and ref Structures. … … 720 727 size_t count = countPrototypeChainEntriesAndCheckForProxies(callFrame, baseValue, slot); 721 728 if (!count) { 722 stubInfo-> accessType = access_get_by_id_generic;729 stubInfo->opcodeID = op_get_by_id_generic; 723 730 return; 724 731 } … … 1022 1029 CallFrame* callFrame = stackFrame.callFrame; 1023 1030 Identifier& ident = stackFrame.args[1].identifier(); 1031 1024 1032 PutPropertySlot slot; 1025 1033 stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].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 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); 1034 1047 CHECK_FOR_EXCEPTION_AT_END(); 1035 1048 } … … 1063 1076 } 1064 1077 1065 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id _method_check)1078 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id) 1066 1079 { 1067 1080 STUB_INIT_STACK_FRAME(stackFrame); … … 1069 1082 CallFrame* callFrame = stackFrame.callFrame; 1070 1083 Identifier& ident = stackFrame.args[1].identifier(); 1084 1071 1085 JSValue baseValue = stackFrame.args[0].jsValue(); 1072 1086 PropertySlot slot(baseValue); 1073 1087 JSValue result = baseValue.get(callFrame, ident, slot); 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) 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) 1133 1096 { 1134 1097 STUB_INIT_STACK_FRAME(stackFrame); … … 1136 1099 CallFrame* callFrame = stackFrame.callFrame; 1137 1100 Identifier& ident = stackFrame.args[1].identifier(); 1101 1138 1102 JSValue baseValue = stackFrame.args[0].jsValue(); 1139 1103 PropertySlot slot(baseValue); 1140 1104 JSValue result = baseValue.get(callFrame, 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); 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); 1148 1189 1149 1190 CHECK_FOR_EXCEPTION_AT_END(); … … 1177 1218 int listIndex = 1; 1178 1219 1179 if (stubInfo-> accessType == access_get_by_id_self) {1220 if (stubInfo->opcodeID == op_get_by_id_self) { 1180 1221 ASSERT(!stubInfo->stubRoutine); 1181 1222 polymorphicStructureList = new PolymorphicAccessStructureList(CodeLocationLabel(), stubInfo->u.getByIdSelf.baseObjectStructure); … … 1201 1242 listIndex = 1; 1202 1243 1203 switch (stubInfo-> accessType) {1204 case access_get_by_id_proto:1244 switch (stubInfo->opcodeID) { 1245 case op_get_by_id_proto: 1205 1246 prototypeStructureList = new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdProto.baseObjectStructure, stubInfo->u.getByIdProto.prototypeStructure); 1206 1247 stubInfo->stubRoutine = CodeLocationLabel(); 1207 1248 stubInfo->initGetByIdProtoList(prototypeStructureList, 2); 1208 1249 break; 1209 case access_get_by_id_chain:1250 case op_get_by_id_chain: 1210 1251 prototypeStructureList = new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure, stubInfo->u.getByIdChain.chain); 1211 1252 stubInfo->stubRoutine = CodeLocationLabel(); 1212 1253 stubInfo->initGetByIdProtoList(prototypeStructureList, 2); 1213 1254 break; 1214 case access_get_by_id_proto_list:1255 case op_get_by_id_proto_list: 1215 1256 prototypeStructureList = stubInfo->u.getByIdProtoList.structureList; 1216 1257 listIndex = stubInfo->u.getByIdProtoList.listSize; … … 1479 1520 1480 1521 #if ENABLE(JIT_OPTIMIZE_CALL) 1481 DEFINE_STUB_FUNCTION(void*, vm_ lazyLinkCall)1522 DEFINE_STUB_FUNCTION(void*, vm_dontLazyLinkCall) 1482 1523 { 1483 1524 STUB_INIT_STACK_FRAME(stackFrame); … … 1485 1526 JSGlobalData* globalData = stackFrame.globalData; 1486 1527 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()); 1487 1539 JITCode& jitCode = callee->body()->generatedJITCode(); 1540 1541 CodeBlock* codeBlock = 0; 1542 if (!callee->isHostFunction()) 1543 codeBlock = &callee->body()->bytecode(callee->scope().node()); 1544 else 1545 codeBlock = &callee->body()->generatedBytecode(); 1546 1488 1547 CallLinkInfo* callLinkInfo = &stackFrame.callFrame->callerFrame()->codeBlock()->getCallLinkInfo(stackFrame.args[1].returnAddress()); 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 } 1548 JIT::linkCall(callee, stackFrame.callFrame->callerFrame()->codeBlock(), codeBlock, jitCode, callLinkInfo, stackFrame.args[2].int32(), stackFrame.globalData); 1502 1549 1503 1550 return jitCode.addressForCall().executableAddress();
Note:
See TracChangeset
for help on using the changeset viewer.