diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index fd1ce0a40ccc..43c3ff205335 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -147,10 +147,11 @@ struct JSTraceMonitor { */ JSContext *tracecx; - CLS(nanojit::LirBuffer) lirbuf; CLS(VMAllocator) allocator; // A chunk allocator for LIR. CLS(nanojit::CodeAlloc) codeAlloc; // A general allocator for native code. CLS(nanojit::Assembler) assembler; + CLS(nanojit::LirBuffer) lirbuf; + CLS(nanojit::LirBuffer) reLirBuf; #ifdef DEBUG CLS(nanojit::LabelMap) labels; #endif @@ -183,17 +184,10 @@ struct JSTraceMonitor { JSBool useReservedObjects; JSObject *reservedObjects; - /* Parts for the regular expression compiler. This is logically - * a distinct compiler but needs to be managed in exactly the same - * way as the trace compiler. */ - CLS(VMAllocator) reAllocator; - CLS(nanojit::CodeAlloc) reCodeAlloc; - CLS(nanojit::Assembler) reAssembler; - CLS(nanojit::LirBuffer) reLirBuf; + /* + * Fragment map for the regular expression compiler. + */ CLS(REHashMap) reFragments; -#ifdef DEBUG - CLS(nanojit::LabelMap) reLabels; -#endif /* Keep a list of recorders we need to abort on cache flush. */ CLS(TraceRecorder) abortStack; diff --git a/js/src/jsregexp.cpp b/js/src/jsregexp.cpp index 55146a7e9d35..b0d9d871f79a 100644 --- a/js/src/jsregexp.cpp +++ b/js/src/jsregexp.cpp @@ -2014,7 +2014,7 @@ LookupNativeRegExp(JSContext* cx, uint16 re_flags, const jschar* re_chars, size_t re_length) { JSTraceMonitor *tm = &JS_TRACE_MONITOR(cx); - VMAllocator &alloc = *tm->reAllocator; + VMAllocator &alloc = *tm->allocator; REHashMap &table = *tm->reFragments; REHashKey k(re_length, re_flags, re_chars); @@ -2477,7 +2477,7 @@ class RegExpNativeCompiler { LIns* compileFlat(RENode *&node, LIns* pos, LInsList& fails) { - VMAllocator *alloc = JS_TRACE_MONITOR(cx).reAllocator; + VMAllocator *alloc = JS_TRACE_MONITOR(cx).allocator; #ifdef USE_DOUBLE_CHAR_MATCH if (node->u.flat.length == 1) { if (node->next && node->next->op == REOP_FLAT && @@ -2540,7 +2540,7 @@ class RegExpNativeCompiler { if (!charSet->converted && !ProcessCharSet(cx, re, charSet)) return NULL; LIns* skip = lirBufWriter->insSkip(bitmapLen); - if (JS_TRACE_MONITOR(cx).reAllocator->outOfMemory()) + if (JS_TRACE_MONITOR(cx).allocator->outOfMemory()) return NULL; void* bitmapData = skip->payload(); memcpy(bitmapData, charSet->u.bits, bitmapLen); @@ -2959,7 +2959,7 @@ class RegExpNativeCompiler { */ LIns *compileNode(RENode *node, LIns *pos, bool atEnd, LInsList &fails) { - VMAllocator *alloc = JS_TRACE_MONITOR(cx).reAllocator; + VMAllocator *alloc = JS_TRACE_MONITOR(cx).allocator; for (; pos && node; node = node->next) { if (alloc->outOfMemory()) return NULL; @@ -3037,7 +3037,7 @@ class RegExpNativeCompiler { /* Failed to match on first character, so fail whole match. */ lir->ins0(LIR_regfence); lir->ins1(LIR_ret, lir->insImm(0)); - return !JS_TRACE_MONITOR(cx).reAllocator->outOfMemory(); + return !JS_TRACE_MONITOR(cx).allocator->outOfMemory(); } /* Compile normal regular expressions that can match starting at any char. */ @@ -3053,7 +3053,7 @@ class RegExpNativeCompiler { lir->insStorei(lir->ins2(LIR_piadd, start, lir->insImmWord(2)), state, offsetof(REGlobalData, skipped)); - return !JS_TRACE_MONITOR(cx).reAllocator->outOfMemory(); + return !JS_TRACE_MONITOR(cx).allocator->outOfMemory(); } inline LIns* @@ -3103,10 +3103,13 @@ class RegExpNativeCompiler { const jschar* re_chars; size_t re_length; JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx); - Assembler *assm = tm->reAssembler; - VMAllocator& alloc = *tm->reAllocator; + Assembler *assm = tm->assembler; + VMAllocator& alloc = *tm->allocator; LIns* loopLabel = NULL; + if (alloc.outOfMemory() || js_OverfullJITCache(tm)) + return JS_FALSE; + re->source->getCharsAndLength(re_chars, re_length); /* * If the regexp is too long nanojit will assert when we @@ -3173,7 +3176,7 @@ class RegExpNativeCompiler { if (alloc.outOfMemory()) goto fail; - ::compile(assm, fragment, alloc verbose_only(, tm->reLabels)); + ::compile(assm, fragment, alloc verbose_only(, tm->labels)); if (assm->error() != nanojit::None) { oom = assm->error() == nanojit::OutOMem; goto fail; @@ -3189,22 +3192,9 @@ class RegExpNativeCompiler { #endif return JS_TRUE; fail: - if (alloc.outOfMemory() || oom || - js_OverfullJITCache(tm, true)) { + if (alloc.outOfMemory() || oom || js_OverfullJITCache(tm)) { delete lirBufWriter; - delete tm->reCodeAlloc; - tm->reCodeAlloc = new CodeAlloc(); - alloc.reset(); - tm->reFragments = new (alloc) REHashMap(alloc); - tm->reLirBuf = new (alloc) LirBuffer(alloc); -#ifdef DEBUG - tm->reLabels = new (alloc) LabelMap(alloc, &js_LogController); - tm->reLirBuf->names = new (alloc) LirNameMap(alloc, tm->reLabels); - tm->reAssembler = new (alloc) Assembler(*tm->reCodeAlloc, alloc, core, - &js_LogController); -#else - tm->reAssembler = new (alloc) Assembler(*tm->reCodeAlloc, alloc, core, NULL); -#endif + js_ResetJIT(cx); } else { if (!guard) insertGuard(loopLabel, re_chars, re_length); re->flags |= JSREG_NOCOMPILE; diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index d83282d49af0..22f21b1d83a8 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -2144,9 +2144,6 @@ oom: void JSTraceMonitor::flush() { - memset(&vmfragments[0], 0, - FRAGMENT_TABLE_SIZE * sizeof(VMFragment*)); - allocator->reset(); delete codeAlloc; codeAlloc = new CodeAlloc(); @@ -2158,16 +2155,19 @@ JSTraceMonitor::flush() globalStates[i].globalSlots = new (alloc) SlotList(allocator); } - assembler = new (alloc) Assembler(*codeAlloc, alloc, core, - &js_LogController); + assembler = new (alloc) Assembler(*codeAlloc, alloc, core, &js_LogController); lirbuf = new (alloc) LirBuffer(alloc); + reLirBuf = new (alloc) LirBuffer(alloc); #ifdef DEBUG - JS_ASSERT(labels); labels = new (alloc) LabelMap(alloc, &js_LogController); + reLirBuf->names = lirbuf->names = new (alloc) LirNameMap(alloc, labels); #endif + memset(&vmfragments[0], 0, FRAGMENT_TABLE_SIZE * sizeof(VMFragment*)); + reFragments = new (alloc) REHashMap(alloc); + needFlush = JS_FALSE; } @@ -3647,6 +3647,12 @@ ResetJIT(JSContext* cx, TraceVisFlushReason r) #define ResetJIT(cx, r) ResetJITImpl(cx) #endif +JS_REQUIRES_STACK void +js_ResetJIT(JSContext* cx) +{ + ResetJIT(cx, FR_OOM); +} + /* Compile the current fragment. */ JS_REQUIRES_STACK void TraceRecorder::compile(JSTraceMonitor* tm) @@ -4562,8 +4568,7 @@ DeleteRecorder(JSContext* cx) /* If we ran out of memory, flush the code cache. */ Assembler *assm = JS_TRACE_MONITOR(cx).assembler; - if (assm->error() == OutOMem || - js_OverfullJITCache(tm, false)) { + if (assm->error() == OutOMem || js_OverfullJITCache(tm)) { ResetJIT(cx, FR_OOM); return false; } @@ -4918,7 +4923,7 @@ RecordTree(JSContext* cx, JSTraceMonitor* tm, VMFragment* f, jsbytecode* outer, f->root = f; f->lirbuf = tm->lirbuf; - if (tm->allocator->outOfMemory() || js_OverfullJITCache(tm, false)) { + if (tm->allocator->outOfMemory() || js_OverfullJITCache(tm)) { Backoff(cx, (jsbytecode*) f->root->ip); ResetJIT(cx, FR_OOM); debug_only_print0(LC_TMTracer, @@ -6304,8 +6309,7 @@ TraceRecorder::monitorRecording(JSContext* cx, TraceRecorder* tr, JSOp op) return JSRS_STOP; } - if (tr->traceMonitor->allocator->outOfMemory() || - js_OverfullJITCache(&JS_TRACE_MONITOR(cx), false)) { + if (tr->traceMonitor->allocator->outOfMemory() || js_OverfullJITCache(&JS_TRACE_MONITOR(cx))) { js_AbortRecording(cx, "no more memory"); ResetJIT(cx, FR_OOM); return JSRS_STOP; @@ -6642,8 +6646,7 @@ void js_SetMaxCodeCacheBytes(JSContext* cx, uint32 bytes) { JSTraceMonitor* tm = &JS_THREAD_DATA(cx)->traceMonitor; - JS_ASSERT(tm->codeAlloc && tm->reCodeAlloc && - tm->allocator && tm->reAllocator); + JS_ASSERT(tm->codeAlloc && tm->allocator); if (bytes > 1 G) bytes = 1 G; if (bytes < 128 K) @@ -6708,53 +6711,14 @@ js_InitJIT(JSTraceMonitor *tm) JS_DHASH_DEFAULT_CAPACITY(PC_HASH_COUNT)); } - if (!tm->allocator) - tm->allocator = new VMAllocator(); + JS_ASSERT(!tm->allocator&& !tm->codeAlloc); + tm->allocator = new VMAllocator(); + tm->codeAlloc = new CodeAlloc(); + tm->flush(); - Allocator& alloc = *tm->allocator; + JS_ASSERT(!tm->reservedDoublePool); + tm->reservedDoublePoolPtr = tm->reservedDoublePool = new jsval[MAX_NATIVE_STACK_SLOTS]; - if (!tm->codeAlloc) - tm->codeAlloc = new CodeAlloc(); - - if (!tm->assembler) { - tm->assembler = new (alloc) Assembler(*tm->codeAlloc, alloc, core, - &js_LogController); - - - JS_ASSERT(!tm->reservedDoublePool); - tm->lirbuf = new (alloc) LirBuffer(alloc); -#ifdef DEBUG - tm->labels = new (alloc) LabelMap(alloc, &js_LogController); - tm->lirbuf->names = new (alloc) LirNameMap(alloc, tm->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 (alloc) SlotList(tm->allocator); - } - 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 (reAlloc) Assembler(*tm->reCodeAlloc, reAlloc, core, - &js_LogController); - - tm->reFragments = new (reAlloc) REHashMap(reAlloc); - tm->reLirBuf = new (reAlloc) LirBuffer(reAlloc); -#ifdef DEBUG - tm->reLabels = new (reAlloc) LabelMap(reAlloc, &js_LogController); - tm->reLirBuf->names = new (reAlloc) LirNameMap(reAlloc, tm->reLabels); -#endif - } #if !defined XP_WIN debug_only(memset(&jitstats, 0, sizeof(jitstats))); #endif @@ -6779,28 +6743,25 @@ js_FinishJIT(JSTraceMonitor *tm) jitstats.typeMapMismatchAtEntry, jitstats.globalShapeMismatchAtEntry); } #endif - if (tm->assembler != NULL) { - JS_ASSERT(tm->reservedDoublePool); + JS_ASSERT(tm->reservedDoublePool); - tm->lirbuf = NULL; + if (tm->recordAttempts.ops) + JS_DHashTableFinish(&tm->recordAttempts); - if (tm->recordAttempts.ops) - JS_DHashTableFinish(&tm->recordAttempts); + memset(&tm->vmfragments[0], 0, FRAGMENT_TABLE_SIZE * sizeof(VMFragment*)); - memset(&tm->vmfragments[0], 0, - FRAGMENT_TABLE_SIZE * sizeof(VMFragment*)); + delete[] tm->reservedDoublePool; + tm->reservedDoublePool = tm->reservedDoublePoolPtr = NULL; - delete[] tm->reservedDoublePool; - tm->reservedDoublePool = tm->reservedDoublePoolPtr = NULL; - } - if (tm->reAssembler != NULL) { - delete tm->reAllocator; - delete tm->reCodeAlloc; - } - if (tm->codeAlloc) + if (tm->codeAlloc) { delete tm->codeAlloc; - if (tm->allocator) + tm->codeAlloc = NULL; + } + + if (tm->allocator) { delete tm->allocator; + tm->allocator = NULL; + } } void @@ -6879,7 +6840,7 @@ js_PurgeScriptFragments(JSContext* cx, JSScript* script) } bool -js_OverfullJITCache(JSTraceMonitor* tm, bool reCache) +js_OverfullJITCache(JSTraceMonitor* tm) { /* * You might imagine the outOfMemory flag on the allocator is sufficient @@ -6918,17 +6879,7 @@ js_OverfullJITCache(JSTraceMonitor* tm, bool reCache) jsuint maxsz = tm->maxCodeCacheBytes; VMAllocator *allocator = tm->allocator; CodeAlloc *codeAlloc = tm->codeAlloc; - if (reCache) { - /* - * At the time of making the code cache size configurable, we were using - * 16 MB for the main code cache and 1 MB for the regular expression code - * cache. We will stick to this 16:1 ratio here until we unify the two - * code caches. - */ - maxsz /= 16; - allocator = tm->reAllocator; - codeAlloc = tm->reCodeAlloc; - } + return (codeAlloc->size() + allocator->size() > maxsz); } diff --git a/js/src/jstracer.h b/js/src/jstracer.h index a80820473ec1..a7b4897a327e 100644 --- a/js/src/jstracer.h +++ b/js/src/jstracer.h @@ -1102,7 +1102,10 @@ extern void js_PurgeScriptFragments(JSContext* cx, JSScript* script); extern bool -js_OverfullJITCache(JSTraceMonitor* tm, bool reCache); +js_OverfullJITCache(JSTraceMonitor* tm); + +extern void +js_ResetJIT(JSContext* cx); extern void js_PurgeJITOracle();