mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-12 10:40:12 +00:00
Bug 1301377 - Disallow GC while using ProfilingFrameIterator r=jandem
This commit is contained in:
parent
7b7d057eda
commit
c50fa1fd48
@ -11,6 +11,7 @@
|
||||
#include "mozilla/Maybe.h"
|
||||
|
||||
#include "jsbytecode.h"
|
||||
#include "js/GCAPI.h"
|
||||
#include "js/TypeDecls.h"
|
||||
#include "js/Utility.h"
|
||||
|
||||
@ -39,6 +40,10 @@ struct ForEachTrackedOptimizationTypeInfoOp;
|
||||
// arbitrary pc. To provide acurate results, profiling must have been enabled
|
||||
// (via EnableRuntimeProfilingStack) before executing the callstack being
|
||||
// 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)
|
||||
{
|
||||
JSRuntime* rt_;
|
||||
@ -50,6 +55,8 @@ class JS_PUBLIC_API(ProfilingFrameIterator)
|
||||
// activation (if any) comes around.
|
||||
void* savedPrevJitTop_;
|
||||
|
||||
JS::AutoCheckCannotGC nogc_;
|
||||
|
||||
static const unsigned StorageSpace = 8 * sizeof(void*);
|
||||
mozilla::AlignedStorage<StorageSpace> storage_;
|
||||
js::wasm::ProfilingFrameIterator& asmJSIter() {
|
||||
|
@ -1639,34 +1639,30 @@ ReadSPSProfilingStack(JSContext* cx, unsigned argc, Value* vp)
|
||||
return true;
|
||||
}
|
||||
|
||||
RootedObject inlineStack(cx);
|
||||
RootedObject inlineFrameInfo(cx);
|
||||
RootedString frameKind(cx);
|
||||
RootedString frameLabel(cx);
|
||||
RootedId idx(cx);
|
||||
struct InlineFrameInfo
|
||||
{
|
||||
InlineFrameInfo(const char* kind, UniqueChars&& label)
|
||||
: kind(kind), label(mozilla::Move(label)) {}
|
||||
const char* kind;
|
||||
UniqueChars label;
|
||||
};
|
||||
|
||||
Vector<Vector<InlineFrameInfo, 0, TempAllocPolicy>, 0, TempAllocPolicy> frameInfo(cx);
|
||||
|
||||
JS::ProfilingFrameIterator::RegisterState state;
|
||||
uint32_t physicalFrameNo = 0;
|
||||
const unsigned propAttrs = JSPROP_ENUMERATE;
|
||||
for (JS::ProfilingFrameIterator i(cx, state); !i.done(); ++i, ++physicalFrameNo) {
|
||||
for (JS::ProfilingFrameIterator i(cx, state); !i.done(); ++i) {
|
||||
MOZ_ASSERT(i.stackAddress() != nullptr);
|
||||
|
||||
// Array holding all inline frames in a single physical jit stack frame.
|
||||
inlineStack = NewDenseEmptyArray(cx);
|
||||
if (!inlineStack)
|
||||
if (!frameInfo.emplaceBack(cx))
|
||||
return false;
|
||||
|
||||
JS::ProfilingFrameIterator::Frame frames[16];
|
||||
uint32_t nframes = i.extractStack(frames, 0, 16);
|
||||
for (uint32_t inlineFrameNo = 0; inlineFrameNo < nframes; inlineFrameNo++) {
|
||||
|
||||
// Object holding frame info.
|
||||
inlineFrameInfo = NewBuiltinClassInstance<PlainObject>(cx);
|
||||
if (!inlineFrameInfo)
|
||||
return false;
|
||||
|
||||
const size_t MaxInlineFrames = 16;
|
||||
JS::ProfilingFrameIterator::Frame frames[MaxInlineFrames];
|
||||
uint32_t nframes = i.extractStack(frames, 0, MaxInlineFrames);
|
||||
MOZ_ASSERT(nframes <= MaxInlineFrames);
|
||||
for (uint32_t i = 0; i < nframes; i++) {
|
||||
const char* frameKindStr = nullptr;
|
||||
switch (frames[inlineFrameNo].kind) {
|
||||
switch (frames[i].kind) {
|
||||
case JS::ProfilingFrameIterator::Frame_Baseline:
|
||||
frameKindStr = "baseline";
|
||||
break;
|
||||
@ -1679,14 +1675,41 @@ ReadSPSProfilingStack(JSContext* cx, unsigned argc, Value* vp)
|
||||
default:
|
||||
frameKindStr = "unknown";
|
||||
}
|
||||
frameKind = NewStringCopyZ<CanGC>(cx, frameKindStr);
|
||||
|
||||
if (!frameInfo.back().emplaceBack(frameKindStr, mozilla::Move(frames[i].label)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
RootedObject inlineFrameInfo(cx);
|
||||
RootedString frameKind(cx);
|
||||
RootedString frameLabel(cx);
|
||||
RootedId idx(cx);
|
||||
|
||||
const unsigned propAttrs = JSPROP_ENUMERATE;
|
||||
|
||||
uint32_t physicalFrameNo = 0;
|
||||
for (auto& frame : frameInfo) {
|
||||
// Array holding all inline frames in a single physical jit stack frame.
|
||||
RootedObject inlineStack(cx, NewDenseEmptyArray(cx));
|
||||
if (!inlineStack)
|
||||
return false;
|
||||
|
||||
uint32_t inlineFrameNo = 0;
|
||||
for (auto& inlineFrame : frame) {
|
||||
// Object holding frame info.
|
||||
RootedObject inlineFrameInfo(cx, NewBuiltinClassInstance<PlainObject>(cx));
|
||||
if (!inlineFrameInfo)
|
||||
return false;
|
||||
|
||||
frameKind = NewStringCopyZ<CanGC>(cx, inlineFrame.kind);
|
||||
if (!frameKind)
|
||||
return false;
|
||||
|
||||
if (!JS_DefineProperty(cx, inlineFrameInfo, "kind", frameKind, propAttrs))
|
||||
return false;
|
||||
|
||||
auto chars = frames[inlineFrameNo].label.release();
|
||||
auto chars = inlineFrame.label.release();
|
||||
frameLabel = NewString<CanGC>(cx, reinterpret_cast<Latin1Char*>(chars), strlen(chars));
|
||||
if (!frameLabel)
|
||||
return false;
|
||||
@ -1697,12 +1720,16 @@ ReadSPSProfilingStack(JSContext* cx, unsigned argc, Value* vp)
|
||||
idx = INT_TO_JSID(inlineFrameNo);
|
||||
if (!JS_DefinePropertyById(cx, inlineStack, idx, inlineFrameInfo, 0))
|
||||
return false;
|
||||
|
||||
++inlineFrameNo;
|
||||
}
|
||||
|
||||
// Push inline array into main array.
|
||||
idx = INT_TO_JSID(physicalFrameNo);
|
||||
if (!JS_DefinePropertyById(cx, stack, idx, inlineStack, 0))
|
||||
return false;
|
||||
|
||||
++physicalFrameNo;
|
||||
}
|
||||
|
||||
args.rval().setObject(*stack);
|
||||
|
12
js/src/jit-test/tests/gc/bug-1301377.js
Normal file
12
js/src/jit-test/tests/gc/bug-1301377.js
Normal file
@ -0,0 +1,12 @@
|
||||
var lfLogBuffer = `
|
||||
gczeal(14);
|
||||
enableSPSProfiling();
|
||||
gczeal(15,3);
|
||||
var s = "";
|
||||
for (let i = 0; i != 30; i+=2) {}
|
||||
readSPSProfilingStack(s, "c0d1c0d1c0d1c0d1c0d1c0d1c0d1c0");
|
||||
`;
|
||||
loadFile(lfLogBuffer);
|
||||
function loadFile(lfVarx) {
|
||||
evaluate(lfVarx);
|
||||
}
|
@ -1723,7 +1723,8 @@ JS::ProfilingFrameIterator::ProfilingFrameIterator(JSContext* cx, const Register
|
||||
: rt_(cx),
|
||||
sampleBufferGen_(sampleBufferGen),
|
||||
activation_(nullptr),
|
||||
savedPrevJitTop_(nullptr)
|
||||
savedPrevJitTop_(nullptr),
|
||||
nogc_(cx)
|
||||
{
|
||||
if (!cx->spsProfiler.enabled())
|
||||
MOZ_CRASH("ProfilingFrameIterator called when spsProfiler not enabled for runtime.");
|
||||
|
Loading…
x
Reference in New Issue
Block a user