Bug 1461012: Add CC optimizations for PrecompiledScript objects. r?mccr8 draft
authorKris Maglione <maglione.k@gmail.com>
Fri, 11 May 2018 15:57:31 -0700
changeset 794388 568ffcb2820f63bfef5792d3bea8d4fd20537b56
parent 794387 31110012986a530ddfaccc565bee834cefb80b7f
push id109677
push usermaglione.k@gmail.com
push dateFri, 11 May 2018 23:00:34 +0000
reviewersmccr8
bugs1461012
milestone62.0a1
Bug 1461012: Add CC optimizations for PrecompiledScript objects. r?mccr8 Tracing the script members held alive by PrecompiledScript objects can be expensive, especially for large scripts. It would be nice if we could avoid tracing them when possible. Most of the time, when PrecompiledScripts are alive, they're held alive by black roots, and have black JS wrappers. In those cases, there's no chance of them creating garbage cycles, and we can just mark their script children black. MozReview-Commit-ID: KnkJfznJZBx
js/xpconnect/loader/ChromeScriptLoader.cpp
js/xpconnect/loader/PrecompiledScript.h
--- a/js/xpconnect/loader/ChromeScriptLoader.cpp
+++ b/js/xpconnect/loader/ChromeScriptLoader.cpp
@@ -15,16 +15,17 @@
 #include "jsfriendapi.h"
 #include "js/Utility.h"
 
 #include "mozilla/dom/ChromeUtils.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/ScriptLoader.h"
 #include "mozilla/HoldDropJSObjects.h"
 #include "mozilla/SystemGroup.h"
+#include "nsCCUncollectableMarker.h"
 #include "nsCycleCollectionParticipant.h"
 
 using namespace JS;
 using namespace mozilla;
 using namespace mozilla::dom;
 
 class AsyncScriptCompiler final : public nsIIncrementalStreamLoaderObserver
                                 , public Runnable
@@ -333,16 +334,24 @@ PrecompiledScript::HasReturnValue()
 }
 
 JSObject*
 PrecompiledScript::WrapObject(JSContext* aCx, HandleObject aGivenProto)
 {
     return PrecompiledScriptBinding::Wrap(aCx, this, aGivenProto);
 }
 
+bool
+PrecompiledScript::IsBlackForCC(bool aTracingNeeded)
+{
+    return (nsCCUncollectableMarker::sGeneration &&
+            HasKnownLiveWrapper() &&
+            (!aTracingNeeded || HasNothingToTrace(this)));
+}
+
 NS_IMPL_CYCLE_COLLECTION_CLASS(PrecompiledScript)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PrecompiledScript)
     NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
     NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(PrecompiledScript)
@@ -356,13 +365,28 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(PrecompiledScript)
     NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mScript)
     NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
+NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(PrecompiledScript)
+    if (tmp->IsBlackForCC(false)) {
+        tmp->mScript.exposeToActiveJS();
+        return true;
+    }
+NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
+
+NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(PrecompiledScript)
+    return tmp->IsBlackForCC(true);
+NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
+
+NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(PrecompiledScript)
+    return tmp->IsBlackForCC(false);
+NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
+
 NS_IMPL_CYCLE_COLLECTING_ADDREF(PrecompiledScript)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(PrecompiledScript)
 
 } // namespace dom
 } // namespace mozilla
--- a/js/xpconnect/loader/PrecompiledScript.h
+++ b/js/xpconnect/loader/PrecompiledScript.h
@@ -17,17 +17,17 @@
 #include "nsWrapperCache.h"
 
 namespace mozilla {
 namespace dom {
 class PrecompiledScript : public nsISupports
                         , public nsWrapperCache
 {
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(PrecompiledScript)
+  NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(PrecompiledScript)
 
   explicit PrecompiledScript(nsISupports* aParent, JS::Handle<JSScript*> aScript, JS::ReadOnlyCompileOptions& aOptions);
 
   void ExecuteInGlobal(JSContext* aCx, JS::HandleObject aGlobal,
                        JS::MutableHandleValue aRval,
                        ErrorResult& aRv);
 
   void GetUrl(nsAString& aUrl);
@@ -38,16 +38,18 @@ class PrecompiledScript : public nsISupp
 
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aGivenProto) override;
 
 protected:
   virtual ~PrecompiledScript();
 
 private:
+  bool IsBlackForCC(bool aTracingNeeded);
+
   nsCOMPtr<nsISupports> mParent;
 
   JS::Heap<JSScript*> mScript;
   nsCString mURL;
   const bool mHasReturnValue;
 };
 
 } // namespace dom