Bug 785440 - Add js::GetContextProfilingStack in such a way that it can be inlined into non-JS code. r?sfink draft
authorMarkus Stange <mstange@themasta.com>
Fri, 05 Jan 2018 14:35:00 +0100
changeset 752761 4ff98962d0b9c6e2fed035d36b918d306dca7717
parent 752760 b0f22ad41945e727e3e137a8a8509d0be5840b6e
child 752762 dcbeccca5644c66053c74297a4136a500a61c765
push id98367
push userbmo:mstange@themasta.com
push dateThu, 08 Feb 2018 21:45:52 +0000
reviewerssfink
bugs785440
milestone60.0a1
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
js/public/ProfilingStack.h
js/public/RootingAPI.h
js/src/jscntxt.h
js/src/vm/GeckoProfiler.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<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*);