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:
Dmitry Bezhetskov 2020-10-23 18:17:36 +00:00
Родитель 2737da4055
Коммит 9534446dab
23 изменённых файлов: 131 добавлений и 64 удалений

Просмотреть файл

@ -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