mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1189490 - Part 2: Stop using mozilla::LinkedList for the allocations and tenure promotions logs and use js::TraceableFifo instead; r=terrence
This commit is contained in:
parent
850280ccc2
commit
7b0a0d9d98
@ -357,15 +357,15 @@ Debugger::Debugger(JSContext* cx, NativeObject* dbg)
|
||||
: object(dbg),
|
||||
uncaughtExceptionHook(nullptr),
|
||||
enabled(true),
|
||||
allowUnobservedAsmJS(false),
|
||||
observedGCs(cx),
|
||||
tenurePromotionsLog(cx),
|
||||
trackingTenurePromotions(false),
|
||||
tenurePromotionsLogLength(0),
|
||||
maxTenurePromotionsLogLength(DEFAULT_MAX_LOG_LENGTH),
|
||||
tenurePromotionsLogOverflowed(false),
|
||||
allowUnobservedAsmJS(false),
|
||||
allocationsLog(cx),
|
||||
trackingAllocationSites(false),
|
||||
allocationSamplingProbability(1.0),
|
||||
allocationsLogLength(0),
|
||||
maxAllocationsLogLength(DEFAULT_MAX_LOG_LENGTH),
|
||||
allocationsLogOverflowed(false),
|
||||
frames(cx->runtime()),
|
||||
@ -390,8 +390,8 @@ Debugger::Debugger(JSContext* cx, NativeObject* dbg)
|
||||
Debugger::~Debugger()
|
||||
{
|
||||
MOZ_ASSERT_IF(debuggees.initialized(), debuggees.empty());
|
||||
emptyAllocationsLog();
|
||||
emptyTenurePromotionsLog();
|
||||
allocationsLog.clear();
|
||||
tenurePromotionsLog.clear();
|
||||
|
||||
/*
|
||||
* Since the inactive state for this link is a singleton cycle, it's always
|
||||
@ -1701,7 +1701,7 @@ Debugger::isDebuggee(const JSCompartment* compartment) const
|
||||
return compartment->isDebuggee() && debuggees.has(compartment->maybeGlobal());
|
||||
}
|
||||
|
||||
Debugger::TenurePromotionsEntry::TenurePromotionsEntry(JSRuntime* rt, JSObject& obj, double when)
|
||||
Debugger::TenurePromotionsLogEntry::TenurePromotionsLogEntry(JSRuntime* rt, JSObject& obj, double when)
|
||||
: className(obj.getClass()->name),
|
||||
when(when),
|
||||
frame(getObjectAllocationSite(obj)),
|
||||
@ -1712,43 +1712,17 @@ Debugger::TenurePromotionsEntry::TenurePromotionsEntry(JSRuntime* rt, JSObject&
|
||||
void
|
||||
Debugger::logTenurePromotion(JSRuntime* rt, JSObject& obj, double when)
|
||||
{
|
||||
auto* entry = js_new<TenurePromotionsEntry>(rt, obj, when);
|
||||
if (!entry)
|
||||
if (!tenurePromotionsLog.emplaceBack(rt, obj, when))
|
||||
CrashAtUnhandlableOOM("Debugger::logTenurePromotion");
|
||||
|
||||
tenurePromotionsLog.insertBack(entry);
|
||||
if (tenurePromotionsLogLength >= maxTenurePromotionsLogLength) {
|
||||
js_delete(tenurePromotionsLog.popFirst());
|
||||
if (tenurePromotionsLog.length() > maxTenurePromotionsLogLength) {
|
||||
if (!tenurePromotionsLog.popFront())
|
||||
CrashAtUnhandlableOOM("Debugger::logTenurePromotion");
|
||||
MOZ_ASSERT(tenurePromotionsLog.length() == maxTenurePromotionsLogLength);
|
||||
tenurePromotionsLogOverflowed = true;
|
||||
} else {
|
||||
tenurePromotionsLogLength++;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ Debugger::AllocationSite*
|
||||
Debugger::AllocationSite::create(JSContext* cx, HandleObject frame, double when, HandleObject obj)
|
||||
{
|
||||
assertSameCompartment(cx, frame);
|
||||
|
||||
RootedAtom ctorName(cx);
|
||||
{
|
||||
AutoCompartment ac(cx, obj);
|
||||
if (!obj->constructorDisplayAtom(cx, &ctorName))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AllocationSite* allocSite = cx->new_<AllocationSite>(frame, when);
|
||||
if (!allocSite)
|
||||
return nullptr;
|
||||
|
||||
allocSite->className = obj->getClass()->name;
|
||||
allocSite->ctorName = ctorName.get();
|
||||
allocSite->size = JS::ubi::Node(obj.get()).size(cx->runtime()->debuggerMallocSizeOf);
|
||||
|
||||
return allocSite;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Debugger::appendAllocationSite(JSContext* cx, HandleObject obj, HandleSavedFrame frame,
|
||||
double when)
|
||||
@ -1760,38 +1734,34 @@ Debugger::appendAllocationSite(JSContext* cx, HandleObject obj, HandleSavedFrame
|
||||
if (!cx->compartment()->wrap(cx, &wrappedFrame))
|
||||
return false;
|
||||
|
||||
AllocationSite* allocSite = AllocationSite::create(cx, wrappedFrame, when, obj);
|
||||
if (!allocSite)
|
||||
RootedAtom ctorName(cx);
|
||||
{
|
||||
AutoCompartment ac(cx, obj);
|
||||
if (!obj->constructorDisplayAtom(cx, &ctorName))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto className = obj->getClass()->name;
|
||||
auto size = JS::ubi::Node(obj.get()).size(cx->runtime()->debuggerMallocSizeOf);
|
||||
|
||||
if (!allocationsLog.emplaceBack(wrappedFrame, when, className, ctorName, size))
|
||||
{
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
allocationsLog.insertBack(allocSite);
|
||||
|
||||
if (allocationsLogLength >= maxAllocationsLogLength) {
|
||||
js_delete(allocationsLog.popFirst());
|
||||
if (allocationsLog.length() > maxAllocationsLogLength) {
|
||||
if (!allocationsLog.popFront()) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(allocationsLog.length() == maxAllocationsLogLength);
|
||||
allocationsLogOverflowed = true;
|
||||
} else {
|
||||
allocationsLogLength++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Debugger::emptyAllocationsLog()
|
||||
{
|
||||
while (!allocationsLog.isEmpty())
|
||||
js_delete(allocationsLog.popFirst());
|
||||
allocationsLogLength = 0;
|
||||
}
|
||||
|
||||
void
|
||||
Debugger::emptyTenurePromotionsLog()
|
||||
{
|
||||
while (!tenurePromotionsLog.isEmpty())
|
||||
js_delete(tenurePromotionsLog.popFirst());
|
||||
tenurePromotionsLogLength = 0;
|
||||
}
|
||||
|
||||
JSTrapStatus
|
||||
Debugger::firePromiseHook(JSContext* cx, Hook hook, HandleObject promise, MutableHandleValue vp)
|
||||
{
|
||||
@ -2332,7 +2302,7 @@ Debugger::removeAllocationsTrackingForAllDebuggees()
|
||||
for (WeakGlobalObjectSet::Range r = debuggees.all(); !r.empty(); r.popFront()) {
|
||||
Debugger::removeAllocationsTracking(*r.front().get());
|
||||
}
|
||||
emptyAllocationsLog();
|
||||
allocationsLog.clear();
|
||||
}
|
||||
|
||||
|
||||
@ -2351,19 +2321,7 @@ Debugger::markCrossCompartmentEdges(JSTracer* trc)
|
||||
// `Debugger::logTenurePromotion`, we can't hold onto CCWs inside the log,
|
||||
// and instead have unwrapped cross-compartment edges. We need to be sure to
|
||||
// mark those here.
|
||||
traceTenurePromotionsLog(trc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Trace every entry in the promoted to tenured heap log.
|
||||
*/
|
||||
void
|
||||
Debugger::traceTenurePromotionsLog(JSTracer* trc)
|
||||
{
|
||||
for (TenurePromotionsEntry* e = tenurePromotionsLog.getFirst(); e; e = e->getNext()) {
|
||||
if (e->frame)
|
||||
TraceEdge(trc, &e->frame, "Debugger::tenurePromotionsLog SavedFrame");
|
||||
}
|
||||
TenurePromotionsLog::trace(&tenurePromotionsLog, trc);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2544,17 +2502,8 @@ Debugger::trace(JSTracer* trc)
|
||||
TraceEdge(trc, &frameobj, "live Debugger.Frame");
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark every allocation site in our allocation log.
|
||||
*/
|
||||
for (AllocationSite* s = allocationsLog.getFirst(); s; s = s->getNext()) {
|
||||
if (s->frame)
|
||||
TraceEdge(trc, &s->frame, "allocation log SavedFrame");
|
||||
if (s->ctorName)
|
||||
TraceEdge(trc, &s->ctorName, "allocation log constructor name");
|
||||
}
|
||||
|
||||
traceTenurePromotionsLog(trc);
|
||||
AllocationsLog::trace(&allocationsLog, trc);
|
||||
TenurePromotionsLog::trace(&tenurePromotionsLog, trc);
|
||||
|
||||
/* Trace the weak map from JSScript instances to Debugger.Script objects. */
|
||||
scripts.trace(trc);
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "js/HashTable.h"
|
||||
#include "vm/GlobalObject.h"
|
||||
#include "vm/SavedStacks.h"
|
||||
#include "js/TraceableFifo.h"
|
||||
|
||||
enum JSTrapStatus {
|
||||
JSTRAP_ERROR,
|
||||
@ -283,63 +284,72 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
|
||||
void logTenurePromotion(JSRuntime* rt, JSObject& obj, double when);
|
||||
static JSObject* getObjectAllocationSite(JSObject& obj);
|
||||
|
||||
private:
|
||||
HeapPtrNativeObject object; /* The Debugger object. Strong reference. */
|
||||
WeakGlobalObjectSet debuggees; /* Debuggee globals. Cross-compartment weak references. */
|
||||
JS::ZoneSet debuggeeZones; /* Set of zones that we have debuggees in. */
|
||||
js::HeapPtrObject uncaughtExceptionHook; /* Strong reference. */
|
||||
bool enabled;
|
||||
JSCList breakpoints; /* Circular list of all js::Breakpoints in this debugger */
|
||||
|
||||
// The set of GC numbers for which one or more of this Debugger's observed
|
||||
// debuggees participated in.
|
||||
js::HashSet<uint64_t> observedGCs;
|
||||
|
||||
struct TenurePromotionsEntry : public mozilla::LinkedListElement<TenurePromotionsEntry>
|
||||
struct TenurePromotionsLogEntry : public JS::StaticTraceable
|
||||
{
|
||||
TenurePromotionsEntry(JSRuntime* rt, JSObject& obj, double when);
|
||||
TenurePromotionsLogEntry(JSRuntime* rt, JSObject& obj, double when);
|
||||
|
||||
const char* className;
|
||||
double when;
|
||||
RelocatablePtrObject frame;
|
||||
size_t size;
|
||||
|
||||
static void trace(TenurePromotionsLogEntry* e, JSTracer* trc) {
|
||||
if (e->frame)
|
||||
TraceEdge(trc, &e->frame, "Debugger::TenurePromotionsLogEntry::frame");
|
||||
}
|
||||
};
|
||||
|
||||
using TenurePromotionsLog = mozilla::LinkedList<TenurePromotionsEntry>;
|
||||
TenurePromotionsLog tenurePromotionsLog;
|
||||
bool trackingTenurePromotions;
|
||||
size_t tenurePromotionsLogLength;
|
||||
size_t maxTenurePromotionsLogLength;
|
||||
bool tenurePromotionsLogOverflowed;
|
||||
|
||||
struct AllocationSite : public mozilla::LinkedListElement<AllocationSite>
|
||||
struct AllocationsLogEntry : public JS::StaticTraceable
|
||||
{
|
||||
AllocationSite(HandleObject frame, double when)
|
||||
AllocationsLogEntry(HandleObject frame, double when, const char* className,
|
||||
HandleAtom ctorName, size_t size)
|
||||
: frame(frame),
|
||||
when(when),
|
||||
className(nullptr),
|
||||
ctorName(nullptr),
|
||||
size(0)
|
||||
className(className),
|
||||
ctorName(ctorName),
|
||||
size(size)
|
||||
{
|
||||
MOZ_ASSERT_IF(frame, UncheckedUnwrap(frame)->is<SavedFrame>());
|
||||
};
|
||||
|
||||
static AllocationSite* create(JSContext* cx, HandleObject frame, double when,
|
||||
HandleObject obj);
|
||||
|
||||
RelocatablePtrObject frame;
|
||||
double when;
|
||||
const char* className;
|
||||
RelocatablePtrAtom ctorName;
|
||||
size_t size;
|
||||
};
|
||||
typedef mozilla::LinkedList<AllocationSite> AllocationSiteList;
|
||||
|
||||
static void trace(AllocationsLogEntry* e, JSTracer* trc) {
|
||||
if (e->frame)
|
||||
TraceEdge(trc, &e->frame, "Debugger::AllocationsLogEntry::frame");
|
||||
if (e->ctorName)
|
||||
TraceEdge(trc, &e->ctorName, "Debugger::AllocationsLogEntry::ctorName");
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
HeapPtrNativeObject object; /* The Debugger object. Strong reference. */
|
||||
WeakGlobalObjectSet debuggees; /* Debuggee globals. Cross-compartment weak references. */
|
||||
JS::ZoneSet debuggeeZones; /* Set of zones that we have debuggees in. */
|
||||
js::HeapPtrObject uncaughtExceptionHook; /* Strong reference. */
|
||||
bool enabled;
|
||||
bool allowUnobservedAsmJS;
|
||||
JSCList breakpoints; /* Circular list of all js::Breakpoints in this debugger */
|
||||
|
||||
// The set of GC numbers for which one or more of this Debugger's observed
|
||||
// debuggees participated in.
|
||||
js::HashSet<uint64_t> observedGCs;
|
||||
|
||||
using TenurePromotionsLog = js::TraceableFifo<TenurePromotionsLogEntry>;
|
||||
TenurePromotionsLog tenurePromotionsLog;
|
||||
bool trackingTenurePromotions;
|
||||
size_t maxTenurePromotionsLogLength;
|
||||
bool tenurePromotionsLogOverflowed;
|
||||
|
||||
using AllocationsLog = js::TraceableFifo<AllocationsLogEntry>;
|
||||
|
||||
AllocationsLog allocationsLog;
|
||||
bool trackingAllocationSites;
|
||||
double allocationSamplingProbability;
|
||||
AllocationSiteList allocationsLog;
|
||||
size_t allocationsLogLength;
|
||||
size_t maxAllocationsLogLength;
|
||||
bool allocationsLogOverflowed;
|
||||
|
||||
@ -347,8 +357,6 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
|
||||
|
||||
bool appendAllocationSite(JSContext* cx, HandleObject obj, HandleSavedFrame frame,
|
||||
double when);
|
||||
void emptyAllocationsLog();
|
||||
void emptyTenurePromotionsLog();
|
||||
|
||||
/*
|
||||
* Recompute the set of debuggee zones based on the set of debuggee globals.
|
||||
@ -503,7 +511,6 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
|
||||
void trace(JSTracer* trc);
|
||||
static void finalize(FreeOp* fop, JSObject* obj);
|
||||
void markCrossCompartmentEdges(JSTracer* tracer);
|
||||
void traceTenurePromotionsLog(JSTracer* trc);
|
||||
|
||||
static const Class jsclass;
|
||||
|
||||
@ -920,6 +927,20 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
|
||||
Debugger & operator=(const Debugger&) = delete;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct DefaultTracer<Debugger::TenurePromotionsLogEntry> {
|
||||
static void trace(JSTracer* trc, Debugger::TenurePromotionsLogEntry* e, const char*) {
|
||||
Debugger::TenurePromotionsLogEntry::trace(e, trc);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct DefaultTracer<Debugger::AllocationsLogEntry> {
|
||||
static void trace(JSTracer* trc, Debugger::AllocationsLogEntry* e, const char*) {
|
||||
Debugger::AllocationsLogEntry::trace(e, trc);
|
||||
}
|
||||
};
|
||||
|
||||
class BreakpointSite {
|
||||
friend class Breakpoint;
|
||||
friend struct ::JSCompartment;
|
||||
|
@ -185,7 +185,7 @@ DebuggerMemory::drainAllocationsLog(JSContext* cx, unsigned argc, Value* vp)
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t length = dbg->allocationsLogLength;
|
||||
size_t length = dbg->allocationsLog.length();
|
||||
|
||||
RootedArrayObject result(cx, NewDenseFullyAllocatedArray(cx, length));
|
||||
if (!result)
|
||||
@ -197,21 +197,21 @@ DebuggerMemory::drainAllocationsLog(JSContext* cx, unsigned argc, Value* vp)
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
// Don't pop the AllocationSite yet. The queue's links are followed by
|
||||
// the GC to find the AllocationSite, but are not barriered, so we must
|
||||
// edit them with great care. Use the queue entry in place, and then
|
||||
// pop and delete together.
|
||||
Debugger::AllocationSite* allocSite = dbg->allocationsLog.getFirst();
|
||||
// Don't pop the AllocationsLogEntry yet. The queue's links are followed
|
||||
// by the GC to find the AllocationsLogEntry, but are not barriered, so
|
||||
// we must edit them with great care. Use the queue entry in place, and
|
||||
// then pop and delete together.
|
||||
Debugger::AllocationsLogEntry& entry = dbg->allocationsLog.front();
|
||||
|
||||
RootedValue frame(cx, ObjectOrNullValue(allocSite->frame));
|
||||
RootedValue frame(cx, ObjectOrNullValue(entry.frame));
|
||||
if (!DefineProperty(cx, obj, cx->names().frame, frame))
|
||||
return false;
|
||||
|
||||
RootedValue timestampValue(cx, NumberValue(allocSite->when));
|
||||
RootedValue timestampValue(cx, NumberValue(entry.when));
|
||||
if (!DefineProperty(cx, obj, cx->names().timestamp, timestampValue))
|
||||
return false;
|
||||
|
||||
RootedString className(cx, Atomize(cx, allocSite->className, strlen(allocSite->className)));
|
||||
RootedString className(cx, Atomize(cx, entry.className, strlen(entry.className)));
|
||||
if (!className)
|
||||
return false;
|
||||
RootedValue classNameValue(cx, StringValue(className));
|
||||
@ -219,26 +219,27 @@ DebuggerMemory::drainAllocationsLog(JSContext* cx, unsigned argc, Value* vp)
|
||||
return false;
|
||||
|
||||
RootedValue ctorName(cx, NullValue());
|
||||
if (allocSite->ctorName)
|
||||
ctorName.setString(allocSite->ctorName);
|
||||
if (entry.ctorName)
|
||||
ctorName.setString(entry.ctorName);
|
||||
if (!DefineProperty(cx, obj, cx->names().constructor, ctorName))
|
||||
return false;
|
||||
|
||||
RootedValue size(cx, NumberValue(allocSite->size));
|
||||
RootedValue size(cx, NumberValue(entry.size));
|
||||
if (!DefineProperty(cx, obj, cx->names().size, size))
|
||||
return false;
|
||||
|
||||
result->setDenseElement(i, ObjectValue(*obj));
|
||||
|
||||
// Pop the front queue entry, and delete it immediately, so that
|
||||
// the GC sees the AllocationSite's RelocatablePtr barriers run
|
||||
// atomically with the change to the graph (the queue link).
|
||||
MOZ_ALWAYS_TRUE(dbg->allocationsLog.popFirst() == allocSite);
|
||||
js_delete(allocSite);
|
||||
// Pop the front queue entry, and delete it immediately, so that the GC
|
||||
// sees the AllocationsLogEntry's RelocatablePtr barriers run atomically
|
||||
// with the change to the graph (the queeue link).
|
||||
if (!dbg->allocationsLog.popFront()) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
dbg->allocationsLogOverflowed = false;
|
||||
dbg->allocationsLogLength = 0;
|
||||
args.rval().setObject(*result);
|
||||
return true;
|
||||
}
|
||||
@ -272,9 +273,11 @@ DebuggerMemory::setMaxAllocationsLogLength(JSContext* cx, unsigned argc, Value*
|
||||
Debugger* dbg = memory->getDebugger();
|
||||
dbg->maxAllocationsLogLength = max;
|
||||
|
||||
while (dbg->allocationsLogLength > dbg->maxAllocationsLogLength) {
|
||||
js_delete(dbg->allocationsLog.getFirst());
|
||||
dbg->allocationsLogLength--;
|
||||
while (dbg->allocationsLog.length() > dbg->maxAllocationsLogLength) {
|
||||
if (!dbg->allocationsLog.popFront()) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
args.rval().setUndefined();
|
||||
@ -352,7 +355,7 @@ DebuggerMemory::drainTenurePromotionsLog(JSContext* cx, unsigned argc, Value* vp
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t length = dbg->tenurePromotionsLogLength;
|
||||
size_t length = dbg->tenurePromotionsLog.length();
|
||||
|
||||
RootedArrayObject result(cx, NewDenseFullyAllocatedArray(cx, length));
|
||||
if (!result)
|
||||
@ -368,41 +371,42 @@ DebuggerMemory::drainTenurePromotionsLog(JSContext* cx, unsigned argc, Value* vp
|
||||
// followed by the GC to find the TenurePromotionsEntry, but are not
|
||||
// barriered, so we must edit them with great care. Use the queue entry
|
||||
// in place, and then pop and delete together.
|
||||
auto* entry = dbg->tenurePromotionsLog.getFirst();
|
||||
auto& entry = dbg->tenurePromotionsLog.front();
|
||||
|
||||
RootedValue frame(cx, ObjectOrNullValue(entry->frame));
|
||||
RootedValue frame(cx, ObjectOrNullValue(entry.frame));
|
||||
if (!cx->compartment()->wrap(cx, &frame) ||
|
||||
!DefineProperty(cx, obj, cx->names().frame, frame))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedValue timestampValue(cx, NumberValue(entry->when));
|
||||
RootedValue timestampValue(cx, NumberValue(entry.when));
|
||||
if (!DefineProperty(cx, obj, cx->names().timestamp, timestampValue))
|
||||
return false;
|
||||
|
||||
RootedString className(cx, Atomize(cx, entry->className, strlen(entry->className)));
|
||||
RootedString className(cx, Atomize(cx, entry.className, strlen(entry.className)));
|
||||
if (!className)
|
||||
return false;
|
||||
RootedValue classNameValue(cx, StringValue(className));
|
||||
if (!DefineProperty(cx, obj, cx->names().class_, classNameValue))
|
||||
return false;
|
||||
|
||||
RootedValue sizeValue(cx, NumberValue(entry->size));
|
||||
RootedValue sizeValue(cx, NumberValue(entry.size));
|
||||
if (!DefineProperty(cx, obj, cx->names().size, sizeValue))
|
||||
return false;
|
||||
|
||||
result->setDenseElement(i, ObjectValue(*obj));
|
||||
|
||||
// Pop the front queue entry, and delete it immediately, so that
|
||||
// the GC sees the TenurePromotionsEntry's RelocatablePtr barriers run
|
||||
// Pop the front queue entry, and delete it immediately, so that the GC
|
||||
// sees the TenurePromotionsEntry's RelocatablePtr barriers run
|
||||
// atomically with the change to the graph (the queue link).
|
||||
MOZ_ALWAYS_TRUE(dbg->tenurePromotionsLog.popFirst() == entry);
|
||||
js_delete(entry);
|
||||
if (!dbg->tenurePromotionsLog.popFront()) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
dbg->tenurePromotionsLogOverflowed = false;
|
||||
dbg->tenurePromotionsLogLength = 0;
|
||||
args.rval().setObject(*result);
|
||||
return true;
|
||||
}
|
||||
@ -436,9 +440,11 @@ DebuggerMemory::setMaxTenurePromotionsLogLength(JSContext* cx, unsigned argc, Va
|
||||
Debugger* dbg = memory->getDebugger();
|
||||
dbg->maxTenurePromotionsLogLength = max;
|
||||
|
||||
while (dbg->tenurePromotionsLogLength > dbg->maxAllocationsLogLength) {
|
||||
js_delete(dbg->tenurePromotionsLog.getFirst());
|
||||
dbg->tenurePromotionsLogLength--;
|
||||
while (dbg->tenurePromotionsLog.length() > dbg->maxAllocationsLogLength) {
|
||||
if (!dbg->tenurePromotionsLog.popFront()) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
args.rval().setUndefined();
|
||||
|
Loading…
Reference in New Issue
Block a user