Bug 1359653: Part 6 - Use the script precompiler in the JS component loader and subscript loader. r=mccr8 r?shu draft
authorKris Maglione <maglione.k@gmail.com>
Tue, 02 May 2017 21:51:54 -0700
changeset 572141 d3cf736c40291469aa2fa76a99d22361133613cc
parent 572140 37f75bddd34ffd622fcb7be2862d5e4d28b441d0
child 572142 75ed7960fab0b95588501a44f6e167dcffec3a9c
push id57000
push usermaglione.k@gmail.com
push dateWed, 03 May 2017 19:40:22 +0000
reviewersmccr8, shu
bugs1359653
milestone55.0a1
Bug 1359653: Part 6 - Use the script precompiler in the JS component loader and subscript loader. r=mccr8 r?shu MozReview-Commit-ID: HMl0xbAARHK
js/xpconnect/loader/mozJSComponentLoader.cpp
js/xpconnect/loader/mozJSSubScriptLoader.cpp
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -19,16 +19,17 @@
 #include "jsapi.h"
 #include "nsCOMPtr.h"
 #include "nsAutoPtr.h"
 #include "nsIComponentManager.h"
 #include "mozilla/Module.h"
 #include "nsIFile.h"
 #include "mozJSComponentLoader.h"
 #include "mozJSLoaderUtils.h"
+#include "ScriptPreloader.h"
 #include "nsIXPConnect.h"
 #include "nsIObserverService.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIFileURL.h"
 #include "nsIJARURI.h"
 #include "nsNetUtil.h"
 #include "jsprf.h"
 #include "nsJSPrincipals.h"
@@ -680,17 +681,20 @@ mozJSComponentLoader::ObjectForLocation(
     StartupCache* cache = StartupCache::GetSingleton();
 
     nsAutoCString cachePath(kJSCachePrefix);
     rv = PathifyURI(aInfo.URI(), cachePath);
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (cache) {
         if (!mReuseLoaderGlobal) {
-            rv = ReadCachedScript(cache, cachePath, cx, mSystemPrincipal, &script);
+            script = ScriptPreloader::GetSingleton().GetCachedScript(cx, cachePath);
+            if (!script) {
+                rv = ReadCachedScript(cache, cachePath, cx, mSystemPrincipal, &script);
+            }
         } else {
             rv = ReadCachedFunction(cache, cachePath, cx, mSystemPrincipal,
                                     function.address());
         }
 
         if (NS_SUCCEEDED(rv)) {
             LOG(("Successfully loaded %s from startupcache\n", nativePath.get()));
         } else {
@@ -844,16 +848,20 @@ mozJSComponentLoader::ObjectForLocation(
     }
 
     // We must have a script or a function (but not both!) here.  We have a
     // script when we're not reusing the loader global, and a function
     // otherwise.
     MOZ_ASSERT(!!script != !!function);
     MOZ_ASSERT(!!script == JS_IsGlobalObject(obj));
 
+    if (script) {
+        ScriptPreloader::GetSingleton().NoteScript(nativePath, cachePath, script);
+    }
+
     if (writeToCache) {
         // We successfully compiled the script, so cache it.
         if (script) {
             rv = WriteCachedScript(cache, cachePath, cx, mSystemPrincipal,
                                    script);
         } else {
             rv = WriteCachedFunction(cache, cachePath, cx, mSystemPrincipal,
                                      function);
@@ -886,17 +894,18 @@ mozJSComponentLoader::ObjectForLocation(
         // We're going to run script via JS_ExecuteScript or
         // JS_CallFunction, so we need an AutoEntryScript.
         // This is Gecko-specific and not in any spec.
         dom::AutoEntryScript aes(CurrentGlobalOrNull(cx),
                                  "component loader load module");
         JSContext* aescx = aes.cx();
         bool ok;
         if (script) {
-            ok = JS_ExecuteScript(aescx, script);
+            JS::RootedValue rval(cx);
+            ok = JS::CloneAndExecuteScript(aescx, script, &rval);
         } else {
             RootedValue rval(cx);
             ok = JS_CallFunction(aescx, obj, function,
                                  JS::HandleValueArray::empty(), &rval);
         }
 
         if (!ok) {
             if (aPropagateExceptions && aes.HasException()) {
--- a/js/xpconnect/loader/mozJSSubScriptLoader.cpp
+++ b/js/xpconnect/loader/mozJSSubScriptLoader.cpp
@@ -2,16 +2,17 @@
 /* vim: set ts=8 sts=4 et sw=4 tw=99: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozJSSubScriptLoader.h"
 #include "mozJSComponentLoader.h"
 #include "mozJSLoaderUtils.h"
+#include "ScriptPreloader.h"
 
 #include "nsIURI.h"
 #include "nsIIOService.h"
 #include "nsIChannel.h"
 #include "nsIInputStream.h"
 #include "nsNetCID.h"
 #include "nsNetUtil.h"
 #include "nsIFileURL.h"
@@ -188,50 +189,51 @@ PrepareScript(nsIURI* uri,
                                buf, len, function);
 }
 
 static bool
 EvalScript(JSContext* cx,
            HandleObject targetObj,
            MutableHandleValue retval,
            nsIURI* uri,
-           bool cache,
+           bool startupCache,
+           bool preloadCache,
            MutableHandleScript script,
            HandleFunction function)
 {
     if (function) {
         script.set(JS_GetFunctionScript(cx, function));
     }
 
     if (function) {
         if (!JS_CallFunction(cx, targetObj, function, JS::HandleValueArray::empty(), retval)) {
             return false;
         }
     } else {
         if (JS_IsGlobalObject(targetObj)) {
-            if (!JS_ExecuteScript(cx, script, retval)) {
+            if (!JS::CloneAndExecuteScript(cx, script, retval)) {
                 return false;
             }
         } else {
             JS::AutoObjectVector envChain(cx);
             if (!envChain.append(targetObj)) {
                 return false;
             }
-            if (!JS_ExecuteScript(cx, envChain, script, retval)) {
+            if (!JS::CloneAndExecuteScript(cx, envChain, script, retval)) {
                 return false;
             }
         }
     }
 
     JSAutoCompartment rac(cx, targetObj);
     if (!JS_WrapValue(cx, retval)) {
         return false;
     }
 
-    if (cache && !!script) {
+    if (script && (startupCache || preloadCache)) {
         nsAutoCString cachePath;
         JSVersion version = JS_GetVersion(cx);
         cachePath.AppendPrintf("jssubloader/%d", version);
         PathifyURI(uri, cachePath);
 
         nsCOMPtr<nsIScriptSecurityManager> secman =
             do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
         if (!secman) {
@@ -240,18 +242,27 @@ EvalScript(JSContext* cx,
 
         nsCOMPtr<nsIPrincipal> principal;
         nsresult rv = secman->GetSystemPrincipal(getter_AddRefs(principal));
         if (NS_FAILED(rv) || !principal) {
             ReportError(cx, LOAD_ERROR_NOPRINCIPALS, uri);
             return false;
         }
 
-        WriteCachedScript(StartupCache::GetSingleton(),
-                          cachePath, cx, principal, script);
+        nsCString uriStr;
+        if (preloadCache && NS_SUCCEEDED(uri->GetSpec(uriStr))) {
+            ScriptPreloader::GetSingleton().NoteScript(uriStr, cachePath, script);
+        }
+
+        if (startupCache) {
+            JSAutoCompartment ac(cx, script);
+            WriteCachedScript(StartupCache::GetSingleton(),
+                              cachePath, cx, principal, script);
+>>>>>>> histedit
+        }
     }
 
     return true;
 }
 
 class AsyncScriptLoader : public nsIIncrementalStreamLoaderObserver
 {
 public:
@@ -395,17 +406,19 @@ AsyncScriptLoader::OnStreamComplete(nsII
     if (!PrepareScript(uri, cx, targetObj, spec.get(), mCharset,
                        reinterpret_cast<const char*>(aBuf), aLength,
                        mReuseGlobal, mWantReturnValue, &script, &function))
     {
         return NS_OK;
     }
 
     JS::Rooted<JS::Value> retval(cx);
-    if (EvalScript(cx, targetObj, &retval, uri, mCache, &script, function)) {
+    if (EvalScript(cx, targetObj, &retval, uri, mCache,
+                   mCache && !mWantReturnValue,
+                   &script, function)) {
         autoPromise.ResolvePromise(retval);
     }
 
     return NS_OK;
 }
 
 nsresult
 mozJSSubScriptLoader::ReadScriptAsync(nsIURI* uri,
@@ -626,19 +639,19 @@ mozJSSubScriptLoader::DoLoadSubScriptWit
     if (!JS::DescribeScriptedCaller(cx, &filename)) {
         // No scripted frame means we don't know who's calling, bail.
         return NS_ERROR_FAILURE;
     }
 
     JSAutoCompartment ac(cx, targetObj);
 
     // Suppress caching if we're compiling as content.
-    StartupCache* cache = (principal == mSystemPrincipal)
-                          ? StartupCache::GetSingleton()
-                          : nullptr;
+    bool ignoreCache = options.ignoreCache || principal != mSystemPrincipal;
+    StartupCache* cache = ignoreCache ? nullptr : StartupCache::GetSingleton();
+
     nsCOMPtr<nsIIOService> serv = do_GetService(NS_IOSERVICE_CONTRACTID);
     if (!serv) {
         ReportError(cx, NS_LITERAL_CSTRING(LOAD_ERROR_NOSERVICE));
         return NS_OK;
     }
 
     // Make sure to explicitly create the URI, since we'll need the
     // canonicalized spec.
@@ -681,18 +694,21 @@ mozJSSubScriptLoader::DoLoadSubScriptWit
     JSVersion version = JS_GetVersion(cx);
     nsAutoCString cachePath;
     cachePath.AppendPrintf("jssubloader/%d", version);
     PathifyURI(uri, cachePath);
 
     RootedFunction function(cx);
     RootedScript script(cx);
     if (cache && !options.ignoreCache) {
-        rv = ReadCachedScript(cache, cachePath, cx, mSystemPrincipal, &script);
-        if (NS_FAILED(rv)) {
+        if (!options.wantReturnValue)
+            script = ScriptPreloader::GetSingleton().GetCachedScript(cx, cachePath);
+        if (!script)
+            rv = ReadCachedScript(cache, cachePath, cx, mSystemPrincipal, &script);
+        if (NS_FAILED(rv) || !script) {
             // ReadCachedScript may have set a pending exception.
             JS_ClearPendingException(cx);
         }
     }
 
     // If we are doing an async load, trigger it and bail out.
     if (!script && options.async) {
         return ReadScriptAsync(uri, targetObj, options.charset, serv,
@@ -707,17 +723,19 @@ mozJSSubScriptLoader::DoLoadSubScriptWit
                         &function))
         {
             return NS_OK;
         }
     } else {
         cache = nullptr;
     }
 
-    Unused << EvalScript(cx, targetObj, retval, uri, !!cache, &script, function);
+    Unused << EvalScript(cx, targetObj, retval, uri, !!cache,
+                         !ignoreCache && !options.wantReturnValue,
+                         &script, function);
     return NS_OK;
 }
 
 /**
   * Let us compile scripts from a URI off the main thread.
   */
 
 class ScriptPrecompiler : public nsIIncrementalStreamLoaderObserver