Bug 1283710 - Part 3: Release JSErrorReport.linebuf_ in destructor if own. r=jwalden
authorTooru Fujisawa <arai_a@mac.com>
Sun, 14 Aug 2016 20:39:31 +0900
changeset 319044 efd6ab563cb9e854fe3c0fbec60d7c491b213648
parent 319043 8900adb4c36dffa8ef6b89ba3e277e39551dea17
child 319045 e8bc246a57ad418864039ffe1dfb2cbe9a83fba1
push id30858
push userryanvm@gmail.com
push dateSun, 23 Oct 2016 17:17:41 +0000
treeherdermozilla-central@a9a41b69f3f9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwalden
bugs1283710
milestone52.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1283710 - Part 3: Release JSErrorReport.linebuf_ in destructor if own. r=jwalden
js/src/frontend/TokenStream.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jsexn.cpp
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -583,17 +583,16 @@ CompileError::throwError(JSContext* cx)
     // as the non-top-level "load", "eval", or "compile" native function
     // returns false, the top-level reporter will eventually receive the
     // uncaught exception report.
     ErrorToException(cx, message, &report, nullptr, nullptr);
 }
 
 CompileError::~CompileError()
 {
-    js_free((void*)report.linebuf());
     js_free(message);
     message = nullptr;
 }
 
 bool
 TokenStream::reportCompileErrorNumberVA(uint32_t offset, unsigned flags, unsigned errorNumber,
                                         va_list args)
 {
@@ -684,17 +683,17 @@ TokenStream::reportCompileErrorNumberVA(
             return false;
         }
 
         // The window into the offending source line, without final \n.
         UniqueTwoByteChars linebuf(windowBuf.stealChars());
         if (!linebuf)
             return false;
 
-        err.report.initLinebuf(linebuf.release(), windowLength, offset - windowStart);
+        err.report.initOwnedLinebuf(linebuf.release(), windowLength, offset - windowStart);
     }
 
     if (cx->isJSContext())
         err.throwError(cx->asJSContext());
 
     return warning;
 }
 
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -6126,25 +6126,36 @@ JS_ErrorFromException(JSContext* cx, Han
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     return ErrorFromException(cx, obj);
 }
 
 void
-JSErrorReport::initLinebuf(const char16_t* linebuf, size_t linebufLength, size_t tokenOffset)
-{
-    MOZ_ASSERT(linebuf);
-    MOZ_ASSERT(tokenOffset <= linebufLength);
-    MOZ_ASSERT(linebuf[linebufLength] == '\0');
-
-    linebuf_ = linebuf;
-    linebufLength_ = linebufLength;
-    tokenOffset_ = tokenOffset;
+JSErrorReport::initBorrowedLinebuf(const char16_t* linebufArg, size_t linebufLengthArg,
+                                   size_t tokenOffsetArg)
+{
+    MOZ_ASSERT(linebufArg);
+    MOZ_ASSERT(tokenOffsetArg <= linebufLengthArg);
+    MOZ_ASSERT(linebufArg[linebufLengthArg] == '\0');
+
+    linebuf_ = linebufArg;
+    linebufLength_ = linebufLengthArg;
+    tokenOffset_ = tokenOffsetArg;
+}
+
+void
+JSErrorReport::freeLinebuf()
+{
+    if (ownsLinebuf_ && linebuf_) {
+        js_free((void*)linebuf_);
+        ownsLinebuf_ = false;
+    }
+    linebuf_ = nullptr;
 }
 
 JSString*
 JSErrorReport::newMessageString(JSContext* cx)
 {
     if (!message_)
         return cx->runtime()->emptyString;
 
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -5305,59 +5305,67 @@ JS_ReportAllocationOverflow(JSContext* c
 
 class JSErrorReport
 {
     // The (default) error message.
     // If ownsMessage_ is true, the it is freed in destructor.
     JS::ConstUTF8CharsZ message_;
 
     // Offending source line without final '\n'.
+    // If ownsLinebuf__ is true, the buffer is freed in destructor.
     const char16_t* linebuf_;
 
     // Number of chars in linebuf_. Does not include trailing '\0'.
     size_t linebufLength_;
 
     // The 0-based offset of error token in linebuf_.
     size_t tokenOffset_;
 
   public:
     JSErrorReport()
       : linebuf_(nullptr), linebufLength_(0), tokenOffset_(0),
         filename(nullptr), lineno(0), column(0),
         flags(0), errorNumber(0),
         exnType(0), isMuted(false),
-        ownsMessage_(false)
+        ownsLinebuf_(false), ownsMessage_(false)
     {}
 
     ~JSErrorReport() {
+        freeLinebuf();
         freeMessage();
     }
 
     const char*     filename;      /* source file name, URL, etc., or null */
     unsigned        lineno;         /* source line number */
     unsigned        column;         /* zero-based column index in line */
     unsigned        flags;          /* error/warning, etc. */
     unsigned        errorNumber;    /* the error number, e.g. see js.msg */
     int16_t         exnType;        /* One of the JSExnType constants */
     bool            isMuted : 1;    /* See the comment in ReadOnlyCompileOptions. */
 
   private:
+    bool ownsLinebuf_ : 1;
     bool ownsMessage_ : 1;
 
   public:
     const char16_t* linebuf() const {
         return linebuf_;
     }
     size_t linebufLength() const {
         return linebufLength_;
     }
     size_t tokenOffset() const {
         return tokenOffset_;
     }
-    void initLinebuf(const char16_t* linebuf, size_t linebufLength, size_t tokenOffset);
+    void initOwnedLinebuf(const char16_t* linebufArg, size_t linebufLengthArg, size_t tokenOffsetArg) {
+        initBorrowedLinebuf(linebufArg, linebufLengthArg, tokenOffsetArg);
+        ownsLinebuf_ = true;
+    }
+    void initBorrowedLinebuf(const char16_t* linebufArg, size_t linebufLengthArg, size_t tokenOffsetArg);
+    void freeLinebuf();
 
     const JS::ConstUTF8CharsZ message() const {
         return message_;
     }
 
     void initOwnedMessage(const char* messageArg) {
         initBorrowedMessage(messageArg);
         ownsMessage_ = true;
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -187,17 +187,17 @@ js::CopyErrorReport(JSContext* cx, JSErr
         js_memcpy(cursor, report->message().c_str(), messageSize);
         cursor += messageSize;
     }
 
     if (report->linebuf()) {
         const char16_t* linebufCopy = (const char16_t*)cursor;
         js_memcpy(cursor, report->linebuf(), linebufSize);
         cursor += linebufSize;
-        copy->initLinebuf(linebufCopy, report->linebufLength(), report->tokenOffset());
+        copy->initBorrowedLinebuf(linebufCopy, report->linebufLength(), report->tokenOffset());
     }
 
     if (report->filename) {
         copy->filename = (const char*)cursor;
         js_memcpy(cursor, report->filename, filenameSize);
     }
     MOZ_ASSERT(cursor + filenameSize == (uint8_t*)copy + mallocSize);