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