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