Index: runtime/vm/metrics.cc |
diff --git a/runtime/vm/metrics.cc b/runtime/vm/metrics.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..41a72ad1ff5614322b10a89c36d594be8698ead0 |
--- /dev/null |
+++ b/runtime/vm/metrics.cc |
@@ -0,0 +1,242 @@ |
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
+// for details. All rights reserved. Use of this source code is governed by a |
+// BSD-style license that can be found in the LICENSE file. |
+ |
+#include "vm/metrics.h" |
+ |
+#include "vm/isolate.h" |
+#include "vm/json_stream.h" |
+#include "vm/native_entry.h" |
+#include "vm/runtime_entry.h" |
+#include "vm/object.h" |
+ |
+namespace dart { |
+ |
+Metric* Metric::vm_list_head_ = NULL; |
+ |
+Metric::Metric() |
+ : isolate_(NULL), |
+ name_(NULL), |
+ description_(NULL), |
+ unit_(kCounter), |
+ value_(0), |
+ next_(NULL) { |
+} |
+ |
+ |
+void Metric::Init(Isolate* isolate, |
+ const char* name, |
+ const char* description, |
+ Unit unit) { |
+ // Only called once. |
+ ASSERT(next_ == NULL); |
+ ASSERT(name != NULL); |
+ isolate_ = isolate; |
+ name_ = name; |
+ description_ = description; |
+ unit_ = unit; |
+ RegisterWithIsolate(); |
+} |
+ |
+ |
+void Metric::Init(const char* name, const char* description, Unit unit) { |
+ // Only called once. |
+ ASSERT(next_ == NULL); |
+ ASSERT(name != NULL); |
+ name_ = name; |
+ description_ = description; |
+ unit_ = unit; |
+ RegisterWithVM(); |
+} |
+ |
+ |
+Metric::~Metric() { |
+ if (isolate_ == NULL) { |
+ DeregisterWithVM(); |
+ } else { |
+ DeregisterWithIsolate(); |
+ } |
+} |
+ |
+ |
+static const char* UnitString(intptr_t unit) { |
+ switch (unit) { |
+ case Metric::kCounter: return "counter"; |
+ case Metric::kByte: return "byte"; |
+ default: |
+ UNREACHABLE(); |
+ } |
+ UNREACHABLE(); |
+ return NULL; |
+} |
+ |
+ |
+void Metric::PrintJSON(JSONStream* stream) { |
+ JSONObject obj(stream); |
+ obj.AddProperty("type", "Counter"); |
+ obj.AddProperty("name", name_); |
+ obj.AddProperty("description", description_); |
+ obj.AddProperty("unit", UnitString(unit())); |
+ obj.AddPropertyF("id", "metrics/vm/%s", name_); |
+ // TODO(johnmccutchan): Overflow? |
+ double value_as_double = static_cast<double>(Value()); |
+ obj.AddProperty("value", value_as_double); |
+} |
+ |
+ |
+bool Metric::NameExists(Metric* head, const char* name) { |
+ ASSERT(name != NULL); |
+ while (head != NULL) { |
+ const char* metric_name = head->name(); |
+ ASSERT(metric_name != NULL); |
+ if (strcmp(metric_name, name) == 0) { |
+ return true; |
+ } |
+ head = head->next(); |
+ } |
+ return false; |
+} |
+ |
+ |
+ |
+void Metric::RegisterWithIsolate() { |
+ ASSERT(isolate_ != NULL); |
+ ASSERT(next_ == NULL); |
+ // No duplicate names allowed. |
+ ASSERT(!NameExists(isolate_->metrics_list_head(), name())); |
+ Metric* head = isolate_->metrics_list_head(); |
+ if (head != NULL) { |
+ set_next(head); |
+ } |
+ isolate_->set_metrics_list_head(this); |
+} |
+ |
+ |
+void Metric::DeregisterWithIsolate() { |
+ Metric* head = isolate_->metrics_list_head(); |
+ ASSERT(head != NULL); |
+ // Handle head of list case. |
+ if (head == this) { |
+ isolate_->set_metrics_list_head(next()); |
+ set_next(NULL); |
+ return; |
+ } |
+ Metric* previous = NULL; |
+ while (true) { |
+ previous = head; |
+ ASSERT(previous != NULL); |
+ head = head->next(); |
+ if (head == NULL) { |
+ break; |
+ } |
+ if (head == this) { |
+ // Remove this from list. |
+ previous->set_next(head->next()); |
+ set_next(NULL); |
+ return; |
+ } |
+ ASSERT(head != NULL); |
+ } |
+ UNREACHABLE(); |
+} |
+ |
+ |
+void Metric::RegisterWithVM() { |
+ ASSERT(isolate_ == NULL); |
+ ASSERT(next_ == NULL); |
+ // No duplicate names allowed. |
+ ASSERT(!NameExists(vm_list_head_, name())); |
+ Metric* head = vm_list_head_; |
+ if (head != NULL) { |
+ set_next(head); |
+ } |
+ vm_list_head_ = this; |
+} |
+ |
+ |
+void Metric::DeregisterWithVM() { |
+ ASSERT(isolate_ == NULL); |
+ Metric* head = vm_list_head_; |
+ if (head == NULL) { |
+ return; |
+ } |
+ // Handle head of list case. |
+ if (head == this) { |
+ vm_list_head_ = next(); |
+ set_next(NULL); |
+ return; |
+ } |
+ Metric* previous = NULL; |
+ while (true) { |
+ previous = head; |
+ ASSERT(previous != NULL); |
+ head = head->next(); |
+ if (head == NULL) { |
+ break; |
+ } |
+ if (head == this) { |
+ // Remove this from list. |
+ previous->set_next(head->next()); |
+ set_next(NULL); |
+ return; |
+ } |
+ ASSERT(head != NULL); |
+ } |
+ UNREACHABLE(); |
+} |
+ |
+ |
+int64_t MetricHeapOldUsed::Value() const { |
+ ASSERT(isolate() == Isolate::Current()); |
+ return isolate()->heap()->UsedInWords(Heap::kOld) * kWordSize; |
+} |
+ |
+ |
+int64_t MetricHeapOldCapacity::Value() const { |
+ ASSERT(isolate() == Isolate::Current()); |
+ return isolate()->heap()->CapacityInWords(Heap::kOld) * kWordSize; |
+} |
+ |
+ |
+int64_t MetricHeapOldExternal::Value() const { |
+ ASSERT(isolate() == Isolate::Current()); |
+ return isolate()->heap()->ExternalInWords(Heap::kOld) * kWordSize; |
+} |
+ |
+ |
+int64_t MetricHeapNewUsed::Value() const { |
+ ASSERT(isolate() == Isolate::Current()); |
+ return isolate()->heap()->UsedInWords(Heap::kNew) * kWordSize; |
+} |
+ |
+ |
+int64_t MetricHeapNewCapacity::Value() const { |
+ ASSERT(isolate() == Isolate::Current()); |
+ return isolate()->heap()->CapacityInWords(Heap::kNew) * kWordSize; |
+} |
+ |
+ |
+int64_t MetricHeapNewExternal::Value() const { |
+ ASSERT(isolate() == Isolate::Current()); |
+ return isolate()->heap()->ExternalInWords(Heap::kNew) * kWordSize; |
+} |
+ |
+ |
+int64_t MetricIsolateCount::Value() const { |
+ return Isolate::IsolateListLength(); |
+} |
+ |
+#define VM_METRIC_VARIABLE(type, variable, name, unit) \ |
+ static type vm_metric_##variable##_; |
+ VM_METRIC_LIST(VM_METRIC_VARIABLE); |
+#undef VM_METRIC_VARIABLE |
+ |
+ |
+void Metric::InitOnce() { |
+#define VM_METRIC_INIT(type, variable, name, unit) \ |
+ vm_metric_##variable##_.Init(name, NULL, Metric::unit); |
+ VM_METRIC_LIST(VM_METRIC_INIT); |
+#undef VM_METRIC_INIT |
+} |
+ |
+} // namespace dart |