Bug 1249123 - Add telemetry for __defineGetter__/__defineSetter__ |this| values. data-review=bsmedberg r=till
authorTom Schuster <evilpies@gmail.com>
Wed, 24 Feb 2016 13:27:12 +0100
changeset 321721 8a2c2d8fc91f7014c701db6ee7d15b2a1b461b01
parent 321720 ba56be94d03d8079358115e3def6a08e09d6f435
child 321722 417bac059dab26a1283843a00a041aebdb2f2813
push id5913
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 16:57:49 +0000
treeherdermozilla-beta@dcaf0a6fa115 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstill
bugs1249123
milestone47.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 1249123 - Add telemetry for __defineGetter__/__defineSetter__ |this| values. data-review=bsmedberg r=till
js/src/builtin/Object.js
js/src/builtin/SelfHostingDefines.h
js/src/jscompartment.h
js/src/jsfriendapi.h
js/src/vm/SelfHosting.cpp
js/xpconnect/src/XPCJSRuntime.cpp
toolkit/components/telemetry/Histograms.json
--- a/js/src/builtin/Object.js
+++ b/js/src/builtin/Object.js
@@ -57,20 +57,23 @@ function Object_toLocaleString() {
     var O = this;
 
     // Step 2.
     return callContentFunction(O.toString, O);
 }
 
 function ObjectDefineSetter(name, setter) {
     var object;
-    if (this === null || this === undefined)
+    if (this === null || this === undefined) {
+        AddContentTelemetry(JS_TELEMETRY_DEFINE_GETTER_SETTER_THIS_NULL_UNDEFINED, 1);
         object = global;
-    else
+    } else {
+        AddContentTelemetry(JS_TELEMETRY_DEFINE_GETTER_SETTER_THIS_NULL_UNDEFINED, 0);
         object = ToObject(this);
+    }
 
     if (!IsCallable(setter))
         ThrowTypeError(JSMSG_BAD_GETTER_OR_SETTER, "setter");
 
     var key = ToPropertyKey(name);
 
     var desc = {
         __proto__: null,
@@ -79,20 +82,23 @@ function ObjectDefineSetter(name, setter
         set: setter
     };
 
     std_Object_defineProperty(object, key, desc);
 }
 
 function ObjectDefineGetter(name, getter) {
     var object;
-    if (this === null || this === undefined)
+    if (this === null || this === undefined) {
+        AddContentTelemetry(JS_TELEMETRY_DEFINE_GETTER_SETTER_THIS_NULL_UNDEFINED, 1);
         object = global;
-    else
+    } else {
+        AddContentTelemetry(JS_TELEMETRY_DEFINE_GETTER_SETTER_THIS_NULL_UNDEFINED, 0);
         object = ToObject(this);
+    }
 
     if (!IsCallable(getter))
         ThrowTypeError(JSMSG_BAD_GETTER_OR_SETTER, "getter");
 
     var key = ToPropertyKey(name);
 
     var desc = {
         __proto__: null,
--- a/js/src/builtin/SelfHostingDefines.h
+++ b/js/src/builtin/SelfHostingDefines.h
@@ -58,9 +58,11 @@
 #define ITEM_KIND_KEY_AND_VALUE 2
 
 // NB: keep these in sync with the copy in jsfriendapi.h.
 #define JSITER_OWNONLY    0x8   /* iterate over obj's own properties only */
 #define JSITER_HIDDEN     0x10  /* also enumerate non-enumerable properties */
 #define JSITER_SYMBOLS    0x20  /* also include symbol property keys */
 #define JSITER_SYMBOLSONLY 0x40 /* exclude string property keys */
 
+#define JS_TELEMETRY_DEFINE_GETTER_SETTER_THIS_NULL_UNDEFINED 25
+
 #endif
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -268,16 +268,24 @@ struct JSCompartment
         // performance data we collect should not be improperly associated
         // to a group to which we do not belong anymore. For another thing,
         // we use `isSystem()` as part of the key to map compartments
         // to a `PerformanceGroup`, so if we do not unlink now, this will
         // be too late once we have updated `isSystem_`.
         performanceMonitoring.unlink();
         isSystem_ = isSystem;
     }
+
+    // Used to approximate non-content code when reporting telemetry.
+    inline bool isProbablySystemOrAddonCode() const {
+        if (creationOptions_.addonIdOrNull())
+            return true;
+
+        return isSystem_;
+    }
   private:
     JSPrincipals*                principals_;
     bool                         isSystem_;
   public:
     bool                         isSelfHosting;
     bool                         marked;
     bool                         warnedAboutFlagsArgument;
     bool                         warnedAboutExprClosure;
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -126,19 +126,24 @@ enum {
     JS_TELEMETRY_GC_NON_INCREMENTAL,
     JS_TELEMETRY_GC_SCC_SWEEP_TOTAL_MS,
     JS_TELEMETRY_GC_SCC_SWEEP_MAX_PAUSE_MS,
     JS_TELEMETRY_GC_MINOR_REASON,
     JS_TELEMETRY_GC_MINOR_REASON_LONG,
     JS_TELEMETRY_GC_MINOR_US,
     JS_TELEMETRY_DEPRECATED_LANGUAGE_EXTENSIONS_IN_CONTENT,
     JS_TELEMETRY_DEPRECATED_LANGUAGE_EXTENSIONS_IN_ADDONS,
-    JS_TELEMETRY_ADDON_EXCEPTIONS
+    JS_TELEMETRY_ADDON_EXCEPTIONS,
+    JS_TELEMETRY_DEFINE_GETTER_SETTER_THIS_NULL_UNDEFINED,
+    JS_TELEMETRY_END
 };
 
+static_assert(JS_TELEMETRY_DEFINE_GETTER_SETTER_THIS_NULL_UNDEFINED == 25,
+              "This value needs to be kept in sync with SelfHostingDefines.h");
+
 typedef void
 (*JSAccumulateTelemetryDataCallback)(int id, uint32_t sample, const char* key);
 
 extern JS_FRIEND_API(void)
 JS_SetAccumulateTelemetryCallback(JSRuntime* rt, JSAccumulateTelemetryDataCallback callback);
 
 extern JS_FRIEND_API(JSPrincipals*)
 JS_GetCompartmentPrincipals(JSCompartment* compartment);
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -1469,16 +1469,33 @@ intrinsic_LocalTZA(JSContext* cx, unsign
     CallArgs args = CallArgsFromVp(argc, vp);
     MOZ_ASSERT(args.length() == 0, "the LocalTZA intrinsic takes no arguments");
 
     args.rval().setDouble(DateTimeInfo::localTZA());
     return true;
 }
 
 static bool
+intrinsic_AddContentTelemetry(JSContext* cx, unsigned argc, Value* vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    MOZ_ASSERT(args.length() == 2);
+
+    int id = args[0].toInt32();
+    MOZ_ASSERT(id < JS_TELEMETRY_END);
+    MOZ_ASSERT(id >= 0);
+
+    if (!cx->compartment()->isProbablySystemOrAddonCode())
+        cx->runtime()->addTelemetry(id, args[1].toInt32());
+
+    args.rval().setUndefined();
+    return true;
+}
+
+static bool
 intrinsic_ConstructFunction(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     MOZ_ASSERT(args.length() == 2);
     MOZ_ASSERT(args[0].toObject().is<JSFunction>());
     MOZ_ASSERT(args[1].toObject().is<ArrayObject>());
 
     RootedArrayObject argsList(cx, &args[1].toObject().as<ArrayObject>());
@@ -1799,16 +1816,17 @@ static const JSFunctionSpec intrinsic_fu
     JS_FN("DumpMessage",             intrinsic_DumpMessage,             1,0),
     JS_FN("OwnPropertyKeys",         intrinsic_OwnPropertyKeys,         1,0),
     JS_FN("MakeDefaultConstructor",  intrinsic_MakeDefaultConstructor,  2,0),
     JS_FN("_ConstructorForTypedArray", intrinsic_ConstructorForTypedArray, 1,0),
     JS_FN("DecompileArg",            intrinsic_DecompileArg,            2,0),
     JS_FN("_FinishBoundFunctionInit", intrinsic_FinishBoundFunctionInit, 4,0),
     JS_FN("RuntimeDefaultLocale",    intrinsic_RuntimeDefaultLocale,    0,0),
     JS_FN("LocalTZA",                intrinsic_LocalTZA,                0,0),
+    JS_FN("AddContentTelemetry",     intrinsic_AddContentTelemetry,     2,0),
 
     JS_INLINABLE_FN("_IsConstructing", intrinsic_IsConstructing,        0,0,
                     IntrinsicIsConstructing),
     JS_INLINABLE_FN("SubstringKernel", intrinsic_SubstringKernel,       3,0,
                     IntrinsicSubstringKernel),
     JS_INLINABLE_FN("_DefineDataProperty",              intrinsic_DefineDataProperty,      4,0,
                     IntrinsicDefineDataProperty),
     JS_INLINABLE_FN("UnsafeSetReservedSlot",            intrinsic_UnsafeSetReservedSlot,   3,0,
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -3202,16 +3202,20 @@ AccumulateTelemetryCallback(int id, uint
         Telemetry::Accumulate(Telemetry::JS_DEPRECATED_LANGUAGE_EXTENSIONS_IN_CONTENT, sample);
         break;
       case JS_TELEMETRY_DEPRECATED_LANGUAGE_EXTENSIONS_IN_ADDONS:
         Telemetry::Accumulate(Telemetry::JS_DEPRECATED_LANGUAGE_EXTENSIONS_IN_ADDONS, sample);
         break;
       case JS_TELEMETRY_ADDON_EXCEPTIONS:
         Telemetry::Accumulate(Telemetry::JS_TELEMETRY_ADDON_EXCEPTIONS, nsDependentCString(key), sample);
         break;
+      case JS_TELEMETRY_DEFINE_GETTER_SETTER_THIS_NULL_UNDEFINED:
+        MOZ_ASSERT(sample == 0 || sample == 1);
+        Telemetry::Accumulate(Telemetry::JS_DEFINE_GETTER_SETTER_THIS_NULL_UNDEFINED, sample);
+        break;
       default:
         MOZ_ASSERT_UNREACHABLE("Unexpected JS_TELEMETRY id");
     }
 }
 
 static void
 CompartmentNameCallback(JSRuntime* rt, JSCompartment* comp,
                         char* buf, size_t bufsize)
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -519,16 +519,24 @@
   },
   "JS_DEPRECATED_LANGUAGE_EXTENSIONS_IN_ADDONS": {
     "alert_emails": ["jdemooij@mozilla.com"],
     "expires_in_version": "never",
     "kind": "enumerated",
     "n_values": 10,
     "description": "Use of SpiderMonkey's deprecated language extensions in add-ons: ForEach=0, DestructuringForIn=1 (obsolete), LegacyGenerator=2, ExpressionClosure=3, LetBlock=4 (obsolete), LetExpression=5 (obsolete), NoSuchMethod=6 (obsolete), FlagsArgument=7, RegExpSourceProp=8 (obsolete), RestoredRegExpStatics=9 (obsolete), BlockScopeFunRedecl=10"
   },
+  "JS_DEFINE_GETTER_SETTER_THIS_NULL_UNDEFINED": {
+    "alert_emails": ["jdemooij@mozilla.com"],
+    "bug_numbers": [1249123],
+    "expires_in_version": "55",
+    "kind": "boolean",
+    "releaseChannelCollection": "opt-out",
+    "description": "__defineGetter__ or __defineSetter__ invoked with 1 = null/undefined or 0 = everything else as |this| value"
+  },
   "XUL_CACHE_DISABLED": {
     "expires_in_version": "default",
     "kind": "flag",
     "description": "XUL cache was disabled"
   },
   "MEMORY_RESIDENT_FAST": {
     "alert_emails": ["memshrink-telemetry-alerts@mozilla.com"],
     "expires_in_version": "never",