Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "src/ic/ic-stats.h" | |
| 6 | |
| 7 #include "src/flags.h" | |
| 8 #include "src/objects-inl.h" | |
| 9 #include "src/tracing/trace-event.h" | |
| 10 #include "src/tracing/traced-value.h" | |
| 11 #include "src/v8.h" | |
| 12 | |
| 13 namespace v8 { | |
| 14 namespace internal { | |
| 15 | |
| 16 base::LazyInstance<ICStats>::type ICStats::instance_ = | |
| 17 LAZY_INSTANCE_INITIALIZER; | |
| 18 | |
| 19 ICStats::ICStats() : ic_infos_(MAX_IC_INFO), pos_(0) { | |
| 20 base::NoBarrier_Store(&being_used_, 0); | |
| 21 } | |
| 22 | |
| 23 void ICStats::Begin() { | |
| 24 if (V8_LIKELY(!FLAG_ic_stats)) return; | |
| 25 base::NoBarrier_Store(&being_used_, 1); | |
| 26 } | |
| 27 | |
| 28 void ICStats::End() { | |
| 29 if (base::NoBarrier_Load(&being_used_) != 1) return; | |
| 30 ++pos_; | |
| 31 if (pos_ == MAX_IC_INFO) { | |
| 32 Dump(); | |
| 33 } | |
| 34 base::NoBarrier_Store(&being_used_, 0); | |
| 35 } | |
| 36 | |
| 37 void ICStats::Reset() { | |
| 38 for (auto ic_info : ic_infos_) { | |
| 39 ic_info.Reset(); | |
| 40 } | |
| 41 pos_ = 0; | |
| 42 } | |
| 43 | |
| 44 void ICStats::Dump() { | |
| 45 auto value = v8::tracing::TracedValue::Create(); | |
| 46 value->BeginArray("data"); | |
| 47 for (int i = 0; i < pos_; ++i) { | |
| 48 ic_infos_[i].AppendToTracedValue(value.get()); | |
| 49 } | |
| 50 value->EndArray(); | |
| 51 | |
| 52 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("v8.ic_stats"), "V8.ICStats", | |
| 53 TRACE_EVENT_SCOPE_THREAD, "ic-stats", std::move(value)); | |
| 54 Reset(); | |
| 55 } | |
| 56 | |
| 57 const char* ICStats::GetOrCacheScriptName(Object* obj) { | |
| 58 if (script_name_map_.find(obj) != script_name_map_.end()) { | |
| 59 return script_name_map_[obj].get(); | |
| 60 } | |
| 61 Script* script = Script::cast(obj); | |
| 62 Object* script_name_raw = script->name(); | |
| 63 if (script_name_raw->IsString()) { | |
| 64 String* script_name = String::cast(script->name()); | |
|
Camillo Bruni
2016/12/02 12:12:55
String::cast(script_name_raw);
lpy
2016/12/05 17:49:10
Done.
| |
| 65 char* c_script_name = | |
| 66 script_name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL) | |
| 67 .release(); | |
| 68 script_name_map_.insert( | |
| 69 std::make_pair(obj, std::unique_ptr<char[]>(c_script_name))); | |
| 70 return c_script_name; | |
| 71 } else { | |
| 72 script_name_map_.insert( | |
| 73 std::make_pair(obj, std::unique_ptr<char[]>(nullptr))); | |
| 74 return nullptr; | |
| 75 } | |
| 76 return nullptr; | |
| 77 } | |
| 78 | |
| 79 std::string& ICStats::GetOrCacheFunctionName(JSFunction* function) { | |
| 80 if (function_name_map_.find(function) != function_name_map_.end()) { | |
| 81 return function_name_map_[function]; | |
| 82 } | |
| 83 SharedFunctionInfo* shared = function->shared(); | |
| 84 std::string function_name = function->IsOptimized() ? "*" : "~"; | |
|
Camillo Bruni
2016/12/02 12:12:55
that might be another boolean that could be put no
lpy
2016/12/05 17:49:10
Done.
| |
| 85 function_name += shared->DebugName()->ToCString().get(); | |
| 86 function_name_map_.insert(std::make_pair(function, function_name)); | |
| 87 return function_name_map_[function]; | |
|
Camillo Bruni
2016/12/02 12:12:55
return function_name;
lpy
2016/12/05 17:49:10
Done.
| |
| 88 } | |
| 89 | |
| 90 ICInfo::ICInfo() | |
| 91 : offset(0), | |
| 92 script_name(nullptr), | |
| 93 line_num(-1), | |
| 94 constructor(0), | |
| 95 map(nullptr), | |
| 96 dict(0), | |
| 97 own(0) {} | |
| 98 | |
| 99 void ICInfo::Reset() { | |
| 100 type.clear(); | |
| 101 function_name.clear(); | |
| 102 offset = 0; | |
| 103 script_name = nullptr; | |
| 104 line_num = -1; | |
| 105 constructor = 0; | |
| 106 state.clear(); | |
| 107 map = nullptr; | |
| 108 dict = 0; | |
| 109 own = 0; | |
| 110 instance_type.clear(); | |
| 111 } | |
| 112 | |
| 113 void ICInfo::AppendToTracedValue(v8::tracing::TracedValue* value) const { | |
| 114 value->BeginDictionary(); | |
| 115 value->SetString("type", type); | |
| 116 if (!function_name.empty()) { | |
| 117 value->SetString("functionName", function_name); | |
| 118 } | |
| 119 if (offset) value->SetInteger("offset", offset); | |
| 120 if (script_name) value->SetString("scriptName", script_name); | |
| 121 if (line_num != -1) value->SetInteger("lineNum", line_num); | |
| 122 if (constructor) value->SetInteger("constructor", constructor); | |
| 123 if (!state.empty()) value->SetString("state", state); | |
| 124 // TODO(lpy) Find a better solution rather than stringstream. | |
| 125 if (map) { | |
| 126 std::stringstream ss; | |
| 127 ss << map; | |
| 128 value->SetString("map", ss.str()); | |
|
Camillo Bruni
2016/12/02 12:12:55
Can't you just use SetInteger and reinterpet_cast
lpy
2016/12/05 17:49:10
Done.
| |
| 129 } | |
| 130 if (map) value->SetInteger("dict", dict); | |
| 131 if (map) value->SetInteger("own", own); | |
| 132 if (!instance_type.empty()) value->SetString("instanceType", instance_type); | |
| 133 value->EndDictionary(); | |
| 134 } | |
| 135 | |
| 136 } // namespace internal | |
| 137 } // namespace v8 | |
| OLD | NEW |