# HG changeset patch # User Markus Stange # Date 1515159300 -3600 # Node ID ecfe33a4bb62c76815592ea9a4a8d9d955a22b03 # Parent 116282d386eca6f2606ed63a651e90d904788de0 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 diff --git a/js/public/ProfilingStack.h b/js/public/ProfilingStack.h --- 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 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 */ diff --git a/js/public/RootingAPI.h b/js/public/RootingAPI.h --- a/js/public/RootingAPI.h +++ b/js/public/RootingAPI.h @@ -16,16 +16,17 @@ #include #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 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_; @@ -1008,16 +1017,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 interface when T = JSObject* with * class-querying and downcasting operations. * * Given a Rooted obj, one can view * Handle h = obj.as(); * as an optimization of * Rooted rooted(cx, &obj->as()); diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h --- 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 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 tempLifoAlloc_; diff --git a/js/src/vm/GeckoProfiler.h b/js/src/vm/GeckoProfiler.h --- 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, 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 strings; bool slowAssertions; uint32_t enabled_; void (*eventMarker_)(const char*);