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/ic/ic.h" | 5 #include "src/ic/ic.h" |
6 | 6 |
7 #include <iostream> | 7 #include <iostream> |
8 | 8 |
9 #include "src/accessors.h" | 9 #include "src/accessors.h" |
10 #include "src/api-arguments-inl.h" | 10 #include "src/api-arguments-inl.h" |
11 #include "src/api.h" | 11 #include "src/api.h" |
12 #include "src/arguments.h" | 12 #include "src/arguments.h" |
13 #include "src/base/bits.h" | 13 #include "src/base/bits.h" |
14 #include "src/codegen.h" | 14 #include "src/codegen.h" |
15 #include "src/conversions.h" | 15 #include "src/conversions.h" |
16 #include "src/execution.h" | 16 #include "src/execution.h" |
17 #include "src/field-type.h" | 17 #include "src/field-type.h" |
18 #include "src/frames-inl.h" | 18 #include "src/frames-inl.h" |
19 #include "src/ic/call-optimization.h" | 19 #include "src/ic/call-optimization.h" |
20 #include "src/ic/handler-compiler.h" | 20 #include "src/ic/handler-compiler.h" |
21 #include "src/ic/handler-configuration-inl.h" | 21 #include "src/ic/handler-configuration-inl.h" |
22 #include "src/ic/ic-compiler.h" | 22 #include "src/ic/ic-compiler.h" |
23 #include "src/ic/ic-inl.h" | 23 #include "src/ic/ic-inl.h" |
24 #include "src/ic/ic-stats.h" | |
24 #include "src/ic/stub-cache.h" | 25 #include "src/ic/stub-cache.h" |
25 #include "src/isolate-inl.h" | 26 #include "src/isolate-inl.h" |
26 #include "src/macro-assembler.h" | 27 #include "src/macro-assembler.h" |
27 #include "src/prototype.h" | 28 #include "src/prototype.h" |
28 #include "src/runtime-profiler.h" | 29 #include "src/runtime-profiler.h" |
29 #include "src/runtime/runtime-utils.h" | 30 #include "src/runtime/runtime-utils.h" |
30 #include "src/runtime/runtime.h" | 31 #include "src/runtime/runtime.h" |
31 #include "src/tracing/trace-event.h" | 32 #include "src/tracing/trace-event.h" |
33 #include "src/tracing/tracing-category-observer.h" | |
32 | 34 |
33 namespace v8 { | 35 namespace v8 { |
34 namespace internal { | 36 namespace internal { |
35 | 37 |
36 char IC::TransitionMarkFromState(IC::State state) { | 38 char IC::TransitionMarkFromState(IC::State state) { |
37 switch (state) { | 39 switch (state) { |
38 case UNINITIALIZED: | 40 case UNINITIALIZED: |
39 return '0'; | 41 return '0'; |
40 case PREMONOMORPHIC: | 42 case PREMONOMORPHIC: |
41 return '.'; | 43 return '.'; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
83 if (FLAG_trace_ic) { \ | 85 if (FLAG_trace_ic) { \ |
84 PrintF("[%s patching generic stub in ", type); \ | 86 PrintF("[%s patching generic stub in ", type); \ |
85 PrintF("(see below) (%s)]\n", reason); \ | 87 PrintF("(see below) (%s)]\n", reason); \ |
86 } \ | 88 } \ |
87 } while (false) | 89 } while (false) |
88 | 90 |
89 #endif // DEBUG | 91 #endif // DEBUG |
90 | 92 |
91 | 93 |
92 void IC::TraceIC(const char* type, Handle<Object> name) { | 94 void IC::TraceIC(const char* type, Handle<Object> name) { |
93 if (FLAG_trace_ic) { | 95 if (FLAG_ic_stats) { |
94 if (AddressIsDeoptimizedCode()) return; | 96 if (AddressIsDeoptimizedCode()) return; |
95 DCHECK(UseVector()); | 97 DCHECK(UseVector()); |
96 State new_state = nexus()->StateFromFeedback(); | 98 State new_state = nexus()->StateFromFeedback(); |
97 TraceIC(type, name, state(), new_state); | 99 TraceIC(type, name, state(), new_state); |
98 } | 100 } |
99 } | 101 } |
100 | 102 |
101 | 103 |
102 void IC::TraceIC(const char* type, Handle<Object> name, State old_state, | 104 void IC::TraceIC(const char* type, Handle<Object> name, State old_state, |
103 State new_state) { | 105 State new_state) { |
104 if (!FLAG_trace_ic) return; | 106 if (V8_LIKELY(!FLAG_ic_stats)) return; |
105 PrintF("[%s%s in ", is_keyed() ? "Keyed" : "", type); | 107 |
108 if (FLAG_ic_stats & | |
Camillo Bruni
2016/12/02 12:12:55
no need to recheck the flag
lpy
2016/12/05 17:49:11
same here, we want to check whether the flag is en
| |
109 v8::tracing::TracingCategoryObserver::ENABLED_BY_TRACING) { | |
110 ICStats::instance()->Begin(); | |
111 ICInfo& ic_info = ICStats::instance()->Current(); | |
112 ic_info.type = is_keyed() ? "Keyed" : ""; | |
113 ic_info.type += type; | |
114 } else if (FLAG_ic_stats) { | |
Camillo Bruni
2016/12/02 12:12:55
same here.
lpy
2016/12/05 17:49:11
see explanation above
| |
115 PrintF("[%s%s in ", is_keyed() ? "Keyed" : "", type); | |
116 } | |
106 | 117 |
107 // TODO(jkummerow): Add support for "apply". The logic is roughly: | 118 // TODO(jkummerow): Add support for "apply". The logic is roughly: |
108 // marker = [fp_ + kMarkerOffset]; | 119 // marker = [fp_ + kMarkerOffset]; |
109 // if marker is smi and marker.value == INTERNAL and | 120 // if marker is smi and marker.value == INTERNAL and |
110 // the frame's code == builtin(Builtins::kFunctionApply): | 121 // the frame's code == builtin(Builtins::kFunctionApply): |
111 // then print "apply from" and advance one frame | 122 // then print "apply from" and advance one frame |
112 | 123 |
113 Object* maybe_function = | 124 Object* maybe_function = |
114 Memory::Object_at(fp_ + JavaScriptFrameConstants::kFunctionOffset); | 125 Memory::Object_at(fp_ + JavaScriptFrameConstants::kFunctionOffset); |
115 if (maybe_function->IsJSFunction()) { | 126 if (maybe_function->IsJSFunction()) { |
116 JSFunction* function = JSFunction::cast(maybe_function); | 127 JSFunction* function = JSFunction::cast(maybe_function); |
117 int code_offset = 0; | 128 int code_offset = 0; |
118 if (function->IsInterpreted()) { | 129 if (function->IsInterpreted()) { |
119 code_offset = InterpretedFrame::GetBytecodeOffset(fp()); | 130 code_offset = InterpretedFrame::GetBytecodeOffset(fp()); |
120 } else { | 131 } else { |
121 code_offset = | 132 code_offset = |
122 static_cast<int>(pc() - function->code()->instruction_start()); | 133 static_cast<int>(pc() - function->code()->instruction_start()); |
123 } | 134 } |
124 JavaScriptFrame::PrintFunctionAndOffset(function, function->abstract_code(), | 135 if (FLAG_ic_stats & |
125 code_offset, stdout, true); | 136 v8::tracing::TracingCategoryObserver::ENABLED_BY_TRACING) { |
137 JavaScriptFrame::CollectFunctionAndOffsetForICStats( | |
138 function, function->abstract_code(), code_offset); | |
139 } else if (FLAG_ic_stats) { | |
140 JavaScriptFrame::PrintFunctionAndOffset( | |
141 function, function->abstract_code(), code_offset, stdout, true); | |
142 } | |
126 } | 143 } |
127 | 144 |
128 const char* modifier = ""; | 145 const char* modifier = ""; |
129 if (kind() == Code::KEYED_STORE_IC) { | 146 if (kind() == Code::KEYED_STORE_IC) { |
130 KeyedAccessStoreMode mode = | 147 KeyedAccessStoreMode mode = |
131 casted_nexus<KeyedStoreICNexus>()->GetKeyedAccessStoreMode(); | 148 casted_nexus<KeyedStoreICNexus>()->GetKeyedAccessStoreMode(); |
132 modifier = GetTransitionMarkModifier(mode); | 149 modifier = GetTransitionMarkModifier(mode); |
133 } | 150 } |
134 Map* map = nullptr; | 151 Map* map = nullptr; |
135 if (!receiver_map().is_null()) { | 152 if (!receiver_map().is_null()) { |
136 map = *receiver_map(); | 153 map = *receiver_map(); |
137 } | 154 } |
138 PrintF(" (%c->%c%s) map=(%p", TransitionMarkFromState(old_state), | 155 if (FLAG_ic_stats & |
139 TransitionMarkFromState(new_state), modifier, | 156 v8::tracing::TracingCategoryObserver::ENABLED_BY_TRACING) { |
140 reinterpret_cast<void*>(map)); | 157 ICInfo& ic_info = ICStats::instance()->Current(); |
158 ic_info.state = "("; | |
Camillo Bruni
2016/12/02 12:12:55
I'm not too familiar with the C++ standard library
lpy
2016/12/05 17:49:11
Done.
| |
159 ic_info.state += TransitionMarkFromState(old_state); | |
160 ic_info.state += "->"; | |
161 ic_info.state += TransitionMarkFromState(new_state); | |
162 ic_info.state += modifier; | |
163 ic_info.state += ")"; | |
164 ic_info.map = reinterpret_cast<void*>(map); | |
165 } else if (FLAG_ic_stats) { | |
166 PrintF(" (%c->%c%s) map=(%p", TransitionMarkFromState(old_state), | |
167 TransitionMarkFromState(new_state), modifier, | |
168 reinterpret_cast<void*>(map)); | |
169 } | |
141 if (map != nullptr) { | 170 if (map != nullptr) { |
142 PrintF(" dict=%u own=%u type=", map->is_dictionary_map(), | 171 if (FLAG_ic_stats & |
143 map->NumberOfOwnDescriptors()); | 172 v8::tracing::TracingCategoryObserver::ENABLED_BY_TRACING) { |
144 std::cout << map->instance_type(); | 173 ICInfo& ic_info = ICStats::instance()->Current(); |
174 ic_info.dict = map->is_dictionary_map(); | |
175 ic_info.own = map->NumberOfOwnDescriptors(); | |
176 ic_info.instance_type = std::to_string(map->instance_type()); | |
177 } else if (FLAG_ic_stats) { | |
178 PrintF(" dict=%u own=%u type=", map->is_dictionary_map(), | |
179 map->NumberOfOwnDescriptors()); | |
180 std::cout << map->instance_type(); | |
181 } | |
145 } | 182 } |
146 PrintF(") "); | 183 if (FLAG_ic_stats & |
147 name->ShortPrint(stdout); | 184 v8::tracing::TracingCategoryObserver::ENABLED_BY_TRACING) { |
148 PrintF("]\n"); | 185 // TODO(lpy) Add name as key field in ICStats. |
186 ICStats::instance()->End(); | |
187 } else if (FLAG_ic_stats) { | |
188 PrintF(") "); | |
189 name->ShortPrint(stdout); | |
190 PrintF("]\n"); | |
191 } | |
149 } | 192 } |
150 | 193 |
151 | 194 |
152 #define TRACE_IC(type, name) TraceIC(type, name) | 195 #define TRACE_IC(type, name) TraceIC(type, name) |
153 | 196 |
154 | 197 |
155 IC::IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus) | 198 IC::IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus) |
156 : isolate_(isolate), | 199 : isolate_(isolate), |
157 vector_set_(false), | 200 vector_set_(false), |
158 target_maps_set_(false), | 201 target_maps_set_(false), |
(...skipping 2746 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2905 } else { | 2948 } else { |
2906 // Install the generic stub. | 2949 // Install the generic stub. |
2907 BinaryOpICStub stub(isolate(), state); | 2950 BinaryOpICStub stub(isolate(), state); |
2908 new_target = stub.GetCode(); | 2951 new_target = stub.GetCode(); |
2909 | 2952 |
2910 // Sanity check the generic stub. | 2953 // Sanity check the generic stub. |
2911 DCHECK_NULL(new_target->FindFirstAllocationSite()); | 2954 DCHECK_NULL(new_target->FindFirstAllocationSite()); |
2912 } | 2955 } |
2913 set_target(*new_target); | 2956 set_target(*new_target); |
2914 | 2957 |
2915 if (FLAG_trace_ic) { | 2958 if (FLAG_ic_stats & |
2959 v8::tracing::TracingCategoryObserver::ENABLED_BY_TRACING) { | |
2960 auto ic_stats = ICStats::instance(); | |
2961 ic_stats->Begin(); | |
2962 ICInfo& ic_info = ic_stats->Current(); | |
2963 ic_info.type = "BinaryOpIC"; | |
2964 ic_info.state = old_state.ToString(); | |
2965 ic_info.state += " => "; | |
2966 ic_info.state += state.ToString(); | |
2967 JavaScriptFrame::CollectTopFrameForICStats(isolate()); | |
2968 ic_stats->End(); | |
2969 } else if (FLAG_ic_stats) { | |
2970 // if (FLAG_trace_ic) { | |
2916 OFStream os(stdout); | 2971 OFStream os(stdout); |
2917 os << "[BinaryOpIC" << old_state << " => " << state << " @ " | 2972 os << "[BinaryOpIC" << old_state << " => " << state << " @ " |
2918 << static_cast<void*>(*new_target) << " <- "; | 2973 << static_cast<void*>(*new_target) << " <- "; |
2919 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); | 2974 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); |
2920 if (!allocation_site.is_null()) { | 2975 if (!allocation_site.is_null()) { |
2921 os << " using allocation site " << static_cast<void*>(*allocation_site); | 2976 os << " using allocation site " << static_cast<void*>(*allocation_site); |
2922 } | 2977 } |
2923 os << "]" << std::endl; | 2978 os << "]" << std::endl; |
2924 } | 2979 } |
2925 | 2980 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2979 isolate(), old_stub.state(), old_stub.left(), old_stub.right(), op_, | 3034 isolate(), old_stub.state(), old_stub.left(), old_stub.right(), op_, |
2980 HasInlinedSmiCode(address()), x, y); | 3035 HasInlinedSmiCode(address()), x, y); |
2981 CompareICStub stub(isolate(), op_, new_left, new_right, state); | 3036 CompareICStub stub(isolate(), op_, new_left, new_right, state); |
2982 if (state == CompareICState::KNOWN_RECEIVER) { | 3037 if (state == CompareICState::KNOWN_RECEIVER) { |
2983 stub.set_known_map( | 3038 stub.set_known_map( |
2984 Handle<Map>(Handle<JSReceiver>::cast(x)->map(), isolate())); | 3039 Handle<Map>(Handle<JSReceiver>::cast(x)->map(), isolate())); |
2985 } | 3040 } |
2986 Handle<Code> new_target = stub.GetCode(); | 3041 Handle<Code> new_target = stub.GetCode(); |
2987 set_target(*new_target); | 3042 set_target(*new_target); |
2988 | 3043 |
2989 if (FLAG_trace_ic) { | 3044 if (FLAG_ic_stats & |
3045 v8::tracing::TracingCategoryObserver::ENABLED_BY_TRACING) { | |
3046 auto ic_stats = ICStats::instance(); | |
3047 ic_stats->Begin(); | |
3048 ICInfo& ic_info = ic_stats->Current(); | |
3049 ic_info.type = "CompareIC"; | |
3050 JavaScriptFrame::CollectTopFrameForICStats(isolate()); | |
3051 ic_info.state = "(("; | |
3052 ic_info.state += CompareICState::GetStateName(old_stub.left()); | |
3053 ic_info.state += "+"; | |
3054 ic_info.state += CompareICState::GetStateName(old_stub.right()); | |
3055 ic_info.state += "="; | |
3056 ic_info.state += CompareICState::GetStateName(old_stub.state()); | |
3057 ic_info.state += ")->("; | |
3058 ic_info.state += CompareICState::GetStateName(new_left); | |
3059 ic_info.state += "+"; | |
3060 ic_info.state += CompareICState::GetStateName(new_right); | |
3061 ic_info.state += "="; | |
3062 ic_info.state += CompareICState::GetStateName(state); | |
3063 ic_info.state += "))#"; | |
3064 ic_info.state += Token::Name(op_); | |
3065 ic_stats->End(); | |
3066 } else if (FLAG_ic_stats) { | |
3067 // if (FLAG_trace_ic) { | |
2990 PrintF("[CompareIC in "); | 3068 PrintF("[CompareIC in "); |
2991 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); | 3069 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); |
2992 PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n", | 3070 PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n", |
2993 CompareICState::GetStateName(old_stub.left()), | 3071 CompareICState::GetStateName(old_stub.left()), |
2994 CompareICState::GetStateName(old_stub.right()), | 3072 CompareICState::GetStateName(old_stub.right()), |
2995 CompareICState::GetStateName(old_stub.state()), | 3073 CompareICState::GetStateName(old_stub.state()), |
2996 CompareICState::GetStateName(new_left), | 3074 CompareICState::GetStateName(new_left), |
2997 CompareICState::GetStateName(new_right), | 3075 CompareICState::GetStateName(new_right), |
2998 CompareICState::GetStateName(state), Token::Name(op_), | 3076 CompareICState::GetStateName(state), Token::Name(op_), |
2999 static_cast<void*>(*stub.GetCode())); | 3077 static_cast<void*>(*stub.GetCode())); |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3237 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state()); | 3315 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state()); |
3238 it.Next(); | 3316 it.Next(); |
3239 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, | 3317 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, |
3240 Object::GetProperty(&it)); | 3318 Object::GetProperty(&it)); |
3241 } | 3319 } |
3242 | 3320 |
3243 return *result; | 3321 return *result; |
3244 } | 3322 } |
3245 } // namespace internal | 3323 } // namespace internal |
3246 } // namespace v8 | 3324 } // namespace v8 |
OLD | NEW |