| 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 |