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