Bug 820583 - Use a larger script size limit when compiling off thread, r=dvander.

This commit is contained in:
Brian Hackett 2013-01-08 13:42:03 -07:00
Родитель 944e9bba9f
Коммит b42b809fbc
3 изменённых файлов: 59 добавлений и 35 удалений

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

@ -1198,6 +1198,28 @@ IonCompile(JSContext *cx, HandleScript script, HandleFunction fun, jsbytecode *o
return abortReason; return abortReason;
} }
static inline bool
OffThreadCompilationEnabled(JSContext *cx)
{
return js_IonOptions.parallelCompilation
&& cx->runtime->useHelperThreads()
&& cx->runtime->helperThreadCount() != 0;
}
static inline bool
OffThreadCompilationAvailable(JSContext *cx)
{
// Even if off thread compilation is enabled, compilation must still occur
// on the main thread in some cases. Do not compile off thread during an
// incremental GC, as this may trip incremental read barriers. Also skip
// off thread compilation if script execution is being profiled, as
// CodeGenerator::maybeCreateScriptCounts will not attach script profiles
// when running off thread.
return OffThreadCompilationEnabled(cx)
&& cx->runtime->gcIncrementalState == gc::NO_INCREMENTAL
&& !cx->runtime->profilingScripts;
}
AbortReason AbortReason
SequentialCompileContext::compile(IonBuilder *builder, MIRGraph *graph, SequentialCompileContext::compile(IonBuilder *builder, MIRGraph *graph,
AutoDestroyAllocator &autoDestroy) AutoDestroyAllocator &autoDestroy)
@ -1214,16 +1236,8 @@ SequentialCompileContext::compile(IonBuilder *builder, MIRGraph *graph,
} }
builder->clearForBackEnd(); builder->clearForBackEnd();
// Try to compile the script off thread, if possible. Compilation cannot be // If possible, compile the script off thread.
// performed off thread during an incremental GC, as doing so may trip if (OffThreadCompilationAvailable(cx)) {
// incremental read barriers. Also skip off thread compilation if script
// execution is being profiled, as CodeGenerator::maybeCreateScriptCounts
// will not attach script profiles when running off thread.
if (js_IonOptions.parallelCompilation &&
OffThreadCompilationAvailable(cx) &&
cx->runtime->gcIncrementalState == gc::NO_INCREMENTAL &&
!cx->runtime->profilingScripts)
{
builder->script()->ion = ION_COMPILING_SCRIPT; builder->script()->ion = ION_COMPILING_SCRIPT;
if (!StartOffThreadIonCompile(cx, builder)) { if (!StartOffThreadIonCompile(cx, builder)) {
@ -1332,27 +1346,47 @@ CheckScript(UnrootedScript script)
return true; return true;
} }
static bool static MethodStatus
CheckScriptSize(UnrootedScript script) CheckScriptSize(JSContext *cx, UnrootedScript script)
{ {
if (!js_IonOptions.limitScriptSize) if (!js_IonOptions.limitScriptSize)
return true; return Method_Compiled;
static const uint32_t MAX_SCRIPT_SIZE = 2000; // Longer scripts can only be compiled off thread, as these compilations
// can be expensive and stall the main thread for too long.
static const uint32_t MAX_MAIN_THREAD_SCRIPT_SIZE = 2000;
static const uint32_t MAX_OFF_THREAD_SCRIPT_SIZE = 20000;
static const uint32_t MAX_LOCALS_AND_ARGS = 256; static const uint32_t MAX_LOCALS_AND_ARGS = 256;
if (script->length > MAX_SCRIPT_SIZE) { if (script->length > MAX_OFF_THREAD_SCRIPT_SIZE) {
IonSpew(IonSpew_Abort, "Script too large (%u bytes)", script->length); IonSpew(IonSpew_Abort, "Script too large (%u bytes)", script->length);
return false; return Method_CantCompile;
}
if (script->length > MAX_MAIN_THREAD_SCRIPT_SIZE) {
if (OffThreadCompilationEnabled(cx)) {
// Even if off thread compilation is enabled, there are cases where
// compilation must still occur on the main thread. Don't compile
// in these cases (except when profiling scripts, as compilations
// occurring with profiling should reflect those without), but do
// not forbid compilation so that the script may be compiled later.
if (!OffThreadCompilationAvailable(cx) && !cx->runtime->profilingScripts) {
IonSpew(IonSpew_Abort, "Script too large for main thread, skipping (%u bytes)", script->length);
return Method_Skipped;
}
} else {
IonSpew(IonSpew_Abort, "Script too large (%u bytes)", script->length);
return Method_CantCompile;
}
} }
uint32_t numLocalsAndArgs = analyze::TotalSlots(script); uint32_t numLocalsAndArgs = analyze::TotalSlots(script);
if (numLocalsAndArgs > MAX_LOCALS_AND_ARGS) { if (numLocalsAndArgs > MAX_LOCALS_AND_ARGS) {
IonSpew(IonSpew_Abort, "Too many locals and arguments (%u)", numLocalsAndArgs); IonSpew(IonSpew_Abort, "Too many locals and arguments (%u)", numLocalsAndArgs);
return false; return Method_CantCompile;
} }
return true; return Method_Compiled;
} }
static MethodStatus static MethodStatus
@ -1366,11 +1400,17 @@ Compile(JSContext *cx, HandleScript script, HandleFunction fun, jsbytecode *osrP
return Method_CantCompile; return Method_CantCompile;
} }
if (!CheckScript(script) || !CheckScriptSize(script)) { if (!CheckScript(script)) {
IonSpew(IonSpew_Abort, "Aborted compilation of %s:%d", script->filename, script->lineno); IonSpew(IonSpew_Abort, "Aborted compilation of %s:%d", script->filename, script->lineno);
return Method_CantCompile; return Method_CantCompile;
} }
MethodStatus status = CheckScriptSize(cx, script);
if (status != Method_Compiled) {
IonSpew(IonSpew_Abort, "Aborted compilation of %s:%d", script->filename, script->lineno);
return status;
}
if (script->ion) { if (script->ion) {
if (!script->ion->method()) if (!script->ion->method())
return Method_CantCompile; return Method_CantCompile;

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

@ -19,12 +19,6 @@ using mozilla::DebugOnly;
#ifdef JS_PARALLEL_COMPILATION #ifdef JS_PARALLEL_COMPILATION
bool
js::OffThreadCompilationAvailable(JSContext *cx)
{
return cx->runtime->useHelperThreads() && cx->runtime->helperThreadCount() > 0;
}
bool bool
js::StartOffThreadIonCompile(JSContext *cx, ion::IonBuilder *builder) js::StartOffThreadIonCompile(JSContext *cx, ion::IonBuilder *builder)
{ {
@ -360,10 +354,4 @@ js::CancelOffThreadIonCompile(JSCompartment *compartment, JSScript *script)
{ {
} }
bool
js::OffThreadCompilationAvailable(JSContext *cx)
{
return false;
}
#endif /* JS_PARALLEL_COMPILATION */ #endif /* JS_PARALLEL_COMPILATION */

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

@ -120,10 +120,6 @@ StartOffThreadIonCompile(JSContext *cx, ion::IonBuilder *builder);
void void
CancelOffThreadIonCompile(JSCompartment *compartment, JSScript *script); CancelOffThreadIonCompile(JSCompartment *compartment, JSScript *script);
/* Return true iff off-thread compilation is possible. */
bool
OffThreadCompilationAvailable(JSContext *cx);
class AutoLockWorkerThreadState class AutoLockWorkerThreadState
{ {
JSRuntime *rt; JSRuntime *rt;