1// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/tags.h"
6
7#include "vm/isolate.h"
8#include "vm/json_stream.h"
9#include "vm/native_entry.h"
10#include "vm/object.h"
11#include "vm/runtime_entry.h"
12
13namespace dart {
14
15const char* VMTag::TagName(uword tag) {
16 if (IsNativeEntryTag(tag)) {
17 const uint8_t* native_reverse_lookup = NativeEntry::ResolveSymbol(tag);
18 if (native_reverse_lookup != NULL) {
19 return reinterpret_cast<const char*>(native_reverse_lookup);
20 }
21 return "Unknown native entry";
22 } else if (IsRuntimeEntryTag(tag)) {
23 const char* runtime_entry_name = RuntimeEntryTagName(tag);
24 ASSERT(runtime_entry_name != NULL);
25 return runtime_entry_name;
26 }
27 ASSERT(tag != kInvalidTagId);
28 ASSERT(tag < kNumVMTags);
29 const TagEntry& entry = entries_[tag];
30 ASSERT(entry.id == tag);
31 return entry.name;
32}
33
34bool VMTag::IsNativeEntryTag(uword tag) {
35 return (tag > kLastTagId) && !IsRuntimeEntryTag(tag);
36}
37
38bool VMTag::IsDartTag(uword id) {
39 return (id == kDartCompiledTagId) || (id == kDartInterpretedTagId);
40}
41
42bool VMTag::IsExitFrameTag(uword id) {
43 return (id != 0) && !IsDartTag(id) && (id != kIdleTagId) &&
44 (id != kVMTagId) && (id != kEmbedderTagId);
45}
46
47bool VMTag::IsRuntimeEntryTag(uword id) {
48 return RuntimeEntryTagName(id) != nullptr;
49}
50
51const char* VMTag::RuntimeEntryTagName(uword id) {
52 void* address = reinterpret_cast<void*>(id);
53
54#define CHECK_RUNTIME_ADDRESS(n) \
55 if (address == k##n##RuntimeEntry.function()) \
56 return k##n##RuntimeEntry.name();
57 RUNTIME_ENTRY_LIST(CHECK_RUNTIME_ADDRESS)
58#undef CHECK_RUNTIME_ADDRESS
59
60#define CHECK_LEAF_RUNTIME_ADDRESS(type, n, ...) \
61 if (address == k##n##RuntimeEntry.function()) \
62 return k##n##RuntimeEntry.name();
63 LEAF_RUNTIME_ENTRY_LIST(CHECK_LEAF_RUNTIME_ADDRESS)
64#undef CHECK_LEAF_RUNTIME_ADDRESS
65
66 return nullptr;
67}
68
69VMTag::TagEntry VMTag::entries_[] = {
70 {
71 "InvalidTag", kInvalidTagId,
72 },
73#define DEFINE_VM_TAG_ENTRY(tag) {"" #tag, k##tag##TagId},
74 VM_TAG_LIST(DEFINE_VM_TAG_ENTRY)
75#undef DEFINE_VM_TAG_ENTRY
76 {"kNumVMTags", kNumVMTags},
77};
78
79VMTagScope::VMTagScope(Thread* thread, uword tag, bool conditional_set)
80 : ThreadStackResource(thread) {
81 if (thread != NULL) {
82 ASSERT(isolate_group() != NULL);
83 previous_tag_ = thread->vm_tag();
84 if (conditional_set) {
85 thread->set_vm_tag(tag);
86 }
87 }
88}
89
90VMTagScope::~VMTagScope() {
91 if (thread() != NULL) {
92 ASSERT(isolate_group() != NULL);
93 thread()->set_vm_tag(previous_tag_);
94 }
95}
96
97VMTagCounters::VMTagCounters() {
98 for (intptr_t i = 0; i < VMTag::kNumVMTags; i++) {
99 counters_[i] = 0;
100 }
101}
102
103void VMTagCounters::Increment(uword tag) {
104 if (VMTag::IsRuntimeEntryTag(tag)) {
105 counters_[VMTag::kRuntimeTagId]++;
106 return;
107 } else if (tag > VMTag::kNumVMTags) {
108 // Assume native entry.
109 counters_[VMTag::kNativeTagId]++;
110 return;
111 }
112 ASSERT(tag != VMTag::kInvalidTagId);
113 ASSERT(tag < VMTag::kNumVMTags);
114 counters_[tag]++;
115}
116
117int64_t VMTagCounters::count(uword tag) {
118 ASSERT(tag != VMTag::kInvalidTagId);
119 ASSERT(tag < VMTag::kNumVMTags);
120 return counters_[tag];
121}
122
123#ifndef PRODUCT
124void VMTagCounters::PrintToJSONObject(JSONObject* obj) {
125 {
126 JSONArray arr(obj, "names");
127 for (intptr_t i = 1; i < VMTag::kNumVMTags; i++) {
128 arr.AddValue(VMTag::TagName(i));
129 }
130 }
131 {
132 JSONArray arr(obj, "counters");
133 for (intptr_t i = 1; i < VMTag::kNumVMTags; i++) {
134 arr.AddValue64(counters_[i]);
135 }
136 }
137}
138#endif // !PRODUCT
139
140const char* UserTags::TagName(uword tag_id) {
141 ASSERT(tag_id >= kUserTagIdOffset);
142 ASSERT(tag_id < kUserTagIdOffset + kMaxUserTags);
143 Zone* zone = Thread::Current()->zone();
144 const UserTag& tag = UserTag::Handle(zone, UserTag::FindTagById(tag_id));
145 ASSERT(!tag.IsNull());
146 const String& label = String::Handle(zone, tag.label());
147 return label.ToCString();
148}
149
150} // namespace dart
151