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

Side by Side Diff: src/ic.cc

Issue 451643002: Clean up IC tracing for CallICs. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Code comments. Created 6 years, 4 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/ic-inl.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 // 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/codegen.h" 10 #include "src/codegen.h"
(...skipping 15 matching lines...) Expand all
26 case PROTOTYPE_FAILURE: 26 case PROTOTYPE_FAILURE:
27 return '^'; 27 return '^';
28 case POLYMORPHIC: return 'P'; 28 case POLYMORPHIC: return 'P';
29 case MEGAMORPHIC: return 'N'; 29 case MEGAMORPHIC: return 'N';
30 case GENERIC: return 'G'; 30 case GENERIC: return 'G';
31 31
32 // We never see the debugger states here, because the state is 32 // We never see the debugger states here, because the state is
33 // computed from the original code - not the patched code. Let 33 // computed from the original code - not the patched code. Let
34 // these cases fall through to the unreachable code below. 34 // these cases fall through to the unreachable code below.
35 case DEBUG_STUB: break; 35 case DEBUG_STUB: break;
36 // Type-vector-based ICs resolve state to one of the above.
37 case DEFAULT:
38 break;
36 } 39 }
37 UNREACHABLE(); 40 UNREACHABLE();
38 return 0; 41 return 0;
39 } 42 }
40 43
41 44
42 const char* GetTransitionMarkModifier(KeyedAccessStoreMode mode) { 45 const char* GetTransitionMarkModifier(KeyedAccessStoreMode mode) {
43 if (mode == STORE_NO_TRANSITION_HANDLE_COW) return ".COW"; 46 if (mode == STORE_NO_TRANSITION_HANDLE_COW) return ".COW";
44 if (mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { 47 if (mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
45 return ".IGNORE_OOB"; 48 return ".IGNORE_OOB";
(...skipping 13 matching lines...) Expand all
59 PrintF(" (%s)]\n", reason); \ 62 PrintF(" (%s)]\n", reason); \
60 } \ 63 } \
61 } while (false) 64 } while (false)
62 65
63 #else 66 #else
64 67
65 #define TRACE_GENERIC_IC(isolate, type, reason) 68 #define TRACE_GENERIC_IC(isolate, type, reason)
66 69
67 #endif // DEBUG 70 #endif // DEBUG
68 71
72
69 void IC::TraceIC(const char* type, Handle<Object> name) { 73 void IC::TraceIC(const char* type, Handle<Object> name) {
70 if (FLAG_trace_ic) { 74 if (FLAG_trace_ic) {
71 Code* new_target = raw_target(); 75 Code* new_target = raw_target();
72 State new_state = new_target->ic_state(); 76 State new_state = new_target->ic_state();
77 TraceIC(type, name, state(), new_state);
78 }
79 }
80
81
82 void IC::TraceIC(const char* type, Handle<Object> name, State old_state,
83 State new_state) {
84 if (FLAG_trace_ic) {
85 Code* new_target = raw_target();
73 PrintF("[%s%s in ", new_target->is_keyed_stub() ? "Keyed" : "", type); 86 PrintF("[%s%s in ", new_target->is_keyed_stub() ? "Keyed" : "", type);
74 87
75 // TODO(jkummerow): Add support for "apply". The logic is roughly: 88 // TODO(jkummerow): Add support for "apply". The logic is roughly:
76 // marker = [fp_ + kMarkerOffset]; 89 // marker = [fp_ + kMarkerOffset];
77 // if marker is smi and marker.value == INTERNAL and 90 // if marker is smi and marker.value == INTERNAL and
78 // the frame's code == builtin(Builtins::kFunctionApply): 91 // the frame's code == builtin(Builtins::kFunctionApply):
79 // then print "apply from" and advance one frame 92 // then print "apply from" and advance one frame
80 93
81 Object* maybe_function = 94 Object* maybe_function =
82 Memory::Object_at(fp_ + JavaScriptFrameConstants::kFunctionOffset); 95 Memory::Object_at(fp_ + JavaScriptFrameConstants::kFunctionOffset);
83 if (maybe_function->IsJSFunction()) { 96 if (maybe_function->IsJSFunction()) {
84 JSFunction* function = JSFunction::cast(maybe_function); 97 JSFunction* function = JSFunction::cast(maybe_function);
85 JavaScriptFrame::PrintFunctionAndOffset(function, function->code(), pc(), 98 JavaScriptFrame::PrintFunctionAndOffset(function, function->code(), pc(),
86 stdout, true); 99 stdout, true);
87 } 100 }
88 101
89 ExtraICState extra_state = new_target->extra_ic_state(); 102 ExtraICState extra_state = new_target->extra_ic_state();
90 const char* modifier = ""; 103 const char* modifier = "";
91 if (new_target->kind() == Code::KEYED_STORE_IC) { 104 if (new_target->kind() == Code::KEYED_STORE_IC) {
92 modifier = GetTransitionMarkModifier( 105 modifier = GetTransitionMarkModifier(
93 KeyedStoreIC::GetKeyedAccessStoreMode(extra_state)); 106 KeyedStoreIC::GetKeyedAccessStoreMode(extra_state));
94 } 107 }
95 PrintF(" (%c->%c%s)", 108 PrintF(" (%c->%c%s)", TransitionMarkFromState(old_state),
96 TransitionMarkFromState(state()), 109 TransitionMarkFromState(new_state), modifier);
97 TransitionMarkFromState(new_state),
98 modifier);
99 #ifdef OBJECT_PRINT 110 #ifdef OBJECT_PRINT
100 OFStream os(stdout); 111 OFStream os(stdout);
101 name->Print(os); 112 name->Print(os);
102 #else 113 #else
103 name->ShortPrint(stdout); 114 name->ShortPrint(stdout);
104 #endif 115 #endif
105 PrintF("]\n"); 116 PrintF("]\n");
106 } 117 }
107 } 118 }
108 119
109 #define TRACE_IC(type, name) TraceIC(type, name) 120 #define TRACE_IC(type, name) TraceIC(type, name)
110 121 #define TRACE_VECTOR_IC(type, name, old_state, new_state) \
122 TraceIC(type, name, old_state, new_state)
111 123
112 IC::IC(FrameDepth depth, Isolate* isolate) 124 IC::IC(FrameDepth depth, Isolate* isolate)
113 : isolate_(isolate), 125 : isolate_(isolate),
114 target_set_(false), 126 target_set_(false),
115 target_maps_set_(false) { 127 target_maps_set_(false) {
116 // To improve the performance of the (much used) IC code, we unfold a few 128 // To improve the performance of the (much used) IC code, we unfold a few
117 // levels of the stack frame iteration code. This yields a ~35% speedup when 129 // levels of the stack frame iteration code. This yields a ~35% speedup when
118 // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag. 130 // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag.
119 const Address entry = 131 const Address entry =
120 Isolate::c_entry_fp(isolate->thread_local_top()); 132 Isolate::c_entry_fp(isolate->thread_local_top());
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 case MEGAMORPHIC: 370 case MEGAMORPHIC:
359 case GENERIC: 371 case GENERIC:
360 if (new_state == MEGAMORPHIC || new_state == GENERIC) break; 372 if (new_state == MEGAMORPHIC || new_state == GENERIC) break;
361 *generic_delta = -1; 373 *generic_delta = -1;
362 if (new_state == MONOMORPHIC || new_state == POLYMORPHIC) { 374 if (new_state == MONOMORPHIC || new_state == POLYMORPHIC) {
363 *polymorphic_delta = 1; 375 *polymorphic_delta = 1;
364 } 376 }
365 break; 377 break;
366 case PROTOTYPE_FAILURE: 378 case PROTOTYPE_FAILURE:
367 case DEBUG_STUB: 379 case DEBUG_STUB:
380 case DEFAULT:
368 UNREACHABLE(); 381 UNREACHABLE();
369 } 382 }
370 } 383 }
371 384
372 385
373 void IC::OnTypeFeedbackChanged(Isolate* isolate, Address address, 386 void IC::OnTypeFeedbackChanged(Isolate* isolate, Address address,
374 State old_state, State new_state, 387 State old_state, State new_state,
375 bool target_remains_ic_stub) { 388 bool target_remains_ic_stub) {
376 Code* host = isolate-> 389 Code* host = isolate->
377 inner_pointer_to_code_cache()->GetCacheEntry(address)->code; 390 inner_pointer_to_code_cache()->GetCacheEntry(address)->code;
(...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after
800 if (UpdatePolymorphicIC(name, code)) break; 813 if (UpdatePolymorphicIC(name, code)) break;
801 CopyICToMegamorphicCache(name); 814 CopyICToMegamorphicCache(name);
802 } 815 }
803 set_target(*megamorphic_stub()); 816 set_target(*megamorphic_stub());
804 // Fall through. 817 // Fall through.
805 case MEGAMORPHIC: 818 case MEGAMORPHIC:
806 UpdateMegamorphicCache(*receiver_type(), *name, *code); 819 UpdateMegamorphicCache(*receiver_type(), *name, *code);
807 break; 820 break;
808 case DEBUG_STUB: 821 case DEBUG_STUB:
809 break; 822 break;
823 case DEFAULT:
810 case GENERIC: 824 case GENERIC:
811 UNREACHABLE(); 825 UNREACHABLE();
812 break; 826 break;
813 } 827 }
814 } 828 }
815 829
816 830
817 Handle<Code> LoadIC::initialize_stub(Isolate* isolate, 831 Handle<Code> LoadIC::initialize_stub(Isolate* isolate,
818 ExtraICState extra_state) { 832 ExtraICState extra_state) {
819 return PropertyICCompiler::ComputeLoad(isolate, UNINITIALIZED, extra_state); 833 return PropertyICCompiler::ComputeLoad(isolate, UNINITIALIZED, extra_state);
(...skipping 1123 matching lines...) Expand 10 before | Expand all | Expand 10 after
1943 Handle<FixedArray> vector, 1957 Handle<FixedArray> vector,
1944 Handle<Smi> slot, 1958 Handle<Smi> slot,
1945 const State& state) { 1959 const State& state) {
1946 DCHECK(FLAG_use_ic && function->IsJSFunction()); 1960 DCHECK(FLAG_use_ic && function->IsJSFunction());
1947 1961
1948 // Are we the array function? 1962 // Are we the array function?
1949 Handle<JSFunction> array_function = Handle<JSFunction>( 1963 Handle<JSFunction> array_function = Handle<JSFunction>(
1950 isolate()->native_context()->array_function()); 1964 isolate()->native_context()->array_function());
1951 if (array_function.is_identical_to(Handle<JSFunction>::cast(function))) { 1965 if (array_function.is_identical_to(Handle<JSFunction>::cast(function))) {
1952 // Alter the slot. 1966 // Alter the slot.
1967 IC::State old_state = FeedbackToState(vector, slot);
1953 Object* feedback = vector->get(slot->value()); 1968 Object* feedback = vector->get(slot->value());
1954 if (!feedback->IsAllocationSite()) { 1969 if (!feedback->IsAllocationSite()) {
1955 Handle<AllocationSite> new_site = 1970 Handle<AllocationSite> new_site =
1956 isolate()->factory()->NewAllocationSite(); 1971 isolate()->factory()->NewAllocationSite();
1957 vector->set(slot->value(), *new_site); 1972 vector->set(slot->value(), *new_site);
1958 } 1973 }
1959 1974
1960 CallIC_ArrayStub stub(isolate(), state); 1975 CallIC_ArrayStub stub(isolate(), state);
1961 set_target(*stub.GetCode()); 1976 set_target(*stub.GetCode());
1962 Handle<String> name; 1977 Handle<String> name;
1963 if (array_function->shared()->name()->IsString()) { 1978 if (array_function->shared()->name()->IsString()) {
1964 name = Handle<String>(String::cast(array_function->shared()->name()), 1979 name = Handle<String>(String::cast(array_function->shared()->name()),
1965 isolate()); 1980 isolate());
1966 } 1981 }
1967 1982
1968 TRACE_IC("CallIC (Array call)", name); 1983 IC::State new_state = FeedbackToState(vector, slot);
1969 Object* new_feedback = vector->get(slot->value()); 1984 OnTypeFeedbackChanged(isolate(), address(), old_state, new_state, true);
1970 UpdateTypeFeedbackInfo(feedback, new_feedback); 1985 TRACE_VECTOR_IC("CallIC (custom handler)", name, old_state, new_state);
1971 return true; 1986 return true;
1972 } 1987 }
1973 return false; 1988 return false;
1974 } 1989 }
1975 1990
1976 1991
1977 void CallIC::PatchMegamorphic(Handle<FixedArray> vector, 1992 void CallIC::PatchMegamorphic(Handle<Object> function,
1978 Handle<Smi> slot) { 1993 Handle<FixedArray> vector, Handle<Smi> slot) {
1979 State state(target()->extra_ic_state()); 1994 State state(target()->extra_ic_state());
1995 IC::State old_state = FeedbackToState(vector, slot);
1980 1996
1981 // We are going generic. 1997 // We are going generic.
1982 vector->set(slot->value(), 1998 vector->set(slot->value(),
1983 *TypeFeedbackInfo::MegamorphicSentinel(isolate()), 1999 *TypeFeedbackInfo::MegamorphicSentinel(isolate()),
1984 SKIP_WRITE_BARRIER); 2000 SKIP_WRITE_BARRIER);
1985 2001
1986 CallICStub stub(isolate(), state); 2002 CallICStub stub(isolate(), state);
1987 Handle<Code> code = stub.GetCode(); 2003 Handle<Code> code = stub.GetCode();
1988 set_target(*code); 2004 set_target(*code);
1989 2005
1990 TRACE_GENERIC_IC(isolate(), "CallIC", "megamorphic"); 2006 Handle<Object> name = isolate()->factory()->empty_string();
2007 if (function->IsJSFunction()) {
2008 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function);
2009 name = handle(js_function->shared()->name(), isolate());
2010 }
2011
2012 IC::State new_state = FeedbackToState(vector, slot);
2013 OnTypeFeedbackChanged(isolate(), address(), old_state, new_state, true);
2014 TRACE_VECTOR_IC("CallIC", name, old_state, new_state);
1991 } 2015 }
1992 2016
1993 2017
1994 void CallIC::UpdateTypeFeedbackInfo(Object* old_feedback,
1995 Object* new_feedback) {
1996 IC::State old_state = FeedbackObjectToState(old_feedback);
1997 IC::State new_state = FeedbackObjectToState(new_feedback);
1998 OnTypeFeedbackChanged(isolate(), address(), old_state, new_state, true);
1999 }
2000
2001
2002 void CallIC::HandleMiss(Handle<Object> receiver, 2018 void CallIC::HandleMiss(Handle<Object> receiver,
2003 Handle<Object> function, 2019 Handle<Object> function,
2004 Handle<FixedArray> vector, 2020 Handle<FixedArray> vector,
2005 Handle<Smi> slot) { 2021 Handle<Smi> slot) {
2006 State state(target()->extra_ic_state()); 2022 State state(target()->extra_ic_state());
2023 IC::State old_state = FeedbackToState(vector, slot);
2024 Handle<Object> name = isolate()->factory()->empty_string();
2007 Object* feedback = vector->get(slot->value()); 2025 Object* feedback = vector->get(slot->value());
2008 2026
2009 // Hand-coded MISS handling is easier if CallIC slots don't contain smis. 2027 // Hand-coded MISS handling is easier if CallIC slots don't contain smis.
2010 DCHECK(!feedback->IsSmi()); 2028 DCHECK(!feedback->IsSmi());
2011 2029
2012 if (feedback->IsJSFunction() || !function->IsJSFunction()) { 2030 if (feedback->IsJSFunction() || !function->IsJSFunction()) {
2013 // We are going generic. 2031 // We are going generic.
2014 vector->set(slot->value(), 2032 vector->set(slot->value(),
2015 *TypeFeedbackInfo::MegamorphicSentinel(isolate()), 2033 *TypeFeedbackInfo::MegamorphicSentinel(isolate()),
2016 SKIP_WRITE_BARRIER); 2034 SKIP_WRITE_BARRIER);
2017
2018 TRACE_GENERIC_IC(isolate(), "CallIC", "megamorphic");
2019 } else { 2035 } else {
2020 // The feedback is either uninitialized or an allocation site. 2036 // The feedback is either uninitialized or an allocation site.
2021 // It might be an allocation site because if we re-compile the full code 2037 // It might be an allocation site because if we re-compile the full code
2022 // to add deoptimization support, we call with the default call-ic, and 2038 // to add deoptimization support, we call with the default call-ic, and
2023 // merely need to patch the target to match the feedback. 2039 // merely need to patch the target to match the feedback.
2024 // TODO(mvstanton): the better approach is to dispense with patching 2040 // TODO(mvstanton): the better approach is to dispense with patching
2025 // altogether, which is in progress. 2041 // altogether, which is in progress.
2026 DCHECK(feedback == *TypeFeedbackInfo::UninitializedSentinel(isolate()) || 2042 DCHECK(feedback == *TypeFeedbackInfo::UninitializedSentinel(isolate()) ||
2027 feedback->IsAllocationSite()); 2043 feedback->IsAllocationSite());
2028 2044
2029 // Do we want to install a custom handler? 2045 // Do we want to install a custom handler?
2030 if (FLAG_use_ic && 2046 if (FLAG_use_ic &&
2031 DoCustomHandler(receiver, function, vector, slot, state)) { 2047 DoCustomHandler(receiver, function, vector, slot, state)) {
2032 return; 2048 return;
2033 } 2049 }
2034 2050
2035 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function);
2036 Handle<Object> name(js_function->shared()->name(), isolate());
2037 TRACE_IC("CallIC", name);
2038 vector->set(slot->value(), *function); 2051 vector->set(slot->value(), *function);
2039 } 2052 }
2040 2053
2041 Object* new_feedback = vector->get(slot->value()); 2054 if (function->IsJSFunction()) {
2042 UpdateTypeFeedbackInfo(feedback, new_feedback); 2055 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function);
2056 name = handle(js_function->shared()->name(), isolate());
2057 }
2058
2059 IC::State new_state = FeedbackToState(vector, slot);
2060 OnTypeFeedbackChanged(isolate(), address(), old_state, new_state, true);
2061 TRACE_VECTOR_IC("CallIC", name, old_state, new_state);
2043 } 2062 }
2044 2063
2045 2064
2046 #undef TRACE_IC 2065 #undef TRACE_IC
2047 2066
2048 2067
2049 // ---------------------------------------------------------------------------- 2068 // ----------------------------------------------------------------------------
2050 // Static IC stub generators. 2069 // Static IC stub generators.
2051 // 2070 //
2052 2071
(...skipping 14 matching lines...) Expand all
2067 2086
2068 RUNTIME_FUNCTION(CallIC_Customization_Miss) { 2087 RUNTIME_FUNCTION(CallIC_Customization_Miss) {
2069 TimerEventScope<TimerEventIcMiss> timer(isolate); 2088 TimerEventScope<TimerEventIcMiss> timer(isolate);
2070 HandleScope scope(isolate); 2089 HandleScope scope(isolate);
2071 DCHECK(args.length() == 4); 2090 DCHECK(args.length() == 4);
2072 // A miss on a custom call ic always results in going megamorphic. 2091 // A miss on a custom call ic always results in going megamorphic.
2073 CallIC ic(isolate); 2092 CallIC ic(isolate);
2074 Handle<Object> function = args.at<Object>(1); 2093 Handle<Object> function = args.at<Object>(1);
2075 Handle<FixedArray> vector = args.at<FixedArray>(2); 2094 Handle<FixedArray> vector = args.at<FixedArray>(2);
2076 Handle<Smi> slot = args.at<Smi>(3); 2095 Handle<Smi> slot = args.at<Smi>(3);
2077 ic.PatchMegamorphic(vector, slot); 2096 ic.PatchMegamorphic(function, vector, slot);
2078 return *function; 2097 return *function;
2079 } 2098 }
2080 2099
2081 2100
2082 // Used from ic-<arch>.cc. 2101 // Used from ic-<arch>.cc.
2083 RUNTIME_FUNCTION(LoadIC_Miss) { 2102 RUNTIME_FUNCTION(LoadIC_Miss) {
2084 TimerEventScope<TimerEventIcMiss> timer(isolate); 2103 TimerEventScope<TimerEventIcMiss> timer(isolate);
2085 HandleScope scope(isolate); 2104 HandleScope scope(isolate);
2086 DCHECK(args.length() == 2); 2105 DCHECK(args.length() == 2);
2087 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); 2106 LoadIC ic(IC::NO_EXTRA_FRAME, isolate);
(...skipping 1063 matching lines...) Expand 10 before | Expand all | Expand 10 after
3151 #undef ADDR 3170 #undef ADDR
3152 }; 3171 };
3153 3172
3154 3173
3155 Address IC::AddressFromUtilityId(IC::UtilityId id) { 3174 Address IC::AddressFromUtilityId(IC::UtilityId id) {
3156 return IC_utilities[id]; 3175 return IC_utilities[id];
3157 } 3176 }
3158 3177
3159 3178
3160 } } // namespace v8::internal 3179 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/ic-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698