Bug 1388221: Optimize defineLazyModuleGetter for already-loaded modules. r?florian
Creating and populating temporary export objects is fairly expensive. Defining
and then redefining lazy getters is sometimes even more expensive.
Caching the export objects from module imports, and immediately defining
properties from already-imported modules appears to save a considerable amount
of overhead at startup.
MozReview-Commit-ID: 2jR1i0WpIcw
--- a/js/xpconnect/loader/XPCOMUtils.jsm
+++ b/js/xpconnect/loader/XPCOMUtils.jsm
@@ -90,16 +90,18 @@
this.EXPORTED_SYMBOLS = [ "XPCOMUtils" ];
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
const Cu = Components.utils;
+const modules = {};
+
this.XPCOMUtils = {
/**
* Generate a QueryInterface implementation. The returned function must be
* assigned to the 'QueryInterface' property of a JS object. When invoked on
* that object, it checks if the given iid is listed in the |interfaces|
* param, and if it is, returns |this| (the object it was called on).
* If the JS object has a classInfo property it'll be returned for the
* nsIClassInfo IID, generateCI can be used to generate the classInfo
@@ -298,30 +300,43 @@ this.XPCOMUtils = {
aPreLambda, aPostLambda, aProxy)
{
let proxy = aProxy || {};
if (typeof(aPreLambda) === "function") {
aPreLambda.apply(proxy);
}
- this.defineLazyGetter(aObject, aName, function XPCU_moduleLambda() {
- var temp = {};
+ function XPCU_moduleLambda() {
try {
- Cu.import(aResource, temp);
+ let temp;
+ if (aResource in modules) {
+ temp = modules[aResource];
+ } else {
+ temp = {};
+ Cu.import(aResource, temp);
+ modules[aResource] = temp;
+ }
if (typeof(aPostLambda) === "function") {
aPostLambda.apply(proxy);
}
+
+ return temp[aSymbol || aName];
} catch (ex) {
Cu.reportError("Failed to load module " + aResource + ".");
throw ex;
}
- return temp[aSymbol || aName];
- });
+ }
+
+ if (!aPostLambda && (aResource in modules || Cu.isModuleLoaded(aResource))) {
+ aObject[aSymbol || aName] = XPCU_moduleLambda();
+ } else {
+ this.defineLazyGetter(aObject, aName, XPCU_moduleLambda);
+ }
},
/**
* Defines a getter on a specified object for preference value. The
* preference is read the first time that the property is accessed,
* and is thereafter kept up-to-date using a preference observer.
*
* @param aObject