Added explicit deallocation (bug 443500, r=gal)

This commit is contained in:
David Anderson 2008-08-11 16:01:21 -07:00
parent 285acf8b9c
commit 1b623f7d25
8 changed files with 112 additions and 22 deletions

View File

@ -1,5 +1,5 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=99: * vim: set ts=4 sw=4 et tw=99:
* *
* ***** BEGIN LICENSE BLOCK ***** * ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
@ -91,7 +91,7 @@ static struct {
#define AUDIT(x) (stat.x++) #define AUDIT(x) (stat.x++)
#else #else
#define AUDIT(x) ((void)0) #define AUDIT(x) ((void)0)
#endif DEBUG #endif
#define INS_CONST(c) addName(lir->insImm(c), #c) #define INS_CONST(c) addName(lir->insImm(c), #c)
@ -99,7 +99,8 @@ using namespace avmplus;
using namespace nanojit; using namespace nanojit;
static GC gc = GC(); static GC gc = GC();
static avmplus::AvmCore* core = new (&gc) avmplus::AvmCore(); static avmplus::AvmCore s_core = avmplus::AvmCore();
static avmplus::AvmCore* core = &s_core;
/* We really need a better way to configure the JIT. Shaver, where is my fancy JIT object? */ /* We really need a better way to configure the JIT. Shaver, where is my fancy JIT object? */
static bool nesting_enabled = getenv("TRACEMONKEY") && strstr(getenv("TRACEMONKEY"), "nesting"); static bool nesting_enabled = getenv("TRACEMONKEY") && strstr(getenv("TRACEMONKEY"), "nesting");
@ -1284,6 +1285,7 @@ TraceRecorder::closeLoop(Fragmento* fragmento)
sprintf(label, "%s:%u", cx->fp->script->filename, sprintf(label, "%s:%u", cx->fp->script->filename,
js_PCToLineNumber(cx, cx->fp->script, cx->fp->regs->pc)); js_PCToLineNumber(cx, cx->fp->script, cx->fp->regs->pc));
fragmento->labels->add(fragment, sizeof(Fragment), 0, label); fragmento->labels->add(fragment, sizeof(Fragment), 0, label);
free(label);
#endif #endif
} }
@ -1364,6 +1366,16 @@ nanojit::Assembler::asm_bailout(LIns *guard, Register state)
/* we adjust ip/sp/rp when exiting from the tree in the recovery code */ /* we adjust ip/sp/rp when exiting from the tree in the recovery code */
} }
void
nanojit::Fragment::onDestroy()
{
if (root == this) {
delete mergeCounts;
delete lirbuf;
}
delete (TreeInfo *)vmprivate;
}
void void
js_DeleteRecorder(JSContext* cx) js_DeleteRecorder(JSContext* cx)
{ {
@ -1495,7 +1507,7 @@ js_RecordTree(JSContext* cx, JSTraceMonitor* tm, Fragment* f)
JS_ASSERT(!f->vmprivate); JS_ASSERT(!f->vmprivate);
/* setup the VM-private treeInfo structure for this fragment */ /* setup the VM-private treeInfo structure for this fragment */
TreeInfo* ti = new TreeInfo(f); // TODO: deallocate when fragment dies TreeInfo* ti = new (&gc) TreeInfo(f); // TODO: deallocate when fragment dies
f->vmprivate = ti; f->vmprivate = ti;
/* we shouldn't have any interned globals for a new tree */ /* we shouldn't have any interned globals for a new tree */
@ -1768,7 +1780,7 @@ js_InitJIT(JSContext* cx)
extern void extern void
js_DestroyJIT(JSContext* cx) js_DestroyJIT(JSContext* cx)
{ {
// TODO: figure out how to properly free fragmento and a potentially pending trace recorder JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
#ifdef DEBUG #ifdef DEBUG
printf("recorder: started(%llu), aborted(%llu), completed(%llu), different header(%llu), " printf("recorder: started(%llu), aborted(%llu), completed(%llu), different header(%llu), "
"trees trashed(%llu), slot promoted(%llu), " "trees trashed(%llu), slot promoted(%llu), "
@ -1779,6 +1791,8 @@ js_DestroyJIT(JSContext* cx)
"global mismatch(%llu)\n", stat.traceTriggered, stat.sideExitIntoInterpreter, "global mismatch(%llu)\n", stat.traceTriggered, stat.sideExitIntoInterpreter,
stat.typeMapMismatchAtEntry, stat.globalShapeMismatchAtEntry); stat.typeMapMismatchAtEntry, stat.globalShapeMismatchAtEntry);
#endif #endif
verbose_only(delete tm->fragmento->labels;)
delete tm->fragmento;
} }
extern void extern void
@ -1792,7 +1806,6 @@ js_FlushJITCache(JSContext* cx)
js_AbortRecording(cx, NULL, "flush cache"); js_AbortRecording(cx, NULL, "flush cache");
Fragmento* fragmento = tm->fragmento; Fragmento* fragmento = tm->fragmento;
if (fragmento) { if (fragmento) {
// TODO: deallocate vmprivate -> TreeInfo for root fragments
fragmento->clearFrags(); fragmento->clearFrags();
#ifdef DEBUG #ifdef DEBUG
JS_ASSERT(fragmento->labels); JS_ASSERT(fragmento->labels);
@ -3884,22 +3897,32 @@ TraceRecorder::record_JSOP_FORLOCAL()
if (stateval == JSVAL_ZERO) if (stateval == JSVAL_ZERO)
goto done; goto done;
LIns* state_ins = lir->ins2(LIR_and, stateval_ins, lir->insImmPtr((void*) ~jsval(3))); LIns* state_ins;
LIns* cursor_ins = lir->insLoadi(state_ins, offsetof(JSNativeEnumerator, cursor)); LIns* cursor_ins;
state_ins = lir->ins2(LIR_and, stateval_ins, lir->insImmPtr((void*) ~jsval(3)));
cursor_ins = lir->insLoadi(state_ins, offsetof(JSNativeEnumerator, cursor));
guard(false, addName(lir->ins_eq0(cursor_ins), "guard(ne->cursor != 0)")); guard(false, addName(lir->ins_eq0(cursor_ins), "guard(ne->cursor != 0)"));
JSNativeEnumerator* ne = (JSNativeEnumerator*) (stateval & ~jsval(3)); JSNativeEnumerator* ne;
ne = (JSNativeEnumerator*) (stateval & ~jsval(3));
if (ne->cursor == 0) if (ne->cursor == 0)
goto done; goto done;
cursor_ins = lir->ins2i(LIR_sub, cursor_ins, 1); cursor_ins = lir->ins2i(LIR_sub, cursor_ins, 1);
lir->insStorei(cursor_ins, state_ins, offsetof(JSNativeEnumerator, cursor)); lir->insStorei(cursor_ins, state_ins, offsetof(JSNativeEnumerator, cursor));
LIns* ids_ins = lir->ins2i(LIR_add, state_ins, offsetof(JSNativeEnumerator, ids)); LIns* ids_ins;
LIns* id_addr_ins = lir->ins2(LIR_add, ids_ins, LIns* id_addr_ins;
ids_ins = lir->ins2i(LIR_add, state_ins, offsetof(JSNativeEnumerator, ids));
id_addr_ins = lir->ins2(LIR_add, ids_ins,
lir->ins2i(LIR_lsh, cursor_ins, (sizeof(jsid) == 4) ? 2 : 3)); lir->ins2i(LIR_lsh, cursor_ins, (sizeof(jsid) == 4) ? 2 : 3));
LIns* id_ins = lir->insLoadi(id_addr_ins, 0); LIns* id_ins;
id_ins = lir->insLoadi(id_addr_ins, 0);
var(GET_SLOTNO(cx->fp->regs->pc), id_ins); var(GET_SLOTNO(cx->fp->regs->pc), id_ins);
// Stack an unboxed true to make JSOP_IFEQ loop. // Stack an unboxed true to make JSOP_IFEQ loop.

View File

@ -169,7 +169,7 @@ public:
bool matches(TypeMap& other); bool matches(TypeMap& other);
}; };
class TreeInfo { class TreeInfo MMGC_SUBCLASS_DECL {
nanojit::Fragment* fragment; nanojit::Fragment* fragment;
public: public:
unsigned entryNativeStackSlots; unsigned entryNativeStackSlots;

View File

@ -1240,7 +1240,12 @@ namespace nanojit
case LIR_loop: case LIR_loop:
{ {
JMP_long_placeholder(); // jump to SOT JMP_long_placeholder(); // jump to SOT
verbose_only( if (_verbose && _outputCache) { _outputCache->removeLast(); outputf(" jmp SOT"); } ); #if defined(NJ_VERBOSE)
if (_verbose && _outputCache) {
delete _outputCache->removeLast();
outputf(" jmp SOT");
}
#endif
loopJumps.add(_nIns); loopJumps.add(_nIns);

View File

@ -71,7 +71,7 @@ namespace nanojit
Fragmento::~Fragmento() Fragmento::~Fragmento()
{ {
debug_only( clearFrags() ); clearFrags();
_frags->clear(); _frags->clear();
while( _allocList.size() > 0 ) while( _allocList.size() > 0 )
{ {
@ -81,6 +81,12 @@ namespace nanojit
#endif #endif
_gcHeap->Free( _allocList.removeLast() ); _gcHeap->Free( _allocList.removeLast() );
} }
delete _frags;
delete _assm;
#if defined(NJ_VERBOSE)
delete enterCounts;
delete mergeCounts;
#endif
NanoAssert(_stats.freePages == _stats.pages ); NanoAssert(_stats.freePages == _stats.pages );
} }
@ -168,6 +174,7 @@ namespace nanojit
while (!_frags->isEmpty()) { while (!_frags->isEmpty()) {
Fragment *f = _frags->removeLast(); Fragment *f = _frags->removeLast();
f->releaseTreeMem(this); f->releaseTreeMem(this);
delete f;
} }
verbose_only( enterCounts->clear();) verbose_only( enterCounts->clear();)
@ -454,6 +461,7 @@ namespace nanojit
Fragment::~Fragment() Fragment::~Fragment()
{ {
onDestroy();
NanoAssert(_pages == 0); NanoAssert(_pages == 0);
} }
@ -627,10 +635,6 @@ namespace nanojit
void Fragment::releaseLirBuffer() void Fragment::releaseLirBuffer()
{ {
if (lirbuf) {
lirbuf->clear();
lirbuf = 0;
}
lastIns = 0; lastIns = 0;
} }
@ -656,6 +660,7 @@ namespace nanojit
{ {
Fragment* next = branch->nextbranch; Fragment* next = branch->nextbranch;
branch->releaseTreeMem(frago); // @todo safer here to recurse in case we support nested trees branch->releaseTreeMem(frago); // @todo safer here to recurse in case we support nested trees
delete branch;
branch = next; branch = next;
} }
} }

View File

@ -184,6 +184,7 @@ namespace nanojit
void releaseTreeMem(Fragmento* frago); void releaseTreeMem(Fragmento* frago);
bool isAnchor() { return anchor == this; } bool isAnchor() { return anchor == this; }
bool isRoot() { return root == this; } bool isRoot() { return root == this; }
void onDestroy();
verbose_only( uint32_t _called; ) verbose_only( uint32_t _called; )
verbose_only( uint32_t _native; ) verbose_only( uint32_t _native; )

View File

@ -114,6 +114,7 @@ namespace nanojit
//buffer_count--; //buffer_count--;
//fprintf(stderr, "~LirBuffer %x start %x\n", (int)this, (int)_start); //fprintf(stderr, "~LirBuffer %x start %x\n", (int)this, (int)_start);
clear(); clear();
delete names;
_frago = 0; _frago = 0;
} }
@ -1315,6 +1316,13 @@ namespace nanojit
List<RetiredEntry*, LIST_GCObjects> retired; List<RetiredEntry*, LIST_GCObjects> retired;
int maxlive; int maxlive;
LiveTable(GC *gc) : live(gc), retired(gc), maxlive(0) {} LiveTable(GC *gc) : live(gc), retired(gc), maxlive(0) {}
~LiveTable()
{
for (size_t i = 0; i < retired.size(); i++) {
delete retired.get(i);
}
}
void add(LInsp i, LInsp use) { void add(LInsp i, LInsp use) {
if (!i->isconst() && !i->isconstq() && !live.containsKey(i)) { if (!i->isconst() && !i->isconstq() && !live.containsKey(i)) {
live.put(i,use); live.put(i,use);
@ -1417,6 +1425,25 @@ namespace nanojit
} }
} }
LabelMap::Entry::~Entry()
{
delete name;
}
LirNameMap::Entry::~Entry()
{
delete name;
}
LirNameMap::~LirNameMap()
{
Entry *e;
while ((e = names.removeLast()) != NULL) {
delete e;
}
}
void LirNameMap::addName(LInsp i, Stringp name) { void LirNameMap::addName(LInsp i, Stringp name) {
if (!names.containsKey(i)) { if (!names.containsKey(i)) {
Entry *e = new (labels->core->gc) Entry(name); Entry *e = new (labels->core->gc) Entry(name);
@ -1787,6 +1814,12 @@ namespace nanojit
root->link(assm); root->link(assm);
if (treeCompile) root->linkBranches(assm); if (treeCompile) root->linkBranches(assm);
} }
#if defined(NJ_VERBOSE)
for (size_t i = 0; i < asmOutput.size(); i++) {
gc->Free(asmOutput.get(i));
}
#endif
} }
#endif /* FEATURE_NANOJIT */ #endif /* FEATURE_NANOJIT */
@ -1796,6 +1829,15 @@ namespace nanojit
: parent(parent), names(core->gc), addrs(core->config.verbose_addrs), end(buf), core(core) : parent(parent), names(core->gc), addrs(core->config.verbose_addrs), end(buf), core(core)
{} {}
LabelMap::~LabelMap()
{
Entry *e;
while ((e = names.removeLast()) != NULL) {
delete e;
}
}
void LabelMap::add(const void *p, size_t size, size_t align, const char *name) void LabelMap::add(const void *p, size_t size, size_t align, const char *name)
{ {
if (!this || names.containsKey(p)) if (!this || names.containsKey(p))

View File

@ -419,6 +419,7 @@ namespace nanojit
public: public:
Entry(int) : name(0), size(0), align(0) {} Entry(int) : name(0), size(0), align(0) {}
Entry(avmplus::String *n, size_t s, size_t a) : name(n),size(s),align(a) {} Entry(avmplus::String *n, size_t s, size_t a) : name(n),size(s),align(a) {}
~Entry();
DRCWB(avmplus::String*) name; DRCWB(avmplus::String*) name;
size_t size:29, align:3; size_t size:29, align:3;
}; };
@ -429,6 +430,7 @@ namespace nanojit
public: public:
AvmCore *core; AvmCore *core;
LabelMap(AvmCore *, LabelMap* parent); LabelMap(AvmCore *, LabelMap* parent);
~LabelMap();
void add(const void *p, size_t size, size_t align, const char *name); void add(const void *p, size_t size, size_t align, const char *name);
void add(const void *p, size_t size, size_t align, avmplus::String*); void add(const void *p, size_t size, size_t align, avmplus::String*);
const char *dup(const char *); const char *dup(const char *);
@ -455,6 +457,7 @@ namespace nanojit
public: public:
Entry(int) : name(0) {} Entry(int) : name(0) {}
Entry(avmplus::String *n) : name(n) {} Entry(avmplus::String *n) : name(n) {}
~Entry();
DRCWB(avmplus::String*) name; DRCWB(avmplus::String*) name;
}; };
avmplus::SortedMap<LInsp, Entry*, avmplus::LIST_GCObjects> names; avmplus::SortedMap<LInsp, Entry*, avmplus::LIST_GCObjects> names;
@ -470,6 +473,7 @@ namespace nanojit
_functions(_functions), _functions(_functions),
labels(r) labels(r)
{} {}
~LirNameMap();
void addName(LInsp i, const char *s); void addName(LInsp i, const char *s);
void addName(LInsp i, avmplus::String *s); void addName(LInsp i, avmplus::String *s);

View File

@ -190,12 +190,22 @@ namespace nanojit
class GCObject class GCObject
{ {
public:
static void operator delete (void *gcObject)
{
free(gcObject);
}
}; };
#define MMGC_SUBCLASS_DECL #define MMGC_SUBCLASS_DECL : public GCObject
class GCFinalizedObject class GCFinalizedObject : public GCObject
{ {
public:
static void operator delete (void *gcObject)
{
free(gcObject);
}
}; };
class GCHeap class GCHeap