Chromium Code Reviews| 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 |