Need an API exposed to control code cache size (474497, r=bent,brendan, sr=mrbkap).

This commit is contained in:
Andreas Gal 2009-04-22 16:52:59 -07:00
parent b554a4c785
commit a51f22dbdf
9 changed files with 80 additions and 18 deletions

View File

@ -1000,6 +1000,7 @@ nsDOMThreadService::CreateJSContext()
JS_SetScriptStackQuota(cx, 100*1024*1024);
JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_JIT | JSOPTION_ANONFUNFIX);
JS_SetGCParameterForThread(cx, JSGC_MAX_CODE_CACHE_BYTES, 1 * 1024 * 1024);
return cx.forget();
}

View File

@ -2600,6 +2600,20 @@ JS_GetGCParameter(JSRuntime *rt, JSGCParamKey key)
}
}
JS_PUBLIC_API(void)
JS_SetGCParameterForThread(JSContext *cx, JSGCParamKey key, uint32 value)
{
JS_ASSERT(key == JSGC_MAX_CODE_CACHE_BYTES);
js_SetMaxCodeCacheBytes(cx, value);
}
JS_PUBLIC_API(uint32)
JS_GetGCParameterForThread(JSContext *cx, JSGCParamKey key)
{
JS_ASSERT(key == JSGC_MAX_CODE_CACHE_BYTES);
return JS_THREAD_DATA(cx)->traceMonitor.maxCodeCacheBytes;
}
JS_PUBLIC_API(intN)
JS_AddExternalStringFinalizer(JSStringFinalizeOp finalizer)
{

View File

@ -1207,7 +1207,10 @@ typedef enum JSGCParamKey {
JSGC_BYTES = 4,
/* Number of times when GC was invoked. */
JSGC_NUMBER = 5
JSGC_NUMBER = 5,
/* Max size of the code cache in bytes. */
JSGC_MAX_CODE_CACHE_BYTES = 6
} JSGCParamKey;
extern JS_PUBLIC_API(void)
@ -1216,6 +1219,12 @@ JS_SetGCParameter(JSRuntime *rt, JSGCParamKey key, uint32 value);
extern JS_PUBLIC_API(uint32)
JS_GetGCParameter(JSRuntime *rt, JSGCParamKey key);
extern JS_PUBLIC_API(void)
JS_SetGCParameterForThread(JSContext *cx, JSGCParamKey key, uint32 value);
extern JS_PUBLIC_API(uint32)
JS_GetGCParameterForThread(JSContext *cx, JSGCParamKey key);
/*
* Add a finalizer for external strings created by JS_NewExternalString (see
* below) using a type-code returned from this function, and that understands

View File

@ -153,6 +153,12 @@ struct JSTraceMonitor {
uintN prohibitFlush;
JSPackedBool needFlush;
/*
* Maximum size of the code cache before we start flushing. 1/16 of this
* size is used as threshold for the regular expression code cache.
*/
uint32 maxCodeCacheBytes;
/*
* reservedObjects is a linked list (via fslots[0]) of preallocated JSObjects.
* The JIT uses this to ensure that leaving a trace tree can't fail.

View File

@ -71,9 +71,6 @@
#include "jstracer.h"
using namespace avmplus;
using namespace nanojit;
/* Amount of memory in the RE fragmento before flushing. */
#define MAX_MEM_IN_RE_FRAGMENTO (1 << 20)
#endif
typedef enum REOp {
@ -2442,7 +2439,7 @@ class RegExpNativeCompiler {
return JS_TRUE;
fail:
if (lirbuf->outOMem() || oom ||
js_OverfullFragmento(fragmento, MAX_MEM_IN_RE_FRAGMENTO)) {
js_OverfullFragmento(&JS_TRACE_MONITOR(cx), fragmento)) {
fragmento->clearFrags();
lirbuf->rewind();
} else {

View File

@ -135,9 +135,6 @@ static const char tagChar[] = "OIDISIBI";
(MAX_NATIVE_STACK_SLOTS * sizeof(jsval) + \
MAX_CALL_STACK_ENTRIES * sizeof(JSInlineFrame))
/* Amount of memory in the main fragmento before flushing. */
#define MAX_MEM_IN_MAIN_FRAGMENTO (1 << 24)
/* Max number of branches per tree. */
#define MAX_BRANCHES 32
@ -3212,8 +3209,8 @@ js_DeleteRecorder(JSContext* cx)
/*
* If we ran out of memory, flush the code cache.
*/
if (JS_TRACE_MONITOR(cx).fragmento->assm()->error() == OutOMem
|| js_OverfullFragmento(tm->fragmento, MAX_MEM_IN_MAIN_FRAGMENTO)) {
if (JS_TRACE_MONITOR(cx).fragmento->assm()->error() == OutOMem ||
js_OverfullFragmento(tm, tm->fragmento)) {
FlushJITCache(cx);
return false;
}
@ -3534,8 +3531,7 @@ js_RecordTree(JSContext* cx, JSTraceMonitor* tm, Fragment* f, jsbytecode* outer,
f->root = f;
f->lirbuf = tm->lirbuf;
if (f->lirbuf->outOMem() ||
js_OverfullFragmento(tm->fragmento, MAX_MEM_IN_MAIN_FRAGMENTO)) {
if (f->lirbuf->outOMem() || js_OverfullFragmento(tm, tm->fragmento)) {
FlushJITCache(cx);
debug_only_v(printf("Out of memory recording new tree, flushing cache.\n");)
return false;
@ -4594,9 +4590,8 @@ TraceRecorder::monitorRecording(JSContext* cx, TraceRecorder* tr, JSOp op)
return JSMRS_STOP;
}
if (tr->lirbuf->outOMem() ||
js_OverfullFragmento(JS_TRACE_MONITOR(cx).fragmento,
MAX_MEM_IN_MAIN_FRAGMENTO)) {
if (tr->lirbuf->outOMem() ||
js_OverfullFragmento(&JS_TRACE_MONITOR(cx), JS_TRACE_MONITOR(cx).fragmento)) {
js_AbortRecording(cx, "no more LIR memory");
FlushJITCache(cx);
return JSMRS_STOP;
@ -4837,6 +4832,22 @@ js_arm_check_vfp() { return false; }
#endif /* NANOJIT_ARM */
#define K *1024
#define M K K
#define G K M
void
js_SetMaxCodeCacheBytes(JSContext* cx, uint32 bytes)
{
JSTraceMonitor* tm = &JS_THREAD_DATA(cx)->traceMonitor;
JS_ASSERT(tm->fragmento && tm->reFragmento);
if (bytes > 1 G)
bytes = 1 G;
if (bytes < 128 K)
bytes = 128 K;
tm->maxCodeCacheBytes = bytes;
}
void
js_InitJIT(JSTraceMonitor *tm)
{
@ -4853,6 +4864,11 @@ js_InitJIT(JSTraceMonitor *tm)
did_we_check_processor_features = true;
}
/*
* Set the default size for the code cache to 16MB.
*/
tm->maxCodeCacheBytes = 16 M;
if (!tm->fragmento) {
JS_ASSERT(!tm->reservedDoublePool);
Fragmento* fragmento = new (&gc) Fragmento(core, 32);
@ -4987,7 +5003,7 @@ js_PurgeScriptFragments(JSContext* cx, JSScript* script)
}
bool
js_OverfullFragmento(Fragmento *frago, size_t maxsz)
js_OverfullFragmento(JSTraceMonitor* tm, Fragmento *fragmento)
{
/*
* You might imagine the outOMem flag on the lirbuf is sufficient
@ -5023,7 +5039,20 @@ js_OverfullFragmento(Fragmento *frago, size_t maxsz)
* handled by the (few) callers of this function.
*
*/
return (frago->_stats.pages > (maxsz >> NJ_LOG2_PAGE_SIZE));
jsuint maxsz = tm->maxCodeCacheBytes;
if (fragmento == tm->fragmento) {
if (tm->prohibitFlush)
return false;
} else {
/*
* 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;
}
return (fragmento->_stats.pages > (maxsz >> NJ_LOG2_PAGE_SIZE));
}
JS_FORCES_STACK JS_FRIEND_API(void)

View File

@ -679,7 +679,7 @@ extern void
js_PurgeScriptFragments(JSContext* cx, JSScript* script);
extern bool
js_OverfullFragmento(nanojit::Fragmento *frago, size_t maxsz);
js_OverfullFragmento(JSTraceMonitor* tm, nanojit::Fragmento *frago);
extern void
js_PurgeJITOracle();
@ -687,6 +687,9 @@ js_PurgeJITOracle();
extern JSObject *
js_GetBuiltinFunction(JSContext *cx, uintN index);
extern void
js_SetMaxCodeCacheBytes(JSContext* cx, uint32 bytes);
#else /* !JS_TRACER */
#define TRACE_0(x) ((void)0)

View File

@ -4633,6 +4633,8 @@ main(int argc, char **argv, char **envp)
if (!cx)
return 1;
JS_SetGCParameterForThread(cx, JSGC_MAX_CODE_CACHE_BYTES, 16 * 1024 * 1024);
JS_BeginRequest(cx);
glob = JS_NewObject(cx, &global_class, NULL, NULL);

View File

@ -1142,6 +1142,7 @@ XPCJSRuntime::OnJSContextNew(JSContext *cx)
JSBool ok = JS_TRUE;
if(!mStrIDs[0])
{
JS_SetGCParameterForThread(cx, JSGC_MAX_CODE_CACHE_BYTES, 16 * 1024 * 1024);
JSAutoRequest ar(cx);
for(uintN i = 0; i < IDX_TOTAL_COUNT; i++)
{