OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
321 | 321 |
322 | 322 |
323 // Load a fast property out of a holder object (src). In-object properties | 323 // Load a fast property out of a holder object (src). In-object properties |
324 // are loaded directly otherwise the property is loaded from the properties | 324 // are loaded directly otherwise the property is loaded from the properties |
325 // fixed array. | 325 // fixed array. |
326 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, | 326 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, |
327 Register dst, | 327 Register dst, |
328 Register src, | 328 Register src, |
329 Handle<JSObject> holder, | 329 Handle<JSObject> holder, |
330 PropertyIndex index) { | 330 PropertyIndex index) { |
331 if (index.is_header_index()) { | 331 DoGenerateFastPropertyLoad( |
332 int offset = index.header_index() * kPointerSize; | 332 masm, dst, src, index.is_inobject(holder), index.translate(holder)); |
333 __ ldr(dst, FieldMemOperand(src, offset)); | |
334 } else { | |
335 // Adjust for the number of properties stored in the holder. | |
336 int slot = index.field_index() - holder->map()->inobject_properties(); | |
337 if (slot < 0) { | |
338 // Get the property straight out of the holder. | |
339 int offset = holder->map()->instance_size() + (slot * kPointerSize); | |
340 __ ldr(dst, FieldMemOperand(src, offset)); | |
341 } else { | |
342 // Calculate the offset into the properties array. | |
343 int offset = slot * kPointerSize + FixedArray::kHeaderSize; | |
344 __ ldr(dst, FieldMemOperand(src, JSObject::kPropertiesOffset)); | |
345 __ ldr(dst, FieldMemOperand(dst, offset)); | |
346 } | |
347 } | |
348 } | 333 } |
349 | 334 |
350 | 335 |
| 336 void StubCompiler::DoGenerateFastPropertyLoad(MacroAssembler* masm, |
| 337 Register dst, |
| 338 Register src, |
| 339 bool inobject, |
| 340 int index) { |
| 341 int offset = index * kPointerSize; |
| 342 if (!inobject) { |
| 343 // Calculate the offset into the properties array. |
| 344 offset = offset + FixedArray::kHeaderSize; |
| 345 __ ldr(dst, FieldMemOperand(src, JSObject::kPropertiesOffset)); |
| 346 src = dst; |
| 347 } |
| 348 __ ldr(dst, FieldMemOperand(src, offset)); |
| 349 } |
| 350 |
| 351 |
351 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, | 352 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, |
352 Register receiver, | 353 Register receiver, |
353 Register scratch, | 354 Register scratch, |
354 Label* miss_label) { | 355 Label* miss_label) { |
355 // Check that the receiver isn't a smi. | 356 // Check that the receiver isn't a smi. |
356 __ JumpIfSmi(receiver, miss_label); | 357 __ JumpIfSmi(receiver, miss_label); |
357 | 358 |
358 // Check that the object is a JS array. | 359 // Check that the object is a JS array. |
359 __ CompareObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE); | 360 __ CompareObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE); |
360 __ b(ne, miss_label); | 361 __ b(ne, miss_label); |
(...skipping 698 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1059 __ bind(&done); | 1060 __ bind(&done); |
1060 __ str(fval, MemOperand(dst, wordoffset, LSL, 2)); | 1061 __ str(fval, MemOperand(dst, wordoffset, LSL, 2)); |
1061 } | 1062 } |
1062 } | 1063 } |
1063 | 1064 |
1064 | 1065 |
1065 #undef __ | 1066 #undef __ |
1066 #define __ ACCESS_MASM(masm()) | 1067 #define __ ACCESS_MASM(masm()) |
1067 | 1068 |
1068 | 1069 |
| 1070 void StubCompiler::GenerateTailCall(Handle<Code> code) { |
| 1071 __ Jump(code, RelocInfo::CODE_TARGET); |
| 1072 } |
| 1073 |
| 1074 |
1069 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, | 1075 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, |
1070 Register object_reg, | 1076 Register object_reg, |
1071 Handle<JSObject> holder, | 1077 Handle<JSObject> holder, |
1072 Register holder_reg, | 1078 Register holder_reg, |
1073 Register scratch1, | 1079 Register scratch1, |
1074 Register scratch2, | 1080 Register scratch2, |
1075 Handle<String> name, | 1081 Handle<String> name, |
1076 int save_at_depth, | 1082 int save_at_depth, |
1077 Label* miss) { | 1083 Label* miss, |
| 1084 PrototypeCheckType check) { |
| 1085 Handle<JSObject> first = object; |
1078 // Make sure there's no overlap between holder and object registers. | 1086 // Make sure there's no overlap between holder and object registers. |
1079 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 1087 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
1080 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 1088 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
1081 && !scratch2.is(scratch1)); | 1089 && !scratch2.is(scratch1)); |
1082 | 1090 |
1083 // Keep track of the current object in register reg. | 1091 // Keep track of the current object in register reg. |
1084 Register reg = object_reg; | 1092 Register reg = object_reg; |
1085 int depth = 0; | 1093 int depth = 0; |
1086 | 1094 |
1087 if (save_at_depth == depth) { | 1095 if (save_at_depth == depth) { |
(...skipping 20 matching lines...) Expand all Loading... |
1108 ASSERT(current->property_dictionary()->FindEntry(*name) == | 1116 ASSERT(current->property_dictionary()->FindEntry(*name) == |
1109 StringDictionary::kNotFound); | 1117 StringDictionary::kNotFound); |
1110 | 1118 |
1111 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, | 1119 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, |
1112 scratch1, scratch2); | 1120 scratch1, scratch2); |
1113 | 1121 |
1114 __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | 1122 __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
1115 reg = holder_reg; // From now on the object will be in holder_reg. | 1123 reg = holder_reg; // From now on the object will be in holder_reg. |
1116 __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); | 1124 __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); |
1117 } else { | 1125 } else { |
1118 Handle<Map> current_map(current->map()); | 1126 Register map_reg = scratch1; |
1119 __ CheckMap(reg, scratch1, current_map, miss, DONT_DO_SMI_CHECK, | 1127 if (!current.is_identical_to(first) || check == CHECK_ALL_MAPS) { |
1120 ALLOW_ELEMENT_TRANSITION_MAPS); | 1128 Handle<Map> current_map(current->map()); |
| 1129 // CheckMap implicitly loads the map of |reg| into |map_reg|. |
| 1130 __ CheckMap(reg, map_reg, current_map, miss, DONT_DO_SMI_CHECK, |
| 1131 ALLOW_ELEMENT_TRANSITION_MAPS); |
| 1132 } else { |
| 1133 __ ldr(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 1134 } |
1121 | 1135 |
1122 // Check access rights to the global object. This has to happen after | 1136 // Check access rights to the global object. This has to happen after |
1123 // the map check so that we know that the object is actually a global | 1137 // the map check so that we know that the object is actually a global |
1124 // object. | 1138 // object. |
1125 if (current->IsJSGlobalProxy()) { | 1139 if (current->IsJSGlobalProxy()) { |
1126 __ CheckAccessGlobalProxy(reg, scratch2, miss); | 1140 __ CheckAccessGlobalProxy(reg, scratch2, miss); |
1127 } | 1141 } |
1128 reg = holder_reg; // From now on the object will be in holder_reg. | 1142 reg = holder_reg; // From now on the object will be in holder_reg. |
1129 | 1143 |
1130 if (heap()->InNewSpace(*prototype)) { | 1144 if (heap()->InNewSpace(*prototype)) { |
1131 // The prototype is in new space; we cannot store a reference to it | 1145 // The prototype is in new space; we cannot store a reference to it |
1132 // in the code. Load it from the map. | 1146 // in the code. Load it from the map. |
1133 __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); | 1147 __ ldr(reg, FieldMemOperand(map_reg, Map::kPrototypeOffset)); |
1134 } else { | 1148 } else { |
1135 // The prototype is in old space; load it directly. | 1149 // The prototype is in old space; load it directly. |
1136 __ mov(reg, Operand(prototype)); | 1150 __ mov(reg, Operand(prototype)); |
1137 } | 1151 } |
1138 } | 1152 } |
1139 | 1153 |
1140 if (save_at_depth == depth) { | 1154 if (save_at_depth == depth) { |
1141 __ str(reg, MemOperand(sp)); | 1155 __ str(reg, MemOperand(sp)); |
1142 } | 1156 } |
1143 | 1157 |
1144 // Go to the next object in the prototype chain. | 1158 // Go to the next object in the prototype chain. |
1145 current = prototype; | 1159 current = prototype; |
1146 } | 1160 } |
1147 | 1161 |
1148 // Log the check depth. | 1162 // Log the check depth. |
1149 LOG(masm()->isolate(), IntEvent("check-maps-depth", depth + 1)); | 1163 LOG(masm()->isolate(), IntEvent("check-maps-depth", depth + 1)); |
1150 | 1164 |
1151 // Check the holder map. | 1165 if (!holder.is_identical_to(first) || check == CHECK_ALL_MAPS) { |
1152 __ CheckMap(reg, scratch1, Handle<Map>(current->map()), miss, | 1166 // Check the holder map. |
1153 DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); | 1167 __ CheckMap(reg, scratch1, Handle<Map>(holder->map()), miss, |
| 1168 DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); |
| 1169 } |
1154 | 1170 |
1155 // Perform security check for access to the global object. | 1171 // Perform security check for access to the global object. |
1156 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | 1172 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
1157 if (holder->IsJSGlobalProxy()) { | 1173 if (holder->IsJSGlobalProxy()) { |
1158 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 1174 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
1159 } | 1175 } |
1160 | 1176 |
1161 // If we've skipped any global objects, it's not enough to verify that | 1177 // If we've skipped any global objects, it's not enough to verify that |
1162 // their maps haven't changed. We also need to check that the property | 1178 // their maps haven't changed. We also need to check that the property |
1163 // cell for the property is still empty. | 1179 // cell for the property is still empty. |
1164 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); | 1180 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); |
1165 | 1181 |
1166 // Return the register containing the holder. | 1182 // Return the register containing the holder. |
1167 return reg; | 1183 return reg; |
1168 } | 1184 } |
1169 | 1185 |
1170 | 1186 |
1171 void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success, | 1187 void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success, |
1172 Label* miss) { | 1188 Label* miss) { |
1173 __ b(success); | 1189 if (!miss->is_unused()) { |
1174 __ bind(miss); | 1190 __ b(success); |
1175 GenerateLoadMiss(masm(), kind()); | 1191 __ bind(miss); |
| 1192 GenerateLoadMiss(masm(), kind()); |
| 1193 } |
1176 } | 1194 } |
1177 | 1195 |
1178 | 1196 |
1179 Register BaseLoadStubCompiler::CallbackHandlerFrontend( | 1197 Register BaseLoadStubCompiler::CallbackHandlerFrontend( |
1180 Handle<JSObject> object, | 1198 Handle<JSObject> object, |
1181 Register object_reg, | 1199 Register object_reg, |
1182 Handle<JSObject> holder, | 1200 Handle<JSObject> holder, |
1183 Handle<String> name, | 1201 Handle<String> name, |
1184 Label* success, | 1202 Label* success, |
1185 FrontendCheckType check, | |
1186 Handle<ExecutableAccessorInfo> callback) { | 1203 Handle<ExecutableAccessorInfo> callback) { |
1187 Label miss; | 1204 Label miss; |
1188 | 1205 |
1189 Register reg = HandlerFrontendHeader( | 1206 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); |
1190 object, object_reg, holder, name, &miss, check); | |
1191 | 1207 |
1192 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 1208 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { |
1193 ASSERT(!reg.is(scratch2())); | 1209 ASSERT(!reg.is(scratch2())); |
1194 ASSERT(!reg.is(scratch3())); | 1210 ASSERT(!reg.is(scratch3())); |
1195 ASSERT(!reg.is(scratch4())); | 1211 ASSERT(!reg.is(scratch4())); |
1196 | 1212 |
1197 // Load the properties dictionary. | 1213 // Load the properties dictionary. |
1198 Register dictionary = scratch4(); | 1214 Register dictionary = scratch4(); |
1199 __ ldr(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); | 1215 __ ldr(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); |
1200 | 1216 |
(...skipping 25 matching lines...) Expand all Loading... |
1226 | 1242 |
1227 | 1243 |
1228 void BaseLoadStubCompiler::NonexistentHandlerFrontend( | 1244 void BaseLoadStubCompiler::NonexistentHandlerFrontend( |
1229 Handle<JSObject> object, | 1245 Handle<JSObject> object, |
1230 Handle<JSObject> last, | 1246 Handle<JSObject> last, |
1231 Handle<String> name, | 1247 Handle<String> name, |
1232 Label* success, | 1248 Label* success, |
1233 Handle<GlobalObject> global) { | 1249 Handle<GlobalObject> global) { |
1234 Label miss; | 1250 Label miss; |
1235 | 1251 |
1236 Register reg = HandlerFrontendHeader( | 1252 Register reg = HandlerFrontendHeader(object, receiver(), last, name, &miss); |
1237 object, receiver(), last, name, &miss, PERFORM_INITIAL_CHECKS); | |
1238 | 1253 |
1239 // If the last object in the prototype chain is a global object, | 1254 // If the last object in the prototype chain is a global object, |
1240 // check that the global property cell is empty. | 1255 // check that the global property cell is empty. |
1241 if (!global.is_null()) { | 1256 if (!global.is_null()) { |
1242 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); | 1257 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); |
1243 } | 1258 } |
1244 | 1259 |
1245 if (!last->HasFastProperties()) { | 1260 if (!last->HasFastProperties()) { |
1246 __ ldr(scratch2(), FieldMemOperand(reg, HeapObject::kMapOffset)); | 1261 __ ldr(scratch2(), FieldMemOperand(reg, HeapObject::kMapOffset)); |
1247 __ ldr(scratch2(), FieldMemOperand(scratch2(), Map::kPrototypeOffset)); | 1262 __ ldr(scratch2(), FieldMemOperand(scratch2(), Map::kPrototypeOffset)); |
(...skipping 1607 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2855 | 2870 |
2856 NonexistentHandlerFrontend(object, last, name, &success, global); | 2871 NonexistentHandlerFrontend(object, last, name, &success, global); |
2857 | 2872 |
2858 __ bind(&success); | 2873 __ bind(&success); |
2859 // Return undefined if maps of the full prototype chain are still the | 2874 // Return undefined if maps of the full prototype chain are still the |
2860 // same and no global property with this name contains a value. | 2875 // same and no global property with this name contains a value. |
2861 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); | 2876 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); |
2862 __ Ret(); | 2877 __ Ret(); |
2863 | 2878 |
2864 // Return the generated code. | 2879 // Return the generated code. |
2865 return GetCode(Code::NONEXISTENT, factory()->empty_string()); | 2880 return GetCode(Code::HANDLER_FRAGMENT, Code::NONEXISTENT, name); |
2866 } | 2881 } |
2867 | 2882 |
2868 | 2883 |
2869 Register* LoadStubCompiler::registers() { | 2884 Register* LoadStubCompiler::registers() { |
2870 // receiver, name, scratch1, scratch2, scratch3, scratch4. | 2885 // receiver, name, scratch1, scratch2, scratch3, scratch4. |
2871 static Register registers[] = { r0, r2, r3, r1, r4, r5 }; | 2886 static Register registers[] = { r0, r2, r3, r1, r4, r5 }; |
2872 return registers; | 2887 return registers; |
2873 } | 2888 } |
2874 | 2889 |
2875 | 2890 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2926 | 2941 |
2927 | 2942 |
2928 Handle<Code> LoadStubCompiler::CompileLoadGlobal( | 2943 Handle<Code> LoadStubCompiler::CompileLoadGlobal( |
2929 Handle<JSObject> object, | 2944 Handle<JSObject> object, |
2930 Handle<GlobalObject> global, | 2945 Handle<GlobalObject> global, |
2931 Handle<JSGlobalPropertyCell> cell, | 2946 Handle<JSGlobalPropertyCell> cell, |
2932 Handle<String> name, | 2947 Handle<String> name, |
2933 bool is_dont_delete) { | 2948 bool is_dont_delete) { |
2934 Label success, miss; | 2949 Label success, miss; |
2935 | 2950 |
2936 HandlerFrontendHeader(object, receiver(), Handle<JSObject>::cast(global), | 2951 __ CheckMap( |
2937 name, &miss, PERFORM_INITIAL_CHECKS); | 2952 receiver(), scratch1(), Handle<Map>(object->map()), &miss, DO_SMI_CHECK); |
| 2953 HandlerFrontendHeader( |
| 2954 object, receiver(), Handle<JSObject>::cast(global), name, &miss); |
2938 | 2955 |
2939 // Get the value from the cell. | 2956 // Get the value from the cell. |
2940 __ mov(r3, Operand(cell)); | 2957 __ mov(r3, Operand(cell)); |
2941 __ ldr(r4, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); | 2958 __ ldr(r4, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); |
2942 | 2959 |
2943 // Check for deleted property if property can actually be deleted. | 2960 // Check for deleted property if property can actually be deleted. |
2944 if (!is_dont_delete) { | 2961 if (!is_dont_delete) { |
2945 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 2962 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
2946 __ cmp(r4, ip); | 2963 __ cmp(r4, ip); |
2947 __ b(eq, &miss); | 2964 __ b(eq, &miss); |
2948 } | 2965 } |
2949 | 2966 |
2950 HandlerFrontendFooter(&success, &miss); | 2967 HandlerFrontendFooter(&success, &miss); |
2951 __ bind(&success); | 2968 __ bind(&success); |
2952 | 2969 |
2953 Counters* counters = masm()->isolate()->counters(); | 2970 Counters* counters = masm()->isolate()->counters(); |
2954 __ IncrementCounter(counters->named_load_global_stub(), 1, r1, r3); | 2971 __ IncrementCounter(counters->named_load_global_stub(), 1, r1, r3); |
2955 __ mov(r0, r4); | 2972 __ mov(r0, r4); |
2956 __ Ret(); | 2973 __ Ret(); |
2957 | 2974 |
2958 // Return the generated code. | 2975 // Return the generated code. |
2959 return GetCode(Code::NORMAL, name); | 2976 return GetCode(Code::IC_FRAGMENT, Code::NORMAL, name); |
2960 } | 2977 } |
2961 | 2978 |
2962 | 2979 |
2963 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( | 2980 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( |
2964 Handle<Map> receiver_map) { | 2981 Handle<Map> receiver_map) { |
2965 // ----------- S t a t e ------------- | 2982 // ----------- S t a t e ------------- |
2966 // -- lr : return address | 2983 // -- lr : return address |
2967 // -- r0 : key | 2984 // -- r0 : key |
2968 // -- r1 : receiver | 2985 // -- r1 : receiver |
2969 // ----------------------------------- | 2986 // ----------------------------------- |
2970 ElementsKind elements_kind = receiver_map->elements_kind(); | 2987 ElementsKind elements_kind = receiver_map->elements_kind(); |
2971 if (receiver_map->has_fast_elements() || | 2988 if (receiver_map->has_fast_elements() || |
2972 receiver_map->has_external_array_elements()) { | 2989 receiver_map->has_external_array_elements()) { |
2973 Handle<Code> stub = KeyedLoadFastElementStub( | 2990 Handle<Code> stub = KeyedLoadFastElementStub( |
2974 receiver_map->instance_type() == JS_ARRAY_TYPE, | 2991 receiver_map->instance_type() == JS_ARRAY_TYPE, |
2975 elements_kind).GetCode(isolate()); | 2992 elements_kind).GetCode(isolate()); |
2976 __ DispatchMap(r1, r2, receiver_map, stub, DO_SMI_CHECK); | 2993 __ DispatchMap(r1, r2, receiver_map, stub, DO_SMI_CHECK); |
2977 } else { | 2994 } else { |
2978 Handle<Code> stub = | 2995 Handle<Code> stub = |
2979 KeyedLoadDictionaryElementStub().GetCode(isolate()); | 2996 KeyedLoadDictionaryElementStub().GetCode(isolate()); |
2980 __ DispatchMap(r1, r2, receiver_map, stub, DO_SMI_CHECK); | 2997 __ DispatchMap(r1, r2, receiver_map, stub, DO_SMI_CHECK); |
2981 } | 2998 } |
2982 | 2999 |
2983 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss(); | 3000 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss(); |
2984 __ Jump(ic, RelocInfo::CODE_TARGET); | 3001 __ Jump(ic, RelocInfo::CODE_TARGET); |
2985 | 3002 |
2986 // Return the generated code. | 3003 // Return the generated code. |
2987 return GetCode(Code::NORMAL, factory()->empty_string()); | 3004 return GetCode(Code::IC_FRAGMENT, Code::NORMAL, factory()->empty_string()); |
2988 } | 3005 } |
2989 | 3006 |
2990 | 3007 |
2991 Handle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic( | 3008 Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC( |
2992 MapHandleList* receiver_maps, | 3009 MapHandleList* receiver_maps, |
2993 CodeHandleList* handler_ics) { | 3010 CodeHandleList* handlers, |
2994 // ----------- S t a t e ------------- | 3011 Handle<String> name, |
2995 // -- lr : return address | 3012 Code::StubType type, |
2996 // -- r0 : key | 3013 IcCheckType check) { |
2997 // -- r1 : receiver | |
2998 // ----------------------------------- | |
2999 Label miss; | 3014 Label miss; |
3000 __ JumpIfSmi(r1, &miss); | 3015 |
| 3016 if (check == PROPERTY) { |
| 3017 GenerateNameCheck(name, this->name(), &miss); |
| 3018 } |
| 3019 |
| 3020 __ JumpIfSmi(receiver(), &miss); |
| 3021 Register map_reg = scratch1(); |
3001 | 3022 |
3002 int receiver_count = receiver_maps->length(); | 3023 int receiver_count = receiver_maps->length(); |
3003 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); | 3024 __ ldr(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset)); |
3004 for (int current = 0; current < receiver_count; ++current) { | 3025 for (int current = 0; current < receiver_count; ++current) { |
3005 __ mov(ip, Operand(receiver_maps->at(current))); | 3026 __ mov(ip, Operand(receiver_maps->at(current))); |
3006 __ cmp(r2, ip); | 3027 __ cmp(map_reg, ip); |
3007 __ Jump(handler_ics->at(current), RelocInfo::CODE_TARGET, eq); | 3028 __ Jump(handlers->at(current), RelocInfo::CODE_TARGET, eq); |
3008 } | 3029 } |
3009 | 3030 |
3010 __ bind(&miss); | 3031 __ bind(&miss); |
3011 Handle<Code> miss_ic = isolate()->builtins()->KeyedLoadIC_Miss(); | 3032 GenerateLoadMiss(masm(), kind()); |
3012 __ Jump(miss_ic, RelocInfo::CODE_TARGET, al); | |
3013 | 3033 |
3014 // Return the generated code. | 3034 // Return the generated code. |
3015 return GetCode(Code::NORMAL, factory()->empty_string(), POLYMORPHIC); | 3035 InlineCacheState state = |
| 3036 receiver_maps->length() > 1 ? POLYMORPHIC : MONOMORPHIC; |
| 3037 return GetCode(Code::IC_FRAGMENT, type, name, state); |
3016 } | 3038 } |
3017 | 3039 |
3018 | 3040 |
3019 Handle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object, | 3041 Handle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object, |
3020 int index, | 3042 int index, |
3021 Handle<Map> transition, | 3043 Handle<Map> transition, |
3022 Handle<String> name) { | 3044 Handle<String> name) { |
3023 // ----------- S t a t e ------------- | 3045 // ----------- S t a t e ------------- |
3024 // -- r0 : value | 3046 // -- r0 : value |
3025 // -- r1 : name | 3047 // -- r1 : name |
(...skipping 1034 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4060 __ Jump(ic_slow, RelocInfo::CODE_TARGET); | 4082 __ Jump(ic_slow, RelocInfo::CODE_TARGET); |
4061 } | 4083 } |
4062 } | 4084 } |
4063 | 4085 |
4064 | 4086 |
4065 #undef __ | 4087 #undef __ |
4066 | 4088 |
4067 } } // namespace v8::internal | 4089 } } // namespace v8::internal |
4068 | 4090 |
4069 #endif // V8_TARGET_ARCH_ARM | 4091 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |