Bug 1283710 - Part 3: Release JSErrorReport.linebuf_ in destructor if own. r=jwalden
☠☠ backed out by 971d67779565 ☠ ☠
authorTooru Fujisawa <arai_a@mac.com>
Sun, 14 Aug 2016 20:39:31 +0900
changeset 318501 dcedbaefe39987d5f802b2c579391d7352df2891
parent 318500 61f8250cbe0b82d7f918756d86e135d7b3fb401d
child 318502 ee5215f1a38e702d7335da05316ead5978e64986
push id30843
push usercbook@mozilla.com
push dateWed, 19 Oct 2016 15:02:57 +0000
treeherdermozilla-central@f40960c63bfa [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
@@ -6125,25 +6125,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
@@ -5299,59 +5299,66 @@ 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() {
         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);