mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1154079 - Add the allocated object's [[class]] name to the allocations log. r=shu
This commit is contained in:
parent
67e5382f15
commit
6175651f60
@ -1423,7 +1423,7 @@ DisplayName(JSContext* cx, unsigned argc, jsval* vp)
|
||||
}
|
||||
|
||||
static JSObject*
|
||||
ShellObjectMetadataCallback(JSContext* cx)
|
||||
ShellObjectMetadataCallback(JSContext* cx, JSObject*)
|
||||
{
|
||||
RootedObject obj(cx, NewBuiltinClassInstance<PlainObject>(cx));
|
||||
if (!obj)
|
||||
|
@ -198,14 +198,16 @@ Function Properties of the `Debugger.Memory.prototype` Object
|
||||
<pre class='language-js'><code>
|
||||
{
|
||||
"timestamp": <i>timestamp</i>,
|
||||
"frame": <i>allocationSite</i>
|
||||
"frame": <i>allocationSite</i>,
|
||||
"class": <i>className</i>
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
Here <i>timestamp</i> is the [timestamp][timestamps] of the allocation event and
|
||||
<i>allocationSite</i> is an allocation site (as a
|
||||
[captured stack][saved-frame]). <i>allocationSite</i> is `null` for objects
|
||||
allocated with no JavaScript frames on the stack.
|
||||
Here <i>timestamp</i> is the [timestamp][timestamps] of the allocation
|
||||
event, <i>allocationSite</i> is an allocation site (as a
|
||||
[captured stack][saved-frame]), and <i>className</i> is the string name of
|
||||
the allocated object's internal `[[Class]]` property. <i>allocationSite</i>
|
||||
is `null` for objects allocated with no JavaScript frames on the stack.
|
||||
|
||||
When `trackingAllocationSites` is `false`, `drainAllocationsLog()` throws an
|
||||
`Error`.
|
||||
|
31
js/src/jit-test/tests/debug/Memory-drainAllocationsLog-15.js
Normal file
31
js/src/jit-test/tests/debug/Memory-drainAllocationsLog-15.js
Normal file
@ -0,0 +1,31 @@
|
||||
// Test drainAllocationsLog() and [[Class]] names.
|
||||
|
||||
const root = newGlobal();
|
||||
const dbg = new Debugger();
|
||||
const wrappedRoot = dbg.addDebuggee(root)
|
||||
|
||||
root.eval(
|
||||
`
|
||||
this.tests = [
|
||||
{ expected: "Object", test: () => new Object },
|
||||
{ expected: "Array", test: () => [] },
|
||||
{ expected: "Date", test: () => new Date },
|
||||
{ expected: "RegExp", test: () => /problems/ },
|
||||
{ expected: "Int8Array", test: () => new Int8Array },
|
||||
{ expected: "Promise", test: makeFakePromise },
|
||||
];
|
||||
`
|
||||
);
|
||||
|
||||
|
||||
for (let { expected, test } of root.tests) {
|
||||
print(expected);
|
||||
|
||||
dbg.memory.trackingAllocationSites = true;
|
||||
test();
|
||||
let allocs = dbg.memory.drainAllocationsLog();
|
||||
dbg.memory.trackingAllocationSites = false;
|
||||
|
||||
assertEq(allocs.some(a => a.class === expected), true);
|
||||
}
|
||||
|
@ -713,7 +713,7 @@ JSCompartment::setNewObjectMetadata(JSContext* cx, JSObject* obj)
|
||||
{
|
||||
MOZ_ASSERT(this == cx->compartment());
|
||||
|
||||
if (JSObject* metadata = objectMetadataCallback(cx)) {
|
||||
if (JSObject* metadata = objectMetadataCallback(cx, obj)) {
|
||||
if (!objectMetadataTable) {
|
||||
objectMetadataTable = cx->new_<ObjectWeakMap>(cx);
|
||||
if (!objectMetadataTable)
|
||||
|
@ -2622,7 +2622,7 @@ class JS_FRIEND_API(AutoCTypesActivityCallback) {
|
||||
};
|
||||
|
||||
typedef JSObject*
|
||||
(* ObjectMetadataCallback)(JSContext* cx);
|
||||
(* ObjectMetadataCallback)(JSContext* cx, JSObject* obj);
|
||||
|
||||
/*
|
||||
* Specify a callback to invoke when creating each JS object in the current
|
||||
|
@ -246,7 +246,8 @@ SetNewObjectMetadata(ExclusiveContext* cxArg, JSObject* obj)
|
||||
// callback, and any reentering of JS via Invoke() etc.
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
cx->compartment()->setNewObjectMetadata(cx, obj);
|
||||
RootedObject hobj(cx, obj);
|
||||
cx->compartment()->setNewObjectMetadata(cx, hobj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1695,8 +1695,8 @@ Debugger::slowPathOnNewGlobalObject(JSContext* cx, Handle<GlobalObject*> global)
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
Debugger::slowPathOnLogAllocationSite(JSContext* cx, HandleSavedFrame frame, int64_t when,
|
||||
GlobalObject::DebuggerVector& dbgs)
|
||||
Debugger::slowPathOnLogAllocationSite(JSContext* cx, HandleObject obj, HandleSavedFrame frame,
|
||||
int64_t when, GlobalObject::DebuggerVector& dbgs)
|
||||
{
|
||||
MOZ_ASSERT(!dbgs.empty());
|
||||
mozilla::DebugOnly<Debugger**> begin = dbgs.begin();
|
||||
@ -1708,7 +1708,7 @@ Debugger::slowPathOnLogAllocationSite(JSContext* cx, HandleSavedFrame frame, int
|
||||
|
||||
if ((*dbgp)->trackingAllocationSites &&
|
||||
(*dbgp)->enabled &&
|
||||
!(*dbgp)->appendAllocationSite(cx, frame, when))
|
||||
!(*dbgp)->appendAllocationSite(cx, obj, frame, when))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -1725,14 +1725,15 @@ Debugger::isDebuggee(const JSCompartment* compartment) const
|
||||
}
|
||||
|
||||
bool
|
||||
Debugger::appendAllocationSite(JSContext* cx, HandleSavedFrame frame, int64_t when)
|
||||
Debugger::appendAllocationSite(JSContext* cx, HandleObject obj, HandleSavedFrame frame,
|
||||
int64_t when)
|
||||
{
|
||||
AutoCompartment ac(cx, object);
|
||||
RootedObject wrapped(cx, frame);
|
||||
if (!cx->compartment()->wrap(cx, &wrapped))
|
||||
RootedObject wrappedFrame(cx, frame);
|
||||
if (!cx->compartment()->wrap(cx, &wrappedFrame))
|
||||
return false;
|
||||
|
||||
AllocationSite* allocSite = cx->new_<AllocationSite>(wrapped, when);
|
||||
AllocationSite* allocSite = cx->new_<AllocationSite>(wrappedFrame, when, obj->getClass()->name);
|
||||
if (!allocSite)
|
||||
return false;
|
||||
|
||||
|
@ -255,11 +255,17 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
|
||||
|
||||
struct AllocationSite : public mozilla::LinkedListElement<AllocationSite>
|
||||
{
|
||||
AllocationSite(HandleObject frame, int64_t when) : frame(frame), when(when) {
|
||||
AllocationSite(HandleObject frame, int64_t when, const char* className)
|
||||
: frame(frame),
|
||||
when(when),
|
||||
className(className)
|
||||
{
|
||||
MOZ_ASSERT_IF(frame, UncheckedUnwrap(frame)->is<SavedFrame>());
|
||||
};
|
||||
|
||||
RelocatablePtrObject frame;
|
||||
int64_t when;
|
||||
const char* className;
|
||||
};
|
||||
typedef mozilla::LinkedList<AllocationSite> AllocationSiteList;
|
||||
|
||||
@ -305,7 +311,8 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
|
||||
|
||||
static const size_t DEFAULT_MAX_ALLOCATIONS_LOG_LENGTH = 5000;
|
||||
|
||||
bool appendAllocationSite(JSContext* cx, HandleSavedFrame frame, int64_t when);
|
||||
bool appendAllocationSite(JSContext* cx, HandleObject obj, HandleSavedFrame frame,
|
||||
int64_t when);
|
||||
void emptyAllocationsLog();
|
||||
|
||||
/*
|
||||
@ -515,7 +522,7 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
|
||||
static JSTrapStatus slowPathOnExceptionUnwind(JSContext* cx, AbstractFramePtr frame);
|
||||
static void slowPathOnNewScript(JSContext* cx, HandleScript script);
|
||||
static void slowPathOnNewGlobalObject(JSContext* cx, Handle<GlobalObject*> global);
|
||||
static bool slowPathOnLogAllocationSite(JSContext* cx, HandleSavedFrame frame,
|
||||
static bool slowPathOnLogAllocationSite(JSContext* cx, HandleObject obj, HandleSavedFrame frame,
|
||||
int64_t when, GlobalObject::DebuggerVector& dbgs);
|
||||
static void slowPathPromiseHook(JSContext* cx, Hook hook, HandleObject promise);
|
||||
static JSTrapStatus dispatchHook(JSContext* cx, MutableHandleValue vp, Hook which,
|
||||
@ -666,7 +673,8 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
|
||||
|
||||
static inline void onNewScript(JSContext* cx, HandleScript script);
|
||||
static inline void onNewGlobalObject(JSContext* cx, Handle<GlobalObject*> global);
|
||||
static inline bool onLogAllocationSite(JSContext* cx, HandleSavedFrame frame, int64_t when);
|
||||
static inline bool onLogAllocationSite(JSContext* cx, JSObject* obj, HandleSavedFrame frame,
|
||||
int64_t when);
|
||||
static inline void onGarbageCollection(JSRuntime* rt, const gcstats::Statistics& stats);
|
||||
static JSTrapStatus onTrap(JSContext* cx, MutableHandleValue vp);
|
||||
static JSTrapStatus onSingleStep(JSContext* cx, MutableHandleValue vp);
|
||||
@ -975,12 +983,13 @@ Debugger::onNewGlobalObject(JSContext* cx, Handle<GlobalObject*> global)
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
Debugger::onLogAllocationSite(JSContext* cx, HandleSavedFrame frame, int64_t when)
|
||||
Debugger::onLogAllocationSite(JSContext* cx, JSObject* obj, HandleSavedFrame frame, int64_t when)
|
||||
{
|
||||
GlobalObject::DebuggerVector* dbgs = cx->global()->getDebuggers();
|
||||
if (!dbgs || dbgs->empty())
|
||||
return true;
|
||||
return Debugger::slowPathOnLogAllocationSite(cx, frame, when, *dbgs);
|
||||
RootedObject hobj(cx, obj);
|
||||
return Debugger::slowPathOnLogAllocationSite(cx, hobj, frame, when, *dbgs);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
|
@ -209,6 +209,13 @@ DebuggerMemory::drainAllocationsLog(JSContext* cx, unsigned argc, Value* vp)
|
||||
if (!DefineProperty(cx, obj, cx->names().timestamp, timestampValue))
|
||||
return false;
|
||||
|
||||
RootedString className(cx, Atomize(cx, allocSite->className, strlen(allocSite->className)));
|
||||
if (!className)
|
||||
return false;
|
||||
RootedValue classNameValue(cx, StringValue(className));
|
||||
if (!DefineProperty(cx, obj, cx->names().class_, classNameValue))
|
||||
return false;
|
||||
|
||||
result->setDenseElement(i, ObjectValue(*obj));
|
||||
|
||||
// Pop the front queue entry, and delete it immediately, so that
|
||||
|
@ -1180,8 +1180,10 @@ SavedStacks::chooseSamplingProbability(JSContext* cx)
|
||||
}
|
||||
|
||||
JSObject*
|
||||
SavedStacksMetadataCallback(JSContext* cx)
|
||||
SavedStacksMetadataCallback(JSContext* cx, JSObject* target)
|
||||
{
|
||||
RootedObject obj(cx, target);
|
||||
|
||||
SavedStacks& stacks = cx->compartment()->savedStacks();
|
||||
if (stacks.allocationSkipCount > 0) {
|
||||
stacks.allocationSkipCount--;
|
||||
@ -1221,7 +1223,7 @@ SavedStacksMetadataCallback(JSContext* cx)
|
||||
if (!stacks.saveCurrentStack(cx, &frame))
|
||||
CrashAtUnhandlableOOM("SavedStacksMetadataCallback");
|
||||
|
||||
if (!Debugger::onLogAllocationSite(cx, frame, PRMJ_Now()))
|
||||
if (!Debugger::onLogAllocationSite(cx, obj, frame, PRMJ_Now()))
|
||||
CrashAtUnhandlableOOM("SavedStacksMetadataCallback");
|
||||
|
||||
return frame;
|
||||
|
@ -260,7 +260,7 @@ struct SavedFrame::HashPolicy
|
||||
inline void AssertObjectIsSavedFrameOrWrapper(JSContext* cx, HandleObject stack);
|
||||
|
||||
class SavedStacks {
|
||||
friend JSObject* SavedStacksMetadataCallback(JSContext* cx);
|
||||
friend JSObject* SavedStacksMetadataCallback(JSContext* cx, JSObject* target);
|
||||
|
||||
public:
|
||||
SavedStacks()
|
||||
@ -400,7 +400,7 @@ class SavedStacks {
|
||||
bool getLocation(JSContext* cx, const FrameIter& iter, MutableHandleLocationValue locationp);
|
||||
};
|
||||
|
||||
JSObject* SavedStacksMetadataCallback(JSContext* cx);
|
||||
JSObject* SavedStacksMetadataCallback(JSContext* cx, JSObject* target);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user