aboutsummaryrefslogtreecommitdiff
path: root/src/ic/ic-stats.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/ic/ic-stats.cc')
-rw-r--r--src/ic/ic-stats.cc144
1 files changed, 144 insertions, 0 deletions
diff --git a/src/ic/ic-stats.cc b/src/ic/ic-stats.cc
new file mode 100644
index 00000000..de2529fc
--- /dev/null
+++ b/src/ic/ic-stats.cc
@@ -0,0 +1,144 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/ic/ic-stats.h"
+
+#include "src/flags.h"
+#include "src/objects-inl.h"
+#include "src/tracing/trace-event.h"
+#include "src/tracing/traced-value.h"
+#include "src/v8.h"
+
+namespace v8 {
+namespace internal {
+
+base::LazyInstance<ICStats>::type ICStats::instance_ =
+ LAZY_INSTANCE_INITIALIZER;
+
+ICStats::ICStats() : ic_infos_(MAX_IC_INFO), pos_(0) {
+ base::NoBarrier_Store(&enabled_, 0);
+}
+
+void ICStats::Begin() {
+ if (V8_LIKELY(!FLAG_ic_stats)) return;
+ base::NoBarrier_Store(&enabled_, 1);
+}
+
+void ICStats::End() {
+ if (base::NoBarrier_Load(&enabled_) != 1) return;
+ ++pos_;
+ if (pos_ == MAX_IC_INFO) {
+ Dump();
+ }
+ base::NoBarrier_Store(&enabled_, 0);
+}
+
+void ICStats::Reset() {
+ for (auto ic_info : ic_infos_) {
+ ic_info.Reset();
+ }
+ pos_ = 0;
+}
+
+void ICStats::Dump() {
+ auto value = v8::tracing::TracedValue::Create();
+ value->BeginArray("data");
+ for (int i = 0; i < pos_; ++i) {
+ ic_infos_[i].AppendToTracedValue(value.get());
+ }
+ value->EndArray();
+
+ TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("v8.ic_stats"), "V8.ICStats",
+ TRACE_EVENT_SCOPE_THREAD, "ic-stats", std::move(value));
+ Reset();
+}
+
+const char* ICStats::GetOrCacheScriptName(Script* script) {
+ if (script_name_map_.find(script) != script_name_map_.end()) {
+ return script_name_map_[script].get();
+ }
+ Object* script_name_raw = script->name();
+ if (script_name_raw->IsString()) {
+ String* script_name = String::cast(script_name_raw);
+ char* c_script_name =
+ script_name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL)
+ .release();
+ script_name_map_.insert(
+ std::make_pair(script, std::unique_ptr<char[]>(c_script_name)));
+ return c_script_name;
+ } else {
+ script_name_map_.insert(
+ std::make_pair(script, std::unique_ptr<char[]>(nullptr)));
+ return nullptr;
+ }
+ return nullptr;
+}
+
+const char* ICStats::GetOrCacheFunctionName(JSFunction* function) {
+ if (function_name_map_.find(function) != function_name_map_.end()) {
+ return function_name_map_[function].get();
+ }
+ SharedFunctionInfo* shared = function->shared();
+ ic_infos_[pos_].is_optimized = function->IsOptimized();
+ char* function_name = shared->DebugName()->ToCString().release();
+ function_name_map_.insert(
+ std::make_pair(function, std::unique_ptr<char[]>(function_name)));
+ return function_name;
+}
+
+ICInfo::ICInfo()
+ : function_name(nullptr),
+ script_offset(0),
+ script_name(nullptr),
+ line_num(-1),
+ is_constructor(false),
+ is_optimized(false),
+ map(nullptr),
+ is_dictionary_map(0),
+ number_of_own_descriptors(0) {}
+
+void ICInfo::Reset() {
+ type.clear();
+ function_name = nullptr;
+ script_offset = 0;
+ script_name = nullptr;
+ line_num = -1;
+ is_constructor = false;
+ is_optimized = false;
+ state.clear();
+ map = nullptr;
+ is_dictionary_map = false;
+ number_of_own_descriptors = 0;
+ instance_type.clear();
+}
+
+void ICInfo::AppendToTracedValue(v8::tracing::TracedValue* value) const {
+ value->BeginDictionary();
+ value->SetString("type", type);
+ if (function_name) {
+ value->SetString("functionName", function_name);
+ if (is_optimized) {
+ value->SetInteger("optimized", is_optimized);
+ }
+ }
+ if (script_offset) value->SetInteger("offset", script_offset);
+ if (script_name) value->SetString("scriptName", script_name);
+ if (line_num != -1) value->SetInteger("lineNum", line_num);
+ if (is_constructor) value->SetInteger("constructor", is_constructor);
+ if (!state.empty()) value->SetString("state", state);
+ if (map) {
+ // V8 cannot represent integer above 2^53 - 1 in JavaScript from JSON,
+ // thus `map` should be converted to a string rather than an integer.
+ std::stringstream ss;
+ ss << map;
+ value->SetString("map", ss.str());
+ }
+ if (map) value->SetInteger("dict", is_dictionary_map);
+ if (map) value->SetInteger("own", number_of_own_descriptors);
+ if (!instance_type.empty()) value->SetString("instanceType", instance_type);
+ value->EndDictionary();
+}
+
+} // namespace internal
+} // namespace v8