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 & |
| 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 { |
| 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 { |
| 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 // Reverse enough space for IC transition state, the longest length is 17. |
| 159 ic_info.state.reserve(17); |
| 160 ic_info.state = "("; |
| 161 ic_info.state += TransitionMarkFromState(old_state); |
| 162 ic_info.state += "->"; |
| 163 ic_info.state += TransitionMarkFromState(new_state); |
| 164 ic_info.state += modifier; |
| 165 ic_info.state += ")"; |
| 166 ic_info.map = reinterpret_cast<void*>(map); |
| 167 } else { |
| 168 PrintF(" (%c->%c%s) map=(%p", TransitionMarkFromState(old_state), |
| 169 TransitionMarkFromState(new_state), modifier, |
| 170 reinterpret_cast<void*>(map)); |
| 171 } |
141 if (map != nullptr) { | 172 if (map != nullptr) { |
142 PrintF(" dict=%u own=%u type=", map->is_dictionary_map(), | 173 if (FLAG_ic_stats & |
143 map->NumberOfOwnDescriptors()); | 174 v8::tracing::TracingCategoryObserver::ENABLED_BY_TRACING) { |
144 std::cout << map->instance_type(); | 175 ICInfo& ic_info = ICStats::instance()->Current(); |
| 176 ic_info.is_dictionary_map = map->is_dictionary_map(); |
| 177 ic_info.number_of_own_descriptors = map->NumberOfOwnDescriptors(); |
| 178 ic_info.instance_type = std::to_string(map->instance_type()); |
| 179 } else { |
| 180 PrintF(" dict=%u own=%u type=", map->is_dictionary_map(), |
| 181 map->NumberOfOwnDescriptors()); |
| 182 std::cout << map->instance_type(); |
| 183 } |
145 } | 184 } |
146 PrintF(") "); | 185 if (FLAG_ic_stats & |
147 name->ShortPrint(stdout); | 186 v8::tracing::TracingCategoryObserver::ENABLED_BY_TRACING) { |
148 PrintF("]\n"); | 187 // TODO(lpy) Add name as key field in ICStats. |
| 188 ICStats::instance()->End(); |
| 189 } else { |
| 190 PrintF(") "); |
| 191 name->ShortPrint(stdout); |
| 192 PrintF("]\n"); |
| 193 } |
149 } | 194 } |
150 | 195 |
151 | 196 |
152 #define TRACE_IC(type, name) TraceIC(type, name) | 197 #define TRACE_IC(type, name) TraceIC(type, name) |
153 | 198 |
154 | 199 |
155 IC::IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus) | 200 IC::IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus) |
156 : isolate_(isolate), | 201 : isolate_(isolate), |
157 vector_set_(false), | 202 vector_set_(false), |
158 target_maps_set_(false), | 203 target_maps_set_(false), |
(...skipping 2746 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2905 } else { | 2950 } else { |
2906 // Install the generic stub. | 2951 // Install the generic stub. |
2907 BinaryOpICStub stub(isolate(), state); | 2952 BinaryOpICStub stub(isolate(), state); |
2908 new_target = stub.GetCode(); | 2953 new_target = stub.GetCode(); |
2909 | 2954 |
2910 // Sanity check the generic stub. | 2955 // Sanity check the generic stub. |
2911 DCHECK_NULL(new_target->FindFirstAllocationSite()); | 2956 DCHECK_NULL(new_target->FindFirstAllocationSite()); |
2912 } | 2957 } |
2913 set_target(*new_target); | 2958 set_target(*new_target); |
2914 | 2959 |
2915 if (FLAG_trace_ic) { | 2960 if (FLAG_ic_stats & |
| 2961 v8::tracing::TracingCategoryObserver::ENABLED_BY_TRACING) { |
| 2962 auto ic_stats = ICStats::instance(); |
| 2963 ic_stats->Begin(); |
| 2964 ICInfo& ic_info = ic_stats->Current(); |
| 2965 ic_info.type = "BinaryOpIC"; |
| 2966 ic_info.state = old_state.ToString(); |
| 2967 ic_info.state += " => "; |
| 2968 ic_info.state += state.ToString(); |
| 2969 JavaScriptFrame::CollectTopFrameForICStats(isolate()); |
| 2970 ic_stats->End(); |
| 2971 } else if (FLAG_ic_stats) { |
| 2972 // if (FLAG_trace_ic) { |
2916 OFStream os(stdout); | 2973 OFStream os(stdout); |
2917 os << "[BinaryOpIC" << old_state << " => " << state << " @ " | 2974 os << "[BinaryOpIC" << old_state << " => " << state << " @ " |
2918 << static_cast<void*>(*new_target) << " <- "; | 2975 << static_cast<void*>(*new_target) << " <- "; |
2919 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); | 2976 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); |
2920 if (!allocation_site.is_null()) { | 2977 if (!allocation_site.is_null()) { |
2921 os << " using allocation site " << static_cast<void*>(*allocation_site); | 2978 os << " using allocation site " << static_cast<void*>(*allocation_site); |
2922 } | 2979 } |
2923 os << "]" << std::endl; | 2980 os << "]" << std::endl; |
2924 } | 2981 } |
2925 | 2982 |
(...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_, | 3036 isolate(), old_stub.state(), old_stub.left(), old_stub.right(), op_, |
2980 HasInlinedSmiCode(address()), x, y); | 3037 HasInlinedSmiCode(address()), x, y); |
2981 CompareICStub stub(isolate(), op_, new_left, new_right, state); | 3038 CompareICStub stub(isolate(), op_, new_left, new_right, state); |
2982 if (state == CompareICState::KNOWN_RECEIVER) { | 3039 if (state == CompareICState::KNOWN_RECEIVER) { |
2983 stub.set_known_map( | 3040 stub.set_known_map( |
2984 Handle<Map>(Handle<JSReceiver>::cast(x)->map(), isolate())); | 3041 Handle<Map>(Handle<JSReceiver>::cast(x)->map(), isolate())); |
2985 } | 3042 } |
2986 Handle<Code> new_target = stub.GetCode(); | 3043 Handle<Code> new_target = stub.GetCode(); |
2987 set_target(*new_target); | 3044 set_target(*new_target); |
2988 | 3045 |
2989 if (FLAG_trace_ic) { | 3046 if (FLAG_ic_stats & |
| 3047 v8::tracing::TracingCategoryObserver::ENABLED_BY_TRACING) { |
| 3048 auto ic_stats = ICStats::instance(); |
| 3049 ic_stats->Begin(); |
| 3050 ICInfo& ic_info = ic_stats->Current(); |
| 3051 ic_info.type = "CompareIC"; |
| 3052 JavaScriptFrame::CollectTopFrameForICStats(isolate()); |
| 3053 ic_info.state = "(("; |
| 3054 ic_info.state += CompareICState::GetStateName(old_stub.left()); |
| 3055 ic_info.state += "+"; |
| 3056 ic_info.state += CompareICState::GetStateName(old_stub.right()); |
| 3057 ic_info.state += "="; |
| 3058 ic_info.state += CompareICState::GetStateName(old_stub.state()); |
| 3059 ic_info.state += ")->("; |
| 3060 ic_info.state += CompareICState::GetStateName(new_left); |
| 3061 ic_info.state += "+"; |
| 3062 ic_info.state += CompareICState::GetStateName(new_right); |
| 3063 ic_info.state += "="; |
| 3064 ic_info.state += CompareICState::GetStateName(state); |
| 3065 ic_info.state += "))#"; |
| 3066 ic_info.state += Token::Name(op_); |
| 3067 ic_stats->End(); |
| 3068 } else if (FLAG_ic_stats) { |
| 3069 // if (FLAG_trace_ic) { |
2990 PrintF("[CompareIC in "); | 3070 PrintF("[CompareIC in "); |
2991 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); | 3071 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); |
2992 PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n", | 3072 PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n", |
2993 CompareICState::GetStateName(old_stub.left()), | 3073 CompareICState::GetStateName(old_stub.left()), |
2994 CompareICState::GetStateName(old_stub.right()), | 3074 CompareICState::GetStateName(old_stub.right()), |
2995 CompareICState::GetStateName(old_stub.state()), | 3075 CompareICState::GetStateName(old_stub.state()), |
2996 CompareICState::GetStateName(new_left), | 3076 CompareICState::GetStateName(new_left), |
2997 CompareICState::GetStateName(new_right), | 3077 CompareICState::GetStateName(new_right), |
2998 CompareICState::GetStateName(state), Token::Name(op_), | 3078 CompareICState::GetStateName(state), Token::Name(op_), |
2999 static_cast<void*>(*stub.GetCode())); | 3079 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()); | 3317 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state()); |
3238 it.Next(); | 3318 it.Next(); |
3239 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, | 3319 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, |
3240 Object::GetProperty(&it)); | 3320 Object::GetProperty(&it)); |
3241 } | 3321 } |
3242 | 3322 |
3243 return *result; | 3323 return *result; |
3244 } | 3324 } |
3245 } // namespace internal | 3325 } // namespace internal |
3246 } // namespace v8 | 3326 } // namespace v8 |
OLD | NEW |