Move JIT handles in scripts to a separate structure, bug 758613. r=dvander

This commit is contained in:
Brian Hackett 2012-05-25 08:20:33 -07:00
parent c6997d5d56
commit 0c72d188da
11 changed files with 88 additions and 35 deletions

View File

@ -2130,8 +2130,7 @@ TypeCompartment::nukeTypes(FreeOp *fop)
for (gc::CellIter i(compartment, gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
JSScript *script = i.get<JSScript>();
if (script->hasJITCode())
mjit::ReleaseScriptCode(fop, script);
mjit::ReleaseScriptCode(fop, script);
}
#endif /* JS_METHODJIT */

View File

@ -1942,7 +1942,7 @@ void
JSScript::recompileForStepMode(FreeOp *fop)
{
#ifdef JS_METHODJIT
if (hasJITCode()) {
if (hasJITInfo()) {
mjit::Recompiler::clearStackReferences(fop, this);
mjit::ReleaseScriptCode(fop, this);
}
@ -2206,7 +2206,7 @@ JSScript::applySpeculationFailed(JSContext *cx, JSScript *script_)
}
#ifdef JS_METHODJIT
if (script->hasJITCode()) {
if (script->hasJITInfo()) {
mjit::Recompiler::clearStackReferences(cx->runtime->defaultFreeOp(), script);
mjit::ReleaseScriptCode(cx->runtime->defaultFreeOp(), script);
}

View File

@ -379,6 +379,26 @@ struct JSScript : public js::gc::Cell
static void staticAsserts();
};
// All the possible JITScripts that can simultaneously exist for a script.
struct JITScriptSet
{
JITScriptHandle jitHandleNormal; // JIT info for normal scripts
JITScriptHandle jitHandleNormalBarriered; // barriered JIT info for normal scripts
JITScriptHandle jitHandleCtor; // JIT info for constructors
JITScriptHandle jitHandleCtorBarriered; // barriered JIT info for constructors
static size_t jitHandleOffset(bool constructing, bool barriers) {
return constructing
? (barriers
? offsetof(JITScriptSet, jitHandleCtorBarriered)
: offsetof(JITScriptSet, jitHandleCtor))
: (barriers
? offsetof(JITScriptSet, jitHandleNormalBarriered)
: offsetof(JITScriptSet, jitHandleNormal));
}
};
#endif // JS_METHODJIT
//
@ -421,15 +441,11 @@ struct JSScript : public js::gc::Cell
/* Persistent type information retained across GCs. */
js::types::TypeScript *types;
public:
private:
#ifdef JS_METHODJIT
JITScriptHandle jitHandleNormal; // JIT info for normal scripts
JITScriptHandle jitHandleNormalBarriered; // barriered JIT info for normal scripts
JITScriptHandle jitHandleCtor; // JIT info for constructors
JITScriptHandle jitHandleCtorBarriered; // barriered JIT info for constructors
JITScriptSet *jitInfo;
#endif
private:
js::HeapPtrFunction function_;
// 32-bit fields.
@ -449,7 +465,7 @@ struct JSScript : public js::gc::Cell
* or has had backedges taken. Reset if the
* script's JIT code is forcibly discarded. */
#if !defined(JS_METHODJIT) && JS_BITS_PER_WORD == 32
#if JS_BITS_PER_WORD == 32
uint32_t pad32;
#endif
@ -666,27 +682,26 @@ struct JSScript : public js::gc::Cell
// accesses jitHandleNormal/jitHandleCtor, via jitHandleOffset().
friend class js::mjit::CallCompiler;
static size_t jitHandleOffset(bool constructing, bool barriers) {
return constructing
? (barriers ? offsetof(JSScript, jitHandleCtorBarriered) : offsetof(JSScript, jitHandleCtor))
: (barriers ? offsetof(JSScript, jitHandleNormalBarriered) : offsetof(JSScript, jitHandleNormal));
public:
bool hasJITInfo() {
return jitInfo != NULL;
}
public:
bool hasJITCode() {
return jitHandleNormal.isValid()
|| jitHandleNormalBarriered.isValid()
|| jitHandleCtor.isValid()
|| jitHandleCtorBarriered.isValid();
}
static size_t offsetOfJITInfo() { return offsetof(JSScript, jitInfo); }
inline bool ensureHasJITInfo(JSContext *cx);
inline void destroyJITInfo(js::FreeOp *fop);
JITScriptHandle *jitHandle(bool constructing, bool barriers) {
JS_ASSERT(jitInfo);
return constructing
? (barriers ? &jitHandleCtorBarriered : &jitHandleCtor)
: (barriers ? &jitHandleNormalBarriered : &jitHandleNormal);
? (barriers ? &jitInfo->jitHandleCtorBarriered : &jitInfo->jitHandleCtor)
: (barriers ? &jitInfo->jitHandleNormalBarriered : &jitInfo->jitHandleNormal);
}
js::mjit::JITScript *getJIT(bool constructing, bool barriers) {
if (!jitInfo)
return NULL;
JITScriptHandle *jith = jitHandle(constructing, barriers);
return jith->isValid() ? jith->getValid() : NULL;
}

View File

@ -213,6 +213,24 @@ JSScript::clearNesting()
}
}
#ifdef JS_METHODJIT
inline bool
JSScript::ensureHasJITInfo(JSContext *cx)
{
if (jitInfo)
return true;
jitInfo = cx->new_<JITScriptSet>();
return jitInfo != NULL;
}
inline void
JSScript::destroyJITInfo(js::FreeOp *fop)
{
fop->delete_(jitInfo);
jitInfo = NULL;
}
#endif /* JS_METHODJIT */
inline void
JSScript::writeBarrierPre(JSScript *script)
{

View File

@ -111,6 +111,8 @@ mjit::Compiler::compile()
CompileStatus status = performCompilation();
if (status != Compile_Okay && status != Compile_Retry) {
if (!outerScript->ensureHasJITInfo(cx))
return Compile_Error;
JSScript::JITScriptHandle *jith = outerScript->jitHandle(isConstructing, cx->compartment->needsBarrier());
JSScript::ReleaseCode(cx->runtime->defaultFreeOp(), jith);
jith->setUnjittable();
@ -909,9 +911,11 @@ mjit::CanMethodJIT(JSContext *cx, JSScript *script, jsbytecode *pc,
if (!cx->methodJitEnabled)
return Compile_Abort;
JSScript::JITScriptHandle *jith = script->jitHandle(construct, cx->compartment->needsBarrier());
if (jith->isUnjittable())
return Compile_Abort;
if (script->hasJITInfo()) {
JSScript::JITScriptHandle *jith = script->jitHandle(construct, cx->compartment->needsBarrier());
if (jith->isUnjittable())
return Compile_Abort;
}
if (request == CompileRequest_Interpreter &&
!cx->hasRunOption(JSOPTION_METHODJIT_ALWAYS) &&
@ -931,6 +935,11 @@ mjit::CanMethodJIT(JSContext *cx, JSScript *script, jsbytecode *pc,
uint64_t gcNumber = cx->runtime->gcNumber;
if (!script->ensureHasJITInfo(cx))
return Compile_Error;
JSScript::JITScriptHandle *jith = script->jitHandle(construct, cx->compartment->needsBarrier());
JITScript *jit;
if (jith->isEmpty()) {
jit = MakeJITScript(cx, script);

View File

@ -1366,7 +1366,10 @@ JSScript::JITScriptHandle::staticAsserts()
size_t
JSScript::sizeOfJitScripts(JSMallocSizeOfFun mallocSizeOf)
{
size_t n = 0;
if (!hasJITInfo())
return 0;
size_t n = mallocSizeOf(jitInfo);
for (int constructing = 0; constructing <= 1; constructing++) {
for (int barriers = 0; barriers <= 1; barriers++) {
JITScript *jit = getJIT((bool) constructing, (bool) barriers);

View File

@ -872,6 +872,9 @@ CanMethodJIT(JSContext *cx, JSScript *script, jsbytecode *pc,
inline void
ReleaseScriptCode(FreeOp *fop, JSScript *script)
{
if (!script->hasJITInfo())
return;
for (int constructing = 0; constructing <= 1; constructing++) {
for (int barriers = 0; barriers <= 1; barriers++) {
JSScript::JITScriptHandle *jith = script->jitHandle((bool) constructing, (bool) barriers);
@ -879,6 +882,8 @@ ReleaseScriptCode(FreeOp *fop, JSScript *script)
JSScript::ReleaseCode(fop, jith);
}
}
script->destroyJITInfo(fop);
}
// Expand all stack frames inlined by the JIT within a compartment.

View File

@ -571,10 +571,13 @@ class CallCompiler : public BaseCompiler
masm.loadPtr(scriptAddr, t0);
// Test that:
// - script->jitHandle{Ctor,Normal}->value is neither NULL nor UNJITTABLE, and
// - script->jitHandle{Ctor,Normal}->value->arityCheckEntry is not NULL.
//
size_t offset = JSScript::jitHandleOffset(callingNew, f.cx->compartment->needsBarrier());
// - script->jitInfo is not NULL
// - script->jitInfo->jitHandle{Ctor,Normal}->value is neither NULL nor UNJITTABLE, and
// - script->jitInfo->jitHandle{Ctor,Normal}->value->arityCheckEntry is not NULL.
masm.loadPtr(Address(t0, JSScript::offsetOfJITInfo()), t0);
Jump hasNoJitInfo = masm.branchPtr(Assembler::Equal, t0, ImmPtr(NULL));
size_t offset = JSScript::JITScriptSet::jitHandleOffset(callingNew,
f.cx->compartment->needsBarrier());
masm.loadPtr(Address(t0, offset), t0);
Jump hasNoJitCode = masm.branchPtr(Assembler::BelowOrEqual, t0,
ImmPtr(JSScript::JITScriptHandle::UNJITTABLE));
@ -583,6 +586,7 @@ class CallCompiler : public BaseCompiler
Jump hasCode = masm.branchPtr(Assembler::NotEqual, t0, ImmPtr(0));
hasNoJitInfo.linkTo(masm.label(), &masm);
hasNoJitCode.linkTo(masm.label(), &masm);
/*

View File

@ -394,7 +394,7 @@ ClearAllFrames(JSCompartment *compartment)
void
Recompiler::clearStackReferences(FreeOp *fop, JSScript *script)
{
JS_ASSERT(script->hasJITCode());
JS_ASSERT(script->hasJITInfo());
JaegerSpew(JSpew_Recompile, "recompiling script (file \"%s\") (line \"%d\") (length \"%d\")\n",
script->filename, script->lineno, script->length);

View File

@ -231,7 +231,7 @@ void
BreakpointSite::recompile(FreeOp *fop)
{
#ifdef JS_METHODJIT
if (script->hasJITCode()) {
if (script->hasJITInfo()) {
mjit::Recompiler::clearStackReferences(fop, script);
mjit::ReleaseScriptCode(fop, script);
}

View File

@ -336,7 +336,7 @@ GlobalObject::clear(JSContext *cx)
*/
for (gc::CellIter i(cx->compartment, gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
JSScript *script = i.get<JSScript>();
if (script->compileAndGo && script->hasJITCode() && script->hasClearedGlobal()) {
if (script->compileAndGo && script->hasJITInfo() && script->hasClearedGlobal()) {
mjit::Recompiler::clearStackReferences(cx->runtime->defaultFreeOp(), script);
mjit::ReleaseScriptCode(cx->runtime->defaultFreeOp(), script);
}