зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1639153 - Part 1: Reserve two slots after stack arguments for the future tls preservation. r=lth
We are going to remove Frame::tls and support trampolines for indirect calls, so we need to get rid of using Frame::tls. In this and the followup patches I will iteratively remove all dependencies of Frame::tls and remove it eventually. In this patch I changed wasm ABI to allocate two stack slots after stack args to preserve caller's and callee's tls'es in the near future. Differential Revision: https://phabricator.services.mozilla.com/D82881
This commit is contained in:
Родитель
2737da4055
Коммит
9534446dab
|
@ -15323,7 +15323,7 @@ void CodeGenerator::emitIonToWasmCallBase(LIonToWasmCallBase<NumDefs>* lir) {
|
||||||
const wasm::FuncExport& funcExport = lir->mir()->funcExport();
|
const wasm::FuncExport& funcExport = lir->mir()->funcExport();
|
||||||
const wasm::FuncType& sig = funcExport.funcType();
|
const wasm::FuncType& sig = funcExport.funcType();
|
||||||
|
|
||||||
ABIArgGenerator abi;
|
WasmABIArgGenerator abi;
|
||||||
for (size_t i = 0; i < lir->numOperands(); i++) {
|
for (size_t i = 0; i < lir->numOperands(); i++) {
|
||||||
MIRType argMir;
|
MIRType argMir;
|
||||||
switch (sig.args()[i].kind()) {
|
switch (sig.args()[i].kind()) {
|
||||||
|
|
|
@ -3049,8 +3049,8 @@ void MacroAssembler::freeStack(Register amount) { addToStackPtr(amount); }
|
||||||
|
|
||||||
// ===============================================================
|
// ===============================================================
|
||||||
// ABI function calls.
|
// ABI function calls.
|
||||||
|
template <class ABIArgGeneratorT>
|
||||||
void MacroAssembler::setupABICall() {
|
void MacroAssembler::setupABICallHelper() {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
MOZ_ASSERT(!inCall_);
|
MOZ_ASSERT(!inCall_);
|
||||||
inCall_ = true;
|
inCall_ = true;
|
||||||
|
@ -3061,7 +3061,7 @@ void MacroAssembler::setupABICall() {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Reinitialize the ABIArg generator.
|
// Reinitialize the ABIArg generator.
|
||||||
abiArgs_ = ABIArgGenerator();
|
abiArgs_ = ABIArgGeneratorT();
|
||||||
|
|
||||||
#if defined(JS_CODEGEN_ARM)
|
#if defined(JS_CODEGEN_ARM)
|
||||||
// On ARM, we need to know what ABI we are using, either in the
|
// On ARM, we need to know what ABI we are using, either in the
|
||||||
|
@ -3084,9 +3084,13 @@ void MacroAssembler::setupABICall() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroAssembler::setupNativeABICall() {
|
||||||
|
setupABICallHelper<ABIArgGenerator>();
|
||||||
|
}
|
||||||
|
|
||||||
void MacroAssembler::setupWasmABICall() {
|
void MacroAssembler::setupWasmABICall() {
|
||||||
MOZ_ASSERT(IsCompilingWasm(), "non-wasm should use setupAlignedABICall");
|
MOZ_ASSERT(IsCompilingWasm(), "non-wasm should use setupAlignedABICall");
|
||||||
setupABICall();
|
setupABICallHelper<WasmABIArgGenerator>();
|
||||||
|
|
||||||
#if defined(JS_CODEGEN_ARM)
|
#if defined(JS_CODEGEN_ARM)
|
||||||
// The builtin thunk does the FP -> GPR moving on soft-FP, so
|
// The builtin thunk does the FP -> GPR moving on soft-FP, so
|
||||||
|
@ -3098,7 +3102,7 @@ void MacroAssembler::setupWasmABICall() {
|
||||||
|
|
||||||
void MacroAssembler::setupAlignedABICall() {
|
void MacroAssembler::setupAlignedABICall() {
|
||||||
MOZ_ASSERT(!IsCompilingWasm(), "wasm should use setupWasmABICall");
|
MOZ_ASSERT(!IsCompilingWasm(), "wasm should use setupWasmABICall");
|
||||||
setupABICall();
|
setupNativeABICall();
|
||||||
dynamicAlignment_ = false;
|
dynamicAlignment_ = false;
|
||||||
|
|
||||||
#if defined(JS_CODEGEN_ARM64)
|
#if defined(JS_CODEGEN_ARM64)
|
||||||
|
|
|
@ -667,7 +667,12 @@ class MacroAssembler : public MacroAssemblerSpecific {
|
||||||
private:
|
private:
|
||||||
// Reinitialize the variables which have to be cleared before making a call
|
// Reinitialize the variables which have to be cleared before making a call
|
||||||
// with callWithABI.
|
// with callWithABI.
|
||||||
void setupABICall();
|
template <class ABIArgGeneratorT>
|
||||||
|
void setupABICallHelper();
|
||||||
|
|
||||||
|
// Reinitialize the variables which have to be cleared before making a call
|
||||||
|
// with native abi.
|
||||||
|
void setupNativeABICall();
|
||||||
|
|
||||||
// Reserve the stack and resolve the arguments move.
|
// Reserve the stack and resolve the arguments move.
|
||||||
void callWithABIPre(uint32_t* stackAdjust,
|
void callWithABIPre(uint32_t* stackAdjust,
|
||||||
|
@ -4335,9 +4340,9 @@ static inline MIRType ToMIRType(ABIArgType argType) {
|
||||||
// Helper for generatePreBarrier.
|
// Helper for generatePreBarrier.
|
||||||
inline DynFn JitMarkFunction(MIRType type);
|
inline DynFn JitMarkFunction(MIRType type);
|
||||||
|
|
||||||
template <class VecT>
|
template <class VecT, class ABIArgGeneratorT>
|
||||||
class ABIArgIter {
|
class ABIArgIterBase {
|
||||||
ABIArgGenerator gen_;
|
ABIArgGeneratorT gen_;
|
||||||
const VecT& types_;
|
const VecT& types_;
|
||||||
unsigned i_;
|
unsigned i_;
|
||||||
|
|
||||||
|
@ -4346,7 +4351,9 @@ class ABIArgIter {
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ABIArgIter(const VecT& types) : types_(types), i_(0) { settle(); }
|
explicit ABIArgIterBase(const VecT& types) : types_(types), i_(0) {
|
||||||
|
settle();
|
||||||
|
}
|
||||||
void operator++(int) {
|
void operator++(int) {
|
||||||
MOZ_ASSERT(!done());
|
MOZ_ASSERT(!done());
|
||||||
i_++;
|
i_++;
|
||||||
|
@ -4376,6 +4383,29 @@ class ABIArgIter {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// This is not an alias because we want to allow class template argument
|
||||||
|
// deduction.
|
||||||
|
template <class VecT>
|
||||||
|
class ABIArgIter : public ABIArgIterBase<VecT, ABIArgGenerator> {
|
||||||
|
public:
|
||||||
|
explicit ABIArgIter(const VecT& types)
|
||||||
|
: ABIArgIterBase<VecT, ABIArgGenerator>(types) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class WasmABIArgGenerator : public ABIArgGenerator {
|
||||||
|
public:
|
||||||
|
WasmABIArgGenerator() {
|
||||||
|
increaseStackOffset(wasm::FrameWithTls::sizeWithoutFrame());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class VecT>
|
||||||
|
class WasmABIArgIter : public ABIArgIterBase<VecT, WasmABIArgGenerator> {
|
||||||
|
public:
|
||||||
|
explicit WasmABIArgIter(const VecT& types)
|
||||||
|
: ABIArgIterBase<VecT, WasmABIArgGenerator>(types) {}
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace jit
|
} // namespace jit
|
||||||
} // namespace js
|
} // namespace js
|
||||||
|
|
||||||
|
|
|
@ -147,6 +147,7 @@ class ABIArgGenerator {
|
||||||
ABIArg next(MIRType argType);
|
ABIArg next(MIRType argType);
|
||||||
ABIArg& current() { return current_; }
|
ABIArg& current() { return current_; }
|
||||||
uint32_t stackBytesConsumedSoFar() const { return stackOffset_; }
|
uint32_t stackBytesConsumedSoFar() const { return stackOffset_; }
|
||||||
|
void increaseStackOffset(uint32_t bytes) { stackOffset_ += bytes; }
|
||||||
};
|
};
|
||||||
|
|
||||||
bool IsUnaligned(const wasm::MemoryAccessDesc& access);
|
bool IsUnaligned(const wasm::MemoryAccessDesc& access);
|
||||||
|
|
|
@ -4359,7 +4359,7 @@ void MacroAssembler::popReturnAddress() { pop(lr); }
|
||||||
// ABI function calls.
|
// ABI function calls.
|
||||||
|
|
||||||
void MacroAssembler::setupUnalignedABICall(Register scratch) {
|
void MacroAssembler::setupUnalignedABICall(Register scratch) {
|
||||||
setupABICall();
|
setupNativeABICall();
|
||||||
dynamicAlignment_ = true;
|
dynamicAlignment_ = true;
|
||||||
|
|
||||||
ma_mov(sp, scratch);
|
ma_mov(sp, scratch);
|
||||||
|
|
|
@ -421,6 +421,7 @@ class ABIArgGenerator {
|
||||||
ABIArg next(MIRType argType);
|
ABIArg next(MIRType argType);
|
||||||
ABIArg& current() { return current_; }
|
ABIArg& current() { return current_; }
|
||||||
uint32_t stackBytesConsumedSoFar() const { return stackOffset_; }
|
uint32_t stackBytesConsumedSoFar() const { return stackOffset_; }
|
||||||
|
void increaseStackOffset(uint32_t bytes) { stackOffset_ += bytes; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
unsigned intRegIndex_;
|
unsigned intRegIndex_;
|
||||||
|
|
|
@ -1099,7 +1099,7 @@ void MacroAssembler::popReturnAddress() {
|
||||||
// ABI function calls.
|
// ABI function calls.
|
||||||
|
|
||||||
void MacroAssembler::setupUnalignedABICall(Register scratch) {
|
void MacroAssembler::setupUnalignedABICall(Register scratch) {
|
||||||
setupABICall();
|
setupNativeABICall();
|
||||||
dynamicAlignment_ = true;
|
dynamicAlignment_ = true;
|
||||||
|
|
||||||
int64_t alignment = ~(int64_t(ABIStackAlignment) - 1);
|
int64_t alignment = ~(int64_t(ABIStackAlignment) - 1);
|
||||||
|
|
|
@ -43,6 +43,8 @@ class ABIArgGenerator {
|
||||||
|
|
||||||
return usedArgSlots_ * sizeof(intptr_t);
|
return usedArgSlots_ * sizeof(intptr_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void increaseStackOffset(uint32_t bytes) { MOZ_CRASH("NYI"); }
|
||||||
};
|
};
|
||||||
|
|
||||||
// These registers may be volatile or nonvolatile.
|
// These registers may be volatile or nonvolatile.
|
||||||
|
|
|
@ -2033,7 +2033,7 @@ void MacroAssembler::storeRegsInMask(LiveRegisterSet set, Address dest,
|
||||||
|
|
||||||
void MacroAssembler::setupUnalignedABICall(Register scratch) {
|
void MacroAssembler::setupUnalignedABICall(Register scratch) {
|
||||||
MOZ_ASSERT(!IsCompilingWasm(), "wasm should only use aligned ABI calls");
|
MOZ_ASSERT(!IsCompilingWasm(), "wasm should only use aligned ABI calls");
|
||||||
setupABICall();
|
setupNativeABICall();
|
||||||
dynamicAlignment_ = true;
|
dynamicAlignment_ = true;
|
||||||
|
|
||||||
ma_move(scratch, StackPointer);
|
ma_move(scratch, StackPointer);
|
||||||
|
|
|
@ -38,6 +38,7 @@ class ABIArgGenerator {
|
||||||
|
|
||||||
return (usedArgSlots_ - 8) * sizeof(int64_t);
|
return (usedArgSlots_ - 8) * sizeof(int64_t);
|
||||||
}
|
}
|
||||||
|
void increaseStackOffset(uint32_t bytes) { MOZ_CRASH("NYI"); }
|
||||||
};
|
};
|
||||||
|
|
||||||
// These registers may be volatile or nonvolatile.
|
// These registers may be volatile or nonvolatile.
|
||||||
|
|
|
@ -1875,7 +1875,7 @@ void MacroAssembler::storeRegsInMask(LiveRegisterSet set, Address dest,
|
||||||
|
|
||||||
void MacroAssembler::setupUnalignedABICall(Register scratch) {
|
void MacroAssembler::setupUnalignedABICall(Register scratch) {
|
||||||
MOZ_ASSERT(!IsCompilingWasm(), "wasm should only use aligned ABI calls");
|
MOZ_ASSERT(!IsCompilingWasm(), "wasm should only use aligned ABI calls");
|
||||||
setupABICall();
|
setupNativeABICall();
|
||||||
dynamicAlignment_ = true;
|
dynamicAlignment_ = true;
|
||||||
|
|
||||||
ma_move(scratch, StackPointer);
|
ma_move(scratch, StackPointer);
|
||||||
|
|
|
@ -619,6 +619,7 @@ class ABIArgGenerator {
|
||||||
ABIArg next(MIRType) { MOZ_CRASH(); }
|
ABIArg next(MIRType) { MOZ_CRASH(); }
|
||||||
ABIArg& current() { MOZ_CRASH(); }
|
ABIArg& current() { MOZ_CRASH(); }
|
||||||
uint32_t stackBytesConsumedSoFar() const { MOZ_CRASH(); }
|
uint32_t stackBytesConsumedSoFar() const { MOZ_CRASH(); }
|
||||||
|
void increaseStackOffset(uint32_t) { MOZ_CRASH(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline bool GetTempRegForIntArg(uint32_t, uint32_t, Register*) {
|
static inline bool GetTempRegForIntArg(uint32_t, uint32_t, Register*) {
|
||||||
|
|
|
@ -191,6 +191,7 @@ class ABIArgGenerator {
|
||||||
ABIArg next(MIRType argType);
|
ABIArg next(MIRType argType);
|
||||||
ABIArg& current() { return current_; }
|
ABIArg& current() { return current_; }
|
||||||
uint32_t stackBytesConsumedSoFar() const { return stackOffset_; }
|
uint32_t stackBytesConsumedSoFar() const { return stackOffset_; }
|
||||||
|
void increaseStackOffset(uint32_t bytes) { stackOffset_ += bytes; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// These registers may be volatile or nonvolatile.
|
// These registers may be volatile or nonvolatile.
|
||||||
|
|
|
@ -335,7 +335,7 @@ void MacroAssembler::subFromStackPtr(Imm32 imm32) {
|
||||||
// ABI function calls.
|
// ABI function calls.
|
||||||
|
|
||||||
void MacroAssembler::setupUnalignedABICall(Register scratch) {
|
void MacroAssembler::setupUnalignedABICall(Register scratch) {
|
||||||
setupABICall();
|
setupNativeABICall();
|
||||||
dynamicAlignment_ = true;
|
dynamicAlignment_ = true;
|
||||||
|
|
||||||
movq(rsp, scratch);
|
movq(rsp, scratch);
|
||||||
|
|
|
@ -87,6 +87,7 @@ class ABIArgGenerator {
|
||||||
ABIArg next(MIRType argType);
|
ABIArg next(MIRType argType);
|
||||||
ABIArg& current() { return current_; }
|
ABIArg& current() { return current_; }
|
||||||
uint32_t stackBytesConsumedSoFar() const { return stackOffset_; }
|
uint32_t stackBytesConsumedSoFar() const { return stackOffset_; }
|
||||||
|
void increaseStackOffset(uint32_t bytes) { stackOffset_ += bytes; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// These registers may be volatile or nonvolatile.
|
// These registers may be volatile or nonvolatile.
|
||||||
|
|
|
@ -334,7 +334,7 @@ void MacroAssembler::subFromStackPtr(Imm32 imm32) {
|
||||||
// ABI function calls.
|
// ABI function calls.
|
||||||
|
|
||||||
void MacroAssembler::setupUnalignedABICall(Register scratch) {
|
void MacroAssembler::setupUnalignedABICall(Register scratch) {
|
||||||
setupABICall();
|
setupNativeABICall();
|
||||||
dynamicAlignment_ = true;
|
dynamicAlignment_ = true;
|
||||||
|
|
||||||
movl(esp, scratch);
|
movl(esp, scratch);
|
||||||
|
|
|
@ -5268,7 +5268,7 @@ class BaseCompiler final : public BaseCompilerInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Identify GC-managed pointers passed on the stack.
|
// Identify GC-managed pointers passed on the stack.
|
||||||
for (ABIArgIter i(args); !i.done(); i++) {
|
for (WasmABIArgIter i(args); !i.done(); i++) {
|
||||||
ABIArg argLoc = *i;
|
ABIArg argLoc = *i;
|
||||||
if (argLoc.kind() == ABIArg::Stack &&
|
if (argLoc.kind() == ABIArg::Stack &&
|
||||||
args[i.index()] == MIRType::RefOrNull) {
|
args[i.index()] == MIRType::RefOrNull) {
|
||||||
|
@ -5354,7 +5354,7 @@ class BaseCompiler final : public BaseCompilerInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy arguments from registers to stack.
|
// Copy arguments from registers to stack.
|
||||||
for (ABIArgIter i(args); !i.done(); i++) {
|
for (WasmABIArgIter i(args); !i.done(); i++) {
|
||||||
if (args.isSyntheticStackResultPointerArg(i.index())) {
|
if (args.isSyntheticStackResultPointerArg(i.index())) {
|
||||||
// If there are stack results and the pointer to stack results
|
// If there are stack results and the pointer to stack results
|
||||||
// was passed in a register, store it to the stack.
|
// was passed in a register, store it to the stack.
|
||||||
|
@ -5619,7 +5619,7 @@ class BaseCompiler final : public BaseCompilerInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t lineOrBytecode;
|
uint32_t lineOrBytecode;
|
||||||
ABIArgGenerator abi;
|
WasmABIArgGenerator abi;
|
||||||
bool isInterModule;
|
bool isInterModule;
|
||||||
bool usesSystemAbi;
|
bool usesSystemAbi;
|
||||||
#ifdef JS_CODEGEN_ARM
|
#ifdef JS_CODEGEN_ARM
|
||||||
|
|
|
@ -41,7 +41,7 @@ class BaseLocalIter {
|
||||||
|
|
||||||
const ValTypeVector& locals_;
|
const ValTypeVector& locals_;
|
||||||
const ArgTypeVector& args_;
|
const ArgTypeVector& args_;
|
||||||
jit::ABIArgIter<ArgTypeVector> argsIter_;
|
jit::WasmABIArgIter<ArgTypeVector> argsIter_;
|
||||||
size_t index_;
|
size_t index_;
|
||||||
int32_t frameSize_;
|
int32_t frameSize_;
|
||||||
int32_t nextFrameSize_;
|
int32_t nextFrameSize_;
|
||||||
|
|
|
@ -128,7 +128,7 @@ bool CreateStackMapForFunctionEntryTrap(const wasm::ArgTypeVector& argTypes,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ABIArgIter i(argTypes); !i.done(); i++) {
|
for (WasmABIArgIter i(argTypes); !i.done(); i++) {
|
||||||
ABIArg argLoc = *i;
|
ABIArg argLoc = *i;
|
||||||
if (argLoc.kind() == ABIArg::Stack &&
|
if (argLoc.kind() == ABIArg::Stack &&
|
||||||
argTypes[i.index()] == MIRType::RefOrNull) {
|
argTypes[i.index()] == MIRType::RefOrNull) {
|
||||||
|
@ -183,7 +183,7 @@ bool GenerateStackmapEntriesForTrapExit(const ArgTypeVector& args,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ABIArgIter i(args); !i.done(); i++) {
|
for (WasmABIArgIter i(args); !i.done(); i++) {
|
||||||
if (!i->argInRegister() || i.mirType() != MIRType::RefOrNull) {
|
if (!i->argInRegister() || i.mirType() != MIRType::RefOrNull) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -261,7 +261,7 @@ class StackMaps {
|
||||||
// the complete native-ABI-level call signature.
|
// the complete native-ABI-level call signature.
|
||||||
template <class T>
|
template <class T>
|
||||||
static inline size_t StackArgAreaSizeUnaligned(const T& argTypes) {
|
static inline size_t StackArgAreaSizeUnaligned(const T& argTypes) {
|
||||||
ABIArgIter<const T> i(argTypes);
|
WasmABIArgIter<const T> i(argTypes);
|
||||||
while (!i.done()) {
|
while (!i.done()) {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
@ -270,7 +270,7 @@ static inline size_t StackArgAreaSizeUnaligned(const T& argTypes) {
|
||||||
|
|
||||||
static inline size_t StackArgAreaSizeUnaligned(
|
static inline size_t StackArgAreaSizeUnaligned(
|
||||||
const SymbolicAddressSignature& saSig) {
|
const SymbolicAddressSignature& saSig) {
|
||||||
// ABIArgIter::ABIArgIter wants the items to be iterated over to be
|
// WasmABIArgIter::ABIArgIter wants the items to be iterated over to be
|
||||||
// presented in some type that has methods length() and operator[]. So we
|
// presented in some type that has methods length() and operator[]. So we
|
||||||
// have to wrap up |saSig|'s array of types in this API-matching class.
|
// have to wrap up |saSig|'s array of types in this API-matching class.
|
||||||
class MOZ_STACK_CLASS ItemsAndLength {
|
class MOZ_STACK_CLASS ItemsAndLength {
|
||||||
|
|
|
@ -67,7 +67,7 @@ class FunctionCompiler;
|
||||||
|
|
||||||
class CallCompileState {
|
class CallCompileState {
|
||||||
// A generator object that is passed each argument as it is compiled.
|
// A generator object that is passed each argument as it is compiled.
|
||||||
ABIArgGenerator abi_;
|
WasmABIArgGenerator abi_;
|
||||||
|
|
||||||
// Accumulates the register arguments while compiling arguments.
|
// Accumulates the register arguments while compiling arguments.
|
||||||
MWasmCall::Args regArgs_;
|
MWasmCall::Args regArgs_;
|
||||||
|
@ -167,7 +167,7 @@ class FunctionCompiler {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ABIArgIter i(args); !i.done(); i++) {
|
for (WasmABIArgIter i(args); !i.done(); i++) {
|
||||||
MWasmParameter* ins = MWasmParameter::New(alloc(), *i, i.mirType());
|
MWasmParameter* ins = MWasmParameter::New(alloc(), *i, i.mirType());
|
||||||
curBlock_->add(ins);
|
curBlock_->add(ins);
|
||||||
if (args.isSyntheticStackResultPointerArg(i.index())) {
|
if (args.isSyntheticStackResultPointerArg(i.index())) {
|
||||||
|
|
|
@ -336,18 +336,28 @@ static void AssertStackAlignment(MacroAssembler& masm, uint32_t alignment,
|
||||||
masm.assertStackAlignment(alignment, addBeforeAssert);
|
masm.assertStackAlignment(alignment, addBeforeAssert);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class VectorT>
|
template <class VectorT, template <class VecT> class ABIArgIterT>
|
||||||
static unsigned StackArgBytes(const VectorT& args) {
|
static unsigned StackArgBytesHelper(const VectorT& args) {
|
||||||
ABIArgIter<VectorT> iter(args);
|
ABIArgIterT<VectorT> iter(args);
|
||||||
while (!iter.done()) {
|
while (!iter.done()) {
|
||||||
iter++;
|
iter++;
|
||||||
}
|
}
|
||||||
return iter.stackBytesConsumedSoFar();
|
return iter.stackBytesConsumedSoFar();
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned StackArgBytes(const FuncType& funcType) {
|
template <class VectorT>
|
||||||
|
static unsigned StackArgBytesForNativeABI(const VectorT& args) {
|
||||||
|
return StackArgBytesHelper<VectorT, ABIArgIter>(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class VectorT>
|
||||||
|
static unsigned StackArgBytesForWasmABI(const VectorT& args) {
|
||||||
|
return StackArgBytesHelper<VectorT, WasmABIArgIter>(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned StackArgBytesForWasmABI(const FuncType& funcType) {
|
||||||
ArgTypeVector args(funcType);
|
ArgTypeVector args(funcType);
|
||||||
return StackArgBytes(args);
|
return StackArgBytesForWasmABI(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Move64(MacroAssembler& masm, const Address& src,
|
static void Move64(MacroAssembler& masm, const Address& src,
|
||||||
|
@ -367,12 +377,12 @@ static void Move64(MacroAssembler& masm, const Address& src,
|
||||||
static void SetupABIArguments(MacroAssembler& masm, const FuncExport& fe,
|
static void SetupABIArguments(MacroAssembler& masm, const FuncExport& fe,
|
||||||
Register argv, Register scratch) {
|
Register argv, Register scratch) {
|
||||||
// Copy parameters out of argv and into the registers/stack-slots specified by
|
// Copy parameters out of argv and into the registers/stack-slots specified by
|
||||||
// the system ABI.
|
// the wasm ABI.
|
||||||
//
|
//
|
||||||
// SetupABIArguments are only used for C++ -> wasm calls through callExport(),
|
// SetupABIArguments are only used for C++ -> wasm calls through callExport(),
|
||||||
// and V128 and Ref types (other than externref) are not currently allowed.
|
// and V128 and Ref types (other than externref) are not currently allowed.
|
||||||
ArgTypeVector args(fe.funcType());
|
ArgTypeVector args(fe.funcType());
|
||||||
for (ABIArgIter iter(args); !iter.done(); iter++) {
|
for (WasmABIArgIter iter(args); !iter.done(); iter++) {
|
||||||
unsigned argOffset = iter.index() * sizeof(ExportArg);
|
unsigned argOffset = iter.index() * sizeof(ExportArg);
|
||||||
Address src(argv, argOffset);
|
Address src(argv, argOffset);
|
||||||
MIRType type = iter.mirType();
|
MIRType type = iter.mirType();
|
||||||
|
@ -808,9 +818,10 @@ static bool GenerateInterpEntry(MacroAssembler& masm, const FuncExport& fe,
|
||||||
masm.Push(scratch);
|
masm.Push(scratch);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Reserve stack space for the call.
|
// Reserve stack space for the wasm call.
|
||||||
unsigned argDecrement = StackDecrementForCall(
|
unsigned argDecrement =
|
||||||
WasmStackAlignment, masm.framePushed(), StackArgBytes(fe.funcType()));
|
StackDecrementForCall(WasmStackAlignment, masm.framePushed(),
|
||||||
|
StackArgBytesForWasmABI(fe.funcType()));
|
||||||
masm.reserveStack(argDecrement);
|
masm.reserveStack(argDecrement);
|
||||||
|
|
||||||
// Copy parameters out of argv and into the wasm ABI registers/stack-slots.
|
// Copy parameters out of argv and into the wasm ABI registers/stack-slots.
|
||||||
|
@ -1003,13 +1014,13 @@ static bool GenerateJitEntry(MacroAssembler& masm, size_t funcExportIndex,
|
||||||
// left):
|
// left):
|
||||||
// <-- retAddr | descriptor | callee | argc | this | arg1..N
|
// <-- retAddr | descriptor | callee | argc | this | arg1..N
|
||||||
|
|
||||||
unsigned normalBytesNeeded = StackArgBytes(fe.funcType());
|
unsigned normalBytesNeeded = StackArgBytesForWasmABI(fe.funcType());
|
||||||
|
|
||||||
MIRTypeVector coerceArgTypes;
|
MIRTypeVector coerceArgTypes;
|
||||||
MOZ_ALWAYS_TRUE(coerceArgTypes.append(MIRType::Int32));
|
MOZ_ALWAYS_TRUE(coerceArgTypes.append(MIRType::Int32));
|
||||||
MOZ_ALWAYS_TRUE(coerceArgTypes.append(MIRType::Pointer));
|
MOZ_ALWAYS_TRUE(coerceArgTypes.append(MIRType::Pointer));
|
||||||
MOZ_ALWAYS_TRUE(coerceArgTypes.append(MIRType::Pointer));
|
MOZ_ALWAYS_TRUE(coerceArgTypes.append(MIRType::Pointer));
|
||||||
unsigned oolBytesNeeded = StackArgBytes(coerceArgTypes);
|
unsigned oolBytesNeeded = StackArgBytesForWasmABI(coerceArgTypes);
|
||||||
|
|
||||||
unsigned bytesNeeded = std::max(normalBytesNeeded, oolBytesNeeded);
|
unsigned bytesNeeded = std::max(normalBytesNeeded, oolBytesNeeded);
|
||||||
|
|
||||||
|
@ -1201,7 +1212,7 @@ static bool GenerateJitEntry(MacroAssembler& masm, size_t funcExportIndex,
|
||||||
|
|
||||||
// Convert all the expected values to unboxed values on the stack.
|
// Convert all the expected values to unboxed values on the stack.
|
||||||
ArgTypeVector args(fe.funcType());
|
ArgTypeVector args(fe.funcType());
|
||||||
for (ABIArgIter iter(args); !iter.done(); iter++) {
|
for (WasmABIArgIter iter(args); !iter.done(); iter++) {
|
||||||
unsigned jitArgOffset =
|
unsigned jitArgOffset =
|
||||||
frameSize + JitFrameLayout::offsetOfActualArg(iter.index());
|
frameSize + JitFrameLayout::offsetOfActualArg(iter.index());
|
||||||
Address argv(sp, jitArgOffset);
|
Address argv(sp, jitArgOffset);
|
||||||
|
@ -1382,7 +1393,9 @@ static bool GenerateJitEntry(MacroAssembler& masm, size_t funcExportIndex,
|
||||||
masm.bind(&oolCall);
|
masm.bind(&oolCall);
|
||||||
masm.setFramePushed(frameSize);
|
masm.setFramePushed(frameSize);
|
||||||
|
|
||||||
ABIArgMIRTypeIter argsIter(coerceArgTypes);
|
// Baseline and Ion call C++ runtime via BuiltinThunk with wasm abi, so to
|
||||||
|
// unify the BuiltinThunk's interface we call it here with wasm abi.
|
||||||
|
jit::WasmABIArgIter<MIRTypeVector> argsIter(coerceArgTypes);
|
||||||
|
|
||||||
// argument 0: function export index.
|
// argument 0: function export index.
|
||||||
if (argsIter->kind() == ABIArg::GPR) {
|
if (argsIter->kind() == ABIArg::GPR) {
|
||||||
|
@ -1471,7 +1484,7 @@ void wasm::GenerateDirectCallFromJit(MacroAssembler& masm, const FuncExport& fe,
|
||||||
masm.orPtr(Imm32(ExitOrJitEntryFPTag), FramePointer);
|
masm.orPtr(Imm32(ExitOrJitEntryFPTag), FramePointer);
|
||||||
|
|
||||||
// Move stack arguments to their final locations.
|
// Move stack arguments to their final locations.
|
||||||
unsigned bytesNeeded = StackArgBytes(fe.funcType());
|
unsigned bytesNeeded = StackArgBytesForWasmABI(fe.funcType());
|
||||||
bytesNeeded = StackDecrementForCall(WasmStackAlignment, masm.framePushed(),
|
bytesNeeded = StackDecrementForCall(WasmStackAlignment, masm.framePushed(),
|
||||||
bytesNeeded);
|
bytesNeeded);
|
||||||
if (bytesNeeded) {
|
if (bytesNeeded) {
|
||||||
|
@ -1482,7 +1495,7 @@ void wasm::GenerateDirectCallFromJit(MacroAssembler& masm, const FuncExport& fe,
|
||||||
fe.funcIndex());
|
fe.funcIndex());
|
||||||
|
|
||||||
ArgTypeVector args(fe.funcType());
|
ArgTypeVector args(fe.funcType());
|
||||||
for (ABIArgIter iter(args); !iter.done(); iter++) {
|
for (WasmABIArgIter iter(args); !iter.done(); iter++) {
|
||||||
MOZ_ASSERT_IF(iter->kind() == ABIArg::GPR, iter->gpr() != scratch);
|
MOZ_ASSERT_IF(iter->kind() == ABIArg::GPR, iter->gpr() != scratch);
|
||||||
MOZ_ASSERT_IF(iter->kind() == ABIArg::GPR, iter->gpr() != FramePointer);
|
MOZ_ASSERT_IF(iter->kind() == ABIArg::GPR, iter->gpr() != FramePointer);
|
||||||
if (iter->kind() != ABIArg::Stack) {
|
if (iter->kind() != ABIArg::Stack) {
|
||||||
|
@ -1868,9 +1881,8 @@ static void FillArgumentArrayForExit(
|
||||||
#endif
|
#endif
|
||||||
masm.load64(src, scratch64);
|
masm.load64(src, scratch64);
|
||||||
GenPrintI64(DebugChannel::Import, masm, scratch64);
|
GenPrintI64(DebugChannel::Import, masm, scratch64);
|
||||||
GenerateBigIntInitialization(masm, offsetFromFPToCallerStackArgs,
|
GenerateBigIntInitialization(masm, sizeof(Frame), scratch64,
|
||||||
scratch64, scratch, nullptr,
|
scratch, nullptr, throwLabel);
|
||||||
throwLabel);
|
|
||||||
masm.storeValue(JSVAL_TYPE_BIGINT, scratch, dst);
|
masm.storeValue(JSVAL_TYPE_BIGINT, scratch, dst);
|
||||||
} else if (type == MIRType::RefOrNull) {
|
} else if (type == MIRType::RefOrNull) {
|
||||||
// This works also for FuncRef because it is distinguishable from a
|
// This works also for FuncRef because it is distinguishable from a
|
||||||
|
@ -1939,10 +1951,10 @@ static bool GenerateImportFunction(jit::MacroAssembler& masm,
|
||||||
|
|
||||||
MOZ_ASSERT(masm.framePushed() == 0);
|
MOZ_ASSERT(masm.framePushed() == 0);
|
||||||
const unsigned sizeOfTlsSlot = sizeof(void*);
|
const unsigned sizeOfTlsSlot = sizeof(void*);
|
||||||
unsigned framePushed =
|
unsigned framePushed = StackDecrementForCall(
|
||||||
StackDecrementForCall(WasmStackAlignment,
|
WasmStackAlignment,
|
||||||
sizeof(Frame), // pushed by prologue
|
sizeof(Frame), // pushed by prologue
|
||||||
StackArgBytes(fi.funcType()) + sizeOfTlsSlot);
|
StackArgBytesForWasmABI(fi.funcType()) + sizeOfTlsSlot);
|
||||||
masm.wasmReserveStackChecked(framePushed, BytecodeOffset(0));
|
masm.wasmReserveStackChecked(framePushed, BytecodeOffset(0));
|
||||||
MOZ_ASSERT(masm.framePushed() == framePushed);
|
MOZ_ASSERT(masm.framePushed() == framePushed);
|
||||||
|
|
||||||
|
@ -1956,7 +1968,7 @@ static bool GenerateImportFunction(jit::MacroAssembler& masm,
|
||||||
// Copy our frame's stack arguments to the callee frame's stack argument.
|
// Copy our frame's stack arguments to the callee frame's stack argument.
|
||||||
unsigned offsetFromFPToCallerStackArgs = sizeof(Frame);
|
unsigned offsetFromFPToCallerStackArgs = sizeof(Frame);
|
||||||
ArgTypeVector args(fi.funcType());
|
ArgTypeVector args(fi.funcType());
|
||||||
for (ABIArgIter i(args); !i.done(); i++) {
|
for (WasmABIArgIter i(args); !i.done(); i++) {
|
||||||
if (i->kind() != ABIArg::Stack) {
|
if (i->kind() != ABIArg::Stack) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -2041,7 +2053,7 @@ static bool GenerateImportInterpExit(MacroAssembler& masm, const FuncImport& fi,
|
||||||
// The padding between stack args and argv ensures that argv is aligned. The
|
// The padding between stack args and argv ensures that argv is aligned. The
|
||||||
// padding between argv and retaddr ensures that sp is aligned.
|
// padding between argv and retaddr ensures that sp is aligned.
|
||||||
unsigned argOffset =
|
unsigned argOffset =
|
||||||
AlignBytes(StackArgBytes(invokeArgTypes), sizeof(double));
|
AlignBytes(StackArgBytesForNativeABI(invokeArgTypes), sizeof(double));
|
||||||
// The abiArgCount includes a stack result pointer argument if needed.
|
// The abiArgCount includes a stack result pointer argument if needed.
|
||||||
unsigned abiArgCount = ArgTypeVector(fi.funcType()).lengthWithStackResults();
|
unsigned abiArgCount = ArgTypeVector(fi.funcType()).lengthWithStackResults();
|
||||||
unsigned argBytes = std::max<size_t>(1, abiArgCount) * sizeof(Value);
|
unsigned argBytes = std::max<size_t>(1, abiArgCount) * sizeof(Value);
|
||||||
|
@ -2054,7 +2066,7 @@ static bool GenerateImportInterpExit(MacroAssembler& masm, const FuncImport& fi,
|
||||||
offsets);
|
offsets);
|
||||||
|
|
||||||
// Fill the argument array.
|
// Fill the argument array.
|
||||||
unsigned offsetFromFPToCallerStackArgs = sizeof(Frame);
|
unsigned offsetFromFPToCallerStackArgs = sizeof(FrameWithTls);
|
||||||
Register scratch = ABINonArgReturnReg0;
|
Register scratch = ABINonArgReturnReg0;
|
||||||
Register scratch2 = ABINonArgReturnReg1;
|
Register scratch2 = ABINonArgReturnReg1;
|
||||||
// The scratch3 reg does not need to be non-volatile, but has to be
|
// The scratch3 reg does not need to be non-volatile, but has to be
|
||||||
|
@ -2262,7 +2274,7 @@ static bool GenerateImportJitExit(MacroAssembler& masm, const FuncImport& fi,
|
||||||
argOffset += sizeof(Value);
|
argOffset += sizeof(Value);
|
||||||
|
|
||||||
// 5. Fill the arguments.
|
// 5. Fill the arguments.
|
||||||
const uint32_t offsetFromFPToCallerStackArgs = sizeof(Frame);
|
const uint32_t offsetFromFPToCallerStackArgs = sizeof(FrameWithTls);
|
||||||
Register scratch = ABINonArgReturnReg1; // Repeatedly clobbered
|
Register scratch = ABINonArgReturnReg1; // Repeatedly clobbered
|
||||||
Register scratch2 = ABINonArgReturnReg0; // Reused as callee below
|
Register scratch2 = ABINonArgReturnReg0; // Reused as callee below
|
||||||
// The scratch3 reg does not need to be non-volatile, but has to be
|
// The scratch3 reg does not need to be non-volatile, but has to be
|
||||||
|
@ -2441,7 +2453,7 @@ static bool GenerateImportJitExit(MacroAssembler& masm, const FuncImport& fi,
|
||||||
MIRTypeVector coerceArgTypes;
|
MIRTypeVector coerceArgTypes;
|
||||||
MOZ_ALWAYS_TRUE(coerceArgTypes.append(MIRType::Pointer));
|
MOZ_ALWAYS_TRUE(coerceArgTypes.append(MIRType::Pointer));
|
||||||
unsigned offsetToCoerceArgv =
|
unsigned offsetToCoerceArgv =
|
||||||
AlignBytes(StackArgBytes(coerceArgTypes), sizeof(Value));
|
AlignBytes(StackArgBytesForWasmABI(coerceArgTypes), sizeof(Value));
|
||||||
MOZ_ASSERT(nativeFramePushed >= offsetToCoerceArgv + sizeof(Value));
|
MOZ_ASSERT(nativeFramePushed >= offsetToCoerceArgv + sizeof(Value));
|
||||||
AssertStackAlignment(masm, ABIStackAlignment);
|
AssertStackAlignment(masm, ABIStackAlignment);
|
||||||
|
|
||||||
|
@ -2573,14 +2585,14 @@ bool wasm::GenerateBuiltinThunk(MacroAssembler& masm, ABIFunctionType abiType,
|
||||||
uint32_t framePushed =
|
uint32_t framePushed =
|
||||||
StackDecrementForCall(ABIStackAlignment,
|
StackDecrementForCall(ABIStackAlignment,
|
||||||
sizeof(Frame), // pushed by prologue
|
sizeof(Frame), // pushed by prologue
|
||||||
StackArgBytes(args));
|
StackArgBytesForNativeABI(args));
|
||||||
|
|
||||||
GenerateExitPrologue(masm, framePushed, exitReason, offsets);
|
GenerateExitPrologue(masm, framePushed, exitReason, offsets);
|
||||||
|
|
||||||
// Copy out and convert caller arguments, if needed.
|
// Copy out and convert caller arguments, if needed.
|
||||||
unsigned offsetFromFPToCallerStackArgs = sizeof(Frame);
|
unsigned offsetFromFPToCallerStackArgs = sizeof(FrameWithTls);
|
||||||
Register scratch = ABINonArgReturnReg0;
|
Register scratch = ABINonArgReturnReg0;
|
||||||
for (ABIArgIter<ABIFunctionArgs> i(args); !i.done(); i++) {
|
for (ABIArgIter i(args); !i.done(); i++) {
|
||||||
if (i->argInRegister()) {
|
if (i->argInRegister()) {
|
||||||
#ifdef JS_CODEGEN_ARM
|
#ifdef JS_CODEGEN_ARM
|
||||||
// Non hard-fp passes the args values in GPRs.
|
// Non hard-fp passes the args values in GPRs.
|
||||||
|
|
|
@ -50,8 +50,8 @@ namespace js {
|
||||||
namespace jit {
|
namespace jit {
|
||||||
class JitScript;
|
class JitScript;
|
||||||
enum class RoundingMode;
|
enum class RoundingMode;
|
||||||
template <class VecT>
|
template <class VecT, class ABIArgGeneratorT>
|
||||||
class ABIArgIter;
|
class ABIArgIterBase;
|
||||||
} // namespace jit
|
} // namespace jit
|
||||||
|
|
||||||
// This is a widespread header, so lets keep out the core wasm impl types.
|
// This is a widespread header, so lets keep out the core wasm impl types.
|
||||||
|
@ -1311,13 +1311,13 @@ class ArgTypeVector {
|
||||||
const ValTypeVector& args_;
|
const ValTypeVector& args_;
|
||||||
bool hasStackResults_;
|
bool hasStackResults_;
|
||||||
|
|
||||||
// To allow ABIArgIter<ArgTypeVector>, we define a private length()
|
// To allow ABIArgIterBase<VecT, ABIArgGeneratorT>, we define a private
|
||||||
// method. To prevent accidental errors, other users need to be
|
// length() method. To prevent accidental errors, other users need to be
|
||||||
// explicit and call lengthWithStackResults() or
|
// explicit and call lengthWithStackResults() or
|
||||||
// lengthWithoutStackResults().
|
// lengthWithoutStackResults().
|
||||||
size_t length() const { return args_.length() + size_t(hasStackResults_); }
|
size_t length() const { return args_.length() + size_t(hasStackResults_); }
|
||||||
friend jit::ABIArgIter<ArgTypeVector>;
|
template <class VecT, class ABIArgGeneratorT>
|
||||||
friend jit::ABIArgIter<const ArgTypeVector>;
|
friend class jit::ABIArgIterBase;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ArgTypeVector(const ValTypeVector& args, StackResults stackResults)
|
ArgTypeVector(const ValTypeVector& args, StackResults stackResults)
|
||||||
|
@ -3303,6 +3303,19 @@ class Frame {
|
||||||
|
|
||||||
static_assert(!std::is_polymorphic_v<Frame>, "Frame doesn't need a vtable.");
|
static_assert(!std::is_polymorphic_v<Frame>, "Frame doesn't need a vtable.");
|
||||||
|
|
||||||
|
class FrameWithTls : public Frame {
|
||||||
|
public:
|
||||||
|
TlsData* calleeTls_;
|
||||||
|
TlsData* callerTls_;
|
||||||
|
|
||||||
|
constexpr static uint32_t sizeWithoutFrame() {
|
||||||
|
return sizeof(wasm::FrameWithTls) - sizeof(wasm::Frame);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(FrameWithTls::sizeWithoutFrame() == 2 * sizeof(void*),
|
||||||
|
"There are only two additional slots");
|
||||||
|
|
||||||
#if defined(JS_CODEGEN_ARM64)
|
#if defined(JS_CODEGEN_ARM64)
|
||||||
static_assert(sizeof(Frame) % 16 == 0, "frame is aligned");
|
static_assert(sizeof(Frame) % 16 == 0, "frame is aligned");
|
||||||
#endif
|
#endif
|
||||||
|
|
Загрузка…
Ссылка в новой задаче