Chromium Code Reviews| 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 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 114 | 114 |
| 115 #else | 115 #else |
| 116 #define TRACE_GENERIC_IC(isolate, type, reason) | 116 #define TRACE_GENERIC_IC(isolate, type, reason) |
| 117 #endif // DEBUG | 117 #endif // DEBUG |
| 118 | 118 |
| 119 #define TRACE_IC(type, name) \ | 119 #define TRACE_IC(type, name) \ |
| 120 ASSERT((TraceIC(type, name), true)) | 120 ASSERT((TraceIC(type, name), true)) |
| 121 | 121 |
| 122 IC::IC(FrameDepth depth, Isolate* isolate) | 122 IC::IC(FrameDepth depth, Isolate* isolate) |
| 123 : isolate_(isolate), | 123 : isolate_(isolate), |
| 124 target_set_(false) { | 124 target_set_(false), |
| 125 target_maps_set_(false) { | |
| 125 // To improve the performance of the (much used) IC code, we unfold a few | 126 // To improve the performance of the (much used) IC code, we unfold a few |
| 126 // levels of the stack frame iteration code. This yields a ~35% speedup when | 127 // levels of the stack frame iteration code. This yields a ~35% speedup when |
| 127 // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag. | 128 // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag. |
| 128 const Address entry = | 129 const Address entry = |
| 129 Isolate::c_entry_fp(isolate->thread_local_top()); | 130 Isolate::c_entry_fp(isolate->thread_local_top()); |
| 130 Address constant_pool = NULL; | 131 Address constant_pool = NULL; |
| 131 if (FLAG_enable_ool_constant_pool) { | 132 if (FLAG_enable_ool_constant_pool) { |
| 132 constant_pool = Memory::Address_at( | 133 constant_pool = Memory::Address_at( |
| 133 entry + ExitFrameConstants::kConstantPoolOffset); | 134 entry + ExitFrameConstants::kConstantPoolOffset); |
| 134 } | 135 } |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 291 | 292 |
| 292 // The stub is not in the cache. We've ruled out all other kinds of failure | 293 // The stub is not in the cache. We've ruled out all other kinds of failure |
| 293 // except for proptotype chain changes, a deprecated map, a map that's | 294 // except for proptotype chain changes, a deprecated map, a map that's |
| 294 // different from the one that the stub expects, elements kind changes, or a | 295 // different from the one that the stub expects, elements kind changes, or a |
| 295 // constant global property that will become mutable. Threat all those | 296 // constant global property that will become mutable. Threat all those |
| 296 // situations as prototype failures (stay monomorphic if possible). | 297 // situations as prototype failures (stay monomorphic if possible). |
| 297 | 298 |
| 298 // If the IC is shared between multiple receivers (slow dictionary mode), then | 299 // If the IC is shared between multiple receivers (slow dictionary mode), then |
| 299 // the map cannot be deprecated and the stub invalidated. | 300 // the map cannot be deprecated and the stub invalidated. |
| 300 if (cache_holder == OWN_MAP) { | 301 if (cache_holder == OWN_MAP) { |
| 301 Map* old_map = target()->FindFirstMap(); | 302 Map* old_map = FirstTargetMap(); |
| 302 if (old_map == *map) return true; | 303 if (old_map == *map) return true; |
| 303 if (old_map != NULL) { | 304 if (old_map != NULL) { |
| 304 if (old_map->is_deprecated()) return true; | 305 if (old_map->is_deprecated()) return true; |
| 305 if (IsMoreGeneralElementsKindTransition(old_map->elements_kind(), | 306 if (IsMoreGeneralElementsKindTransition(old_map->elements_kind(), |
| 306 map->elements_kind())) { | 307 map->elements_kind())) { |
| 307 return true; | 308 return true; |
| 308 } | 309 } |
| 309 } | 310 } |
| 310 } | 311 } |
| 311 | 312 |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 617 } | 618 } |
| 618 | 619 |
| 619 | 620 |
| 620 bool IC::UpdatePolymorphicIC(Handle<HeapType> type, | 621 bool IC::UpdatePolymorphicIC(Handle<HeapType> type, |
| 621 Handle<String> name, | 622 Handle<String> name, |
| 622 Handle<Code> code) { | 623 Handle<Code> code) { |
| 623 if (!code->is_handler()) return false; | 624 if (!code->is_handler()) return false; |
| 624 TypeHandleList types; | 625 TypeHandleList types; |
| 625 CodeHandleList handlers; | 626 CodeHandleList handlers; |
| 626 | 627 |
| 627 target()->FindAllTypes(&types); | 628 TargetTypes(&types); |
| 628 int number_of_types = types.length(); | 629 int number_of_types = types.length(); |
| 629 int deprecated_types = 0; | 630 int deprecated_types = 0; |
| 630 int handler_to_overwrite = -1; | 631 int handler_to_overwrite = -1; |
| 631 | 632 |
| 632 for (int i = 0; i < number_of_types; i++) { | 633 for (int i = 0; i < number_of_types; i++) { |
| 633 Handle<HeapType> current_type = types.at(i); | 634 Handle<HeapType> current_type = types.at(i); |
| 634 if (current_type->IsClass() && current_type->AsClass()->is_deprecated()) { | 635 if (current_type->IsClass() && current_type->AsClass()->is_deprecated()) { |
| 635 // Filter out deprecated maps to ensure their instances get migrated. | 636 // Filter out deprecated maps to ensure their instances get migrated. |
| 636 ++deprecated_types; | 637 ++deprecated_types; |
| 637 } else if (type->IsCurrently(current_type)) { | 638 } else if (type->IsCurrently(current_type)) { |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 720 if (!handler->is_handler()) return set_target(*handler); | 721 if (!handler->is_handler()) return set_target(*handler); |
| 721 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC( | 722 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC( |
| 722 kind(), name, type, handler, extra_ic_state()); | 723 kind(), name, type, handler, extra_ic_state()); |
| 723 set_target(*ic); | 724 set_target(*ic); |
| 724 } | 725 } |
| 725 | 726 |
| 726 | 727 |
| 727 void IC::CopyICToMegamorphicCache(Handle<String> name) { | 728 void IC::CopyICToMegamorphicCache(Handle<String> name) { |
| 728 TypeHandleList types; | 729 TypeHandleList types; |
| 729 CodeHandleList handlers; | 730 CodeHandleList handlers; |
| 730 target()->FindAllTypes(&types); | 731 TargetTypes(&types); |
| 731 if (!target()->FindHandlers(&handlers, types.length())) return; | 732 if (!target()->FindHandlers(&handlers, types.length())) return; |
| 732 for (int i = 0; i < types.length(); i++) { | 733 for (int i = 0; i < types.length(); i++) { |
| 733 UpdateMegamorphicCache(*types.at(i), *name, *handlers.at(i)); | 734 UpdateMegamorphicCache(*types.at(i), *name, *handlers.at(i)); |
| 734 } | 735 } |
| 735 } | 736 } |
| 736 | 737 |
| 737 | 738 |
| 738 bool IC::IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map) { | 739 bool IC::IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map) { |
| 739 if (source_map == NULL) return true; | 740 if (source_map == NULL) return true; |
| 740 if (target_map == NULL) return false; | 741 if (target_map == NULL) return false; |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1021 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS | 1022 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS |
| 1022 // via megamorphic stubs, since they don't have a map in their relocation info | 1023 // via megamorphic stubs, since they don't have a map in their relocation info |
| 1023 // and so the stubs can't be harvested for the object needed for a map check. | 1024 // and so the stubs can't be harvested for the object needed for a map check. |
| 1024 if (target()->type() != Code::NORMAL) { | 1025 if (target()->type() != Code::NORMAL) { |
| 1025 TRACE_GENERIC_IC(isolate(), "KeyedIC", "non-NORMAL target type"); | 1026 TRACE_GENERIC_IC(isolate(), "KeyedIC", "non-NORMAL target type"); |
| 1026 return generic_stub(); | 1027 return generic_stub(); |
| 1027 } | 1028 } |
| 1028 | 1029 |
| 1029 Handle<Map> receiver_map(receiver->map(), isolate()); | 1030 Handle<Map> receiver_map(receiver->map(), isolate()); |
| 1030 MapHandleList target_receiver_maps; | 1031 MapHandleList target_receiver_maps; |
| 1031 if (state() == UNINITIALIZED || state() == PREMONOMORPHIC) { | 1032 if (target().is_identical_to(string_stub())) { |
| 1032 // Optimistically assume that ICs that haven't reached the MONOMORPHIC state | 1033 target_receiver_maps.Add(isolate()->factory()->string_map()); |
| 1033 // yet will do so and stay there. | 1034 } else { |
| 1035 TargetMaps(&target_receiver_maps); | |
| 1036 } | |
| 1037 if (target_receiver_maps.length() == 0) { | |
| 1034 return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map); | 1038 return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map); |
| 1035 } | 1039 } |
| 1036 | 1040 |
| 1037 if (target().is_identical_to(string_stub())) { | |
| 1038 target_receiver_maps.Add(isolate()->factory()->string_map()); | |
| 1039 } else { | |
| 1040 target()->FindAllMaps(&target_receiver_maps); | |
| 1041 if (target_receiver_maps.length() == 0) { | |
| 1042 return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map); | |
| 1043 } | |
| 1044 } | |
| 1045 | |
| 1046 // The first time a receiver is seen that is a transitioned version of the | 1041 // The first time a receiver is seen that is a transitioned version of the |
| 1047 // previous monomorphic receiver type, assume the new ElementsKind is the | 1042 // previous monomorphic receiver type, assume the new ElementsKind is the |
| 1048 // monomorphic type. This benefits global arrays that only transition | 1043 // monomorphic type. This benefits global arrays that only transition |
| 1049 // once, and all call sites accessing them are faster if they remain | 1044 // once, and all call sites accessing them are faster if they remain |
| 1050 // monomorphic. If this optimistic assumption is not true, the IC will | 1045 // monomorphic. If this optimistic assumption is not true, the IC will |
| 1051 // miss again and it will become polymorphic and support both the | 1046 // miss again and it will become polymorphic and support both the |
| 1052 // untransitioned and transitioned maps. | 1047 // untransitioned and transitioned maps. |
| 1053 if (state() == MONOMORPHIC && | 1048 if (state() == MONOMORPHIC && |
| 1054 IsMoreGeneralElementsKindTransition( | 1049 IsMoreGeneralElementsKindTransition( |
| 1055 target_receiver_maps.at(0)->elements_kind(), | 1050 target_receiver_maps.at(0)->elements_kind(), |
| (...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1419 KeyedAccessStoreMode store_mode) { | 1414 KeyedAccessStoreMode store_mode) { |
| 1420 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS | 1415 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS |
| 1421 // via megamorphic stubs, since they don't have a map in their relocation info | 1416 // via megamorphic stubs, since they don't have a map in their relocation info |
| 1422 // and so the stubs can't be harvested for the object needed for a map check. | 1417 // and so the stubs can't be harvested for the object needed for a map check. |
| 1423 if (target()->type() != Code::NORMAL) { | 1418 if (target()->type() != Code::NORMAL) { |
| 1424 TRACE_GENERIC_IC(isolate(), "KeyedIC", "non-NORMAL target type"); | 1419 TRACE_GENERIC_IC(isolate(), "KeyedIC", "non-NORMAL target type"); |
| 1425 return generic_stub(); | 1420 return generic_stub(); |
| 1426 } | 1421 } |
| 1427 | 1422 |
| 1428 Handle<Map> receiver_map(receiver->map(), isolate()); | 1423 Handle<Map> receiver_map(receiver->map(), isolate()); |
| 1429 if (state() == UNINITIALIZED || state() == PREMONOMORPHIC) { | 1424 MapHandleList target_receiver_maps; |
| 1430 // Optimistically assume that ICs that haven't reached the MONOMORPHIC state | 1425 TargetMaps(&target_receiver_maps); |
| 1431 // yet will do so and stay there. | 1426 if (target_receiver_maps.length() == 0) { |
|
Toon Verwaest
2014/04/01 15:22:05
length() == 0 isn't the same as UNINITIALIZED || P
ulan
2014/04/01 16:14:07
The comment that I removed seems to be out-dated:
| |
| 1432 Handle<Map> monomorphic_map = ComputeTransitionedMap(receiver, store_mode); | 1427 Handle<Map> monomorphic_map = ComputeTransitionedMap(receiver, store_mode); |
| 1433 store_mode = GetNonTransitioningStoreMode(store_mode); | 1428 store_mode = GetNonTransitioningStoreMode(store_mode); |
| 1434 return isolate()->stub_cache()->ComputeKeyedStoreElement( | 1429 return isolate()->stub_cache()->ComputeKeyedStoreElement( |
| 1435 monomorphic_map, strict_mode(), store_mode); | 1430 monomorphic_map, strict_mode(), store_mode); |
| 1436 } | 1431 } |
| 1437 | 1432 |
| 1438 MapHandleList target_receiver_maps; | |
| 1439 target()->FindAllMaps(&target_receiver_maps); | |
| 1440 if (target_receiver_maps.length() == 0) { | |
| 1441 // In the case that there is a non-map-specific IC is installed (e.g. keyed | |
| 1442 // stores into properties in dictionary mode), then there will be not | |
| 1443 // receiver maps in the target. | |
| 1444 return generic_stub(); | |
| 1445 } | |
| 1446 | |
| 1447 // There are several special cases where an IC that is MONOMORPHIC can still | 1433 // There are several special cases where an IC that is MONOMORPHIC can still |
| 1448 // transition to a different GetNonTransitioningStoreMode IC that handles a | 1434 // transition to a different GetNonTransitioningStoreMode IC that handles a |
| 1449 // superset of the original IC. Handle those here if the receiver map hasn't | 1435 // superset of the original IC. Handle those here if the receiver map hasn't |
| 1450 // changed or it has transitioned to a more general kind. | 1436 // changed or it has transitioned to a more general kind. |
| 1451 KeyedAccessStoreMode old_store_mode = | 1437 KeyedAccessStoreMode old_store_mode = |
| 1452 KeyedStoreIC::GetKeyedAccessStoreMode(target()->extra_ic_state()); | 1438 KeyedStoreIC::GetKeyedAccessStoreMode(target()->extra_ic_state()); |
| 1453 Handle<Map> previous_receiver_map = target_receiver_maps.at(0); | 1439 Handle<Map> previous_receiver_map = target_receiver_maps.at(0); |
| 1454 if (state() == MONOMORPHIC) { | 1440 if (state() == MONOMORPHIC) { |
| 1455 Handle<Map> transitioned_receiver_map = receiver_map; | 1441 Handle<Map> transitioned_receiver_map = receiver_map; |
| 1456 if (IsTransitionStoreMode(store_mode)) { | 1442 if (IsTransitionStoreMode(store_mode)) { |
| (...skipping 1281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2738 // types must be supported as a result of the miss. | 2724 // types must be supported as a result of the miss. |
| 2739 bool already_monomorphic = stub.IsMonomorphic(); | 2725 bool already_monomorphic = stub.IsMonomorphic(); |
| 2740 | 2726 |
| 2741 stub.UpdateStatus(object); | 2727 stub.UpdateStatus(object); |
| 2742 | 2728 |
| 2743 NilValue nil = stub.GetNilValue(); | 2729 NilValue nil = stub.GetNilValue(); |
| 2744 | 2730 |
| 2745 // Find or create the specialized stub to support the new set of types. | 2731 // Find or create the specialized stub to support the new set of types. |
| 2746 Handle<Code> code; | 2732 Handle<Code> code; |
| 2747 if (stub.IsMonomorphic()) { | 2733 if (stub.IsMonomorphic()) { |
| 2748 Handle<Map> monomorphic_map(already_monomorphic | 2734 Handle<Map> monomorphic_map(already_monomorphic && FirstTargetMap() != NULL |
| 2749 ? target()->FindFirstMap() | 2735 ? FirstTargetMap() |
| 2750 : HeapObject::cast(*object)->map()); | 2736 : HeapObject::cast(*object)->map()); |
| 2751 code = isolate()->stub_cache()->ComputeCompareNil(monomorphic_map, stub); | 2737 code = isolate()->stub_cache()->ComputeCompareNil(monomorphic_map, stub); |
| 2752 } else { | 2738 } else { |
| 2753 code = stub.GetCode(isolate()); | 2739 code = stub.GetCode(isolate()); |
| 2754 } | 2740 } |
| 2755 set_target(*code); | 2741 set_target(*code); |
| 2756 return DoCompareNilSlow(nil, object); | 2742 return DoCompareNilSlow(nil, object); |
| 2757 } | 2743 } |
| 2758 | 2744 |
| 2759 | 2745 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2838 #undef ADDR | 2824 #undef ADDR |
| 2839 }; | 2825 }; |
| 2840 | 2826 |
| 2841 | 2827 |
| 2842 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2828 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 2843 return IC_utilities[id]; | 2829 return IC_utilities[id]; |
| 2844 } | 2830 } |
| 2845 | 2831 |
| 2846 | 2832 |
| 2847 } } // namespace v8::internal | 2833 } } // namespace v8::internal |
| OLD | NEW |