
# HG changeset patch
# User Hannes Verschore <hv1989@gmail.com>
# Date 1450481544 18000
# Node ID 6bc6cbcf117e2e230ab189c5d3f244f30a294232
# Parent  e33b2a6d17d48e38f0a6f67ce1e4e65d73ed797e
Bug 1231170: TraceLogger - Use size in debugger instead of the current id to track last logged item, r=bbouvier

diff --git a/js/src/jit-test/tests/tracelogger/bug1231170.js b/js/src/jit-test/tests/tracelogger/bug1231170.js
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/tracelogger/bug1231170.js
@@ -0,0 +1,3 @@
+var du = new Debugger();
+if (typeof du.drainTraceLogger === "function")
+    du.drainTraceLogger();
diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -372,20 +372,20 @@ Debugger::Debugger(JSContext* cx, Native
     maxAllocationsLogLength(DEFAULT_MAX_LOG_LENGTH),
     allocationsLogOverflowed(false),
     frames(cx->runtime()),
     scripts(cx),
     sources(cx),
     objects(cx),
     environments(cx),
 #ifdef NIGHTLY_BUILD
-    traceLoggerLastDrainedId(0),
+    traceLoggerLastDrainedSize(0),
     traceLoggerLastDrainedIteration(0),
 #endif
-    traceLoggerScriptedCallsLastDrainedId(0),
+    traceLoggerScriptedCallsLastDrainedSize(0),
     traceLoggerScriptedCallsLastDrainedIteration(0)
 {
     assertSameCompartment(cx, dbg);
 
     cx->runtime()->debuggerList.insertBack(this);
     JS_INIT_CLIST(&breakpoints);
     JS_INIT_CLIST(&onNewGlobalObjectWatchersLink);
 }
@@ -4397,19 +4397,19 @@ Debugger::drainTraceLogger(JSContext* cx
 {
     THIS_DEBUGGER(cx, argc, vp, "drainTraceLogger", args, dbg);
     if (!args.requireAtLeast(cx, "Debugger.drainTraceLogger", 0))
         return false;
 
     size_t num;
     TraceLoggerThread* logger = TraceLoggerForMainThread(cx->runtime());
     bool lostEvents = logger->lostEvents(dbg->traceLoggerLastDrainedIteration,
-                                         dbg->traceLoggerLastDrainedId);
+                                         dbg->traceLoggerLastDrainedSize);
     EventEntry* events = logger->getEventsStartingAt(&dbg->traceLoggerLastDrainedIteration,
-                                                     &dbg->traceLoggerLastDrainedId,
+                                                     &dbg->traceLoggerLastDrainedSize,
                                                      &num);
 
     RootedObject array(cx, NewDenseEmptyArray(cx));
     JSAtom* dataAtom = Atomize(cx, "data", strlen("data"));
     if (!dataAtom)
         return false;
     RootedId dataId(cx, AtomToId(dataAtom));
 
@@ -4492,20 +4492,20 @@ Debugger::drainTraceLoggerScriptCalls(JS
 {
     THIS_DEBUGGER(cx, argc, vp, "drainTraceLoggerScriptCalls", args, dbg);
     if (!args.requireAtLeast(cx, "Debugger.drainTraceLoggerScriptCalls", 0))
         return false;
 
     size_t num;
     TraceLoggerThread* logger = TraceLoggerForMainThread(cx->runtime());
     bool lostEvents = logger->lostEvents(dbg->traceLoggerScriptedCallsLastDrainedIteration,
-                                         dbg->traceLoggerScriptedCallsLastDrainedId);
+                                         dbg->traceLoggerScriptedCallsLastDrainedSize);
     EventEntry* events = logger->getEventsStartingAt(
                                          &dbg->traceLoggerScriptedCallsLastDrainedIteration,
-                                         &dbg->traceLoggerScriptedCallsLastDrainedId,
+                                         &dbg->traceLoggerScriptedCallsLastDrainedSize,
                                          &num);
 
     RootedObject array(cx, NewDenseEmptyArray(cx));
     RootedId fileNameId(cx, AtomToId(cx->names().fileName));
     RootedId lineNumberId(cx, AtomToId(cx->names().lineNumber));
     RootedId columnNumberId(cx, AtomToId(cx->names().columnNumber));
     JSAtom* logTypeAtom = Atomize(cx, "logType", strlen("logType"));
     if (!logTypeAtom)
diff --git a/js/src/vm/Debugger.h b/js/src/vm/Debugger.h
--- a/js/src/vm/Debugger.h
+++ b/js/src/vm/Debugger.h
@@ -443,20 +443,20 @@ class Debugger : private mozilla::Linked
     /* The map from debuggee Envs to Debugger.Environment instances. */
     ObjectWeakMap environments;
 
     /*
      * Keep track of tracelogger last drained identifiers to know if there are
      * lost events.
      */
 #ifdef NIGHTLY_BUILD
-    uint32_t traceLoggerLastDrainedId;
+    uint32_t traceLoggerLastDrainedSize;
     uint32_t traceLoggerLastDrainedIteration;
 #endif
-    uint32_t traceLoggerScriptedCallsLastDrainedId;
+    uint32_t traceLoggerScriptedCallsLastDrainedSize;
     uint32_t traceLoggerScriptedCallsLastDrainedIteration;
 
     class FrameRange;
     class ScriptQuery;
     class ObjectQuery;
 
     bool addDebuggeeGlobal(JSContext* cx, Handle<GlobalObject*> obj);
     void removeDebuggeeGlobal(FreeOp* fop, GlobalObject* global,
diff --git a/js/src/vm/TraceLogging.h b/js/src/vm/TraceLogging.h
--- a/js/src/vm/TraceLogging.h
+++ b/js/src/vm/TraceLogging.h
@@ -203,47 +203,47 @@ class TraceLoggerThread
     bool enable();
     bool enable(JSContext* cx);
     bool disable();
 
-    // Given the previous iteration and lastEntryId, return an array of events
+    // Given the previous iteration and size, return an array of events
     // (there could be lost events). At the same time update the iteration and
-    // lastEntry and gives back how many events there are.
-    EventEntry* getEventsStartingAt(uint32_t* lastIteration, uint32_t* lastEntryId, size_t* num) {
+    // size and gives back how many events there are.
+    EventEntry* getEventsStartingAt(uint32_t* lastIteration, uint32_t* lastSize, size_t* num) {
         EventEntry* start;
         if (iteration_ == *lastIteration) {
-            MOZ_ASSERT(*lastEntryId < events.size());
-            *num = events.lastEntryId() - *lastEntryId;
-            start = events.data() + *lastEntryId + 1;
+            MOZ_ASSERT(*lastSize <= events.size());
+            *num = events.size() - *lastSize;
+            start = events.data() + *lastSize;
         } else {
             *num = events.size();
             start = events.data();
         }
 
         *lastIteration = iteration_;
-        *lastEntryId = events.lastEntryId();
+        *lastSize = events.size();
         return start;
     }
 
     // Extract the details filename, lineNumber and columnNumber out of a event
     // containing script information.
     void extractScriptDetails(uint32_t textId, const char** filename, size_t* filename_len,
                               const char** lineno, size_t* lineno_len, const char** colno,
                               size_t* colno_len);
 
-    bool lostEvents(uint32_t lastIteration, uint32_t lastEntryId) {
+    bool lostEvents(uint32_t lastIteration, uint32_t lastSize) {
         // If still logging in the same iteration, there are no lost events.
         if (lastIteration == iteration_) {
-            MOZ_ASSERT(lastEntryId < events.size());
+            MOZ_ASSERT(lastSize <= events.size());
             return false;
         }
 
-        // When proceeded to the next iteration and lastEntryId points to
-        // the maximum capacity there are no logs that are lost.
-        if (lastIteration + 1 == iteration_ && lastEntryId == events.capacity())
+        // If we are in a consecutive iteration we are only sure we didn't lose any events,
+        // when the lastSize equals the maximum size 'events' can get.
+        if (lastIteration == iteration_ - 1 && lastSize == CONTINUOUSSPACE_LIMIT)
             return false;
 
         return true;
     }
 
     const char* eventText(uint32_t id);
     bool textIdIsScriptEvent(uint32_t id);
 


