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 -*-
* vim: set ts=8 sw=4 et tw=99:
* vim: set ts=4 sw=4 et tw=99:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
@ -91,7 +91,7 @@ static struct {
#define AUDIT(x) (stat.x++)
#else
#define AUDIT(x) ((void)0)
#endif DEBUG
#endif
#define INS_CONST(c) addName(lir->insImm(c), #c)
@ -99,7 +99,8 @@ using namespace avmplus;
using namespace nanojit;
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? */
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,
js_PCToLineNumber(cx, cx->fp->script, cx->fp->regs->pc));
fragmento->labels->add(fragment, sizeof(Fragment), 0, label);
free(label);
#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 */
}
void
nanojit::Fragment::onDestroy()
{
if (root == this) {
delete mergeCounts;
delete lirbuf;
}
delete (TreeInfo *)vmprivate;
}
void
js_DeleteRecorder(JSContext* cx)
{
@ -1495,7 +1507,7 @@ js_RecordTree(JSContext* cx, JSTraceMonitor* tm, Fragment* f)
JS_ASSERT(!f->vmprivate);
/* 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;
/* we shouldn't have any interned globals for a new tree */
@ -1768,7 +1780,7 @@ js_InitJIT(JSContext* cx)
extern void
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
printf("recorder: started(%llu), aborted(%llu), completed(%llu), different header(%llu), "
"trees trashed(%llu), slot promoted(%llu), "
@ -1779,6 +1791,8 @@ js_DestroyJIT(JSContext* cx)
"global mismatch(%llu)\n", stat.traceTriggered, stat.sideExitIntoInterpreter,
stat.typeMapMismatchAtEntry, stat.globalShapeMismatchAtEntry);
#endif
verbose_only(delete tm->fragmento->labels;)
delete tm->fragmento;
}
extern void
@ -1792,7 +1806,6 @@ js_FlushJITCache(JSContext* cx)
js_AbortRecording(cx, NULL, "flush cache");
Fragmento* fragmento = tm->fragmento;
if (fragmento) {
// TODO: deallocate vmprivate -> TreeInfo for root fragments
fragmento->clearFrags();
#ifdef DEBUG
JS_ASSERT(fragmento->labels);
@ -3884,22 +3897,32 @@ TraceRecorder::record_JSOP_FORLOCAL()
if (stateval == JSVAL_ZERO)
goto done;
LIns* state_ins = lir->ins2(LIR_and, stateval_ins, lir->insImmPtr((void*) ~jsval(3)));
LIns* cursor_ins = lir->insLoadi(state_ins, offsetof(JSNativeEnumerator, cursor));
LIns* state_ins;
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)"));
JSNativeEnumerator* ne = (JSNativeEnumerator*) (stateval & ~jsval(3));
JSNativeEnumerator* ne;
ne = (JSNativeEnumerator*) (stateval & ~jsval(3));
if (ne->cursor == 0)
goto done;
cursor_ins = lir->ins2i(LIR_sub, cursor_ins, 1);
lir->insStorei(cursor_ins, state_ins, offsetof(JSNativeEnumerator, cursor));
LIns* ids_ins = lir->ins2i(LIR_add, state_ins, offsetof(JSNativeEnumerator, ids));
LIns* id_addr_ins = lir->ins2(LIR_add, ids_ins,
LIns* 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));
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);
// Stack an unboxed true to make JSOP_IFEQ loop.

View File

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

View File

@ -1240,7 +1240,12 @@ namespace nanojit
case LIR_loop:
{
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);

View File

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

View File

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

View File

@ -114,6 +114,7 @@ namespace nanojit
//buffer_count--;
//fprintf(stderr, "~LirBuffer %x start %x\n", (int)this, (int)_start);
clear();
delete names;
_frago = 0;
}
@ -1315,6 +1316,13 @@ namespace nanojit
List<RetiredEntry*, LIST_GCObjects> retired;
int maxlive;
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) {
if (!i->isconst() && !i->isconstq() && !live.containsKey(i)) {
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) {
if (!names.containsKey(i)) {
Entry *e = new (labels->core->gc) Entry(name);
@ -1787,6 +1814,12 @@ namespace nanojit
root->link(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 */
@ -1796,6 +1829,15 @@ namespace nanojit
: 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)
{
if (!this || names.containsKey(p))

View File

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

View File

@ -190,12 +190,22 @@ namespace nanojit
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