Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(93)

Side by Side Diff: src/arm/stub-cache-arm.cc

Issue 12340112: Polymorphism support for load IC. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Added ARM port, introduced GenerateTailCall Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm/ic-arm.cc ('k') | src/builtins.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/arm/ic-arm.cc ('k') | src/builtins.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698