mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 23:31:56 +00:00
Bug 1103056 - Make optimized asm.js FFI exit also work with Baseline scripts. r=luke,h4writer
This commit is contained in:
parent
e2095db058
commit
7ba80f9531
@ -79,7 +79,7 @@ AsmJSFrameIterator::settle()
|
||||
fp_ = nullptr;
|
||||
MOZ_ASSERT(done());
|
||||
break;
|
||||
case AsmJSModule::CodeRange::IonFFI:
|
||||
case AsmJSModule::CodeRange::JitFFI:
|
||||
case AsmJSModule::CodeRange::SlowFFI:
|
||||
case AsmJSModule::CodeRange::Interrupt:
|
||||
case AsmJSModule::CodeRange::Inline:
|
||||
@ -458,7 +458,7 @@ AsmJSProfilingFrameIterator::initFromFP(const AsmJSActivation &activation)
|
||||
callerFP_ = CallerFPFromFP(fp);
|
||||
AssertMatchesCallSite(*module_, codeRange, callerPC_, callerFP_, fp);
|
||||
break;
|
||||
case AsmJSModule::CodeRange::IonFFI:
|
||||
case AsmJSModule::CodeRange::JitFFI:
|
||||
case AsmJSModule::CodeRange::SlowFFI:
|
||||
case AsmJSModule::CodeRange::Interrupt:
|
||||
case AsmJSModule::CodeRange::Inline:
|
||||
@ -513,7 +513,7 @@ AsmJSProfilingFrameIterator::AsmJSProfilingFrameIterator(const AsmJSActivation &
|
||||
const AsmJSModule::CodeRange *codeRange = module_->lookupCodeRange(state.pc);
|
||||
switch (codeRange->kind()) {
|
||||
case AsmJSModule::CodeRange::Function:
|
||||
case AsmJSModule::CodeRange::IonFFI:
|
||||
case AsmJSModule::CodeRange::JitFFI:
|
||||
case AsmJSModule::CodeRange::SlowFFI:
|
||||
case AsmJSModule::CodeRange::Interrupt:
|
||||
case AsmJSModule::CodeRange::Thunk: {
|
||||
@ -615,7 +615,7 @@ AsmJSProfilingFrameIterator::operator++()
|
||||
callerPC_ = nullptr;
|
||||
break;
|
||||
case AsmJSModule::CodeRange::Function:
|
||||
case AsmJSModule::CodeRange::IonFFI:
|
||||
case AsmJSModule::CodeRange::JitFFI:
|
||||
case AsmJSModule::CodeRange::SlowFFI:
|
||||
case AsmJSModule::CodeRange::Interrupt:
|
||||
case AsmJSModule::CodeRange::Inline:
|
||||
@ -672,15 +672,15 @@ AsmJSProfilingFrameIterator::label() const
|
||||
//
|
||||
// NB: these labels are regexp-matched by
|
||||
// browser/devtools/profiler/cleopatra/js/parserWorker.js.
|
||||
const char *ionFFIDescription = "fast FFI trampoline (in asm.js)";
|
||||
const char *jitFFIDescription = "fast FFI trampoline (in asm.js)";
|
||||
const char *slowFFIDescription = "slow FFI trampoline (in asm.js)";
|
||||
const char *interruptDescription = "interrupt due to out-of-bounds or long execution (in asm.js)";
|
||||
|
||||
switch (AsmJSExit::ExtractReasonKind(exitReason_)) {
|
||||
case AsmJSExit::Reason_None:
|
||||
break;
|
||||
case AsmJSExit::Reason_IonFFI:
|
||||
return ionFFIDescription;
|
||||
case AsmJSExit::Reason_JitFFI:
|
||||
return jitFFIDescription;
|
||||
case AsmJSExit::Reason_SlowFFI:
|
||||
return slowFFIDescription;
|
||||
case AsmJSExit::Reason_Interrupt:
|
||||
@ -693,7 +693,7 @@ AsmJSProfilingFrameIterator::label() const
|
||||
switch (codeRange->kind()) {
|
||||
case AsmJSModule::CodeRange::Function: return codeRange->functionProfilingLabel(*module_);
|
||||
case AsmJSModule::CodeRange::Entry: return "entry trampoline (in asm.js)";
|
||||
case AsmJSModule::CodeRange::IonFFI: return ionFFIDescription;
|
||||
case AsmJSModule::CodeRange::JitFFI: return jitFFIDescription;
|
||||
case AsmJSModule::CodeRange::SlowFFI: return slowFFIDescription;
|
||||
case AsmJSModule::CodeRange::Interrupt: return interruptDescription;
|
||||
case AsmJSModule::CodeRange::Inline: return "inline stub (in asm.js)";
|
||||
|
@ -69,7 +69,7 @@ namespace AsmJSExit
|
||||
// handler).
|
||||
enum ReasonKind {
|
||||
Reason_None,
|
||||
Reason_IonFFI,
|
||||
Reason_JitFFI,
|
||||
Reason_SlowFFI,
|
||||
Reason_Interrupt,
|
||||
Reason_Builtin
|
||||
@ -106,7 +106,7 @@ namespace AsmJSExit
|
||||
typedef uint32_t Reason;
|
||||
|
||||
static const uint32_t None = Reason_None;
|
||||
static const uint32_t IonFFI = Reason_IonFFI;
|
||||
static const uint32_t JitFFI = Reason_JitFFI;
|
||||
static const uint32_t SlowFFI = Reason_SlowFFI;
|
||||
static const uint32_t Interrupt = Reason_Interrupt;
|
||||
static inline Reason Builtin(BuiltinKind builtin) {
|
||||
|
@ -105,11 +105,11 @@ AsmJSModule::~AsmJSModule()
|
||||
if (code_) {
|
||||
for (unsigned i = 0; i < numExits(); i++) {
|
||||
AsmJSModule::ExitDatum &exitDatum = exitIndexToGlobalDatum(i);
|
||||
if (!exitDatum.ionScript)
|
||||
if (!exitDatum.baselineScript)
|
||||
continue;
|
||||
|
||||
jit::DependentAsmJSModuleExit exit(this, i);
|
||||
exitDatum.ionScript->removeDependentAsmJSModule(exit);
|
||||
exitDatum.baselineScript->removeDependentAsmJSModule(exit);
|
||||
}
|
||||
|
||||
DeallocateExecutableMemory(code_, pod.totalBytes_, AsmJSPageSize);
|
||||
@ -501,23 +501,31 @@ CoerceInPlace_ToNumber(MutableHandleValue val)
|
||||
}
|
||||
|
||||
static bool
|
||||
TryEnablingIon(JSContext *cx, AsmJSModule &module, HandleFunction fun, uint32_t exitIndex,
|
||||
TryEnablingJit(JSContext *cx, AsmJSModule &module, HandleFunction fun, uint32_t exitIndex,
|
||||
int32_t argc, Value *argv)
|
||||
{
|
||||
if (!fun->hasScript())
|
||||
return true;
|
||||
|
||||
// Test if the function is Ion compiled
|
||||
// Test if the function is JIT compiled.
|
||||
JSScript *script = fun->nonLazyScript();
|
||||
if (!script->hasIonScript())
|
||||
if (!script->hasBaselineScript()) {
|
||||
MOZ_ASSERT(!script->hasIonScript());
|
||||
return true;
|
||||
}
|
||||
|
||||
// Currently we can't rectify arguments. Therefore disabling if argc is too low.
|
||||
if (fun->nargs() > size_t(argc))
|
||||
return true;
|
||||
|
||||
// Normally the types should correspond, since we just ran with those types,
|
||||
// but there are reports this is asserting. Therefore doing it as a check, instead of DEBUG only.
|
||||
// Ensure the argument types are included in the argument TypeSets stored in
|
||||
// the TypeScript. This is necessary for Ion, because the FFI exit will
|
||||
// use the skip-arg-checks entry point.
|
||||
//
|
||||
// Note that the TypeScript is never discarded while the script has a
|
||||
// BaselineScript, so if those checks hold now they must hold at least until
|
||||
// the BaselineScript is discarded and when that happens the FFI exit is
|
||||
// patched back.
|
||||
if (!types::TypeScript::ThisTypes(script)->hasType(types::Type::UndefinedType()))
|
||||
return true;
|
||||
for (uint32_t i = 0; i < fun->nargs(); i++) {
|
||||
@ -533,11 +541,11 @@ TryEnablingIon(JSContext *cx, AsmJSModule &module, HandleFunction fun, uint32_t
|
||||
if (module.exitIsOptimized(exitIndex))
|
||||
return true;
|
||||
|
||||
IonScript *ionScript = script->ionScript();
|
||||
if (!ionScript->addDependentAsmJSModule(cx, DependentAsmJSModuleExit(&module, exitIndex)))
|
||||
BaselineScript *baselineScript = script->baselineScript();
|
||||
if (!baselineScript->addDependentAsmJSModule(cx, DependentAsmJSModuleExit(&module, exitIndex)))
|
||||
return false;
|
||||
|
||||
module.optimizeExit(exitIndex, ionScript);
|
||||
module.optimizeExit(exitIndex, baselineScript);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -553,7 +561,7 @@ InvokeFromAsmJS(AsmJSActivation *activation, int32_t exitIndex, int32_t argc, Va
|
||||
if (!Invoke(cx, UndefinedValue(), fval, argc, argv, rval))
|
||||
return false;
|
||||
|
||||
return TryEnablingIon(cx, module, fun, exitIndex, argc, argv);
|
||||
return TryEnablingJit(cx, module, fun, exitIndex, argc, argv);
|
||||
}
|
||||
|
||||
// Use an int32_t return type instead of bool since bool does not have a
|
||||
@ -748,7 +756,7 @@ AsmJSModule::staticallyLink(ExclusiveContext *cx)
|
||||
AsmJSModule::ExitDatum &exitDatum = exitIndexToGlobalDatum(i);
|
||||
exitDatum.exit = interpExitTrampoline(exits_[i]);
|
||||
exitDatum.fun = nullptr;
|
||||
exitDatum.ionScript = nullptr;
|
||||
exitDatum.baselineScript = nullptr;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(isStaticallyLinked());
|
||||
@ -904,7 +912,7 @@ AsmJSModule::detachHeap(JSContext *cx)
|
||||
// Even if this->active(), to reach here, the activation must have called
|
||||
// out via an FFI stub. FFI stubs check if heapDatum() is null on reentry
|
||||
// and throw an exception if so.
|
||||
MOZ_ASSERT_IF(active(), activation()->exitReason() == AsmJSExit::Reason_IonFFI ||
|
||||
MOZ_ASSERT_IF(active(), activation()->exitReason() == AsmJSExit::Reason_JitFFI ||
|
||||
activation()->exitReason() == AsmJSExit::Reason_SlowFFI);
|
||||
|
||||
restoreHeapToInitialState(maybeHeap_);
|
||||
@ -1338,7 +1346,7 @@ AsmJSModule::CodeRange::CodeRange(Kind kind, uint32_t begin, uint32_t profilingR
|
||||
|
||||
MOZ_ASSERT(begin_ < profilingReturn_);
|
||||
MOZ_ASSERT(profilingReturn_ < end_);
|
||||
MOZ_ASSERT(u.kind_ == IonFFI || u.kind_ == SlowFFI || u.kind_ == Interrupt);
|
||||
MOZ_ASSERT(u.kind_ == JitFFI || u.kind_ == SlowFFI || u.kind_ == Interrupt);
|
||||
}
|
||||
|
||||
AsmJSModule::CodeRange::CodeRange(AsmJSExit::BuiltinKind builtin, uint32_t begin,
|
||||
|
@ -371,7 +371,7 @@ class AsmJSModule
|
||||
unsigned ffiIndex_;
|
||||
unsigned globalDataOffset_;
|
||||
unsigned interpCodeOffset_;
|
||||
unsigned ionCodeOffset_;
|
||||
unsigned jitCodeOffset_;
|
||||
|
||||
friend class AsmJSModule;
|
||||
|
||||
@ -379,7 +379,7 @@ class AsmJSModule
|
||||
Exit() {}
|
||||
Exit(unsigned ffiIndex, unsigned globalDataOffset)
|
||||
: ffiIndex_(ffiIndex), globalDataOffset_(globalDataOffset),
|
||||
interpCodeOffset_(0), ionCodeOffset_(0)
|
||||
interpCodeOffset_(0), jitCodeOffset_(0)
|
||||
{}
|
||||
unsigned ffiIndex() const {
|
||||
return ffiIndex_;
|
||||
@ -391,13 +391,13 @@ class AsmJSModule
|
||||
MOZ_ASSERT(!interpCodeOffset_);
|
||||
interpCodeOffset_ = off;
|
||||
}
|
||||
void initIonOffset(unsigned off) {
|
||||
MOZ_ASSERT(!ionCodeOffset_);
|
||||
ionCodeOffset_ = off;
|
||||
void initJitOffset(unsigned off) {
|
||||
MOZ_ASSERT(!jitCodeOffset_);
|
||||
jitCodeOffset_ = off;
|
||||
}
|
||||
void updateOffsets(jit::MacroAssembler &masm) {
|
||||
interpCodeOffset_ = masm.actualOffset(interpCodeOffset_);
|
||||
ionCodeOffset_ = masm.actualOffset(ionCodeOffset_);
|
||||
jitCodeOffset_ = masm.actualOffset(jitCodeOffset_);
|
||||
}
|
||||
|
||||
size_t serializedSize() const;
|
||||
@ -419,7 +419,7 @@ class AsmJSModule
|
||||
struct ExitDatum
|
||||
{
|
||||
uint8_t *exit;
|
||||
jit::IonScript *ionScript;
|
||||
jit::BaselineScript *baselineScript;
|
||||
HeapPtrFunction fun;
|
||||
};
|
||||
|
||||
@ -558,7 +558,7 @@ class AsmJSModule
|
||||
void setDeltas(uint32_t entry, uint32_t profilingJump, uint32_t profilingEpilogue);
|
||||
|
||||
public:
|
||||
enum Kind { Function, Entry, IonFFI, SlowFFI, Interrupt, Thunk, Inline };
|
||||
enum Kind { Function, Entry, JitFFI, SlowFFI, Interrupt, Thunk, Inline };
|
||||
|
||||
CodeRange() {}
|
||||
CodeRange(uint32_t nameIndex, uint32_t lineNumber, const AsmJSFunctionLabels &l);
|
||||
@ -570,7 +570,7 @@ class AsmJSModule
|
||||
Kind kind() const { return Kind(u.kind_); }
|
||||
bool isFunction() const { return kind() == Function; }
|
||||
bool isEntry() const { return kind() == Entry; }
|
||||
bool isFFI() const { return kind() == IonFFI || kind() == SlowFFI; }
|
||||
bool isFFI() const { return kind() == JitFFI || kind() == SlowFFI; }
|
||||
bool isInterrupt() const { return kind() == Interrupt; }
|
||||
bool isThunk() const { return kind() == Thunk; }
|
||||
|
||||
@ -1325,10 +1325,10 @@ class AsmJSModule
|
||||
MOZ_ASSERT(exit.interpCodeOffset_);
|
||||
return code_ + exit.interpCodeOffset_;
|
||||
}
|
||||
uint8_t *ionExitTrampoline(const Exit &exit) const {
|
||||
uint8_t *jitExitTrampoline(const Exit &exit) const {
|
||||
MOZ_ASSERT(isFinished());
|
||||
MOZ_ASSERT(exit.ionCodeOffset_);
|
||||
return code_ + exit.ionCodeOffset_;
|
||||
MOZ_ASSERT(exit.jitCodeOffset_);
|
||||
return code_ + exit.jitCodeOffset_;
|
||||
}
|
||||
public:
|
||||
|
||||
@ -1463,17 +1463,17 @@ class AsmJSModule
|
||||
ExitDatum &exitDatum = exitIndexToGlobalDatum(exitIndex);
|
||||
return exitDatum.exit != interpExitTrampoline(exit(exitIndex));
|
||||
}
|
||||
void optimizeExit(unsigned exitIndex, jit::IonScript *ionScript) const {
|
||||
void optimizeExit(unsigned exitIndex, jit::BaselineScript *baselineScript) const {
|
||||
MOZ_ASSERT(!exitIsOptimized(exitIndex));
|
||||
ExitDatum &exitDatum = exitIndexToGlobalDatum(exitIndex);
|
||||
exitDatum.exit = ionExitTrampoline(exit(exitIndex));
|
||||
exitDatum.ionScript = ionScript;
|
||||
exitDatum.exit = jitExitTrampoline(exit(exitIndex));
|
||||
exitDatum.baselineScript = baselineScript;
|
||||
}
|
||||
void detachIonCompilation(size_t exitIndex) const {
|
||||
void detachJitCompilation(size_t exitIndex) const {
|
||||
MOZ_ASSERT(isFinished());
|
||||
ExitDatum &exitDatum = exitIndexToGlobalDatum(exitIndex);
|
||||
exitDatum.exit = interpExitTrampoline(exit(exitIndex));
|
||||
exitDatum.ionScript = nullptr;
|
||||
exitDatum.baselineScript = nullptr;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
@ -1870,13 +1870,13 @@ class MOZ_STACK_CLASS ModuleCompiler
|
||||
uint32_t end = masm_.currentOffset();
|
||||
return module_->addCodeRange(AsmJSModule::CodeRange::SlowFFI, beg, pret, end);
|
||||
}
|
||||
bool finishGeneratingIonExit(unsigned exitIndex, Label *begin, Label *profilingReturn) {
|
||||
bool finishGeneratingJitExit(unsigned exitIndex, Label *begin, Label *profilingReturn) {
|
||||
MOZ_ASSERT(finishedFunctionBodies_);
|
||||
uint32_t beg = begin->offset();
|
||||
module_->exit(exitIndex).initIonOffset(beg);
|
||||
module_->exit(exitIndex).initJitOffset(beg);
|
||||
uint32_t pret = profilingReturn->offset();
|
||||
uint32_t end = masm_.currentOffset();
|
||||
return module_->addCodeRange(AsmJSModule::CodeRange::IonFFI, beg, pret, end);
|
||||
return module_->addCodeRange(AsmJSModule::CodeRange::JitFFI, beg, pret, end);
|
||||
}
|
||||
bool finishGeneratingInterrupt(Label *begin, Label *profilingReturn) {
|
||||
MOZ_ASSERT(finishedFunctionBodies_);
|
||||
@ -8453,7 +8453,7 @@ GenerateFFIIonExit(ModuleCompiler &m, const ModuleCompiler::ExitDescriptor &exit
|
||||
unsigned framePushed = Max(ionFrameSize, coerceFrameSize);
|
||||
|
||||
Label begin;
|
||||
GenerateAsmJSExitPrologue(masm, framePushed, AsmJSExit::IonFFI, &begin);
|
||||
GenerateAsmJSExitPrologue(masm, framePushed, AsmJSExit::JitFFI, &begin);
|
||||
|
||||
// 1. Descriptor
|
||||
size_t argOffset = offsetToIonArgs;
|
||||
@ -8501,7 +8501,7 @@ GenerateFFIIonExit(ModuleCompiler &m, const ModuleCompiler::ExitDescriptor &exit
|
||||
argOffset += exit.sig().args().length() * sizeof(Value);
|
||||
MOZ_ASSERT(argOffset == offsetToIonArgs + ionArgBytes);
|
||||
|
||||
// 6. Ion will clobber all registers, even non-volatiles. GlobalReg and
|
||||
// 6. Jit code will clobber all registers, even non-volatiles. GlobalReg and
|
||||
// HeapReg are removed from the general register set for asm.js code, so
|
||||
// these will not have been saved by the caller like all other registers,
|
||||
// so they must be explicitly preserved. Only save GlobalReg since
|
||||
@ -8553,7 +8553,7 @@ GenerateFFIIonExit(ModuleCompiler &m, const ModuleCompiler::ExitDescriptor &exit
|
||||
|
||||
// 2. Call
|
||||
AssertStackAlignment(masm, AsmJSStackAlignment);
|
||||
masm.callIonFromAsmJS(callee);
|
||||
masm.callJitFromAsmJS(callee);
|
||||
AssertStackAlignment(masm, AsmJSStackAlignment);
|
||||
|
||||
{
|
||||
@ -8625,7 +8625,7 @@ GenerateFFIIonExit(ModuleCompiler &m, const ModuleCompiler::ExitDescriptor &exit
|
||||
GenerateCheckForHeapDetachment(m, ABIArgGenerator::NonReturn_VolatileReg0);
|
||||
|
||||
Label profilingReturn;
|
||||
GenerateAsmJSExitEpilogue(masm, framePushed, AsmJSExit::IonFFI, &profilingReturn);
|
||||
GenerateAsmJSExitEpilogue(masm, framePushed, AsmJSExit::JitFFI, &profilingReturn);
|
||||
|
||||
if (oolConvert.used()) {
|
||||
masm.bind(&oolConvert);
|
||||
@ -8669,7 +8669,7 @@ GenerateFFIIonExit(ModuleCompiler &m, const ModuleCompiler::ExitDescriptor &exit
|
||||
|
||||
MOZ_ASSERT(masm.framePushed() == 0);
|
||||
|
||||
return m.finishGeneratingIonExit(exitIndex, &begin, &profilingReturn) && !masm.oom();
|
||||
return m.finishGeneratingJitExit(exitIndex, &begin, &profilingReturn) && !masm.oom();
|
||||
}
|
||||
|
||||
// See "asm.js FFI calls" comment above.
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
|
||||
#include "asmjs/AsmJSModule.h"
|
||||
#include "jit/BaselineCompiler.h"
|
||||
#include "jit/BaselineIC.h"
|
||||
#include "jit/CompileInfo.h"
|
||||
@ -45,6 +46,7 @@ BaselineScript::BaselineScript(uint32_t prologueOffset, uint32_t epilogueOffset,
|
||||
: method_(nullptr),
|
||||
templateScope_(nullptr),
|
||||
fallbackStubSpace_(),
|
||||
dependentAsmJSModules_(nullptr),
|
||||
prologueOffset_(prologueOffset),
|
||||
epilogueOffset_(epilogueOffset),
|
||||
#ifdef DEBUG
|
||||
@ -440,9 +442,54 @@ BaselineScript::Destroy(FreeOp *fop, BaselineScript *script)
|
||||
MOZ_ASSERT(fop->runtime()->gc.nursery.isEmpty());
|
||||
#endif
|
||||
|
||||
script->unlinkDependentAsmJSModules(fop);
|
||||
|
||||
fop->delete_(script);
|
||||
}
|
||||
|
||||
void
|
||||
BaselineScript::unlinkDependentAsmJSModules(FreeOp *fop)
|
||||
{
|
||||
// Remove any links from AsmJSModules that contain optimized FFI calls into
|
||||
// this BaselineScript.
|
||||
if (dependentAsmJSModules_) {
|
||||
for (size_t i = 0; i < dependentAsmJSModules_->length(); i++) {
|
||||
DependentAsmJSModuleExit exit = (*dependentAsmJSModules_)[i];
|
||||
exit.module->detachJitCompilation(exit.exitIndex);
|
||||
}
|
||||
|
||||
fop->delete_(dependentAsmJSModules_);
|
||||
dependentAsmJSModules_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
BaselineScript::addDependentAsmJSModule(JSContext *cx, DependentAsmJSModuleExit exit)
|
||||
{
|
||||
if (!dependentAsmJSModules_) {
|
||||
dependentAsmJSModules_ = cx->new_<Vector<DependentAsmJSModuleExit> >(cx);
|
||||
if (!dependentAsmJSModules_)
|
||||
return false;
|
||||
}
|
||||
return dependentAsmJSModules_->append(exit);
|
||||
}
|
||||
|
||||
void
|
||||
BaselineScript::removeDependentAsmJSModule(DependentAsmJSModuleExit exit)
|
||||
{
|
||||
if (!dependentAsmJSModules_)
|
||||
return;
|
||||
|
||||
for (size_t i = 0; i < dependentAsmJSModules_->length(); i++) {
|
||||
if ((*dependentAsmJSModules_)[i].module == exit.module &&
|
||||
(*dependentAsmJSModules_)[i].exitIndex == exit.exitIndex)
|
||||
{
|
||||
dependentAsmJSModules_->erase(dependentAsmJSModules_->begin() + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ICEntry &
|
||||
BaselineScript::icEntry(size_t index)
|
||||
{
|
||||
|
@ -93,6 +93,19 @@ struct PCMappingIndexEntry
|
||||
uint32_t bufferOffset;
|
||||
};
|
||||
|
||||
// Describes a single AsmJSModule which jumps (via an FFI exit with the given
|
||||
// index) directly to a BaselineScript or IonScript.
|
||||
struct DependentAsmJSModuleExit
|
||||
{
|
||||
const AsmJSModule *module;
|
||||
size_t exitIndex;
|
||||
|
||||
DependentAsmJSModuleExit(const AsmJSModule *module, size_t exitIndex)
|
||||
: module(module),
|
||||
exitIndex(exitIndex)
|
||||
{ }
|
||||
};
|
||||
|
||||
struct BaselineScript
|
||||
{
|
||||
public:
|
||||
@ -114,6 +127,10 @@ struct BaselineScript
|
||||
// Allocated space for fallback stubs.
|
||||
FallbackICStubSpace fallbackStubSpace_;
|
||||
|
||||
// If non-null, the list of AsmJSModules that contain an optimized call
|
||||
// directly to this script.
|
||||
Vector<DependentAsmJSModuleExit> *dependentAsmJSModules_;
|
||||
|
||||
// Native code offset right before the scope chain is initialized.
|
||||
uint32_t prologueOffset_;
|
||||
|
||||
@ -347,6 +364,10 @@ struct BaselineScript
|
||||
jsbytecode *pcForNativeAddress(JSScript *script, uint8_t *nativeAddress);
|
||||
jsbytecode *pcForNativeOffset(JSScript *script, uint32_t nativeOffset);
|
||||
|
||||
bool addDependentAsmJSModule(JSContext *cx, DependentAsmJSModuleExit exit);
|
||||
void unlinkDependentAsmJSModules(FreeOp *fop);
|
||||
void removeDependentAsmJSModule(DependentAsmJSModuleExit exit);
|
||||
|
||||
private:
|
||||
jsbytecode *pcForNativeOffset(JSScript *script, uint32_t nativeOffset, bool isReturn);
|
||||
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include "jscompartment.h"
|
||||
#include "jsprf.h"
|
||||
|
||||
#include "asmjs/AsmJSModule.h"
|
||||
#include "gc/Marking.h"
|
||||
#include "jit/AliasAnalysis.h"
|
||||
#include "jit/BacktrackingAllocator.h"
|
||||
@ -844,7 +843,6 @@ IonScript::IonScript()
|
||||
parallelAge_(0),
|
||||
recompileInfo_(),
|
||||
osrPcMismatchCounter_(0),
|
||||
dependentAsmJSModules(nullptr),
|
||||
pendingBuilder_(nullptr)
|
||||
{
|
||||
}
|
||||
@ -1222,32 +1220,9 @@ IonScript::destroyCaches()
|
||||
getCacheFromIndex(i).destroy();
|
||||
}
|
||||
|
||||
bool
|
||||
IonScript::addDependentAsmJSModule(JSContext *cx, DependentAsmJSModuleExit exit)
|
||||
{
|
||||
if (!dependentAsmJSModules) {
|
||||
dependentAsmJSModules = cx->new_<Vector<DependentAsmJSModuleExit> >(cx);
|
||||
if (!dependentAsmJSModules)
|
||||
return false;
|
||||
}
|
||||
return dependentAsmJSModules->append(exit);
|
||||
}
|
||||
|
||||
void
|
||||
IonScript::unlinkFromRuntime(FreeOp *fop)
|
||||
{
|
||||
// Remove any links from AsmJSModules that contain optimized FFI calls into
|
||||
// this IonScript.
|
||||
if (dependentAsmJSModules) {
|
||||
for (size_t i = 0; i < dependentAsmJSModules->length(); i++) {
|
||||
DependentAsmJSModuleExit exit = dependentAsmJSModules->begin()[i];
|
||||
exit.module->detachIonCompilation(exit.exitIndex);
|
||||
}
|
||||
|
||||
fop->delete_(dependentAsmJSModules);
|
||||
dependentAsmJSModules = nullptr;
|
||||
}
|
||||
|
||||
// The writes to the executable buffer below may clobber backedge jumps, so
|
||||
// make sure that those backedges are unlinked from the runtime and not
|
||||
// reclobbered with garbage if an interrupt is requested.
|
||||
|
@ -160,19 +160,6 @@ class IonCache;
|
||||
struct PatchableBackedgeInfo;
|
||||
struct CacheLocation;
|
||||
|
||||
// Describes a single AsmJSModule which jumps (via an FFI exit with the given
|
||||
// index) directly into an IonScript.
|
||||
struct DependentAsmJSModuleExit
|
||||
{
|
||||
const AsmJSModule *module;
|
||||
size_t exitIndex;
|
||||
|
||||
DependentAsmJSModuleExit(const AsmJSModule *module, size_t exitIndex)
|
||||
: module(module),
|
||||
exitIndex(exitIndex)
|
||||
{ }
|
||||
};
|
||||
|
||||
// An IonScript attaches Ion-generated information to a JSScript.
|
||||
struct IonScript
|
||||
{
|
||||
@ -298,10 +285,6 @@ struct IonScript
|
||||
// a LOOPENTRY pc other than osrPc_.
|
||||
uint32_t osrPcMismatchCounter_;
|
||||
|
||||
// If non-null, the list of AsmJSModules
|
||||
// that contain an optimized call directly into this IonScript.
|
||||
Vector<DependentAsmJSModuleExit> *dependentAsmJSModules;
|
||||
|
||||
IonBuilder *pendingBuilder_;
|
||||
|
||||
private:
|
||||
@ -352,19 +335,6 @@ struct IonScript
|
||||
PatchableBackedge *backedgeList() {
|
||||
return (PatchableBackedge *) &bottomBuffer()[backedgeList_];
|
||||
}
|
||||
bool addDependentAsmJSModule(JSContext *cx, DependentAsmJSModuleExit exit);
|
||||
void removeDependentAsmJSModule(DependentAsmJSModuleExit exit) {
|
||||
if (!dependentAsmJSModules)
|
||||
return;
|
||||
for (size_t i = 0; i < dependentAsmJSModules->length(); i++) {
|
||||
if (dependentAsmJSModules->begin()[i].module == exit.module &&
|
||||
dependentAsmJSModules->begin()[i].exitIndex == exit.exitIndex)
|
||||
{
|
||||
dependentAsmJSModules->erase(dependentAsmJSModules->begin() + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void trace(JSTracer *trc);
|
||||
|
@ -1861,11 +1861,11 @@ MacroAssemblerARMCompat::callIon(Register callee)
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssemblerARMCompat::callIonFromAsmJS(Register callee)
|
||||
MacroAssemblerARMCompat::callJitFromAsmJS(Register callee)
|
||||
{
|
||||
ma_callIonNoPush(callee);
|
||||
|
||||
// The Ion ABI has the callee pop the return address off the stack.
|
||||
// The JIT ABI has the callee pop the return address off the stack.
|
||||
// The asm.js caller assumes that the call leaves sp unchanged, so bump
|
||||
// the stack.
|
||||
subPtr(Imm32(sizeof(void*)), sp);
|
||||
|
@ -1293,7 +1293,7 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
|
||||
// Makes an Ion call using the only two methods that it is sane for
|
||||
// independent code to make a call.
|
||||
void callIon(Register callee);
|
||||
void callIonFromAsmJS(Register callee);
|
||||
void callJitFromAsmJS(Register callee);
|
||||
|
||||
void reserveStack(uint32_t amount);
|
||||
void freeStack(uint32_t amount);
|
||||
|
@ -1549,11 +1549,11 @@ MacroAssemblerMIPSCompat::callIon(Register callee)
|
||||
}
|
||||
}
|
||||
void
|
||||
MacroAssemblerMIPSCompat::callIonFromAsmJS(Register callee)
|
||||
MacroAssemblerMIPSCompat::callJitFromAsmJS(Register callee)
|
||||
{
|
||||
ma_callIonNoPush(callee);
|
||||
|
||||
// The Ion ABI has the callee pop the return address off the stack.
|
||||
// The JIT ABI has the callee pop the return address off the stack.
|
||||
// The asm.js caller assumes that the call leaves sp unchanged, so bump
|
||||
// the stack.
|
||||
subPtr(Imm32(sizeof(void*)), StackPointer);
|
||||
|
@ -1140,7 +1140,7 @@ public:
|
||||
// Makes an Ion call using the only two methods that it is sane for
|
||||
// indep code to make a call
|
||||
void callIon(Register callee);
|
||||
void callIonFromAsmJS(Register callee);
|
||||
void callJitFromAsmJS(Register callee);
|
||||
|
||||
void reserveStack(uint32_t amount);
|
||||
void freeStack(uint32_t amount);
|
||||
|
@ -191,7 +191,7 @@ class MacroAssemblerNone : public Assembler
|
||||
void callWithExitFrame(JitCode *, Register) { MOZ_CRASH(); }
|
||||
|
||||
void callIon(Register callee) { MOZ_CRASH(); }
|
||||
void callIonFromAsmJS(Register callee) { MOZ_CRASH(); }
|
||||
void callJitFromAsmJS(Register callee) { MOZ_CRASH(); }
|
||||
|
||||
void nop() { MOZ_CRASH(); }
|
||||
void breakpoint() { MOZ_CRASH(); }
|
||||
|
@ -1205,7 +1205,7 @@ class MacroAssemblerX86Shared : public Assembler
|
||||
void callIon(Register callee) {
|
||||
call(callee);
|
||||
}
|
||||
void callIonFromAsmJS(Register callee) {
|
||||
void callJitFromAsmJS(Register callee) {
|
||||
call(callee);
|
||||
}
|
||||
void call(AsmJSImmPtr target) {
|
||||
|
Loading…
Reference in New Issue
Block a user