Bug 858551 part 1 - Make JSScript::{baseline, ion, parallelIon} private. r=djvj

This commit is contained in:
Jan de Mooij 2013-04-09 13:34:49 +02:00
parent c3c36ead25
commit ec0cfe278a
25 changed files with 179 additions and 148 deletions

View File

@ -181,7 +181,7 @@ Zone::discardJitCode(FreeOp *fop, bool discardConstraints)
/* Assert no baseline scripts are marked as active. */
for (CellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) {
JSScript *script = i.get<JSScript>();
JS_ASSERT_IF(script->hasBaselineScript(), !script->baseline->active());
JS_ASSERT_IF(script->hasBaselineScript(), !script->baselineScript()->active());
}
# endif

View File

@ -223,7 +223,7 @@ ConvertFrames(JSContext *cx, IonActivation *activation, IonBailoutIterator &it)
// determine if we have a critical sequence of bailout.
//
// Note: frame conversion only occurs in sequential mode
if (it.script()->ion == it.ionScript()) {
if (it.script()->maybeIonScript() == it.ionScript()) {
IonSpew(IonSpew_Bailouts, " Current script use count is %u",
it.script()->getUseCount());
}
@ -539,8 +539,7 @@ ion::ShapeGuardFailure()
JSContext *cx = GetIonContext()->cx;
RawScript script = GetBailedJSScript(cx);
JS_ASSERT(script->hasIonScript());
JS_ASSERT(!script->ion->invalidated());
JS_ASSERT(!script->ionScript()->invalidated());
script->failedShapeGuard = true;
@ -555,15 +554,14 @@ ion::CachedShapeGuardFailure()
JSContext *cx = GetIonContext()->cx;
RawScript script = GetBailedJSScript(cx);
JS_ASSERT(script->hasIonScript());
JS_ASSERT(!script->ion->invalidated());
JS_ASSERT(!script->ionScript()->invalidated());
script->failedShapeGuard = true;
// Purge JM caches in the script and all inlined script, to avoid baking in
// the same shape guard next time.
for (size_t i = 0; i < script->ion->scriptEntries(); i++)
mjit::PurgeCaches(script->ion->getScript(i));
for (size_t i = 0; i < script->ionScript()->scriptEntries(); i++)
mjit::PurgeCaches(script->ionScript()->getScript(i));
IonSpew(IonSpew_Invalidate, "Invalidating due to shape guard failure");

View File

@ -1106,8 +1106,7 @@ HandleBoundsCheckFailure(JSContext *cx, HandleScript outerScript, HandleScript i
innerScript->filename(), innerScript->lineno,
outerScript->filename(), outerScript->lineno);
JS_ASSERT(outerScript->hasIonScript());
JS_ASSERT(!outerScript->ion->invalidated());
JS_ASSERT(!outerScript->ionScript()->invalidated());
// TODO: Currently this mimic's Ion's handling of this case. Investigate setting
// the flag on innerScript as opposed to outerScript, and maybe invalidating both
@ -1126,8 +1125,7 @@ HandleShapeGuardFailure(JSContext *cx, HandleScript outerScript, HandleScript in
innerScript->filename(), innerScript->lineno,
outerScript->filename(), outerScript->lineno);
JS_ASSERT(outerScript->hasIonScript());
JS_ASSERT(!outerScript->ion->invalidated());
JS_ASSERT(!outerScript->ionScript()->invalidated());
// TODO: Currently this mimic's Ion's handling of this case. Investigate setting
// the flag on innerScript as opposed to outerScript, and maybe invalidating both
@ -1144,8 +1142,7 @@ HandleCachedShapeGuardFailure(JSContext *cx, HandleScript outerScript, HandleScr
innerScript->filename(), innerScript->lineno,
outerScript->filename(), outerScript->lineno);
JS_ASSERT(outerScript->hasIonScript());
JS_ASSERT(!outerScript->ion->invalidated());
JS_ASSERT(!outerScript->ionScript()->invalidated());
outerScript->failedShapeGuard = true;

View File

@ -123,14 +123,15 @@ BaselineCompiler::compile()
pcEntries.length());
if (!baselineScript)
return Method_Error;
script->baseline = baselineScript;
baselineScript->setMethod(code);
script->setBaselineScript(baselineScript);
IonSpew(IonSpew_BaselineScripts, "Created BaselineScript %p (raw %p) for %s:%d",
(void *) script->baseline, (void *) code->raw(),
(void *) script->baselineScript(), (void *) code->raw(),
script->filename(), script->lineno);
script->baseline->setMethod(code);
JS_ASSERT(pcMappingIndexEntries.length() > 0);
baselineScript->copyPCMappingIndexEntries(&pcMappingIndexEntries[0]);
@ -412,7 +413,7 @@ BaselineCompiler::emitUseCountIncrement()
masm.branch32(Assembler::LessThan, countReg, Imm32(minUses), &skipCall);
masm.branchPtr(Assembler::Equal,
Address(scriptReg, offsetof(JSScript, ion)),
Address(scriptReg, JSScript::offsetOfIonScript()),
ImmWord(ION_COMPILING_SCRIPT), &skipCall);
// Call IC.
@ -2412,7 +2413,7 @@ BaselineCompiler::emit_JSOP_ARGUMENTS()
// Load script->baseline.
Register scratch = R1.scratchReg();
masm.movePtr(ImmGCPtr(script), scratch);
masm.loadPtr(Address(scratch, offsetof(JSScript, baseline)), scratch);
masm.loadPtr(Address(scratch, JSScript::offsetOfBaselineScript()), scratch);
// If we don't need an arguments object, skip the VM call.
masm.branchTest32(Assembler::Zero, Address(scratch, BaselineScript::offsetOfFlags()),

View File

@ -157,7 +157,7 @@ BaselineFrame::initForOsr(StackFrame *fp, uint32_t numStackValues)
// debug prologue/epilogue calls).
IonFrameIterator iter(cx->mainThread().ionTop);
JS_ASSERT(iter.returnAddress() == NULL);
BaselineScript *baseline = fp->script()->baseline;
BaselineScript *baseline = fp->script()->baselineScript();
iter.current()->setReturnAddress(baseline->returnAddressForIC(baseline->icEntry(0)));
if (!Debugger::handleBaselineOsr(cx, fp, this))

View File

@ -670,12 +670,11 @@ EnsureCanEnterIon(JSContext *cx, ICUseCount_Fallback *stub, BaselineFrame *frame
if (stat != Method_Compiled) {
// TODO: If stat == Method_CantCompile, insert stub that just skips the useCount
// entirely, instead of resetting it.
if (stat == Method_CantCompile ||
(script->hasIonScript() && script->ion->bailoutExpected()))
{
bool bailoutExpected = script->hasIonScript() && script->ionScript()->bailoutExpected();
if (stat == Method_CantCompile || bailoutExpected) {
IonSpew(IonSpew_BaselineOSR, " Reset UseCount cantCompile=%s bailoutExpected=%s!",
stat == Method_CantCompile ? "yes" : "no",
(script->hasIonScript() && script->ion->bailoutExpected()) ? "yes" : "no");
bailoutExpected ? "yes" : "no");
script->resetUseCount();
}
return true;

View File

@ -60,8 +60,7 @@ class BaselineInspector
}
BaselineScript *baselineScript() const {
JS_ASSERT(hasBaselineScript());
return script->baseline;
return script->baselineScript();
}
private:

View File

@ -174,10 +174,8 @@ EnterBaseline(JSContext *cx, StackFrame *fp, void *jitcode, bool osr)
IonExecStatus
ion::EnterBaselineMethod(JSContext *cx, StackFrame *fp)
{
RootedScript script(cx, fp->script());
BaselineScript *baseline = script->baseline;
IonCode *code = baseline->method();
void *jitcode = code->raw();
BaselineScript *baseline = fp->script()->baselineScript();
void *jitcode = baseline->method()->raw();
return EnterBaseline(cx, fp, jitcode, /* osr = */false);
}
@ -187,9 +185,8 @@ ion::EnterBaselineAtBranch(JSContext *cx, StackFrame *fp, jsbytecode *pc)
{
JS_ASSERT(JSOp(*pc) == JSOP_LOOPENTRY);
RootedScript script(cx, fp->script());
BaselineScript *baseline = script->baseline;
uint8_t *jitcode = baseline->nativeCodeForPC(script, pc);
BaselineScript *baseline = fp->script()->baselineScript();
uint8_t *jitcode = baseline->nativeCodeForPC(fp->script(), pc);
// Skip debug breakpoint/trap handler, the interpreter already handled it
// for the current op.
@ -202,7 +199,8 @@ ion::EnterBaselineAtBranch(JSContext *cx, StackFrame *fp, jsbytecode *pc)
static MethodStatus
BaselineCompile(JSContext *cx, HandleScript script)
{
JS_ASSERT(!script->baseline);
JS_ASSERT(!script->hasBaselineScript());
JS_ASSERT(script->canBaselineCompile());
LifoAlloc alloc(BASELINE_LIFO_ALLOC_PRIMARY_CHUNK_SIZE);
@ -219,11 +217,11 @@ BaselineCompile(JSContext *cx, HandleScript script)
AutoFlushCache afc("BaselineJIT", cx->runtime->ionRuntime());
MethodStatus status = compiler.compile();
JS_ASSERT_IF(status == Method_Compiled, script->baseline);
JS_ASSERT_IF(status != Method_Compiled, !script->baseline);
JS_ASSERT_IF(status == Method_Compiled, script->hasBaselineScript());
JS_ASSERT_IF(status != Method_Compiled, !script->hasBaselineScript());
if (status == Method_CantCompile)
script->baseline = BASELINE_DISABLED_SCRIPT;
script->setBaselineScript(BASELINE_DISABLED_SCRIPT);
return status;
}
@ -235,7 +233,7 @@ ion::CanEnterBaselineJIT(JSContext *cx, JSScript *scriptArg, StackFrame *fp, boo
JS_ASSERT(ion::IsBaselineEnabled(cx));
// Skip if the script has been disabled.
if (scriptArg->baseline == BASELINE_DISABLED_SCRIPT)
if (!scriptArg->canBaselineCompile())
return Method_Skipped;
if (scriptArg->length > BaselineScript::MAX_JSSCRIPT_LENGTH)
@ -272,7 +270,7 @@ ion::CanEnterBaselineJIT(JSContext *cx, JSScript *scriptArg, StackFrame *fp, boo
RootedScript original(cx, script->originalFunction()->nonLazyScript());
JS_ASSERT(original != script);
if (original->baseline == BASELINE_DISABLED_SCRIPT)
if (!original->canBaselineCompile())
return Method_CantCompile;
if (!original->hasBaselineScript()) {
@ -530,7 +528,7 @@ BaselineScript::copyPCMappingIndexEntries(const PCMappingIndexEntry *entries)
uint8_t *
BaselineScript::nativeCodeForPC(JSScript *script, jsbytecode *pc, PCMappingSlotInfo *slotInfo)
{
JS_ASSERT(script->baseline == this);
JS_ASSERT(script->baselineScript() == this);
JS_ASSERT(pc >= script->code);
JS_ASSERT(pc < script->code + script->length);
@ -581,7 +579,7 @@ BaselineScript::nativeCodeForPC(JSScript *script, jsbytecode *pc, PCMappingSlotI
void
BaselineScript::toggleDebugTraps(RawScript script, jsbytecode *pc)
{
JS_ASSERT(script->baseline == this);
JS_ASSERT(script->baselineScript() == this);
SrcNoteLineScanner scanner(script->notes(), script->lineno);
@ -704,19 +702,19 @@ ion::FinishDiscardBaselineScript(FreeOp *fop, RawScript script)
if (!script->hasBaselineScript())
return;
if (script->baseline->active()) {
if (script->baselineScript()->active()) {
// Script is live on the stack. Keep the BaselineScript, but destroy
// stubs allocated in the optimized stub space.
script->baseline->purgeOptimizedStubs(script->zone());
script->baselineScript()->purgeOptimizedStubs(script->zone());
// Reset |active| flag so that we don't need a separate script
// iteration to unmark them.
script->baseline->resetActive();
script->baselineScript()->resetActive();
return;
}
BaselineScript::Destroy(fop, script->baseline);
script->baseline = NULL;
BaselineScript::Destroy(fop, script->baselineScript());
script->setBaselineScript(NULL);
}
void
@ -736,7 +734,7 @@ ion::SizeOfBaselineData(JSScript *script, JSMallocSizeOfFun mallocSizeOf, size_t
*fallbackStubs = 0;
if (script->hasBaselineScript())
script->baseline->sizeOfIncludingThis(mallocSizeOf, data, fallbackStubs);
script->baselineScript()->sizeOfIncludingThis(mallocSizeOf, data, fallbackStubs);
}
void

View File

@ -4533,6 +4533,9 @@ CodeGenerator::link()
cacheList_.length(), runtimeData_.length(),
safepoints_.size(), graph.mir().numScripts(),
executionMode == ParallelExecution ? ForkJoinSlices(cx) : 0);
ionScript->setMethod(code);
SetIonScript(script, executionMode, ionScript);
if (!ionScript)
@ -4551,7 +4554,6 @@ CodeGenerator::link()
ptrdiff_t real_invalidate = masm.actualOffset(invalidate_.offset());
ionScript->setInvalidationEpilogueOffset(real_invalidate);
ionScript->setMethod(code);
ionScript->setDeoptTable(deoptTable_);
// for generating inline caches during the execution.

View File

@ -11,7 +11,8 @@
namespace js {
namespace ion {
static inline bool HasIonScript(RawScript script, ExecutionMode cmode)
static inline bool
HasIonScript(RawScript script, ExecutionMode cmode)
{
switch (cmode) {
case SequentialExecution: return script->hasIonScript();
@ -21,35 +22,39 @@ static inline bool HasIonScript(RawScript script, ExecutionMode cmode)
return false;
}
static inline IonScript *GetIonScript(RawScript script, ExecutionMode cmode)
static inline IonScript *
GetIonScript(RawScript script, ExecutionMode cmode)
{
switch (cmode) {
case SequentialExecution: return script->ion;
case ParallelExecution: return script->parallelIon;
case SequentialExecution: return script->maybeIonScript();
case ParallelExecution: return script->maybeParallelIonScript();
}
JS_NOT_REACHED("No such execution mode");
return NULL;
}
static inline void SetIonScript(RawScript script, ExecutionMode cmode, IonScript *ionScript)
static inline void
SetIonScript(RawScript script, ExecutionMode cmode, IonScript *ionScript)
{
switch (cmode) {
case SequentialExecution: script->ion = ionScript; return;
case ParallelExecution: script->parallelIon = ionScript; return;
case SequentialExecution: script->setIonScript(ionScript); return;
case ParallelExecution: script->setParallelIonScript(ionScript); return;
}
JS_NOT_REACHED("No such execution mode");
}
static inline size_t OffsetOfIonInJSScript(ExecutionMode cmode)
static inline size_t
OffsetOfIonInJSScript(ExecutionMode cmode)
{
switch (cmode) {
case SequentialExecution: return offsetof(JSScript, ion);
case ParallelExecution: return offsetof(JSScript, parallelIon);
case SequentialExecution: return JSScript::offsetOfIonScript();
case ParallelExecution: return JSScript::offsetOfParallelIonScript();
}
JS_NOT_REACHED("No such execution mode");
}
static inline bool CanIonCompile(RawScript script, ExecutionMode cmode)
static inline bool
CanIonCompile(RawScript script, ExecutionMode cmode)
{
switch (cmode) {
case SequentialExecution: return script->canIonCompile();
@ -59,12 +64,14 @@ static inline bool CanIonCompile(RawScript script, ExecutionMode cmode)
return false;
}
static inline bool CanIonCompile(RawFunction fun, ExecutionMode cmode)
static inline bool
CanIonCompile(RawFunction fun, ExecutionMode cmode)
{
return fun->isInterpreted() && CanIonCompile(fun->nonLazyScript(), cmode);
}
static inline bool CompilingOffThread(RawScript script, ExecutionMode cmode)
static inline bool
CompilingOffThread(RawScript script, ExecutionMode cmode)
{
switch (cmode) {
case SequentialExecution: return script->isIonCompilingOffThread();
@ -74,7 +81,8 @@ static inline bool CompilingOffThread(RawScript script, ExecutionMode cmode)
return false;
}
static inline bool CompilingOffThread(HandleScript script, ExecutionMode cmode)
static inline bool
CompilingOffThread(HandleScript script, ExecutionMode cmode)
{
switch (cmode) {
case SequentialExecution: return script->isIonCompilingOffThread();
@ -84,16 +92,8 @@ static inline bool CompilingOffThread(HandleScript script, ExecutionMode cmode)
return false;
}
static inline bool Disabled(RawScript script, ExecutionMode cmode) {
switch (cmode) {
case SequentialExecution: return script->isIonCompilingOffThread();
case ParallelExecution: return script->isParallelIonCompilingOffThread();
}
JS_NOT_REACHED("No such execution mode");
return false;
}
static inline types::CompilerOutput::Kind CompilerOutputKind(ExecutionMode cmode)
static inline types::CompilerOutput::Kind
CompilerOutputKind(ExecutionMode cmode)
{
switch (cmode) {
case SequentialExecution: return types::CompilerOutput::Ion;

View File

@ -310,7 +310,7 @@ ion::FinishOffThreadBuilder(IonBuilder *builder)
if (builder->script()->isIonCompilingOffThread()) {
types::TypeCompartment &types = builder->script()->compartment()->types;
builder->recompileInfo.compilerOutput(types)->invalidate();
builder->script()->ion = NULL;
builder->script()->setIonScript(NULL);
}
// The builder is allocated into its LifoAlloc, so destroying that will
@ -873,9 +873,9 @@ ion::ToggleBarriers(JS::Zone *zone, bool needs)
for (gc::CellIterUnderGC i(zone, gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
RawScript script = i.get<JSScript>();
if (script->hasIonScript())
script->ion->toggleBarriers(needs);
script->ionScript()->toggleBarriers(needs);
if (script->hasBaselineScript())
script->baseline->toggleBarriers(needs);
script->baselineScript()->toggleBarriers(needs);
}
for (CompartmentsInZoneIter comp(zone); !comp.done(); comp.next()) {
@ -1366,9 +1366,10 @@ AbortReason
SequentialCompileContext::compile(IonBuilder *builder, MIRGraph *graph,
ScopedJSDeletePtr<LifoAlloc> &autoDelete)
{
JS_ASSERT(!builder->script()->ion);
JSContext *cx = GetIonContext()->cx;
JS_ASSERT(!builder->script()->hasIonScript());
JS_ASSERT(builder->script()->canIonCompile());
JSContext *cx = GetIonContext()->cx;
RootedScript builderScript(cx, builder->script());
IonSpewNewFunction(graph, builderScript);
@ -1380,7 +1381,7 @@ SequentialCompileContext::compile(IonBuilder *builder, MIRGraph *graph,
// If possible, compile the script off thread.
if (OffThreadCompilationAvailable(cx)) {
builder->script()->ion = ION_COMPILING_SCRIPT;
builder->script()->setIonScript(ION_COMPILING_SCRIPT);
if (!StartOffThreadIonCompile(cx, builder)) {
IonSpew(IonSpew_Abort, "Unable to start off-thread ion compilation.");
@ -1586,15 +1587,15 @@ ion::CanEnterAtBranch(JSContext *cx, JSScript *script, AbstractFramePtr fp,
JS_ASSERT((JSOp)*pc == JSOP_LOOPENTRY);
// Skip if the script has been disabled.
if (script->ion == ION_DISABLED_SCRIPT)
if (!script->canIonCompile())
return Method_Skipped;
// Skip if the script is being compiled off thread.
if (script->ion == ION_COMPILING_SCRIPT)
if (script->isIonCompilingOffThread())
return Method_Skipped;
// Skip if the code is expected to result in a bailout.
if (script->ion && script->ion->bailoutExpected())
if (script->hasIonScript() && script->ionScript()->bailoutExpected())
return Method_Skipped;
// Optionally ignore on user request.
@ -1618,7 +1619,7 @@ ion::CanEnterAtBranch(JSContext *cx, JSScript *script, AbstractFramePtr fp,
return status;
}
if (script->ion && script->ion->osrPc() != pc)
if (script->hasIonScript() && script->ionScript()->osrPc() != pc)
return Method_Skipped;
return Method_Compiled;
@ -1630,15 +1631,15 @@ ion::CanEnter(JSContext *cx, JSScript *script, AbstractFramePtr fp, bool isConst
JS_ASSERT(ion::IsEnabled(cx));
// Skip if the script has been disabled.
if (script->ion == ION_DISABLED_SCRIPT)
if (!script->canIonCompile())
return Method_Skipped;
// Skip if the script is being compiled off thread.
if (script->ion == ION_COMPILING_SCRIPT)
if (script->isIonCompilingOffThread())
return Method_Skipped;
// Skip if the code is expected to result in a bailout.
if (script->ion && script->ion->bailoutExpected())
if (script->hasIonScript() && script->ionScript()->bailoutExpected())
return Method_Skipped;
// If constructing, allocate a new |this| object before building Ion.
@ -1798,7 +1799,8 @@ ParallelCompileContext::compile(IonBuilder *builder,
MIRGraph *graph,
ScopedJSDeletePtr<LifoAlloc> &autoDelete)
{
JS_ASSERT(!builder->script()->parallelIon);
JS_ASSERT(!builder->script()->hasParallelIonScript());
JS_ASSERT(builder->script()->canParallelIonCompile());
RootedScript builderScript(cx_, builder->script());
IonSpewNewFunction(graph, builderScript);
@ -1844,7 +1846,7 @@ ion::CanEnterUsingFastInvoke(JSContext *cx, HandleScript script, uint32_t numAct
JS_ASSERT(ion::IsEnabled(cx));
// Skip if the code is expected to result in a bailout.
if (!script->hasIonScript() || script->ion->bailoutExpected())
if (!script->hasIonScript() || script->ionScript()->bailoutExpected())
return Method_Skipped;
// Don't handle arguments underflow, to make this work we would have to pad
@ -1859,7 +1861,7 @@ ion::CanEnterUsingFastInvoke(JSContext *cx, HandleScript script, uint32_t numAct
if (!cx->compartment->ionCompartment()->enterJIT())
return Method_Error;
if (!script->ion)
if (!script->hasIonScript())
return Method_Skipped;
return Method_Compiled;
@ -1871,7 +1873,7 @@ EnterIon(JSContext *cx, StackFrame *fp, void *jitcode)
JS_CHECK_RECURSION(cx, return IonExec_Aborted);
JS_ASSERT(ion::IsEnabled(cx));
JS_ASSERT(CheckFrame(fp));
JS_ASSERT(!fp->script()->ion->bailoutExpected());
JS_ASSERT(!fp->script()->ionScript()->bailoutExpected());
EnterIonCode enter = cx->compartment->ionCompartment()->enterJIT();
@ -1954,7 +1956,7 @@ IonExecStatus
ion::Cannon(JSContext *cx, StackFrame *fp)
{
RootedScript script(cx, fp->script());
IonScript *ion = script->ion;
IonScript *ion = script->ionScript();
IonCode *code = ion->method();
void *jitcode = code->raw();
@ -1985,7 +1987,7 @@ IonExecStatus
ion::SideCannon(JSContext *cx, StackFrame *fp, jsbytecode *pc)
{
RootedScript script(cx, fp->script());
IonScript *ion = script->ion;
IonScript *ion = script->ionScript();
IonCode *code = ion->method();
void *osrcode = code->raw() + ion->osrEntryOffset();
@ -2132,10 +2134,10 @@ InvalidateActivation(FreeOp *fop, uint8_t *ionTop, bool invalidateAll)
if (!script->hasIonScript())
continue;
if (!invalidateAll && !script->ion->invalidated())
if (!invalidateAll && !script->ionScript()->invalidated())
continue;
IonScript *ionScript = script->ion;
IonScript *ionScript = script->ionScript();
// Purge ICs before we mark this script as invalidated. This will
// prevent lastJump_ from appearing to be a bogus pointer, just
@ -2343,29 +2345,33 @@ ion::Invalidate(JSContext *cx, RawScript script, bool resetUses)
}
static void
FinishInvalidationOf(FreeOp *fop, RawScript script, IonScript **ionField)
FinishInvalidationOf(FreeOp *fop, RawScript script, IonScript *ionScript, bool parallel)
{
// If this script has Ion code on the stack, invalidation() will return
// true. In this case we have to wait until destroying it.
if (!(*ionField)->invalidated()) {
if (!ionScript->invalidated()) {
types::TypeCompartment &types = script->compartment()->types;
(*ionField)->recompileInfo().compilerOutput(types)->invalidate();
ionScript->recompileInfo().compilerOutput(types)->invalidate();
ion::IonScript::Destroy(fop, *ionField);
ion::IonScript::Destroy(fop, ionScript);
}
// In all cases, NULL out script->ion to avoid re-entry.
*ionField = NULL;
// In all cases, NULL out script->ion or script->parallelIon to avoid
// re-entry.
if (parallel)
script->setParallelIonScript(NULL);
else
script->setIonScript(NULL);
}
void
ion::FinishInvalidation(FreeOp *fop, RawScript script)
{
if (script->hasIonScript())
FinishInvalidationOf(fop, script, &script->ion);
FinishInvalidationOf(fop, script, script->ionScript(), false);
if (script->hasParallelIonScript())
FinishInvalidationOf(fop, script, &script->parallelIon);
FinishInvalidationOf(fop, script, script->parallelIonScript(), true);
}
void
@ -2406,7 +2412,7 @@ ion::ForbidCompilation(JSContext *cx, RawScript script, ExecutionMode mode)
return;
}
script->ion = ION_DISABLED_SCRIPT;
script->setIonScript(ION_DISABLED_SCRIPT);
return;
case ParallelExecution:
@ -2415,7 +2421,7 @@ ion::ForbidCompilation(JSContext *cx, RawScript script, ExecutionMode mode)
return;
}
script->parallelIon = ION_DISABLED_SCRIPT;
script->setParallelIonScript(ION_DISABLED_SCRIPT);
return;
}
@ -2504,10 +2510,10 @@ void
ion::PurgeCaches(RawScript script, Zone *zone)
{
if (script->hasIonScript())
script->ion->purgeCaches(zone);
script->ionScript()->purgeCaches(zone);
if (script->hasParallelIonScript())
script->parallelIon->purgeCaches(zone);
script->parallelIonScript()->purgeCaches(zone);
}
size_t
@ -2516,10 +2522,10 @@ ion::SizeOfIonData(RawScript script, JSMallocSizeOfFun mallocSizeOf)
size_t result = 0;
if (script->hasIonScript())
result += script->ion->sizeOfIncludingThis(mallocSizeOf);
result += script->ionScript()->sizeOfIncludingThis(mallocSizeOf);
if (script->hasParallelIonScript())
result += script->parallelIon->sizeOfIncludingThis(mallocSizeOf);
result += script->parallelIonScript()->sizeOfIncludingThis(mallocSizeOf);
return result;
}
@ -2528,24 +2534,24 @@ void
ion::DestroyIonScripts(FreeOp *fop, RawScript script)
{
if (script->hasIonScript())
ion::IonScript::Destroy(fop, script->ion);
ion::IonScript::Destroy(fop, script->ionScript());
if (script->hasParallelIonScript())
ion::IonScript::Destroy(fop, script->parallelIon);
ion::IonScript::Destroy(fop, script->parallelIonScript());
if (script->hasBaselineScript())
ion::BaselineScript::Destroy(fop, script->baseline);
ion::BaselineScript::Destroy(fop, script->baselineScript());
}
void
ion::TraceIonScripts(JSTracer* trc, RawScript script)
{
if (script->hasIonScript())
ion::IonScript::Trace(trc, script->ion);
ion::IonScript::Trace(trc, script->ionScript());
if (script->hasParallelIonScript())
ion::IonScript::Trace(trc, script->parallelIon);
ion::IonScript::Trace(trc, script->parallelIonScript());
if (script->hasBaselineScript())
ion::BaselineScript::Trace(trc, script->baseline);
ion::BaselineScript::Trace(trc, script->baselineScript());
}

View File

@ -1581,7 +1581,7 @@ SetPropertyIC::update(JSContext *cx, size_t cacheIndex, HandleObject obj,
void *returnAddr;
const SafepointIndex *safepointIndex;
RootedScript script(cx, GetTopIonJSScript(cx, &safepointIndex, &returnAddr));
IonScript *ion = script->ion;
IonScript *ion = script->ionScript();
SetPropertyIC &cache = ion->getCache(cacheIndex).toSetProperty();
RootedPropertyName name(cx, cache.name());
RootedId id(cx, AtomToId(name));

View File

@ -61,9 +61,8 @@ IonFrameIterator::checkInvalidation(IonScript **ionScriptOut) const
RawScript script = this->script();
// N.B. the current IonScript is not the same as the frame's
// IonScript if the frame has since been invalidated.
IonScript *currentIonScript = script->ion;
bool invalidated = !script->hasIonScript() ||
!currentIonScript->containsReturnAddress(returnAddr);
!script->ionScript()->containsReturnAddress(returnAddr);
if (!invalidated)
return false;
@ -180,7 +179,7 @@ IonFrameIterator::baselineScriptAndPc(JSScript **scriptRes, jsbytecode **pcRes)
*scriptRes = script;
uint8_t *retAddr = returnAddressToFp();
if (pcRes)
*pcRes = script->baseline->icEntryFromReturnAddress(retAddr).pc(script);
*pcRes = script->baselineScript()->icEntryFromReturnAddress(retAddr).pc(script);
}
Value *
@ -389,7 +388,7 @@ HandleException(JSContext *cx, const IonFrameIterator &frame, ResumeFromExceptio
// Resume at the start of the catch block.
rfe->kind = ResumeFromException::RESUME_CATCH;
jsbytecode *catchPC = script->main() + tn->start + tn->length;
rfe->target = script->baseline->nativeCodeForPC(script, catchPC);
rfe->target = script->baselineScript()->nativeCodeForPC(script, catchPC);
return;
}
break;
@ -639,9 +638,9 @@ MarkIonJSFrame(JSTracer *trc, const IonFrameIterator &frame)
// is now NULL or recompiled). Manually trace it here.
IonScript::Trace(trc, ionScript);
} else if (CalleeTokenIsFunction(layout->calleeToken())) {
ionScript = CalleeTokenToFunction(layout->calleeToken())->nonLazyScript()->ion;
ionScript = CalleeTokenToFunction(layout->calleeToken())->nonLazyScript()->ionScript();
} else {
ionScript = CalleeTokenToScript(layout->calleeToken())->ion;
ionScript = CalleeTokenToScript(layout->calleeToken())->ionScript();
}
if (CalleeTokenIsFunction(layout->calleeToken()))

View File

@ -662,7 +662,7 @@ MacroAssembler::performOsr()
const Register ionScript = regs.takeAny();
const Register osrEntry = regs.takeAny();
loadPtr(Address(script, offsetof(JSScript, ion)), ionScript);
loadPtr(Address(script, JSScript::offsetOfIonScript()), ionScript);
load32(Address(ionScript, IonScript::offsetOfOsrEntryOffset()), osrEntry);
// Get ionScript->method->code, and scoot to the osrEntry.
@ -935,7 +935,7 @@ MacroAssembler::loadBaselineOrIonCode(Register script, Register scratch, Label *
bool baselineEnabled = ion::IsBaselineEnabled(GetIonContext()->cx);
Label noIonScript, done;
Address scriptIon(script, offsetof(JSScript, ion));
Address scriptIon(script, JSScript::offsetOfIonScript());
branchPtr(Assembler::BelowOrEqual, scriptIon, ImmWord(ION_COMPILING_SCRIPT),
&noIonScript);
{
@ -956,7 +956,7 @@ MacroAssembler::loadBaselineOrIonCode(Register script, Register scratch, Label *
// The script does not have an IonScript. If |failure| is NULL,
// assume the script has a baseline script.
if (baselineEnabled) {
loadPtr(Address(script, offsetof(JSScript, baseline)), script);
loadPtr(Address(script, JSScript::offsetOfBaselineScript()), script);
if (failure)
branchPtr(Assembler::BelowOrEqual, script, ImmWord(BASELINE_DISABLED_SCRIPT), failure);
loadPtr(Address(script, BaselineScript::offsetOfMethod()), script);

View File

@ -306,14 +306,14 @@ ParallelCompileContext::appendToWorklist(HandleFunction fun)
}
// Skip if we're compiling off thread.
if (script->parallelIon == ION_COMPILING_SCRIPT) {
if (script->isParallelIonCompilingOffThread()) {
Spew(SpewCompile, "Skipping %p:%s:%u, off-main-thread compilation in progress",
fun.get(), script->filename(), script->lineno);
return true;
}
// Skip if the code is expected to result in a bailout.
if (script->parallelIon && script->parallelIon->bailoutExpected()) {
if (script->hasParallelIonScript() && script->parallelIonScript()->bailoutExpected()) {
Spew(SpewCompile, "Skipping %p:%s:%u, bailout expected",
fun.get(), script->filename(), script->lineno);
return true;

View File

@ -76,7 +76,7 @@ InvokeFunction(JSContext *cx, HandleFunction fun0, uint32_t argc, Value *argv, V
if (cx->methodJitEnabled && !fun->nonLazyScript()->canIonCompile()) {
RawScript script = GetTopIonJSScript(cx);
if (script->hasIonScript() &&
++script->ion->slowCallCount >= js_IonOptions.slowCallLimit)
++script->ionScript()->slowCallCount >= js_IonOptions.slowCallLimit)
{
AutoFlushCache afc("InvokeFunction");
@ -678,8 +678,8 @@ HandleDebugTrap(JSContext *cx, BaselineFrame *frame, uint8_t *retAddr, JSBool *m
{
*mustReturn = false;
RootedScript script(cx, GetTopIonJSScript(cx));
jsbytecode *pc = script->baseline->icEntryFromReturnAddress(retAddr).pc(script);
RootedScript script(cx, frame->script());
jsbytecode *pc = script->baselineScript()->icEntryFromReturnAddress(retAddr).pc(script);
JS_ASSERT(cx->compartment->debugMode());
JS_ASSERT(script->stepModeEnabled() || script->hasBreakpointsAt(pc));

View File

@ -420,7 +420,7 @@ class AutoDetectInvalidation
public:
AutoDetectInvalidation(JSContext *cx, Value *rval, IonScript *ionScript = NULL)
: cx_(cx),
ionScript_(ionScript ? ionScript : GetTopIonJSScript(cx)->ion),
ionScript_(ionScript ? ionScript : GetTopIonJSScript(cx)->ionScript()),
rval_(rval),
disabled_(false)
{ }

View File

@ -124,7 +124,7 @@ IonBailoutIterator::IonBailoutIterator(const IonActivationIterator &activations,
current_ = fp;
type_ = IonFrame_OptimizedJS;
topFrameSize_ = current_ - sp;
topIonScript_ = script()->ion;
topIonScript_ = script()->ionScript();
if (bailout->frameClass() == FrameSizeClass::None()) {
snapshotOffset_ = bailout->snapshotOffset();

View File

@ -61,7 +61,7 @@ IonBailoutIterator::IonBailoutIterator(const IonActivationIterator &activations,
current_ = fp;
type_ = IonFrame_OptimizedJS;
topFrameSize_ = current_ - sp;
topIonScript_ = script()->ion;
topIonScript_ = script()->ionScript();
snapshotOffset_ = bailout->snapshotOffset();
}

View File

@ -77,7 +77,7 @@ IonBailoutIterator::IonBailoutIterator(const IonActivationIterator &activations,
current_ = fp;
type_ = IonFrame_OptimizedJS;
topFrameSize_ = current_ - sp;
topIonScript_ = script()->ion;
topIonScript_ = script()->ionScript();
if (bailout->frameClass() == FrameSizeClass::None()) {
snapshotOffset_ = bailout->snapshotOffset();

View File

@ -4821,7 +4821,7 @@ js::ReleaseAllJITCode(FreeOp *fop)
/* Assert no baseline scripts are marked as active. */
for (CellIter i(zone, FINALIZE_SCRIPT); !i.done(); i.next()) {
JSScript *script = i.get<JSScript>();
JS_ASSERT_IF(script->hasBaselineScript(), !script->baseline->active());
JS_ASSERT_IF(script->hasBaselineScript(), !script->baselineScript()->active());
}
# endif

View File

@ -151,7 +151,7 @@ CompilerOutput::isValid() const
case Ion:
#ifdef JS_ION
if (script->hasIonScript()) {
JS_ASSERT(this == script->ion->recompileInfo().compilerOutput(types));
JS_ASSERT(this == script->ionScript()->recompileInfo().compilerOutput(types));
return true;
}
if (script->isIonCompilingOffThread())

View File

@ -588,9 +588,15 @@ class JSScript : public js::gc::Cell
return hasIonScript() || hasParallelIonScript();
}
/* Information attached by Ion: script for sequential mode execution */
private:
/* Information attached by Baseline/Ion for sequential mode execution. */
js::ion::IonScript *ion;
js::ion::BaselineScript *baseline;
/* Information attached by Ion for parallel mode execution */
js::ion::IonScript *parallelIon;
public:
bool hasIonScript() const {
return ion && ion != ION_DISABLED_SCRIPT && ion != ION_COMPILING_SCRIPT;
}
@ -606,23 +612,32 @@ class JSScript : public js::gc::Cell
JS_ASSERT(hasIonScript());
return ion;
}
/* Information attached by the baseline compiler. */
js::ion::BaselineScript *baseline;
js::ion::IonScript *maybeIonScript() const {
return ion;
}
js::ion::IonScript *const *addressOfIonScript() const {
return &ion;
}
void setIonScript(js::ion::IonScript *ionScript) {
ion = ionScript;
}
bool hasBaselineScript() const {
return baseline && baseline != BASELINE_DISABLED_SCRIPT;
}
bool canBaselineCompile() const {
return baseline != BASELINE_DISABLED_SCRIPT;
}
js::ion::BaselineScript *baselineScript() const {
JS_ASSERT(hasBaselineScript());
return baseline;
}
void setBaselineScript(js::ion::BaselineScript *baselineScript) {
baseline = baselineScript;
}
uint32_t padding0;
/* Information attached by Ion: script for parallel mode execution */
js::ion::IonScript *parallelIon;
bool hasParallelIonScript() const {
return parallelIon && parallelIon != ION_DISABLED_SCRIPT && parallelIon != ION_COMPILING_SCRIPT;
}
@ -639,6 +654,22 @@ class JSScript : public js::gc::Cell
JS_ASSERT(hasParallelIonScript());
return parallelIon;
}
js::ion::IonScript *maybeParallelIonScript() const {
return parallelIon;
}
void setParallelIonScript(js::ion::IonScript *ionScript) {
parallelIon = ionScript;
}
static size_t offsetOfBaselineScript() {
return offsetof(JSScript, baseline);
}
static size_t offsetOfIonScript() {
return offsetof(JSScript, ion);
}
static size_t offsetOfParallelIonScript() {
return offsetof(JSScript, parallelIon);
}
/*
* Original compiled function for the script, if it has a function.

View File

@ -960,7 +960,7 @@ IonGetsFirstChance(JSContext *cx, JSScript *script, jsbytecode *pc, CompileReque
return false;
// If we cannot enter Ion because bailouts are expected, let JM take over.
if (script->hasIonScript() && script->ion->bailoutExpected())
if (script->hasIonScript() && script->ionScript()->bailoutExpected())
return false;
// If we cannot enter Ion because it was compiled for OSR at a different PC,
@ -976,7 +976,7 @@ IonGetsFirstChance(JSContext *cx, JSScript *script, jsbytecode *pc, CompileReque
// If ion compilation is pending or in progress on another thread, continue
// using JM until that compilation finishes.
if (script->ion == ION_COMPILING_SCRIPT)
if (script->isIonCompilingOffThread())
return false;
return true;
@ -4024,7 +4024,7 @@ mjit::Compiler::ionCompileHelper()
if (!recompileCheckForIon)
return;
void *ionScriptAddress = &script_->ion;
const void *ionScriptAddress = script_->addressOfIonScript();
#ifdef JS_CPU_X64
// Allocate a temp register. Note that we have to do this before calling
@ -4055,7 +4055,8 @@ mjit::Compiler::ionCompileHelper()
trigger.inlineJump = masm.branch32(Assembler::GreaterThanOrEqual,
AbsoluteAddress(useCountAddress),
Imm32(minUses));
Jump scriptJump = stubcc.masm.branch32(Assembler::Equal, AbsoluteAddress(ionScriptAddress),
Jump scriptJump = stubcc.masm.branch32(Assembler::Equal,
AbsoluteAddress((void *)ionScriptAddress),
Imm32(0));
#elif defined(JS_CPU_X64)
/* Handle processors that can't load from absolute addresses. */
@ -4063,7 +4064,7 @@ mjit::Compiler::ionCompileHelper()
trigger.inlineJump = masm.branch32(Assembler::GreaterThanOrEqual,
Address(reg),
Imm32(minUses));
stubcc.masm.move(ImmPtr(ionScriptAddress), reg);
stubcc.masm.move(ImmPtr((void *)ionScriptAddress), reg);
Jump scriptJump = stubcc.masm.branchPtr(Assembler::Equal, Address(reg), ImmPtr(NULL));
frame.freeReg(reg);
#else

View File

@ -247,7 +247,7 @@ BreakpointSite::recompile(FreeOp *fop)
#ifdef JS_ION
if (script->hasBaselineScript())
script->baseline->toggleDebugTraps(script, pc);
script->baselineScript()->toggleDebugTraps(script, pc);
#endif
}