Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(31)

Side by Side Diff: src/ic.cc

Issue 220923003: Lazily initialize the target map list in IC. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ic.h ('k') | src/objects.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698