Bug 834936 - Temporarily load JSMs into fewer compartments; r=rnewman
authorGregory Szorc <gps@mozilla.com>
Sun, 27 Jan 2013 11:26:48 -0800
changeset 120043 b0d6d514d3414193b7608e1983aaa87dc1446943
parent 119979 aafdf3566582e9bf2635c03cf40f6173e7a79817
child 120044 3742b1608ddbd4c9c75bf80c00ad9b687adf49dc
push id24236
push usergszorc@mozilla.com
push dateMon, 28 Jan 2013 19:05:22 +0000
treeherdermozilla-central@3742b1608ddb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrnewman
bugs834936
milestone21.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 834936 - Temporarily load JSMs into fewer compartments; r=rnewman We concatenate JSMs together so we use less compartments and therefore less memory. This is intended to be a temporary hack until the overhead of compartments is less.
services/common/Makefile.in
services/common/bagheeraclient.js
services/datareporting/DataReportingService.js
services/datareporting/Makefile.in
services/datareporting/policy.jsm
services/datareporting/sessions.jsm
services/healthreport/HealthReport.jsm
services/healthreport/HealthReportComponents.manifest
services/healthreport/Makefile.in
services/healthreport/healthreporter.jsm
services/healthreport/modules-testing/utils.jsm
services/healthreport/profile.jsm
services/healthreport/providers.jsm
services/healthreport/tests/xpcshell/test_load_modules.js
services/metrics/Makefile.in
services/metrics/Metrics.jsm
services/metrics/collector.jsm
services/metrics/dataprovider.jsm
services/metrics/storage.jsm
services/metrics/tests/xpcshell/test_load_modules.js
--- a/services/common/Makefile.in
+++ b/services/common/Makefile.in
@@ -6,17 +6,16 @@ DEPTH     = @DEPTH@
 topsrcdir = @top_srcdir@
 srcdir    = @srcdir@
 VPATH     = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 modules := \
   async.js \
-  bagheeraclient.js \
   log4moz.js \
   observers.js \
   preferences.js \
   rest.js \
   storageservice.js \
   stringbundle.js \
   tokenserverclient.js \
   utils.js \
@@ -40,16 +39,20 @@ PREF_JS_EXPORTS = $(srcdir)/services-com
 
 MODULES_FILES := $(modules)
 MODULES_DEST = $(FINAL_TARGET)/modules/services-common
 INSTALL_TARGETS += MODULES
 
 TESTING_JS_MODULES := $(addprefix modules-testing/,$(testing_modules))
 TESTING_JS_MODULE_DIR := services-common
 
+PP_JS_MODULES := bagheeraclient.js
+PP_JS_MODULES_PATH = $(FINAL_TARGET)/modules/services-common
+PP_TARGETS += PP_JS_MODULES
+
 include $(topsrcdir)/config/rules.mk
 
 # What follows is a helper to launch a standalone storage server instance.
 # Most of the code lives in a Python script in the tests directory. If we
 # ever consolidate our Python code, and/or have a supplemental driver for the
 # build system, this can go away.
 
 server_port := 8080
--- a/services/common/bagheeraclient.js
+++ b/services/common/bagheeraclient.js
@@ -6,23 +6,27 @@
  * This file contains a client API for the Bagheera data storage service.
  *
  * Information about Bagheera is available at
  * https://github.com/mozilla-metrics/bagheera
  */
 
 "use strict";
 
+#ifndef MERGED_COMPARTMENT
+
 this.EXPORTED_SYMBOLS = [
   "BagheeraClient",
   "BagheeraClientRequestResult",
 ];
 
 const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
 
+#endif
+
 Cu.import("resource://gre/modules/commonjs/promise/core.js");
 Cu.import("resource://services-common/log4moz.js");
 Cu.import("resource://services-common/rest.js");
 Cu.import("resource://services-common/utils.js");
 
 
 /**
  * Represents the result of a Bagheera request.
--- a/services/datareporting/DataReportingService.js
+++ b/services/datareporting/DataReportingService.js
@@ -1,18 +1,16 @@
 /* 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/. */
 
 "use strict";
 
 const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
 
-Cu.import("resource://gre/modules/services/datareporting/policy.jsm");
-Cu.import("resource://gre/modules/services/datareporting/sessions.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://services-common/observers.js");
 Cu.import("resource://services-common/preferences.js");
 Cu.import("resource://services-common/utils.js");
 
 
 const ROOT_BRANCH = "datareporting.";
 const POLICY_BRANCH = ROOT_BRANCH + "policy.";
@@ -218,17 +216,17 @@ DataReportingService.prototype = Object.
     return this._healthReporter;
   },
 
   _loadHealthReporter: function () {
     let ns = {};
     // Lazy import so application startup isn't adversely affected.
 
     Cu.import("resource://gre/modules/Task.jsm", ns);
-    Cu.import("resource://gre/modules/services/healthreport/healthreporter.jsm", ns);
+    Cu.import("resource://gre/modules/HealthReport.jsm", ns);
     Cu.import("resource://services-common/log4moz.js", ns);
 
     // How many times will we rewrite this code before rolling it up into a
     // generic module? See also bug 451283.
     const LOGGERS = [
       "Services.DataReporting",
       "Services.HealthReport",
       "Services.Metrics",
@@ -252,8 +250,15 @@ DataReportingService.prototype = Object.
     this._healthReporter = new ns.HealthReporter(HEALTHREPORT_BRANCH,
                                                  this.policy,
                                                  this.sessionRecorder);
   },
 });
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([DataReportingService]);
 
+#define MERGED_COMPARTMENT
+
+#include policy.jsm
+;
+#include sessions.jsm
+;
+
--- a/services/datareporting/Makefile.in
+++ b/services/datareporting/Makefile.in
@@ -6,21 +6,24 @@ DEPTH     = @DEPTH@
 topsrcdir = @top_srcdir@
 srcdir    = @srcdir@
 VPATH     = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 TEST_DIRS += tests
 
-MODULES_FILES := policy.jsm sessions.jsm
-MODULES_DEST = $(FINAL_TARGET)/modules/services/datareporting
-INSTALL_TARGETS += MODULES
+MODULES := policy.jsm sessions.jsm
+MODULES_PATH = $(FINAL_TARGET)/modules/services/datareporting
+PP_TARGETS += MODULES
 
 TESTING_JS_MODULES := $(addprefix modules-testing/,mocks.jsm)
 TESTING_JS_MODULE_DIR := services/datareporting
 
 EXTRA_COMPONENTS := \
   DataReporting.manifest \
+  $(NULL)
+
+EXTRA_PP_COMPONENTS := \
   DataReportingService.js \
   $(NULL)
 
 include $(topsrcdir)/config/rules.mk
--- a/services/datareporting/policy.jsm
+++ b/services/datareporting/policy.jsm
@@ -10,23 +10,27 @@
  *
  * DataReportingPolicy is both a driver for data reporting notification
  * (a true policy) and the driver for FHR data submission. The latter should
  * eventually be split into its own type and module.
  */
 
 "use strict";
 
+#ifndef MERGED_COMPARTMENT
+
 this.EXPORTED_SYMBOLS = [
   "DataSubmissionRequest", // For test use only.
   "DataReportingPolicy",
 ];
 
 const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
 
+#endif
+
 Cu.import("resource://gre/modules/commonjs/promise/core.js");
 Cu.import("resource://services-common/log4moz.js");
 Cu.import("resource://services-common/utils.js");
 
 const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
 
 // Used as a sanity lower bound for dates stored in prefs. This module was
 // implemented in 2012, so any earlier dates indicate an incorrect clock.
--- a/services/datareporting/sessions.jsm
+++ b/services/datareporting/sessions.jsm
@@ -1,20 +1,24 @@
 /* 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/. */
 
 "use strict";
 
+#ifndef MERGED_COMPARTMENT
+
 this.EXPORTED_SYMBOLS = [
   "SessionRecorder",
 ];
 
 const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
 
+#endif
+
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://services-common/log4moz.js");
 Cu.import("resource://services-common/preferences.js");
 Cu.import("resource://services-common/utils.js");
 
 
 // We automatically prune sessions older than this.
 const MAX_SESSION_AGE_MS = 7 * 24 * 60 * 60 * 1000; // 7 days.
new file mode 100644
--- /dev/null
+++ b/services/healthreport/HealthReport.jsm
@@ -0,0 +1,37 @@
+/* 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/. */
+
+"use strict";
+
+this.EXPORTED_SYMBOLS = [
+  "HealthReporter",
+  "AddonsProvider",
+  "AppInfoProvider",
+  "CrashesProvider",
+  "Metrics",
+  "ProfileMetadataProvider",
+  "SessionsProvider",
+  "SysInfoProvider",
+];
+
+const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
+
+const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
+
+// We concatenate the JSMs together to eliminate compartment overhead.
+// This is a giant hack until compartment overhead is no longer an
+// issue.
+#define MERGED_COMPARTMENT
+
+#include ../common/bagheeraclient.js
+;
+#include ../metrics/Metrics.jsm
+;
+#include healthreporter.jsm
+;
+#include profile.jsm
+;
+#include providers.jsm
+;
+
--- a/services/healthreport/HealthReportComponents.manifest
+++ b/services/healthreport/HealthReportComponents.manifest
@@ -1,8 +1,8 @@
 # Register Firefox Health Report providers.
-category healthreport-js-provider AddonsProvider resource://gre/modules/services/healthreport/providers.jsm
-category healthreport-js-provider AppInfoProvider resource://gre/modules/services/healthreport/providers.jsm
-category healthreport-js-provider CrashesProvider resource://gre/modules/services/healthreport/providers.jsm
-category healthreport-js-provider SysInfoProvider resource://gre/modules/services/healthreport/providers.jsm
-category healthreport-js-provider ProfileMetadataProvider resource://gre/modules/services/healthreport/profile.jsm
-category healthreport-js-provider SessionsProvider resource://gre/modules/services/healthreport/providers.jsm
+category healthreport-js-provider AddonsProvider resource://gre/modules/HealthReport.jsm
+category healthreport-js-provider AppInfoProvider resource://gre/modules/HealthReport.jsm
+category healthreport-js-provider CrashesProvider resource://gre/modules/HealthReport.jsm
+category healthreport-js-provider SysInfoProvider resource://gre/modules/HealthReport.jsm
+category healthreport-js-provider ProfileMetadataProvider resource://gre/modules/HealthReport.jsm
+category healthreport-js-provider SessionsProvider resource://gre/modules/HealthReport.jsm
 
--- a/services/healthreport/Makefile.in
+++ b/services/healthreport/Makefile.in
@@ -16,19 +16,23 @@ modules := \
   $(NULL)
 
 testing_modules := \
   utils.jsm \
   $(NULL)
 
 TEST_DIRS += tests
 
-MODULES_FILES := $(modules)
-MODULES_DEST = $(FINAL_TARGET)/modules/services/healthreport
-INSTALL_TARGETS += MODULES
+MAIN_JS_MODULE := HealthReport.jsm
+MAIN_JS_MODULE_PATH = $(FINAL_TARGET)/modules
+PP_TARGETS += MAIN_JS_MODULE
+
+MODULES := $(modules)
+MODULES_PATH = $(FINAL_TARGET)/modules/services/healthreport
+PP_TARGETS += MODULES
 
 TESTING_JS_MODULES := $(addprefix modules-testing/,$(testing_modules))
 TESTING_JS_MODULE_DIR := services/healthreport
 
 EXTRA_COMPONENTS := \
   HealthReportComponents.manifest \
   $(NULL)
 
--- a/services/healthreport/healthreporter.jsm
+++ b/services/healthreport/healthreporter.jsm
@@ -1,37 +1,42 @@
 /* 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/. */
 
 "use strict";
 
+#ifndef MERGED_COMPARTMENT
+
 this.EXPORTED_SYMBOLS = ["HealthReporter"];
 
 const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
 
+const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
+
+Cu.import("resource://gre/modules/Metrics.jsm");
+Cu.import("resource://services-common/bagheeraclient.js");
+#endif
+
 Cu.import("resource://services-common/async.js");
-Cu.import("resource://services-common/bagheeraclient.js");
 Cu.import("resource://services-common/log4moz.js");
 Cu.import("resource://services-common/preferences.js");
 Cu.import("resource://services-common/utils.js");
 Cu.import("resource://gre/modules/commonjs/promise/core.js");
-Cu.import("resource://gre/modules/Metrics.jsm");
 Cu.import("resource://gre/modules/osfile.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/Task.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 
 // Oldest year to allow in date preferences. This module was implemented in
 // 2012 and no dates older than that should be encountered.
 const OLDEST_ALLOWED_YEAR = 2012;
 
 const DAYS_IN_PAYLOAD = 180;
-const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
 
 const DEFAULT_DATABASE_NAME = "healthreport.sqlite";
 
 
 /**
  * Coordinates collection and submission of health report metrics.
  *
  * This is the main type for Firefox Health Report. It glues all the
--- a/services/healthreport/modules-testing/utils.jsm
+++ b/services/healthreport/modules-testing/utils.jsm
@@ -15,17 +15,17 @@ this.EXPORTED_SYMBOLS = [
 
 const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
 
 Cu.import("resource://gre/modules/commonjs/promise/core.js");
 Cu.import("resource://gre/modules/FileUtils.jsm");
 Cu.import("resource://gre/modules/osfile.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/services-common/utils.js");
-Cu.import("resource://gre/modules/services/healthreport/healthreporter.jsm");
+Cu.import("resource://gre/modules/HealthReport.jsm");
 
 
 let APP_INFO = {
   vendor: "Mozilla",
   name: "xpcshell",
   ID: "xpcshell@tests.mozilla.org",
   version: "1",
   appBuildID: "20121107",
--- a/services/healthreport/profile.jsm
+++ b/services/healthreport/profile.jsm
@@ -1,27 +1,33 @@
 /* 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/. */
 
 "use strict";
 
+#ifndef MERGED_COMPARTMENT
+
 this.EXPORTED_SYMBOLS = [
   "ProfileCreationTimeAccessor",
   "ProfileMetadataProvider",
 ];
 
 const {utils: Cu, classes: Cc, interfaces: Ci} = Components;
 
+const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
+
+Cu.import("resource://gre/modules/Metrics.jsm");
+
+#endif
+
 const DEFAULT_PROFILE_MEASUREMENT_NAME = "age";
-const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
 const REQUIRED_UINT32_TYPE = {type: "TYPE_UINT32"};
 
 Cu.import("resource://gre/modules/commonjs/promise/core.js");
-Cu.import("resource://gre/modules/Metrics.jsm");
 Cu.import("resource://gre/modules/osfile.jsm")
 Cu.import("resource://gre/modules/Task.jsm");
 Cu.import("resource://services-common/log4moz.js");
 Cu.import("resource://services-common/utils.js");
 
 // Profile creation time access.
 // This is separate from the provider to simplify testing and enable extraction
 // to a shared location in the future.
--- a/services/healthreport/providers.jsm
+++ b/services/healthreport/providers.jsm
@@ -9,30 +9,35 @@
  * overhead of JS compartments (which are created for each module), we
  * currently have all the code in one file. When the overhead of
  * compartments reaches a reasonable level, this file should be split
  * up.
  */
 
 "use strict";
 
+#ifndef MERGED_COMPARTMENT
+
 this.EXPORTED_SYMBOLS = [
   "AddonsProvider",
   "AppInfoProvider",
   "CrashDirectoryService",
   "CrashesProvider",
   "SessionsProvider",
   "SysInfoProvider",
 ];
 
 const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
 
+Cu.import("resource://gre/modules/Metrics.jsm");
+
+#endif
+
 Cu.import("resource://gre/modules/commonjs/promise/core.js");
 Cu.import("resource://gre/modules/osfile.jsm");
-Cu.import("resource://gre/modules/Metrics.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/Task.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://services-common/preferences.js");
 Cu.import("resource://services-common/utils.js");
 
 XPCOMUtils.defineLazyModuleGetter(this, "AddonManager",
                                   "resource://gre/modules/AddonManager.jsm");
--- a/services/healthreport/tests/xpcshell/test_load_modules.js
+++ b/services/healthreport/tests/xpcshell/test_load_modules.js
@@ -9,10 +9,12 @@ const modules = [
   "providers.jsm",
 ];
 
 function run_test() {
   for (let m of modules) {
     let resource = "resource://gre/modules/services/healthreport/" + m;
     Components.utils.import(resource, {});
   }
+
+  Components.utils.import("resource://gre/modules/HealthReport.jsm", {});
 }
 
--- a/services/metrics/Makefile.in
+++ b/services/metrics/Makefile.in
@@ -16,20 +16,22 @@ modules := \
   $(NULL)
 
 testing_modules := \
   mocks.jsm \
   $(NULL)
 
 # We install Metrics.jsm into the "main" JSM repository and the rest in
 # services. External consumers should only go through Metrics.jsm.
-EXTRA_JS_MODULES := Metrics.jsm
+MAIN_JS_MODULE := Metrics.jsm
+MAIN_JS_MODULE_PATH = $(FINAL_TARGET)/modules
+PP_TARGETS += MAIN_JS_MODULE
 
 TEST_DIRS += tests
 
-MODULES_FILES := $(modules)
-MODULES_DEST = $(FINAL_TARGET)/modules/services/metrics
-INSTALL_TARGETS += MODULES
+JS_MODULES := $(modules)
+JS_MODULES_PATH = $(FINAL_TARGET)/modules/services/metrics
+PP_TARGETS += JS_MODULES
 
 TESTING_JS_MODULES := $(addprefix modules-testing/,$(testing_modules))
 TESTING_JS_MODULE_DIR := services/metrics
 
 include $(topsrcdir)/config/rules.mk
--- a/services/metrics/Metrics.jsm
+++ b/services/metrics/Metrics.jsm
@@ -1,22 +1,35 @@
 /* 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/. */
 
 "use strict";
 
+#ifndef MERGED_COMPARTMENT
+
 this.EXPORTED_SYMBOLS = ["Metrics"];
 
 const {utils: Cu} = Components;
 
-Cu.import("resource://gre/modules/services/metrics/collector.jsm");
-Cu.import("resource://gre/modules/services/metrics/dataprovider.jsm");
-Cu.import("resource://gre/modules/services/metrics/storage.jsm");
+const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
+
+#endif
 
+// We concatenate the JSMs together to eliminate compartment overhead.
+// This is a giant hack until compartment overhead is no longer an
+// issue.
+#define MERGED_COMPARTMENT
+
+#include collector.jsm
+;
+#include dataprovider.jsm
+;
+#include storage.jsm
+;
 
 this.Metrics = {
   Collector: Collector,
   DailyValues: DailyValues,
   Measurement: Measurement,
   Provider: Provider,
   Storage: MetricsStorageBackend,
   dateToDays: dateToDays,
--- a/services/metrics/collector.jsm
+++ b/services/metrics/collector.jsm
@@ -1,23 +1,26 @@
 /* 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/. */
 
 "use strict";
 
+#ifndef MERGED_COMPARTMENT
 this.EXPORTED_SYMBOLS = ["Collector"];
 
 const {utils: Cu} = Components;
 
+Cu.import("resource://gre/modules/services/metrics/dataprovider.jsm");
+#endif
+
 Cu.import("resource://gre/modules/commonjs/promise/core.js");
 Cu.import("resource://gre/modules/Task.jsm");
 Cu.import("resource://services-common/log4moz.js");
 Cu.import("resource://services-common/utils.js");
-Cu.import("resource://gre/modules/services/metrics/dataprovider.jsm");
 
 
 /**
  * Handles and coordinates the collection of metrics data from providers.
  *
  * This provides an interface for managing `Metrics.Provider` instances. It
  * provides APIs for bulk collection of data.
  */
--- a/services/metrics/dataprovider.jsm
+++ b/services/metrics/dataprovider.jsm
@@ -1,30 +1,34 @@
 /* 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/. */
 
 "use strict";
 
+#ifndef MERGED_COMPARTMENT
+
 this.EXPORTED_SYMBOLS = [
   "Measurement",
   "Provider",
 ];
 
 const {utils: Cu} = Components;
 
+const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
+
+#endif
+
 Cu.import("resource://gre/modules/commonjs/promise/core.js");
 Cu.import("resource://gre/modules/Task.jsm");
 Cu.import("resource://services-common/log4moz.js");
 Cu.import("resource://services-common/preferences.js");
 Cu.import("resource://services-common/utils.js");
 
 
-const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
-
 
 /**
  * Represents a collection of related pieces/fields of data.
  *
  * This is an abstract base type. Providers implement child types that
  * implement core functions such as `registerStorage`.
  *
  * This type provides the primary interface for storing, retrieving, and
--- a/services/metrics/storage.jsm
+++ b/services/metrics/storage.jsm
@@ -1,32 +1,36 @@
 /* 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/. */
 
 "use strict";
 
+#ifndef MERGED_COMPARTMENT
+
 this.EXPORTED_SYMBOLS = [
   "DailyValues",
   "MetricsStorageBackend",
   "dateToDays",
   "daysToDate",
 ];
 
 const {utils: Cu} = Components;
 
+const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
+
+#endif
+
 Cu.import("resource://gre/modules/commonjs/promise/core.js");
 Cu.import("resource://gre/modules/Sqlite.jsm");
 Cu.import("resource://gre/modules/Task.jsm");
 Cu.import("resource://services-common/log4moz.js");
 Cu.import("resource://services-common/utils.js");
 
 
-const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
-
 // These do not account for leap seconds. Meh.
 function dateToDays(date) {
   return Math.floor(date.getTime() / MILLISECONDS_PER_DAY);
 }
 
 function daysToDate(days) {
   return new Date(days * MILLISECONDS_PER_DAY);
 }
--- a/services/metrics/tests/xpcshell/test_load_modules.js
+++ b/services/metrics/tests/xpcshell/test_load_modules.js
@@ -14,16 +14,18 @@ const test_modules = [
 ];
 
 function run_test() {
   for (let m of modules) {
     let resource = "resource://gre/modules/services/metrics/" + m;
     Components.utils.import(resource, {});
   }
 
+  Components.utils.import("resource://gre/modules/Metrics.jsm", {});
+
   for (let m of test_modules) {
     let resource = "resource://testing-common/services/metrics/" + m;
     Components.utils.import(resource, {});
   }
 
   Components.utils.import("resource://gre/modules/Metrics.jsm", {});
 }