Bug 510036 - Convert LabelMap to HashMap<> and Allocator, r=gal.
--- a/js/src/jsregexp.cpp
+++ b/js/src/jsregexp.cpp
@@ -3088,41 +3088,41 @@ class RegExpNativeCompiler {
GuardRecord* guard = NULL;
LIns* pos;
bool oom = false;
const jschar* re_chars;
size_t re_length;
JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
Assembler *assm = tm->reAssembler;
Fragmento* fragmento = tm->reFragmento;
- VMAllocator *alloc = tm->reAllocator;
+ VMAllocator& alloc = *tm->reAllocator;
re->source->getCharsAndLength(re_chars, re_length);
/*
* If the regexp is too long nanojit will assert when we
* try to insert the guard record.
*/
if (re_length > 1024) {
re->flags |= JSREG_NOCOMPILE;
return JS_FALSE;
}
this->cx = cx;
/* At this point we have an empty fragment. */
LirBuffer* lirbuf = fragment->lirbuf;
- if (alloc->outOfMemory())
+ if (alloc.outOfMemory())
goto fail;
/* FIXME Use bug 463260 smart pointer when available. */
lir = lirBufWriter = new (&gc) LirBufWriter(lirbuf);
/* FIXME Use bug 463260 smart pointer when available. */
#ifdef NJ_VERBOSE
debug_only_stmt(
if (js_LogController.lcbits & LC_TMRegexp) {
- lir = new (&gc) VerboseWriter(*alloc, lir, lirbuf->names,
+ lir = new (&gc) VerboseWriter(alloc, lir, lirbuf->names,
&js_LogController);
}
)
#endif
/*
* Although we could just load REGlobalData::cpend from 'state', by
* passing it as a parameter, we avoid loading it every iteration.
@@ -3141,41 +3141,43 @@ class RegExpNativeCompiler {
goto fail;
} else {
if (!compileAnchoring(cs->result, pos))
goto fail;
}
guard = insertGuard(re_chars, re_length);
- if (alloc->outOfMemory())
+ if (alloc.outOfMemory())
goto fail;
- ::compile(fragmento, assm, fragment, *alloc);
+ ::compile(fragmento, assm, fragment, alloc);
if (assm->error() != nanojit::None) {
oom = assm->error() == nanojit::OutOMem;
goto fail;
}
delete lirBufWriter;
#ifdef NJ_VERBOSE
debug_only_stmt( if (js_LogController.lcbits & LC_TMRegexp)
delete lir; )
#endif
return JS_TRUE;
fail:
- if (alloc->outOfMemory() || oom ||
+ if (alloc.outOfMemory() || oom ||
js_OverfullFragmento(tm, fragmento)) {
fragmento->clearFrags();
#ifdef DEBUG
- fragmento->labels->clear();
- delete lirbuf->names;
- lirbuf->names = new (&gc) LirNameMap(&gc, *alloc, fragmento->labels);
+ delete lirbuf->names;
#endif
tm->reCodeAlloc->sweep();
- alloc->reset();
+ alloc.reset();
+#ifdef DEBUG
+ fragmento->labels = new (alloc) LabelMap(alloc, &js_LogController);
+ lirbuf->names = new (&gc) LirNameMap(&gc, alloc, fragmento->labels);
+#endif
lirbuf->clear();
} else {
if (!guard) insertGuard(re_chars, re_length);
re->flags |= JSREG_NOCOMPILE;
}
delete lirBufWriter;
#ifdef NJ_VERBOSE
debug_only_stmt( if (js_LogController.lcbits & LC_TMRegexp)
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -3343,20 +3343,16 @@ FlushJITCache(JSContext* cx)
if (fragmento) {
if (tm->prohibitFlush) {
debug_only_print0(LC_TMTracer, "Deferring fragmento flush due to deep bail.\n");
tm->needFlush = JS_TRUE;
return;
}
fragmento->clearFrags();
-#ifdef DEBUG
- JS_ASSERT(fragmento->labels);
- fragmento->labels->clear();
-#endif
for (size_t i = 0; i < FRAGMENT_TABLE_SIZE; ++i) {
VMFragment* f = tm->vmfragments[i];
while (f) {
VMFragment* next = f->next;
fragmento->clearFragment(f);
f = next;
}
@@ -3365,20 +3361,29 @@ FlushJITCache(JSContext* cx)
for (size_t i = 0; i < MONITOR_N_GLOBAL_STATES; ++i) {
tm->globalStates[i].globalShape = -1;
tm->globalStates[i].globalSlots->clear();
}
}
#ifdef DEBUG
delete tm->lirbuf->names;
- tm->lirbuf->names = new (&gc) LirNameMap(&gc, *tm->allocator, tm->fragmento->labels);
-#endif
+#endif
+
tm->allocator->reset();
tm->codeAlloc->sweep();
+
+#ifdef DEBUG
+ JS_ASSERT(fragmento);
+ JS_ASSERT(fragmento->labels);
+ Allocator& alloc = *tm->allocator;
+ fragmento->labels = new (alloc) LabelMap(alloc, &js_LogController);
+ tm->lirbuf->names = new (&gc) LirNameMap(&gc, alloc, tm->fragmento->labels);
+#endif
+
tm->lirbuf->clear();
tm->needFlush = JS_FALSE;
}
/* Compile the current fragment. */
JS_REQUIRES_STACK void
TraceRecorder::compile(JSTraceMonitor* tm)
{
@@ -6406,58 +6411,62 @@ js_InitJIT(JSTraceMonitor *tm)
JS_DHashTableInit(&tm->recordAttempts, JS_DHashGetStubOps(),
NULL, sizeof(PCHashEntry),
JS_DHASH_DEFAULT_CAPACITY(PC_HASH_COUNT));
}
if (!tm->allocator)
tm->allocator = new VMAllocator();
+ Allocator& alloc = *tm->allocator;
+
if (!tm->codeAlloc)
tm->codeAlloc = new CodeAlloc();
if (!tm->assembler)
- tm->assembler = new (&gc) Assembler(*tm->codeAlloc, *tm->allocator, core,
+ tm->assembler = new (&gc) Assembler(*tm->codeAlloc, alloc, core,
&js_LogController);
if (!tm->fragmento) {
JS_ASSERT(!tm->reservedDoublePool);
Fragmento* fragmento = new (&gc) Fragmento(core, &js_LogController, 32, tm->codeAlloc);
- verbose_only(fragmento->labels = new (&gc) LabelMap(core, *tm->allocator);)
+ verbose_only(fragmento->labels = new (alloc) LabelMap(alloc, &js_LogController);)
tm->fragmento = fragmento;
- tm->lirbuf = new (&gc) LirBuffer(*tm->allocator);
+ tm->lirbuf = new (&gc) LirBuffer(alloc);
#ifdef DEBUG
- tm->lirbuf->names = new (&gc) LirNameMap(&gc, *tm->allocator, tm->fragmento->labels);
+ tm->lirbuf->names = new (&gc) LirNameMap(&gc, alloc, tm->fragmento->labels);
#endif
for (size_t i = 0; i < MONITOR_N_GLOBAL_STATES; ++i) {
tm->globalStates[i].globalShape = -1;
JS_ASSERT(!tm->globalStates[i].globalSlots);
tm->globalStates[i].globalSlots = new (&gc) SlotList();
}
tm->reservedDoublePoolPtr = tm->reservedDoublePool = new jsval[MAX_NATIVE_STACK_SLOTS];
memset(tm->vmfragments, 0, sizeof(tm->vmfragments));
}
if (!tm->reAllocator)
tm->reAllocator = new VMAllocator();
+ Allocator& reAlloc = *tm->reAllocator;
+
if (!tm->reCodeAlloc)
tm->reCodeAlloc = new CodeAlloc();
if (!tm->reAssembler)
- tm->reAssembler = new (&gc) Assembler(*tm->reCodeAlloc, *tm->reAllocator, core,
+ tm->reAssembler = new (&gc) Assembler(*tm->reCodeAlloc, reAlloc, core,
&js_LogController);
if (!tm->reFragmento) {
Fragmento* fragmento = new (&gc) Fragmento(core, &js_LogController, 32, tm->reCodeAlloc);
- verbose_only(fragmento->labels = new (&gc) LabelMap(core, *tm->reAllocator);)
+ verbose_only(fragmento->labels = new (reAlloc) LabelMap(reAlloc, &js_LogController);)
tm->reFragmento = fragmento;
- tm->reLirBuf = new (&gc) LirBuffer(*tm->reAllocator);
+ tm->reLirBuf = new (&gc) LirBuffer(reAlloc);
#ifdef DEBUG
- tm->reLirBuf->names = new (&gc) LirNameMap(&gc, *tm->reAllocator, fragmento->labels);
+ tm->reLirBuf->names = new (&gc) LirNameMap(&gc, reAlloc, fragmento->labels);
#endif
}
#if !defined XP_WIN
debug_only(memset(&jitstats, 0, sizeof(jitstats)));
#endif
}
void
@@ -6476,17 +6485,16 @@ js_FinishJIT(JSTraceMonitor *tm)
debug_only_printf(LC_TMStats,
"monitor: triggered(%llu), exits(%llu), type mismatch(%llu), "
"global mismatch(%llu)\n", jitstats.traceTriggered, jitstats.sideExitIntoInterpreter,
jitstats.typeMapMismatchAtEntry, jitstats.globalShapeMismatchAtEntry);
}
#endif
if (tm->fragmento != NULL) {
JS_ASSERT(tm->reservedDoublePool);
- verbose_only(delete tm->fragmento->labels;)
#ifdef DEBUG
delete tm->lirbuf->names;
tm->lirbuf->names = NULL;
#endif
delete tm->lirbuf;
tm->lirbuf = NULL;
if (tm->recordAttempts.ops)
@@ -6507,17 +6515,16 @@ js_FinishJIT(JSTraceMonitor *tm)
JS_ASSERT(tm->globalStates[i].globalSlots);
delete tm->globalStates[i].globalSlots;
}
delete[] tm->reservedDoublePool;
tm->reservedDoublePool = tm->reservedDoublePoolPtr = NULL;
}
if (tm->reFragmento != NULL) {
delete tm->reLirBuf;
- verbose_only(delete tm->reFragmento->labels;)
delete tm->reFragmento;
delete tm->reAllocator;
delete tm->reAssembler;
delete tm->reCodeAlloc;
}
if (tm->assembler)
delete tm->assembler;
if (tm->codeAlloc)
--- a/js/src/nanojit/Assembler.h
+++ b/js/src/nanojit/Assembler.h
@@ -162,16 +162,17 @@ namespace nanojit
void FASTCALL output(const char* s);
void FASTCALL outputf(const char* format, ...);
void FASTCALL output_asm(const char* s);
bool outputAddr, vpad[3]; // if outputAddr=true then next asm instr. will include address in output
void printActivationState();
StringList* _outputCache;
+ LabelMap* _labelMap;
// Log controller object. Contains what-stuff-should-we-print
// bits, and a sink function for debug printing
LogControl* _logc;
#endif
Assembler(CodeAlloc& codeAlloc, Allocator& alloc, AvmCore* core, LogControl* logc);
~Assembler() {}
--- a/js/src/nanojit/Fragmento.h
+++ b/js/src/nanojit/Fragmento.h
@@ -94,17 +94,17 @@ namespace nanojit
{
uint32_t pages; // pages consumed
uint32_t flushes, ilsize, abcsize, compiles, totalCompiles;
}
_stats;
verbose_only( DWB(BlockHist*) enterCounts; )
verbose_only( DWB(BlockHist*) mergeCounts; )
- verbose_only( DWB(LabelMap*) labels; )
+ verbose_only( LabelMap* labels; )
#ifdef AVMPLUS_VERBOSE
void drawTrees(char *fileName);
#endif
void clearFragment(Fragment *f);
private:
AvmCore* _core;
--- a/js/src/nanojit/LIR.cpp
+++ b/js/src/nanojit/LIR.cpp
@@ -2194,60 +2194,49 @@ namespace nanojit
if (op == LIR_label)
exprs.clear();
return out->ins0(op);
}
#endif /* FEATURE_NANOJIT */
#if defined(NJ_VERBOSE)
- LabelMap::LabelMap(AvmCore *core, nanojit::Allocator& a)
- : allocator(a), names(core->gc), addrs(core->config.verbose_addrs), end(buf)
+ LabelMap::LabelMap(nanojit::Allocator& a, LogControl *logc)
+ : allocator(a), names(a), logc(logc), end(buf)
{}
- LabelMap::~LabelMap()
- {
- clear();
- }
-
- void LabelMap::clear()
- {
- // don't free entries since they're owned by Allocator
- names.clear();
- }
-
void LabelMap::add(const void *p, size_t size, size_t align, const char *name)
{
if (!this || names.containsKey(p))
return;
char* copy = new (allocator) char[VMPI_strlen(name)+1];
VMPI_strcpy(copy, name);
Entry *e = new (allocator) Entry(copy, size << align, align);
names.put(p, e);
}
const char *LabelMap::format(const void *p)
{
char b[200];
- int i = names.findNear(p);
- if (i >= 0) {
- const void *start = names.keyAt(i);
- Entry *e = names.at(i);
+
+ const void *start = names.findNear(p);
+ if (start != NULL) {
+ Entry *e = names.get(start);
const void *end = (const char*)start + e->size;
const char *name = e->name;
if (p == start) {
- if (addrs)
+ if (!(logc->lcbits & LC_NoCodeAddrs))
VMPI_sprintf(b,"%p %s",p,name);
else
VMPI_strcpy(b, name);
return dup(b);
}
else if (p > start && p < end) {
int32_t d = int32_t(intptr_t(p)-intptr_t(start)) >> e->align;
- if (addrs)
+ if (!(logc->lcbits & LC_NoCodeAddrs))
VMPI_sprintf(b, "%p %s+%d", p, name, d);
else
VMPI_sprintf(b,"%s+%d", name, d);
return dup(b);
}
else {
VMPI_sprintf(b, "%p", p);
return dup(b);
--- a/js/src/nanojit/LIR.h
+++ b/js/src/nanojit/LIR.h
@@ -856,37 +856,35 @@ namespace nanojit
#ifdef NJ_VERBOSE
extern const char* lirNames[];
/**
* map address ranges to meaningful names.
*/
- class LabelMap MMGC_SUBCLASS_DECL
+ class LabelMap
{
Allocator& allocator;
class Entry
{
public:
Entry(char *n, size_t s, size_t a) : name(n),size(s),align(a) {}
char* name;
size_t size:29, align:3;
};
- avmplus::SortedMap<const void*, Entry*, avmplus::LIST_NonGCObjects> names;
- bool addrs, pad[3];
+ TreeMap<const void*, Entry*> names;
+ LogControl *logc;
char buf[1000], *end;
void formatAddr(const void *p, char *buf);
public:
- LabelMap(avmplus::AvmCore *, Allocator& allocator);
- ~LabelMap();
+ LabelMap(Allocator& allocator, LogControl* logc);
void add(const void *p, size_t size, size_t align, const char *name);
const char *dup(const char *);
const char *format(const void *p);
- void clear();
};
class LirNameMap MMGC_SUBCLASS_DECL
{
Allocator& alloc;
template <class Key>
class CountMap: public avmplus::SortedMap<Key, int, avmplus::LIST_NonGCObjects> {