WasmBuiltins.h (12579B)
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 2017 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_builtins_h 20 #define wasm_builtins_h 21 22 #include "intgemm/IntegerGemmIntrinsic.h" 23 #include "jit/IonTypes.h" 24 #include "wasm/WasmBuiltinModuleGenerated.h" 25 #include "wasm/WasmConstants.h" 26 27 namespace js { 28 class JitFrameIter; 29 namespace jit { 30 class AutoMarkJitCodeWritableForThread; 31 struct ResumeFromException; 32 } // namespace jit 33 namespace wasm { 34 35 class WasmFrameIter; 36 class CodeRange; 37 class FuncType; 38 39 // A wasm::SymbolicAddress represents a pointer to a well-known function/global 40 // that is embedded in wasm code. Since wasm code is serialized and later 41 // deserialized into a different address space, symbolic addresses must be used 42 // for *all* pointers into the address space. The MacroAssembler records a list 43 // of all SymbolicAddresses and the offsets of their use in the code for later 44 // patching during static linking. 45 46 enum class SymbolicAddress { 47 ToInt32, 48 #if defined(JS_CODEGEN_ARM) 49 aeabi_idivmod, 50 aeabi_uidivmod, 51 #endif 52 ModD, 53 SinNativeD, 54 SinFdlibmD, 55 CosNativeD, 56 CosFdlibmD, 57 TanNativeD, 58 TanFdlibmD, 59 ASinD, 60 ACosD, 61 ATanD, 62 CeilD, 63 CeilF, 64 FloorD, 65 FloorF, 66 TruncD, 67 TruncF, 68 NearbyIntD, 69 NearbyIntF, 70 ExpD, 71 LogD, 72 PowD, 73 ATan2D, 74 ArrayMemMove, 75 ArrayRefsMove, 76 HandleDebugTrap, 77 HandleRequestTierUp, 78 HandleThrow, 79 HandleTrap, 80 ReportV128JSCall, 81 CallImport_General, 82 CoerceInPlace_ToInt32, 83 CoerceInPlace_ToNumber, 84 CoerceInPlace_JitEntry, 85 CoerceInPlace_ToBigInt, 86 AllocateBigInt, 87 BoxValue_Anyref, 88 DivI64, 89 UDivI64, 90 ModI64, 91 UModI64, 92 TruncateDoubleToInt64, 93 TruncateDoubleToUint64, 94 SaturatingTruncateDoubleToInt64, 95 SaturatingTruncateDoubleToUint64, 96 Uint64ToFloat32, 97 Uint64ToDouble, 98 Int64ToFloat32, 99 Int64ToDouble, 100 MemoryGrowM32, 101 MemoryGrowM64, 102 MemorySizeM32, 103 MemorySizeM64, 104 WaitI32M32, 105 WaitI32M64, 106 WaitI64M32, 107 WaitI64M64, 108 WakeM32, 109 WakeM64, 110 MemCopyM32, 111 MemCopySharedM32, 112 MemCopyM64, 113 MemCopySharedM64, 114 MemCopyAny, 115 DataDrop, 116 MemFillM32, 117 MemFillSharedM32, 118 MemFillM64, 119 MemFillSharedM64, 120 MemDiscardM32, 121 MemDiscardSharedM32, 122 MemDiscardM64, 123 MemDiscardSharedM64, 124 MemInitM32, 125 MemInitM64, 126 TableCopy, 127 ElemDrop, 128 TableFill, 129 TableGet, 130 TableGrow, 131 TableInit, 132 TableSet, 133 TableSize, 134 RefFunc, 135 PostBarrierEdge, 136 PostBarrierEdgePrecise, 137 PostBarrierWholeCell, 138 ExceptionNew, 139 ThrowException, 140 StructNewIL_true, 141 StructNewIL_false, 142 StructNewOOL_true, 143 StructNewOOL_false, 144 ArrayNew_true, 145 ArrayNew_false, 146 ArrayNewData, 147 ArrayNewElem, 148 ArrayInitData, 149 ArrayInitElem, 150 ArrayCopy, 151 SlotsToAllocKindBytesTable, 152 #define VISIT_BUILTIN_FUNC(op, export, sa_name, ...) sa_name, 153 FOR_EACH_BUILTIN_MODULE_FUNC(VISIT_BUILTIN_FUNC) 154 #undef VISIT_BUILTIN_FUNC 155 #ifdef ENABLE_WASM_JSPI 156 UpdateSuspenderState, 157 #endif 158 #ifdef WASM_CODEGEN_DEBUG 159 PrintI32, 160 PrintPtr, 161 PrintF32, 162 PrintF64, 163 PrintText, 164 #endif 165 Limit 166 }; 167 168 // The FailureMode indicates whether, immediately after a call to a builtin 169 // returns, the return value should be checked against an error condition 170 // (and if so, which one) which signals that the C++ calle has already 171 // reported an error and thus wasm needs to wasmTrap(Trap::ThrowReported). 172 173 enum class FailureMode : uint8_t { 174 Infallible, 175 FailOnNegI32, 176 FailOnMaxI32, 177 FailOnNullPtr, 178 FailOnInvalidRef, 179 }; 180 181 // SymbolicAddressSignature carries type information for a function referred 182 // to by a SymbolicAddress. In order that |argTypes| can be written out as a 183 // static initialiser, it has to have fixed length. At present 184 // SymbolicAddressType is used to describe functions with at most 14 arguments, 185 // so |argTypes| has 15 entries in order to allow the last value to be 186 // MIRType::None, in the hope of catching any accidental overruns of the 187 // defined section of the array. 188 189 static constexpr size_t SymbolicAddressSignatureMaxArgs = 14; 190 191 struct SymbolicAddressSignature { 192 // The SymbolicAddress that is described. 193 const SymbolicAddress identity; 194 // The return type, or MIRType::None to denote 'void'. 195 const jit::MIRType retType; 196 // The failure mode, which is checked by masm.wasmCallBuiltinInstanceMethod. 197 const FailureMode failureMode; 198 // The trap to execute if the builtin fails. 199 const Trap failureTrap; 200 // The number of arguments, 0 .. SymbolicAddressSignatureMaxArgs only. 201 const uint8_t numArgs; 202 // The argument types; SymbolicAddressSignatureMaxArgs + 1 guard, which 203 // should be MIRType::None. 204 const jit::MIRType argTypes[SymbolicAddressSignatureMaxArgs + 1]; 205 }; 206 207 // The 32 in this assertion is derived as follows: SymbolicAddress is probably 208 // size-4 aligned-4, but it's at the start of the struct, so there's no 209 // alignment hole before it. All other components (MIRType and uint8_t) are 210 // size-1 aligned-1, and there are 18 in total, so it is reasonable to assume 211 // that they also don't create any alignment holes. Hence it is also 212 // reasonable to assume that the actual size is 1 * 4 + 18 * 1 == 22. The 213 // worst-plausible-case rounding will take that up to 32. Hence, the 214 // assertion uses 32. 215 216 static_assert(sizeof(SymbolicAddressSignature) <= 32, 217 "SymbolicAddressSignature unexpectedly large"); 218 219 // These provide argument type information for a subset of the SymbolicAddress 220 // targets, for which type info is needed to generate correct stackmaps. 221 222 extern const SymbolicAddressSignature SASigSinNativeD; 223 extern const SymbolicAddressSignature SASigSinFdlibmD; 224 extern const SymbolicAddressSignature SASigCosNativeD; 225 extern const SymbolicAddressSignature SASigCosFdlibmD; 226 extern const SymbolicAddressSignature SASigTanNativeD; 227 extern const SymbolicAddressSignature SASigTanFdlibmD; 228 extern const SymbolicAddressSignature SASigASinD; 229 extern const SymbolicAddressSignature SASigACosD; 230 extern const SymbolicAddressSignature SASigATanD; 231 extern const SymbolicAddressSignature SASigCeilD; 232 extern const SymbolicAddressSignature SASigCeilF; 233 extern const SymbolicAddressSignature SASigFloorD; 234 extern const SymbolicAddressSignature SASigFloorF; 235 extern const SymbolicAddressSignature SASigTruncD; 236 extern const SymbolicAddressSignature SASigTruncF; 237 extern const SymbolicAddressSignature SASigNearbyIntD; 238 extern const SymbolicAddressSignature SASigNearbyIntF; 239 extern const SymbolicAddressSignature SASigExpD; 240 extern const SymbolicAddressSignature SASigLogD; 241 extern const SymbolicAddressSignature SASigPowD; 242 extern const SymbolicAddressSignature SASigATan2D; 243 extern const SymbolicAddressSignature SASigArrayMemMove; 244 extern const SymbolicAddressSignature SASigArrayRefsMove; 245 extern const SymbolicAddressSignature SASigMemoryGrowM32; 246 extern const SymbolicAddressSignature SASigMemoryGrowM64; 247 extern const SymbolicAddressSignature SASigMemorySizeM32; 248 extern const SymbolicAddressSignature SASigMemorySizeM64; 249 extern const SymbolicAddressSignature SASigWaitI32M32; 250 extern const SymbolicAddressSignature SASigWaitI32M64; 251 extern const SymbolicAddressSignature SASigWaitI64M32; 252 extern const SymbolicAddressSignature SASigWaitI64M64; 253 extern const SymbolicAddressSignature SASigWakeM32; 254 extern const SymbolicAddressSignature SASigWakeM64; 255 extern const SymbolicAddressSignature SASigMemCopyM32; 256 extern const SymbolicAddressSignature SASigMemCopySharedM32; 257 extern const SymbolicAddressSignature SASigMemCopyM64; 258 extern const SymbolicAddressSignature SASigMemCopySharedM64; 259 extern const SymbolicAddressSignature SASigMemCopyAny; 260 extern const SymbolicAddressSignature SASigDataDrop; 261 extern const SymbolicAddressSignature SASigMemFillM32; 262 extern const SymbolicAddressSignature SASigMemFillSharedM32; 263 extern const SymbolicAddressSignature SASigMemFillM64; 264 extern const SymbolicAddressSignature SASigMemFillSharedM64; 265 extern const SymbolicAddressSignature SASigMemDiscardM32; 266 extern const SymbolicAddressSignature SASigMemDiscardSharedM32; 267 extern const SymbolicAddressSignature SASigMemDiscardM64; 268 extern const SymbolicAddressSignature SASigMemDiscardSharedM64; 269 extern const SymbolicAddressSignature SASigMemInitM32; 270 extern const SymbolicAddressSignature SASigMemInitM64; 271 extern const SymbolicAddressSignature SASigTableCopy; 272 extern const SymbolicAddressSignature SASigElemDrop; 273 extern const SymbolicAddressSignature SASigTableFill; 274 extern const SymbolicAddressSignature SASigTableGet; 275 extern const SymbolicAddressSignature SASigTableGrow; 276 extern const SymbolicAddressSignature SASigTableInit; 277 extern const SymbolicAddressSignature SASigTableSet; 278 extern const SymbolicAddressSignature SASigTableSize; 279 extern const SymbolicAddressSignature SASigRefFunc; 280 extern const SymbolicAddressSignature SASigPostBarrierEdge; 281 extern const SymbolicAddressSignature SASigPostBarrierEdgePrecise; 282 extern const SymbolicAddressSignature SASigPostBarrierWholeCell; 283 extern const SymbolicAddressSignature SASigExceptionNew; 284 extern const SymbolicAddressSignature SASigThrowException; 285 extern const SymbolicAddressSignature SASigStructNewIL_true; 286 extern const SymbolicAddressSignature SASigStructNewIL_false; 287 extern const SymbolicAddressSignature SASigStructNewOOL_true; 288 extern const SymbolicAddressSignature SASigStructNewOOL_false; 289 extern const SymbolicAddressSignature SASigArrayNew_true; 290 extern const SymbolicAddressSignature SASigArrayNew_false; 291 extern const SymbolicAddressSignature SASigArrayNewData; 292 extern const SymbolicAddressSignature SASigArrayNewElem; 293 extern const SymbolicAddressSignature SASigArrayInitData; 294 extern const SymbolicAddressSignature SASigArrayInitElem; 295 extern const SymbolicAddressSignature SASigArrayCopy; 296 extern const SymbolicAddressSignature SASigUpdateSuspenderState; 297 #define VISIT_BUILTIN_FUNC(op, export, sa_name, ...) \ 298 extern const SymbolicAddressSignature SASig##sa_name; 299 FOR_EACH_BUILTIN_MODULE_FUNC(VISIT_BUILTIN_FUNC) 300 #undef VISIT_BUILTIN_FUNC 301 302 bool IsRoundingFunction(SymbolicAddress callee, jit::RoundingMode* mode); 303 304 // A SymbolicAddress that NeedsBuiltinThunk() will call through a thunk to the 305 // C++ function. This will be true for all normal calls from normal wasm 306 // function code. Only calls to C++ from other exits/thunks do not need a thunk. 307 // See "The Wasm-builtin ABIs in WasmFrame.h". 308 309 bool NeedsBuiltinThunk(SymbolicAddress sym); 310 311 // Returns the ABI that needs to be used to call a builtin. 312 inline jit::ABIKind ABIForBuiltin(SymbolicAddress sym) { 313 // Builtin thunks use the WebAssembly ABI. See GenerateBuiltinThunk for more 314 // information. 315 if (NeedsBuiltinThunk(sym)) { 316 return jit::ABIKind::Wasm; 317 } 318 319 // Otherwise non-thunked builtins use the System ABI directly. 320 return jit::ABIKind::System; 321 } 322 323 // This function queries whether pc is in one of the process's builtin thunks 324 // and, if so, returns the CodeRange and pointer to the code segment that the 325 // CodeRange is relative to. 326 327 bool LookupBuiltinThunk(void* pc, const CodeRange** codeRange, 328 const uint8_t** codeBase); 329 330 // EnsureBuiltinThunksInitialized() must be called, and must succeed, before 331 // SymbolicAddressTarget() or MaybeGetBuiltinThunk(). This function creates all 332 // thunks for the process. ReleaseBuiltinThunks() should be called before 333 // ReleaseProcessExecutableMemory() so that the latter can assert that all 334 // executable code has been released. 335 336 bool EnsureBuiltinThunksInitialized(); 337 bool EnsureBuiltinThunksInitialized( 338 jit::AutoMarkJitCodeWritableForThread& writable); 339 340 void HandleExceptionWasm(JSContext* cx, JitFrameIter& iter, 341 jit::ResumeFromException* rfe); 342 343 void* SymbolicAddressTarget(SymbolicAddress sym); 344 345 void* ProvisionalLazyJitEntryStub(); 346 347 void* MaybeGetTypedNative(JSFunction* f, const FuncType& funcType); 348 349 void ReleaseBuiltinThunks(); 350 351 void* AddressOf(SymbolicAddress imm, jit::ABIFunctionType* abiType); 352 353 #ifdef WASM_CODEGEN_DEBUG 354 void PrintI32(int32_t val); 355 void PrintF32(float val); 356 void PrintF64(double val); 357 void PrintPtr(uint8_t* val); 358 void PrintText(const char* out); 359 #endif 360 361 } // namespace wasm 362 } // namespace js 363 364 #endif // wasm_builtins_h