Differential D3095 Diff 13993 libraries/source/spidermonkey/include-win32-debug/js/ProfilingFrameIterator.h
Changeset View
Changeset View
Standalone View
Standalone View
libraries/source/spidermonkey/include-win32-debug/js/ProfilingFrameIterator.h
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- | ||||
* vim: set ts=8 sts=4 et sw=4 tw=99: | * vim: set ts=8 sts=4 et sw=4 tw=99: | ||||
* This Source Code Form is subject to the terms of the Mozilla Public | * 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 | * 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/. */ | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||||
#ifndef js_ProfilingFrameIterator_h | #ifndef js_ProfilingFrameIterator_h | ||||
#define js_ProfilingFrameIterator_h | #define js_ProfilingFrameIterator_h | ||||
#include "mozilla/Alignment.h" | #include "mozilla/Alignment.h" | ||||
#include "mozilla/Maybe.h" | #include "mozilla/Maybe.h" | ||||
#include "jsbytecode.h" | #include "jsbytecode.h" | ||||
#include "js/GCAPI.h" | |||||
#include "js/TypeDecls.h" | #include "js/TypeDecls.h" | ||||
#include "js/Utility.h" | #include "js/Utility.h" | ||||
struct JSContext; | |||||
struct JSRuntime; | struct JSRuntime; | ||||
class JSScript; | class JSScript; | ||||
namespace js { | namespace js { | ||||
class Activation; | class Activation; | ||||
class AsmJSProfilingFrameIterator; | |||||
namespace jit { | namespace jit { | ||||
class JitActivation; | class JitActivation; | ||||
class JitProfilingFrameIterator; | class JitProfilingFrameIterator; | ||||
class JitcodeGlobalEntry; | class JitcodeGlobalEntry; | ||||
} // namespace jit | } // namespace jit | ||||
namespace wasm { | |||||
class ProfilingFrameIterator; | |||||
} // namespace wasm | |||||
} // namespace js | } // namespace js | ||||
namespace JS { | namespace JS { | ||||
struct ForEachTrackedOptimizationAttemptOp; | struct ForEachTrackedOptimizationAttemptOp; | ||||
struct ForEachTrackedOptimizationTypeInfoOp; | struct ForEachTrackedOptimizationTypeInfoOp; | ||||
// This iterator can be used to walk the stack of a thread suspended at an | // This iterator can be used to walk the stack of a thread suspended at an | ||||
// arbitrary pc. To provide acurate results, profiling must have been enabled | // arbitrary pc. To provide acurate results, profiling must have been enabled | ||||
// (via EnableRuntimeProfilingStack) before executing the callstack being | // (via EnableRuntimeProfilingStack) before executing the callstack being | ||||
// unwound. | // unwound. | ||||
// | |||||
// Note that the caller must not do anything that could cause GC to happen while | |||||
// the iterator is alive, since this could invalidate Ion code and cause its | |||||
// contents to become out of date. | |||||
class JS_PUBLIC_API(ProfilingFrameIterator) | class JS_PUBLIC_API(ProfilingFrameIterator) | ||||
{ | { | ||||
JSRuntime* rt_; | JSRuntime* rt_; | ||||
uint32_t sampleBufferGen_; | uint32_t sampleBufferGen_; | ||||
js::Activation* activation_; | js::Activation* activation_; | ||||
// When moving past a JitActivation, we need to save the prevJitTop | // When moving past a JitActivation, we need to save the prevJitTop | ||||
// from it to use as the exit-frame pointer when the next caller jit | // from it to use as the exit-frame pointer when the next caller jit | ||||
// activation (if any) comes around. | // activation (if any) comes around. | ||||
void* savedPrevJitTop_; | void* savedPrevJitTop_; | ||||
JS::AutoCheckCannotGC nogc_; | |||||
static const unsigned StorageSpace = 8 * sizeof(void*); | static const unsigned StorageSpace = 8 * sizeof(void*); | ||||
mozilla::AlignedStorage<StorageSpace> storage_; | mozilla::AlignedStorage<StorageSpace> storage_; | ||||
js::AsmJSProfilingFrameIterator& asmJSIter() { | js::wasm::ProfilingFrameIterator& wasmIter() { | ||||
MOZ_ASSERT(!done()); | MOZ_ASSERT(!done()); | ||||
MOZ_ASSERT(isAsmJS()); | MOZ_ASSERT(isWasm()); | ||||
return *reinterpret_cast<js::AsmJSProfilingFrameIterator*>(storage_.addr()); | return *reinterpret_cast<js::wasm::ProfilingFrameIterator*>(storage_.addr()); | ||||
} | } | ||||
const js::AsmJSProfilingFrameIterator& asmJSIter() const { | const js::wasm::ProfilingFrameIterator& wasmIter() const { | ||||
MOZ_ASSERT(!done()); | MOZ_ASSERT(!done()); | ||||
MOZ_ASSERT(isAsmJS()); | MOZ_ASSERT(isWasm()); | ||||
return *reinterpret_cast<const js::AsmJSProfilingFrameIterator*>(storage_.addr()); | return *reinterpret_cast<const js::wasm::ProfilingFrameIterator*>(storage_.addr()); | ||||
} | } | ||||
js::jit::JitProfilingFrameIterator& jitIter() { | js::jit::JitProfilingFrameIterator& jitIter() { | ||||
MOZ_ASSERT(!done()); | MOZ_ASSERT(!done()); | ||||
MOZ_ASSERT(isJit()); | MOZ_ASSERT(isJit()); | ||||
return *reinterpret_cast<js::jit::JitProfilingFrameIterator*>(storage_.addr()); | return *reinterpret_cast<js::jit::JitProfilingFrameIterator*>(storage_.addr()); | ||||
} | } | ||||
Show All 13 Lines | public: | ||||
struct RegisterState | struct RegisterState | ||||
{ | { | ||||
RegisterState() : pc(nullptr), sp(nullptr), lr(nullptr) {} | RegisterState() : pc(nullptr), sp(nullptr), lr(nullptr) {} | ||||
void* pc; | void* pc; | ||||
void* sp; | void* sp; | ||||
void* lr; | void* lr; | ||||
}; | }; | ||||
ProfilingFrameIterator(JSRuntime* rt, const RegisterState& state, | ProfilingFrameIterator(JSContext* cx, const RegisterState& state, | ||||
uint32_t sampleBufferGen = UINT32_MAX); | uint32_t sampleBufferGen = UINT32_MAX); | ||||
~ProfilingFrameIterator(); | ~ProfilingFrameIterator(); | ||||
void operator++(); | void operator++(); | ||||
bool done() const { return !activation_; } | bool done() const { return !activation_; } | ||||
// Assuming the stack grows down (we do), the return value: | // Assuming the stack grows down (we do), the return value: | ||||
// - always points into the stack | // - always points into the stack | ||||
// - is weakly monotonically increasing (may be equal for successive frames) | // - is weakly monotonically increasing (may be equal for successive frames) | ||||
// - will compare greater than newer native and psuedo-stack frame addresses | // - will compare greater than newer native and psuedo-stack frame addresses | ||||
// and less than older native and psuedo-stack frame addresses | // and less than older native and psuedo-stack frame addresses | ||||
void* stackAddress() const; | void* stackAddress() const; | ||||
enum FrameKind | enum FrameKind | ||||
{ | { | ||||
Frame_Baseline, | Frame_Baseline, | ||||
Frame_Ion, | Frame_Ion, | ||||
Frame_AsmJS | Frame_Wasm | ||||
}; | }; | ||||
struct Frame | struct Frame | ||||
{ | { | ||||
FrameKind kind; | FrameKind kind; | ||||
void* stackAddress; | void* stackAddress; | ||||
void* returnAddress; | void* returnAddress; | ||||
void* activation; | void* activation; | ||||
const char* label; | UniqueChars label; | ||||
}; | }; | ||||
bool isAsmJS() const; | bool isWasm() const; | ||||
bool isJit() const; | bool isJit() const; | ||||
uint32_t extractStack(Frame* frames, uint32_t offset, uint32_t end) const; | uint32_t extractStack(Frame* frames, uint32_t offset, uint32_t end) const; | ||||
mozilla::Maybe<Frame> getPhysicalFrameWithoutLabel() const; | mozilla::Maybe<Frame> getPhysicalFrameWithoutLabel() const; | ||||
private: | private: | ||||
mozilla::Maybe<Frame> getPhysicalFrameAndEntry(js::jit::JitcodeGlobalEntry* entry) const; | mozilla::Maybe<Frame> getPhysicalFrameAndEntry(js::jit::JitcodeGlobalEntry* entry) const; | ||||
void iteratorConstruct(const RegisterState& state); | void iteratorConstruct(const RegisterState& state); | ||||
void iteratorConstruct(); | void iteratorConstruct(); | ||||
void iteratorDestroy(); | void iteratorDestroy(); | ||||
bool iteratorDone(); | bool iteratorDone(); | ||||
}; | }; | ||||
JS_FRIEND_API(bool) | JS_FRIEND_API(bool) | ||||
IsProfilingEnabledForRuntime(JSRuntime* runtime); | IsProfilingEnabledForContext(JSContext* cx); | ||||
/** | /** | ||||
* After each sample run, this method should be called with the latest sample | * After each sample run, this method should be called with the latest sample | ||||
* buffer generation, and the lapCount. It will update corresponding fields on | * buffer generation, and the lapCount. It will update corresponding fields on | ||||
* JSRuntime. | * JSRuntime. | ||||
* | * | ||||
* See fields |profilerSampleBufferGen|, |profilerSampleBufferLapCount| on | * See fields |profilerSampleBufferGen|, |profilerSampleBufferLapCount| on | ||||
* JSRuntime for documentation about what these values are used for. | * JSRuntime for documentation about what these values are used for. | ||||
*/ | */ | ||||
JS_FRIEND_API(void) | JS_FRIEND_API(void) | ||||
UpdateJSRuntimeProfilerSampleBufferGen(JSRuntime* runtime, uint32_t generation, | UpdateJSContextProfilerSampleBufferGen(JSContext* cx, uint32_t generation, | ||||
uint32_t lapCount); | uint32_t lapCount); | ||||
struct ForEachProfiledFrameOp | struct ForEachProfiledFrameOp | ||||
{ | { | ||||
// A handle to the underlying JitcodeGlobalEntry, so as to avoid repeated | // A handle to the underlying JitcodeGlobalEntry, so as to avoid repeated | ||||
// lookups on JitcodeGlobalTable. | // lookups on JitcodeGlobalTable. | ||||
class MOZ_STACK_CLASS FrameHandle | class MOZ_STACK_CLASS FrameHandle | ||||
{ | { | ||||
friend JS_PUBLIC_API(void) ForEachProfiledFrame(JSRuntime* rt, void* addr, | friend JS_PUBLIC_API(void) ForEachProfiledFrame(JSContext* cx, void* addr, | ||||
ForEachProfiledFrameOp& op); | ForEachProfiledFrameOp& op); | ||||
JSRuntime* rt_; | JSRuntime* rt_; | ||||
js::jit::JitcodeGlobalEntry& entry_; | js::jit::JitcodeGlobalEntry& entry_; | ||||
void* addr_; | void* addr_; | ||||
void* canonicalAddr_; | void* canonicalAddr_; | ||||
const char* label_; | const char* label_; | ||||
uint32_t depth_; | uint32_t depth_; | ||||
mozilla::Maybe<uint8_t> optsIndex_; | mozilla::Maybe<uint8_t> optsIndex_; | ||||
FrameHandle(JSRuntime* rt, js::jit::JitcodeGlobalEntry& entry, void* addr, | FrameHandle(JSRuntime* rt, js::jit::JitcodeGlobalEntry& entry, void* addr, | ||||
const char* label, uint32_t depth); | const char* label, uint32_t depth); | ||||
void updateHasTrackedOptimizations(); | void updateHasTrackedOptimizations(); | ||||
public: | public: | ||||
const char* label() const { return label_; } | const char* label() const { return label_; } | ||||
uint32_t depth() const { return depth_; } | uint32_t depth() const { return depth_; } | ||||
bool hasTrackedOptimizations() const { return optsIndex_.isSome(); } | bool hasTrackedOptimizations() const { return optsIndex_.isSome(); } | ||||
void* canonicalAddress() const { return canonicalAddr_; } | void* canonicalAddress() const { return canonicalAddr_; } | ||||
ProfilingFrameIterator::FrameKind frameKind() const; | JS_PUBLIC_API(ProfilingFrameIterator::FrameKind) frameKind() const; | ||||
void forEachOptimizationAttempt(ForEachTrackedOptimizationAttemptOp& op, | JS_PUBLIC_API(void) forEachOptimizationAttempt(ForEachTrackedOptimizationAttemptOp& op, | ||||
JSScript** scriptOut, jsbytecode** pcOut) const; | JSScript** scriptOut, | ||||
void forEachOptimizationTypeInfo(ForEachTrackedOptimizationTypeInfoOp& op) const; | jsbytecode** pcOut) const; | ||||
JS_PUBLIC_API(void) | |||||
forEachOptimizationTypeInfo(ForEachTrackedOptimizationTypeInfoOp& op) const; | |||||
}; | }; | ||||
// Called once per frame. | // Called once per frame. | ||||
virtual void operator()(const FrameHandle& frame) = 0; | virtual void operator()(const FrameHandle& frame) = 0; | ||||
}; | }; | ||||
JS_PUBLIC_API(void) | JS_PUBLIC_API(void) | ||||
ForEachProfiledFrame(JSRuntime* rt, void* addr, ForEachProfiledFrameOp& op); | ForEachProfiledFrame(JSContext* cx, void* addr, ForEachProfiledFrameOp& op); | ||||
} // namespace JS | } // namespace JS | ||||
#endif /* js_ProfilingFrameIterator_h */ | #endif /* js_ProfilingFrameIterator_h */ |
Wildfire Games · Phabricator