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 | |
13 | namespace dart { |
14 | |
15 | const 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 | |
34 | bool VMTag::IsNativeEntryTag(uword tag) { |
35 | return (tag > kLastTagId) && !IsRuntimeEntryTag(tag); |
36 | } |
37 | |
38 | bool VMTag::IsDartTag(uword id) { |
39 | return (id == kDartCompiledTagId) || (id == kDartInterpretedTagId); |
40 | } |
41 | |
42 | bool VMTag::IsExitFrameTag(uword id) { |
43 | return (id != 0) && !IsDartTag(id) && (id != kIdleTagId) && |
44 | (id != kVMTagId) && (id != kEmbedderTagId); |
45 | } |
46 | |
47 | bool VMTag::IsRuntimeEntryTag(uword id) { |
48 | return RuntimeEntryTagName(id) != nullptr; |
49 | } |
50 | |
51 | const 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 | |
69 | VMTag::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 | |
79 | VMTagScope::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 | |
90 | VMTagScope::~VMTagScope() { |
91 | if (thread() != NULL) { |
92 | ASSERT(isolate_group() != NULL); |
93 | thread()->set_vm_tag(previous_tag_); |
94 | } |
95 | } |
96 | |
97 | VMTagCounters::VMTagCounters() { |
98 | for (intptr_t i = 0; i < VMTag::kNumVMTags; i++) { |
99 | counters_[i] = 0; |
100 | } |
101 | } |
102 | |
103 | void 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 | |
117 | int64_t VMTagCounters::count(uword tag) { |
118 | ASSERT(tag != VMTag::kInvalidTagId); |
119 | ASSERT(tag < VMTag::kNumVMTags); |
120 | return counters_[tag]; |
121 | } |
122 | |
123 | #ifndef PRODUCT |
124 | void 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 | |
140 | const 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 | |