mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-11 08:13:35 +00:00
Bug 672112 - Fix PICTable bug in tracer (r=dmandelin)
This commit is contained in:
parent
692bbd7e4c
commit
3eec196c84
@ -1662,6 +1662,7 @@ TreeFragment::initialize(JSContext* cx, SlotList *globalSlots, bool speculate)
|
|||||||
this->shapes.clear();
|
this->shapes.clear();
|
||||||
this->unstableExits = NULL;
|
this->unstableExits = NULL;
|
||||||
this->sideExits.clear();
|
this->sideExits.clear();
|
||||||
|
this->picTables.clear();
|
||||||
|
|
||||||
/* Determine the native frame layout at the entry point. */
|
/* Determine the native frame layout at the entry point. */
|
||||||
this->nativeStackBase = (nStackTypes - (cx->regs().sp - cx->fp()->base())) *
|
this->nativeStackBase = (nStackTypes - (cx->regs().sp - cx->fp()->base())) *
|
||||||
@ -2890,23 +2891,61 @@ HasUnreachableGCThings(JSContext *cx, TreeFragment *f)
|
|||||||
*/
|
*/
|
||||||
if (IsAboutToBeFinalized(cx, f->globalObj))
|
if (IsAboutToBeFinalized(cx, f->globalObj))
|
||||||
return true;
|
return true;
|
||||||
Value* vp = f->gcthings.data();
|
Value* vs = f->gcthings.data();
|
||||||
for (unsigned len = f->gcthings.length(); len; --len) {
|
for (unsigned i = 0; i < f->gcthings.length(); ++i) {
|
||||||
Value &v = *vp++;
|
Value &v = vs[i];
|
||||||
JS_ASSERT(v.isMarkable());
|
JS_ASSERT(v.isMarkable());
|
||||||
if (IsAboutToBeFinalized(cx, v.toGCThing()))
|
if (IsAboutToBeFinalized(cx, v.toGCThing()))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const Shape** shapep = f->shapes.data();
|
const Shape** shapes = f->shapes.data();
|
||||||
for (unsigned len = f->shapes.length(); len; --len) {
|
for (unsigned i = 0; i < f->shapes.length(); ++i) {
|
||||||
const Shape* shape = *shapep++;
|
if (IsAboutToBeFinalized(cx, shapes[i]))
|
||||||
if (IsAboutToBeFinalized(cx, shape))
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const size_t PIC_TABLE_ENTRY_COUNT = 32;
|
||||||
|
|
||||||
|
struct PICTableEntry
|
||||||
|
{
|
||||||
|
jsid id;
|
||||||
|
uint32 shape;
|
||||||
|
uint32 slot;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PICTable
|
||||||
|
{
|
||||||
|
PICTable() : entryCount(0) {}
|
||||||
|
|
||||||
|
PICTableEntry entries[PIC_TABLE_ENTRY_COUNT];
|
||||||
|
uint32 entryCount;
|
||||||
|
|
||||||
|
bool scan(uint32 shape, jsid id, uint32 *slotOut) {
|
||||||
|
for (size_t i = 0; i < entryCount; ++i) {
|
||||||
|
PICTableEntry &entry = entries[i];
|
||||||
|
if (entry.shape == shape && entry.id == id) {
|
||||||
|
*slotOut = entry.slot;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update(uint32 shape, jsid id, uint32 slot) {
|
||||||
|
if (entryCount >= PIC_TABLE_ENTRY_COUNT)
|
||||||
|
return;
|
||||||
|
PICTableEntry &newEntry = entries[entryCount++];
|
||||||
|
newEntry.shape = shape;
|
||||||
|
newEntry.id = id;
|
||||||
|
newEntry.slot = slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() { entryCount = 0; }
|
||||||
|
};
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
ContainsUnrechableGCThingImpl(JSContext *cx, TreeFragment *f)
|
ContainsUnrechableGCThingImpl(JSContext *cx, TreeFragment *f)
|
||||||
{
|
{
|
||||||
@ -2975,7 +3014,7 @@ void
|
|||||||
TraceMonitor::sweep(JSContext *cx)
|
TraceMonitor::sweep(JSContext *cx)
|
||||||
{
|
{
|
||||||
JS_ASSERT(!ontrace());
|
JS_ASSERT(!ontrace());
|
||||||
debug_only_print0(LC_TMTracer, "Purging fragments with dead things");
|
debug_only_print0(LC_TMTracer, "Purging fragments with dead things\n");
|
||||||
|
|
||||||
bool shouldAbortRecording = false;
|
bool shouldAbortRecording = false;
|
||||||
TreeFragment *recorderTree = NULL;
|
TreeFragment *recorderTree = NULL;
|
||||||
@ -2983,7 +3022,7 @@ TraceMonitor::sweep(JSContext *cx)
|
|||||||
recorderTree = recorder->getTree();
|
recorderTree = recorder->getTree();
|
||||||
shouldAbortRecording = HasUnreachableGCThings(cx, recorderTree);
|
shouldAbortRecording = HasUnreachableGCThings(cx, recorderTree);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < FRAGMENT_TABLE_SIZE; ++i) {
|
for (size_t i = 0; i < FRAGMENT_TABLE_SIZE; ++i) {
|
||||||
TreeFragment** fragp = &vmfragments[i];
|
TreeFragment** fragp = &vmfragments[i];
|
||||||
while (TreeFragment* frag = *fragp) {
|
while (TreeFragment* frag = *fragp) {
|
||||||
@ -2997,9 +3036,9 @@ TraceMonitor::sweep(JSContext *cx)
|
|||||||
fragp = &frag->next;
|
fragp = &frag->next;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug_only_printf(LC_TMTracer,
|
debug_only_printf(LC_TMTracer,
|
||||||
"TreeFragment peer %p has dead gc thing."
|
"TreeFragment peer %p has dead gc thing. "
|
||||||
"Disconnecting tree %p with ip %p\n",
|
"Disconnecting tree %p with ip %p\n",
|
||||||
(void *) peer, (void *) frag, frag->ip);
|
(void *) peer, (void *) frag, frag->ip);
|
||||||
JS_ASSERT(frag->root == frag);
|
JS_ASSERT(frag->root == frag);
|
||||||
@ -3014,17 +3053,21 @@ TraceMonitor::sweep(JSContext *cx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
/* These tables contain GC things, so they must be cleared on GC. */
|
||||||
for (size_t i = 0; i < FRAGMENT_TABLE_SIZE; ++i) {
|
for (size_t i = 0; i < FRAGMENT_TABLE_SIZE; ++i) {
|
||||||
for (TreeFragment* frag = vmfragments[i]; frag; frag = frag->next) {
|
for (TreeFragment* frag = vmfragments[i]; frag; frag = frag->next) {
|
||||||
TreeFragment* peer = frag;
|
TreeFragment* peer = frag;
|
||||||
do {
|
do {
|
||||||
JS_ASSERT(!peer->visiting);
|
JS_ASSERT(!peer->visiting);
|
||||||
|
|
||||||
|
PICTable** tables = peer->picTables.data();
|
||||||
|
for (unsigned j = 0; j < peer->picTables.length(); ++j)
|
||||||
|
tables[j]->clear();
|
||||||
|
|
||||||
peer = peer->peer;
|
peer = peer->peer;
|
||||||
} while (peer);
|
} while (peer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (shouldAbortRecording)
|
if (shouldAbortRecording)
|
||||||
recorder->finishAbort("dead GC things");
|
recorder->finishAbort("dead GC things");
|
||||||
@ -12562,43 +12605,6 @@ RootedStringToId(JSContext* cx, JSString** namep, jsid* idp)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const size_t PIC_TABLE_ENTRY_COUNT = 32;
|
|
||||||
|
|
||||||
struct PICTableEntry
|
|
||||||
{
|
|
||||||
jsid id;
|
|
||||||
uint32 shape;
|
|
||||||
uint32 slot;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PICTable
|
|
||||||
{
|
|
||||||
PICTable() : entryCount(0) {}
|
|
||||||
|
|
||||||
PICTableEntry entries[PIC_TABLE_ENTRY_COUNT];
|
|
||||||
uint32 entryCount;
|
|
||||||
|
|
||||||
bool scan(uint32 shape, jsid id, uint32 *slotOut) {
|
|
||||||
for (size_t i = 0; i < entryCount; ++i) {
|
|
||||||
PICTableEntry &entry = entries[i];
|
|
||||||
if (entry.shape == shape && entry.id == id) {
|
|
||||||
*slotOut = entry.slot;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void update(uint32 shape, jsid id, uint32 slot) {
|
|
||||||
if (entryCount >= PIC_TABLE_ENTRY_COUNT)
|
|
||||||
return;
|
|
||||||
PICTableEntry &newEntry = entries[entryCount++];
|
|
||||||
newEntry.shape = shape;
|
|
||||||
newEntry.id = id;
|
|
||||||
newEntry.slot = slot;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static JSBool FASTCALL
|
static JSBool FASTCALL
|
||||||
GetPropertyByName(JSContext* cx, JSObject* obj, JSString** namep, Value* vp, PICTable *picTable)
|
GetPropertyByName(JSContext* cx, JSObject* obj, JSString** namep, Value* vp, PICTable *picTable)
|
||||||
{
|
{
|
||||||
@ -12691,6 +12697,7 @@ TraceRecorder::getPropertyByName(LIns* obj_ins, Value* idvalp, Value* outp)
|
|||||||
LIns* vp_ins = w.name(w.allocp(sizeof(Value)), "vp");
|
LIns* vp_ins = w.name(w.allocp(sizeof(Value)), "vp");
|
||||||
LIns* idvalp_ins = w.name(addr(idvalp), "idvalp");
|
LIns* idvalp_ins = w.name(addr(idvalp), "idvalp");
|
||||||
PICTable *picTable = new (traceAlloc()) PICTable();
|
PICTable *picTable = new (traceAlloc()) PICTable();
|
||||||
|
tree->picTables.add(picTable);
|
||||||
LIns* pic_ins = w.nameImmpNonGC(picTable);
|
LIns* pic_ins = w.nameImmpNonGC(picTable);
|
||||||
LIns* args[] = {pic_ins, vp_ins, idvalp_ins, obj_ins, cx_ins};
|
LIns* args[] = {pic_ins, vp_ins, idvalp_ins, obj_ins, cx_ins};
|
||||||
LIns* ok_ins = w.call(&GetPropertyByName_ci, args);
|
LIns* ok_ins = w.call(&GetPropertyByName_ci, args);
|
||||||
|
@ -539,6 +539,8 @@ struct LinkableFragment : public VMFragment
|
|||||||
SlotList* globalSlots;
|
SlotList* globalSlots;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct PICTable;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* argc is cx->fp->argc at the trace loop header, i.e., the number of arguments
|
* argc is cx->fp->argc at the trace loop header, i.e., the number of arguments
|
||||||
* pushed for the innermost JS frame. This is required as part of the fragment
|
* pushed for the innermost JS frame. This is required as part of the fragment
|
||||||
@ -564,6 +566,7 @@ struct TreeFragment : public LinkableFragment
|
|||||||
sideExits(alloc),
|
sideExits(alloc),
|
||||||
gcthings(alloc),
|
gcthings(alloc),
|
||||||
shapes(alloc),
|
shapes(alloc),
|
||||||
|
picTables(alloc),
|
||||||
visiting(false)
|
visiting(false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
@ -590,6 +593,7 @@ struct TreeFragment : public LinkableFragment
|
|||||||
/* All embedded GC things are registered here so the GC can scan them. */
|
/* All embedded GC things are registered here so the GC can scan them. */
|
||||||
Queue<Value> gcthings;
|
Queue<Value> gcthings;
|
||||||
Queue<const js::Shape*> shapes;
|
Queue<const js::Shape*> shapes;
|
||||||
|
Queue<PICTable*> picTables;
|
||||||
unsigned maxNativeStackSlots;
|
unsigned maxNativeStackSlots;
|
||||||
/* Gives the number of times we have entered this trace. */
|
/* Gives the number of times we have entered this trace. */
|
||||||
uintN execs;
|
uintN execs;
|
||||||
|
Loading…
Reference in New Issue
Block a user