Bug 471602 part 1: make regexp compiler use one shared LIR buffer, r=gal
authorDavid Mandelin <dmandelin@mozilla.com>
Wed, 31 Dec 2008 16:41:33 -0800
changeset 22912 4fe84f9aa9b97e8da9d6936f4f2f8a234cede160
parent 22911 dea8b86fe1609c20bd8589351312c19703afa980
child 22913 4fa0463ddf165fd712ec18ccf9aa03b3acfb5f9b
push id498
push userrsayre@mozilla.com
push dateFri, 23 Jan 2009 02:33:10 +0000
reviewersgal
bugs471602
milestone1.9.1b3pre
Bug 471602 part 1: make regexp compiler use one shared LIR buffer, r=gal
js/src/jscntxt.h
js/src/jsregexp.cpp
js/src/jstracer.cpp
js/src/nanojit/LIR.cpp
js/src/nanojit/LIR.h
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -92,16 +92,17 @@ typedef struct JSGSNCache {
 /* These helper macros take a cx as parameter and operate on its GSN cache. */
 #define JS_CLEAR_GSN_CACHE(cx)      GSN_CACHE_CLEAR(&JS_GSN_CACHE(cx))
 #define JS_METER_GSN_CACHE(cx,cnt)  GSN_CACHE_METER(&JS_GSN_CACHE(cx), cnt)
 
 #ifdef __cplusplus
 namespace nanojit {
     class Fragment;
     class Fragmento;
+    class LirBuffer;
 }
 class TraceRecorder;
 extern "C++" { template<typename T> class Queue; }
 typedef Queue<uint16> SlotList;
 class TypeMap;
 
 # define CLS(T)  T*
 #else
@@ -127,16 +128,17 @@ typedef struct JSTraceMonitor {
     CLS(SlotList)           globalSlots;
     CLS(TypeMap)            globalTypeMap;
     jsval                   *recoveryDoublePool;
     jsval                   *recoveryDoublePoolPtr;
 
     /* Fragmento for the regular expression compiler. This is logically
      * a distinct compiler but needs to be managed in exactly the same
      * way as the real tracing Fragmento. */
+    CLS(nanojit::LirBuffer) reLirBuf;
     CLS(nanojit::Fragmento) reFragmento;
 
     /* Keep a list of recorders we need to abort on cache flush. */
     CLS(TraceRecorder)      abortStack;
 } JSTraceMonitor;
 
 #ifdef JS_TRACER
 # define JS_ON_TRACE(cx)            (JS_TRACE_MONITOR(cx).onTrace)
--- a/js/src/jsregexp.cpp
+++ b/js/src/jsregexp.cpp
@@ -2048,16 +2048,17 @@ static JSBool
 ProcessCharSet(JSContext *cx, JSRegExp *re, RECharSet *charSet);
 
 class RegExpNativeCompiler {
  private:
     JSContext*       cx;
     JSRegExp*        re;
     CompilerState*   cs;            /* RegExp to compile */
     Fragment*        fragment;
+    LirBuffer*       lirbuf;
     LirWriter*       lir;
     LirBufWriter*    lirBufWriter;  /* for skip */
 
     LIns*            state;
     LIns*            gdata;
     LIns*            cpend;
 
     JSBool isCaseInsensitive() const { return cs->flags & JSREG_FOLD; }
@@ -2419,18 +2420,17 @@ GetNativeRegExp(JSContext* cx, JSRegExp*
     fragment = LookupNativeRegExp(cx, hash, re->flags, re_chars, re_length);
     if (fragment) {
         if (fragment->code())
             goto ok;
         if (fragment->isBlacklisted())
             return NULL;
     } else {
         fragment = fragmento->getAnchor(hash);
-        fragment->lirbuf = new (&gc) LirBuffer(fragmento, NULL);
-        /* required to have the onDestroy method delete the lirbuf. */
+        fragment->lirbuf = JS_TRACE_MONITOR(cx).reLirBuf;
         fragment->root = fragment;
     }
         
     if (!CompileRegExpToNative(cx, re, fragment))
         return NULL;
  ok:
     union { NIns *code; NativeRegExp func; } u;
     u.code = fragment->code();
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -2694,17 +2694,17 @@ nanojit::LirNameMap::formatGuard(LIns *i
             (long int)x->sp_adj,
             (long int)x->rp_adj);
 }
 #endif
 
 void
 nanojit::Fragment::onDestroy()
 {
-    if (root == this) {
+    if (root == this && lirbuf && !lirbuf->shared) {
         delete lirbuf;
     }
     delete (TreeInfo *)vmprivate;
 }
 
 void
 js_DeleteRecorder(JSContext* cx)
 {
@@ -4029,16 +4029,18 @@ js_InitJIT(JSTraceMonitor *tm)
         tm->globalSlots = new (&gc) SlotList();
         tm->globalTypeMap = new (&gc) TypeMap();
         tm->recoveryDoublePoolPtr = tm->recoveryDoublePool = new jsval[MAX_NATIVE_STACK_SLOTS];
     }
     if (!tm->reFragmento) {
         Fragmento* fragmento = new (&gc) Fragmento(core, 20);
         verbose_only(fragmento->labels = new (&gc) LabelMap(core, NULL);)
         tm->reFragmento = fragmento;
+        tm->reLirBuf = new (&gc) LirBuffer(fragmento, NULL);
+        tm->reLirBuf->shared = true;
     }
     InitIMacroCode();
 #if !defined XP_WIN
     debug_only(memset(&jitstats, 0, sizeof(jitstats)));
 #endif
 }
 
 extern void
@@ -4066,16 +4068,17 @@ js_FinishJIT(JSTraceMonitor *tm)
         delete tm->globalSlots;
         tm->globalSlots = NULL;
         delete tm->globalTypeMap;
         tm->globalTypeMap = NULL;
         delete[] tm->recoveryDoublePool;
         tm->recoveryDoublePool = tm->recoveryDoublePoolPtr = NULL;
     }
     if (tm->reFragmento != NULL) {
+        delete tm->reLirBuf;
         verbose_only(delete tm->reFragmento->labels;)
         delete tm->reFragmento;
     }
 }
 
 void
 TraceRecorder::pushAbortStack()
 {
--- a/js/src/nanojit/LIR.cpp
+++ b/js/src/nanojit/LIR.cpp
@@ -83,17 +83,17 @@ namespace nanojit
 	#undef counter_value
 	#define counter_value(x)		x
 #endif /* NJ_PROFILE */
 
 	//static int32_t buffer_count = 0;
 	
 	// LCompressedBuffer
 	LirBuffer::LirBuffer(Fragmento* frago, const CallInfo* functions)
-		: _frago(frago), _pages(frago->core()->GetGC()), _functions(functions), abi(ABI_FASTCALL)
+		: _frago(frago), _pages(frago->core()->GetGC()), _functions(functions), abi(ABI_FASTCALL), shared(false)
 	{
 		clear();
 		Page* start = pageAlloc();
 		if (start)
 			_unused = &start->lir[0];
 		//buffer_count++;
 		//fprintf(stderr, "LirBuffer %x unused %x\n", (int)this, (int)_unused);
 	}
--- a/js/src/nanojit/LIR.h
+++ b/js/src/nanojit/LIR.h
@@ -709,16 +709,18 @@ namespace nanojit
 			}
 			_stats;
 
 			const CallInfo* _functions;
             AbiKind abi;
             LInsp state,param1,sp,rp;
             LInsp savedRegs[NumSavedRegs];
             bool explicitSavedRegs;
+
+     		bool shared;
 			
 		protected:
 			friend class LirBufWriter;
 
 			LInsp		commit(uint32_t count);
 			Page*		pageAlloc();
 
 			PageList	_pages;