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-08-06 04:57:48 +00:00
Родитель d78a8c8c6a
Коммит 827e244302
15 изменённых файлов: 104 добавлений и 48 удалений

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

@ -14481,7 +14481,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()) {

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

@ -4144,9 +4144,9 @@ static inline MIRType ToMIRType(ABIArgType argType) {
MOZ_CRASH("unexpected argType"); MOZ_CRASH("unexpected argType");
} }
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_;
@ -4155,7 +4155,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_++;
@ -4185,6 +4187,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);

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

@ -415,6 +415,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_;

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

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

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

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

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

@ -617,6 +617,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*) {

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

@ -192,6 +192,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.

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

@ -5151,7 +5151,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) {
@ -5236,7 +5236,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.
@ -5501,7 +5501,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

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

@ -42,7 +42,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;
} }

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

@ -252,7 +252,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++;
} }
@ -261,7 +261,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 {

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

@ -64,7 +64,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_;
@ -161,7 +161,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())) {

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

@ -292,18 +292,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,
@ -323,12 +333,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 anyref) are not currently allowed. // and V128 and Ref types (other than anyref) 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();
@ -760,9 +770,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.
@ -955,13 +966,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 = StackArgBytesForNativeABI(coerceArgTypes);
unsigned bytesNeeded = std::max(normalBytesNeeded, oolBytesNeeded); unsigned bytesNeeded = std::max(normalBytesNeeded, oolBytesNeeded);
@ -1152,7 +1163,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);
@ -1411,7 +1422,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) {
@ -1422,7 +1433,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) {
@ -1877,10 +1888,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);
@ -1894,7 +1905,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;
} }
@ -1979,7 +1990,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);
@ -1992,7 +2003,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
@ -2213,7 +2224,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
@ -2391,7 +2402,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);
@ -2522,14 +2533,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.
@ -1276,13 +1276,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)
@ -3285,6 +3285,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