Bug 1560425 - Remove old performance measurement API r=jorendorff

Differential Revision: https://phabricator.services.mozilla.com/D35522

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Matthew Gaudet 2019-07-02 14:37:17 +00:00
Родитель f4b4b49bee
Коммит 680c9fdc50
18 изменённых файлов: 0 добавлений и 976 удалений

Просмотреть файл

@ -146,8 +146,6 @@ var whitelist = [
{file: "resource://gre/modules/Manifest.jsm"},
// Bug 1351097
{file: "resource://gre/modules/accessibility/AccessFu.jsm"},
// Bug 1356043
{file: "resource://gre/modules/PerfMeasurement.jsm"},
// Bug 1356045
{file: "chrome://global/content/test-ipc.xul"},
// Bug 1378173 (warning: still used by devtools)

Просмотреть файл

@ -1,34 +0,0 @@
function spin_loop()
{
for (let i = 0; i < 10000; i++) ;
}
function check_timing(label, count) {
if (count == -1) {
print("TEST-UNEXPECTED-FAIL | TestPerf | " + label);
throwError();
} else {
print("TEST-PASS | TestPerf | " + label + " = " + count);
}
}
var pm = new PerfMeasurement(PerfMeasurement.ALL);
if (pm.eventsMeasured == 0) {
print("TEST-KNOWN-FAIL | perf-smoketest | stub, skipping test");
} else {
pm.start();
spin_loop();
pm.stop();
check_timing("cpu_cycles", pm.cpu_cycles);
check_timing("instructions", pm.instructions);
check_timing("cache_references", pm.cache_references);
check_timing("cache_misses", pm.cache_misses);
check_timing("branch_instructions", pm.branch_instructions);
check_timing("branch_misses", pm.branch_misses);
check_timing("bus_cycles", pm.bus_cycles);
check_timing("page_faults", pm.page_faults);
check_timing("major_page_faults", pm.major_page_faults);
check_timing("context_switches", pm.context_switches);
check_timing("cpu_migrations", pm.cpu_migrations);
}

Просмотреть файл

@ -112,7 +112,6 @@ EXPORTS += [
'jsfriendapi.h',
'jspubtd.h',
'jstypes.h',
'perf/jsperf.h',
]
EXPORTS.js += [
@ -248,7 +247,6 @@ UNIFIED_SOURCES += [
'jsexn.cpp',
'jsfriendapi.cpp',
'jsnum.cpp',
'perf/jsperf.cpp',
'proxy/BaseProxyHandler.cpp',
'proxy/CrossCompartmentWrapper.cpp',
'proxy/DeadObjectProxy.cpp',
@ -347,9 +345,6 @@ UNIFIED_SOURCES += [
# RtlGenRandom declaration's calling convention in <ntsecapi.h> on Windows.
# jsutil.cpp cannot be built in unified mode because it is needed for
# check-vanilla-allocations.
# perf/ProfilingStack.cpp cannot be built in unified mode because we want to
# suppress warnings due to usage of the system allocator, and this allows it
# to have a deterministic object name.
# util/DoubleToString.cpp cannot be built in unified mode because we want to
# suppress compiler warnings in third-party dtoa.c.
# vm/Interpreter.cpp is gigantic and destroys incremental build times for any
@ -405,17 +400,6 @@ if CONFIG['MOZ_VTUNE']:
]
SOURCES['vtune/ittnotify_static.c'].flags += ['-Wno-varargs', '-Wno-unknown-pragmas']
if CONFIG['HAVE_LINUX_PERF_EVENT_H']:
SOURCES += [
'perf/pm_linux.cpp'
]
if CONFIG['LINUX_HEADERS_INCLUDES']:
SOURCES['perf/pm_linux.cpp'].flags += [CONFIG['LINUX_HEADERS_INCLUDES']]
else:
SOURCES += [
'perf/pm_stub.cpp'
]
DIRS += [
'build',
'frontend',

Просмотреть файл

@ -1,245 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#include "perf/jsperf.h"
#include "js/PropertySpec.h"
#include "vm/JSContext.h" /* for error messages */
#include "vm/JSObject.h" /* for unwrapping without a context */
#include "gc/FreeOp-inl.h"
using namespace js;
using JS::PerfMeasurement;
// You cannot forward-declare a static object in C++, so instead
// we have to forward-declare the helper function that refers to it.
static PerfMeasurement* GetPM(JSContext* cx, JS::HandleValue value,
const char* fname);
// Property access
#define GETTER(name) \
static bool pm_get_##name(JSContext* cx, unsigned argc, Value* vp) { \
CallArgs args = CallArgsFromVp(argc, vp); \
PerfMeasurement* p = GetPM(cx, args.thisv(), #name); \
if (!p) return false; \
args.rval().setNumber(double(p->name)); \
return true; \
}
GETTER(cpu_cycles)
GETTER(instructions)
GETTER(cache_references)
GETTER(cache_misses)
GETTER(branch_instructions)
GETTER(branch_misses)
GETTER(bus_cycles)
GETTER(page_faults)
GETTER(major_page_faults)
GETTER(context_switches)
GETTER(cpu_migrations)
GETTER(eventsMeasured)
#undef GETTER
// Calls
static bool pm_start(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
PerfMeasurement* p = GetPM(cx, args.thisv(), "start");
if (!p) return false;
p->start();
args.rval().setUndefined();
return true;
}
static bool pm_stop(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
PerfMeasurement* p = GetPM(cx, args.thisv(), "stop");
if (!p) return false;
p->stop();
args.rval().setUndefined();
return true;
}
static bool pm_reset(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
PerfMeasurement* p = GetPM(cx, args.thisv(), "reset");
if (!p) return false;
p->reset();
args.rval().setUndefined();
return true;
}
static bool pm_canMeasureSomething(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
PerfMeasurement* p = GetPM(cx, args.thisv(), "canMeasureSomething");
if (!p) return false;
args.rval().setBoolean(PerfMeasurement::canMeasureSomething());
return true;
}
static const uint8_t PM_FATTRS = JSPROP_READONLY | JSPROP_PERMANENT;
static const JSFunctionSpec pm_fns[] = {
JS_FN("start", pm_start, 0, PM_FATTRS),
JS_FN("stop", pm_stop, 0, PM_FATTRS),
JS_FN("reset", pm_reset, 0, PM_FATTRS),
JS_FN("canMeasureSomething", pm_canMeasureSomething, 0, PM_FATTRS),
JS_FS_END};
static const uint8_t PM_PATTRS = JSPROP_ENUMERATE | JSPROP_PERMANENT;
#define GETTER(name) JS_PSG(#name, pm_get_##name, PM_PATTRS)
static const JSPropertySpec pm_props[] = {GETTER(cpu_cycles),
GETTER(instructions),
GETTER(cache_references),
GETTER(cache_misses),
GETTER(branch_instructions),
GETTER(branch_misses),
GETTER(bus_cycles),
GETTER(page_faults),
GETTER(major_page_faults),
GETTER(context_switches),
GETTER(cpu_migrations),
GETTER(eventsMeasured),
JS_PS_END};
#undef GETTER
// If this were C++ these would be "static const" members.
#define CONSTANT(name) \
{ #name, PerfMeasurement::name }
static const struct pm_const {
const char* name;
PerfMeasurement::EventMask value;
} pm_consts[] = {CONSTANT(CPU_CYCLES),
CONSTANT(INSTRUCTIONS),
CONSTANT(CACHE_REFERENCES),
CONSTANT(CACHE_MISSES),
CONSTANT(BRANCH_INSTRUCTIONS),
CONSTANT(BRANCH_MISSES),
CONSTANT(BUS_CYCLES),
CONSTANT(PAGE_FAULTS),
CONSTANT(MAJOR_PAGE_FAULTS),
CONSTANT(CONTEXT_SWITCHES),
CONSTANT(CPU_MIGRATIONS),
CONSTANT(ALL),
CONSTANT(NUM_MEASURABLE_EVENTS),
{0, PerfMeasurement::EventMask(0)}};
#undef CONSTANT
static bool pm_construct(JSContext* cx, unsigned argc, Value* vp);
static void pm_finalize(JSFreeOp* fop, JSObject* obj);
static const JSClassOps pm_classOps = {nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, pm_finalize};
static const JSClass pm_class = {
"PerfMeasurement", JSCLASS_HAS_PRIVATE | JSCLASS_FOREGROUND_FINALIZE,
&pm_classOps};
// Constructor and destructor
static bool pm_construct(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
uint32_t mask;
if (!args.hasDefined(0)) {
ReportMissingArg(cx, args.calleev(), 0);
return false;
}
if (!JS::ToUint32(cx, args[0], &mask)) return false;
JS::RootedObject obj(cx, JS_NewObjectForConstructor(cx, &pm_class, args));
if (!obj) return false;
if (!JS_FreezeObject(cx, obj)) return false;
PerfMeasurement* p =
cx->new_<PerfMeasurement>(PerfMeasurement::EventMask(mask));
if (!p) return false;
JS_InitPrivate(obj, p, sizeof(*p), JS::MemoryUse::PerfMeasurement);
args.rval().setObject(*obj);
return true;
}
static void pm_finalize(JSFreeOp* fop, JSObject* obj) {
auto pm = static_cast<PerfMeasurement*>(JS_GetPrivate(obj));
js::FreeOp::get(fop)->delete_(obj, pm, MemoryUse::PerfMeasurement);
}
// Helpers (declared above)
static PerfMeasurement* GetPM(JSContext* cx, JS::HandleValue value,
const char* fname) {
if (!value.isObject()) {
UniqueChars bytes =
DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, value, nullptr);
if (!bytes) return nullptr;
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, 0, JSMSG_OBJECT_REQUIRED,
bytes.get());
return nullptr;
}
RootedObject obj(cx, &value.toObject());
PerfMeasurement* p =
(PerfMeasurement*)JS_GetInstancePrivate(cx, obj, &pm_class, nullptr);
if (p) return p;
// JS_GetInstancePrivate only sets an exception if its last argument
// is nonzero, so we have to do it by hand.
JS_ReportErrorNumberASCII(cx, GetErrorMessage, 0, JSMSG_INCOMPATIBLE_PROTO,
pm_class.name, fname, JS_GetClass(obj)->name);
return nullptr;
}
namespace JS {
JSObject* RegisterPerfMeasurement(JSContext* cx, HandleObject globalArg) {
static const uint8_t PM_CATTRS =
JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT;
RootedObject global(cx, globalArg);
RootedObject prototype(cx);
prototype = JS_InitClass(cx, global, nullptr /* parent */, &pm_class,
pm_construct, 1, pm_props, pm_fns, 0, 0);
if (!prototype) return 0;
RootedObject ctor(cx);
ctor = JS_GetConstructor(cx, prototype);
if (!ctor) return 0;
for (const pm_const* c = pm_consts; c->name; c++) {
if (!JS_DefineProperty(cx, ctor, c->name, c->value, PM_CATTRS)) return 0;
}
if (!JS_FreezeObject(cx, prototype) || !JS_FreezeObject(cx, ctor)) {
return 0;
}
return prototype;
}
PerfMeasurement* ExtractPerfMeasurement(const Value& wrapper) {
if (wrapper.isPrimitive()) return 0;
// This is what JS_GetInstancePrivate does internally. We can't
// call JS_anything from here, because we don't have a JSContext.
JSObject* obj = wrapper.toObjectOrNull();
if (obj->getClass() != js::Valueify(&pm_class)) return 0;
return (PerfMeasurement*)obj->as<js::NativeObject>().getPrivate();
}
} // namespace JS

Просмотреть файл

@ -1,132 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef perf_jsperf_h
#define perf_jsperf_h
#include "jstypes.h"
#include "js/TypeDecls.h"
#include "js/Utility.h"
namespace JS {
/*
* JS::PerfMeasurement is a generic way to access detailed performance
* measurement APIs provided by your operating system. The details of
* exactly how this works and what can be measured are highly
* system-specific, but this interface is (one hopes) implementable
* on top of all of them.
*
* To use this API, create a PerfMeasurement object, passing its
* constructor a bitmask indicating which events you are interested
* in. Thereafter, Start() zeroes all counters and starts timing;
* Stop() stops timing again; and the counters for the events you
* requested are available as data values after calling Stop(). The
* object may be reused for many measurements.
*/
class JS_FRIEND_API PerfMeasurement {
protected:
// Implementation-specific data, if any.
void* impl;
public:
/*
* Events that may be measured. Taken directly from the list of
* "generalized hardware performance event types" in the Linux
* perf_event API, plus some of the "software events".
*/
enum EventMask {
CPU_CYCLES = 0x00000001,
INSTRUCTIONS = 0x00000002,
CACHE_REFERENCES = 0x00000004,
CACHE_MISSES = 0x00000008,
BRANCH_INSTRUCTIONS = 0x00000010,
BRANCH_MISSES = 0x00000020,
BUS_CYCLES = 0x00000040,
PAGE_FAULTS = 0x00000080,
MAJOR_PAGE_FAULTS = 0x00000100,
CONTEXT_SWITCHES = 0x00000200,
CPU_MIGRATIONS = 0x00000400,
ALL = 0x000007ff,
NUM_MEASURABLE_EVENTS = 11
};
/*
* Bitmask of events that will be measured when this object is
* active (between Start() and Stop()). This may differ from the
* bitmask passed to the constructor if the platform does not
* support measuring all of the requested events.
*/
const EventMask eventsMeasured;
/*
* Counters for each measurable event.
* Immediately after one of these objects is created, all of the
* counters for enabled events will be zero, and all of the
* counters for disabled events will be uint64_t(-1).
*/
uint64_t cpu_cycles;
uint64_t instructions;
uint64_t cache_references;
uint64_t cache_misses;
uint64_t branch_instructions;
uint64_t branch_misses;
uint64_t bus_cycles;
uint64_t page_faults;
uint64_t major_page_faults;
uint64_t context_switches;
uint64_t cpu_migrations;
/*
* Prepare to measure the indicated set of events. If not all of
* the requested events can be measured on the current platform,
* then the eventsMeasured bitmask will only include the subset of
* |toMeasure| corresponding to the events that can be measured.
*/
explicit PerfMeasurement(EventMask toMeasure);
/* Done with this set of measurements, tear down OS-level state. */
~PerfMeasurement();
/* Start a measurement cycle. */
void start();
/*
* End a measurement cycle, and for each enabled counter, add the
* number of measured events of that type to the appropriate
* visible variable.
*/
void stop();
/* Reset all enabled counters to zero. */
void reset();
/*
* True if this platform supports measuring _something_, i.e. it's
* not using the stub implementation.
*/
static bool canMeasureSomething();
};
/* Inject a Javascript wrapper around the above C++ class into the
* Javascript object passed as an argument (this will normally be a
* global object). The JS-visible API is identical to the C++ API.
*/
extern JS_FRIEND_API JSObject* RegisterPerfMeasurement(JSContext* cx,
JS::HandleObject global);
/*
* Given a Value which contains an instance of the aforementioned
* wrapper class, extract the C++ object. Returns nullptr if the
* Value is not an instance of the wrapper.
*/
extern JS_FRIEND_API PerfMeasurement* ExtractPerfMeasurement(
const Value& wrapper);
} // namespace JS
#endif /* perf_jsperf_h */

Просмотреть файл

@ -1,272 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
/* This variant of nsIPerfMeasurement uses the perf_event interface
* added in Linux 2.6.31. We key compilation of this file off the
* existence of <linux/perf_event.h>.
*/
#include <errno.h>
#include <linux/perf_event.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/syscall.h>
#include <unistd.h>
#include "perf/jsperf.h"
using namespace js;
// As of July 2010, this system call has not been added to the
// C library, so we have to provide our own wrapper function.
// If this code runs on a kernel that does not implement the
// system call (2.6.30 or older) nothing unpredictable will
// happen - it will just always fail and return -1.
static int sys_perf_event_open(struct perf_event_attr* attr, pid_t pid, int cpu,
int group_fd, unsigned long flags) {
return syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags);
}
namespace {
using JS::PerfMeasurement;
typedef PerfMeasurement::EventMask EventMask;
// Additional state required by this implementation.
struct Impl {
// Each active counter corresponds to an open file descriptor.
int f_cpu_cycles;
int f_instructions;
int f_cache_references;
int f_cache_misses;
int f_branch_instructions;
int f_branch_misses;
int f_bus_cycles;
int f_page_faults;
int f_major_page_faults;
int f_context_switches;
int f_cpu_migrations;
// Counter group leader, for Start and Stop.
int group_leader;
// Whether counters are running.
bool running;
Impl();
~Impl();
EventMask init(EventMask toMeasure);
void start();
void stop(PerfMeasurement* counters);
};
// Mapping from our event bitmask to codes passed into the kernel, and
// to fields in the PerfMeasurement and PerfMeasurement::impl structures.
static const struct {
EventMask bit;
uint32_t type;
uint32_t config;
uint64_t PerfMeasurement::*counter;
int Impl::*fd;
} kSlots[PerfMeasurement::NUM_MEASURABLE_EVENTS] = {
#define HW(mask, constant, fieldname) \
{ \
PerfMeasurement::mask, PERF_TYPE_HARDWARE, PERF_COUNT_HW_##constant, \
&PerfMeasurement::fieldname, &Impl::f_##fieldname \
}
#define SW(mask, constant, fieldname) \
{ \
PerfMeasurement::mask, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_##constant, \
&PerfMeasurement::fieldname, &Impl::f_##fieldname \
}
HW(CPU_CYCLES, CPU_CYCLES, cpu_cycles),
HW(INSTRUCTIONS, INSTRUCTIONS, instructions),
HW(CACHE_REFERENCES, CACHE_REFERENCES, cache_references),
HW(CACHE_MISSES, CACHE_MISSES, cache_misses),
HW(BRANCH_INSTRUCTIONS, BRANCH_INSTRUCTIONS, branch_instructions),
HW(BRANCH_MISSES, BRANCH_MISSES, branch_misses),
HW(BUS_CYCLES, BUS_CYCLES, bus_cycles),
SW(PAGE_FAULTS, PAGE_FAULTS, page_faults),
SW(MAJOR_PAGE_FAULTS, PAGE_FAULTS_MAJ, major_page_faults),
SW(CONTEXT_SWITCHES, CONTEXT_SWITCHES, context_switches),
SW(CPU_MIGRATIONS, CPU_MIGRATIONS, cpu_migrations),
#undef HW
#undef SW
};
Impl::Impl()
: f_cpu_cycles(-1),
f_instructions(-1),
f_cache_references(-1),
f_cache_misses(-1),
f_branch_instructions(-1),
f_branch_misses(-1),
f_bus_cycles(-1),
f_page_faults(-1),
f_major_page_faults(-1),
f_context_switches(-1),
f_cpu_migrations(-1),
group_leader(-1),
running(false) {}
Impl::~Impl() {
// Close all active counter descriptors. Take care to do the group
// leader last (this may not be necessary, but it's unclear what
// happens if you close the group leader out from under a group).
for (const auto& slot : kSlots) {
int fd = this->*(slot.fd);
if (fd != -1 && fd != group_leader) close(fd);
}
if (group_leader != -1) close(group_leader);
}
EventMask Impl::init(EventMask toMeasure) {
MOZ_ASSERT(group_leader == -1);
if (!toMeasure) return EventMask(0);
EventMask measured = EventMask(0);
struct perf_event_attr attr;
for (const auto& slot : kSlots) {
if (!(toMeasure & slot.bit)) continue;
memset(&attr, 0, sizeof(attr));
attr.size = sizeof(attr);
// Set the type and config fields to indicate the counter we
// want to enable. We want read format 0, and we're not using
// sampling, so leave those fields unset.
attr.type = slot.type;
attr.config = slot.config;
// If this will be the group leader it should start off
// disabled. Otherwise it should start off enabled (but blocked
// on the group leader).
if (group_leader == -1) attr.disabled = 1;
// The rest of the bit fields are really poorly documented.
// For instance, I have *no idea* whether we should be setting
// the inherit, inherit_stat, or task flags. I'm pretty sure
// we do want to set mmap and comm, and not any of the ones I
// haven't mentioned.
attr.mmap = 1;
attr.comm = 1;
int fd =
sys_perf_event_open(&attr, 0 /* trace self */, -1 /* on any cpu */,
group_leader, 0 /* no flags presently defined */);
if (fd == -1) continue;
measured = EventMask(measured | slot.bit);
this->*(slot.fd) = fd;
if (group_leader == -1) group_leader = fd;
}
return measured;
}
void Impl::start() {
if (running || group_leader == -1) return;
running = true;
ioctl(group_leader, PERF_EVENT_IOC_ENABLE, 0);
}
void Impl::stop(PerfMeasurement* counters) {
// This scratch buffer is to ensure that we have read all the
// available data, even if that's more than we expect.
unsigned char buf[1024];
if (!running || group_leader == -1) return;
ioctl(group_leader, PERF_EVENT_IOC_DISABLE, 0);
running = false;
// read out and reset all the counter values
for (const auto& slot : kSlots) {
int fd = this->*(slot.fd);
if (fd == -1) continue;
if (read(fd, buf, sizeof(buf)) == sizeof(uint64_t)) {
uint64_t cur;
memcpy(&cur, buf, sizeof(uint64_t));
counters->*(slot.counter) += cur;
}
// Reset the counter regardless of whether the read did what
// we expected.
ioctl(fd, PERF_EVENT_IOC_RESET, 0);
}
}
} // namespace
namespace JS {
#define initCtr(flag) ((eventsMeasured & flag) ? 0 : -1)
PerfMeasurement::PerfMeasurement(PerfMeasurement::EventMask toMeasure)
: impl(js_new<Impl>()),
eventsMeasured(impl ? static_cast<Impl*>(impl)->init(toMeasure)
: EventMask(0)),
cpu_cycles(initCtr(CPU_CYCLES)),
instructions(initCtr(INSTRUCTIONS)),
cache_references(initCtr(CACHE_REFERENCES)),
cache_misses(initCtr(CACHE_MISSES)),
branch_instructions(initCtr(BRANCH_INSTRUCTIONS)),
branch_misses(initCtr(BRANCH_MISSES)),
bus_cycles(initCtr(BUS_CYCLES)),
page_faults(initCtr(PAGE_FAULTS)),
major_page_faults(initCtr(MAJOR_PAGE_FAULTS)),
context_switches(initCtr(CONTEXT_SWITCHES)),
cpu_migrations(initCtr(CPU_MIGRATIONS)) {}
#undef initCtr
PerfMeasurement::~PerfMeasurement() { js_delete(static_cast<Impl*>(impl)); }
void PerfMeasurement::start() {
if (impl) static_cast<Impl*>(impl)->start();
}
void PerfMeasurement::stop() {
if (impl) static_cast<Impl*>(impl)->stop(this);
}
void PerfMeasurement::reset() {
for (const auto& slot : kSlots) {
if (eventsMeasured & slot.bit)
this->*(slot.counter) = 0;
else
this->*(slot.counter) = -1;
}
}
bool PerfMeasurement::canMeasureSomething() {
// Find out if the kernel implements the performance measurement
// API. If it doesn't, syscall(__NR_perf_event_open, ...) is
// guaranteed to return -1 and set errno to ENOSYS.
//
// We set up input parameters that should provoke an EINVAL error
// from a kernel that does implement perf_event_open, but we can't
// be sure it will (newer kernels might add more event types), so
// we have to take care to close any valid fd it might return.
struct perf_event_attr attr;
memset(&attr, 0, sizeof(attr));
attr.size = sizeof(attr);
attr.type = PERF_TYPE_MAX;
int fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
if (fd >= 0) {
close(fd);
return true;
}
return errno != ENOSYS;
}
} // namespace JS

Просмотреть файл

@ -1,47 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#include "perf/jsperf.h"
namespace JS {
PerfMeasurement::PerfMeasurement(PerfMeasurement::EventMask)
: impl(0),
eventsMeasured(EventMask(0)),
cpu_cycles(-1),
instructions(-1),
cache_references(-1),
cache_misses(-1),
branch_instructions(-1),
branch_misses(-1),
bus_cycles(-1),
page_faults(-1),
major_page_faults(-1),
context_switches(-1),
cpu_migrations(-1) {}
PerfMeasurement::~PerfMeasurement() {}
void PerfMeasurement::start() {}
void PerfMeasurement::stop() {}
void PerfMeasurement::reset() {
cpu_cycles = -1;
instructions = -1;
cache_references = -1;
cache_misses = -1;
branch_instructions = -1;
branch_misses = -1;
bus_cycles = -1;
page_faults = -1;
major_page_faults = -1;
context_switches = -1;
cpu_migrations = -1;
}
bool PerfMeasurement::canMeasureSomething() { return false; }
} // namespace JS

Просмотреть файл

@ -107,7 +107,6 @@
#include "js/SweepingAPI.h"
#include "js/Warnings.h" // JS::SetWarningReporter
#include "js/Wrapper.h"
#include "perf/jsperf.h"
#include "shell/jsoptparse.h"
#include "shell/jsshell.h"
#include "shell/OSObject.h"
@ -9904,9 +9903,6 @@ static JSObject* NewGlobalObject(JSContext* cx, JS::RealmOptions& options,
if (!JS_DefineDebuggerObject(cx, glob)) {
return nullptr;
}
if (!JS::RegisterPerfMeasurement(cx, glob)) {
return nullptr;
}
if (!JS_DefineFunctionsWithHelp(cx, glob, shell_functions) ||
!JS_DefineProfilingFunctions(cx, glob)) {
return nullptr;

Просмотреть файл

@ -115,9 +115,6 @@ with Files("**/browser/tools/mozscreenshots/**"):
with Files("**/devtools/shared/test-helpers/**"):
SCHEDULES.inclusive += ['test-verify', 'test-verify-gpu']
with Files("**/toolkit/components/perf/**"):
SCHEDULES.inclusive += ['test-verify', 'test-verify-gpu']
CONFIGURE_SUBST_FILES += [
'config/autoconf.mk',
'config/emptyvars.mk',

Просмотреть файл

@ -49,7 +49,6 @@ DIRS += [
'osfile',
'parentalcontrols',
'passwordmgr',
'perf',
'perfmonitoring',
'pictureinpicture',
'places',

Просмотреть файл

@ -1,7 +0,0 @@
"use strict";
module.exports = {
"extends": [
"plugin:mozilla/chrome-test"
]
};

Просмотреть файл

@ -1,74 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
/* 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/. */
#include "PerfMeasurement.h"
#include "jsperf.h"
#include "nsMemory.h"
#include "mozilla/Preferences.h"
#include "mozJSComponentLoader.h"
#include "nsZipArchive.h"
#include "xpc_make_class.h"
namespace mozilla {
namespace jsperf {
NS_IMPL_ISUPPORTS(Module, nsIXPCScriptable)
Module::Module() = default;
Module::~Module() = default;
#define XPC_MAP_CLASSNAME Module
#define XPC_MAP_QUOTED_CLASSNAME "Module"
#define XPC_MAP_FLAGS XPC_SCRIPTABLE_WANT_CALL
#include "xpc_map_end.h"
static bool SealObjectAndPrototype(JSContext* cx, JS::Handle<JSObject*> parent,
const char* name) {
JS::Rooted<JS::Value> prop(cx);
if (!JS_GetProperty(cx, parent, name, &prop)) return false;
if (prop.isUndefined()) {
// Pretend we sealed the object.
return true;
}
JS::Rooted<JSObject*> obj(cx, prop.toObjectOrNull());
if (!JS_GetProperty(cx, obj, "prototype", &prop)) return false;
JS::Rooted<JSObject*> prototype(cx, prop.toObjectOrNull());
return JS_FreezeObject(cx, obj) && JS_FreezeObject(cx, prototype);
}
static bool InitAndSealPerfMeasurementClass(JSContext* cx,
JS::Handle<JSObject*> global) {
// Init the PerfMeasurement class
if (!JS::RegisterPerfMeasurement(cx, global)) return false;
// Seal up Object, Function, and Array and their prototypes. (This single
// object instance is shared amongst everyone who imports the jsperf module.)
if (!SealObjectAndPrototype(cx, global, "Object") ||
!SealObjectAndPrototype(cx, global, "Function") ||
!SealObjectAndPrototype(cx, global, "Array"))
return false;
// Finally, seal the global object, for good measure. (But not recursively;
// this breaks things.)
return JS_FreezeObject(cx, global);
}
NS_IMETHODIMP
Module::Call(nsIXPConnectWrappedNative* wrapper, JSContext* cx, JSObject* obj,
const JS::CallArgs& args, bool* _retval) {
mozJSComponentLoader* loader = mozJSComponentLoader::Get();
JS::Rooted<JSObject*> targetObj(cx);
loader->FindTargetObject(cx, &targetObj);
*_retval = InitAndSealPerfMeasurementClass(cx, targetObj);
return NS_OK;
}
} // namespace jsperf
} // namespace mozilla

Просмотреть файл

@ -1,29 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
/* 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/. */
#ifndef COMPONENTS_PERFMEASUREMENT_H
#define COMPONENTS_PERFMEASUREMENT_H
#include "nsIXPCScriptable.h"
#include "mozilla/Attributes.h"
namespace mozilla {
namespace jsperf {
class Module final : public nsIXPCScriptable {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIXPCSCRIPTABLE
Module();
private:
~Module();
};
} // namespace jsperf
} // namespace mozilla
#endif

Просмотреть файл

@ -1,19 +0,0 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* 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/. */
var EXPORTED_SYMBOLS = [ "PerfMeasurement" ];
/*
* This is the js module for jsperf. Import it like so:
* Components.utils.import("resource://gre/modules/PerfMeasurement.jsm");
*
* This will create a 'PerfMeasurement' class. Instances of this class can
* be used to benchmark browser operations.
*
* For documentation on the API, see js/src/perf/jsperf.h.
*
*/
Cc["@mozilla.org/jsperf;1"].createInstance()();

Просмотреть файл

@ -1,3 +0,0 @@
[DEFAULT]
[test_pm.xul]

Просмотреть файл

@ -1,14 +0,0 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
Classes = [
{
'cid': '{421c38e6-aee0-4509-a025-130f4378035a}',
'contract_ids': ['@mozilla.org/jsperf;1'],
'type': 'mozilla::jsperf::Module',
'headers': ['/toolkit/components/perf/PerfMeasurement.h'],
},
]

Просмотреть файл

@ -1,28 +0,0 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
with Files('**'):
BUG_COMPONENT = ('Core', 'JavaScript Engine')
SOURCES += [
'PerfMeasurement.cpp',
]
EXTRA_JS_MODULES += [
'PerfMeasurement.jsm',
]
XPCOM_MANIFESTS += [
'components.conf',
]
FINAL_LIBRARY = 'xul'
LOCAL_INCLUDES += [
'/js/xpconnect/loader',
]
MOCHITEST_CHROME_MANIFESTS += ['chrome.ini']

Просмотреть файл

@ -1,46 +0,0 @@
<?xml version="1.0"?>
<!-- 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/. -->
<window title="Performance measurement tests"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="test()">
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
<script><![CDATA[
function test()
{
SimpleTest.waitForExplicitFinish();
const {PerfMeasurement} = ChromeUtils.import("resource://gre/modules/PerfMeasurement.jsm");
let pm = new PerfMeasurement(PerfMeasurement.ALL);
if (pm.eventsMeasured == 0) {
todo(false, "stub, skipping test");
} else {
pm.start();
for (let i = 0; i < 10000; i++) ;
pm.stop();
events = ["cpu_cycles", "instructions", "cache_references", "cache_misses",
"branch_instructions", "branch_misses", "bus_cycles", "page_faults",
"major_page_faults", "context_switches", "cpu_migrations"];
for (var i = 0; i < events.length; i++) {
var e = events[i];
((pm.eventsMeasured & PerfMeasurement[e.toUpperCase()]) ? isnot : todo_is)(pm[e], -1, e);
}
}
SimpleTest.finish();
}
]]></script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display:none;"></div>
<pre id="test"></pre>
</body>
<label id="test-result"/>
</window>