Bug 1533755 - Cleanups in PrivateScriptData. r=jandem
☠☠ backed out by 638b7cfb8639 ☠ ☠
authorTed Campbell <tcampbell@mozilla.com>
Mon, 11 Mar 2019 20:01:26 +0000
changeset 524421 35825a8005ab0f60ec24b2655e771d090f6c36d6
parent 524420 9ff4178c5e2d278c8b0e7a25f1f6bb5b5bd8b217
child 524422 d5eff5c34ce9c47055b6599487c837cc6363d6b5
push id2032
push userffxbld-merge
push dateMon, 13 May 2019 09:36:57 +0000
treeherdermozilla-release@455c1065dcbe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1533755
milestone67.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 1533755 - Cleanups in PrivateScriptData. r=jandem Also add a GCManagedDeletePolicy so that the script data can be dropped even when we are not sweeping. Differential Revision: https://phabricator.services.mozilla.com/D22715
js/src/vm/JSScript.cpp
js/src/vm/JSScript.h
--- a/js/src/vm/JSScript.cpp
+++ b/js/src/vm/JSScript.cpp
@@ -613,18 +613,17 @@ XDRResult js::PrivateScriptData::XDR(XDR
   {
     MOZ_ASSERT(nscopes > 0);
     GCPtrScope* vector = data->scopes().data();
     for (uint32_t i = 0; i < nscopes; ++i) {
       RootedScope scope(cx);
       if (mode == XDR_ENCODE) {
         scope = vector[i];
       }
-      MOZ_TRY(
-          XDRScope(xdr, script->data_, scriptEnclosingScope, fun, i, &scope));
+      MOZ_TRY(XDRScope(xdr, data, scriptEnclosingScope, fun, i, &scope));
       if (mode == XDR_DECODE) {
         vector[i].init(scope);
       }
     }
 
     // Verify marker to detect data corruption after decoding scope data. A
     // mismatch here indicates we will almost certainly crash in release.
     MOZ_TRY(xdr->codeMarker(0x48922BAB));
@@ -636,17 +635,17 @@ XDRResult js::PrivateScriptData::XDR(XDR
    * after the enclosing block has been XDR'd.
    */
   if (nobjects) {
     for (GCPtrObject& elem : data->objects()) {
       RootedObject inner(cx);
       if (mode == XDR_ENCODE) {
         inner = elem;
       }
-      MOZ_TRY(XDRInnerObject(xdr, script->data_, sourceObject, &inner));
+      MOZ_TRY(XDRInnerObject(xdr, data, sourceObject, &inner));
       if (mode == XDR_DECODE) {
         elem.init(inner);
       }
     }
   }
 
   // Verify marker to detect data corruption after decoding object data. A
   // mismatch here indicates we will almost certainly crash in release.
@@ -3257,17 +3256,17 @@ PrivateScriptData* PrivateScriptData::ne
   }
   if (nresumeoffsets) {
     bce->resumeOffsetList.finish(data->resumeOffsets());
   }
 
   return true;
 }
 
-void PrivateScriptData::traceChildren(JSTracer* trc) {
+void PrivateScriptData::trace(JSTracer* trc) {
   auto scopearray = scopes();
   TraceRange(trc, scopearray.size(), scopearray.data(), "scopes");
 
   if (hasConsts()) {
     auto constarray = consts();
     TraceRange(trc, constarray.size(), constarray.data(), "consts");
   }
 
@@ -4552,17 +4551,17 @@ void JSScript::traceChildren(JSTracer* t
   // JSScript::Create(), but not yet finished initializing it with
   // fullyInitFromEmitter() or fullyInitTrivial().
 
   MOZ_ASSERT_IF(trc->isMarkingTracer() &&
                     GCMarker::fromTracer(trc)->shouldCheckCompartments(),
                 zone()->isCollecting());
 
   if (data_) {
-    data_->traceChildren(trc);
+    data_->trace(trc);
   }
 
   if (scriptData()) {
     scriptData()->traceChildren(trc);
   }
 
   MOZ_ASSERT_IF(sourceObject(),
                 MaybeForwarded(sourceObject())->compartment() == compartment());
--- a/js/src/vm/JSScript.h
+++ b/js/src/vm/JSScript.h
@@ -1350,17 +1350,17 @@ class alignas(JS::Value) PrivateScriptDa
   // the private data.
   struct alignas(uintptr_t) PackedSpan {
     uint32_t offset;
     uint32_t length;
   };
 
   // Concrete Fields
   PackedOffsets packedOffsets = {};  // zeroes
-  uint32_t nscopes;
+  uint32_t nscopes = 0;
 
   // Translate an offset into a concrete pointer.
   template <typename T>
   T* offsetToPointer(size_t offset) {
     uintptr_t base = reinterpret_cast<uintptr_t>(this);
     uintptr_t elem = base + offset;
     return reinterpret_cast<T*>(elem);
   }
@@ -1392,16 +1392,20 @@ class alignas(JS::Value) PrivateScriptDa
                                uint32_t nobjects, uint32_t ntrynotes,
                                uint32_t nscopenotes, uint32_t nresumeoffsets);
 
   // Initialize header and PackedSpans
   PrivateScriptData(uint32_t nscopes_, uint32_t nconsts, uint32_t nobjects,
                     uint32_t ntrynotes, uint32_t nscopenotes,
                     uint32_t nresumeoffsets);
 
+  // PrivateScriptData has trailing data so isn't copyable or movable.
+  PrivateScriptData(const PrivateScriptData&) = delete;
+  PrivateScriptData& operator=(const PrivateScriptData&) = delete;
+
  public:
   // Accessors for typed array spans.
   mozilla::Span<GCPtrScope> scopes() {
     GCPtrScope* base =
         packedOffsetToPointer<GCPtrScope>(packedOffsets.scopesOffset);
     return mozilla::MakeSpan(base, nscopes);
   }
   mozilla::Span<GCPtrValue> consts() {
@@ -1445,17 +1449,17 @@ class alignas(JS::Value) PrivateScriptDa
 
   // Clone src script data into dst script.
   static bool Clone(JSContext* cx, js::HandleScript src, js::HandleScript dst,
                     js::MutableHandle<JS::GCVector<js::Scope*>> scopes);
 
   static bool InitFromEmitter(JSContext* cx, js::HandleScript script,
                               js::frontend::BytecodeEmitter* bce);
 
-  void traceChildren(JSTracer* trc);
+  void trace(JSTracer* trc);
 };
 
 /*
  * Common data that can be shared between many scripts in a single runtime.
  */
 class SharedScriptData {
   // This class is reference counted as follows: each pointer from a JSScript
   // counts as one reference plus there may be one reference from the shared
@@ -1570,16 +1574,26 @@ using ScriptDataTable =
     HashSet<SharedScriptData*, ScriptBytecodeHasher, SystemAllocPolicy>;
 
 extern void SweepScriptData(JSRuntime* rt);
 
 extern void FreeScriptData(JSRuntime* rt);
 
 } /* namespace js */
 
+namespace JS {
+
+// Define a GCManagedDeletePolicy to allow deleting type outside of normal
+// sweeping.
+template <>
+struct JS::DeletePolicy<js::PrivateScriptData>
+    : public js::GCManagedDeletePolicy<js::PrivateScriptData> {};
+
+} /* namespace JS */
+
 class JSScript : public js::gc::TenuredCell {
  private:
   // Pointer to baseline->method()->raw(), ion->method()->raw(), a wasm jit
   // entry, the JIT's EnterInterpreter stub, or the lazy link stub. Must be
   // non-null.
   uint8_t* jitCodeRaw_ = nullptr;
   uint8_t* jitCodeSkipArgCheck_ = nullptr;