1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #ifndef TraceLoggingTypes_h
8 #define TraceLoggingTypes_h
9
10 #include "mozilla/Assertions.h"
11 #include "mozilla/MemoryReporting.h"
12 #include "mozilla/TimeStamp.h"
13
14 #include <cstddef>
15 #include <cstdint>
16
17 #include "js/AllocPolicy.h"
18 #include "js/Utility.h"
19
20 class JSLinearString;
21
22 // Tree items, meaning they have a start and stop and form a nested tree.
23 #define TRACELOGGER_TREE_ITEMS(_) \
24 _(AnnotateScripts) \
25 _(Baseline) \
26 _(BaselineCompilation) \
27 _(Engine) \
28 _(GC) \
29 _(GCAllocation) \
30 _(GCSweeping) \
31 _(GCFree) \
32 _(Interpreter) \
33 _(InlinedScripts) \
34 _(IonAnalysis) \
35 _(IonCompilation) \
36 _(IonLinking) \
37 _(IonMonkey) \
38 _(IrregexpCompile) \
39 _(IrregexpExecute) \
40 _(MinorGC) \
41 _(Frontend) \
42 _(ParsingFull) \
43 _(ParsingSyntax) \
44 _(BytecodeEmission) \
45 _(BytecodeFoldConstants) \
46 _(BytecodeNameFunctions) \
47 _(DecodeScript) \
48 _(DecodeFunction) \
49 _(EncodeScript) \
50 _(EncodeFunction) \
51 _(Scripts) \
52 _(VM) \
53 _(CompressSource) \
54 _(WasmCompilation) \
55 _(Call) \
56 \
57 /* Specific passes during ion compilation */ \
58 _(PruneUnusedBranches) \
59 _(FoldTests) \
60 _(FoldEmptyBlocks) \
61 _(SplitCriticalEdges) \
62 _(RenumberBlocks) \
63 _(ScalarReplacement) \
64 _(DominatorTree) \
65 _(PhiAnalysis) \
66 _(MakeLoopsContiguous) \
67 _(ApplyTypes) \
68 _(EagerSimdUnbox) \
69 _(AliasAnalysis) \
70 _(GVN) \
71 _(LICM) \
72 _(RangeAnalysis) \
73 _(LoopUnrolling) \
74 _(Sink) \
75 _(FoldLoadsWithUnbox) \
76 _(RemoveUnnecessaryBitops) \
77 _(FoldLinearArithConstants) \
78 _(EffectiveAddressAnalysis) \
79 _(AlignmentMaskAnalysis) \
80 _(EliminateDeadCode) \
81 _(ReorderInstructions) \
82 _(EdgeCaseAnalysis) \
83 _(EliminateRedundantChecks) \
84 _(AddKeepAliveInstructions) \
85 _(GenerateLIR) \
86 _(RegisterAllocation) \
87 _(GenerateCode) \
88 _(IonBuilderRestartLoop) \
89 _(VMSpecific)
90
91 // Log items, with timestamp only.
92 #define TRACELOGGER_LOG_ITEMS(_) \
93 _(Bailout) \
94 _(Invalidation) \
95 _(Disable) \
96 _(Enable) \
97 _(Stop)
98
99 // Predefined IDs for common operations. These IDs can be used
100 // without using TraceLogCreateTextId, because there are already created.
101 enum TraceLoggerTextId {
102 TraceLogger_Error = 0,
103 TraceLogger_Internal,
104 #define DEFINE_TEXT_ID(textId) TraceLogger_##textId,
105 TRACELOGGER_TREE_ITEMS(DEFINE_TEXT_ID) TraceLogger_TreeItemEnd,
106 TRACELOGGER_LOG_ITEMS(DEFINE_TEXT_ID)
107 #undef DEFINE_TEXT_ID
108 TraceLogger_Last
109 };
110
TLTextIdString(TraceLoggerTextId id)111 inline const char* TLTextIdString(TraceLoggerTextId id) {
112 switch (id) {
113 case TraceLogger_Error:
114 return "TraceLogger failed to process text";
115 case TraceLogger_Internal:
116 case TraceLogger_TreeItemEnd:
117 return "TraceLogger internal event";
118 #define NAME(textId) \
119 case TraceLogger_##textId: \
120 return #textId;
121 TRACELOGGER_TREE_ITEMS(NAME)
122 TRACELOGGER_LOG_ITEMS(NAME)
123 #undef NAME
124 default:
125 MOZ_CRASH();
126 }
127 }
128
129 uint32_t TLStringToTextId(JSLinearString* str);
130
131 // Return whether a given item id can be enabled/disabled.
TLTextIdIsTogglable(uint32_t id)132 inline bool TLTextIdIsTogglable(uint32_t id) {
133 if (id == TraceLogger_Error) {
134 return false;
135 }
136 if (id == TraceLogger_Internal) {
137 return false;
138 }
139 if (id == TraceLogger_Stop) {
140 return false;
141 }
142 // Actually never used. But added here so it doesn't show as toggle
143 if (id == TraceLogger_TreeItemEnd) {
144 return false;
145 }
146 if (id == TraceLogger_Last) {
147 return false;
148 }
149 // Cannot toggle the logging of one engine on/off, because at the stop
150 // event it is sometimes unknown which engine was running.
151 if (id == TraceLogger_IonMonkey || id == TraceLogger_Baseline ||
152 id == TraceLogger_Interpreter) {
153 return false;
154 }
155 return true;
156 }
157
TLTextIdIsEnumEvent(uint32_t id)158 inline bool TLTextIdIsEnumEvent(uint32_t id) { return id < TraceLogger_Last; }
159
TLTextIdIsScriptEvent(uint32_t id)160 inline bool TLTextIdIsScriptEvent(uint32_t id) {
161 return !TLTextIdIsEnumEvent(id);
162 }
163
TLTextIdIsTreeEvent(uint32_t id)164 inline bool TLTextIdIsTreeEvent(uint32_t id) {
165 // Everything between TraceLogger_Error and TraceLogger_TreeItemEnd are tree
166 // events and atm also every custom event.
167 return (id > TraceLogger_Error && id < TraceLogger_TreeItemEnd) ||
168 id >= TraceLogger_Last;
169 }
170
TLTextIdIsLogEvent(uint32_t id)171 inline bool TLTextIdIsLogEvent(uint32_t id) {
172 // These id's do not have start & stop events.
173 return (id > TraceLogger_TreeItemEnd && id < TraceLogger_Last);
174 }
175
TLTextIdIsInternalEvent(uint32_t id)176 inline bool TLTextIdIsInternalEvent(uint32_t id) {
177 // Id's used for bookkeeping. Does not correspond to real events.
178 return (id == TraceLogger_Error || id == TraceLogger_Last ||
179 id == TraceLogger_TreeItemEnd || id == TraceLogger_Internal ||
180 id == TraceLogger_Stop);
181 }
182
183 template <class T>
184 class ContinuousSpace {
185 T* data_;
186 uint32_t size_;
187 uint32_t capacity_;
188
189 // The maximum number of bytes of RAM a continuous space structure can take.
190 static const uint32_t LIMIT = 200 * 1024 * 1024;
191
192 public:
ContinuousSpace()193 ContinuousSpace() : data_(nullptr), size_(0), capacity_(0) {}
194
init()195 bool init() {
196 capacity_ = 64;
197 size_ = 0;
198 data_ = js_pod_malloc<T>(capacity_);
199 if (!data_) {
200 return false;
201 }
202
203 return true;
204 }
205
~ContinuousSpace()206 ~ContinuousSpace() {
207 js_free(data_);
208 data_ = nullptr;
209 }
210
maxSize()211 static uint32_t maxSize() { return LIMIT / sizeof(T); }
212
data()213 T* data() { return data_; }
214
capacity()215 uint32_t capacity() const { return capacity_; }
216
size()217 uint32_t size() const { return size_; }
218
empty()219 bool empty() const { return size_ == 0; }
220
lastEntryId()221 uint32_t lastEntryId() const {
222 MOZ_ASSERT(!empty());
223 return size_ - 1;
224 }
225
lastEntry()226 T& lastEntry() { return data()[lastEntryId()]; }
227
228 bool hasSpaceForAdd(uint32_t count = 1) {
229 if (size_ + count <= capacity_) {
230 return true;
231 }
232 return false;
233 }
234
235 bool ensureSpaceBeforeAdd(uint32_t count = 1) {
236 MOZ_ASSERT(data_);
237 if (hasSpaceForAdd(count)) {
238 return true;
239 }
240
241 // Limit the size of a continuous buffer.
242 if (size_ + count > maxSize()) {
243 return false;
244 }
245
246 uint32_t nCapacity = capacity_ * 2;
247 nCapacity = (nCapacity < maxSize()) ? nCapacity : maxSize();
248
249 T* entries = js_pod_realloc<T>(data_, capacity_, nCapacity);
250 if (!entries) {
251 return false;
252 }
253
254 data_ = entries;
255 capacity_ = nCapacity;
256
257 return true;
258 }
259
260 T& operator[](size_t i) {
261 MOZ_ASSERT(i < size_);
262 return data()[i];
263 }
264
push(T & data)265 void push(T& data) {
266 MOZ_ASSERT(size_ < capacity_);
267 data()[size_++] = data;
268 }
269
pushUninitialized()270 T& pushUninitialized() {
271 MOZ_ASSERT(size_ < capacity_);
272 return data()[size_++];
273 }
274
pop()275 void pop() {
276 MOZ_ASSERT(!empty());
277 size_--;
278 }
279
clear()280 void clear() { size_ = 0; }
281
reset()282 bool reset() {
283 size_t oldCapacity = data_ ? capacity_ : 0;
284 capacity_ = 64;
285 size_ = 0;
286 data_ = js_pod_realloc<T>(data_, oldCapacity, capacity_);
287
288 if (!data_) {
289 return false;
290 }
291
292 return true;
293 }
294
sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)295 size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
296 return mallocSizeOf(data_);
297 }
298 };
299
300 // The layout of the event log in memory and in the log file.
301 // Readable by JS using TypedArrays.
302 struct EventEntry {
303 mozilla::TimeStamp time;
304 uint32_t textId;
EventEntryEventEntry305 EventEntry() : textId(0) {}
306 };
307
308 #endif /* TraceLoggingTypes_h */
309