--- a/js/src/asmjs/AsmJSFrameIterator.cpp
+++ b/js/src/asmjs/AsmJSFrameIterator.cpp
@@ -74,17 +74,17 @@ AsmJSFrameIterator::settle()
case AsmJSModule::CodeRange::Function:
callsite_ = module_->lookupCallSite(returnAddress);
MOZ_ASSERT(callsite_);
break;
case AsmJSModule::CodeRange::Entry:
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:
case AsmJSModule::CodeRange::Thunk:
MOZ_CRASH("Should not encounter an exit during iteration");
}
}
@@ -453,17 +453,17 @@ AsmJSProfilingFrameIterator::initFromFP(
callerFP_ = nullptr;
break;
case AsmJSModule::CodeRange::Function:
fp = CallerFPFromFP(fp);
callerPC_ = ReturnAddressFromFP(fp);
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:
case AsmJSModule::CodeRange::Thunk:
MOZ_CRASH("Unexpected CodeRange kind");
}
// Since, despite the above reasoning for skipping a frame, we do want FFI
@@ -508,17 +508,17 @@ AsmJSProfilingFrameIterator::AsmJSProfil
}
// Note: fp may be null while entering and leaving the activation.
uint8_t *fp = activation.fp();
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: {
// While codeRange describes the *current* frame, the fp/pc state stored in
// the iterator is the *caller's* frame. The reason for this is that the
// activation.fp isn't always the AsmJSFrame for state.pc; during the
// prologue/epilogue, activation.fp will point to the caller's frame.
// Naively unwinding starting at activation.fp could thus lead to the
@@ -610,17 +610,17 @@ AsmJSProfilingFrameIterator::operator++(
switch (codeRange->kind()) {
case AsmJSModule::CodeRange::Entry:
MOZ_ASSERT(callerFP_ == nullptr);
MOZ_ASSERT(callerPC_ != nullptr);
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:
case AsmJSModule::CodeRange::Thunk:
stackAddress_ = callerFP_;
callerPC_ = ReturnAddressFromFP(callerFP_);
AssertMatchesCallSite(*module_, codeRange, callerPC_, CallerFPFromFP(callerFP_), callerFP_);
callerFP_ = CallerFPFromFP(callerFP_);
@@ -667,38 +667,38 @@ AsmJSProfilingFrameIterator::label() con
{
MOZ_ASSERT(!done());
// Use the same string for both time inside and under so that the two
// entries will be coalesced by the profiler.
//
// 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:
return interruptDescription;
case AsmJSExit::Reason_Builtin:
return BuiltinToName(AsmJSExit::ExtractBuiltinKind(exitReason_));
}
auto codeRange = reinterpret_cast<const AsmJSModule::CodeRange*>(codeRange_);
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)";
case AsmJSModule::CodeRange::Thunk: return BuiltinToName(codeRange->thunkTarget());
}
MOZ_CRASH("Bad exit kind");
}
--- a/js/src/asmjs/AsmJSFrameIterator.h
+++ b/js/src/asmjs/AsmJSFrameIterator.h
@@ -64,17 +64,17 @@ namespace AsmJSExit
{
// List of reasons for execution leaving asm.js-generated code, stored in
// AsmJSActivation. The initial and default state is AsmJSNoExit. If
// AsmJSNoExit is observed when the pc isn't in asm.js code, execution must
// have been interrupted asynchronously (viz., by a exception/signal
// handler).
enum ReasonKind {
Reason_None,
- Reason_IonFFI,
+ Reason_JitFFI,
Reason_SlowFFI,
Reason_Interrupt,
Reason_Builtin
};
// For Reason_Builtin, the list of builtins, so they can be displayed in the
// profile call stack.
enum BuiltinKind {
@@ -101,17 +101,17 @@ namespace AsmJSExit
Builtin_Limit
};
// A Reason contains both a ReasonKind and (if Reason_Builtin) a
// BuiltinKind.
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) {
return uint16_t(Reason_Builtin) | (uint16_t(builtin) << 16);
}
static inline ReasonKind ExtractReasonKind(Reason reason) {
return ReasonKind(uint16_t(reason));
}
--- a/js/src/asmjs/AsmJSModule.cpp
+++ b/js/src/asmjs/AsmJSModule.cpp
@@ -100,21 +100,21 @@ AsmJSModule::~AsmJSModule()
{
MOZ_ASSERT(!interrupted_);
scriptSource_->decref();
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);
}
for (size_t i = 0; i < numFunctionCounts(); i++)
js_delete(functionCounts(i));
@@ -496,69 +496,77 @@ CoerceInPlace_ToNumber(MutableHandleValu
if (!ToNumber(cx, val, &dbl))
return false;
val.set(DoubleValue(dbl));
return true;
}
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++) {
types::StackTypeSet *typeset = types::TypeScript::ArgTypes(script, i);
types::Type type = types::Type::DoubleType();
if (!argv[i].isDouble())
type = types::Type::PrimitiveType(argv[i].extractNonDoubleType());
if (!typeset->hasType(type))
return true;
}
// The exit may have become optimized while executing the FFI.
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;
}
static bool
InvokeFromAsmJS(AsmJSActivation *activation, int32_t exitIndex, int32_t argc, Value *argv,
MutableHandleValue rval)
{
JSContext *cx = activation->cx();
AsmJSModule &module = activation->module();
RootedFunction fun(cx, module.exitIndexToGlobalDatum(exitIndex).fun);
RootedValue fval(cx, ObjectValue(*fun));
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
// specified width and the caller is assuming a word-sized return.
static int32_t
InvokeFromAsmJS_Ignore(int32_t exitIndex, int32_t argc, Value *argv)
{
AsmJSActivation *activation = PerThreadData::innermostAsmJSActivation();
@@ -743,17 +751,17 @@ AsmJSModule::staticallyLink(ExclusiveCon
}
// Initialize global data segment
for (size_t i = 0; i < exits_.length(); i++) {
AsmJSModule::ExitDatum &exitDatum = exitIndexToGlobalDatum(i);
exitDatum.exit = interpExitTrampoline(exits_[i]);
exitDatum.fun = nullptr;
- exitDatum.ionScript = nullptr;
+ exitDatum.baselineScript = nullptr;
}
MOZ_ASSERT(isStaticallyLinked());
}
#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
static inline size_t
ViewTypeByteSize(AsmJSHeapAccess::ViewType vt)
@@ -899,17 +907,17 @@ AsmJSModule::detachHeap(JSContext *cx)
if (interrupted_) {
JS_ReportError(cx, "attempt to detach from inside interrupt handler");
return false;
}
// 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_);
MOZ_ASSERT(hasDetachedHeap());
return true;
}
@@ -1333,17 +1341,17 @@ AsmJSModule::CodeRange::CodeRange(Kind k
: begin_(begin),
profilingReturn_(profilingReturn),
end_(end)
{
u.kind_ = kind;
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,
uint32_t profilingReturn, uint32_t end)
: begin_(begin),
profilingReturn_(profilingReturn),
end_(end)
{
--- a/js/src/asmjs/AsmJSModule.h
+++ b/js/src/asmjs/AsmJSModule.h
@@ -366,43 +366,43 @@ class AsmJSModule
bool clone(ExclusiveContext *cx, Global *out) const;
};
class Exit
{
unsigned ffiIndex_;
unsigned globalDataOffset_;
unsigned interpCodeOffset_;
- unsigned ionCodeOffset_;
+ unsigned jitCodeOffset_;
friend class AsmJSModule;
public:
Exit() {}
Exit(unsigned ffiIndex, unsigned globalDataOffset)
: ffiIndex_(ffiIndex), globalDataOffset_(globalDataOffset),
- interpCodeOffset_(0), ionCodeOffset_(0)
+ interpCodeOffset_(0), jitCodeOffset_(0)
{}
unsigned ffiIndex() const {
return ffiIndex_;
}
unsigned globalDataOffset() const {
return globalDataOffset_;
}
void initInterpOffset(unsigned off) {
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;
uint8_t *serialize(uint8_t *cursor) const;
const uint8_t *deserialize(ExclusiveContext *cx, const uint8_t *cursor);
bool clone(ExclusiveContext *cx, Exit *out) const;
};
@@ -414,17 +414,17 @@ class AsmJSModule
typedef int32_t (*CodePtr)(EntryArg *args, uint8_t *global);
// An Exit holds bookkeeping information about an exit; the ExitDatum
// struct overlays the actual runtime data stored in the global data
// section.
struct ExitDatum
{
uint8_t *exit;
- jit::IonScript *ionScript;
+ jit::BaselineScript *baselineScript;
HeapPtrFunction fun;
};
typedef Vector<AsmJSCoercion, 0, SystemAllocPolicy> ArgCoercionVector;
enum ReturnType { Return_Int32, Return_Double, Return_Int32x4, Return_Float32x4, Return_Void };
class ExportedFunction
@@ -553,29 +553,29 @@ class AsmJSModule
uint16_t target_;
} thunk;
uint8_t kind_;
} u;
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);
CodeRange(Kind kind, uint32_t begin, uint32_t end);
CodeRange(Kind kind, uint32_t begin, uint32_t profilingReturn, uint32_t end);
CodeRange(AsmJSExit::BuiltinKind builtin, uint32_t begin, uint32_t pret, uint32_t end);
void updateOffsets(jit::MacroAssembler &masm);
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; }
uint32_t begin() const {
return begin_;
}
uint32_t entry() const {
MOZ_ASSERT(isFunction());
@@ -1320,20 +1320,20 @@ class AsmJSModule
return pc >= code_ && pc < (code_ + codeBytes());
}
private:
uint8_t *interpExitTrampoline(const Exit &exit) const {
MOZ_ASSERT(isFinished());
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:
// Lookup a callsite by the return pc (from the callee to the caller).
// Return null if no callsite was found.
const jit::CallSite *lookupCallSite(void *returnAddress) const;
// Lookup the name the code range containing the given pc. Return null if no
@@ -1458,27 +1458,27 @@ class AsmJSModule
MOZ_ASSERT(isFinished());
return *(ExitDatum *)(globalData() + exitIndexToGlobalDataOffset(exitIndex));
}
bool exitIsOptimized(unsigned exitIndex) const {
MOZ_ASSERT(isFinished());
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;
}
/*************************************************************************/
// These functions are called after finish() but before staticallyLink():
bool addRelativeLink(RelativeLink link) {
MOZ_ASSERT(isFinished() && !isStaticallyLinked());
return staticLinkData_.relativeLinks.append(link);
--- a/js/src/asmjs/AsmJSValidate.cpp
+++ b/js/src/asmjs/AsmJSValidate.cpp
@@ -1865,23 +1865,23 @@ class MOZ_STACK_CLASS ModuleCompiler
bool finishGeneratingInterpExit(unsigned exitIndex, Label *begin, Label *profilingReturn) {
MOZ_ASSERT(finishedFunctionBodies_);
uint32_t beg = begin->offset();
module_->exit(exitIndex).initInterpOffset(beg);
uint32_t pret = profilingReturn->offset();
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_);
uint32_t beg = begin->offset();
uint32_t pret = profilingReturn->offset();
uint32_t end = masm_.currentOffset();
return module_->addCodeRange(AsmJSModule::CodeRange::Interrupt, beg, pret, end);
}
@@ -8448,17 +8448,17 @@ GenerateFFIIonExit(ModuleCompiler &m, co
coerceArgTypes.infallibleAppend(MIRType_Pointer); // argv
unsigned offsetToCoerceArgv = AlignBytes(StackArgBytes(coerceArgTypes), sizeof(double));
unsigned totalCoerceBytes = offsetToCoerceArgv + sizeof(Value) + MaybeSavedGlobalReg;
unsigned coerceFrameSize = StackDecrementForCall(masm, AsmJSStackAlignment, totalCoerceBytes);
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;
uint32_t descriptor = MakeFrameDescriptor(framePushed, JitFrame_Entry);
masm.storePtr(ImmWord(uintptr_t(descriptor)), Address(StackPointer, argOffset));
argOffset += sizeof(size_t);
// 2. Callee
@@ -8496,17 +8496,17 @@ GenerateFFIIonExit(ModuleCompiler &m, co
argOffset += sizeof(Value);
// 5. Fill the arguments
unsigned offsetToCallerStackArgs = framePushed + sizeof(AsmJSFrame);
FillArgumentArray(m, exit.sig().args(), argOffset, offsetToCallerStackArgs, scratch);
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
// HeapReg must be reloaded (from global data) after the call since the
// heap may change during the FFI call.
#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS)
JS_STATIC_ASSERT(MaybeSavedGlobalReg > 0);
unsigned savedGlobalOffset = framePushed - MaybeSavedGlobalReg;
@@ -8548,17 +8548,17 @@ GenerateFFIIonExit(ModuleCompiler &m, co
masm.storePtr(reg2, Address(reg1, JitActivation::offsetOfPrevJitTop()));
masm.loadPtr(Address(reg0, offsetOfJitJSContext), reg2);
masm.storePtr(reg2, Address(reg1, JitActivation::offsetOfPrevJitJSContext()));
masm.storePtr(reg3, Address(reg0, offsetOfJitJSContext));
}
// 2. Call
AssertStackAlignment(masm, AsmJSStackAlignment);
- masm.callIonFromAsmJS(callee);
+ masm.callJitFromAsmJS(callee);
AssertStackAlignment(masm, AsmJSStackAlignment);
{
// Disable Activation.
//
// This sequence needs three registers, and must preserve the JSReturnReg_Data and
// JSReturnReg_Type, so there are five live registers.
MOZ_ASSERT(JSReturnReg_Data == AsmJSIonExitRegReturnData);
@@ -8620,17 +8620,17 @@ GenerateFFIIonExit(ModuleCompiler &m, co
#endif
// The heap pointer has to be reloaded anyway since Ion could have clobbered
// it. Additionally, the FFI may have detached the heap buffer.
masm.loadAsmJSHeapRegisterFromGlobalData();
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);
masm.setFramePushed(framePushed);
// Store return value into argv[0]
masm.storeValue(JSReturnOperand, Address(StackPointer, offsetToCoerceArgv));
@@ -8664,17 +8664,17 @@ GenerateFFIIonExit(ModuleCompiler &m, co
}
masm.jump(&done);
masm.setFramePushed(0);
}
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.
static bool
GenerateFFIExits(ModuleCompiler &m, const ModuleCompiler::ExitDescriptor &exit, unsigned exitIndex,
Label *throwLabel)
{
// Generate the slow path through the interpreter
--- a/js/src/jit/BaselineJIT.cpp
+++ b/js/src/jit/BaselineJIT.cpp
@@ -3,16 +3,17 @@
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "jit/BaselineJIT.h"
#include "mozilla/MemoryReporting.h"
+#include "asmjs/AsmJSModule.h"
#include "jit/BaselineCompiler.h"
#include "jit/BaselineIC.h"
#include "jit/CompileInfo.h"
#include "jit/JitCommon.h"
#include "jit/JitSpewer.h"
#include "vm/Interpreter.h"
#include "vm/TraceLogging.h"
@@ -40,16 +41,17 @@ PCMappingSlotInfo::ToSlotLocation(const
return SlotIgnore;
}
BaselineScript::BaselineScript(uint32_t prologueOffset, uint32_t epilogueOffset,
uint32_t spsPushToggleOffset, uint32_t postDebugPrologueOffset)
: method_(nullptr),
templateScope_(nullptr),
fallbackStubSpace_(),
+ dependentAsmJSModules_(nullptr),
prologueOffset_(prologueOffset),
epilogueOffset_(epilogueOffset),
#ifdef DEBUG
spsOn_(false),
#endif
spsPushToggleOffset_(spsPushToggleOffset),
postDebugPrologueOffset_(postDebugPrologueOffset),
flags_(0)
@@ -435,19 +437,64 @@ BaselineScript::Destroy(FreeOp *fop, Bas
* will contain entries refering to the referenced things. Since we can
* destroy scripts outside the context of a GC, this situation can result
* in invalid store buffer entries. Assert that if we do destroy scripts
* outside of a GC that we at least emptied the nursery first.
*/
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)
{
MOZ_ASSERT(index < numICEntries());
return icEntryList()[index];
}
PCMappingIndexEntry &
--- a/js/src/jit/BaselineJIT.h
+++ b/js/src/jit/BaselineJIT.h
@@ -88,16 +88,29 @@ struct PCMappingIndexEntry
// Native code offset.
uint32_t nativeOffset;
// Offset in the CompactBuffer where data for pcOffset starts.
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:
static const uint32_t MAX_JSSCRIPT_LENGTH = 0x0fffffffu;
// Limit the locals on a given script so that stack check on baseline frames
// doesn't overflow a uint32_t value.
// (MAX_JSSCRIPT_SLOTS * sizeof(Value)) must fit within a uint32_t.
@@ -109,16 +122,20 @@ struct BaselineScript
// For heavyweight scripts, template objects to use for the call object and
// decl env object (linked via the call object's enclosing scope).
HeapPtrObject templateScope_;
// 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_;
// Native code offset right before the frame is popped and the method
// returned from.
uint32_t epilogueOffset_;
// The offsets for the toggledJump instructions for SPS update ICs.
@@ -342,16 +359,20 @@ struct BaselineScript
uint8_t *nativeCodeForPC(JSScript *script, jsbytecode *pc, PCMappingSlotInfo *slotInfo = nullptr);
jsbytecode *pcForReturnOffset(JSScript *script, uint32_t nativeOffset);
jsbytecode *pcForReturnAddress(JSScript *script, uint8_t *nativeAddress);
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);
public:
// Toggle debug traps (used for breakpoints and step mode) in the script.
// If |pc| is nullptr, toggle traps for all ops in the script. Else, only
// toggle traps at |pc|.
void toggleDebugTraps(JSScript *script, jsbytecode *pc);
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -7,17 +7,16 @@
#include "jit/Ion.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/ThreadLocal.h"
#include "jscompartment.h"
#include "jsprf.h"
-#include "asmjs/AsmJSModule.h"
#include "gc/Marking.h"
#include "jit/AliasAnalysis.h"
#include "jit/BacktrackingAllocator.h"
#include "jit/BaselineFrame.h"
#include "jit/BaselineInspector.h"
#include "jit/BaselineJIT.h"
#include "jit/CodeGenerator.h"
#include "jit/EdgeCaseAnalysis.h"
@@ -839,17 +838,16 @@ IonScript::IonScript()
callTargetList_(0),
callTargetEntries_(0),
backedgeList_(0),
backedgeEntries_(0),
invalidationCount_(0),
parallelAge_(0),
recompileInfo_(),
osrPcMismatchCounter_(0),
- dependentAsmJSModules(nullptr),
pendingBuilder_(nullptr)
{
}
IonScript *
IonScript::New(JSContext *cx, types::RecompileInfo recompileInfo,
uint32_t frameSlots, uint32_t frameSize,
size_t snapshotsListSize, size_t snapshotsRVATableSize,
@@ -1217,42 +1215,19 @@ IonScript::purgeCaches()
void
IonScript::destroyCaches()
{
for (size_t i = 0; i < numCaches(); i++)
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.
JitRuntime *jrt = fop->runtime()->jitRuntime();
JitRuntime::AutoMutateBackedges amb(jrt);
for (size_t i = 0; i < backedgeEntries_; i++)
jrt->removePatchableBackedge(&backedgeList()[i]);
--- a/js/src/jit/IonCode.h
+++ b/js/src/jit/IonCode.h
@@ -155,29 +155,16 @@ class SnapshotWriter;
class RecoverWriter;
class SafepointWriter;
class SafepointIndex;
class OsiIndex;
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
{
private:
// Code pointer containing the actual method.
PreBarrieredJitCode method_;
// Deoptimization table used by this method.
@@ -293,20 +280,16 @@ struct IonScript
// The optimization level this script was compiled in.
OptimizationLevel optimizationLevel_;
// Number of times we tried to enter this script via OSR but failed due to
// 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:
inline uint8_t *bottomBuffer() {
return reinterpret_cast<uint8_t *>(this);
}
inline const uint8_t *bottomBuffer() const {
return reinterpret_cast<const uint8_t *>(this);
@@ -347,29 +330,16 @@ struct IonScript
return &bottomBuffer()[runtimeData_];
}
JSScript **callTargetList() {
return (JSScript **) &bottomBuffer()[callTargetList_];
}
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);
public:
// Do not call directly, use IonScript::New. This is public for cx->new_.
IonScript();
--- a/js/src/jit/arm/MacroAssembler-arm.cpp
+++ b/js/src/jit/arm/MacroAssembler-arm.cpp
@@ -1856,21 +1856,21 @@ MacroAssemblerARMCompat::callIon(Registe
ma_callIonHalfPush(callee);
} else {
adjustFrame(sizeof(void*));
ma_callIon(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);
}
void
MacroAssembler::alignFrameForICArguments(AfterICSaveLive &aic)
{
--- a/js/src/jit/arm/MacroAssembler-arm.h
+++ b/js/src/jit/arm/MacroAssembler-arm.h
@@ -1288,17 +1288,17 @@ class MacroAssemblerARMCompat : public M
void callWithExitFrame(Label *target);
void callWithExitFrame(JitCode *target);
void callWithExitFrame(JitCode *target, Register dynStack);
// 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);
void freeStack(Register amount);
void add32(Register src, Register dest);
void add32(Imm32 imm, Register dest);
void add32(Imm32 imm, const Address &dest);
--- a/js/src/jit/mips/MacroAssembler-mips.cpp
+++ b/js/src/jit/mips/MacroAssembler-mips.cpp
@@ -1544,21 +1544,21 @@ MacroAssemblerMIPSCompat::callIon(Regist
if ((framePushed() & 7) == 4) {
ma_callIonHalfPush(callee);
} else {
adjustFrame(sizeof(uint32_t));
ma_callIon(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);
}
void
MacroAssemblerMIPSCompat::reserveStack(uint32_t amount)
{
--- a/js/src/jit/mips/MacroAssembler-mips.h
+++ b/js/src/jit/mips/MacroAssembler-mips.h
@@ -1135,17 +1135,17 @@ public:
void callWithExitFrame(Label *target);
void callWithExitFrame(JitCode *target);
void callWithExitFrame(JitCode *target, Register dynStack);
// 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);
void freeStack(Register amount);
void add32(Register src, Register dest);
void add32(Imm32 imm, Register dest);
void add32(Imm32 imm, const Address &dest);
--- a/js/src/jit/none/MacroAssembler-none.h
+++ b/js/src/jit/none/MacroAssembler-none.h
@@ -186,17 +186,17 @@ class MacroAssemblerNone : public Assemb
void setupUnalignedABICall(uint32_t, Register) { MOZ_CRASH(); }
template <typename T> void passABIArg(T, MoveOp::Type v = MoveOp::GENERAL) { MOZ_CRASH(); }
void callWithExitFrame(Label *) { MOZ_CRASH(); }
void callWithExitFrame(JitCode *) { MOZ_CRASH(); }
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(); }
void abiret() { MOZ_CRASH(); }
void ret() { MOZ_CRASH(); }
CodeOffsetLabel toggledJump(Label *) { MOZ_CRASH(); }
CodeOffsetLabel toggledCall(JitCode *, bool) { MOZ_CRASH(); }
--- a/js/src/jit/shared/MacroAssembler-x86-shared.h
+++ b/js/src/jit/shared/MacroAssembler-x86-shared.h
@@ -1200,17 +1200,17 @@ class MacroAssemblerX86Shared : public A
}
void call(const CallSiteDesc &desc, Register reg) {
call(reg);
append(desc, currentOffset(), framePushed_);
}
void callIon(Register callee) {
call(callee);
}
- void callIonFromAsmJS(Register callee) {
+ void callJitFromAsmJS(Register callee) {
call(callee);
}
void call(AsmJSImmPtr target) {
mov(target, eax);
call(eax);
}
void callAndPushReturnAddress(Label *label) {
call(label);