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