Bug 1547478 - Root fresh BinAST metadata created during XDR decoding until it's transferred into its ScriptSource. r=tcampbell
authorJeff Walden <jwalden@mit.edu>
Mon, 29 Apr 2019 14:33:55 -0700
changeset 531197 e2e8514d344b0f34c0981f1c4aeb6c26984b2107
parent 531196 06c42ef3ab2b6dd9a03e5d46528d0dcb66b2d4a9
child 531198 878d133f6a4ce580145297fe2fc01b57cf428b82
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstcampbell
bugs1547478
milestone68.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 1547478 - Root fresh BinAST metadata created during XDR decoding until it's transferred into its ScriptSource. r=tcampbell Differential Revision: https://phabricator.services.mozilla.com/D29314
js/src/vm/JSScript.cpp
js/src/vm/JSScript.h
--- a/js/src/vm/JSScript.cpp
+++ b/js/src/vm/JSScript.cpp
@@ -2183,30 +2183,30 @@ MOZ_MUST_USE bool ScriptSource::setBinAS
   }
 
   data = SourceType(BinAST(std::move(*deduped)));
   return true;
 }
 
 MOZ_MUST_USE bool ScriptSource::initializeBinAST(
     JSContext* cx, UniqueChars&& buf, size_t len,
-    UniquePtr<frontend::BinASTSourceMetadata> metadata) {
+    MutableHandle<UniquePtr<frontend::BinASTSourceMetadata>> metadata) {
   MOZ_ASSERT(data.is<Missing>(),
              "should only be initializing a fresh ScriptSource");
   MOZ_ASSERT(binASTMetadata_ == nullptr, "shouldn't have BinAST metadata yet");
 
   auto& cache = cx->zone()->runtimeFromAnyThread()->sharedImmutableStrings();
   auto deduped = cache.getOrCreate(std::move(buf), len);
   if (!deduped) {
     ReportOutOfMemory(cx);
     return false;
   }
 
   data = SourceType(BinAST(std::move(*deduped)));
-  binASTMetadata_ = std::move(metadata);
+  binASTMetadata_ = std::move(metadata.get());
   return true;
 }
 
 const uint8_t* ScriptSource::binASTSource() {
   MOZ_ASSERT(hasBinASTSource());
   return reinterpret_cast<const uint8_t*>(data.as<BinAST>().string.chars());
 }
 
@@ -2769,22 +2769,27 @@ XDRResult ScriptSource::codeBinASTData(X
 
   // XDR any BinAST metadata.
   uint8_t hasMetadata;
   if (mode == XDR_ENCODE) {
     hasMetadata = ss->binASTMetadata_ != nullptr;
   }
   MOZ_TRY(xdr->codeUint8(&hasMetadata));
 
-  UniquePtr<frontend::BinASTSourceMetadata> freshMetadata;
+  Rooted<UniquePtr<frontend::BinASTSourceMetadata>> freshMetadata(xdr->cx());
   if (hasMetadata) {
-    // If we're decoding, we decode into fresh metadata.  If we're encoding,
-    // we encode *from* the stored metadata.
-    auto& binASTMetadata =
-        mode == XDR_DECODE ? freshMetadata : ss->binASTMetadata_;
+    // If we're decoding, this is a *mutable borrowed* reference to the
+    // |UniquePtr| stored in the |Rooted| above, and the |UniquePtr| will be
+    // filled with freshly allocated metadata.
+    //
+    // If we're encoding, this is an *immutable borrowed* reference to the
+    // |UniquePtr| stored in |ss|.  (Immutable up to GCs transparently moving
+    // things around, that is.)
+    UniquePtr<frontend::BinASTSourceMetadata>& binASTMetadata =
+        mode == XDR_DECODE ? freshMetadata.get() : ss->binASTMetadata_;
 
     uint32_t numBinASTKinds;
     uint32_t numStrings;
     if (mode == XDR_ENCODE) {
       numBinASTKinds = binASTMetadata->numBinASTKinds();
       numStrings = binASTMetadata->numStrings();
     }
     MOZ_TRY(xdr->codeUint32(&numBinASTKinds));
@@ -2846,22 +2851,22 @@ XDRResult ScriptSource::codeBinASTData(X
         new (&slices[i]) frontend::BinASTSourceMetadata::CharSlice(
             sourceBase + sliceOffset, sliceLen);
       }
     }
   }
 
   if (mode == XDR_DECODE) {
     if (!ss->initializeBinAST(xdr->cx(), std::move(bytes), binASTLength,
-                              std::move(freshMetadata))) {
+                              &freshMetadata)) {
       return xdr->fail(JS::TranscodeResult_Throw);
     }
-  } else {
-    MOZ_ASSERT(freshMetadata == nullptr);
-  }
+  }
+
+  MOZ_ASSERT(freshMetadata == nullptr);
 
   return Ok();
 #endif  // !defined(JS_BUILD_BINAST)
 }
 
 template <XDRMode mode>
 /* static */
 XDRResult ScriptSource::xdrData(XDRState<mode>* const xdr,
--- a/js/src/vm/JSScript.h
+++ b/js/src/vm/JSScript.h
@@ -1001,17 +1001,17 @@ class ScriptSource {
                                         size_t len);
 
   /*
    * Initialize this as containing BinAST data for |buf|/|len|, using a shared,
    * deduplicated version of |buf| if necessary.
    */
   MOZ_MUST_USE bool initializeBinAST(
       JSContext* cx, UniqueChars&& buf, size_t len,
-      UniquePtr<frontend::BinASTSourceMetadata> metadata);
+      JS::MutableHandle<UniquePtr<frontend::BinASTSourceMetadata>> metadata);
 
   const uint8_t* binASTSource();
 
 #endif /* JS_BUILD_BINAST */
 
  private:
   void performTaskWork(SourceCompressionTask* task);