1 //! Keys for identifying functions during compilation, in call graphs, and when 2 //! resolving relocations. 3 4 #[cfg(feature = "component-model")] 5 use crate::component; 6 use crate::{ 7 BuiltinFunctionIndex, DefinedFuncIndex, HostCall, ModuleInternedTypeIndex, StaticModuleIndex, 8 }; 9 use core::{cmp, fmt}; 10 use serde_derive::{Deserialize, Serialize}; 11 12 /// The kind of a function that is being compiled, linked, or otherwise 13 /// referenced. 14 /// 15 /// This is like a `FuncKey` but without any payload values. 16 #[repr(u32)] 17 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] 18 #[cfg_attr(test, derive(arbitrary::Arbitrary))] 19 pub enum FuncKeyKind { 20 /// A Wasm-defined function. 21 DefinedWasmFunction = FuncKey::new_kind(0b0000), 22 23 /// A trampoline from an array-caller to the given Wasm-callee. 24 ArrayToWasmTrampoline = FuncKey::new_kind(0b0001), 25 26 /// A trampoline from a Wasm-caller to an array-callee of the given type. 27 WasmToArrayTrampoline = FuncKey::new_kind(0b0010), 28 29 /// A trampoline from a Wasm-caller to the given builtin. 30 WasmToBuiltinTrampoline = FuncKey::new_kind(0b0011), 31 32 /// A trampoline from the patchable ABI to the given builtin. 33 PatchableToBuiltinTrampoline = FuncKey::new_kind(0b0100), 34 35 /// A Pulley-specific host call. 36 PulleyHostCall = FuncKey::new_kind(0b0101), 37 38 /// A Wasm-caller to component builtin trampoline. 39 #[cfg(feature = "component-model")] 40 ComponentTrampoline = FuncKey::new_kind(0b0110), 41 42 /// A Wasm-caller to array-callee `resource.drop` trampoline. 43 #[cfg(feature = "component-model")] 44 ResourceDropTrampoline = FuncKey::new_kind(0b0111), 45 46 /// A Wasmtime unsafe intrinsic function. 47 #[cfg(feature = "component-model")] 48 UnsafeIntrinsic = FuncKey::new_kind(0b1000), 49 } 50 51 impl From<FuncKeyKind> for u32 { from(kind: FuncKeyKind) -> Self52 fn from(kind: FuncKeyKind) -> Self { 53 kind as u32 54 } 55 } 56 57 impl FuncKeyKind { 58 /// Get this kind's raw representation. into_raw(self) -> u3259 pub fn into_raw(self) -> u32 { 60 self.into() 61 } 62 63 /// Construct a `FuncKind` from its raw representation. 64 /// 65 /// Panics when given invalid raw representations. from_raw(raw: u32) -> Self66 pub fn from_raw(raw: u32) -> Self { 67 match raw { 68 x if x == Self::DefinedWasmFunction.into() => Self::DefinedWasmFunction, 69 x if x == Self::ArrayToWasmTrampoline.into() => Self::ArrayToWasmTrampoline, 70 x if x == Self::WasmToArrayTrampoline.into() => Self::WasmToArrayTrampoline, 71 x if x == Self::WasmToBuiltinTrampoline.into() => Self::WasmToBuiltinTrampoline, 72 x if x == Self::PatchableToBuiltinTrampoline.into() => { 73 Self::PatchableToBuiltinTrampoline 74 } 75 x if x == Self::PulleyHostCall.into() => Self::PulleyHostCall, 76 77 #[cfg(feature = "component-model")] 78 x if x == Self::ComponentTrampoline.into() => Self::ComponentTrampoline, 79 #[cfg(feature = "component-model")] 80 x if x == Self::ResourceDropTrampoline.into() => Self::ResourceDropTrampoline, 81 #[cfg(feature = "component-model")] 82 x if x == Self::UnsafeIntrinsic.into() => Self::UnsafeIntrinsic, 83 84 _ => panic!("invalid raw value passed to `FuncKind::from_raw`: {raw}"), 85 } 86 } 87 } 88 89 /// The namespace half of a `FuncKey`. 90 /// 91 /// This is an opaque combination of the key's kind and module index, if any. 92 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] 93 pub struct FuncKeyNamespace(u32); 94 95 impl fmt::Debug for FuncKeyNamespace { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result96 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 97 struct Hex<T: fmt::LowerHex>(T); 98 impl<T: fmt::LowerHex> fmt::Debug for Hex<T> { 99 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 100 write!(f, "{:#x}", self.0) 101 } 102 } 103 f.debug_struct("FuncKeyNamespace") 104 .field("raw", &Hex(self.0)) 105 .field("kind", &self.kind()) 106 .field("module", &self.module()) 107 .finish() 108 } 109 } 110 111 impl From<FuncKeyNamespace> for u32 { from(ns: FuncKeyNamespace) -> Self112 fn from(ns: FuncKeyNamespace) -> Self { 113 ns.0 114 } 115 } 116 117 impl FuncKeyNamespace { 118 /// Get this `FuncNamespace`'s raw representation. into_raw(self) -> u32119 pub fn into_raw(self) -> u32 { 120 self.0 121 } 122 123 /// Construct a `FuncNamespace` from its raw representation. 124 /// 125 /// Panics when given invalid raw representations. from_raw(raw: u32) -> Self126 pub fn from_raw(raw: u32) -> Self { 127 match FuncKeyKind::from_raw(raw & FuncKey::KIND_MASK) { 128 FuncKeyKind::DefinedWasmFunction | FuncKeyKind::ArrayToWasmTrampoline => Self(raw), 129 FuncKeyKind::WasmToArrayTrampoline 130 | FuncKeyKind::WasmToBuiltinTrampoline 131 | FuncKeyKind::PatchableToBuiltinTrampoline 132 | FuncKeyKind::PulleyHostCall => { 133 assert_eq!(raw & FuncKey::MODULE_MASK, 0); 134 Self(raw) 135 } 136 137 #[cfg(feature = "component-model")] 138 FuncKeyKind::ComponentTrampoline => { 139 let _ = Abi::from_raw(raw & FuncKey::MODULE_MASK); 140 Self(raw) 141 } 142 143 #[cfg(feature = "component-model")] 144 FuncKeyKind::ResourceDropTrampoline => { 145 assert_eq!(raw & FuncKey::MODULE_MASK, 0); 146 Self(raw) 147 } 148 149 #[cfg(feature = "component-model")] 150 FuncKeyKind::UnsafeIntrinsic => { 151 let _ = Abi::from_raw(raw & FuncKey::MODULE_MASK); 152 Self(raw) 153 } 154 } 155 } 156 157 /// Get this `FuncNamespace`'s kind. kind(&self) -> FuncKeyKind158 pub fn kind(&self) -> FuncKeyKind { 159 let raw = self.0 & FuncKey::KIND_MASK; 160 FuncKeyKind::from_raw(raw) 161 } 162 module(&self) -> u32163 fn module(&self) -> u32 { 164 self.0 & FuncKey::MODULE_MASK 165 } 166 } 167 168 /// The index half of a `FuncKey`. 169 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] 170 pub struct FuncKeyIndex(u32); 171 172 impl From<FuncKeyIndex> for u32 { from(index: FuncKeyIndex) -> Self173 fn from(index: FuncKeyIndex) -> Self { 174 index.0 175 } 176 } 177 178 impl FuncKeyIndex { 179 /// Get this index's raw representation. into_raw(self) -> u32180 pub fn into_raw(self) -> u32 { 181 self.0 182 } 183 184 /// Construct a `FuncKeyIndex` from its raw representation. 185 /// 186 /// Invalid raw representations will not be caught eagerly, but will cause 187 /// panics when paired with a `FuncKeyNamespace` to create a whole 188 /// `FuncKey`. from_raw(raw: u32) -> Self189 pub fn from_raw(raw: u32) -> Self { 190 FuncKeyIndex(raw) 191 } 192 } 193 194 /// ABI signature of functions that are generated here. 195 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] 196 #[cfg_attr(test, derive(arbitrary::Arbitrary))] 197 pub enum Abi { 198 /// The "wasm" ABI, or suitable to be a `wasm_call` field of a `VMFuncRef`. 199 Wasm = 0, 200 /// The "array" ABI, or suitable to be an `array_call` field. 201 Array = 1, 202 /// The "patchable" ABI. Signature same as Wasm ABI, but 203 /// Cranelift-level (machine-level) ABI is different (no 204 /// clobbers). 205 Patchable = 2, 206 } 207 208 #[cfg(feature = "component-model")] 209 impl Abi { from_raw(raw: u32) -> Self210 fn from_raw(raw: u32) -> Self { 211 match raw { 212 x if x == Self::Wasm.into_raw() => Self::Wasm, 213 x if x == Self::Array.into_raw() => Self::Array, 214 x if x == Self::Patchable.into_raw() => Self::Patchable, 215 _ => panic!("invalid raw representation passed to `Abi::from_raw`: {raw}"), 216 } 217 } 218 into_raw(self) -> u32219 fn into_raw(self) -> u32 { 220 (self as u8).into() 221 } 222 } 223 224 /// A sortable, comparable function key for compilation output, call graph 225 /// edges, and relocations. 226 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 227 pub enum FuncKey { 228 /// A Wasm-defined function. 229 DefinedWasmFunction(StaticModuleIndex, DefinedFuncIndex), 230 231 /// A trampoline from an array-caller to the given Wasm-callee. 232 ArrayToWasmTrampoline(StaticModuleIndex, DefinedFuncIndex), 233 234 /// A trampoline from a Wasm-caller to an array-callee of the given type. 235 WasmToArrayTrampoline(ModuleInternedTypeIndex), 236 237 /// A trampoline from a Wasm-caller to the given builtin. 238 WasmToBuiltinTrampoline(BuiltinFunctionIndex), 239 240 /// A Pulley-specific host call. 241 PulleyHostCall(HostCall), 242 243 /// A trampoline from the patchable ABI to the given builtin. 244 PatchableToBuiltinTrampoline(BuiltinFunctionIndex), 245 246 /// A Wasm-caller to component builtin trampoline. 247 #[cfg(feature = "component-model")] 248 ComponentTrampoline(Abi, component::TrampolineIndex), 249 250 /// A Wasm-caller to array-callee `resource.drop` trampoline. 251 #[cfg(feature = "component-model")] 252 ResourceDropTrampoline, 253 254 /// A Wasmtime intrinsic function. 255 #[cfg(feature = "component-model")] 256 UnsafeIntrinsic(Abi, component::UnsafeIntrinsic), 257 } 258 259 impl Ord for FuncKey { cmp(&self, other: &Self) -> cmp::Ordering260 fn cmp(&self, other: &Self) -> cmp::Ordering { 261 // Make sure to sort by our raw parts, because `CompiledFunctionsTable` 262 // relies on this for its binary search tables. 263 let raw_self = self.into_raw_parts(); 264 let raw_other = other.into_raw_parts(); 265 raw_self.cmp(&raw_other) 266 } 267 } 268 269 impl PartialOrd for FuncKey { partial_cmp(&self, other: &Self) -> Option<cmp::Ordering>270 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> { 271 Some(self.cmp(other)) 272 } 273 } 274 275 impl FuncKey { 276 const KIND_BITS: u32 = 4; 277 const KIND_OFFSET: u32 = 32 - Self::KIND_BITS; 278 const KIND_MASK: u32 = ((1 << Self::KIND_BITS) - 1) << Self::KIND_OFFSET; 279 const MODULE_MASK: u32 = !Self::KIND_MASK; 280 new_kind(kind: u32) -> u32281 const fn new_kind(kind: u32) -> u32 { 282 assert!(kind < (1 << Self::KIND_BITS)); 283 kind << Self::KIND_OFFSET 284 } 285 286 /// Split this key into its namespace and index halves. 287 #[inline] into_parts(self) -> (FuncKeyNamespace, FuncKeyIndex)288 pub fn into_parts(self) -> (FuncKeyNamespace, FuncKeyIndex) { 289 let (namespace, index) = match self { 290 FuncKey::DefinedWasmFunction(module, def_func) => { 291 assert_eq!(module.as_u32() & Self::KIND_MASK, 0); 292 let namespace = FuncKeyKind::DefinedWasmFunction.into_raw() | module.as_u32(); 293 let index = def_func.as_u32(); 294 (namespace, index) 295 } 296 FuncKey::ArrayToWasmTrampoline(module, def_func) => { 297 assert_eq!(module.as_u32() & Self::KIND_MASK, 0); 298 let namespace = FuncKeyKind::ArrayToWasmTrampoline.into_raw() | module.as_u32(); 299 let index = def_func.as_u32(); 300 (namespace, index) 301 } 302 FuncKey::WasmToArrayTrampoline(ty) => { 303 let namespace = FuncKeyKind::WasmToArrayTrampoline.into_raw(); 304 let index = ty.as_u32(); 305 (namespace, index) 306 } 307 FuncKey::WasmToBuiltinTrampoline(builtin) => { 308 let namespace = FuncKeyKind::WasmToBuiltinTrampoline.into_raw(); 309 let index = builtin.index(); 310 (namespace, index) 311 } 312 FuncKey::PatchableToBuiltinTrampoline(builtin) => { 313 let namespace = FuncKeyKind::PatchableToBuiltinTrampoline.into_raw(); 314 let index = builtin.index(); 315 (namespace, index) 316 } 317 FuncKey::PulleyHostCall(host_call) => { 318 let namespace = FuncKeyKind::PulleyHostCall.into_raw(); 319 let index = host_call.index(); 320 (namespace, index) 321 } 322 323 #[cfg(feature = "component-model")] 324 FuncKey::ComponentTrampoline(abi, trampoline) => { 325 let abi = abi.into_raw(); 326 assert_eq!(abi & Self::KIND_MASK, 0); 327 let namespace = FuncKeyKind::ComponentTrampoline.into_raw() | abi; 328 let index = trampoline.as_u32(); 329 (namespace, index) 330 } 331 #[cfg(feature = "component-model")] 332 FuncKey::ResourceDropTrampoline => { 333 let namespace = FuncKeyKind::ResourceDropTrampoline.into_raw(); 334 let index = 0; 335 (namespace, index) 336 } 337 #[cfg(feature = "component-model")] 338 FuncKey::UnsafeIntrinsic(abi, intrinsic) => { 339 let abi = abi.into_raw(); 340 assert_eq!(abi & Self::KIND_MASK, 0); 341 let namespace = FuncKeyKind::UnsafeIntrinsic.into_raw() | abi; 342 let index = intrinsic.index(); 343 (namespace, index) 344 } 345 }; 346 (FuncKeyNamespace(namespace), FuncKeyIndex(index)) 347 } 348 349 /// Get this key's kind. kind(self) -> FuncKeyKind350 pub fn kind(self) -> FuncKeyKind { 351 self.namespace().kind() 352 } 353 354 /// Get this key's namespace. namespace(self) -> FuncKeyNamespace355 pub fn namespace(self) -> FuncKeyNamespace { 356 self.into_parts().0 357 } 358 359 /// Get this key's index. index(self) -> FuncKeyIndex360 pub fn index(self) -> FuncKeyIndex { 361 self.into_parts().1 362 } 363 364 /// Get ABI of the function that this key is defining. abi(self) -> Abi365 pub fn abi(self) -> Abi { 366 match self { 367 FuncKey::DefinedWasmFunction(_, _) => Abi::Wasm, 368 FuncKey::ArrayToWasmTrampoline(_, _) => Abi::Array, 369 FuncKey::WasmToArrayTrampoline(_) => Abi::Wasm, 370 FuncKey::WasmToBuiltinTrampoline(_) => Abi::Wasm, 371 FuncKey::PatchableToBuiltinTrampoline(_) => Abi::Patchable, 372 FuncKey::PulleyHostCall(_) => Abi::Wasm, 373 #[cfg(feature = "component-model")] 374 FuncKey::ComponentTrampoline(abi, _) => abi, 375 #[cfg(feature = "component-model")] 376 FuncKey::ResourceDropTrampoline => Abi::Wasm, 377 #[cfg(feature = "component-model")] 378 FuncKey::UnsafeIntrinsic(abi, _) => abi, 379 } 380 } 381 382 /// Get the raw, underlying `(namespace, index)` representation of this 383 /// compilation key. 384 /// 385 /// The resulting values should only be used for (eventually) calling 386 /// `FuncKey::from_raw_parts` or `FuncKey{Namespace,Index}::from_raw`. 387 // 388 // NB: We use two `u32`s to exactly match 389 // `cranelift_codegen::ir::UserExternalName` and ensure that we can map 390 // one-to-one between that and `FuncKey`. into_raw_parts(self) -> (u32, u32)391 pub fn into_raw_parts(self) -> (u32, u32) { 392 let (ns, index) = self.into_parts(); 393 (ns.into_raw(), index.into_raw()) 394 } 395 396 /// Create a key from its namespace and index parts. 397 /// 398 /// Should only be called with namespaces and indices that are ultimately 399 /// derived from the same key. For example, if you attempt to pair an index 400 /// and namespace that come from different keys, that may panic. If it 401 /// happens not to panic, you'll end up with a valid key that names an 402 /// arbitrary function in the given namespace, but that function probably 403 /// does not actually exist in the compilation artifact. from_parts(namespace: FuncKeyNamespace, index: FuncKeyIndex) -> Self404 pub fn from_parts(namespace: FuncKeyNamespace, index: FuncKeyIndex) -> Self { 405 Self::from_raw_parts(namespace.into_raw(), index.into_raw()) 406 } 407 408 /// Create a key from its raw, underlying representation. 409 /// 410 /// Should only be given the results of a previous call to 411 /// `FuncKey::into_raw_parts`. 412 /// 413 /// Panics when given invalid raw parts. from_raw_parts(a: u32, b: u32) -> Self414 pub fn from_raw_parts(a: u32, b: u32) -> Self { 415 match FuncKeyKind::from_raw(a & Self::KIND_MASK) { 416 FuncKeyKind::DefinedWasmFunction => { 417 let module = StaticModuleIndex::from_u32(a & Self::MODULE_MASK); 418 let def_func = DefinedFuncIndex::from_u32(b); 419 Self::DefinedWasmFunction(module, def_func) 420 } 421 FuncKeyKind::ArrayToWasmTrampoline => { 422 let module = StaticModuleIndex::from_u32(a & Self::MODULE_MASK); 423 let def_func = DefinedFuncIndex::from_u32(b); 424 Self::ArrayToWasmTrampoline(module, def_func) 425 } 426 FuncKeyKind::WasmToArrayTrampoline => { 427 assert_eq!(a & Self::MODULE_MASK, 0); 428 let ty = ModuleInternedTypeIndex::from_u32(b); 429 Self::WasmToArrayTrampoline(ty) 430 } 431 FuncKeyKind::WasmToBuiltinTrampoline => { 432 assert_eq!(a & Self::MODULE_MASK, 0); 433 let builtin = BuiltinFunctionIndex::from_u32(b); 434 Self::WasmToBuiltinTrampoline(builtin) 435 } 436 FuncKeyKind::PatchableToBuiltinTrampoline => { 437 assert_eq!(a & Self::MODULE_MASK, 0); 438 let builtin = BuiltinFunctionIndex::from_u32(b); 439 Self::PatchableToBuiltinTrampoline(builtin) 440 } 441 FuncKeyKind::PulleyHostCall => { 442 assert_eq!(a & Self::MODULE_MASK, 0); 443 let host_call = HostCall::from_index(b); 444 Self::PulleyHostCall(host_call) 445 } 446 447 #[cfg(feature = "component-model")] 448 FuncKeyKind::ComponentTrampoline => { 449 let abi = Abi::from_raw(a & Self::MODULE_MASK); 450 let trampoline = component::TrampolineIndex::from_u32(b); 451 Self::ComponentTrampoline(abi, trampoline) 452 } 453 #[cfg(feature = "component-model")] 454 FuncKeyKind::ResourceDropTrampoline => { 455 assert_eq!(a & Self::MODULE_MASK, 0); 456 assert_eq!(b, 0); 457 Self::ResourceDropTrampoline 458 } 459 #[cfg(feature = "component-model")] 460 FuncKeyKind::UnsafeIntrinsic => { 461 let abi = Abi::from_raw(a & Self::MODULE_MASK); 462 let intrinsic = component::UnsafeIntrinsic::from_u32(b); 463 Self::UnsafeIntrinsic(abi, intrinsic) 464 } 465 } 466 } 467 468 /// Create a key from a raw packed `u64` representation. 469 /// 470 /// Should only be given a value produced by `into_raw_u64()`. 471 /// 472 /// Panics when given an invalid value. from_raw_u64(value: u64) -> Self473 pub fn from_raw_u64(value: u64) -> Self { 474 let hi = u32::try_from(value >> 32).unwrap(); 475 let lo = u32::try_from(value & 0xffff_ffff).unwrap(); 476 FuncKey::from_raw_parts(hi, lo) 477 } 478 479 /// Produce a packed `u64` representation of this key. 480 /// 481 /// May be used with `from_raw_64()` to reconstruct this key. into_raw_u64(&self) -> u64482 pub fn into_raw_u64(&self) -> u64 { 483 let (hi, lo) = self.into_raw_parts(); 484 (u64::from(hi) << 32) | u64::from(lo) 485 } 486 487 /// Unwrap a `FuncKey::DefinedWasmFunction` or else panic. unwrap_defined_wasm_function(self) -> (StaticModuleIndex, DefinedFuncIndex)488 pub fn unwrap_defined_wasm_function(self) -> (StaticModuleIndex, DefinedFuncIndex) { 489 match self { 490 Self::DefinedWasmFunction(module, def_func) => (module, def_func), 491 _ => panic!("`FuncKey::unwrap_defined_wasm_function` called on {self:?}"), 492 } 493 } 494 495 /// Unwrap a `FuncKey::ArrayToWasmTrampoline` or else panic. unwrap_array_to_wasm_trampoline(self) -> (StaticModuleIndex, DefinedFuncIndex)496 pub fn unwrap_array_to_wasm_trampoline(self) -> (StaticModuleIndex, DefinedFuncIndex) { 497 match self { 498 Self::ArrayToWasmTrampoline(module, def_func) => (module, def_func), 499 _ => panic!("`FuncKey::unwrap_array_to_wasm_trampoline` called on {self:?}"), 500 } 501 } 502 503 /// Unwrap a `FuncKey::WasmToArrayTrampoline` or else panic. unwrap_wasm_to_array_trampoline(self) -> ModuleInternedTypeIndex504 pub fn unwrap_wasm_to_array_trampoline(self) -> ModuleInternedTypeIndex { 505 match self { 506 Self::WasmToArrayTrampoline(ty) => ty, 507 _ => panic!("`FuncKey::unwrap_wasm_to_array_trampoline` called on {self:?}"), 508 } 509 } 510 511 /// Unwrap a `FuncKey::WasmToBuiltinTrampoline` or else panic. unwrap_wasm_to_builtin_trampoline(self) -> BuiltinFunctionIndex512 pub fn unwrap_wasm_to_builtin_trampoline(self) -> BuiltinFunctionIndex { 513 match self { 514 Self::WasmToBuiltinTrampoline(builtin) => builtin, 515 _ => panic!("`FuncKey::unwrap_wasm_to_builtin_trampoline` called on {self:?}"), 516 } 517 } 518 519 /// Unwrap a `FuncKey::PulleyHostCall` or else panic. unwrap_pulley_host_call(self) -> HostCall520 pub fn unwrap_pulley_host_call(self) -> HostCall { 521 match self { 522 Self::PulleyHostCall(host_call) => host_call, 523 _ => panic!("`FuncKey::unwrap_pulley_host_call` called on {self:?}"), 524 } 525 } 526 527 /// Unwrap a `FuncKey::ComponentTrampoline` or else panic. 528 #[cfg(feature = "component-model")] unwrap_component_trampoline(self) -> (crate::Abi, component::TrampolineIndex)529 pub fn unwrap_component_trampoline(self) -> (crate::Abi, component::TrampolineIndex) { 530 match self { 531 Self::ComponentTrampoline(abi, trampoline) => (abi, trampoline), 532 _ => panic!("`FuncKey::unwrap_component_trampoline` called on {self:?}"), 533 } 534 } 535 536 /// Unwrap a `FuncKey::ResourceDropTrampoline` or else panic. 537 #[cfg(feature = "component-model")] unwrap_resource_drop_trampoline(self)538 pub fn unwrap_resource_drop_trampoline(self) { 539 match self { 540 Self::ResourceDropTrampoline => {} 541 _ => panic!("`FuncKey::unwrap_resource_drop_trampoline` called on {self:?}"), 542 } 543 } 544 545 /// Is this "Store-invariant"? This allows us to execute 546 /// EngineCode directly rather than StoreCode. 547 /// 548 /// Any function that is either directly from Wasm code, or calls 549 /// it directly (not indirected through a runtime-provided 550 /// function pointer), is "store-variant": we need to use a 551 /// StoreCode-specific version of the code to hit any patching 552 /// that our specific instantiations may have (due to debugging 553 /// breakpoints, etc). Trampolines into the runtime cannot be 554 /// patched and so can use EngineCode instead. This allows for 555 /// less complex plumbing in some places where we can avoid 556 /// looking up the StoreCode (or having access to the Store). is_store_invariant(&self) -> bool557 pub fn is_store_invariant(&self) -> bool { 558 match self { 559 Self::DefinedWasmFunction(..) | Self::ArrayToWasmTrampoline(..) => false, 560 Self::WasmToArrayTrampoline(..) 561 | Self::WasmToBuiltinTrampoline(..) 562 | Self::PatchableToBuiltinTrampoline(..) 563 | Self::PulleyHostCall(..) => true, 564 #[cfg(feature = "component-model")] 565 Self::ComponentTrampoline(..) 566 | Self::ResourceDropTrampoline 567 | Self::UnsafeIntrinsic(..) => true, 568 } 569 } 570 } 571