From 72ef3e3d3847591765f4227bbfc2c8eca41402c9 Mon Sep 17 00:00:00 2001 From: Dmitry Bezhetskov Date: Sat, 31 Oct 2020 09:56:05 +0000 Subject: [PATCH] Bug 1639153 - Part 2: Preserve callee and caller tls'es. r=lth This is a followup patch for removing Frame::tls. Now, we are preserving caller's and callee's tls'es for all possible cross-instance calls in the previously allocated abi slots. We also use preserved tls values to restore the caller's tls in Ion. Baseline doesn't need this because it restores the caller tls from its private stack slot after the call. Depends on D82881 Differential Revision: https://phabricator.services.mozilla.com/D82888 --- js/src/jit/CodeGenerator.cpp | 3 ++- js/src/jit/MacroAssembler.cpp | 18 ++++++++++++++++++ js/src/jit/MacroAssembler.h | 5 +++++ js/src/wasm/WasmTypes.h | 13 +++++++++++++ 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp index e80b1f766f95..d7c565fe1e77 100644 --- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -8606,7 +8606,8 @@ void CodeGenerator::visitWasmCall(LWasmCall* lir) { MOZ_ASSERT(!lir->safepoint()->isWasmTrap()); if (reloadRegs) { - masm.loadWasmTlsRegFromFrame(); + masm.loadPtr(Address(masm.getStackPointer(), WasmCallerTLSOffsetBeforeCall), + WasmTlsReg); masm.loadWasmPinnedRegsFromTls(); if (switchRealm) { masm.switchToWasmTlsRealm(ABINonArgReturnReg0, ABINonArgReturnReg1); diff --git a/js/src/jit/MacroAssembler.cpp b/js/src/jit/MacroAssembler.cpp index d1c9ec718707..afcabfdfa655 100644 --- a/js/src/jit/MacroAssembler.cpp +++ b/js/src/jit/MacroAssembler.cpp @@ -3758,6 +3758,9 @@ std::pair MacroAssembler::wasmReserveStackChecked( CodeOffset MacroAssembler::wasmCallImport(const wasm::CallSiteDesc& desc, const wasm::CalleeDesc& callee) { + storePtr(WasmTlsReg, + Address(getStackPointer(), WasmCallerTLSOffsetBeforeCall)); + // Load the callee, before the caller's registers are clobbered. uint32_t globalDataOffset = callee.importGlobalDataOffset(); loadWasmGlobalPtr(globalDataOffset + offsetof(wasm::FuncImportTls, code), @@ -3776,6 +3779,9 @@ CodeOffset MacroAssembler::wasmCallImport(const wasm::CallSiteDesc& desc, // Switch to the callee's TLS and pinned registers and make the call. loadWasmGlobalPtr(globalDataOffset + offsetof(wasm::FuncImportTls, tls), WasmTlsReg); + + storePtr(WasmTlsReg, + Address(getStackPointer(), WasmCalleeTLSOffsetBeforeCall)); loadWasmPinnedRegsFromTls(); return call(desc, ABINonArgReg0); @@ -3786,6 +3792,10 @@ CodeOffset MacroAssembler::wasmCallBuiltinInstanceMethod( wasm::SymbolicAddress builtin, wasm::FailureMode failureMode) { MOZ_ASSERT(instanceArg != ABIArg()); + storePtr(WasmTlsReg, + Address(getStackPointer(), WasmCallerTLSOffsetBeforeCall)); + storePtr(WasmTlsReg, + Address(getStackPointer(), WasmCalleeTLSOffsetBeforeCall)); if (instanceArg.kind() == ABIArg::GPR) { loadPtr(Address(WasmTlsReg, offsetof(wasm::TlsData, instance)), instanceArg.gpr()); @@ -3851,6 +3861,10 @@ CodeOffset MacroAssembler::wasmCallIndirect(const wasm::CallSiteDesc& desc, addPtr(index, scratch); } loadPtr(Address(scratch, offsetof(wasm::FunctionTableElem, code)), scratch); + storePtr(WasmTlsReg, + Address(getStackPointer(), WasmCallerTLSOffsetBeforeCall)); + storePtr(WasmTlsReg, + Address(getStackPointer(), WasmCallerTLSOffsetBeforeCall)); return call(desc, scratch); } @@ -3892,7 +3906,11 @@ CodeOffset MacroAssembler::wasmCallIndirect(const wasm::CallSiteDesc& desc, addPtr(index, scratch); } + storePtr(WasmTlsReg, + Address(getStackPointer(), WasmCallerTLSOffsetBeforeCall)); loadPtr(Address(scratch, offsetof(wasm::FunctionTableElem, tls)), WasmTlsReg); + storePtr(WasmTlsReg, + Address(getStackPointer(), WasmCalleeTLSOffsetBeforeCall)); Label nonNull; branchTest32(Assembler::NonZero, WasmTlsReg, WasmTlsReg, &nonNull); diff --git a/js/src/jit/MacroAssembler.h b/js/src/jit/MacroAssembler.h index 1c03b77b6478..3c0c775874b3 100644 --- a/js/src/jit/MacroAssembler.h +++ b/js/src/jit/MacroAssembler.h @@ -260,6 +260,11 @@ static inline DynFn DynamicFunction(Sig fun); enum class CharEncoding { Latin1, TwoByte }; +constexpr uint32_t WasmCallerTLSOffsetBeforeCall = + wasm::FrameWithTls::callerTLSOffset() + ShadowStackSpace; +constexpr uint32_t WasmCalleeTLSOffsetBeforeCall = + wasm::FrameWithTls::calleeTLSOffset() + ShadowStackSpace; + // The public entrypoint for emitting assembly. Note that a MacroAssembler can // use cx->lifoAlloc, so take care not to interleave masm use with other // lifoAlloc use if one will be destroyed before the other. diff --git a/js/src/wasm/WasmTypes.h b/js/src/wasm/WasmTypes.h index 1bccb7dd7495..7205d493dddb 100644 --- a/js/src/wasm/WasmTypes.h +++ b/js/src/wasm/WasmTypes.h @@ -3311,8 +3311,21 @@ class FrameWithTls : public Frame { constexpr static uint32_t sizeWithoutFrame() { return sizeof(wasm::FrameWithTls) - sizeof(wasm::Frame); } + + constexpr static uint32_t calleeTLSOffset() { + return offsetof(FrameWithTls, calleeTls_) - sizeof(wasm::Frame); + } + + constexpr static uint32_t callerTLSOffset() { + return offsetof(FrameWithTls, callerTls_) - sizeof(wasm::Frame); + } }; +static_assert(FrameWithTls::calleeTLSOffset() == 0u, + "Callee tls stored right above the return address."); +static_assert(FrameWithTls::callerTLSOffset() == sizeof(void*), + "Caller tls stored right above the callee tls."); + static_assert(FrameWithTls::sizeWithoutFrame() == 2 * sizeof(void*), "There are only two additional slots"); -- 2.11.4.GIT