Bug 510036 - Convert LabelMap to HashMap<> and Allocator, r=gal.
authorEdwin Smith <edwsmith@adobe.com>
Tue, 04 Aug 2009 13:56:48 -0400
changeset 31516 1ecbcf5cf36259c591767e4ac0fd3ac89481fb76
parent 31515 39aeb2d502f0a9ef339d3d4198eb917c35e61022
child 31517 0209eec3617f309f803f7f765a247688f416a090
push id8556
push userrsayre@mozilla.com
push dateThu, 13 Aug 2009 21:38:45 +0000
treeherderautoland@9734564871cb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgal
bugs510036
milestone1.9.2a2pre
Bug 510036 - Convert LabelMap to HashMap<> and Allocator, r=gal.
js/src/jsregexp.cpp
js/src/jstracer.cpp
js/src/nanojit/Assembler.h
js/src/nanojit/Fragmento.h
js/src/nanojit/LIR.cpp
js/src/nanojit/LIR.h
--- 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> {