Use a single lirbuf for the tracer and rewind lirbuf during GC (471821, r=danderson).
authorAndreas Gal <gal@mozilla.com>
Fri, 02 Jan 2009 10:55:02 -0800
changeset 22914 f9bf8c0f3676e332f7942f9f6258d10c3b795e7a
parent 22913 4fa0463ddf165fd712ec18ccf9aa03b3acfb5f9b
child 22915 42e811a01a34fac60bf741d681f984194f49af6b
push id498
push userrsayre@mozilla.com
push dateFri, 23 Jan 2009 02:33:10 +0000
reviewersdanderson
bugs471821
milestone1.9.1b3pre
Use a single lirbuf for the tracer and rewind lirbuf during GC (471821, r=danderson).
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
@@ -117,16 +117,17 @@ class TypeMap;
 typedef struct JSTraceMonitor {
     /*
      * Flag set when running (or recording) JIT-compiled code. This prevents
      * both interpreter activation and last-ditch garbage collection when up
      * against our runtime's memory limits. This flag also suppresses calls to
      * JS_ReportOutOfMemory when failing due to runtime limits.
      */
     JSBool                  onTrace;
+    CLS(nanojit::LirBuffer) lirbuf;
     CLS(nanojit::Fragmento) fragmento;
     CLS(TraceRecorder)      recorder;
     uint32                  globalShape;
     CLS(SlotList)           globalSlots;
     CLS(TypeMap)            globalTypeMap;
     jsval                   *recoveryDoublePool;
     jsval                   *recoveryDoublePoolPtr;
 
--- a/js/src/jsregexp.cpp
+++ b/js/src/jsregexp.cpp
@@ -2359,16 +2359,17 @@ class RegExpNativeCompiler {
         delete lirBufWriter;
 #ifdef NJ_VERBOSE
         debug_only_v(delete lir;)
 #endif
         return JS_TRUE;
     fail:
         if (lirbuf->outOMem() || oom) {
             fragmento->clearFrags();
+            lirbuf->rewind();
         } else {
             if (!guard) insertGuard(re_chars, re_length);
             fragment->blacklist();
         }
         delete lirBufWriter;
 #ifdef NJ_VERBOSE
         debug_only_v(delete lir;)
 #endif
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -2694,19 +2694,16 @@ nanojit::LirNameMap::formatGuard(LIns *i
             (long int)x->sp_adj,
             (long int)x->rp_adj);
 }
 #endif
 
 void
 nanojit::Fragment::onDestroy()
 {
-    if (root == this && lirbuf && !lirbuf->shared) {
-        delete lirbuf;
-    }
     delete (TreeInfo *)vmprivate;
 }
 
 void
 js_DeleteRecorder(JSContext* cx)
 {
     JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
 
@@ -3006,23 +3003,17 @@ js_RecordTree(JSContext* cx, JSTraceMoni
     /* Try to find an unused peer fragment, or allocate a new one. */
     while (f->code() && f->peer)
         f = f->peer;
     if (f->code())
         f = JS_TRACE_MONITOR(cx).fragmento->getAnchor(f->root->ip);
 
     f->recordAttempts++;
     f->root = f;
-    /* allocate space to store the LIR for this tree */
-    if (!f->lirbuf) {
-        f->lirbuf = new (&gc) LirBuffer(tm->fragmento, NULL);
-#ifdef DEBUG
-        f->lirbuf->names = new (&gc) LirNameMap(&gc, NULL, tm->fragmento->labels);
-#endif
-    }
+    f->lirbuf = tm->lirbuf;
 
     if (f->lirbuf->outOMem()) {
         js_FlushJITCache(cx);
         debug_only_v(printf("Out of memory recording new tree, flushing cache.\n");)
         return false;
     }
 
     JS_ASSERT(!f->code() && !f->vmprivate);
@@ -4021,26 +4012,29 @@ js_InitJIT(JSTraceMonitor *tm)
         did_we_check_sse2 = true;
     }
 #endif
     if (!tm->fragmento) {
         JS_ASSERT(!tm->globalSlots && !tm->globalTypeMap && !tm->recoveryDoublePool);
         Fragmento* fragmento = new (&gc) Fragmento(core, 24);
         verbose_only(fragmento->labels = new (&gc) LabelMap(core, NULL);)
         tm->fragmento = fragmento;
+        tm->lirbuf = new (&gc) LirBuffer(fragmento, NULL);
+#ifdef DEBUG
+        tm->lirbuf->names = new (&gc) LirNameMap(&gc, NULL, tm->fragmento->labels);
+#endif
         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
@@ -4058,16 +4052,22 @@ js_FinishJIT(JSTraceMonitor *tm)
         printf("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->globalSlots && tm->globalTypeMap && tm->recoveryDoublePool);
         verbose_only(delete tm->fragmento->labels;)
+#ifdef DEBUG
+        delete tm->lirbuf->names;
+        tm->lirbuf->names = NULL;
+#endif
+        delete tm->lirbuf;
+        tm->lirbuf = NULL;
         delete tm->fragmento;
         tm->fragmento = NULL;
         delete tm->globalSlots;
         tm->globalSlots = NULL;
         delete tm->globalTypeMap;
         tm->globalTypeMap = NULL;
         delete[] tm->recoveryDoublePool;
         tm->recoveryDoublePool = tm->recoveryDoublePoolPtr = NULL;
@@ -4127,16 +4127,17 @@ js_FlushJITCache(JSContext* cx)
     Fragmento* fragmento = tm->fragmento;
     if (fragmento) {
         fragmento->clearFrags();
 #ifdef DEBUG
         JS_ASSERT(fragmento->labels);
         delete fragmento->labels;
         fragmento->labels = new (&gc) LabelMap(core, NULL);
 #endif
+        tm->lirbuf->rewind();
     }
     if (cx->fp) {
         tm->globalShape = OBJ_SHAPE(JS_GetGlobalForObject(cx, cx->fp->scopeChain));
         tm->globalSlots->clear();
         tm->globalTypeMap->clear();
     }
 }
 
--- a/js/src/nanojit/LIR.cpp
+++ b/js/src/nanojit/LIR.cpp
@@ -83,30 +83,23 @@ 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), shared(false)
+		: _frago(frago), _pages(frago->core()->GetGC()), _functions(functions), abi(ABI_FASTCALL)
 	{
-		clear();
-		Page* start = pageAlloc();
-		if (start)
-			_unused = &start->lir[0];
-		//buffer_count++;
-		//fprintf(stderr, "LirBuffer %x unused %x\n", (int)this, (int)_unused);
+		rewind();
 	}
 
 	LirBuffer::~LirBuffer()
 	{
-		//buffer_count--;
-		//fprintf(stderr, "~LirBuffer %x start %x\n", (int)this, (int)_start);
 		clear();
 		verbose_only(if (names) NJ_DELETE(names);)
 		_frago = 0;
 	}
 	
 	void LirBuffer::clear()
 	{
 		// free all the memory and clear the stats
@@ -118,16 +111,23 @@ namespace nanojit
 		for (int i = 0; i < NumSavedRegs; ++i)
 			savedRegs[i] = NULL;
 		explicitSavedRegs = false;
 		// pre-allocate the next page we will be using
 		_nextPage = pageAlloc();
 		NanoAssert(_nextPage || _noMem);
 	}
 
+    void LirBuffer::rewind()
+	{
+		clear();
+		Page* start = pageAlloc();
+		_unused = start ? &start->lir[0] : NULL;
+    }
+
 	int32_t LirBuffer::insCount() 
 	{
 		// doesn't include embedded constants nor LIR_skip payload
 		return _stats.lir;
 	}
 
 	int32_t LirBuffer::byteCount() 
 	{
--- a/js/src/nanojit/LIR.h
+++ b/js/src/nanojit/LIR.h
@@ -688,16 +688,17 @@ namespace nanojit
 
 	class LirBuffer : public avmplus::GCFinalizedObject
 	{
 		public:
 			DWB(Fragmento*)		_frago;
 			LirBuffer(Fragmento* frago, const CallInfo* functions);
 			virtual ~LirBuffer();
 			void        clear();
+            void        rewind();
 			LInsp		next();
 			bool		outOMem() { return _noMem != 0; }
 			
 			debug_only (void validate() const;)
 			verbose_only(DWB(LirNameMap*) names;)
 			
 			int32_t insCount();
 			int32_t byteCount();
@@ -709,18 +710,16 @@ 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;