db-move: moved gnome-clocks from [testing] to [extra] (x86_64)
[arch-packages.git] / js38 / trunk / mozjs38-fix-tracelogger.patch
blob6798d24a31ecb367258b0a6da4390a4c3481edb7
1 # === Fix the SM38 tracelogger ===
2 # This patch is a squashed version of several patches that were adapted
3 # to fix failing hunks.
5 # Applied in the following order, they are:
6 # * https://bugzilla.mozilla.org/show_bug.cgi?id=1223767
7 # Assertion failure: i < size_, at js/src/vm/TraceLoggingTypes.h:210
8 # Also fix stop-information to make reduce.py work correctly.
9 # * https://bugzilla.mozilla.org/show_bug.cgi?id=1227914
10 # Limit the memory tracelogger can take.
11 # This causes tracelogger to flush data to the disk regularly and prevents out of
12 # memory issues if a lot of data gets logged.
13 # * https://bugzilla.mozilla.org/show_bug.cgi?id=1155618
14 # Fix tracelogger destructor that touches possibly uninitialised hash table.
15 # * https://bugzilla.mozilla.org/show_bug.cgi?id=1223636
16 # Don't treat extraTextId as containing only extra ids.
17 # This fixes an assertion failure: id == nextTextId at js/src/vm/TraceLoggingGraph.cpp
18 # * https://bugzilla.mozilla.org/show_bug.cgi?id=1227028
19 # Fix when to keep the payload of a TraceLogger event.
20 # This fixes an assertion failure: textId < uint32_t(1 << 31) at js/src/vm/TraceLoggingGraph.h
21 # * https://bugzilla.mozilla.org/show_bug.cgi?id=1266649
22 # Handle failing to add to pointermap gracefully.
23 # * https://bugzilla.mozilla.org/show_bug.cgi?id=1280648
24 # Don't cache based on pointers to movable GC things.
25 # * https://bugzilla.mozilla.org/show_bug.cgi?id=1224123
26 # Fix the use of LastEntryId in tracelogger.h.
27 # * https://bugzilla.mozilla.org/show_bug.cgi?id=1231170
28 # Use size in debugger instead of the current id to track last logged item.
29 # * https://bugzilla.mozilla.org/show_bug.cgi?id=1221844
30 # Move TraceLogger_Invalidation to LOG_ITEM.
31 # Add some debug checks to logTimestamp.
32 # * https://bugzilla.mozilla.org/show_bug.cgi?id=1255766
33 # Also mark resizing of memory.
34 # * https://bugzilla.mozilla.org/show_bug.cgi?id=1259403
35 # Only increase capacity by multiples of 2.
36 # Always make sure there are 3 free slots for events.
37 # ===
39 diff --git a/js/src/jit-test/tests/tracelogger/bug1231170.js b/js/src/jit-test/tests/tracelogger/bug1231170.js
40 new file mode 100644
41 index 0000000..023e93e
42 --- /dev/null
43 +++ b/js/src/jit-test/tests/tracelogger/bug1231170.js
44 @@ -0,0 +1,3 @@
45 +var du = new Debugger();
46 +if (typeof du.drainTraceLogger === "function")
47 + du.drainTraceLogger();
48 diff --git a/js/src/jit-test/tests/tracelogger/bug1266649.js b/js/src/jit-test/tests/tracelogger/bug1266649.js
49 new file mode 100644
50 index 0000000..81ae7ad
51 --- /dev/null
52 +++ b/js/src/jit-test/tests/tracelogger/bug1266649.js
53 @@ -0,0 +1,10 @@
55 +var du = new Debugger();
56 +if (typeof du.setupTraceLogger === "function" &&
57 + typeof oomTest === 'function')
59 + du.setupTraceLogger({
60 + Scripts: true
61 + })
62 + oomTest(() => function(){});
64 diff --git a/js/src/jit/Ion.cpp b/js/src/jit/Ion.cpp
65 index 93e2fda..09049d6 100644
66 --- a/js/src/jit/Ion.cpp
67 +++ b/js/src/jit/Ion.cpp
68 @@ -1055,6 +1055,8 @@ IonScript::Destroy(FreeOp* fop, IonScript* script)
70 script->destroyCaches();
71 script->unlinkFromRuntime(fop);
72 + // Frees the potential event we have set.
73 + script->traceLoggerScriptEvent_ = TraceLoggerEvent();
74 fop->free_(script);
77 diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp
78 index 26262fd..af7f313 100644
79 --- a/js/src/vm/Debugger.cpp
80 +++ b/js/src/vm/Debugger.cpp
81 @@ -369,10 +369,10 @@ Debugger::Debugger(JSContext* cx, NativeObject* dbg)
82 objects(cx),
83 environments(cx),
84 #ifdef NIGHTLY_BUILD
85 - traceLoggerLastDrainedId(0),
86 + traceLoggerLastDrainedSize(0),
87 traceLoggerLastDrainedIteration(0),
88 #endif
89 - traceLoggerScriptedCallsLastDrainedId(0),
90 + traceLoggerScriptedCallsLastDrainedSize(0),
91 traceLoggerScriptedCallsLastDrainedIteration(0)
93 assertSameCompartment(cx, dbg);
94 @@ -3907,9 +3907,9 @@ Debugger::drainTraceLogger(JSContext* cx, unsigned argc, Value* vp)
95 size_t num;
96 TraceLoggerThread* logger = TraceLoggerForMainThread(cx->runtime());
97 bool lostEvents = logger->lostEvents(dbg->traceLoggerLastDrainedIteration,
98 - dbg->traceLoggerLastDrainedId);
99 + dbg->traceLoggerLastDrainedSize);
100 EventEntry* events = logger->getEventsStartingAt(&dbg->traceLoggerLastDrainedIteration,
101 - &dbg->traceLoggerLastDrainedId,
102 + &dbg->traceLoggerLastDrainedSize,
103 &num);
105 RootedObject array(cx, NewDenseEmptyArray(cx));
106 @@ -4002,10 +4002,10 @@ Debugger::drainTraceLoggerScriptCalls(JSContext* cx, unsigned argc, Value* vp)
107 size_t num;
108 TraceLoggerThread* logger = TraceLoggerForMainThread(cx->runtime());
109 bool lostEvents = logger->lostEvents(dbg->traceLoggerScriptedCallsLastDrainedIteration,
110 - dbg->traceLoggerScriptedCallsLastDrainedId);
111 + dbg->traceLoggerScriptedCallsLastDrainedSize);
112 EventEntry* events = logger->getEventsStartingAt(
113 &dbg->traceLoggerScriptedCallsLastDrainedIteration,
114 - &dbg->traceLoggerScriptedCallsLastDrainedId,
115 + &dbg->traceLoggerScriptedCallsLastDrainedSize,
116 &num);
118 RootedObject array(cx, NewDenseEmptyArray(cx));
119 diff --git a/js/src/vm/Debugger.h b/js/src/vm/Debugger.h
120 index 8cac36a..c92d685 100644
121 --- a/js/src/vm/Debugger.h
122 +++ b/js/src/vm/Debugger.h
123 @@ -314,10 +314,10 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
124 * lost events.
126 #ifdef NIGHTLY_BUILD
127 - uint32_t traceLoggerLastDrainedId;
128 + uint32_t traceLoggerLastDrainedSize;
129 uint32_t traceLoggerLastDrainedIteration;
130 #endif
131 - uint32_t traceLoggerScriptedCallsLastDrainedId;
132 + uint32_t traceLoggerScriptedCallsLastDrainedSize;
133 uint32_t traceLoggerScriptedCallsLastDrainedIteration;
135 class FrameRange;
136 diff --git a/js/src/vm/TraceLogging.cpp b/js/src/vm/TraceLogging.cpp
137 index 6715b36..9766a6f 100644
138 --- a/js/src/vm/TraceLogging.cpp
139 +++ b/js/src/vm/TraceLogging.cpp
140 @@ -131,7 +131,7 @@ TraceLoggerThread::init()
142 if (!pointerMap.init())
143 return false;
144 - if (!extraTextId.init())
145 + if (!textIdPayloads.init())
146 return false;
147 if (!events.init())
148 return false;
149 @@ -185,10 +185,10 @@ TraceLoggerThread::~TraceLoggerThread()
150 graph = nullptr;
153 - for (TextIdHashMap::Range r = extraTextId.all(); !r.empty(); r.popFront())
154 - js_delete(r.front().value());
155 - extraTextId.finish();
156 - pointerMap.finish();
157 + if (textIdPayloads.initialized()) {
158 + for (TextIdHashMap::Range r = textIdPayloads.all(); !r.empty(); r.popFront())
159 + js_delete(r.front().value());
163 bool
164 @@ -287,7 +287,7 @@ TraceLoggerThread::eventText(uint32_t id)
165 if (id < TraceLogger_Last)
166 return TLTextIdString(static_cast<TraceLoggerTextId>(id));
168 - TextIdHashMap::Ptr p = extraTextId.lookup(id);
169 + TextIdHashMap::Ptr p = textIdPayloads.lookup(id);
170 MOZ_ASSERT(p);
172 return p->value()->string();
173 @@ -341,13 +341,15 @@ TraceLoggerThread::extractScriptDetails(uint32_t textId, const char** filename,
174 TraceLoggerEventPayload*
175 TraceLoggerThread::getOrCreateEventPayload(TraceLoggerTextId textId)
177 - TextIdHashMap::AddPtr p = extraTextId.lookupForAdd(textId);
178 - if (p)
179 + TextIdHashMap::AddPtr p = textIdPayloads.lookupForAdd(textId);
180 + if (p) {
181 + MOZ_ASSERT(p->value()->textId() == textId); // Sanity check.
182 return p->value();
185 TraceLoggerEventPayload* payload = js_new<TraceLoggerEventPayload>(textId, (char*)nullptr);
187 - if (!extraTextId.add(p, textId, payload))
188 + if (!textIdPayloads.add(p, textId, payload))
189 return nullptr;
191 return payload;
192 @@ -357,8 +359,10 @@ TraceLoggerEventPayload*
193 TraceLoggerThread::getOrCreateEventPayload(const char* text)
195 PointerHashMap::AddPtr p = pointerMap.lookupForAdd((const void*)text);
196 - if (p)
197 + if (p) {
198 + MOZ_ASSERT(p->value()->textId() < nextTextId); // Sanity check.
199 return p->value();
202 size_t len = strlen(text);
203 char* str = js_pod_malloc<char>(len + 1);
204 @@ -369,7 +373,7 @@ TraceLoggerThread::getOrCreateEventPayload(const char* text)
205 MOZ_ASSERT(ret == len);
206 MOZ_ASSERT(strlen(str) == len);
208 - uint32_t textId = extraTextId.count() + TraceLogger_Last;
209 + uint32_t textId = nextTextId;
211 TraceLoggerEventPayload* payload = js_new<TraceLoggerEventPayload>(textId, str);
212 if (!payload) {
213 @@ -377,17 +381,19 @@ TraceLoggerThread::getOrCreateEventPayload(const char* text)
214 return nullptr;
217 - if (!extraTextId.putNew(textId, payload)) {
218 + if (!textIdPayloads.putNew(textId, payload)) {
219 js_delete(payload);
220 return nullptr;
223 - if (!pointerMap.add(p, text, payload))
224 - return nullptr;
226 if (graph.get())
227 graph->addTextId(textId, str);
229 + nextTextId++;
231 + if (!pointerMap.add(p, text, payload))
232 + return nullptr;
234 return payload;
237 @@ -407,9 +413,14 @@ TraceLoggerThread::getOrCreateEventPayload(TraceLoggerTextId type, const char* f
238 if (!traceLoggerState->isTextIdEnabled(type))
239 return getOrCreateEventPayload(type);
241 - PointerHashMap::AddPtr p = pointerMap.lookupForAdd(ptr);
242 - if (p)
243 - return p->value();
244 + PointerHashMap::AddPtr p;
245 + if (ptr) {
246 + p = pointerMap.lookupForAdd(ptr);
247 + if (p) {
248 + MOZ_ASSERT(p->value()->textId() < nextTextId); // Sanity check.
249 + return p->value();
253 // Compute the length of the string to create.
254 size_t lenFilename = strlen(filename);
255 @@ -428,24 +439,28 @@ TraceLoggerThread::getOrCreateEventPayload(TraceLoggerTextId type, const char* f
256 MOZ_ASSERT(ret == len);
257 MOZ_ASSERT(strlen(str) == len);
259 - uint32_t textId = extraTextId.count() + TraceLogger_Last;
260 + uint32_t textId = nextTextId;
261 TraceLoggerEventPayload* payload = js_new<TraceLoggerEventPayload>(textId, str);
262 if (!payload) {
263 js_free(str);
264 return nullptr;
267 - if (!extraTextId.putNew(textId, payload)) {
268 + if (!textIdPayloads.putNew(textId, payload)) {
269 js_delete(payload);
270 return nullptr;
273 - if (!pointerMap.add(p, ptr, payload))
274 - return nullptr;
276 if (graph.get())
277 graph->addTextId(textId, str);
279 + nextTextId++;
281 + if (ptr) {
282 + if (!pointerMap.add(p, ptr, payload))
283 + return nullptr;
286 return payload;
289 @@ -453,14 +468,14 @@ TraceLoggerEventPayload*
290 TraceLoggerThread::getOrCreateEventPayload(TraceLoggerTextId type, JSScript* script)
292 return getOrCreateEventPayload(type, script->filename(), script->lineno(), script->column(),
293 - script);
294 + nullptr);
297 TraceLoggerEventPayload*
298 TraceLoggerThread::getOrCreateEventPayload(TraceLoggerTextId type,
299 const JS::ReadOnlyCompileOptions& script)
301 - return getOrCreateEventPayload(type, script.filename(), script.lineno, script.column, &script);
302 + return getOrCreateEventPayload(type, script.filename(), script.lineno, script.column, nullptr);
305 void
306 @@ -485,7 +500,7 @@ TraceLoggerThread::startEvent(uint32_t id)
307 if (!traceLoggerState->isTextIdEnabled(id))
308 return;
310 - logTimestamp(id);
311 + log(id);
314 void
315 @@ -510,7 +525,7 @@ TraceLoggerThread::stopEvent(uint32_t id)
316 if (!traceLoggerState->isTextIdEnabled(id))
317 return;
319 - logTimestamp(TraceLogger_Stop);
320 + log(TraceLogger_Stop);
323 void
324 @@ -522,23 +537,57 @@ TraceLoggerThread::logTimestamp(TraceLoggerTextId id)
325 void
326 TraceLoggerThread::logTimestamp(uint32_t id)
328 + MOZ_ASSERT(id > TraceLogger_LastTreeItem && id < TraceLogger_Last);
329 + log(id);
332 +void
333 +TraceLoggerThread::log(uint32_t id)
335 if (enabled == 0)
336 return;
338 MOZ_ASSERT(traceLoggerState);
339 - if (!events.ensureSpaceBeforeAdd()) {
341 + // We request for 3 items to add, since if we don't have enough room
342 + // we record the time it took to make more place. To log this information
343 + // we need 2 extra free entries.
344 + if (!events.hasSpaceForAdd(3)) {
345 uint64_t start = rdtsc() - traceLoggerState->startupTime;
347 - if (graph.get())
348 - graph->log(events);
349 + if (!events.ensureSpaceBeforeAdd(3)) {
350 + if (graph.get())
351 + graph->log(events);
353 + iteration_++;
354 + events.clear();
356 + // Remove the item in the pointerMap for which the payloads
357 + // have no uses anymore
358 + for (PointerHashMap::Enum e(pointerMap); !e.empty(); e.popFront()) {
359 + if (e.front().value()->uses() != 0)
360 + continue;
362 + TextIdHashMap::Ptr p = textIdPayloads.lookup(e.front().value()->textId());
363 + MOZ_ASSERT(p);
364 + textIdPayloads.remove(p);
366 + e.removeFront();
369 - iteration_++;
370 - events.clear();
371 + // Free all payloads that have no uses anymore.
372 + for (TextIdHashMap::Enum e(textIdPayloads); !e.empty(); e.popFront()) {
373 + if (e.front().value()->uses() == 0) {
374 + js_delete(e.front().value());
375 + e.removeFront();
380 // Log the time it took to flush the events as being from the
381 // Tracelogger.
382 if (graph.get()) {
383 - MOZ_ASSERT(events.capacity() > 2);
384 + MOZ_ASSERT(events.hasSpaceForAdd(2));
385 EventEntry& entryStart = events.pushUninitialized();
386 entryStart.time = start;
387 entryStart.textId = TraceLogger_Internal;
388 @@ -548,13 +597,6 @@ TraceLoggerThread::logTimestamp(uint32_t id)
389 entryStop.textId = TraceLogger_Stop;
392 - // Free all TextEvents that have no uses anymore.
393 - for (TextIdHashMap::Enum e(extraTextId); !e.empty(); e.popFront()) {
394 - if (e.front().value()->uses() == 0) {
395 - js_delete(e.front().value());
396 - e.removeFront();
401 uint64_t time = rdtsc() - traceLoggerState->startupTime;
402 @@ -956,3 +998,16 @@ TraceLoggerEvent::~TraceLoggerEvent()
403 if (payload_)
404 payload_->release();
407 +TraceLoggerEvent&
408 +TraceLoggerEvent::operator=(const TraceLoggerEvent& other)
410 + if (hasPayload())
411 + payload()->release();
412 + if (other.hasPayload())
413 + other.payload()->use();
415 + payload_ = other.payload_;
417 + return *this;
419 diff --git a/js/src/vm/TraceLogging.h b/js/src/vm/TraceLogging.h
420 index a124dcb..91a1eb0 100644
421 --- a/js/src/vm/TraceLogging.h
422 +++ b/js/src/vm/TraceLogging.h
423 @@ -110,6 +110,9 @@ class TraceLoggerEvent {
424 bool hasPayload() const {
425 return !!payload_;
428 + TraceLoggerEvent& operator=(const TraceLoggerEvent& other);
429 + TraceLoggerEvent(const TraceLoggerEvent& event) = delete;
433 @@ -130,6 +133,10 @@ class TraceLoggerEventPayload {
434 uses_(0)
437 + ~TraceLoggerEventPayload() {
438 + MOZ_ASSERT(uses_ == 0);
441 uint32_t textId() {
442 return textId_;
444 @@ -166,7 +173,8 @@ class TraceLoggerThread
445 mozilla::UniquePtr<TraceLoggerGraph> graph;
447 PointerHashMap pointerMap;
448 - TextIdHashMap extraTextId;
449 + TextIdHashMap textIdPayloads;
450 + uint32_t nextTextId;
452 ContinuousSpace<EventEntry> events;
454 @@ -181,6 +189,7 @@ class TraceLoggerThread
455 : enabled(0),
456 failed(false),
457 graph(),
458 + nextTextId(TraceLogger_Last),
459 iteration_(0),
460 top(nullptr)
462 @@ -195,22 +204,22 @@ class TraceLoggerThread
463 bool enable(JSContext* cx);
464 bool disable();
466 - // Given the previous iteration and lastEntryId, return an array of events
467 + // Given the previous iteration and size, return an array of events
468 // (there could be lost events). At the same time update the iteration and
469 - // lastEntry and gives back how many events there are.
470 - EventEntry* getEventsStartingAt(uint32_t* lastIteration, uint32_t* lastEntryId, size_t* num) {
471 + // size and gives back how many events there are.
472 + EventEntry* getEventsStartingAt(uint32_t* lastIteration, uint32_t* lastSize, size_t* num) {
473 EventEntry* start;
474 if (iteration_ == *lastIteration) {
475 - MOZ_ASSERT(events.lastEntryId() >= *lastEntryId);
476 - *num = events.lastEntryId() - *lastEntryId;
477 - start = events.data() + *lastEntryId + 1;
478 + MOZ_ASSERT(*lastSize <= events.size());
479 + *num = events.size() - *lastSize;
480 + start = events.data() + *lastSize;
481 } else {
482 - *num = events.lastEntryId() + 1;
483 + *num = events.size();
484 start = events.data();
487 *lastIteration = iteration_;
488 - *lastEntryId = events.lastEntryId();
489 + *lastSize = events.size();
490 return start;
493 @@ -220,16 +229,16 @@ class TraceLoggerThread
494 const char** lineno, size_t* lineno_len, const char** colno,
495 size_t* colno_len);
497 - bool lostEvents(uint32_t lastIteration, uint32_t lastEntryId) {
498 + bool lostEvents(uint32_t lastIteration, uint32_t lastSize) {
499 // If still logging in the same iteration, there are no lost events.
500 if (lastIteration == iteration_) {
501 - MOZ_ASSERT(lastEntryId <= events.lastEntryId());
502 + MOZ_ASSERT(lastSize <= events.size());
503 return false;
506 - // When proceeded to the next iteration and lastEntryId points to
507 - // the maximum capacity there are no logs that are lost.
508 - if (lastIteration + 1 == iteration_ && lastEntryId == events.capacity())
509 + // If we are in a consecutive iteration we are only sure we didn't lose any events,
510 + // when the lastSize equals the maximum size 'events' can get.
511 + if (lastIteration == iteration_ - 1 && lastSize == events.maxSize())
512 return false;
514 return true;
515 @@ -268,6 +277,7 @@ class TraceLoggerThread
516 void stopEvent(uint32_t id);
517 private:
518 void stopEvent();
519 + void log(uint32_t id);
521 public:
522 static unsigned offsetOfEnabled() {
523 diff --git a/js/src/vm/TraceLoggingGraph.cpp b/js/src/vm/TraceLoggingGraph.cpp
524 index d1b7f2e..a4eb273 100644
525 --- a/js/src/vm/TraceLoggingGraph.cpp
526 +++ b/js/src/vm/TraceLoggingGraph.cpp
527 @@ -276,7 +276,7 @@ TraceLoggerGraph::flush()
528 if (bytesWritten < tree.size())
529 return false;
531 - treeOffset += tree.lastEntryId();
532 + treeOffset += tree.size();
533 tree.clear();
536 @@ -359,7 +359,7 @@ TraceLoggerGraph::startEventInternal(uint32_t id, uint64_t timestamp)
538 if (parent.lastChildId() == 0) {
539 MOZ_ASSERT(!entry.hasChildren());
540 - MOZ_ASSERT(parent.treeId() == tree.lastEntryId() + treeOffset);
541 + MOZ_ASSERT(parent.treeId() == treeOffset + tree.size() - 1);
543 if (!updateHasChildren(parent.treeId()))
544 return false;
545 diff --git a/js/src/vm/TraceLoggingTypes.h b/js/src/vm/TraceLoggingTypes.h
546 index f1c9d0c..10b76d6 100644
547 --- a/js/src/vm/TraceLoggingTypes.h
548 +++ b/js/src/vm/TraceLoggingTypes.h
549 @@ -21,7 +21,6 @@
550 _(Internal) \
551 _(Interpreter) \
552 _(InlinedScripts) \
553 - _(Invalidation) \
554 _(IonCompilation) \
555 _(IonCompilationPaused) \
556 _(IonLinking) \
557 @@ -60,6 +59,7 @@
559 #define TRACELOGGER_LOG_ITEMS(_) \
560 _(Bailout) \
561 + _(Invalidation) \
562 _(Disable) \
563 _(Enable) \
564 _(Stop)
565 @@ -130,6 +130,9 @@ class ContinuousSpace {
566 uint32_t size_;
567 uint32_t capacity_;
569 + // The maximum amount of ram memory a continuous space structure can take (in bytes).
570 + static const uint32_t LIMIT = 200 * 1024 * 1024;
572 public:
573 ContinuousSpace ()
574 : data_(nullptr)
575 @@ -151,6 +154,10 @@ class ContinuousSpace {
576 data_ = nullptr;
579 + static uint32_t maxSize() {
580 + return LIMIT / sizeof(T);
583 T* data() {
584 return data_;
586 @@ -187,11 +194,14 @@ class ContinuousSpace {
587 if (hasSpaceForAdd(count))
588 return true;
590 + // Limit the size of a continuous buffer.
591 + if (size_ + count > maxSize())
592 + return false;
594 uint32_t nCapacity = capacity_ * 2;
595 - if (size_ + count > nCapacity)
596 - nCapacity = size_ + count;
597 - T* entries = (T*) js_realloc(data_, nCapacity * sizeof(T));
598 + nCapacity = (nCapacity < maxSize()) ? nCapacity : maxSize();
600 + T* entries = (T*) js_realloc(data_, nCapacity * sizeof(T));
601 if (!entries)
602 return false;