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