| 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 return KeyedLoadGenericStub(isolate).GetCode(); | 611 return KeyedLoadGenericStub(isolate).GetCode(); |
| 612 } else { | 612 } else { |
| 613 return isolate->builtins()->KeyedLoadIC_Generic(); | 613 return isolate->builtins()->KeyedLoadIC_Megamorphic(); |
| 614 } | 614 } |
| 615 } | 615 } |
| 616 | 616 |
| 617 | 617 |
| 618 static bool MigrateDeprecated(Handle<Object> object) { | 618 static bool MigrateDeprecated(Handle<Object> object) { |
| 619 if (!object->IsJSObject()) return false; | 619 if (!object->IsJSObject()) return false; |
| 620 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 620 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 621 if (!receiver->map()->is_deprecated()) return false; | 621 if (!receiver->map()->is_deprecated()) return false; |
| 622 JSObject::MigrateInstance(Handle<JSObject>::cast(object)); | 622 JSObject::MigrateInstance(Handle<JSObject>::cast(object)); |
| 623 return true; | 623 return true; |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 699 | 699 |
| 700 // Check if the name is trivially convertible to an index and get | 700 // Check if the name is trivially convertible to an index and get |
| 701 // the element or char if so. | 701 // the element or char if so. |
| 702 uint32_t index; | 702 uint32_t index; |
| 703 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { | 703 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { |
| 704 // Rewrite to the generic keyed load stub. | 704 // Rewrite to the generic keyed load stub. |
| 705 if (FLAG_use_ic) { | 705 if (FLAG_use_ic) { |
| 706 if (UseVector()) { | 706 if (UseVector()) { |
| 707 ConfigureVectorState(GENERIC); | 707 ConfigureVectorState(GENERIC); |
| 708 } else { | 708 } else { |
| 709 set_target(*KeyedLoadIC::generic_stub(isolate())); | 709 set_target(*KeyedLoadIC::megamorphic_stub(isolate())); |
| 710 } | 710 } |
| 711 TRACE_IC("LoadIC", name); | 711 TRACE_IC("LoadIC", name); |
| 712 TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index"); | 712 TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index"); |
| 713 } | 713 } |
| 714 Handle<Object> result; | 714 Handle<Object> result; |
| 715 ASSIGN_RETURN_ON_EXCEPTION( | 715 ASSIGN_RETURN_ON_EXCEPTION( |
| 716 isolate(), result, | 716 isolate(), result, |
| 717 Runtime::GetElementOrCharAt(isolate(), object, index), Object); | 717 Runtime::GetElementOrCharAt(isolate(), object, index), Object); |
| 718 return result; | 718 return result; |
| 719 } | 719 } |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 944 case PROTOTYPE_FAILURE: | 944 case PROTOTYPE_FAILURE: |
| 945 case MONOMORPHIC: | 945 case MONOMORPHIC: |
| 946 case POLYMORPHIC: | 946 case POLYMORPHIC: |
| 947 if (!target()->is_keyed_stub() || state() == PROTOTYPE_FAILURE) { | 947 if (!target()->is_keyed_stub() || state() == PROTOTYPE_FAILURE) { |
| 948 if (UpdatePolymorphicIC(name, code)) break; | 948 if (UpdatePolymorphicIC(name, code)) break; |
| 949 // For keyed stubs, we can't know whether old handlers were for the | 949 // For keyed stubs, we can't know whether old handlers were for the |
| 950 // same key. | 950 // same key. |
| 951 CopyICToMegamorphicCache(name); | 951 CopyICToMegamorphicCache(name); |
| 952 } | 952 } |
| 953 if (UseVector()) { | 953 if (UseVector()) { |
| 954 ConfigureVectorState(kind() == Code::KEYED_LOAD_IC ? GENERIC | 954 ConfigureVectorState(MEGAMORPHIC); |
| 955 : MEGAMORPHIC); | |
| 956 } else { | 955 } else { |
| 957 set_target(*megamorphic_stub()); | 956 set_target(*megamorphic_stub()); |
| 958 } | 957 } |
| 959 // Fall through. | 958 // Fall through. |
| 960 case MEGAMORPHIC: | 959 case MEGAMORPHIC: |
| 961 UpdateMegamorphicCache(*receiver_type(), *name, *code); | 960 UpdateMegamorphicCache(*receiver_type(), *name, *code); |
| 962 // Indicate that we've handled this case. | 961 // Indicate that we've handled this case. |
| 963 if (UseVector()) { | 962 if (UseVector()) { |
| 964 vector_set_ = true; | 963 vector_set_ = true; |
| 965 } else { | 964 } else { |
| 966 target_set_ = true; | 965 target_set_ = true; |
| 967 } | 966 } |
| 968 break; | 967 break; |
| 969 case DEBUG_STUB: | 968 case DEBUG_STUB: |
| 970 break; | 969 break; |
| 971 case DEFAULT: | 970 case DEFAULT: |
| 971 case GENERIC: |
| 972 UNREACHABLE(); | 972 UNREACHABLE(); |
| 973 break; | 973 break; |
| 974 case GENERIC: | |
| 975 // The generic keyed store stub re-uses store handlers, which can miss. | |
| 976 // That's ok, no reason to do anything. | |
| 977 DCHECK(target()->kind() == Code::KEYED_STORE_IC); | |
| 978 break; | |
| 979 } | 974 } |
| 980 } | 975 } |
| 981 | 976 |
| 982 | 977 |
| 983 Handle<Code> LoadIC::initialize_stub(Isolate* isolate, | 978 Handle<Code> LoadIC::initialize_stub(Isolate* isolate, |
| 984 ExtraICState extra_state) { | 979 ExtraICState extra_state) { |
| 985 if (FLAG_vector_ics) { | 980 if (FLAG_vector_ics) { |
| 986 return LoadICTrampolineStub(isolate, LoadICState(extra_state)).GetCode(); | 981 return LoadICTrampolineStub(isolate, LoadICState(extra_state)).GetCode(); |
| 987 } | 982 } |
| 988 | 983 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1015 return initialize_stub(isolate); | 1010 return initialize_stub(isolate); |
| 1016 } | 1011 } |
| 1017 | 1012 |
| 1018 | 1013 |
| 1019 Handle<Code> LoadIC::megamorphic_stub() { | 1014 Handle<Code> LoadIC::megamorphic_stub() { |
| 1020 if (kind() == Code::LOAD_IC) { | 1015 if (kind() == Code::LOAD_IC) { |
| 1021 MegamorphicLoadStub stub(isolate(), LoadICState(extra_ic_state())); | 1016 MegamorphicLoadStub stub(isolate(), LoadICState(extra_ic_state())); |
| 1022 return stub.GetCode(); | 1017 return stub.GetCode(); |
| 1023 } else { | 1018 } else { |
| 1024 DCHECK_EQ(Code::KEYED_LOAD_IC, kind()); | 1019 DCHECK_EQ(Code::KEYED_LOAD_IC, kind()); |
| 1025 return KeyedLoadIC::generic_stub(isolate()); | 1020 return KeyedLoadIC::megamorphic_stub(isolate()); |
| 1026 } | 1021 } |
| 1027 } | 1022 } |
| 1028 | 1023 |
| 1029 | 1024 |
| 1030 Handle<Code> LoadIC::pre_monomorphic_stub(Isolate* isolate, | 1025 Handle<Code> LoadIC::pre_monomorphic_stub(Isolate* isolate, |
| 1031 ExtraICState extra_state) { | 1026 ExtraICState extra_state) { |
| 1032 DCHECK(!FLAG_vector_ics); | 1027 DCHECK(!FLAG_vector_ics); |
| 1033 return PropertyICCompiler::ComputeLoad(isolate, PREMONOMORPHIC, extra_state); | 1028 return PropertyICCompiler::ComputeLoad(isolate, PREMONOMORPHIC, extra_state); |
| 1034 } | 1029 } |
| 1035 | 1030 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1084 } else { | 1079 } else { |
| 1085 code = ComputeHandler(lookup); | 1080 code = ComputeHandler(lookup); |
| 1086 } | 1081 } |
| 1087 | 1082 |
| 1088 PatchCache(lookup->name(), code); | 1083 PatchCache(lookup->name(), code); |
| 1089 TRACE_IC("LoadIC", lookup->name()); | 1084 TRACE_IC("LoadIC", lookup->name()); |
| 1090 } | 1085 } |
| 1091 | 1086 |
| 1092 | 1087 |
| 1093 void IC::UpdateMegamorphicCache(HeapType* type, Name* name, Code* code) { | 1088 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()); | 1089 Map* map = *TypeToMap(type, isolate()); |
| 1097 isolate()->stub_cache()->Set(name, map, code); | 1090 isolate()->stub_cache()->Set(name, map, code); |
| 1098 } | 1091 } |
| 1099 | 1092 |
| 1100 | 1093 |
| 1101 Handle<Code> IC::ComputeHandler(LookupIterator* lookup, Handle<Object> value) { | 1094 Handle<Code> IC::ComputeHandler(LookupIterator* lookup, Handle<Object> value) { |
| 1102 bool receiver_is_holder = | 1095 bool receiver_is_holder = |
| 1103 lookup->GetReceiver().is_identical_to(lookup->GetHolder<JSObject>()); | 1096 lookup->GetReceiver().is_identical_to(lookup->GetHolder<JSObject>()); |
| 1104 CacheHolderFlag flag; | 1097 CacheHolderFlag flag; |
| 1105 Handle<Map> stub_holder_map = IC::GetHandlerCacheHolder( | 1098 Handle<Map> stub_holder_map = IC::GetHandlerCacheHolder( |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1363 } | 1356 } |
| 1364 | 1357 |
| 1365 DCHECK(state() != GENERIC); | 1358 DCHECK(state() != GENERIC); |
| 1366 | 1359 |
| 1367 // Determine the list of receiver maps that this call site has seen, | 1360 // Determine the list of receiver maps that this call site has seen, |
| 1368 // adding the map that was just encountered. | 1361 // adding the map that was just encountered. |
| 1369 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) { | 1362 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) { |
| 1370 // If the miss wasn't due to an unseen map, a polymorphic stub | 1363 // If the miss wasn't due to an unseen map, a polymorphic stub |
| 1371 // won't help, use the generic stub. | 1364 // won't help, use the generic stub. |
| 1372 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "same map added twice"); | 1365 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "same map added twice"); |
| 1373 return generic_stub(); | 1366 return megamorphic_stub(isolate()); |
| 1374 } | 1367 } |
| 1375 | 1368 |
| 1376 // If the maximum number of receiver maps has been exceeded, use the generic | 1369 // If the maximum number of receiver maps has been exceeded, use the generic |
| 1377 // version of the IC. | 1370 // version of the IC. |
| 1378 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { | 1371 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { |
| 1379 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "max polymorph exceeded"); | 1372 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "max polymorph exceeded"); |
| 1380 return generic_stub(); | 1373 return megamorphic_stub(isolate()); |
| 1381 } | 1374 } |
| 1382 | 1375 |
| 1383 if (FLAG_vector_ics) { | 1376 if (FLAG_vector_ics) { |
| 1384 CodeHandleList handlers(target_receiver_maps.length()); | 1377 CodeHandleList handlers(target_receiver_maps.length()); |
| 1385 ElementHandlerCompiler compiler(isolate()); | 1378 ElementHandlerCompiler compiler(isolate()); |
| 1386 compiler.CompileElementHandlers(&target_receiver_maps, &handlers); | 1379 compiler.CompileElementHandlers(&target_receiver_maps, &handlers); |
| 1387 TypeHandleList types(target_receiver_maps.length()); | 1380 TypeHandleList types(target_receiver_maps.length()); |
| 1388 for (int i = 0; i < target_receiver_maps.length(); i++) { | 1381 for (int i = 0; i < target_receiver_maps.length(); i++) { |
| 1389 types.Add(HeapType::Class(target_receiver_maps.at(i), isolate())); | 1382 types.Add(HeapType::Class(target_receiver_maps.at(i), isolate())); |
| 1390 } | 1383 } |
| 1391 ConfigureVectorState(Handle<Name>::null(), &types, &handlers); | 1384 ConfigureVectorState(Handle<Name>::null(), &types, &handlers); |
| 1392 return null_handle; | 1385 return null_handle; |
| 1393 } | 1386 } |
| 1394 | 1387 |
| 1395 return PropertyICCompiler::ComputeKeyedLoadPolymorphic(&target_receiver_maps); | 1388 return PropertyICCompiler::ComputeKeyedLoadPolymorphic(&target_receiver_maps); |
| 1396 } | 1389 } |
| 1397 | 1390 |
| 1398 | 1391 |
| 1399 MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object, | 1392 MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object, |
| 1400 Handle<Object> key) { | 1393 Handle<Object> key) { |
| 1401 if (MigrateDeprecated(object)) { | 1394 if (MigrateDeprecated(object)) { |
| 1402 Handle<Object> result; | 1395 Handle<Object> result; |
| 1403 ASSIGN_RETURN_ON_EXCEPTION( | 1396 ASSIGN_RETURN_ON_EXCEPTION( |
| 1404 isolate(), result, Runtime::GetObjectProperty(isolate(), object, key), | 1397 isolate(), result, Runtime::GetObjectProperty(isolate(), object, key), |
| 1405 Object); | 1398 Object); |
| 1406 return result; | 1399 return result; |
| 1407 } | 1400 } |
| 1408 | 1401 |
| 1409 Handle<Object> load_handle; | 1402 Handle<Object> load_handle; |
| 1410 Handle<Code> stub = generic_stub(); | 1403 Handle<Code> stub = megamorphic_stub(isolate()); |
| 1411 | 1404 |
| 1412 // Check for non-string values that can be converted into an | 1405 // Check for non-string values that can be converted into an |
| 1413 // internalized string directly or is representable as a smi. | 1406 // internalized string directly or is representable as a smi. |
| 1414 key = TryConvertKey(key, isolate()); | 1407 key = TryConvertKey(key, isolate()); |
| 1415 | 1408 |
| 1416 if (key->IsInternalizedString() || key->IsSymbol()) { | 1409 if (key->IsInternalizedString() || key->IsSymbol()) { |
| 1417 ASSIGN_RETURN_ON_EXCEPTION(isolate(), load_handle, | 1410 ASSIGN_RETURN_ON_EXCEPTION(isolate(), load_handle, |
| 1418 LoadIC::Load(object, Handle<Name>::cast(key)), | 1411 LoadIC::Load(object, Handle<Name>::cast(key)), |
| 1419 Object); | 1412 Object); |
| 1420 } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) { | 1413 } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) { |
| 1421 if (object->IsJSObject() || (object->IsString() && key->IsNumber())) { | 1414 if (object->IsJSObject() || (object->IsString() && key->IsNumber())) { |
| 1422 Handle<HeapObject> receiver = Handle<HeapObject>::cast(object); | 1415 Handle<HeapObject> receiver = Handle<HeapObject>::cast(object); |
| 1423 if (object->IsString() || !Object::ToSmi(isolate(), key).is_null()) { | 1416 if (object->IsString() || !Object::ToSmi(isolate(), key).is_null()) { |
| 1424 stub = LoadElementStub(receiver); | 1417 stub = LoadElementStub(receiver); |
| 1425 } | 1418 } |
| 1426 } | 1419 } |
| 1427 } | 1420 } |
| 1428 | 1421 |
| 1429 if (!UseVector()) { | 1422 if (!UseVector()) { |
| 1430 if (!is_target_set()) { | 1423 if (!is_target_set()) { |
| 1431 Code* generic = *generic_stub(); | 1424 Code* generic = *megamorphic_stub(isolate()); |
| 1432 if (*stub == generic) { | 1425 if (*stub == generic) { |
| 1433 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); | 1426 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); |
| 1434 } | 1427 } |
| 1435 | 1428 |
| 1436 set_target(*stub); | 1429 set_target(*stub); |
| 1437 TRACE_IC("LoadIC", key); | 1430 TRACE_IC("LoadIC", key); |
| 1438 } | 1431 } |
| 1439 } else { | 1432 } else { |
| 1440 if (!is_vector_set() || stub.is_null()) { | 1433 if (!is_vector_set() || stub.is_null()) { |
| 1441 Code* generic = *generic_stub(); | 1434 Code* generic = *megamorphic_stub(isolate()); |
| 1442 if (!stub.is_null() && *stub == generic) { | 1435 if (!stub.is_null() && *stub == generic) { |
| 1443 ConfigureVectorState(GENERIC); | 1436 ConfigureVectorState(GENERIC); |
| 1444 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); | 1437 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); |
| 1445 } | 1438 } |
| 1446 | 1439 |
| 1447 TRACE_IC("LoadIC", key); | 1440 TRACE_IC("LoadIC", key); |
| 1448 } | 1441 } |
| 1449 } | 1442 } |
| 1450 | 1443 |
| 1451 if (!load_handle.is_null()) return load_handle; | 1444 if (!load_handle.is_null()) return load_handle; |
| (...skipping 1555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3007 static const Address IC_utilities[] = { | 3000 static const Address IC_utilities[] = { |
| 3008 #define ADDR(name) FUNCTION_ADDR(name), | 3001 #define ADDR(name) FUNCTION_ADDR(name), |
| 3009 IC_UTIL_LIST(ADDR) NULL | 3002 IC_UTIL_LIST(ADDR) NULL |
| 3010 #undef ADDR | 3003 #undef ADDR |
| 3011 }; | 3004 }; |
| 3012 | 3005 |
| 3013 | 3006 |
| 3014 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } | 3007 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } |
| 3015 } | 3008 } |
| 3016 } // namespace v8::internal | 3009 } // namespace v8::internal |
| OLD | NEW |