js/src/perf/jsperf.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "perf/jsperf.h"
     8 #include "jscntxt.h" /* for error messages */
     9 #include "jsobj.h" /* for unwrapping without a context */
    11 using namespace JS;
    13 // You cannot forward-declare a static object in C++, so instead
    14 // we have to forward-declare the helper function that refers to it.
    15 static PerfMeasurement* GetPM(JSContext* cx, JS::HandleValue value, const char* fname);
    17 // Property access
    19 #define GETTER(name)                                                    \
    20     static bool                                                         \
    21     pm_get_##name(JSContext* cx, unsigned argc, Value *vp)              \
    22     {                                                                   \
    23         CallArgs args = CallArgsFromVp(argc, vp);                       \
    24         PerfMeasurement* p = GetPM(cx, args.thisv(), #name);            \
    25         if (!p)                                                         \
    26             return false;                                               \
    27         args.rval().setNumber(double(p->name));                         \
    28         return true;                                                    \
    29     }
    31 GETTER(cpu_cycles)
    32 GETTER(instructions)
    33 GETTER(cache_references)
    34 GETTER(cache_misses)
    35 GETTER(branch_instructions)
    36 GETTER(branch_misses)
    37 GETTER(bus_cycles)
    38 GETTER(page_faults)
    39 GETTER(major_page_faults)
    40 GETTER(context_switches)
    41 GETTER(cpu_migrations)
    42 GETTER(eventsMeasured)
    44 #undef GETTER
    46 // Calls
    48 static bool
    49 pm_start(JSContext* cx, unsigned argc, jsval* vp)
    50 {
    51     CallArgs args = CallArgsFromVp(argc, vp);
    52     PerfMeasurement* p = GetPM(cx, args.thisv(), "start");
    53     if (!p)
    54         return false;
    56     p->start();
    57     args.rval().setUndefined();
    58     return true;
    59 }
    61 static bool
    62 pm_stop(JSContext* cx, unsigned argc, jsval* vp)
    63 {
    64     CallArgs args = CallArgsFromVp(argc, vp);
    65     PerfMeasurement* p = GetPM(cx, args.thisv(), "stop");
    66     if (!p)
    67         return false;
    69     p->stop();
    70     args.rval().setUndefined();
    71     return true;
    72 }
    74 static bool
    75 pm_reset(JSContext* cx, unsigned argc, jsval* vp)
    76 {
    77     CallArgs args = CallArgsFromVp(argc, vp);
    78     PerfMeasurement* p = GetPM(cx, args.thisv(), "reset");
    79     if (!p)
    80         return false;
    82     p->reset();
    83     args.rval().setUndefined();
    84     return true;
    85 }
    87 static bool
    88 pm_canMeasureSomething(JSContext* cx, unsigned argc, jsval* vp)
    89 {
    90     CallArgs args = CallArgsFromVp(argc, vp);
    91     PerfMeasurement* p = GetPM(cx, args.thisv(), "canMeasureSomething");
    92     if (!p)
    93         return false;
    95     args.rval().setBoolean(p->canMeasureSomething());
    96     return true;
    97 }
    99 static const uint8_t PM_FATTRS = JSPROP_READONLY | JSPROP_PERMANENT;
   100 static const JSFunctionSpec pm_fns[] = {
   101     JS_FN("start",               pm_start,               0, PM_FATTRS),
   102     JS_FN("stop",                pm_stop,                0, PM_FATTRS),
   103     JS_FN("reset",               pm_reset,               0, PM_FATTRS),
   104     JS_FN("canMeasureSomething", pm_canMeasureSomething, 0, PM_FATTRS),
   105     JS_FS_END
   106 };
   108 static const uint8_t PM_PATTRS =
   109     JSPROP_ENUMERATE | JSPROP_PERMANENT;
   111 #define GETTER(name)                            \
   112     JS_PSG(#name, pm_get_##name, PM_PATTRS)
   114 static const JSPropertySpec pm_props[] = {
   115     GETTER(cpu_cycles),
   116     GETTER(instructions),
   117     GETTER(cache_references),
   118     GETTER(cache_misses),
   119     GETTER(branch_instructions),
   120     GETTER(branch_misses),
   121     GETTER(bus_cycles),
   122     GETTER(page_faults),
   123     GETTER(major_page_faults),
   124     GETTER(context_switches),
   125     GETTER(cpu_migrations),
   126     GETTER(eventsMeasured),
   127     JS_PS_END
   128 };
   130 #undef GETTER
   132 // If this were C++ these would be "static const" members.
   134 static const uint8_t PM_CATTRS = JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT;
   136 #define CONSTANT(name) { #name, PerfMeasurement::name }
   138 static const struct pm_const {
   139     const char *name;
   140     PerfMeasurement::EventMask value;
   141 } pm_consts[] = {
   142     CONSTANT(CPU_CYCLES),
   143     CONSTANT(INSTRUCTIONS),
   144     CONSTANT(CACHE_REFERENCES),
   145     CONSTANT(CACHE_MISSES),
   146     CONSTANT(BRANCH_INSTRUCTIONS),
   147     CONSTANT(BRANCH_MISSES),
   148     CONSTANT(BUS_CYCLES),
   149     CONSTANT(PAGE_FAULTS),
   150     CONSTANT(MAJOR_PAGE_FAULTS),
   151     CONSTANT(CONTEXT_SWITCHES),
   152     CONSTANT(CPU_MIGRATIONS),
   153     CONSTANT(ALL),
   154     CONSTANT(NUM_MEASURABLE_EVENTS),
   155     { 0, PerfMeasurement::EventMask(0) }
   156 };
   158 #undef CONSTANT
   160 static bool pm_construct(JSContext* cx, unsigned argc, jsval* vp);
   161 static void pm_finalize(JSFreeOp* fop, JSObject* obj);
   163 static const JSClass pm_class = {
   164     "PerfMeasurement", JSCLASS_HAS_PRIVATE,
   165     JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
   166     JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, pm_finalize
   167 };
   169 // Constructor and destructor
   171 static bool
   172 pm_construct(JSContext* cx, unsigned argc, jsval* vp)
   173 {
   174     CallArgs args = CallArgsFromVp(argc, vp);
   176     uint32_t mask;
   177     if (!args.hasDefined(0)) {
   178         js_ReportMissingArg(cx, args.calleev(), 0);
   179         return false;
   180     }
   181     if (!JS::ToUint32(cx, args[0], &mask))
   182         return false;
   184     JS::RootedObject obj(cx, JS_NewObjectForConstructor(cx, &pm_class, args));
   185     if (!obj)
   186         return false;
   188     if (!JS_FreezeObject(cx, obj))
   189         return false;
   191     PerfMeasurement* p = cx->new_<PerfMeasurement>(PerfMeasurement::EventMask(mask));
   192     if (!p) {
   193         JS_ReportOutOfMemory(cx);
   194         return false;
   195     }
   197     JS_SetPrivate(obj, p);
   198     args.rval().setObject(*obj);
   199     return true;
   200 }
   202 static void
   203 pm_finalize(JSFreeOp* fop, JSObject* obj)
   204 {
   205     js::FreeOp::get(fop)->delete_(static_cast<PerfMeasurement*>(JS_GetPrivate(obj)));
   206 }
   208 // Helpers (declared above)
   210 static PerfMeasurement*
   211 GetPM(JSContext* cx, JS::HandleValue value, const char* fname)
   212 {
   213     if (!value.isObject()) {
   214         JS_ReportErrorNumber(cx, js_GetErrorMessage, 0, JSMSG_NOT_NONNULL_OBJECT);
   215         return nullptr;
   216     }
   217     RootedObject obj(cx, &value.toObject());
   218     PerfMeasurement* p = (PerfMeasurement*)
   219         JS_GetInstancePrivate(cx, obj, &pm_class, nullptr);
   220     if (p)
   221         return p;
   223     // JS_GetInstancePrivate only sets an exception if its last argument
   224     // is nonzero, so we have to do it by hand.
   225     JS_ReportErrorNumber(cx, js_GetErrorMessage, 0, JSMSG_INCOMPATIBLE_PROTO,
   226                          pm_class.name, fname, JS_GetClass(obj)->name);
   227     return nullptr;
   228 }
   230 namespace JS {
   232 JSObject*
   233 RegisterPerfMeasurement(JSContext *cx, HandleObject globalArg)
   234 {
   235     RootedObject global(cx, globalArg);
   236     RootedObject prototype(cx);
   237     prototype = JS_InitClass(cx, global, js::NullPtr() /* parent */,
   238                              &pm_class, pm_construct, 1,
   239                              pm_props, pm_fns, 0, 0);
   240     if (!prototype)
   241         return 0;
   243     RootedObject ctor(cx);
   244     ctor = JS_GetConstructor(cx, prototype);
   245     if (!ctor)
   246         return 0;
   248     for (const pm_const *c = pm_consts; c->name; c++) {
   249         if (!JS_DefineProperty(cx, ctor, c->name, c->value, PM_CATTRS,
   250                                JS_PropertyStub, JS_StrictPropertyStub))
   251             return 0;
   252     }
   254     if (!JS_FreezeObject(cx, prototype) ||
   255         !JS_FreezeObject(cx, ctor)) {
   256         return 0;
   257     }
   259     return prototype;
   260 }
   262 PerfMeasurement*
   263 ExtractPerfMeasurement(jsval wrapper)
   264 {
   265     if (JSVAL_IS_PRIMITIVE(wrapper))
   266         return 0;
   268     // This is what JS_GetInstancePrivate does internally.  We can't
   269     // call JS_anything from here, because we don't have a JSContext.
   270     JSObject *obj = JSVAL_TO_OBJECT(wrapper);
   271     if (obj->getClass() != js::Valueify(&pm_class))
   272         return 0;
   274     return (PerfMeasurement*) obj->getPrivate();
   275 }
   277 } // namespace JS

mercurial