Use a single lirbuf for the tracer and rewind lirbuf during GC (471821, r=danderson).
Use a single lirbuf for the tracer and rewind lirbuf during GC (471821, r=danderson).
--- 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;