Flutter Engine
The Flutter Engine
tags.cc
Go to the documentation of this file.
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 "platform/utils.h"
8#include "vm/isolate.h"
9#include "vm/json_stream.h"
10#include "vm/native_entry.h"
11#include "vm/object.h"
12#include "vm/runtime_entry.h"
13
14namespace dart {
15
16MallocGrowableArray<const char*> UserTags::subscribed_tags_(4);
17Mutex* UserTags::subscribed_tags_lock_ = nullptr;
18
19const char* VMTag::TagName(uword tag) {
20 if (IsNativeEntryTag(tag)) {
21 const uint8_t* native_reverse_lookup = NativeEntry::ResolveSymbol(tag);
22 if (native_reverse_lookup != nullptr) {
23 return reinterpret_cast<const char*>(native_reverse_lookup);
24 }
25 return "Unknown native entry";
26 } else if (IsRuntimeEntryTag(tag)) {
27 const char* runtime_entry_name = RuntimeEntryTagName(tag);
28 ASSERT(runtime_entry_name != nullptr);
29 return runtime_entry_name;
30 }
31 ASSERT(tag != kInvalidTagId);
32 ASSERT(tag < kNumVMTags);
33 const TagEntry& entry = entries_[tag];
34 ASSERT(entry.id == tag);
35 return entry.name;
36}
37
39 return (tag > kLastTagId) && !IsRuntimeEntryTag(tag);
40}
41
43 return (id != 0) && !IsDartTag(id) && (id != kIdleTagId) &&
44 (id != kVMTagId) && (id != kEmbedderTagId);
45}
46
48 return RuntimeEntryTagName(id) != nullptr;
49}
50
52 const void* address = reinterpret_cast<const void*>(id);
53
54#define CHECK_RUNTIME_ADDRESS(n) \
55 if (address == k##n##RuntimeEntry.function()) \
56 return k##n##RuntimeEntry.name();
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();
64#undef CHECK_LEAF_RUNTIME_ADDRESS
65
66 return nullptr;
67}
68
69const VMTag::TagEntry VMTag::entries_[] = {
70 {
71 "InvalidTag",
72 kInvalidTagId,
73 },
74#define DEFINE_VM_TAG_ENTRY(tag) {"" #tag, k##tag##TagId},
76#undef DEFINE_VM_TAG_ENTRY
77 {"kNumVMTags", kNumVMTags},
78};
79
80VMTagScope::VMTagScope(Thread* thread, uword tag, bool conditional_set)
81 : ThreadStackResource(thread) {
82 if (thread != nullptr) {
83 ASSERT(isolate_group() != nullptr);
84 previous_tag_ = thread->vm_tag();
85 if (conditional_set) {
86 thread->set_vm_tag(tag);
87 }
88 }
89}
90
92 if (thread() != nullptr) {
93 ASSERT(isolate_group() != nullptr);
94 thread()->set_vm_tag(previous_tag_);
95 }
96}
97
99 for (intptr_t i = 0; i < VMTag::kNumVMTags; i++) {
100 counters_[i] = 0;
101 }
102}
103
106 if (tag < VMTag::kNumVMTags) {
107 counters_[tag]++;
108 } else if (VMTag::IsRuntimeEntryTag(tag)) {
109 counters_[VMTag::kRuntimeTagId]++;
110 } else {
111 // Assume native entry.
112 counters_[VMTag::kNativeTagId]++;
113 }
114}
115
119 return counters_[tag];
120}
121
122#ifndef PRODUCT
124 {
125 JSONArray arr(obj, "names");
126 for (intptr_t i = 1; i < VMTag::kNumVMTags; i++) {
128 }
129 }
130 {
131 JSONArray arr(obj, "counters");
132 for (intptr_t i = 1; i < VMTag::kNumVMTags; i++) {
133 arr.AddValue64(counters_[i]);
134 }
135 }
136}
137#endif // !PRODUCT
138
139const char* UserTags::TagName(uword tag_id) {
140 ASSERT(tag_id >= kUserTagIdOffset);
142 const Thread* thread = Thread::Current();
143 Zone* zone = thread->zone();
144 Isolate* isolate = thread->isolate();
145 const UserTag& tag =
146 UserTag::Handle(zone, UserTag::FindTagById(isolate, tag_id));
147 ASSERT(!tag.IsNull());
148 const String& label = String::Handle(zone, tag.label());
149 return label.ToCString();
150}
151
152void UserTags::AddStreamableTagName(const char* tag) {
153 MutexLocker ml(subscribed_tags_lock_);
154 // Check this tag isn't already in the subscription list.
155 for (intptr_t i = 0; i < subscribed_tags_.length(); ++i) {
156 if (strcmp(tag, subscribed_tags_.At(i)) == 0) {
157 return;
158 }
159 }
160 subscribed_tags_.Add(Utils::StrDup(tag));
161}
162
164 MutexLocker ml(subscribed_tags_lock_);
165 bool found = false;
166 for (intptr_t i = 0; i < subscribed_tags_.length(); ++i) {
167 if (strcmp(tag, subscribed_tags_.At(i)) == 0) {
168 free(const_cast<char*>(subscribed_tags_.At(i)));
169 subscribed_tags_.RemoveAt(i);
170 found = true;
171 break;
172 }
173 }
174 ASSERT(found);
175}
176
177bool UserTags::IsTagNameStreamable(const char* tag) {
178 MutexLocker ml(subscribed_tags_lock_);
179 for (intptr_t i = 0; i < subscribed_tags_.length(); ++i) {
180 if (strcmp(tag, subscribed_tags_.At(i)) == 0) {
181 return true;
182 }
183 }
184 return false;
185}
186
188 subscribed_tags_lock_ = new Mutex();
189}
190
192 {
193 MutexLocker ml(subscribed_tags_lock_);
194 for (intptr_t i = 0; i < subscribed_tags_.length(); ++i) {
195 free(const_cast<char*>(subscribed_tags_.At(i)));
196 }
197 subscribed_tags_.Clear();
198 }
199 delete subscribed_tags_lock_;
200 subscribed_tags_lock_ = nullptr;
201}
202
203} // namespace dart
void Add(const T &value)
const T & At(intptr_t index) const
void RemoveAt(intptr_t i)
intptr_t length() const
void AddValue64(int64_t i) const
Definition: json_stream.h:496
void AddValue(bool b) const
Definition: json_stream.h:494
static const uint8_t * ResolveSymbol(uword pc)
Definition: native_entry.cc:73
bool IsNull() const
Definition: object.h:363
static Object & Handle()
Definition: object.h:407
static const char * ToCString(Thread *thread, StringPtr ptr)
Definition: object.cc:24126
IsolateGroup * isolate_group() const
Zone * zone() const
Definition: thread_state.h:37
void set_vm_tag(uword tag)
Definition: thread.h:822
uword vm_tag() const
Definition: thread.h:821
static Thread * Current()
Definition: thread.h:362
Isolate * isolate() const
Definition: thread.h:534
static UserTagPtr FindTagById(const Isolate *isolate, uword tag_id)
Definition: object.cc:27053
StringPtr label() const
Definition: object.h:13168
static const char * TagName(uword tag_id)
Definition: tags.cc:139
static constexpr intptr_t kMaxUserTags
Definition: tags.h:110
static bool IsTagNameStreamable(const char *tag)
Definition: tags.cc:177
static void RemoveStreamableTagName(const char *tag)
Definition: tags.cc:163
static void Cleanup()
Definition: tags.cc:191
static constexpr uword kUserTagIdOffset
Definition: tags.h:111
static void AddStreamableTagName(const char *tag)
Definition: tags.cc:152
static void Init()
Definition: tags.cc:187
static char * StrDup(const char *s)
int64_t count(uword tag)
Definition: tags.cc:116
void Increment(uword tag)
Definition: tags.cc:104
void PrintToJSONObject(JSONObject *obj)
Definition: tags.cc:123
VMTagScope(Thread *thread, uword tag, bool conditional_set=true)
Definition: tags.cc:80
static bool IsExitFrameTag(uword id)
Definition: tags.cc:42
static const char * RuntimeEntryTagName(uword id)
Definition: tags.cc:51
static bool IsNativeEntryTag(uword id)
Definition: tags.cc:38
@ kLastTagId
Definition: tags.h:56
@ kInvalidTagId
Definition: tags.h:38
@ kNumVMTags
Definition: tags.h:42
static bool IsRuntimeEntryTag(uword id)
Definition: tags.cc:47
static const char * TagName(uword id)
Definition: tags.cc:19
static bool IsDartTag(uword id)
Definition: tags.h:64
#define ASSERT(E)
Definition: dart_vm.cc:33
uintptr_t uword
Definition: globals.h:501
#define RUNTIME_ENTRY_LIST(V)
#define LEAF_RUNTIME_ENTRY_LIST(V)
#define CHECK_LEAF_RUNTIME_ADDRESS(type, n,...)
#define DEFINE_VM_TAG_ENTRY(tag)
#define CHECK_RUNTIME_ADDRESS(n)
#define VM_TAG_LIST(V)
Definition: tags.h:19
const uintptr_t id