Bug 1606113 - Move BaseScript::sharedData tracing/finalizing to BaseScript. r=jandem
authorTed Campbell <tcampbell@mozilla.com>
Mon, 30 Dec 2019 08:45:20 +0000
changeset 508489 33ae0330cbe4d25f47ba07badbe87f939b1d0b1a
parent 508488 96d2a50a56a624099abf2265c37b81ef0fd16d45
child 508490 710e512a73524c36120734a60c721578bf415f49
push id104019
push usertcampbell@mozilla.com
push dateMon, 30 Dec 2019 14:20:00 +0000
treeherderautoland@710e512a7352 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1606113
milestone73.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 1606113 - Move BaseScript::sharedData tracing/finalizing to BaseScript. r=jandem Move the code from JSScript to BaseScript and rename freeScriptData to freeSharedData. Depends on D58301 Differential Revision: https://phabricator.services.mozilla.com/D58303
js/src/gc/Marking.cpp
js/src/vm/JSScript.cpp
js/src/vm/JSScript.h
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -1100,16 +1100,20 @@ void BaseScript::traceChildren(JSTracer*
   TraceEdge(trc, &functionOrGlobal_, "function");
   TraceNullableEdge(trc, &sourceObject_, "sourceObject");
 
   warmUpData_.trace(trc);
 
   if (data_) {
     data_->trace(trc);
   }
+
+  if (sharedData_) {
+    sharedData_->traceChildren(trc);
+  }
 }
 
 void LazyScript::traceChildren(JSTracer* trc) {
   // Trace base class fields.
   BaseScript::traceChildren(trc);
 
   if (trc->traceWeakEdges()) {
     TraceNullableEdge(trc, &script_, "script");
@@ -1136,16 +1140,19 @@ inline void js::GCMarker::eagerlyMarkChi
       } else if (elem.is<JSString>()) {
         traverseEdge(thing, &elem.as<JSString>());
       } else {
         MOZ_ASSERT(!elem);
       }
     }
   }
 
+  MOZ_ASSERT(thing->sharedData_ == nullptr,
+             "LazyScript should not have shared data.");
+
   // script_ is weak so is not traced here.
 
   markImplicitEdges(thing);
 }
 
 void Shape::traceChildren(JSTracer* trc) {
   TraceEdge(trc, &base_, "base");
   TraceEdge(trc, &propidRef(), "propid");
--- a/js/src/vm/JSScript.cpp
+++ b/js/src/vm/JSScript.cpp
@@ -687,16 +687,18 @@ void js::BaseScript::finalize(JSFreeOp* 
   }
 
   if (data_) {
     size_t size = data_->allocationSize();
     AlwaysPoison(data_, JS_POISONED_JSSCRIPT_DATA_PATTERN, size,
                  MemCheckKind::MakeNoAccess);
     fop->free_(this, data_, size, MemoryUse::ScriptPrivateData);
   }
+
+  freeSharedData();
 }
 
 template <XDRMode mode>
 /* static */
 XDRResult js::PrivateScriptData::XDR(XDRState<mode>* xdr, HandleScript script,
                                      HandleScriptSourceObject sourceObject,
                                      HandleScope scriptEnclosingScope,
                                      HandleObject funOrMod) {
@@ -1227,23 +1229,22 @@ XDRResult js::XDRScript(XDRState<mode>* 
 
     // Set the script in its function now so that inner scripts to be
     // decoded may iterate the static scope chain.
     if (isFunctionScript) {
       funOrMod->as<JSFunction>().initScript(script);
     }
   }
 
-  // If XDR operation fails, we must call JSScript::freeScriptData in order
-  // to neuter the script. Various things that iterate raw scripts in a GC
-  // arena use the presense of this data to detect if initialization is
-  // complete.
+  // If XDR operation fails, we must call BaseScript::freeSharedData in order to
+  // neuter the script. Various things that iterate raw scripts in a GC arena
+  // use the presense of this data to detect if initialization is complete.
   auto scriptDataGuard = mozilla::MakeScopeExit([&] {
     if (mode == XDR_DECODE) {
-      script->freeScriptData();
+      script->freeSharedData();
     }
   });
 
   // NOTE: The script data is rooted by the script.
   MOZ_TRY(PrivateScriptData::XDR<mode>(xdr, script, sourceObject,
                                        scriptEnclosingScope, funOrMod));
   MOZ_TRY(RuntimeScriptData::XDR<mode>(xdr, script));
 
@@ -4126,18 +4127,16 @@ bool JSScript::createImmutableScriptData
   if (!isd) {
     return false;
   }
 
   sharedData_->isd_ = std::move(isd);
   return true;
 }
 
-void JSScript::freeScriptData() { sharedData_ = nullptr; }
-
 // Takes owndership of the script's sharedData_ and either adds it into the
 // runtime's RuntimeScriptDataTable or frees it if a matching entry already
 // exists.
 bool JSScript::shareScriptData(JSContext* cx) {
   RuntimeScriptData* rsd = sharedData();
   MOZ_ASSERT(rsd);
   MOZ_ASSERT(rsd->refCount() == 1);
 
@@ -4453,21 +4452,21 @@ void JSScript::initFromFunctionBox(front
   }
 }
 
 /* static */
 bool JSScript::fullyInitFromEmitter(JSContext* cx, HandleScript script,
                                     frontend::BytecodeEmitter* bce) {
   MOZ_ASSERT(!script->data_, "JSScript already initialized");
 
-  // If initialization fails, we must call JSScript::freeScriptData in order to
-  // neuter the script. Various things that iterate raw scripts in a GC arena
+  // If initialization fails, we must call BaseScript::freeSharedData in order
+  // to neuter the script. Various things that iterate raw scripts in a GC arena
   // use the presense of this data to detect if initialization is complete.
   auto scriptDataGuard =
-      mozilla::MakeScopeExit([&] { script->freeScriptData(); });
+      mozilla::MakeScopeExit([&] { script->freeSharedData(); });
 
   /* The counts of indexed things must be checked during code generation. */
   MOZ_ASSERT(bce->perScriptData().atomIndices()->count() <= INDEX_LIMIT);
   MOZ_ASSERT(bce->perScriptData().gcThingList().length() <= INDEX_LIMIT);
 
   uint64_t nslots =
       bce->maxFixedSlots +
       static_cast<uint64_t>(bce->bytecodeSection().maxStackDepth());
@@ -4650,18 +4649,16 @@ void JSScript::finalize(JSFreeOp* fop) {
     // Note: we should only get here if the VTune JIT profiler is running.
     zone()->scriptVTuneIdMap->remove(this);
   }
 #endif
 
   // Finalize the base-script fields.
   BaseScript::finalize(fop);
 
-  freeScriptData();
-
   // In most cases, our LazyScript's script pointer will reference this
   // script, and thus be nulled out by normal weakref processing. However, if
   // we unlazified the LazyScript during incremental sweeping, it will have a
   // completely different JSScript.
   MOZ_ASSERT_IF(
       lazyScript && !IsAboutToBeFinalizedUnbarriered(&lazyScript),
       !lazyScript->hasScript() || lazyScript->maybeScriptUnbarriered() != this);
 }
@@ -5322,20 +5319,16 @@ void JSScript::traceChildren(JSTracer* t
   // NOTE: this JSScript may be partially initialized at this point.  E.g. we
   // may have created it and partially initialized it with
   // JSScript::Create(), but not yet finished initializing it with
   // fullyInitFromEmitter().
 
   // Trace base class fields.
   BaseScript::traceChildren(trc);
 
-  if (sharedData()) {
-    sharedData()->traceChildren(trc);
-  }
-
   if (maybeLazyScript()) {
     TraceManuallyBarrieredEdge(trc, &lazyScript, "lazyScript");
   }
 
   if (hasDebugScript()) {
     DebugAPI::traceDebugScript(trc, this);
   }
 
--- a/js/src/vm/JSScript.h
+++ b/js/src/vm/JSScript.h
@@ -2510,16 +2510,17 @@ setterLevel:                            
     data_->setFieldInitializers(fieldInitializers);
   }
   const FieldInitializers& getFieldInitializers() const {
     MOZ_ASSERT(data_);
     return data_->getFieldInitializers();
   }
 
   RuntimeScriptData* sharedData() { return sharedData_; }
+  void freeSharedData() { sharedData_ = nullptr; }
 
  protected:
   void traceChildren(JSTracer* trc);
   void finalize(JSFreeOp* fop);
 
  public:
   size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) {
     return mallocSizeOf(data_);
@@ -3005,17 +3006,16 @@ class JSScript : public js::BaseScript {
  private:
   bool createJitScript(JSContext* cx);
 
   bool createScriptData(JSContext* cx, uint32_t natoms);
   bool createImmutableScriptData(JSContext* cx, uint32_t codeLength,
                                  uint32_t noteLength, uint32_t numResumeOffsets,
                                  uint32_t numScopeNotes, uint32_t numTryNotes);
   bool shareScriptData(JSContext* cx);
-  void freeScriptData();
 
  public:
   inline uint32_t getWarmUpCount() const;
   inline void incWarmUpCounter(uint32_t amount = 1);
   inline void resetWarmUpCounterForGC();
 
   void resetWarmUpCounterToDelayIonCompilation();