Move the allocation of the LIR buffer and the FragmentInfo data structure creation (which includes typemap and interned global calculation) into loopedge.

This commit is contained in:
Andreas Gal 2008-07-16 21:41:03 -07:00
parent 782f2b87ec
commit def4afc614
2 changed files with 71 additions and 85 deletions

View File

@ -428,6 +428,7 @@ TraceRecorder::TraceRecorder(JSContext* cx, Fragmento* fragmento, Fragment* _fra
this->cx = cx;
this->globalObj = JS_GetGlobalForObject(cx, cx->fp->scopeChain);
this->fragment = _fragment;
this->lirbuf = _fragment->lirbuf;
entryFrame = cx->fp;
entryRegs.pc = entryFrame->regs->pc;
entryRegs.sp = entryFrame->regs->sp;
@ -438,13 +439,8 @@ TraceRecorder::TraceRecorder(JSContext* cx, Fragmento* fragmento, Fragment* _fra
js_PCToLineNumber(cx, cx->fp->script, entryRegs.pc));
#endif
fragment->calldepth = 0;
lirbuf = new (&gc) LirBuffer(fragmento, builtins);
fragment->lirbuf = lirbuf;
lir = lir_buf_writer = new (&gc) LirBufWriter(lirbuf);
#ifdef DEBUG
lirbuf->names = new (&gc) LirNameMap(&gc, builtins, fragmento->labels);
lir = verbose_filter = new (&gc) VerboseWriter(&gc, lir, lirbuf->names);
#endif
lir = cse_filter = new (&gc) CseFilter(lir, &gc);
@ -454,55 +450,18 @@ TraceRecorder::TraceRecorder(JSContext* cx, Fragmento* fragmento, Fragment* _fra
lir = func_filter = new (&gc) FuncFilter(lir, *this);
lir->ins0(LIR_trace);
if (fragment->vmprivate == NULL) {
/* calculate the number of globals we want to intern */
int internableGlobals = findInternableGlobals(entryFrame, NULL);
if (internableGlobals < 0)
return;
JS_ASSERT(fragment->vmprivate != NULL);
fragmentInfo = (VMFragmentInfo*)fragment->vmprivate;
/* generate the entry map and store it in the trace */
unsigned entryNativeFrameSlots = nativeFrameSlots(entryFrame, entryRegs);
LIns* data = lir_buf_writer->skip(sizeof(*fragmentInfo) +
internableGlobals * sizeof(uint16) +
entryNativeFrameSlots * sizeof(uint8));
fragmentInfo = (VMFragmentInfo*)data->payload();
fragmentInfo->typeMap = (uint8*)(fragmentInfo + 1);
fragmentInfo->gslots = (uint16*)(fragmentInfo->typeMap +
entryNativeFrameSlots * sizeof(uint8));
fragmentInfo->entryNativeFrameSlots = entryNativeFrameSlots;
fragmentInfo->nativeStackBase = (entryNativeFrameSlots -
(entryRegs.sp - entryFrame->spbase)) * sizeof(double);
fragmentInfo->maxNativeFrameSlots = entryNativeFrameSlots;
fragmentInfo->maxCallDepth = 0;
/* setup the list of global properties we want to intern */
findInternableGlobals(entryFrame, fragmentInfo->gslots);
fragmentInfo->ngslots = internableGlobals;
fragmentInfo->globalShape = OBJ_SCOPE(globalObj)->shape;
/* build the entry type map */
uint8* m = fragmentInfo->typeMap;
/* remember the coerced type of each active slot in the type map */
FORALL_SLOTS_IN_PENDING_FRAMES(cx, fragmentInfo->ngslots, fragmentInfo->gslots,
entryFrame, entryFrame,
*m++ = getCoercedType(*vp)
);
} else {
/* recompiling the trace, we already have a fragment info structure */
fragmentInfo = (VMFragmentInfo*)fragment->vmprivate;
}
fragment->vmprivate = fragmentInfo;
fragment->lirbuf->state = lir->insParam(0);
fragment->lirbuf->param1 = lir->insParam(1);
fragment->lirbuf->sp = lir->insLoadi(fragment->lirbuf->state, offsetof(InterpState, sp));
fragment->lirbuf->rp = lir->insLoadi(fragment->lirbuf->state, offsetof(InterpState, rp));
cx_ins = lir->insLoadi(fragment->lirbuf->state, offsetof(InterpState, cx));
lirbuf->state = lir->insParam(0);
lirbuf->param1 = lir->insParam(1);
lirbuf->sp = lir->insLoadi(lirbuf->state, offsetof(InterpState, sp));
lirbuf->rp = lir->insLoadi(lirbuf->state, offsetof(InterpState, rp));
cx_ins = lir->insLoadi(lirbuf->state, offsetof(InterpState, cx));
#ifdef DEBUG
lirbuf->names->addName(fragment->lirbuf->state, "state");
lirbuf->names->addName(fragment->lirbuf->sp, "sp");
lirbuf->names->addName(fragment->lirbuf->rp, "rp");
lirbuf->names->addName(lirbuf->state, "state");
lirbuf->names->addName(lirbuf->sp, "sp");
lirbuf->names->addName(lirbuf->rp, "rp");
lirbuf->names->addName(cx_ins, "cx");
#endif
@ -519,7 +478,6 @@ TraceRecorder::TraceRecorder(JSContext* cx, Fragmento* fragmento, Fragment* _fra
TraceRecorder::~TraceRecorder()
{
#ifdef DEBUG
delete lirbuf->names;
delete verbose_filter;
#endif
delete cse_filter;
@ -581,9 +539,10 @@ TraceRecorder::isGlobal(jsval* p) const
size_t(p - globalObj->dslots) < size_t(globalObj->dslots[-1] - JS_INITIAL_NSLOTS);
}
int
TraceRecorder::findInternableGlobals(JSStackFrame* fp, uint16* slots) const
static int
findInternableGlobals(JSContext* cx, JSStackFrame* fp, uint16* slots)
{
JSObject* globalObj = JS_GetGlobalForObject(cx, fp->scopeChain);
unsigned count = 0;
unsigned n;
JSAtom** atoms = fp->script->atomMap.vector;
@ -619,30 +578,10 @@ TraceRecorder::findInternableGlobals(JSStackFrame* fp, uint16* slots) const
/* Calculate the total number of native frame slots we need from this frame
all the way back to the entry frame, including the current stack usage. */
unsigned
TraceRecorder::nativeFrameSlots(JSStackFrame* fp, JSFrameRegs& regs) const
static unsigned nativeFrameSlots(unsigned ngslots, JSStackFrame* entryFrame,
JSStackFrame* fp, JSFrameRegs& regs)
{
unsigned slots = 0;
unsigned n;
JSAtom** atoms = entryFrame->script->atomMap.vector;
unsigned natoms = entryFrame->script->atomMap.length;
for (n = 0; n < natoms; ++n) {
JSAtom* atom = atoms[n];
if (!ATOM_IS_STRING(atom))
continue;
jsid id = ATOM_TO_JSID(atom);
JSObject* obj2;
JSProperty* prop;
if (!js_LookupProperty(cx, globalObj, id, &obj2, &prop))
continue; /* XXX need to signal real error */
if (obj2 != globalObj)
continue;
JS_ASSERT(prop);
JSScopeProperty* sprop = (JSScopeProperty*)prop;
if (SPROP_HAS_STUB_GETTER(sprop) && SPROP_HAS_STUB_SETTER(sprop))
++slots;
JS_UNLOCK_OBJ(cx, obj2);
}
unsigned slots = ngslots;
for (;;) {
slots += 1/*rval*/ + (regs.sp - fp->spbase);
if (fp->callee)
@ -858,10 +797,10 @@ TraceRecorder::import(jsval* p, uint8& t, const char *prefix, int index)
read and promote it to double since all arithmetic operations expect
to see doubles on entry. The first op to use this slot will emit a
f2i cast which will cancel out the i2f we insert here. */
ins = lir->ins1(LIR_i2f, lir->insLoadi(fragment->lirbuf->sp, offset));
ins = lir->ins1(LIR_i2f, lir->insLoadi(lirbuf->sp, offset));
} else {
JS_ASSERT(isNumber(*p) == (TYPEMAP_GET_TYPE(t) == JSVAL_DOUBLE));
ins = lir->insLoad(t == JSVAL_DOUBLE ? LIR_ldq : LIR_ld, fragment->lirbuf->sp, offset);
ins = lir->insLoad(t == JSVAL_DOUBLE ? LIR_ldq : LIR_ld, lirbuf->sp, offset);
}
tracker.set(p, ins);
#ifdef DEBUG
@ -883,7 +822,7 @@ TraceRecorder::set(jsval* p, LIns* i)
{
tracker.set(p, i);
if (onFrame(p))
lir->insStorei(i, fragment->lirbuf->sp, -fragmentInfo->nativeStackBase + nativeFrameOffset(p) + 8);
lir->insStorei(i, lirbuf->sp, -fragmentInfo->nativeStackBase + nativeFrameOffset(p) + 8);
}
LIns*
@ -896,7 +835,7 @@ SideExit*
TraceRecorder::snapshot()
{
/* generate the entry map and stash it in the trace */
unsigned slots = nativeFrameSlots(cx->fp, *cx->fp->regs);
unsigned slots = nativeFrameSlots(fragmentInfo->ngslots, entryFrame, cx->fp, *cx->fp->regs);
trackNativeFrameUse(slots);
/* reserve space for the type map, ExitFilter will write it out for us */
LIns* data = lir_buf_writer->skip(slots * sizeof(uint8));
@ -1149,6 +1088,44 @@ js_LoopEdge(JSContext* cx)
int hits = ++f->hits();
if (!f->isBlacklisted() && hits >= HOTLOOP1) {
if (hits == HOTLOOP1 || hits == HOTLOOP2 || hits == HOTLOOP3) {
f->calldepth = 0;
/* allocate space to store the LIR for this tree */
if (!f->lirbuf) {
f->lirbuf = new (&gc) LirBuffer(tm->fragmento, builtins);
#ifdef DEBUG
f->lirbuf->names = new (&gc) LirNameMap(&gc, builtins, tm->fragmento->labels);
#endif
}
/* create the tree anchor structure */
if (!f->vmprivate) {
/* setup the VM-private FragmentInfo structure for this fragment */
VMFragmentInfo* fi = new VMFragmentInfo(); // TODO: deallocate when fragment dies
f->vmprivate = fi;
/* create the list of global properties we want to intern */
int internableGlobals = findInternableGlobals(cx, cx->fp, NULL);
if (internableGlobals < 0)
return false;
fi->gslots = (uint16*)malloc(sizeof(uint16) * internableGlobals);
if ((fi->ngslots = findInternableGlobals(cx, cx->fp, fi->gslots)) < 0)
return false;
fi->globalShape = OBJ_SCOPE(JS_GetGlobalForObject(cx,
cx->fp->scopeChain))->shape;
/* determine the native frame layout at the entry point */
unsigned entryNativeFrameSlots = nativeFrameSlots(fi->ngslots,
cx->fp, cx->fp, *cx->fp->regs);
fi->entryNativeFrameSlots = entryNativeFrameSlots;
fi->nativeStackBase = (entryNativeFrameSlots -
(cx->fp->regs->sp - cx->fp->spbase)) * sizeof(double);
fi->maxNativeFrameSlots = entryNativeFrameSlots;
fi->maxCallDepth = 0;
/* build the entry type map */
fi->typeMap = (uint8*)malloc(fi->entryNativeFrameSlots * sizeof(uint8));
uint8* m = fi->typeMap;
/* remember the coerced type of each active slot in the type map */
FORALL_SLOTS_IN_PENDING_FRAMES(cx, fi->ngslots, fi->gslots, cx->fp, cx->fp,
*m++ = getCoercedType(*vp)
);
}
tm->recorder = new (&gc) TraceRecorder(cx, tm->fragmento, f);
/* start recording if no exception during construction */

View File

@ -88,7 +88,18 @@ public:
void clear();
};
struct VMFragmentInfo {
class VMFragmentInfo {
public:
VMFragmentInfo() {
typeMap = NULL;
gslots = NULL;
}
virtual ~VMFragmentInfo() {
if (typeMap) free(typeMap);
if (gslots) free(gslots);
}
unsigned entryNativeFrameSlots;
unsigned maxNativeFrameSlots;
size_t nativeStackBase;
@ -136,8 +147,6 @@ class TraceRecorder {
JSStackFrame* findFrame(jsval* p) const;
bool onFrame(jsval* p) const;
bool isGlobal(jsval* p) const;
int findInternableGlobals(JSStackFrame* fp, uint16* slots) const;
unsigned nativeFrameSlots(JSStackFrame* fp, JSFrameRegs& regs) const;
size_t nativeFrameOffset(jsval* p) const;
void import(jsval* p, uint8& t, const char *prefix, int index);
void trackNativeFrameUse(unsigned slots);