зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1057082 - Part 1 - Add profilingActivation linked list and refactor ProfilingFrameIterator. r=luke
This commit is contained in:
Родитель
872b0b7fbc
Коммит
7141c60325
|
@ -15,7 +15,11 @@
|
|||
|
||||
class JSAtom;
|
||||
struct JSRuntime;
|
||||
namespace js { class AsmJSActivation; class AsmJSProfilingFrameIterator; }
|
||||
|
||||
namespace js {
|
||||
class Activation;
|
||||
class AsmJSProfilingFrameIterator;
|
||||
}
|
||||
|
||||
namespace JS {
|
||||
|
||||
|
@ -25,15 +29,15 @@ namespace JS {
|
|||
// unwound.
|
||||
class JS_PUBLIC_API(ProfilingFrameIterator)
|
||||
{
|
||||
js::AsmJSActivation *activation_;
|
||||
js::Activation *activation_;
|
||||
|
||||
static const unsigned StorageSpace = 6 * sizeof(void*);
|
||||
mozilla::AlignedStorage<StorageSpace> storage_;
|
||||
js::AsmJSProfilingFrameIterator &iter() {
|
||||
js::AsmJSProfilingFrameIterator &asmJSIter() {
|
||||
JS_ASSERT(!done());
|
||||
return *reinterpret_cast<js::AsmJSProfilingFrameIterator*>(storage_.addr());
|
||||
}
|
||||
const js::AsmJSProfilingFrameIterator &iter() const {
|
||||
const js::AsmJSProfilingFrameIterator &asmJSIter() const {
|
||||
JS_ASSERT(!done());
|
||||
return *reinterpret_cast<const js::AsmJSProfilingFrameIterator*>(storage_.addr());
|
||||
}
|
||||
|
@ -64,6 +68,12 @@ class JS_PUBLIC_API(ProfilingFrameIterator)
|
|||
// Return a label suitable for regexp-matching as performed by
|
||||
// browser/devtools/profiler/cleopatra/js/parserWorker.js
|
||||
const char *label() const;
|
||||
|
||||
private:
|
||||
void iteratorConstruct(const RegisterState &state);
|
||||
void iteratorConstruct();
|
||||
void iteratorDestroy();
|
||||
bool iteratorDone();
|
||||
};
|
||||
|
||||
} // namespace JS
|
||||
|
|
|
@ -267,6 +267,10 @@ class ForkJoinActivation : public Activation
|
|||
public:
|
||||
explicit ForkJoinActivation(JSContext *cx);
|
||||
~ForkJoinActivation();
|
||||
|
||||
bool isProfiling() const {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class ForkJoinContext;
|
||||
|
|
|
@ -78,6 +78,7 @@ PerThreadData::PerThreadData(JSRuntime *runtime)
|
|||
traceLogger(nullptr),
|
||||
#endif
|
||||
activation_(nullptr),
|
||||
profilingActivation_(nullptr),
|
||||
asmJSActivationStack_(nullptr),
|
||||
autoFlushICache_(nullptr),
|
||||
#if defined(JS_ARM_SIMULATOR) || defined(JS_MIPS_SIMULATOR)
|
||||
|
|
|
@ -567,6 +567,12 @@ class PerThreadData : public PerThreadDataFriendFields
|
|||
*/
|
||||
js::Activation *activation_;
|
||||
|
||||
/*
|
||||
* Points to the most recent profiling activation running on the
|
||||
* thread. Protected by rt->interruptLock.
|
||||
*/
|
||||
js::Activation * volatile profilingActivation_;
|
||||
|
||||
/* See AsmJSActivation comment. Protected by rt->interruptLock. */
|
||||
js::AsmJSActivation * volatile asmJSActivationStack_;
|
||||
|
||||
|
@ -589,6 +595,10 @@ class PerThreadData : public PerThreadDataFriendFields
|
|||
return offsetof(PerThreadData, activation_);
|
||||
}
|
||||
|
||||
js::Activation *profilingActivation() const {
|
||||
return profilingActivation_;
|
||||
}
|
||||
|
||||
js::AsmJSActivation *asmJSActivationStack() const {
|
||||
return asmJSActivationStack_;
|
||||
}
|
||||
|
|
|
@ -738,11 +738,16 @@ Activation::Activation(ThreadSafeContext *cx, Kind kind)
|
|||
: cx_(cx),
|
||||
compartment_(cx->compartment_),
|
||||
prev_(cx->perThreadData->activation_),
|
||||
prevProfiling_(prev_ ? prev_->mostRecentProfiling() : nullptr),
|
||||
savedFrameChain_(0),
|
||||
hideScriptedCallerCount_(0),
|
||||
kind_(kind)
|
||||
{
|
||||
cx->perThreadData->activation_ = this;
|
||||
|
||||
// Link the activation into the list of profiling activations if needed.
|
||||
if (isProfiling())
|
||||
registerProfiling();
|
||||
}
|
||||
|
||||
Activation::~Activation()
|
||||
|
@ -750,6 +755,33 @@ Activation::~Activation()
|
|||
JS_ASSERT(cx_->perThreadData->activation_ == this);
|
||||
JS_ASSERT(hideScriptedCallerCount_ == 0);
|
||||
cx_->perThreadData->activation_ = prev_;
|
||||
|
||||
if (isProfiling())
|
||||
unregisterProfiling();
|
||||
}
|
||||
|
||||
bool
|
||||
Activation::isProfiling() const
|
||||
{
|
||||
if (isInterpreter())
|
||||
return asInterpreter()->isProfiling();
|
||||
|
||||
if (isJit())
|
||||
return asJit()->isProfiling();
|
||||
|
||||
if (isForkJoin())
|
||||
return asForkJoin()->isProfiling();
|
||||
|
||||
JS_ASSERT(isAsmJS());
|
||||
return asAsmJS()->isProfiling();
|
||||
}
|
||||
|
||||
Activation *
|
||||
Activation::mostRecentProfiling()
|
||||
{
|
||||
if (isProfiling())
|
||||
return this;
|
||||
return prevProfiling_;
|
||||
}
|
||||
|
||||
InterpreterActivation::InterpreterActivation(RunState &state, JSContext *cx,
|
||||
|
|
|
@ -1618,6 +1618,23 @@ InterpreterFrameIterator::operator++()
|
|||
return *this;
|
||||
}
|
||||
|
||||
void
|
||||
Activation::registerProfiling()
|
||||
{
|
||||
JS_ASSERT(isProfiling());
|
||||
JSRuntime::AutoLockForInterrupt lock(cx_->asJSContext()->runtime());
|
||||
cx_->perThreadData->profilingActivation_ = this;
|
||||
}
|
||||
|
||||
void
|
||||
Activation::unregisterProfiling()
|
||||
{
|
||||
JS_ASSERT(isProfiling());
|
||||
JSRuntime::AutoLockForInterrupt lock(cx_->asJSContext()->runtime());
|
||||
JS_ASSERT(cx_->perThreadData->profilingActivation_ == this);
|
||||
cx_->perThreadData->profilingActivation_ = prevProfiling_;
|
||||
}
|
||||
|
||||
ActivationIterator::ActivationIterator(JSRuntime *rt)
|
||||
: jitTop_(rt->mainThread.jitTop),
|
||||
activation_(rt->mainThread.activation_)
|
||||
|
@ -1653,50 +1670,99 @@ ActivationIterator::settle()
|
|||
}
|
||||
|
||||
JS::ProfilingFrameIterator::ProfilingFrameIterator(JSRuntime *rt, const RegisterState &state)
|
||||
: activation_(rt->mainThread.asmJSActivationStack())
|
||||
: activation_(rt->mainThread.profilingActivation())
|
||||
{
|
||||
if (!activation_)
|
||||
return;
|
||||
|
||||
JS_ASSERT(activation_->isProfiling());
|
||||
|
||||
static_assert(sizeof(AsmJSProfilingFrameIterator) <= StorageSpace, "Need to increase storage");
|
||||
new (storage_.addr()) AsmJSProfilingFrameIterator(*activation_, state);
|
||||
|
||||
iteratorConstruct(state);
|
||||
settle();
|
||||
}
|
||||
|
||||
JS::ProfilingFrameIterator::~ProfilingFrameIterator()
|
||||
{
|
||||
if (!done())
|
||||
iter().~AsmJSProfilingFrameIterator();
|
||||
if (!done()) {
|
||||
JS_ASSERT(activation_->isProfiling());
|
||||
iteratorDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
JS::ProfilingFrameIterator::operator++()
|
||||
{
|
||||
JS_ASSERT(!done());
|
||||
++iter();
|
||||
|
||||
JS_ASSERT(activation_->isAsmJS());
|
||||
++asmJSIter();
|
||||
settle();
|
||||
}
|
||||
|
||||
void
|
||||
JS::ProfilingFrameIterator::settle()
|
||||
{
|
||||
while (iter().done()) {
|
||||
iter().~AsmJSProfilingFrameIterator();
|
||||
activation_ = activation_->prevAsmJS();
|
||||
while (iteratorDone()) {
|
||||
iteratorDestroy();
|
||||
activation_ = activation_->prevProfiling();
|
||||
if (!activation_)
|
||||
return;
|
||||
new (storage_.addr()) AsmJSProfilingFrameIterator(*activation_);
|
||||
iteratorConstruct();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
JS::ProfilingFrameIterator::iteratorConstruct(const RegisterState &state)
|
||||
{
|
||||
JS_ASSERT(!done());
|
||||
|
||||
JS_ASSERT(activation_->isAsmJS());
|
||||
new (storage_.addr()) AsmJSProfilingFrameIterator(*activation_->asAsmJS(), state);
|
||||
}
|
||||
|
||||
void
|
||||
JS::ProfilingFrameIterator::iteratorConstruct()
|
||||
{
|
||||
JS_ASSERT(!done());
|
||||
|
||||
JS_ASSERT(activation_->isAsmJS());
|
||||
new (storage_.addr()) AsmJSProfilingFrameIterator(*activation_->asAsmJS());
|
||||
}
|
||||
|
||||
void
|
||||
JS::ProfilingFrameIterator::iteratorDestroy()
|
||||
{
|
||||
JS_ASSERT(!done());
|
||||
|
||||
JS_ASSERT(activation_->isAsmJS());
|
||||
asmJSIter().~AsmJSProfilingFrameIterator();
|
||||
}
|
||||
|
||||
bool
|
||||
JS::ProfilingFrameIterator::iteratorDone()
|
||||
{
|
||||
JS_ASSERT(!done());
|
||||
|
||||
JS_ASSERT(activation_->isAsmJS());
|
||||
return asmJSIter().done();
|
||||
}
|
||||
|
||||
void *
|
||||
JS::ProfilingFrameIterator::stackAddress() const
|
||||
{
|
||||
return iter().stackAddress();
|
||||
JS_ASSERT(!done());
|
||||
|
||||
JS_ASSERT(activation_->isAsmJS());
|
||||
return asmJSIter().stackAddress();
|
||||
}
|
||||
|
||||
const char *
|
||||
JS::ProfilingFrameIterator::label() const
|
||||
{
|
||||
return iter().label();
|
||||
JS_ASSERT(!done());
|
||||
|
||||
JS_ASSERT(activation_->isAsmJS());
|
||||
return asmJSIter().label();
|
||||
}
|
||||
|
|
|
@ -1103,6 +1103,7 @@ class Activation
|
|||
ThreadSafeContext *cx_;
|
||||
JSCompartment *compartment_;
|
||||
Activation *prev_;
|
||||
Activation *prevProfiling_;
|
||||
|
||||
// Counter incremented by JS_SaveFrameChain on the top-most activation and
|
||||
// decremented by JS_RestoreFrameChain. If > 0, ScriptFrameIter should stop
|
||||
|
@ -1133,6 +1134,8 @@ class Activation
|
|||
Activation *prev() const {
|
||||
return prev_;
|
||||
}
|
||||
Activation *prevProfiling() const { return prevProfiling_; }
|
||||
inline Activation *mostRecentProfiling();
|
||||
|
||||
bool isInterpreter() const {
|
||||
return kind_ == Interpreter;
|
||||
|
@ -1147,6 +1150,10 @@ class Activation
|
|||
return kind_ == AsmJS;
|
||||
}
|
||||
|
||||
inline bool isProfiling() const;
|
||||
void registerProfiling();
|
||||
void unregisterProfiling();
|
||||
|
||||
InterpreterActivation *asInterpreter() const {
|
||||
JS_ASSERT(isInterpreter());
|
||||
return (InterpreterActivation *)this;
|
||||
|
@ -1238,6 +1245,10 @@ class InterpreterActivation : public Activation
|
|||
return opMask_;
|
||||
}
|
||||
|
||||
bool isProfiling() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If this js::Interpret frame is running |script|, enable interrupts.
|
||||
void enableInterruptsIfRunning(JSScript *script) {
|
||||
if (regs_.fp()->script() == script)
|
||||
|
@ -1323,6 +1334,10 @@ class JitActivation : public Activation
|
|||
}
|
||||
void setActive(JSContext *cx, bool active = true);
|
||||
|
||||
bool isProfiling() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t *prevJitTop() const {
|
||||
return prevJitTop_;
|
||||
}
|
||||
|
@ -1481,6 +1496,10 @@ class AsmJSActivation : public Activation
|
|||
AsmJSModule &module() const { return module_; }
|
||||
AsmJSActivation *prevAsmJS() const { return prevAsmJS_; }
|
||||
|
||||
bool isProfiling() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns a pointer to the base of the innermost stack frame of asm.js code
|
||||
// in this activation.
|
||||
uint8_t *fp() const { return fp_; }
|
||||
|
|
Загрузка…
Ссылка в новой задаче