Bug 785440 - Add js::GetContextProfilingStack in such a way that it can be inlined into non-JS code. r?sfink
This requires moving some things around. RootingContext is an existing
superclass of JSContext whose members are exposed in a header file, so we can
use it to expose the location of the geckoProfiler_ member to non-JS code.
MozReview-Commit-ID: 3oClAEVMsDr
--- a/js/public/ProfilingStack.h
+++ b/js/public/ProfilingStack.h
@@ -262,16 +262,18 @@ class ProfileEntry
// signify a nullptr pc, use a -1 index. This is checked against in
// pc() and setPC() to set/get the right pc.
static const int32_t NullPCOffset = -1;
};
JS_FRIEND_API(void)
SetContextProfilingStack(JSContext* cx, PseudoStack* pseudoStack);
+// GetContextProfilingStack also exists, but it's defined in RootingAPI.h.
+
JS_FRIEND_API(void)
EnableContextProfilingStack(JSContext* cx, bool enabled);
JS_FRIEND_API(void)
RegisterContextProfilingEventMarker(JSContext* cx, void (*fn)(const char*));
} // namespace js
@@ -377,9 +379,52 @@ class PseudoStack
// WARNING WARNING WARNING
//
// This is an atomic variable that uses ReleaseAcquire memory ordering.
// See the "Concurrency considerations" paragraph at the top of this file
// for more details.
mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire> stackPointer;
};
+namespace js {
+
+class AutoGeckoProfilerEntry;
+class GeckoProfilerEntryMarker;
+class GeckoProfilerBaselineOSRMarker;
+
+class GeckoProfilerThread
+{
+ friend class AutoGeckoProfilerEntry;
+ friend class GeckoProfilerEntryMarker;
+ friend class GeckoProfilerBaselineOSRMarker;
+
+ PseudoStack* pseudoStack_;
+
+ public:
+ GeckoProfilerThread();
+
+ uint32_t stackPointer() { MOZ_ASSERT(installed()); return pseudoStack_->stackPointer; }
+ ProfileEntry* stack() { return pseudoStack_->entries; }
+ PseudoStack* getPseudoStack() { return pseudoStack_; }
+
+ /* management of whether instrumentation is on or off */
+ bool installed() { return pseudoStack_ != nullptr; }
+
+ void setProfilingStack(PseudoStack* pseudoStack);
+ void trace(JSTracer* trc);
+
+ /*
+ * Functions which are the actual instrumentation to track run information
+ *
+ * - enter: a function has started to execute
+ * - updatePC: updates the pc information about where a function
+ * is currently executing
+ * - exit: this function has ceased execution, and no further
+ * entries/exits will be made
+ */
+ bool enter(JSContext* cx, JSScript* script, JSFunction* maybeFun);
+ void exit(JSScript* script, JSFunction* maybeFun);
+ inline void updatePC(JSContext* cx, JSScript* script, jsbytecode* pc);
+};
+
+} // namespace js
+
#endif /* js_ProfilingStack_h */
--- a/js/public/RootingAPI.h
+++ b/js/public/RootingAPI.h
@@ -16,16 +16,17 @@
#include <type_traits>
#include "jspubtd.h"
#include "js/GCAnnotations.h"
#include "js/GCPolicyAPI.h"
#include "js/HeapAPI.h"
+#include "js/ProfilingStack.h"
#include "js/TypeDecls.h"
#include "js/UniquePtr.h"
#include "js/Utility.h"
/*
* Moving GC Stack Rooting
*
* A moving GC may change the physical location of GC allocated things, even
@@ -789,22 +790,30 @@ class RootingContext
// Stack GC roots for Rooted GC heap pointers.
RootedListHeads stackRoots_;
template <typename T> friend class JS::Rooted;
// Stack GC roots for AutoFooRooter classes.
JS::AutoGCRooter* autoGCRooters_;
friend class JS::AutoGCRooter;
+ // Gecko profiling metadata.
+ // This isn't really rooting related. It's only here because we want
+ // GetContextProfilingStack to be inlineable into non-JS code, and we
+ // didn't want to add another superclass of JSContext just for this.
+ js::GeckoProfilerThread geckoProfiler_;
+
public:
RootingContext();
void traceStackRoots(JSTracer* trc);
void checkNoGCRooters();
+ js::GeckoProfilerThread& geckoProfiler() { return geckoProfiler_; }
+
protected:
// The remaining members in this class should only be accessed through
// JSContext pointers. They are unrelated to rooting and are in place so
// that inlined API functions can directly access the data.
/* The current compartment. */
JSCompartment* compartment_;
@@ -1011,16 +1020,22 @@ GetContextCompartment(const JSContext* c
}
inline JS::Zone*
GetContextZone(const JSContext* cx)
{
return JS::RootingContext::get(cx)->zone_;
}
+inline PseudoStack*
+GetContextProfilingStack(JSContext* cx)
+{
+ return JS::RootingContext::get(cx)->geckoProfiler().getPseudoStack();
+}
+
/**
* Augment the generic Rooted<T> interface when T = JSObject* with
* class-querying and downcasting operations.
*
* Given a Rooted<JSObject*> obj, one can view
* Handle<StringObject*> h = obj.as<StringObject*>();
* as an optimization of
* Rooted<StringObject*> rooted(cx, &obj->as<StringObject*>());
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -588,22 +588,16 @@ struct JSContext : public JS::RootingCon
}
void disableProfilerSampling() {
suppressProfilerSampling = true;
}
void enableProfilerSampling() {
suppressProfilerSampling = false;
}
- private:
- /* Gecko profiling metadata */
- js::UnprotectedData<js::GeckoProfilerThread> geckoProfiler_;
- public:
- js::GeckoProfilerThread& geckoProfiler() { return geckoProfiler_.ref(); }
-
#if defined(XP_DARWIN)
js::wasm::MachExceptionHandler wasmMachExceptionHandler;
#endif
/* Temporary arena pool used while compiling and decompiling. */
static const size_t TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE = 4 * 1024;
private:
js::ThreadLocalData<js::LifoAlloc> tempLifoAlloc_;
--- a/js/src/vm/GeckoProfiler.h
+++ b/js/src/vm/GeckoProfiler.h
@@ -105,54 +105,16 @@ namespace js {
// The `ProfileStringMap` weakly holds its `JSScript*` keys and owns its string
// values. Entries are removed when the `JSScript` is finalized; see
// `GeckoProfiler::onScriptFinalized`.
using ProfileStringMap = HashMap<JSScript*,
UniqueChars,
DefaultHasher<JSScript*>,
SystemAllocPolicy>;
-class AutoGeckoProfilerEntry;
-class GeckoProfilerEntryMarker;
-class GeckoProfilerBaselineOSRMarker;
-
-class GeckoProfilerThread
-{
- friend class AutoGeckoProfilerEntry;
- friend class GeckoProfilerEntryMarker;
- friend class GeckoProfilerBaselineOSRMarker;
-
- PseudoStack* pseudoStack_;
-
- public:
- GeckoProfilerThread();
-
- uint32_t stackPointer() { MOZ_ASSERT(installed()); return pseudoStack_->stackPointer; }
- ProfileEntry* stack() { return pseudoStack_->entries; }
-
- /* management of whether instrumentation is on or off */
- bool installed() { return pseudoStack_ != nullptr; }
-
- void setProfilingStack(PseudoStack* pseudoStack);
- void trace(JSTracer* trc);
-
- /*
- * Functions which are the actual instrumentation to track run information
- *
- * - enter: a function has started to execute
- * - updatePC: updates the pc information about where a function
- * is currently executing
- * - exit: this function has ceased execution, and no further
- * entries/exits will be made
- */
- bool enter(JSContext* cx, JSScript* script, JSFunction* maybeFun);
- void exit(JSScript* script, JSFunction* maybeFun);
- inline void updatePC(JSContext* cx, JSScript* script, jsbytecode* pc);
-};
-
class GeckoProfilerRuntime
{
JSRuntime* rt;
ExclusiveData<ProfileStringMap> strings;
bool slowAssertions;
uint32_t enabled_;
void (*eventMarker_)(const char*);