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 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
308 | 308 |
309 | 309 |
310 // Load a fast property out of a holder object (src). In-object properties | 310 // Load a fast property out of a holder object (src). In-object properties |
311 // are loaded directly otherwise the property is loaded from the properties | 311 // are loaded directly otherwise the property is loaded from the properties |
312 // fixed array. | 312 // fixed array. |
313 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, | 313 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, |
314 Register dst, | 314 Register dst, |
315 Register src, | 315 Register src, |
316 Handle<JSObject> holder, | 316 Handle<JSObject> holder, |
317 PropertyIndex index) { | 317 PropertyIndex index) { |
318 if (index.is_header_index()) { | 318 DoGenerateFastPropertyLoad( |
319 int offset = index.header_index() * kPointerSize; | 319 masm, dst, src, index.is_inobject(holder), index.translate(holder)); |
320 __ lw(dst, FieldMemOperand(src, offset)); | |
321 } else { | |
322 // Adjust for the number of properties stored in the holder. | |
323 int slot = index.field_index() - holder->map()->inobject_properties(); | |
324 if (slot < 0) { | |
325 // Get the property straight out of the holder. | |
326 int offset = holder->map()->instance_size() + (slot * kPointerSize); | |
327 __ lw(dst, FieldMemOperand(src, offset)); | |
328 } else { | |
329 // Calculate the offset into the properties array. | |
330 int offset = slot * kPointerSize + FixedArray::kHeaderSize; | |
331 __ lw(dst, FieldMemOperand(src, JSObject::kPropertiesOffset)); | |
332 __ lw(dst, FieldMemOperand(dst, offset)); | |
333 } | |
334 } | |
335 } | 320 } |
336 | 321 |
337 | 322 |
| 323 void StubCompiler::DoGenerateFastPropertyLoad(MacroAssembler* masm, |
| 324 Register dst, |
| 325 Register src, |
| 326 bool inobject, |
| 327 int index) { |
| 328 int offset = index * kPointerSize; |
| 329 if (!inobject) { |
| 330 // Calculate the offset into the properties array. |
| 331 offset = offset + FixedArray::kHeaderSize; |
| 332 __ lw(dst, FieldMemOperand(src, JSObject::kPropertiesOffset)); |
| 333 src = dst; |
| 334 } |
| 335 __ lw(dst, FieldMemOperand(src, offset)); |
| 336 } |
| 337 |
| 338 |
338 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, | 339 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, |
339 Register receiver, | 340 Register receiver, |
340 Register scratch, | 341 Register scratch, |
341 Label* miss_label) { | 342 Label* miss_label) { |
342 // Check that the receiver isn't a smi. | 343 // Check that the receiver isn't a smi. |
343 __ JumpIfSmi(receiver, miss_label); | 344 __ JumpIfSmi(receiver, miss_label); |
344 | 345 |
345 // Check that the object is a JS array. | 346 // Check that the object is a JS array. |
346 __ GetObjectType(receiver, scratch, scratch); | 347 __ GetObjectType(receiver, scratch, scratch); |
347 __ Branch(miss_label, ne, scratch, Operand(JS_ARRAY_TYPE)); | 348 __ Branch(miss_label, ne, scratch, Operand(JS_ARRAY_TYPE)); |
(...skipping 712 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1060 __ addu(scratch1, dst, scratch1); | 1061 __ addu(scratch1, dst, scratch1); |
1061 __ sw(fval, MemOperand(scratch1, 0)); | 1062 __ sw(fval, MemOperand(scratch1, 0)); |
1062 } | 1063 } |
1063 } | 1064 } |
1064 | 1065 |
1065 | 1066 |
1066 #undef __ | 1067 #undef __ |
1067 #define __ ACCESS_MASM(masm()) | 1068 #define __ ACCESS_MASM(masm()) |
1068 | 1069 |
1069 | 1070 |
| 1071 void StubCompiler::GenerateTailCall(Handle<Code> code) { |
| 1072 __ Jump(code, RelocInfo::CODE_TARGET); |
| 1073 } |
| 1074 |
| 1075 |
1070 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, | 1076 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, |
1071 Register object_reg, | 1077 Register object_reg, |
1072 Handle<JSObject> holder, | 1078 Handle<JSObject> holder, |
1073 Register holder_reg, | 1079 Register holder_reg, |
1074 Register scratch1, | 1080 Register scratch1, |
1075 Register scratch2, | 1081 Register scratch2, |
1076 Handle<String> name, | 1082 Handle<String> name, |
1077 int save_at_depth, | 1083 int save_at_depth, |
1078 Label* miss) { | 1084 Label* miss, |
| 1085 PrototypeCheckType check) { |
| 1086 Handle<JSObject> first = object; |
1079 // Make sure there's no overlap between holder and object registers. | 1087 // Make sure there's no overlap between holder and object registers. |
1080 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 1088 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
1081 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 1089 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
1082 && !scratch2.is(scratch1)); | 1090 && !scratch2.is(scratch1)); |
1083 | 1091 |
1084 // Keep track of the current object in register reg. | 1092 // Keep track of the current object in register reg. |
1085 Register reg = object_reg; | 1093 Register reg = object_reg; |
1086 int depth = 0; | 1094 int depth = 0; |
1087 | 1095 |
1088 if (save_at_depth == depth) { | 1096 if (save_at_depth == depth) { |
(...skipping 20 matching lines...) Expand all Loading... |
1109 ASSERT(current->property_dictionary()->FindEntry(*name) == | 1117 ASSERT(current->property_dictionary()->FindEntry(*name) == |
1110 StringDictionary::kNotFound); | 1118 StringDictionary::kNotFound); |
1111 | 1119 |
1112 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, | 1120 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, |
1113 scratch1, scratch2); | 1121 scratch1, scratch2); |
1114 | 1122 |
1115 __ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | 1123 __ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
1116 reg = holder_reg; // From now on the object will be in holder_reg. | 1124 reg = holder_reg; // From now on the object will be in holder_reg. |
1117 __ lw(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); | 1125 __ lw(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); |
1118 } else { | 1126 } else { |
1119 Handle<Map> current_map(current->map()); | 1127 Register map_reg = scratch1; |
1120 __ CheckMap(reg, scratch1, current_map, miss, DONT_DO_SMI_CHECK, | 1128 if (!current.is_identical_to(first) || check == CHECK_ALL_MAPS) { |
1121 ALLOW_ELEMENT_TRANSITION_MAPS); | 1129 Handle<Map> current_map(current->map()); |
| 1130 // CheckMap implicitly loads the map of |reg| into |map_reg|. |
| 1131 __ CheckMap(reg, map_reg, current_map, miss, DONT_DO_SMI_CHECK, |
| 1132 ALLOW_ELEMENT_TRANSITION_MAPS); |
| 1133 } else { |
| 1134 __ lw(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 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 __ lw(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); | 1147 __ lw(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 __ li(reg, Operand(prototype)); | 1150 __ li(reg, Operand(prototype)); |
1137 } | 1151 } |
1138 } | 1152 } |
1139 | 1153 |
1140 if (save_at_depth == depth) { | 1154 if (save_at_depth == depth) { |
1141 __ sw(reg, MemOperand(sp)); | 1155 __ sw(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 __ Branch(success); | 1189 if (!miss->is_unused()) { |
1174 __ bind(miss); | 1190 __ Branch(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 __ lw(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); | 1215 __ lw(dictionary, FieldMemOperand(reg, JSObject::kPropertiesOffset)); |
1200 | 1216 |
(...skipping 24 matching lines...) Expand all Loading... |
1225 | 1241 |
1226 | 1242 |
1227 void BaseLoadStubCompiler::NonexistentHandlerFrontend( | 1243 void BaseLoadStubCompiler::NonexistentHandlerFrontend( |
1228 Handle<JSObject> object, | 1244 Handle<JSObject> object, |
1229 Handle<JSObject> last, | 1245 Handle<JSObject> last, |
1230 Handle<String> name, | 1246 Handle<String> name, |
1231 Label* success, | 1247 Label* success, |
1232 Handle<GlobalObject> global) { | 1248 Handle<GlobalObject> global) { |
1233 Label miss; | 1249 Label miss; |
1234 | 1250 |
1235 Register reg = HandlerFrontendHeader( | 1251 Register reg = HandlerFrontendHeader(object, receiver(), last, name, &miss); |
1236 object, receiver(), last, name, &miss, PERFORM_INITIAL_CHECKS); | |
1237 | 1252 |
1238 // If the last object in the prototype chain is a global object, | 1253 // If the last object in the prototype chain is a global object, |
1239 // check that the global property cell is empty. | 1254 // check that the global property cell is empty. |
1240 if (!global.is_null()) { | 1255 if (!global.is_null()) { |
1241 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); | 1256 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); |
1242 } | 1257 } |
1243 | 1258 |
1244 if (!last->HasFastProperties()) { | 1259 if (!last->HasFastProperties()) { |
1245 __ lw(scratch2(), FieldMemOperand(reg, HeapObject::kMapOffset)); | 1260 __ lw(scratch2(), FieldMemOperand(reg, HeapObject::kMapOffset)); |
1246 __ lw(scratch2(), FieldMemOperand(scratch2(), Map::kPrototypeOffset)); | 1261 __ lw(scratch2(), FieldMemOperand(scratch2(), Map::kPrototypeOffset)); |
(...skipping 1603 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2850 Label success; | 2865 Label success; |
2851 | 2866 |
2852 NonexistentHandlerFrontend(object, last, name, &success, global); | 2867 NonexistentHandlerFrontend(object, last, name, &success, global); |
2853 | 2868 |
2854 __ bind(&success); | 2869 __ bind(&success); |
2855 // Return undefined if maps of the full prototype chain is still the same. | 2870 // Return undefined if maps of the full prototype chain is still the same. |
2856 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); | 2871 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); |
2857 __ Ret(); | 2872 __ Ret(); |
2858 | 2873 |
2859 // Return the generated code. | 2874 // Return the generated code. |
2860 return GetCode(Code::NONEXISTENT, factory()->empty_string()); | 2875 return GetCode(Code::HANDLER_FRAGMENT, Code::NONEXISTENT, name); |
2861 } | 2876 } |
2862 | 2877 |
2863 | 2878 |
2864 Register* LoadStubCompiler::registers() { | 2879 Register* LoadStubCompiler::registers() { |
2865 // receiver, name, scratch1, scratch2, scratch3, scratch4. | 2880 // receiver, name, scratch1, scratch2, scratch3, scratch4. |
2866 static Register registers[] = { a0, a2, a3, a1, t0, t1 }; | 2881 static Register registers[] = { a0, a2, a3, a1, t0, t1 }; |
2867 return registers; | 2882 return registers; |
2868 } | 2883 } |
2869 | 2884 |
2870 | 2885 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2920 | 2935 |
2921 | 2936 |
2922 Handle<Code> LoadStubCompiler::CompileLoadGlobal( | 2937 Handle<Code> LoadStubCompiler::CompileLoadGlobal( |
2923 Handle<JSObject> object, | 2938 Handle<JSObject> object, |
2924 Handle<GlobalObject> global, | 2939 Handle<GlobalObject> global, |
2925 Handle<JSGlobalPropertyCell> cell, | 2940 Handle<JSGlobalPropertyCell> cell, |
2926 Handle<String> name, | 2941 Handle<String> name, |
2927 bool is_dont_delete) { | 2942 bool is_dont_delete) { |
2928 Label success, miss; | 2943 Label success, miss; |
2929 | 2944 |
2930 HandlerFrontendHeader(object, receiver(), Handle<JSObject>::cast(global), | 2945 __ CheckMap( |
2931 name, &miss, PERFORM_INITIAL_CHECKS); | 2946 receiver(), scratch1(), Handle<Map>(object->map()), &miss, DO_SMI_CHECK); |
| 2947 HandlerFrontendHeader( |
| 2948 object, receiver(), Handle<JSObject>::cast(global), name, &miss); |
2932 | 2949 |
2933 // Get the value from the cell. | 2950 // Get the value from the cell. |
2934 __ li(a3, Operand(cell)); | 2951 __ li(a3, Operand(cell)); |
2935 __ lw(t0, FieldMemOperand(a3, JSGlobalPropertyCell::kValueOffset)); | 2952 __ lw(t0, FieldMemOperand(a3, JSGlobalPropertyCell::kValueOffset)); |
2936 | 2953 |
2937 // Check for deleted property if property can actually be deleted. | 2954 // Check for deleted property if property can actually be deleted. |
2938 if (!is_dont_delete) { | 2955 if (!is_dont_delete) { |
2939 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 2956 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
2940 __ Branch(&miss, eq, t0, Operand(at)); | 2957 __ Branch(&miss, eq, t0, Operand(at)); |
2941 } | 2958 } |
2942 | 2959 |
2943 HandlerFrontendFooter(&success, &miss); | 2960 HandlerFrontendFooter(&success, &miss); |
2944 __ bind(&success); | 2961 __ bind(&success); |
2945 | 2962 |
2946 Counters* counters = masm()->isolate()->counters(); | 2963 Counters* counters = masm()->isolate()->counters(); |
2947 __ IncrementCounter(counters->named_load_global_stub(), 1, a1, a3); | 2964 __ IncrementCounter(counters->named_load_global_stub(), 1, a1, a3); |
2948 __ mov(v0, t0); | 2965 __ mov(v0, t0); |
2949 __ Ret(); | 2966 __ Ret(); |
2950 | 2967 |
2951 // Return the generated code. | 2968 // Return the generated code. |
2952 return GetCode(Code::NORMAL, name); | 2969 return GetCode(Code::IC_FRAGMENT, Code::NORMAL, name); |
2953 } | 2970 } |
2954 | 2971 |
2955 | 2972 |
2956 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( | 2973 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( |
2957 Handle<Map> receiver_map) { | 2974 Handle<Map> receiver_map) { |
2958 // ----------- S t a t e ------------- | 2975 // ----------- S t a t e ------------- |
2959 // -- ra : return address | 2976 // -- ra : return address |
2960 // -- a0 : key | 2977 // -- a0 : key |
2961 // -- a1 : receiver | 2978 // -- a1 : receiver |
2962 // ----------------------------------- | 2979 // ----------------------------------- |
2963 ElementsKind elements_kind = receiver_map->elements_kind(); | 2980 ElementsKind elements_kind = receiver_map->elements_kind(); |
2964 if (receiver_map->has_fast_elements() || | 2981 if (receiver_map->has_fast_elements() || |
2965 receiver_map->has_external_array_elements()) { | 2982 receiver_map->has_external_array_elements()) { |
2966 Handle<Code> stub = KeyedLoadFastElementStub( | 2983 Handle<Code> stub = KeyedLoadFastElementStub( |
2967 receiver_map->instance_type() == JS_ARRAY_TYPE, | 2984 receiver_map->instance_type() == JS_ARRAY_TYPE, |
2968 elements_kind).GetCode(isolate()); | 2985 elements_kind).GetCode(isolate()); |
2969 __ DispatchMap(a1, a2, receiver_map, stub, DO_SMI_CHECK); | 2986 __ DispatchMap(a1, a2, receiver_map, stub, DO_SMI_CHECK); |
2970 } else { | 2987 } else { |
2971 Handle<Code> stub = | 2988 Handle<Code> stub = |
2972 KeyedLoadDictionaryElementStub().GetCode(isolate()); | 2989 KeyedLoadDictionaryElementStub().GetCode(isolate()); |
2973 __ DispatchMap(a1, a2, receiver_map, stub, DO_SMI_CHECK); | 2990 __ DispatchMap(a1, a2, receiver_map, stub, DO_SMI_CHECK); |
2974 } | 2991 } |
2975 | 2992 |
2976 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss(); | 2993 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss(); |
2977 __ Jump(ic, RelocInfo::CODE_TARGET); | 2994 __ Jump(ic, RelocInfo::CODE_TARGET); |
2978 | 2995 |
2979 // Return the generated code. | 2996 // Return the generated code. |
2980 return GetCode(Code::NORMAL, factory()->empty_string()); | 2997 return GetCode(Code::IC_FRAGMENT, Code::NORMAL, factory()->empty_string()); |
2981 } | 2998 } |
2982 | 2999 |
2983 | 3000 |
2984 Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC( | 3001 Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC( |
2985 MapHandleList* receiver_maps, | 3002 MapHandleList* receiver_maps, |
2986 CodeHandleList* handlers) { | 3003 CodeHandleList* handlers, |
2987 // ----------- S t a t e ------------- | 3004 Handle<String> name, |
2988 // -- ra : return address | 3005 Code::StubType type, |
2989 // -- a0 : key | 3006 IcCheckType check) { |
2990 // -- a1 : receiver | |
2991 // ----------------------------------- | |
2992 Label miss; | 3007 Label miss; |
2993 __ JumpIfSmi(a1, &miss); | 3008 |
| 3009 if (check == PROPERTY) { |
| 3010 GenerateNameCheck(name, this->name(), &miss); |
| 3011 } |
| 3012 |
| 3013 __ JumpIfSmi(receiver(), &miss); |
| 3014 Register map_reg = scratch1(); |
2994 | 3015 |
2995 int receiver_count = receiver_maps->length(); | 3016 int receiver_count = receiver_maps->length(); |
2996 __ lw(a2, FieldMemOperand(a1, HeapObject::kMapOffset)); | 3017 __ lw(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset)); |
2997 for (int current = 0; current < receiver_count; ++current) { | 3018 for (int current = 0; current < receiver_count; ++current) { |
2998 __ Jump(handlers->at(current), RelocInfo::CODE_TARGET, | 3019 __ Jump(handlers->at(current), RelocInfo::CODE_TARGET, |
2999 eq, a2, Operand(receiver_maps->at(current))); | 3020 eq, map_reg, Operand(receiver_maps->at(current))); |
3000 } | 3021 } |
3001 | 3022 |
3002 __ bind(&miss); | 3023 __ bind(&miss); |
3003 GenerateLoadMiss(masm(), kind()); | 3024 GenerateLoadMiss(masm(), kind()); |
3004 | 3025 |
3005 // Return the generated code. | 3026 // Return the generated code. |
3006 return GetCode(Code::NORMAL, factory()->empty_string(), POLYMORPHIC); | 3027 InlineCacheState state = |
| 3028 receiver_maps->length() > 1 ? POLYMORPHIC : MONOMORPHIC; |
| 3029 return GetCode(Code::IC_FRAGMENT, type, name, state); |
3007 } | 3030 } |
3008 | 3031 |
3009 | 3032 |
3010 Handle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object, | 3033 Handle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object, |
3011 int index, | 3034 int index, |
3012 Handle<Map> transition, | 3035 Handle<Map> transition, |
3013 Handle<String> name) { | 3036 Handle<String> name) { |
3014 // ----------- S t a t e ------------- | 3037 // ----------- S t a t e ------------- |
3015 // -- a0 : value | 3038 // -- a0 : value |
3016 // -- a1 : key | 3039 // -- a1 : key |
(...skipping 1094 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4111 __ Jump(ic_slow, RelocInfo::CODE_TARGET); | 4134 __ Jump(ic_slow, RelocInfo::CODE_TARGET); |
4112 } | 4135 } |
4113 } | 4136 } |
4114 | 4137 |
4115 | 4138 |
4116 #undef __ | 4139 #undef __ |
4117 | 4140 |
4118 } } // namespace v8::internal | 4141 } } // namespace v8::internal |
4119 | 4142 |
4120 #endif // V8_TARGET_ARCH_MIPS | 4143 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |