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.

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

mercurial