Use a single code cache for the JIT and the RegExp compiler (515852, r=dmandelin).

This commit is contained in:
Andreas Gal 2009-09-12 23:04:27 -07:00
Родитель 684a76e23e
Коммит 0eb8ef2771
4 изменённых файлов: 60 добавлений и 122 удалений

Просмотреть файл

@ -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();