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 |