Bug 823884: Make call uninlineable when aborting during inlining, r=nbp

This commit is contained in:
Hannes Verschore 2012-12-28 21:33:07 +01:00
Родитель e4b89b0500
Коммит b3a11b3d2a
6 изменённых файлов: 54 добавлений и 17 удалений

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

@ -1135,7 +1135,7 @@ AttachFinishedCompilations(JSContext *cx)
static const size_t BUILDER_LIFO_ALLOC_PRIMARY_CHUNK_SIZE = 1 << 12;
template <typename CompileContext>
static bool
static AbortReason
IonCompile(JSContext *cx, HandleScript script, HandleFunction fun, jsbytecode *osrPc, bool constructing,
CompileContext &compileContext)
{
@ -1149,31 +1149,31 @@ IonCompile(JSContext *cx, HandleScript script, HandleFunction fun, jsbytecode *o
LifoAlloc *alloc = cx->new_<LifoAlloc>(BUILDER_LIFO_ALLOC_PRIMARY_CHUNK_SIZE);
if (!alloc)
return false;
return AbortReason_Alloc;
AutoDestroyAllocator autoDestroy(alloc);
TempAllocator *temp = alloc->new_<TempAllocator>(alloc);
if (!temp)
return false;
return AbortReason_Alloc;
IonContext ictx(cx, cx->compartment, temp);
if (!cx->compartment->ensureIonCompartmentExists(cx))
return false;
return AbortReason_Alloc;
MIRGraph *graph = alloc->new_<MIRGraph>(temp);
ExecutionMode executionMode = compileContext.executionMode();
CompileInfo *info = alloc->new_<CompileInfo>(script, fun, osrPc, constructing,
executionMode);
if (!info)
return false;
return AbortReason_Alloc;
types::AutoEnterTypeInference enter(cx, true);
TypeInferenceOracle oracle;
if (!oracle.init(cx, script))
return false;
return AbortReason_Disable;
AutoFlushCache afc("IonCompile");
@ -1185,10 +1185,10 @@ IonCompile(JSContext *cx, HandleScript script, HandleFunction fun, jsbytecode *o
IonBuilder *builder = alloc->new_<IonBuilder>(cx, temp, graph, &oracle, info);
if (!compileContext.compile(builder, graph, autoDestroy)) {
IonSpew(IonSpew_Abort, "IM Compilation failed.");
return false;
return builder->abortReason();
}
return true;
return AbortReason_NoAbort;
}
bool
@ -1245,16 +1245,27 @@ SequentialCompileContext::compile(IonBuilder *builder, MIRGraph *graph,
return success;
}
bool
MethodStatus
TestIonCompile(JSContext *cx, HandleScript script, HandleFunction fun, jsbytecode *osrPc, bool constructing)
{
SequentialCompileContext compileContext;
if (!IonCompile(cx, script, fun, osrPc, constructing, compileContext)) {
AbortReason reason = IonCompile(cx, script, fun, osrPc, constructing, compileContext);
if (reason == AbortReason_Alloc)
return Method_Skipped;
if (reason == AbortReason_Inlining)
return Method_Skipped;
if (reason == AbortReason_Disable) {
if (!cx->isExceptionPending())
ForbidCompilation(cx, script);
return false;
return Method_CantCompile;
}
return true;
JS_ASSERT(reason == AbortReason_NoAbort);
return Method_Compiled;
}
static bool
@ -1370,10 +1381,12 @@ Compile(JSContext *cx, HandleScript script, HandleFunction fun, jsbytecode *osrP
}
SequentialCompileContext compileContext;
if (!IonCompile(cx, script, fun, osrPc, constructing, compileContext))
AbortReason reason = IonCompile(cx, script, fun, osrPc, constructing, compileContext);
if (reason == AbortReason_Disable)
return Method_CantCompile;
// Compilation succeeded, but we invalidated right away.
// Compilation succeeded or we invalidated right away or an inlining/alloc abort
return script->hasIonScript() ? Method_Compiled : Method_Skipped;
}

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

@ -211,6 +211,13 @@ enum MethodStatus
Method_Compiled
};
enum AbortReason {
AbortReason_Alloc,
AbortReason_Inlining,
AbortReason_Disable,
AbortReason_NoAbort
};
// An Ion context is needed to enter into either an Ion method or an instance
// of the Ion compiler. It points to a temporary allocator and the active
// JSContext, either of which may be NULL, and the active compartment, which
@ -296,7 +303,7 @@ class CodeGenerator;
CodeGenerator *CompileBackEnd(MIRGenerator *mir);
void AttachFinishedCompilations(JSContext *cx);
void FinishOffThreadBuilder(IonBuilder *builder);
bool TestIonCompile(JSContext *cx, HandleScript script, HandleFunction fun, jsbytecode *osrPc, bool constructing);
MethodStatus TestIonCompile(JSContext *cx, HandleScript script, HandleFunction fun, jsbytecode *osrPc, bool constructing);
static inline bool IsEnabled(JSContext *cx)
{

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

@ -35,6 +35,7 @@ IonBuilder::IonBuilder(JSContext *cx, TempAllocator *temp, MIRGraph *graph,
backgroundCodegen_(NULL),
recompileInfo(cx->compartment->types.compiledInfo),
cx(cx),
abortReason_(AbortReason_Disable),
loopDepth_(loopDepth),
callerResumePoint_(NULL),
callerBuilder_(NULL),
@ -360,6 +361,7 @@ IonBuilder::build()
return false;
JS_ASSERT(loopDepth_ == 0);
abortReason_ = AbortReason_NoAbort;
return true;
}
@ -3172,8 +3174,16 @@ IonBuilder::jsop_call_inline(HandleFunction callee, uint32_t argc, bool construc
}
// Build the graph.
if (!inlineBuilder.buildInline(this, inlineResumePoint, thisDefn, argv))
if (!inlineBuilder.buildInline(this, inlineResumePoint, thisDefn, argv)) {
JS_ASSERT(calleeScript->hasAnalysis());
// Inlining the callee failed. Disable inlining the function
if (inlineBuilder.abortReason_ == AbortReason_Disable)
calleeScript->analysis()->setIonUninlineable();
abortReason_ = AbortReason_Inlining;
return false;
}
MIRGraphExits &exits = *inlineBuilder.graph().exitAccumulator();

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

@ -492,8 +492,11 @@ class IonBuilder : public MIRGenerator
CodeGenerator *backgroundCodegen() const { return backgroundCodegen_; }
void setBackgroundCodegen(CodeGenerator *codegen) { backgroundCodegen_ = codegen; }
AbortReason abortReason() { return abortReason_; }
private:
JSContext *cx;
AbortReason abortReason_;
jsbytecode *pc;
MBasicBlock *current;

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

@ -888,6 +888,7 @@ class ScriptAnalysis
bool failed() const { return hadFailure; }
bool ionInlineable() const { return isIonInlineable; }
bool ionInlineable(uint32_t argc) const { return isIonInlineable && argc == script_->function()->nargs; }
void setIonUninlineable() { isIonInlineable = false; }
bool jaegerInlineable() const { return isJaegerInlineable; }
bool jaegerInlineable(uint32_t argc) const { return isJaegerInlineable && argc == script_->function()->nargs; }
bool jaegerCompileable() { return isJaegerCompileable; }

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

@ -839,7 +839,10 @@ stubs::TriggerIonCompile(VMFrame &f)
osrPC = NULL;
RootedFunction scriptFunction(f.cx, script->function());
if (!ion::TestIonCompile(f.cx, script, scriptFunction, osrPC, f.fp()->isConstructing())) {
ion::MethodStatus compileStatus =
ion::TestIonCompile(f.cx, script, scriptFunction, osrPC, f.fp()->isConstructing());
if (compileStatus != ion::Method_Compiled) {
if (f.cx->isExceptionPending())
THROW();
}