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
parent 5c77201aa0
commit 5c20f19dae
3 changed files with 59 additions and 35 deletions

View File

@ -1198,6 +1198,28 @@ IonCompile(JSContext *cx, HandleScript script, HandleFunction fun, jsbytecode *o
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
SequentialCompileContext::compile(IonBuilder *builder, MIRGraph *graph,
AutoDestroyAllocator &autoDestroy)
@ -1214,16 +1236,8 @@ SequentialCompileContext::compile(IonBuilder *builder, MIRGraph *graph,
}
builder->clearForBackEnd();
// Try to compile the script off thread, if possible. Compilation cannot be
// performed off thread during an incremental GC, as doing so 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.
if (js_IonOptions.parallelCompilation &&
OffThreadCompilationAvailable(cx) &&
cx->runtime->gcIncrementalState == gc::NO_INCREMENTAL &&
!cx->runtime->profilingScripts)
{
// If possible, compile the script off thread.
if (OffThreadCompilationAvailable(cx)) {
builder->script()->ion = ION_COMPILING_SCRIPT;
if (!StartOffThreadIonCompile(cx, builder)) {
@ -1332,27 +1346,47 @@ CheckScript(UnrootedScript script)
return true;
}
static bool
CheckScriptSize(UnrootedScript script)
static MethodStatus
CheckScriptSize(JSContext *cx, UnrootedScript script)
{
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;
if (script->length > MAX_SCRIPT_SIZE) {
if (script->length > MAX_OFF_THREAD_SCRIPT_SIZE) {
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);
if (numLocalsAndArgs > MAX_LOCALS_AND_ARGS) {
IonSpew(IonSpew_Abort, "Too many locals and arguments (%u)", numLocalsAndArgs);
return false;
return Method_CantCompile;
}
return true;
return Method_Compiled;
}
static MethodStatus
@ -1366,11 +1400,17 @@ Compile(JSContext *cx, HandleScript script, HandleFunction fun, jsbytecode *osrP
return Method_CantCompile;
}
if (!CheckScript(script) || !CheckScriptSize(script)) {
if (!CheckScript(script)) {
IonSpew(IonSpew_Abort, "Aborted compilation of %s:%d", script->filename, script->lineno);
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->method())
return Method_CantCompile;

View File

@ -19,12 +19,6 @@ using mozilla::DebugOnly;
#ifdef JS_PARALLEL_COMPILATION
bool
js::OffThreadCompilationAvailable(JSContext *cx)
{
return cx->runtime->useHelperThreads() && cx->runtime->helperThreadCount() > 0;
}
bool
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 */

View File

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