xref: /wasmtime-44.0.1/crates/environ/src/key.rs (revision 17fbd3c6)
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