OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
361 ? initialize_stub_strict() | 361 ? initialize_stub_strict() |
362 : initialize_stub()); | 362 : initialize_stub()); |
363 } | 363 } |
364 | 364 |
365 | 365 |
366 static bool HasInterceptorGetter(JSObject* object) { | 366 static bool HasInterceptorGetter(JSObject* object) { |
367 return !object->GetNamedInterceptor()->getter()->IsUndefined(); | 367 return !object->GetNamedInterceptor()->getter()->IsUndefined(); |
368 } | 368 } |
369 | 369 |
370 | 370 |
371 static void LookupForRead(Object* object, | |
372 String* name, | |
373 LookupResult* lookup) { | |
374 AssertNoAllocation no_gc; | |
375 // Skip all the objects with named interceptors, but | |
376 // without actual getter. | |
377 while (true) { | |
378 object->Lookup(name, lookup); | |
379 // Besides normal conditions (property not found or it's not | |
380 // an interceptor), bail out if lookup is not cacheable: we won't | |
381 // be able to IC it anyway and regular lookup should work fine. | |
382 if (!lookup->IsFound() | |
383 || (lookup->type() != INTERCEPTOR) | |
384 || !lookup->IsCacheable()) { | |
385 return; | |
386 } | |
387 | |
388 JSObject* holder = lookup->holder(); | |
389 if (HasInterceptorGetter(holder)) { | |
390 return; | |
391 } | |
392 | |
393 holder->LocalLookupRealNamedProperty(name, lookup); | |
394 if (lookup->IsProperty()) { | |
395 ASSERT(lookup->type() != INTERCEPTOR); | |
396 return; | |
397 } | |
398 | |
399 Object* proto = holder->GetPrototype(); | |
400 if (proto->IsNull()) { | |
401 lookup->NotFound(); | |
402 return; | |
403 } | |
404 | |
405 object = proto; | |
406 } | |
407 } | |
408 | |
409 | |
410 static void LookupForRead(Handle<Object> object, | 371 static void LookupForRead(Handle<Object> object, |
411 Handle<String> name, | 372 Handle<String> name, |
412 LookupResult* lookup) { | 373 LookupResult* lookup) { |
413 // Skip all the objects with named interceptors, but | 374 // Skip all the objects with named interceptors, but |
414 // without actual getter. | 375 // without actual getter. |
415 while (true) { | 376 while (true) { |
416 object->Lookup(*name, lookup); | 377 object->Lookup(*name, lookup); |
417 // Besides normal conditions (property not found or it's not | 378 // Besides normal conditions (property not found or it's not |
418 // an interceptor), bail out if lookup is not cacheable: we won't | 379 // an interceptor), bail out if lookup is not cacheable: we won't |
419 // be able to IC it anyway and regular lookup should work fine. | 380 // be able to IC it anyway and regular lookup should work fine. |
(...skipping 680 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1100 return object; | 1061 return object; |
1101 } | 1062 } |
1102 | 1063 |
1103 | 1064 |
1104 MaybeObject* KeyedLoadIC::Load(State state, | 1065 MaybeObject* KeyedLoadIC::Load(State state, |
1105 Handle<Object> object, | 1066 Handle<Object> object, |
1106 Handle<Object> key, | 1067 Handle<Object> key, |
1107 bool force_generic_stub) { | 1068 bool force_generic_stub) { |
1108 // Check for values that can be converted into a symbol. | 1069 // Check for values that can be converted into a symbol. |
1109 // TODO(1295): Remove this code. | 1070 // TODO(1295): Remove this code. |
1110 HandleScope scope(isolate()); | |
1111 if (key->IsHeapNumber() && | 1071 if (key->IsHeapNumber() && |
1112 isnan(HeapNumber::cast(*key)->value())) { | 1072 isnan(Handle<HeapNumber>::cast(key)->value())) { |
1113 key = isolate()->factory()->nan_symbol(); | 1073 key = isolate()->factory()->nan_symbol(); |
1114 } else if (key->IsUndefined()) { | 1074 } else if (key->IsUndefined()) { |
1115 key = isolate()->factory()->undefined_symbol(); | 1075 key = isolate()->factory()->undefined_symbol(); |
1116 } | 1076 } |
1117 | 1077 |
1118 if (key->IsSymbol()) { | 1078 if (key->IsSymbol()) { |
1119 Handle<String> name = Handle<String>::cast(key); | 1079 Handle<String> name = Handle<String>::cast(key); |
1120 | 1080 |
1121 // If the object is undefined or null it's illegal to try to get any | 1081 // If the object is undefined or null it's illegal to try to get any |
1122 // of its properties; throw a TypeError in that case. | 1082 // of its properties; throw a TypeError in that case. |
1123 if (object->IsUndefined() || object->IsNull()) { | 1083 if (object->IsUndefined() || object->IsNull()) { |
1124 return TypeError("non_object_property_load", object, name); | 1084 return TypeError("non_object_property_load", object, name); |
1125 } | 1085 } |
1126 | 1086 |
1127 if (FLAG_use_ic) { | 1087 if (FLAG_use_ic) { |
1128 // TODO(1073): don't ignore the current stub state. | 1088 // TODO(1073): don't ignore the current stub state. |
1129 | 1089 |
1130 // Use specialized code for getting the length of strings. | 1090 // Use specialized code for getting the length of strings. |
1131 if (object->IsString() && | 1091 if (object->IsString() && |
1132 name->Equals(isolate()->heap()->length_symbol())) { | 1092 name->Equals(isolate()->heap()->length_symbol())) { |
1133 Handle<String> string = Handle<String>::cast(object); | 1093 Handle<String> string = Handle<String>::cast(object); |
1134 Object* code = NULL; | 1094 Handle<Code> code = |
1135 { MaybeObject* maybe_code = | 1095 isolate()->stub_cache()->ComputeKeyedLoadStringLength(name, |
1136 isolate()->stub_cache()->ComputeKeyedLoadStringLength(*name, | 1096 string); |
1137 *string); | 1097 ASSERT(!code.is_null()); |
1138 if (!maybe_code->ToObject(&code)) return maybe_code; | 1098 set_target(*code); |
1139 } | |
1140 set_target(Code::cast(code)); | |
1141 #ifdef DEBUG | 1099 #ifdef DEBUG |
1142 TraceIC("KeyedLoadIC", name, state, target()); | 1100 TraceIC("KeyedLoadIC", name, state, target()); |
1143 #endif // DEBUG | 1101 #endif // DEBUG |
1144 return Smi::FromInt(string->length()); | 1102 return Smi::FromInt(string->length()); |
1145 } | 1103 } |
1146 | 1104 |
1147 // Use specialized code for getting the length of arrays. | 1105 // Use specialized code for getting the length of arrays. |
1148 if (object->IsJSArray() && | 1106 if (object->IsJSArray() && |
1149 name->Equals(isolate()->heap()->length_symbol())) { | 1107 name->Equals(isolate()->heap()->length_symbol())) { |
1150 Handle<JSArray> array = Handle<JSArray>::cast(object); | 1108 Handle<JSArray> array = Handle<JSArray>::cast(object); |
1151 Object* code; | 1109 Handle<Code> code = |
1152 { MaybeObject* maybe_code = | 1110 isolate()->stub_cache()->ComputeKeyedLoadArrayLength(name, array); |
1153 isolate()->stub_cache()->ComputeKeyedLoadArrayLength(*name, | 1111 ASSERT(!code.is_null()); |
1154 *array); | 1112 set_target(*code); |
1155 if (!maybe_code->ToObject(&code)) return maybe_code; | |
1156 } | |
1157 set_target(Code::cast(code)); | |
1158 #ifdef DEBUG | 1113 #ifdef DEBUG |
1159 TraceIC("KeyedLoadIC", name, state, target()); | 1114 TraceIC("KeyedLoadIC", name, state, target()); |
1160 #endif // DEBUG | 1115 #endif // DEBUG |
1161 return JSArray::cast(*object)->length(); | 1116 return array->length(); |
1162 } | 1117 } |
1163 | 1118 |
1164 // Use specialized code for getting prototype of functions. | 1119 // Use specialized code for getting prototype of functions. |
1165 if (object->IsJSFunction() && | 1120 if (object->IsJSFunction() && |
1166 name->Equals(isolate()->heap()->prototype_symbol()) && | 1121 name->Equals(isolate()->heap()->prototype_symbol()) && |
1167 JSFunction::cast(*object)->should_have_prototype()) { | 1122 Handle<JSFunction>::cast(object)->should_have_prototype()) { |
1168 Handle<JSFunction> function = Handle<JSFunction>::cast(object); | 1123 Handle<JSFunction> function = Handle<JSFunction>::cast(object); |
1169 Object* code; | 1124 Handle<Code> code = |
1170 { MaybeObject* maybe_code = | 1125 isolate()->stub_cache()->ComputeKeyedLoadFunctionPrototype( |
1171 isolate()->stub_cache()->ComputeKeyedLoadFunctionPrototype( | 1126 name, function); |
1172 *name, *function); | 1127 ASSERT(!code.is_null()); |
1173 if (!maybe_code->ToObject(&code)) return maybe_code; | 1128 set_target(*code); |
1174 } | |
1175 set_target(Code::cast(code)); | |
1176 #ifdef DEBUG | 1129 #ifdef DEBUG |
1177 TraceIC("KeyedLoadIC", name, state, target()); | 1130 TraceIC("KeyedLoadIC", name, state, target()); |
1178 #endif // DEBUG | 1131 #endif // DEBUG |
1179 return Accessors::FunctionGetPrototype(*object, 0); | 1132 return Accessors::FunctionGetPrototype(*object, 0); |
1180 } | 1133 } |
1181 } | 1134 } |
1182 | 1135 |
1183 // Check if the name is trivially convertible to an index and get | 1136 // Check if the name is trivially convertible to an index and get |
1184 // the element or char if so. | 1137 // the element or char if so. |
1185 uint32_t index = 0; | 1138 uint32_t index = 0; |
1186 if (name->AsArrayIndex(&index)) { | 1139 if (name->AsArrayIndex(&index)) { |
1187 HandleScope scope(isolate()); | |
1188 // Rewrite to the generic keyed load stub. | 1140 // Rewrite to the generic keyed load stub. |
1189 if (FLAG_use_ic) set_target(generic_stub()); | 1141 if (FLAG_use_ic) set_target(*generic_stub()); |
1190 return Runtime::GetElementOrCharAt(isolate(), object, index); | 1142 return Runtime::GetElementOrCharAt(isolate(), object, index); |
1191 } | 1143 } |
1192 | 1144 |
1193 // Named lookup. | 1145 // Named lookup. |
1194 LookupResult lookup(isolate()); | 1146 LookupResult lookup(isolate()); |
1195 LookupForRead(*object, *name, &lookup); | 1147 LookupForRead(object, name, &lookup); |
1196 | 1148 |
1197 // If we did not find a property, check if we need to throw an exception. | 1149 // If we did not find a property, check if we need to throw an exception. |
1198 if (!lookup.IsProperty() && IsContextual(object)) { | 1150 if (!lookup.IsProperty() && IsContextual(object)) { |
1199 return ReferenceError("not_defined", name); | 1151 return ReferenceError("not_defined", name); |
1200 } | 1152 } |
1201 | 1153 |
1202 if (FLAG_use_ic) { | 1154 if (FLAG_use_ic) { |
1203 UpdateCaches(&lookup, state, object, name); | 1155 UpdateCaches(&lookup, state, object, name); |
1204 } | 1156 } |
1205 | 1157 |
1206 PropertyAttributes attr; | 1158 PropertyAttributes attr; |
1207 if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) { | 1159 if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) { |
1208 // Get the property. | 1160 // Get the property. |
1209 Object* result; | 1161 Handle<Object> result = |
1210 { MaybeObject* maybe_result = | 1162 Object::GetProperty(object, object, &lookup, name, &attr); |
1211 object->GetProperty(*object, &lookup, *name, &attr); | 1163 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
1212 if (!maybe_result->ToObject(&result)) return maybe_result; | |
1213 } | |
1214 // If the property is not present, check if we need to throw an | 1164 // If the property is not present, check if we need to throw an |
1215 // exception. | 1165 // exception. |
1216 if (attr == ABSENT && IsContextual(object)) { | 1166 if (attr == ABSENT && IsContextual(object)) { |
1217 return ReferenceError("not_defined", name); | 1167 return ReferenceError("not_defined", name); |
1218 } | 1168 } |
1219 return result; | 1169 return *result; |
1220 } | 1170 } |
1221 | 1171 |
1222 return object->GetProperty(*object, &lookup, *name, &attr); | 1172 return object->GetProperty(*object, &lookup, *name, &attr); |
1223 } | 1173 } |
1224 | 1174 |
1225 // Do not use ICs for objects that require access checks (including | 1175 // Do not use ICs for objects that require access checks (including |
1226 // the global object). | 1176 // the global object). |
1227 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); | 1177 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); |
1228 | 1178 |
1229 if (use_ic) { | 1179 if (use_ic) { |
1230 Code* stub = generic_stub(); | 1180 Handle<Code> stub = generic_stub(); |
1231 if (!force_generic_stub) { | 1181 if (!force_generic_stub) { |
1232 if (object->IsString() && key->IsNumber()) { | 1182 if (object->IsString() && key->IsNumber()) { |
1233 if (state == UNINITIALIZED) { | 1183 if (state == UNINITIALIZED) { |
1234 stub = string_stub(); | 1184 stub = string_stub(); |
1235 } | 1185 } |
1236 } else if (object->IsJSObject()) { | 1186 } else if (object->IsJSObject()) { |
1237 JSObject* receiver = JSObject::cast(*object); | 1187 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1238 Heap* heap = Handle<JSObject>::cast(object)->GetHeap(); | 1188 if (receiver->elements()->map() == |
1239 Map* elements_map = Handle<JSObject>::cast(object)->elements()->map(); | 1189 isolate()->heap()->non_strict_arguments_elements_map()) { |
1240 if (elements_map == heap->non_strict_arguments_elements_map()) { | |
1241 stub = non_strict_arguments_stub(); | 1190 stub = non_strict_arguments_stub(); |
1242 } else if (receiver->HasIndexedInterceptor()) { | 1191 } else if (receiver->HasIndexedInterceptor()) { |
1243 stub = indexed_interceptor_stub(); | 1192 stub = indexed_interceptor_stub(); |
1244 } else if (key->IsSmi() && (target() != non_strict_arguments_stub())) { | 1193 } else if (key->IsSmi() && (target() != *non_strict_arguments_stub())) { |
1245 MaybeObject* maybe_stub = ComputeStub(receiver, | 1194 stub = ComputeStub(receiver, LOAD, kNonStrictMode, stub); |
1246 LOAD, | |
1247 kNonStrictMode, | |
1248 stub); | |
1249 stub = maybe_stub->IsFailure() ? | |
1250 NULL : Code::cast(maybe_stub->ToObjectUnchecked()); | |
1251 } | 1195 } |
1252 } | 1196 } |
1253 } | 1197 } |
1254 if (stub != NULL) set_target(stub); | 1198 if (!stub.is_null()) set_target(*stub); |
1255 } | 1199 } |
1256 | 1200 |
1257 #ifdef DEBUG | 1201 #ifdef DEBUG |
1258 TraceIC("KeyedLoadIC", key, state, target()); | 1202 TraceIC("KeyedLoadIC", key, state, target()); |
1259 #endif // DEBUG | 1203 #endif // DEBUG |
1260 | 1204 |
1261 // Get the property. | 1205 // Get the property. |
1262 return Runtime::GetObjectProperty(isolate(), object, key); | 1206 return Runtime::GetObjectProperty(isolate(), object, key); |
1263 } | 1207 } |
1264 | 1208 |
1265 | 1209 |
1266 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state, | 1210 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, |
1267 Handle<Object> object, Handle<String> name) { | 1211 State state, |
| 1212 Handle<Object> object, |
| 1213 Handle<String> name) { |
1268 // Bail out if we didn't find a result. | 1214 // Bail out if we didn't find a result. |
1269 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; | 1215 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; |
1270 | 1216 |
1271 if (!object->IsJSObject()) return; | 1217 if (!object->IsJSObject()) return; |
1272 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1218 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1273 | 1219 |
1274 if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return; | 1220 if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return; |
1275 | 1221 |
1276 // Compute the code stub for this load. | 1222 // Compute the code stub for this load. |
1277 MaybeObject* maybe_code = NULL; | 1223 Handle<Code> code; |
1278 Object* code; | |
1279 | 1224 |
1280 if (state == UNINITIALIZED) { | 1225 if (state == UNINITIALIZED) { |
1281 // This is the first time we execute this inline cache. | 1226 // This is the first time we execute this inline cache. |
1282 // Set the target to the pre monomorphic stub to delay | 1227 // Set the target to the pre monomorphic stub to delay |
1283 // setting the monomorphic state. | 1228 // setting the monomorphic state. |
1284 maybe_code = pre_monomorphic_stub(); | 1229 code = pre_monomorphic_stub(); |
1285 } else { | 1230 } else { |
1286 // Compute a monomorphic stub. | 1231 // Compute a monomorphic stub. |
| 1232 Handle<JSObject> holder(lookup->holder()); |
1287 switch (lookup->type()) { | 1233 switch (lookup->type()) { |
1288 case FIELD: { | 1234 case FIELD: |
1289 maybe_code = isolate()->stub_cache()->ComputeKeyedLoadField( | 1235 code = isolate()->stub_cache()->ComputeKeyedLoadField( |
1290 *name, *receiver, lookup->holder(), lookup->GetFieldIndex()); | 1236 name, receiver, holder, lookup->GetFieldIndex()); |
1291 break; | 1237 break; |
1292 } | |
1293 case CONSTANT_FUNCTION: { | 1238 case CONSTANT_FUNCTION: { |
1294 Object* constant = lookup->GetConstantFunction(); | 1239 Handle<Object> constant(lookup->GetConstantFunction()); |
1295 maybe_code = isolate()->stub_cache()->ComputeKeyedLoadConstant( | 1240 code = isolate()->stub_cache()->ComputeKeyedLoadConstant( |
1296 *name, *receiver, lookup->holder(), constant); | 1241 name, receiver, holder, constant); |
1297 break; | 1242 break; |
1298 } | 1243 } |
1299 case CALLBACKS: { | 1244 case CALLBACKS: { |
1300 if (!lookup->GetCallbackObject()->IsAccessorInfo()) return; | 1245 Handle<Object> callback_object(lookup->GetCallbackObject()); |
1301 AccessorInfo* callback = | 1246 if (!callback_object->IsAccessorInfo()) return; |
1302 AccessorInfo::cast(lookup->GetCallbackObject()); | 1247 Handle<AccessorInfo> callback = |
| 1248 Handle<AccessorInfo>::cast(callback_object); |
1303 if (v8::ToCData<Address>(callback->getter()) == 0) return; | 1249 if (v8::ToCData<Address>(callback->getter()) == 0) return; |
1304 maybe_code = isolate()->stub_cache()->ComputeKeyedLoadCallback( | 1250 code = isolate()->stub_cache()->ComputeKeyedLoadCallback( |
1305 *name, *receiver, lookup->holder(), callback); | 1251 name, receiver, holder, callback); |
1306 break; | 1252 break; |
1307 } | 1253 } |
1308 case INTERCEPTOR: { | 1254 case INTERCEPTOR: |
1309 ASSERT(HasInterceptorGetter(lookup->holder())); | 1255 ASSERT(HasInterceptorGetter(lookup->holder())); |
1310 maybe_code = isolate()->stub_cache()->ComputeKeyedLoadInterceptor( | 1256 code = isolate()->stub_cache()->ComputeKeyedLoadInterceptor( |
1311 *name, *receiver, lookup->holder()); | 1257 name, receiver, holder); |
1312 break; | 1258 break; |
1313 } | 1259 default: |
1314 default: { | |
1315 // Always rewrite to the generic case so that we do not | 1260 // Always rewrite to the generic case so that we do not |
1316 // repeatedly try to rewrite. | 1261 // repeatedly try to rewrite. |
1317 maybe_code = generic_stub(); | 1262 code = generic_stub(); |
1318 break; | 1263 break; |
1319 } | |
1320 } | 1264 } |
1321 } | 1265 } |
1322 | 1266 |
1323 // If we're unable to compute the stub (not enough memory left), we | |
1324 // simply avoid updating the caches. | |
1325 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return; | |
1326 | |
1327 // Patch the call site depending on the state of the cache. Make | 1267 // Patch the call site depending on the state of the cache. Make |
1328 // sure to always rewrite from monomorphic to megamorphic. | 1268 // sure to always rewrite from monomorphic to megamorphic. |
1329 ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE); | 1269 ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE); |
1330 if (state == UNINITIALIZED || state == PREMONOMORPHIC) { | 1270 if (state == UNINITIALIZED || state == PREMONOMORPHIC) { |
1331 set_target(Code::cast(code)); | 1271 set_target(*code); |
1332 } else if (state == MONOMORPHIC) { | 1272 } else if (state == MONOMORPHIC) { |
1333 set_target(megamorphic_stub()); | 1273 set_target(*megamorphic_stub()); |
1334 } | 1274 } |
1335 | 1275 |
1336 #ifdef DEBUG | 1276 #ifdef DEBUG |
1337 TraceIC("KeyedLoadIC", name, state, target()); | 1277 TraceIC("KeyedLoadIC", name, state, target()); |
1338 #endif | 1278 #endif |
1339 } | 1279 } |
1340 | 1280 |
1341 | 1281 |
1342 static bool StoreICableLookup(LookupResult* lookup) { | 1282 static bool StoreICableLookup(LookupResult* lookup) { |
1343 // Bail out if we didn't find a result. | 1283 // Bail out if we didn't find a result. |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1559 return false; | 1499 return false; |
1560 } | 1500 } |
1561 } | 1501 } |
1562 receiver_maps->Add(new_receiver_map); | 1502 receiver_maps->Add(new_receiver_map); |
1563 return true; | 1503 return true; |
1564 } | 1504 } |
1565 | 1505 |
1566 | 1506 |
1567 void KeyedIC::GetReceiverMapsForStub(Code* stub, MapList* result) { | 1507 void KeyedIC::GetReceiverMapsForStub(Code* stub, MapList* result) { |
1568 ASSERT(stub->is_inline_cache_stub()); | 1508 ASSERT(stub->is_inline_cache_stub()); |
1569 if (stub == string_stub()) { | 1509 if (!string_stub().is_null() && stub == *string_stub()) { |
1570 return result->Add(isolate()->heap()->string_map()); | 1510 return result->Add(isolate()->heap()->string_map()); |
1571 } else if (stub->is_keyed_load_stub() || stub->is_keyed_store_stub()) { | 1511 } else if (stub->is_keyed_load_stub() || stub->is_keyed_store_stub()) { |
1572 if (stub->ic_state() == MONOMORPHIC) { | 1512 if (stub->ic_state() == MONOMORPHIC) { |
1573 result->Add(Map::cast(stub->FindFirstMap())); | 1513 result->Add(Map::cast(stub->FindFirstMap())); |
1574 } else { | 1514 } else { |
1575 ASSERT(stub->ic_state() == MEGAMORPHIC); | 1515 ASSERT(stub->ic_state() == MEGAMORPHIC); |
1576 AssertNoAllocation no_allocation; | 1516 AssertNoAllocation no_allocation; |
1577 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); | 1517 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); |
1578 for (RelocIterator it(stub, mask); !it.done(); it.next()) { | 1518 for (RelocIterator it(stub, mask); !it.done(); it.next()) { |
1579 RelocInfo* info = it.rinfo(); | 1519 RelocInfo* info = it.rinfo(); |
1580 Object* object = info->target_object(); | 1520 Object* object = info->target_object(); |
1581 ASSERT(object->IsMap()); | 1521 ASSERT(object->IsMap()); |
1582 AddOneReceiverMapIfMissing(result, Map::cast(object)); | 1522 AddOneReceiverMapIfMissing(result, Map::cast(object)); |
1583 } | 1523 } |
1584 } | 1524 } |
1585 } | 1525 } |
1586 } | 1526 } |
1587 | 1527 |
1588 | 1528 |
| 1529 Handle<Code> KeyedIC::ComputeStub(Handle<JSObject> receiver, |
| 1530 StubKind stub_kind, |
| 1531 StrictModeFlag strict_mode, |
| 1532 Handle<Code> generic_stub) { |
| 1533 CALL_HEAP_FUNCTION(isolate(), |
| 1534 ComputeStub(*receiver, |
| 1535 stub_kind, |
| 1536 strict_mode, |
| 1537 *generic_stub), |
| 1538 Code); |
| 1539 } |
| 1540 |
| 1541 |
| 1542 |
1589 MaybeObject* KeyedIC::ComputeStub(JSObject* receiver, | 1543 MaybeObject* KeyedIC::ComputeStub(JSObject* receiver, |
1590 StubKind stub_kind, | 1544 StubKind stub_kind, |
1591 StrictModeFlag strict_mode, | 1545 StrictModeFlag strict_mode, |
1592 Code* generic_stub) { | 1546 Code* generic_stub) { |
1593 State ic_state = target()->ic_state(); | 1547 State ic_state = target()->ic_state(); |
1594 if ((ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) && | 1548 if ((ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) && |
1595 !IsTransitionStubKind(stub_kind)) { | 1549 !IsTransitionStubKind(stub_kind)) { |
1596 Code* monomorphic_stub; | 1550 Code* monomorphic_stub; |
1597 MaybeObject* maybe_stub = ComputeMonomorphicStub(receiver, | 1551 MaybeObject* maybe_stub = ComputeMonomorphicStub(receiver, |
1598 stub_kind, | 1552 stub_kind, |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1656 MaybeObject* maybe_update = cache->Update(&target_receiver_maps, flags, stub); | 1610 MaybeObject* maybe_update = cache->Update(&target_receiver_maps, flags, stub); |
1657 if (maybe_update->IsFailure()) return maybe_update; | 1611 if (maybe_update->IsFailure()) return maybe_update; |
1658 return stub; | 1612 return stub; |
1659 } | 1613 } |
1660 | 1614 |
1661 | 1615 |
1662 MaybeObject* KeyedIC::ComputeMonomorphicStubWithoutMapCheck( | 1616 MaybeObject* KeyedIC::ComputeMonomorphicStubWithoutMapCheck( |
1663 Map* receiver_map, | 1617 Map* receiver_map, |
1664 StrictModeFlag strict_mode) { | 1618 StrictModeFlag strict_mode) { |
1665 if ((receiver_map->instance_type() & kNotStringTag) == 0) { | 1619 if ((receiver_map->instance_type() & kNotStringTag) == 0) { |
1666 ASSERT(string_stub() != NULL); | 1620 ASSERT(!string_stub().is_null()); |
1667 return string_stub(); | 1621 return *string_stub(); |
1668 } else { | 1622 } else { |
1669 ASSERT(receiver_map->has_dictionary_elements() || | 1623 ASSERT(receiver_map->has_dictionary_elements() || |
1670 receiver_map->has_fast_elements() || | 1624 receiver_map->has_fast_elements() || |
1671 receiver_map->has_fast_smi_only_elements() || | 1625 receiver_map->has_fast_smi_only_elements() || |
1672 receiver_map->has_fast_double_elements() || | 1626 receiver_map->has_fast_double_elements() || |
1673 receiver_map->has_external_array_elements()); | 1627 receiver_map->has_external_array_elements()); |
1674 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; | 1628 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; |
1675 return GetElementStubWithoutMapCheck(is_js_array, | 1629 return GetElementStubWithoutMapCheck(is_js_array, |
1676 receiver_map->elements_kind()); | 1630 receiver_map->elements_kind()); |
1677 } | 1631 } |
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1986 HandleScope scope(isolate); | 1940 HandleScope scope(isolate); |
1987 ASSERT(args.length() == 2); | 1941 ASSERT(args.length() == 2); |
1988 LoadIC ic(isolate); | 1942 LoadIC ic(isolate); |
1989 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 1943 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
1990 return ic.Load(state, args.at<Object>(0), args.at<String>(1)); | 1944 return ic.Load(state, args.at<Object>(0), args.at<String>(1)); |
1991 } | 1945 } |
1992 | 1946 |
1993 | 1947 |
1994 // Used from ic-<arch>.cc | 1948 // Used from ic-<arch>.cc |
1995 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) { | 1949 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) { |
1996 NoHandleAllocation na; | 1950 HandleScope scope(isolate); |
1997 ASSERT(args.length() == 2); | 1951 ASSERT(args.length() == 2); |
1998 KeyedLoadIC ic(isolate); | 1952 KeyedLoadIC ic(isolate); |
1999 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 1953 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
2000 return ic.Load(state, args.at<Object>(0), args.at<Object>(1), false); | 1954 return ic.Load(state, args.at<Object>(0), args.at<Object>(1), false); |
2001 } | 1955 } |
2002 | 1956 |
2003 | 1957 |
2004 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissForceGeneric) { | 1958 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissForceGeneric) { |
2005 NoHandleAllocation na; | 1959 HandleScope scope(isolate); |
2006 ASSERT(args.length() == 2); | 1960 ASSERT(args.length() == 2); |
2007 KeyedLoadIC ic(isolate); | 1961 KeyedLoadIC ic(isolate); |
2008 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 1962 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
2009 return ic.Load(state, args.at<Object>(0), args.at<Object>(1), true); | 1963 return ic.Load(state, args.at<Object>(0), args.at<Object>(1), true); |
2010 } | 1964 } |
2011 | 1965 |
2012 | 1966 |
2013 // Used from ic-<arch>.cc. | 1967 // Used from ic-<arch>.cc. |
2014 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) { | 1968 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) { |
2015 HandleScope scope; | 1969 HandleScope scope; |
(...skipping 527 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2543 #undef ADDR | 2497 #undef ADDR |
2544 }; | 2498 }; |
2545 | 2499 |
2546 | 2500 |
2547 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2501 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
2548 return IC_utilities[id]; | 2502 return IC_utilities[id]; |
2549 } | 2503 } |
2550 | 2504 |
2551 | 2505 |
2552 } } // namespace v8::internal | 2506 } } // namespace v8::internal |
OLD | NEW |