зеркало из https://github.com/mozilla/gecko-dev.git
Use a single code cache for the JIT and the RegExp compiler (515852, r=dmandelin).
This commit is contained in:
Родитель
684a76e23e
Коммит
0eb8ef2771
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
Загрузка…
Ссылка в новой задаче