OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/api.h" | 8 #include "src/api.h" |
9 #include "src/arguments.h" | 9 #include "src/arguments.h" |
10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
(...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
599 CompareICStub stub(target->stub_key(), isolate); | 599 CompareICStub stub(target->stub_key(), isolate); |
600 // Only clear CompareICs that can retain objects. | 600 // Only clear CompareICs that can retain objects. |
601 if (stub.state() != CompareICState::KNOWN_OBJECT) return; | 601 if (stub.state() != CompareICState::KNOWN_OBJECT) return; |
602 SetTargetAtAddress(address, GetRawUninitialized(isolate, stub.op()), | 602 SetTargetAtAddress(address, GetRawUninitialized(isolate, stub.op()), |
603 constant_pool); | 603 constant_pool); |
604 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK); | 604 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK); |
605 } | 605 } |
606 | 606 |
607 | 607 |
608 // static | 608 // static |
609 Handle<Code> KeyedLoadIC::generic_stub(Isolate* isolate) { | 609 Handle<Code> KeyedLoadIC::megamorphic_stub(Isolate* isolate) { |
610 if (FLAG_compiled_keyed_generic_loads) { | 610 if (FLAG_compiled_keyed_generic_loads) { |
611 // TODO(dcarney): what do to here? | |
Jakob Kummerow
2015/01/29 15:58:55
Put in a TODO comment into the hydrogen-generated
| |
611 return KeyedLoadGenericStub(isolate).GetCode(); | 612 return KeyedLoadGenericStub(isolate).GetCode(); |
612 } else { | 613 } else { |
613 return isolate->builtins()->KeyedLoadIC_Generic(); | 614 return isolate->builtins()->KeyedLoadIC_Megamorphic(); |
614 } | 615 } |
615 } | 616 } |
616 | 617 |
617 | 618 |
618 static bool MigrateDeprecated(Handle<Object> object) { | 619 static bool MigrateDeprecated(Handle<Object> object) { |
619 if (!object->IsJSObject()) return false; | 620 if (!object->IsJSObject()) return false; |
620 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 621 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
621 if (!receiver->map()->is_deprecated()) return false; | 622 if (!receiver->map()->is_deprecated()) return false; |
622 JSObject::MigrateInstance(Handle<JSObject>::cast(object)); | 623 JSObject::MigrateInstance(Handle<JSObject>::cast(object)); |
623 return true; | 624 return true; |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
699 | 700 |
700 // Check if the name is trivially convertible to an index and get | 701 // Check if the name is trivially convertible to an index and get |
701 // the element or char if so. | 702 // the element or char if so. |
702 uint32_t index; | 703 uint32_t index; |
703 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { | 704 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { |
704 // Rewrite to the generic keyed load stub. | 705 // Rewrite to the generic keyed load stub. |
705 if (FLAG_use_ic) { | 706 if (FLAG_use_ic) { |
706 if (UseVector()) { | 707 if (UseVector()) { |
707 ConfigureVectorState(GENERIC); | 708 ConfigureVectorState(GENERIC); |
708 } else { | 709 } else { |
709 set_target(*KeyedLoadIC::generic_stub(isolate())); | 710 set_target(*KeyedLoadIC::megamorphic_stub(isolate())); |
710 } | 711 } |
711 TRACE_IC("LoadIC", name); | 712 TRACE_IC("LoadIC", name); |
712 TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index"); | 713 TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index"); |
713 } | 714 } |
714 Handle<Object> result; | 715 Handle<Object> result; |
715 ASSIGN_RETURN_ON_EXCEPTION( | 716 ASSIGN_RETURN_ON_EXCEPTION( |
716 isolate(), result, | 717 isolate(), result, |
717 Runtime::GetElementOrCharAt(isolate(), object, index), Object); | 718 Runtime::GetElementOrCharAt(isolate(), object, index), Object); |
718 return result; | 719 return result; |
719 } | 720 } |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
964 vector_set_ = true; | 965 vector_set_ = true; |
965 } else { | 966 } else { |
966 target_set_ = true; | 967 target_set_ = true; |
967 } | 968 } |
968 break; | 969 break; |
969 case DEBUG_STUB: | 970 case DEBUG_STUB: |
970 break; | 971 break; |
971 case DEFAULT: | 972 case DEFAULT: |
972 UNREACHABLE(); | 973 UNREACHABLE(); |
973 break; | 974 break; |
974 case GENERIC: | 975 case GENERIC: |
Jakob Kummerow
2015/01/29 15:58:55
nit: just combine it with the DEFAULT case.
| |
975 // The generic keyed store stub re-uses store handlers, which can miss. | 976 UNREACHABLE(); |
976 // That's ok, no reason to do anything. | |
977 DCHECK(target()->kind() == Code::KEYED_STORE_IC); | |
978 break; | 977 break; |
979 } | 978 } |
980 } | 979 } |
981 | 980 |
982 | 981 |
983 Handle<Code> LoadIC::initialize_stub(Isolate* isolate, | 982 Handle<Code> LoadIC::initialize_stub(Isolate* isolate, |
984 ExtraICState extra_state) { | 983 ExtraICState extra_state) { |
985 if (FLAG_vector_ics) { | 984 if (FLAG_vector_ics) { |
986 return LoadICTrampolineStub(isolate, LoadICState(extra_state)).GetCode(); | 985 return LoadICTrampolineStub(isolate, LoadICState(extra_state)).GetCode(); |
987 } | 986 } |
(...skipping 27 matching lines...) Expand all Loading... | |
1015 return initialize_stub(isolate); | 1014 return initialize_stub(isolate); |
1016 } | 1015 } |
1017 | 1016 |
1018 | 1017 |
1019 Handle<Code> LoadIC::megamorphic_stub() { | 1018 Handle<Code> LoadIC::megamorphic_stub() { |
1020 if (kind() == Code::LOAD_IC) { | 1019 if (kind() == Code::LOAD_IC) { |
1021 MegamorphicLoadStub stub(isolate(), LoadICState(extra_ic_state())); | 1020 MegamorphicLoadStub stub(isolate(), LoadICState(extra_ic_state())); |
1022 return stub.GetCode(); | 1021 return stub.GetCode(); |
1023 } else { | 1022 } else { |
1024 DCHECK_EQ(Code::KEYED_LOAD_IC, kind()); | 1023 DCHECK_EQ(Code::KEYED_LOAD_IC, kind()); |
1025 return KeyedLoadIC::generic_stub(isolate()); | 1024 return KeyedLoadIC::megamorphic_stub(isolate()); |
1026 } | 1025 } |
1027 } | 1026 } |
1028 | 1027 |
1029 | 1028 |
1030 Handle<Code> LoadIC::pre_monomorphic_stub(Isolate* isolate, | 1029 Handle<Code> LoadIC::pre_monomorphic_stub(Isolate* isolate, |
1031 ExtraICState extra_state) { | 1030 ExtraICState extra_state) { |
1032 DCHECK(!FLAG_vector_ics); | 1031 DCHECK(!FLAG_vector_ics); |
1033 return PropertyICCompiler::ComputeLoad(isolate, PREMONOMORPHIC, extra_state); | 1032 return PropertyICCompiler::ComputeLoad(isolate, PREMONOMORPHIC, extra_state); |
1034 } | 1033 } |
1035 | 1034 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1084 } else { | 1083 } else { |
1085 code = ComputeHandler(lookup); | 1084 code = ComputeHandler(lookup); |
1086 } | 1085 } |
1087 | 1086 |
1088 PatchCache(lookup->name(), code); | 1087 PatchCache(lookup->name(), code); |
1089 TRACE_IC("LoadIC", lookup->name()); | 1088 TRACE_IC("LoadIC", lookup->name()); |
1090 } | 1089 } |
1091 | 1090 |
1092 | 1091 |
1093 void IC::UpdateMegamorphicCache(HeapType* type, Name* name, Code* code) { | 1092 void IC::UpdateMegamorphicCache(HeapType* type, Name* name, Code* code) { |
1094 // Megamorphic state isn't implemented for keyed loads currently. | |
1095 if (kind() == Code::KEYED_LOAD_IC) return; | |
1096 Map* map = *TypeToMap(type, isolate()); | 1093 Map* map = *TypeToMap(type, isolate()); |
1097 isolate()->stub_cache()->Set(name, map, code); | 1094 isolate()->stub_cache()->Set(name, map, code); |
1098 } | 1095 } |
1099 | 1096 |
1100 | 1097 |
1101 Handle<Code> IC::ComputeHandler(LookupIterator* lookup, Handle<Object> value) { | 1098 Handle<Code> IC::ComputeHandler(LookupIterator* lookup, Handle<Object> value) { |
1102 bool receiver_is_holder = | 1099 bool receiver_is_holder = |
1103 lookup->GetReceiver().is_identical_to(lookup->GetHolder<JSObject>()); | 1100 lookup->GetReceiver().is_identical_to(lookup->GetHolder<JSObject>()); |
1104 CacheHolderFlag flag; | 1101 CacheHolderFlag flag; |
1105 Handle<Map> stub_holder_map = IC::GetHandlerCacheHolder( | 1102 Handle<Map> stub_holder_map = IC::GetHandlerCacheHolder( |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1363 } | 1360 } |
1364 | 1361 |
1365 DCHECK(state() != GENERIC); | 1362 DCHECK(state() != GENERIC); |
1366 | 1363 |
1367 // Determine the list of receiver maps that this call site has seen, | 1364 // Determine the list of receiver maps that this call site has seen, |
1368 // adding the map that was just encountered. | 1365 // adding the map that was just encountered. |
1369 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) { | 1366 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) { |
1370 // If the miss wasn't due to an unseen map, a polymorphic stub | 1367 // If the miss wasn't due to an unseen map, a polymorphic stub |
1371 // won't help, use the generic stub. | 1368 // won't help, use the generic stub. |
1372 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "same map added twice"); | 1369 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "same map added twice"); |
1373 return generic_stub(); | 1370 return megamorphic_stub(isolate()); |
1374 } | 1371 } |
1375 | 1372 |
1376 // If the maximum number of receiver maps has been exceeded, use the generic | 1373 // If the maximum number of receiver maps has been exceeded, use the generic |
1377 // version of the IC. | 1374 // version of the IC. |
1378 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { | 1375 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { |
1379 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "max polymorph exceeded"); | 1376 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "max polymorph exceeded"); |
1380 return generic_stub(); | 1377 return megamorphic_stub(isolate()); |
1381 } | 1378 } |
1382 | 1379 |
1383 if (FLAG_vector_ics) { | 1380 if (FLAG_vector_ics) { |
1384 CodeHandleList handlers(target_receiver_maps.length()); | 1381 CodeHandleList handlers(target_receiver_maps.length()); |
1385 ElementHandlerCompiler compiler(isolate()); | 1382 ElementHandlerCompiler compiler(isolate()); |
1386 compiler.CompileElementHandlers(&target_receiver_maps, &handlers); | 1383 compiler.CompileElementHandlers(&target_receiver_maps, &handlers); |
1387 TypeHandleList types(target_receiver_maps.length()); | 1384 TypeHandleList types(target_receiver_maps.length()); |
1388 for (int i = 0; i < target_receiver_maps.length(); i++) { | 1385 for (int i = 0; i < target_receiver_maps.length(); i++) { |
1389 types.Add(HeapType::Class(target_receiver_maps.at(i), isolate())); | 1386 types.Add(HeapType::Class(target_receiver_maps.at(i), isolate())); |
1390 } | 1387 } |
1391 ConfigureVectorState(Handle<Name>::null(), &types, &handlers); | 1388 ConfigureVectorState(Handle<Name>::null(), &types, &handlers); |
1392 return null_handle; | 1389 return null_handle; |
1393 } | 1390 } |
1394 | 1391 |
1395 return PropertyICCompiler::ComputeKeyedLoadPolymorphic(&target_receiver_maps); | 1392 return PropertyICCompiler::ComputeKeyedLoadPolymorphic(&target_receiver_maps); |
1396 } | 1393 } |
1397 | 1394 |
1398 | 1395 |
1399 MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object, | 1396 MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object, |
1400 Handle<Object> key) { | 1397 Handle<Object> key) { |
1401 if (MigrateDeprecated(object)) { | 1398 if (MigrateDeprecated(object)) { |
1402 Handle<Object> result; | 1399 Handle<Object> result; |
1403 ASSIGN_RETURN_ON_EXCEPTION( | 1400 ASSIGN_RETURN_ON_EXCEPTION( |
1404 isolate(), result, Runtime::GetObjectProperty(isolate(), object, key), | 1401 isolate(), result, Runtime::GetObjectProperty(isolate(), object, key), |
1405 Object); | 1402 Object); |
1406 return result; | 1403 return result; |
1407 } | 1404 } |
1408 | 1405 |
1409 Handle<Object> load_handle; | 1406 Handle<Object> load_handle; |
1410 Handle<Code> stub = generic_stub(); | 1407 Handle<Code> stub = megamorphic_stub(isolate()); |
1411 | 1408 |
1412 // Check for non-string values that can be converted into an | 1409 // Check for non-string values that can be converted into an |
1413 // internalized string directly or is representable as a smi. | 1410 // internalized string directly or is representable as a smi. |
1414 key = TryConvertKey(key, isolate()); | 1411 key = TryConvertKey(key, isolate()); |
1415 | 1412 |
1416 if (key->IsInternalizedString() || key->IsSymbol()) { | 1413 if (key->IsInternalizedString() || key->IsSymbol()) { |
1417 ASSIGN_RETURN_ON_EXCEPTION(isolate(), load_handle, | 1414 ASSIGN_RETURN_ON_EXCEPTION(isolate(), load_handle, |
1418 LoadIC::Load(object, Handle<Name>::cast(key)), | 1415 LoadIC::Load(object, Handle<Name>::cast(key)), |
1419 Object); | 1416 Object); |
1420 } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) { | 1417 } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) { |
1421 if (object->IsJSObject() || (object->IsString() && key->IsNumber())) { | 1418 if (object->IsJSObject() || (object->IsString() && key->IsNumber())) { |
1422 Handle<HeapObject> receiver = Handle<HeapObject>::cast(object); | 1419 Handle<HeapObject> receiver = Handle<HeapObject>::cast(object); |
1423 if (object->IsString() || !Object::ToSmi(isolate(), key).is_null()) { | 1420 if (object->IsString() || !Object::ToSmi(isolate(), key).is_null()) { |
1424 stub = LoadElementStub(receiver); | 1421 stub = LoadElementStub(receiver); |
1425 } | 1422 } |
1426 } | 1423 } |
1427 } | 1424 } |
1428 | 1425 |
1429 if (!UseVector()) { | 1426 if (!UseVector()) { |
1430 if (!is_target_set()) { | 1427 if (!is_target_set()) { |
1431 Code* generic = *generic_stub(); | 1428 Code* generic = *megamorphic_stub(isolate()); |
1432 if (*stub == generic) { | 1429 if (*stub == generic) { |
1433 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); | 1430 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); |
1434 } | 1431 } |
1435 | 1432 |
1436 set_target(*stub); | 1433 set_target(*stub); |
1437 TRACE_IC("LoadIC", key); | 1434 TRACE_IC("LoadIC", key); |
1438 } | 1435 } |
1439 } else { | 1436 } else { |
1440 if (!is_vector_set() || stub.is_null()) { | 1437 if (!is_vector_set() || stub.is_null()) { |
1441 Code* generic = *generic_stub(); | 1438 Code* generic = *megamorphic_stub(isolate()); |
1442 if (!stub.is_null() && *stub == generic) { | 1439 if (!stub.is_null() && *stub == generic) { |
1443 ConfigureVectorState(GENERIC); | 1440 ConfigureVectorState(GENERIC); |
Jakob Kummerow
2015/01/29 15:58:55
In a follow-up CL, please port the renaming change
| |
1444 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); | 1441 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); |
1445 } | 1442 } |
1446 | 1443 |
1447 TRACE_IC("LoadIC", key); | 1444 TRACE_IC("LoadIC", key); |
1448 } | 1445 } |
1449 } | 1446 } |
1450 | 1447 |
1451 if (!load_handle.is_null()) return load_handle; | 1448 if (!load_handle.is_null()) return load_handle; |
1452 Handle<Object> result; | 1449 Handle<Object> result; |
1453 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result, | 1450 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result, |
(...skipping 1550 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3004 static const Address IC_utilities[] = { | 3001 static const Address IC_utilities[] = { |
3005 #define ADDR(name) FUNCTION_ADDR(name), | 3002 #define ADDR(name) FUNCTION_ADDR(name), |
3006 IC_UTIL_LIST(ADDR) NULL | 3003 IC_UTIL_LIST(ADDR) NULL |
3007 #undef ADDR | 3004 #undef ADDR |
3008 }; | 3005 }; |
3009 | 3006 |
3010 | 3007 |
3011 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } | 3008 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } |
3012 } | 3009 } |
3013 } // namespace v8::internal | 3010 } // namespace v8::internal |
OLD | NEW |