mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Added explicit deallocation (bug 443500, r=gal)
This commit is contained in:
parent
285acf8b9c
commit
1b623f7d25
@ -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.
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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; )
|
||||||
|
@ -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))
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user