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