1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  * vim: set ts=8 sts=2 et sw=2 tw=80:
3  *
4  * Copyright 2021 Mozilla Foundation
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #ifndef wasm_tls_data_h
20 #define wasm_tls_data_h
21 
22 #include "mozilla/Atomics.h"
23 
24 #include <stdint.h>
25 
26 #include "NamespaceImports.h"
27 
28 #include "js/Utility.h"
29 #include "wasm/WasmTypeDecls.h"
30 
31 namespace js {
32 namespace wasm {
33 
34 using mozilla::Atomic;
35 
36 // TLS data for a single module instance.
37 //
38 // Every WebAssembly function expects to be passed a hidden TLS pointer argument
39 // in WasmTlsReg. The TLS pointer argument points to a TlsData struct.
40 // Compiled functions expect that the TLS pointer does not change for the
41 // lifetime of the thread.
42 //
43 // There is a TlsData per module instance per thread, so inter-module calls need
44 // to pass the TLS pointer appropriate for the callee module.
45 //
46 // After the TlsData struct follows the module's declared TLS variables.
47 
48 struct TlsData {
49   // Pointer to the base of the default memory (or null if there is none).
50   uint8_t* memoryBase;
51 
52   // Bounds check limit in bytes (or zero if there is no memory).  This is
53   // 64-bits on 64-bit systems so as to allow for heap lengths up to and beyond
54   // 4GB, and 32-bits on 32-bit systems, where heaps are limited to 2GB.
55   //
56   // On 64-bit systems, the upper bits of this value will be zero and 32-bit
57   // bounds checks can be used under the following circumstances:
58   //
59   // - The heap is for asm.js; asm.js heaps are limited to 2GB
60   // - The max size of the heap is encoded in the module and is less than 4GB
61   // - Cranelift is present in the system; Cranelift-compatible heaps are
62   //   limited to 4GB-128K
63   //
64   // All our jits require little-endian byte order, so the address of the 32-bit
65   // heap limit is the same as the address of the 64-bit heap limit: the address
66   // of this member.
67   uintptr_t boundsCheckLimit;
68 
69   // Pointer to the Instance that contains this TLS data.
70   Instance* instance;
71 
72   // Equal to instance->realm_.
73   JS::Realm* realm;
74 
75   // The containing JSContext.
76   JSContext* cx;
77 
78   // The class_ of WasmValueBox, this is a per-process value.
79   const JSClass* valueBoxClass;
80 
81   // Usually equal to cx->stackLimitForJitCode(JS::StackForUntrustedScript),
82   // but can be racily set to trigger immediate trap as an opportunity to
83   // CheckForInterrupt without an additional branch.
84   Atomic<uintptr_t, mozilla::Relaxed> stackLimit;
85 
86   // Set to 1 when wasm should call CheckForInterrupt.
87   Atomic<uint32_t, mozilla::Relaxed> interrupt;
88 
89   uint8_t* addressOfNeedsIncrementalBarrier;
90 
91   // Methods to set, test and clear the above two fields. Both interrupt
92   // fields are Relaxed and so no consistency/ordering can be assumed.
93   void setInterrupt();
94   bool isInterrupted() const;
95   void resetInterrupt(JSContext* cx);
96 
97   // Pointer that should be freed (due to padding before the TlsData).
98   void* allocatedBase;
99 
100   // When compiling with tiering, the jumpTable has one entry for each
101   // baseline-compiled function.
102   void** jumpTable;
103 
104   // The globalArea must be the last field.  Globals for the module start here
105   // and are inline in this structure.  16-byte alignment is required for SIMD
106   // data.
107   MOZ_ALIGNED_DECL(16, char globalArea);
108 };
109 
110 static const size_t TlsDataAlign = 16;  // = Simd128DataSize
111 static_assert(offsetof(TlsData, globalArea) % TlsDataAlign == 0, "aligned");
112 
113 struct TlsDataDeleter {
operatorTlsDataDeleter114   void operator()(TlsData* tlsData) { js_free(tlsData->allocatedBase); }
115 };
116 
117 using UniqueTlsData = UniquePtr<TlsData, TlsDataDeleter>;
118 
119 extern UniqueTlsData CreateTlsData(uint32_t globalDataLength);
120 
121 // ExportArg holds the unboxed operands to the wasm entry trampoline which can
122 // be called through an ExportFuncPtr.
123 
124 struct ExportArg {
125   uint64_t lo;
126   uint64_t hi;
127 };
128 
129 using ExportFuncPtr = int32_t (*)(ExportArg*, TlsData*);
130 
131 // FuncImportTls describes the region of wasm global memory allocated in the
132 // instance's thread-local storage for a function import. This is accessed
133 // directly from JIT code and mutated by Instance as exits become optimized and
134 // deoptimized.
135 
136 struct FuncImportTls {
137   // The code to call at an import site: a wasm callee, a thunk into C++, or a
138   // thunk into JIT code.
139   void* code;
140 
141   // The callee's TlsData pointer, which must be loaded to WasmTlsReg (along
142   // with any pinned registers) before calling 'code'.
143   TlsData* tls;
144 
145   // The callee function's realm.
146   JS::Realm* realm;
147 
148   // A GC pointer which keeps the callee alive and is used to recover import
149   // values for lazy table initialization.
150   GCPtrFunction fun;
151   static_assert(sizeof(GCPtrFunction) == sizeof(void*), "for JIT access");
152 };
153 
154 // TableTls describes the region of wasm global memory allocated in the
155 // instance's thread-local storage which is accessed directly from JIT code
156 // to bounds-check and index the table.
157 
158 struct TableTls {
159   // Length of the table in number of elements (not bytes).
160   uint32_t length;
161 
162   // Pointer to the array of elements (which can have various representations).
163   // For tables of anyref this is null.
164   void* functionBase;
165 };
166 
167 // Table element for TableRepr::Func which carries both the code pointer and
168 // a tls pointer (and thus anything reachable through the tls, including the
169 // instance).
170 
171 struct FunctionTableElem {
172   // The code to call when calling this element. The table ABI is the system
173   // ABI with the additional ABI requirements that:
174   //  - WasmTlsReg and any pinned registers have been loaded appropriately
175   //  - if this is a heterogeneous table that requires a signature check,
176   //    WasmTableCallSigReg holds the signature id.
177   void* code;
178 
179   // The pointer to the callee's instance's TlsData. This must be loaded into
180   // WasmTlsReg before calling 'code'.
181   TlsData* tls;
182 };
183 
184 }  // namespace wasm
185 }  // namespace js
186 
187 #endif  // wasm_tls_data_h
188