Coverage Report

Created: 2026-09-28 08:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wasmtime/crates/environ/src/component/translate/inline.rs
Line
Count
Source
1
//! Implementation of "inlining" a component into a flat list of initializers.
2
//!
3
//! After the first phase of compiling a component we're left with a single
4
//! root `Translation` for the original component along with a "static" list of
5
//! child components. Each `Translation` has a list of `LocalInitializer` items
6
//! inside of it which is a primitive representation of how the component
7
//! should be constructed with effectively one initializer per item in the
8
//! index space of a component. This "local initializer" list would be
9
//! relatively inefficient to process at runtime and more importantly doesn't
10
//! convey enough information to understand what trampolines need to be
11
//! compiled or what fused adapters need to be generated. This consequently is
12
//! the motivation for this file.
13
//!
14
//! The second phase of compilation, inlining here, will in a sense interpret
15
//! the initializers, at compile time, into a new list of `GlobalInitializer` entries
16
//! which are a sort of "global initializer". The generated `GlobalInitializer` is
17
//! much more specific than the `LocalInitializer` and additionally far fewer
18
//! `GlobalInitializer` structures are generated (in theory) than there are local
19
//! initializers.
20
//!
21
//! The "inlining" portion of the name of this module indicates how the
22
//! instantiation of a component is interpreted as calling a function. The
23
//! function's arguments are the imports provided to the instantiation of a
24
//! component, and further nested function calls happen on a stack when a
25
//! nested component is instantiated. The inlining then refers to how this
26
//! stack of instantiations is flattened to one list of `GlobalInitializer`
27
//! entries to represent the process of instantiating a component graph,
28
//! similar to how function inlining removes call instructions and creates one
29
//! giant function for a call graph. Here there are no inlining heuristics or
30
//! anything like that, we simply inline everything into the root component's
31
//! list of initializers.
32
//!
33
//! Another primary task this module performs is a form of dataflow analysis
34
//! to represent items in each index space with their definition rather than
35
//! references of relative indices. These definitions (all the `*Def` types in
36
//! this module) are not local to any one nested component and instead
37
//! represent state available at runtime tracked in the final `Component`
38
//! produced.
39
//!
40
//! With all this pieced together the general idea is relatively
41
//! straightforward. All of a component's initializers are processed in sequence
42
//! where instantiating a nested component pushes a "frame" onto a stack to
43
//! start executing and we resume at the old one when we're done. Items are
44
//! tracked where they come from and at the end after processing only the
45
//! side-effectful initializers are emitted to the `GlobalInitializer` list in the
46
//! final `Component`.
47
48
use crate::component::translate::*;
49
use crate::{EntityType, Memory};
50
use core::str::FromStr;
51
use std::borrow::Cow;
52
use wasmparser::component_types::{ComponentAnyTypeId, ComponentCoreModuleTypeId};
53
54
6.10k
pub(super) fn run(
55
6.10k
    types: &mut ComponentTypesBuilder,
56
6.10k
    result: &Translation<'_>,
57
6.10k
    nested_modules: &PrimaryMap<StaticModuleIndex, ModuleTranslation<'_>>,
58
6.10k
    nested_components: &PrimaryMap<StaticComponentIndex, Translation<'_>>,
59
6.10k
) -> Result<dfg::ComponentDfg> {
60
6.10k
    let mut inliner = Inliner {
61
6.10k
        nested_modules,
62
6.10k
        nested_components,
63
6.10k
        result: Default::default(),
64
6.10k
        import_path_interner: Default::default(),
65
6.10k
        runtime_instances: PrimaryMap::default(),
66
6.10k
    };
67
68
6.10k
    let index = RuntimeComponentInstanceIndex::from_u32(0);
69
70
    // The initial arguments to the root component are all host imports. This
71
    // means that they're all using the `ComponentItemDef::Host` variant. Here
72
    // an `ImportIndex` is allocated for each item and then the argument is
73
    // recorded.
74
    //
75
    // Note that this is represents the abstract state of a host import of an
76
    // item since we don't know the precise structure of the host import.
77
6.10k
    let mut args = HashMap::with_capacity(result.exports.len());
78
6.10k
    let mut path = Vec::new();
79
6.10k
    types.resources_mut().set_current_instance(index);
80
6.10k
    let types_ref = result.types_ref();
81
74.9k
    for init in result.initializers.iter() {
82
74.9k
        let (name, ty) = match *init {
83
831
            LocalInitializer::Import(name, ty) => (name, ty),
84
74.0k
            _ => continue,
85
        };
86
87
        // Before `convert_component_entity_type` below all resource types
88
        // introduced by this import need to be registered and have indexes
89
        // assigned to them. Any fresh new resource type referred to by imports
90
        // is a brand new introduction of a resource which needs to have a type
91
        // allocated to it, so new runtime imports are injected for each
92
        // resource along with updating the `imported_resources` map.
93
831
        let index = inliner.result.import_types.next_key();
94
831
        types.resources_mut().register_component_entity_type(
95
831
            &types_ref,
96
831
            ty,
97
831
            &mut path,
98
350
            &mut |path| {
99
350
                let index = inliner.runtime_import(&ImportPath {
100
350
                    index,
101
350
                    path: path.iter().copied().map(Into::into).collect(),
102
350
                });
103
350
                inliner.result.imported_resources.push(index)
104
350
            },
105
        );
106
107
        // With resources all taken care of it's now possible to convert this
108
        // into Wasmtime's type system.
109
831
        let ty = types.convert_component_entity_type(types_ref, ty)?;
110
111
        // Imports of types that aren't resources are not required to be
112
        // specified by the host since it's just for type information within
113
        // the component.
114
831
        if let TypeDef::Interface(_) = ty {
115
30
            continue;
116
801
        }
117
801
        let index = inliner.result.import_types.push((
118
801
            name.name.to_string(),
119
801
            ComponentExtern {
120
801
                ty,
121
801
                data: ComponentExternData::new(name),
122
801
            },
123
801
        ));
124
801
        let path = ImportPath::root(index);
125
801
        args.insert(name.name, ComponentItemDef::from_import(path, ty)?);
126
    }
127
128
    // This will run the inliner to completion after being seeded with the
129
    // initial frame. When the inliner finishes it will return the exports of
130
    // the root frame which are then used for recording the exports of the
131
    // component.
132
6.09k
    inliner.result.num_runtime_component_instances += 1;
133
6.09k
    let frame = InlinerFrame::new(index, result, ComponentClosure::default(), args, None);
134
6.09k
    let resources_snapshot = types.resources_mut().clone();
135
6.09k
    let mut frames = vec![(frame, resources_snapshot)];
136
6.09k
    let exports = inliner.run(types, &mut frames)?;
137
6.09k
    assert!(frames.is_empty());
138
139
6.09k
    let mut export_map = Default::default();
140
11.0k
    for (name, (def, data)) in exports {
141
11.0k
        let data = ComponentExternData::new(data);
142
11.0k
        inliner.record_export(name, def, data, types, &mut export_map)?;
143
    }
144
6.08k
    inliner.result.exports = export_map;
145
6.08k
    inliner.result.num_future_tables = types.num_future_tables();
146
6.08k
    inliner.result.num_stream_tables = types.num_stream_tables();
147
6.08k
    inliner.result.num_error_context_tables = types.num_error_context_tables();
148
149
6.08k
    Ok(inliner.result)
150
6.10k
}
151
152
struct Inliner<'a> {
153
    /// The list of static modules that were found during initial translation of
154
    /// the component.
155
    ///
156
    /// This is used during the instantiation of these modules to ahead-of-time
157
    /// order the arguments precisely according to what the module is defined as
158
    /// needing which avoids the need to do string lookups or permute arguments
159
    /// at runtime.
160
    nested_modules: &'a PrimaryMap<StaticModuleIndex, ModuleTranslation<'a>>,
161
162
    /// The list of static components that were found during initial translation of
163
    /// the component.
164
    ///
165
    /// This is used when instantiating nested components to push a new
166
    /// `InlinerFrame` with the `Translation`s here.
167
    nested_components: &'a PrimaryMap<StaticComponentIndex, Translation<'a>>,
168
169
    /// The final `Component` that is being constructed and returned from this
170
    /// inliner.
171
    result: dfg::ComponentDfg,
172
173
    // Maps used to "intern" various runtime items to only save them once at
174
    // runtime instead of multiple times.
175
    import_path_interner: HashMap<ImportPath<'a>, RuntimeImportIndex>,
176
177
    /// Origin information about where each runtime instance came from
178
    runtime_instances: PrimaryMap<dfg::InstanceId, InstanceModule>,
179
}
180
181
/// A "stack frame" as part of the inlining process, or the progress through
182
/// instantiating a component.
183
///
184
/// All instantiations of a component will create an `InlinerFrame` and are
185
/// incrementally processed via the `initializers` list here. Note that the
186
/// inliner frames are stored on the heap to avoid recursion based on user
187
/// input.
188
struct InlinerFrame<'a> {
189
    instance: RuntimeComponentInstanceIndex,
190
191
    /// The remaining initializers to process when instantiating this component.
192
    initializers: std::slice::Iter<'a, LocalInitializer<'a>>,
193
194
    /// The component being instantiated.
195
    translation: &'a Translation<'a>,
196
197
    /// The "closure arguments" to this component, or otherwise the maps indexed
198
    /// by `ModuleUpvarIndex` and `ComponentUpvarIndex`. This is created when
199
    /// a component is created and stored as part of a component's state during
200
    /// inlining.
201
    closure: ComponentClosure<'a>,
202
203
    /// The arguments to the creation of this component.
204
    ///
205
    /// At the root level these are all imports from the host and between
206
    /// components this otherwise tracks how all the arguments are defined.
207
    args: HashMap<&'a str, ComponentItemDef<'a>>,
208
209
    // core wasm index spaces
210
    funcs: PrimaryMap<FuncIndex, (ModuleInternedTypeIndex, dfg::CoreDef)>,
211
    memories: PrimaryMap<MemoryIndex, dfg::CoreExport<EntityIndex>>,
212
    tables: PrimaryMap<TableIndex, dfg::CoreExport<EntityIndex>>,
213
    globals: PrimaryMap<GlobalIndex, dfg::CoreExport<EntityIndex>>,
214
    tags: PrimaryMap<TagIndex, dfg::CoreExport<EntityIndex>>,
215
    modules: PrimaryMap<ModuleIndex, ModuleDef<'a>>,
216
217
    // component model index spaces
218
    component_funcs: PrimaryMap<ComponentFuncIndex, ComponentFuncDef<'a>>,
219
    module_instances: PrimaryMap<ModuleInstanceIndex, ModuleInstanceDef<'a>>,
220
    component_instances: PrimaryMap<ComponentInstanceIndex, ComponentInstanceDef<'a>>,
221
    components: PrimaryMap<ComponentIndex, ComponentDef<'a>>,
222
223
    /// The type of instance produced by completing the instantiation of this
224
    /// frame.
225
    ///
226
    /// This is a wasmparser-relative piece of type information which is used to
227
    /// register resource types after instantiation has completed.
228
    ///
229
    /// This is `Some` for all subcomponents and `None` for the root component.
230
    instance_ty: Option<ComponentInstanceTypeId>,
231
}
232
233
/// "Closure state" for a component which is resolved from the `ClosedOverVars`
234
/// state that was calculated during translation.
235
//
236
// FIXME: this is cloned quite a lot and given the internal maps if this is a
237
// perf issue we may want to `Rc` these fields. Note that this is only a perf
238
// hit at compile-time though which we in general don't pay too much
239
// attention to.
240
#[derive(Default, Clone)]
241
struct ComponentClosure<'a> {
242
    modules: PrimaryMap<ModuleUpvarIndex, ModuleDef<'a>>,
243
    components: PrimaryMap<ComponentUpvarIndex, ComponentDef<'a>>,
244
}
245
246
/// Representation of a "path" into an import.
247
///
248
/// Imports from the host at this time are one of three things:
249
///
250
/// * Functions
251
/// * Core wasm modules
252
/// * "Instances" of these three items
253
///
254
/// The "base" values are functions and core wasm modules, but the abstraction
255
/// of an instance allows embedding functions/modules deeply within other
256
/// instances. This "path" represents optionally walking through a host instance
257
/// to get to the final desired item. At runtime instances are just maps of
258
/// values and so this is used to ensure that we primarily only deal with
259
/// individual functions and modules instead of synthetic instances.
260
#[derive(Clone, PartialEq, Hash, Eq)]
261
struct ImportPath<'a> {
262
    index: ImportIndex,
263
    path: Vec<Cow<'a, str>>,
264
}
265
266
/// Representation of all items which can be defined within a component.
267
///
268
/// This is the "value" of an item defined within a component and is used to
269
/// represent both imports and exports.
270
#[derive(Clone)]
271
enum ComponentItemDef<'a> {
272
    Component(ComponentDef<'a>),
273
    Instance(ComponentInstanceDef<'a>),
274
    Func(ComponentFuncDef<'a>),
275
    Module(ModuleDef<'a>),
276
    Type(TypeDef),
277
}
278
279
#[derive(Clone)]
280
enum ModuleDef<'a> {
281
    /// A core wasm module statically defined within the original component.
282
    ///
283
    /// The `StaticModuleIndex` indexes into the `static_modules` map in the
284
    /// `Inliner`.
285
    Static(StaticModuleIndex, ComponentCoreModuleTypeId),
286
287
    /// A core wasm module that was imported from the host.
288
    Import(ImportPath<'a>, TypeModuleIndex),
289
}
290
291
// Note that unlike all other `*Def` types which are not allowed to have local
292
// indices this type does indeed have local indices. That is represented with
293
// the lack of a `Clone` here where once this is created it's never moved across
294
// components because module instances always stick within one component.
295
enum ModuleInstanceDef<'a> {
296
    /// A core wasm module instance was created through the instantiation of a
297
    /// module.
298
    ///
299
    /// The `RuntimeInstanceIndex` was the index allocated as this was the
300
    /// `n`th instantiation and the `ModuleIndex` points into an
301
    /// `InlinerFrame`'s local index space.
302
    Instantiated(dfg::InstanceId, ModuleIndex),
303
304
    /// A "synthetic" core wasm module which is just a bag of named indices.
305
    ///
306
    /// Note that this can really only be used for passing as an argument to
307
    /// another module's instantiation and is used to rename arguments locally.
308
    Synthetic(&'a HashMap<&'a str, EntityIndex>),
309
}
310
311
#[derive(Clone)]
312
enum ComponentFuncDef<'a> {
313
    /// A compile-time builtin intrinsic.
314
    UnsafeIntrinsic(UnsafeIntrinsic),
315
316
    /// A host-imported component function.
317
    Import(ImportPath<'a>),
318
319
    /// A core wasm function was lifted into a component function.
320
    Lifted {
321
        /// The component function type.
322
        ty: TypeFuncIndex,
323
        /// The core Wasm function.
324
        func: dfg::CoreDef,
325
        /// Canonical options.
326
        options: AdapterOptions,
327
    },
328
}
329
330
#[derive(Clone)]
331
enum ComponentInstanceDef<'a> {
332
    /// The `__wasmtime_intrinsics` instance that exports all of our
333
    /// compile-time builtin intrinsics.
334
    Intrinsics,
335
336
    /// A host-imported instance.
337
    ///
338
    /// This typically means that it's "just" a map of named values. It's not
339
    /// actually supported to take a `wasmtime::component::Instance` and pass it
340
    /// to another instance at this time.
341
    Import(ImportPath<'a>, TypeComponentInstanceIndex),
342
343
    /// A concrete map of values.
344
    ///
345
    /// This is used for both instantiated components as well as "synthetic"
346
    /// components. This variant can be used for both because both are
347
    /// represented by simply a bag of items within the entire component
348
    /// instantiation process.
349
    //
350
    // FIXME: same as the issue on `ComponentClosure` where this is cloned a lot
351
    // and may need `Rc`.
352
    Items(
353
        IndexMap<&'a str, (ComponentItemDef<'a>, wasmparser::ComponentExternName<'a>)>,
354
        TypeComponentInstanceIndex,
355
    ),
356
}
357
358
#[derive(Clone)]
359
struct ComponentDef<'a> {
360
    index: StaticComponentIndex,
361
    closure: ComponentClosure<'a>,
362
}
363
364
impl<'a> Inliner<'a> {
365
    /// Symbolically instantiates a component using the type information and
366
    /// `frames` provided.
367
    ///
368
    /// The `types` provided is the type information for the entire component
369
    /// translation process. This is a distinct output artifact separate from
370
    /// the component metadata.
371
    ///
372
    /// The `frames` argument is storage to handle a "call stack" of components
373
    /// instantiating one another. The youngest frame (last element) of the
374
    /// frames list is a component that's currently having its initializers
375
    /// processed. The second element of each frame is a snapshot of the
376
    /// resource-related information just before the frame was translated. For
377
    /// more information on this snapshotting see the documentation on
378
    /// `ResourcesBuilder`.
379
6.09k
    fn run(
380
6.09k
        &mut self,
381
6.09k
        types: &mut ComponentTypesBuilder,
382
6.09k
        frames: &mut Vec<(InlinerFrame<'a>, ResourcesBuilder)>,
383
6.09k
    ) -> Result<IndexMap<&'a str, (ComponentItemDef<'a>, wasmparser::ComponentExternName<'a>)>>
384
    {
385
        // This loop represents the execution of the instantiation of a
386
        // component. This is an iterative process which is finished once all
387
        // initializers are processed. Currently this is modeled as an infinite
388
        // loop which drives the top-most iterator of the `frames` stack
389
        // provided as an argument to this function.
390
        loop {
391
281k
            let (frame, _) = frames.last_mut().unwrap();
392
281k
            types.resources_mut().set_current_instance(frame.instance);
393
281k
            match frame.initializers.next() {
394
                // Process the initializer and if it started the instantiation
395
                // of another component then we push that frame on the stack to
396
                // continue onwards.
397
260k
                Some(init) => match self.initializer(frames, types, init)? {
398
15.5k
                    Some(new_frame) => {
399
15.5k
                        frames.push((new_frame, types.resources_mut().clone()));
400
15.5k
                    }
401
244k
                    None => {}
402
                },
403
404
                // If there are no more initializers for this frame then the
405
                // component it represents has finished instantiation. The
406
                // exports of the component are collected and then the entire
407
                // frame is discarded. The exports are then either pushed in the
408
                // parent frame, if any, as a new component instance or they're
409
                // returned from this function for the root set of exports.
410
                None => {
411
21.6k
                    let exports = frame
412
21.6k
                        .translation
413
21.6k
                        .exports
414
21.6k
                        .iter()
415
33.1k
                        .map(|(name, (item, data))| Ok((*name, (frame.item(*item, types)?, *data))))
416
21.6k
                        .collect::<Result<_>>()?;
417
21.6k
                    let instance_ty = frame.instance_ty;
418
21.6k
                    let (_, snapshot) = frames.pop().unwrap();
419
21.6k
                    *types.resources_mut() = snapshot;
420
21.6k
                    match frames.last_mut() {
421
15.5k
                        Some((parent, _)) => {
422
15.5k
                            parent.finish_instantiate(exports, instance_ty.unwrap(), types)?;
423
                        }
424
6.09k
                        None => break Ok(exports),
425
                    }
426
                }
427
            }
428
        }
429
6.09k
    }
430
431
260k
    fn initializer(
432
260k
        &mut self,
433
260k
        frames: &mut Vec<(InlinerFrame<'a>, ResourcesBuilder)>,
434
260k
        types: &mut ComponentTypesBuilder,
435
260k
        initializer: &'a LocalInitializer,
436
260k
    ) -> Result<Option<InlinerFrame<'a>>> {
437
        use LocalInitializer::*;
438
439
260k
        let (frame, _) = frames.last_mut().unwrap();
440
260k
        match initializer {
441
            // When a component imports an item the actual definition of the
442
            // item is looked up here (not at runtime) via its name. The
443
            // arguments provided in our `InlinerFrame` describe how each
444
            // argument was defined, so we simply move it from there into the
445
            // correct index space.
446
            //
447
            // Note that for the root component this will add `*::Import` items
448
            // but for sub-components this will do resolution to connect what
449
            // was provided as an import at the instantiation-site to what was
450
            // needed during the component's instantiation.
451
15.6k
            Import(name, ty) => {
452
15.6k
                let arg = match frame.args.get(name.name) {
453
15.5k
                    Some(arg) => arg,
454
455
                    // Not all arguments need to be provided for instantiation,
456
                    // namely the root component in Wasmtime doesn't require
457
                    // structural type imports to be satisfied. These type
458
                    // imports are relevant for bindings generators and such but
459
                    // as a runtime there's not really a definition to fit in.
460
                    //
461
                    // If no argument was provided for `name` then it's asserted
462
                    // that this is a type import and additionally it's not a
463
                    // resource type import (which indeed must be provided). If
464
                    // all that passes then this initializer is effectively
465
                    // skipped.
466
                    None => {
467
30
                        match ty {
468
                            ComponentEntityType::Type {
469
                                created: ComponentAnyTypeId::Resource(_),
470
                                ..
471
0
                            } => unreachable!(),
472
30
                            ComponentEntityType::Type { .. } => {}
473
0
                            _ => unreachable!(),
474
                        }
475
30
                        return Ok(None);
476
                    }
477
                };
478
479
                // Next resource types need to be handled. For example if a
480
                // resource is imported into this component then it needs to be
481
                // assigned a unique table to provide the isolation guarantees
482
                // of resources (this component's table is shared with no
483
                // others). Here `register_component_entity_type` will find
484
                // imported resources and then `lookup_resource` will find the
485
                // resource within `arg` as necessary to lookup the original
486
                // true definition of this resource.
487
                //
488
                // This is what enables tracking true resource origins
489
                // throughout component translation while simultaneously also
490
                // tracking unique tables for each resource in each component.
491
15.5k
                let mut path = Vec::new();
492
15.5k
                let (resources, types) = types.resources_mut_and_types();
493
15.5k
                resources.register_component_entity_type(
494
15.5k
                    &frame.translation.types_ref(),
495
15.5k
                    *ty,
496
15.5k
                    &mut path,
497
947
                    &mut |path| arg.lookup_resource(path, types),
498
                );
499
500
                // And now with all the type information out of the way the
501
                // `arg` definition is moved into its corresponding index space.
502
15.5k
                frame.push_item(arg.clone());
503
            }
504
505
0
            IntrinsicsImport => {
506
0
                frame
507
0
                    .component_instances
508
0
                    .push(ComponentInstanceDef::Intrinsics);
509
0
            }
510
511
            // Lowering a component function to a core wasm function is
512
            // generally what "triggers compilation". Here various metadata is
513
            // recorded and then the final component gets an initializer
514
            // recording the lowering.
515
            //
516
            // NB: at this time only lowered imported functions are supported.
517
            Lower {
518
14.6k
                func,
519
14.6k
                options,
520
14.6k
                lower_ty,
521
            } => {
522
14.6k
                let lower_ty =
523
14.6k
                    types.convert_component_func_type(frame.translation.types_ref(), *lower_ty)?;
524
14.6k
                let options_lower = self.adapter_options(frames, types, options);
525
14.6k
                let (frame, _) = frames.last_mut().unwrap();
526
14.6k
                let lower_core_type = options_lower.core_type;
527
14.6k
                let func = match &frame.component_funcs[*func] {
528
                    // If this component function was originally a host import
529
                    // then this is a lowered host function which needs a
530
                    // trampoline to enter WebAssembly. That's recorded here
531
                    // with all relevant information.
532
264
                    ComponentFuncDef::Import(path) => {
533
264
                        let import = self.runtime_import(path);
534
264
                        let options = self.canonical_options(options_lower);
535
264
                        let index = self.result.trampolines.push((
536
264
                            lower_core_type,
537
264
                            dfg::Trampoline::LowerImport {
538
264
                                import,
539
264
                                options,
540
264
                                lower_ty,
541
264
                            },
542
264
                        ));
543
264
                        dfg::CoreDef::Trampoline(index)
544
                    }
545
546
                    // Lowering a lifted function means that a "fused adapter"
547
                    // was just identified.
548
                    //
549
                    // Metadata about this fused adapter is recorded in the
550
                    // `Adapters` output of this compilation pass. Currently the
551
                    // implementation of fused adapters is to generate a core
552
                    // wasm module which is instantiated with relevant imports
553
                    // and the exports are used as the fused adapters. At this
554
                    // time we don't know when precisely the instance will be
555
                    // created but we do know that the result of this will be an
556
                    // export from a previously-created instance.
557
                    //
558
                    // To model this the result of this arm is a
559
                    // `CoreDef::Export`. The actual indices listed within the
560
                    // export are "fake indices" in the sense of they're not
561
                    // resolved yet. This resolution will happen at a later
562
                    // compilation phase. Any usages of the `CoreDef::Export`
563
                    // here will be detected and rewritten to an actual runtime
564
                    // instance created.
565
                    //
566
                    // The `instance` field of the `CoreExport` has a marker
567
                    // which indicates that it's a fused adapter. The `item` is
568
                    // a function where the function index corresponds to the
569
                    // `adapter_idx` which contains the metadata about this
570
                    // adapter being created. The metadata is used to learn
571
                    // about the dependencies and when the adapter module can
572
                    // be instantiated.
573
                    ComponentFuncDef::Lifted {
574
14.3k
                        ty: lift_ty,
575
14.3k
                        func,
576
14.3k
                        options: options_lift,
577
                    } => {
578
14.3k
                        let adapter_idx = self.result.adapters.push(Adapter {
579
14.3k
                            lift_ty: *lift_ty,
580
14.3k
                            lift_options: options_lift.clone(),
581
14.3k
                            lower_ty,
582
14.3k
                            lower_options: options_lower,
583
14.3k
                            func: func.clone(),
584
14.3k
                        });
585
14.3k
                        dfg::CoreDef::Adapter(adapter_idx)
586
                    }
587
588
0
                    ComponentFuncDef::UnsafeIntrinsic(intrinsic) => {
589
0
                        dfg::CoreDef::UnsafeIntrinsic(options.core_type, *intrinsic)
590
                    }
591
                };
592
14.6k
                frame.funcs.push((lower_core_type, func));
593
            }
594
595
            // Lifting a core wasm function is relatively easy for now in that
596
            // some metadata about the lifting is simply recorded. This'll get
597
            // plumbed through to exports or a fused adapter later on.
598
22.2k
            Lift(ty, func, options) => {
599
22.2k
                let ty = types.convert_component_func_type(frame.translation.types_ref(), *ty)?;
600
22.2k
                let options = self.adapter_options(frames, types, options);
601
22.2k
                let (frame, _) = frames.last_mut().unwrap();
602
22.2k
                let func = frame.funcs[*func].1.clone();
603
22.2k
                frame
604
22.2k
                    .component_funcs
605
22.2k
                    .push(ComponentFuncDef::Lifted { ty, func, options });
606
            }
607
608
            // A new resource type is being introduced, so it's recorded as a
609
            // brand new resource in the final `resources` array. Additionally
610
            // for now resource introductions are considered side effects to
611
            // know when to register their destructors so that's recorded as
612
            // well.
613
            //
614
            // Note that this has the effect of when a component is instantiated
615
            // twice it will produce unique types for the resources from each
616
            // instantiation. That's the intended runtime semantics and
617
            // implementation here, however.
618
1.03k
            Resource(ty, rep, dtor) => {
619
1.03k
                let idx = self.result.resources.push(dfg::Resource {
620
1.03k
                    rep: *rep,
621
1.03k
                    dtor: dtor.map(|i| frame.funcs[i].1.clone()),
622
1.03k
                    instance: frame.instance,
623
                });
624
1.03k
                self.result
625
1.03k
                    .side_effects
626
1.03k
                    .push(dfg::SideEffect::Resource(idx));
627
628
                // Register with type translation that all future references to
629
                // `ty` will refer to `idx`.
630
                //
631
                // Note that this registration information is lost when this
632
                // component finishes instantiation due to the snapshotting
633
                // behavior in the frame processing loop above. This is also
634
                // intended, though, since `ty` can't be referred to outside of
635
                // this component.
636
1.03k
                let idx = self.result.resource_index(idx);
637
1.03k
                types.resources_mut().register_resource(ty.resource(), idx);
638
            }
639
640
            // Resource-related intrinsics are generally all the same.
641
            // Wasmparser type information is converted to wasmtime type
642
            // information and then new entries for each intrinsic are recorded.
643
870
            ResourceNew(id, ty) => {
644
870
                let id = types.resource_id(id.resource());
645
870
                let index = self.result.trampolines.push((
646
870
                    *ty,
647
870
                    dfg::Trampoline::ResourceNew {
648
870
                        instance: frame.instance,
649
870
                        ty: id,
650
870
                    },
651
870
                ));
652
870
                frame.funcs.push((*ty, dfg::CoreDef::Trampoline(index)));
653
870
            }
654
80
            ResourceRep(id, ty) => {
655
80
                let id = types.resource_id(id.resource());
656
80
                let index = self.result.trampolines.push((
657
80
                    *ty,
658
80
                    dfg::Trampoline::ResourceRep {
659
80
                        instance: frame.instance,
660
80
                        ty: id,
661
80
                    },
662
80
                ));
663
80
                frame.funcs.push((*ty, dfg::CoreDef::Trampoline(index)));
664
80
            }
665
943
            ResourceDrop(id, ty) => {
666
943
                let id = types.resource_id(id.resource());
667
943
                let index = self.result.trampolines.push((
668
943
                    *ty,
669
943
                    dfg::Trampoline::ResourceDrop {
670
943
                        instance: frame.instance,
671
943
                        ty: id,
672
943
                    },
673
943
                ));
674
943
                frame.funcs.push((*ty, dfg::CoreDef::Trampoline(index)));
675
943
            }
676
86
            BackpressureInc { func } => {
677
86
                let index = self.result.trampolines.push((
678
86
                    *func,
679
86
                    dfg::Trampoline::BackpressureInc {
680
86
                        instance: frame.instance,
681
86
                    },
682
86
                ));
683
86
                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
684
86
            }
685
73
            BackpressureDec { func } => {
686
73
                let index = self.result.trampolines.push((
687
73
                    *func,
688
73
                    dfg::Trampoline::BackpressureDec {
689
73
                        instance: frame.instance,
690
73
                    },
691
73
                ));
692
73
                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
693
73
            }
694
7.09k
            TaskReturn { result, options } => {
695
7.09k
                let results = result
696
7.09k
                    .iter()
697
7.09k
                    .map(|ty| types.valtype(frame.translation.types_ref(), ty))
698
7.09k
                    .collect::<Result<_>>()?;
699
7.09k
                let results = types.new_tuple_type(results);
700
7.09k
                let func = options.core_type;
701
7.09k
                let options = self.adapter_options(frames, types, options);
702
7.09k
                let (frame, _) = frames.last_mut().unwrap();
703
7.09k
                let options = self.canonical_options(options);
704
7.09k
                let index = self.result.trampolines.push((
705
7.09k
                    func,
706
7.09k
                    dfg::Trampoline::TaskReturn {
707
7.09k
                        instance: frame.instance,
708
7.09k
                        results,
709
7.09k
                        options,
710
7.09k
                    },
711
7.09k
                ));
712
7.09k
                frame.funcs.push((func, dfg::CoreDef::Trampoline(index)));
713
            }
714
108
            TaskCancel { func } => {
715
108
                let index = self.result.trampolines.push((
716
108
                    *func,
717
108
                    dfg::Trampoline::TaskCancel {
718
108
                        instance: frame.instance,
719
108
                    },
720
108
                ));
721
108
                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
722
108
            }
723
2.46k
            WaitableSetNew { func } => {
724
2.46k
                let index = self.result.trampolines.push((
725
2.46k
                    *func,
726
2.46k
                    dfg::Trampoline::WaitableSetNew {
727
2.46k
                        instance: frame.instance,
728
2.46k
                    },
729
2.46k
                ));
730
2.46k
                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
731
2.46k
            }
732
421
            WaitableSetWait { options } => {
733
421
                let func = options.core_type;
734
421
                let options = self.adapter_options(frames, types, options);
735
421
                let (frame, _) = frames.last_mut().unwrap();
736
421
                let options = self.canonical_options(options);
737
421
                let index = self.result.trampolines.push((
738
421
                    func,
739
421
                    dfg::Trampoline::WaitableSetWait {
740
421
                        instance: frame.instance,
741
421
                        options,
742
421
                    },
743
421
                ));
744
421
                frame.funcs.push((func, dfg::CoreDef::Trampoline(index)));
745
421
            }
746
84
            WaitableSetPoll { options } => {
747
84
                let func = options.core_type;
748
84
                let options = self.adapter_options(frames, types, options);
749
84
                let (frame, _) = frames.last_mut().unwrap();
750
84
                let options = self.canonical_options(options);
751
84
                let index = self.result.trampolines.push((
752
84
                    func,
753
84
                    dfg::Trampoline::WaitableSetPoll {
754
84
                        instance: frame.instance,
755
84
                        options,
756
84
                    },
757
84
                ));
758
84
                frame.funcs.push((func, dfg::CoreDef::Trampoline(index)));
759
84
            }
760
69
            WaitableSetDrop { func } => {
761
69
                let index = self.result.trampolines.push((
762
69
                    *func,
763
69
                    dfg::Trampoline::WaitableSetDrop {
764
69
                        instance: frame.instance,
765
69
                    },
766
69
                ));
767
69
                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
768
69
            }
769
2.33k
            WaitableJoin { func } => {
770
2.33k
                let index = self.result.trampolines.push((
771
2.33k
                    *func,
772
2.33k
                    dfg::Trampoline::WaitableJoin {
773
2.33k
                        instance: frame.instance,
774
2.33k
                    },
775
2.33k
                ));
776
2.33k
                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
777
2.33k
            }
778
2.09k
            SubtaskDrop { func } => {
779
2.09k
                let index = self.result.trampolines.push((
780
2.09k
                    *func,
781
2.09k
                    dfg::Trampoline::SubtaskDrop {
782
2.09k
                        instance: frame.instance,
783
2.09k
                    },
784
2.09k
                ));
785
2.09k
                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
786
2.09k
            }
787
187
            SubtaskCancel { func, async_ } => {
788
187
                let index = self.result.trampolines.push((
789
187
                    *func,
790
187
                    dfg::Trampoline::SubtaskCancel {
791
187
                        instance: frame.instance,
792
187
                        async_: *async_,
793
187
                    },
794
187
                ));
795
187
                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
796
187
            }
797
245
            StreamNew { ty, func } => {
798
245
                let InterfaceType::Stream(ty) =
799
245
                    types.defined_type(frame.translation.types_ref(), *ty)?
800
                else {
801
0
                    unreachable!()
802
                };
803
245
                let index = self.result.trampolines.push((
804
245
                    *func,
805
245
                    dfg::Trampoline::StreamNew {
806
245
                        instance: frame.instance,
807
245
                        ty,
808
245
                    },
809
245
                ));
810
245
                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
811
            }
812
211
            StreamRead { ty, options } => {
813
211
                let InterfaceType::Stream(ty) =
814
211
                    types.defined_type(frame.translation.types_ref(), *ty)?
815
                else {
816
0
                    unreachable!()
817
                };
818
211
                let func = options.core_type;
819
211
                let options = self.adapter_options(frames, types, options);
820
211
                let (frame, _) = frames.last_mut().unwrap();
821
211
                let options = self.canonical_options(options);
822
211
                let index = self.result.trampolines.push((
823
211
                    func,
824
211
                    dfg::Trampoline::StreamRead {
825
211
                        instance: frame.instance,
826
211
                        ty,
827
211
                        options,
828
211
                    },
829
211
                ));
830
211
                frame.funcs.push((func, dfg::CoreDef::Trampoline(index)));
831
            }
832
235
            StreamWrite { ty, options } => {
833
235
                let InterfaceType::Stream(ty) =
834
235
                    types.defined_type(frame.translation.types_ref(), *ty)?
835
                else {
836
0
                    unreachable!()
837
                };
838
235
                let func = options.core_type;
839
235
                let options = self.adapter_options(frames, types, options);
840
235
                let (frame, _) = frames.last_mut().unwrap();
841
235
                let options = self.canonical_options(options);
842
235
                let index = self.result.trampolines.push((
843
235
                    func,
844
235
                    dfg::Trampoline::StreamWrite {
845
235
                        instance: frame.instance,
846
235
                        ty,
847
235
                        options,
848
235
                    },
849
235
                ));
850
235
                frame.funcs.push((func, dfg::CoreDef::Trampoline(index)));
851
            }
852
57
            StreamCancelRead { ty, func, async_ } => {
853
57
                let InterfaceType::Stream(ty) =
854
57
                    types.defined_type(frame.translation.types_ref(), *ty)?
855
                else {
856
0
                    unreachable!()
857
                };
858
57
                let index = self.result.trampolines.push((
859
57
                    *func,
860
57
                    dfg::Trampoline::StreamCancelRead {
861
57
                        instance: frame.instance,
862
57
                        ty,
863
57
                        async_: *async_,
864
57
                    },
865
57
                ));
866
57
                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
867
            }
868
64
            StreamCancelWrite { ty, func, async_ } => {
869
64
                let InterfaceType::Stream(ty) =
870
64
                    types.defined_type(frame.translation.types_ref(), *ty)?
871
                else {
872
0
                    unreachable!()
873
                };
874
64
                let index = self.result.trampolines.push((
875
64
                    *func,
876
64
                    dfg::Trampoline::StreamCancelWrite {
877
64
                        instance: frame.instance,
878
64
                        ty,
879
64
                        async_: *async_,
880
64
                    },
881
64
                ));
882
64
                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
883
            }
884
132
            StreamDropReadable { ty, func } => {
885
132
                let InterfaceType::Stream(ty) =
886
132
                    types.defined_type(frame.translation.types_ref(), *ty)?
887
                else {
888
0
                    unreachable!()
889
                };
890
132
                let index = self.result.trampolines.push((
891
132
                    *func,
892
132
                    dfg::Trampoline::StreamDropReadable {
893
132
                        instance: frame.instance,
894
132
                        ty,
895
132
                    },
896
132
                ));
897
132
                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
898
            }
899
163
            StreamDropWritable { ty, func } => {
900
163
                let InterfaceType::Stream(ty) =
901
163
                    types.defined_type(frame.translation.types_ref(), *ty)?
902
                else {
903
0
                    unreachable!()
904
                };
905
163
                let index = self.result.trampolines.push((
906
163
                    *func,
907
163
                    dfg::Trampoline::StreamDropWritable {
908
163
                        instance: frame.instance,
909
163
                        ty,
910
163
                    },
911
163
                ));
912
163
                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
913
            }
914
296
            FutureNew { ty, func } => {
915
296
                let InterfaceType::Future(ty) =
916
296
                    types.defined_type(frame.translation.types_ref(), *ty)?
917
                else {
918
0
                    unreachable!()
919
                };
920
296
                let index = self.result.trampolines.push((
921
296
                    *func,
922
296
                    dfg::Trampoline::FutureNew {
923
296
                        instance: frame.instance,
924
296
                        ty,
925
296
                    },
926
296
                ));
927
296
                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
928
            }
929
258
            FutureRead { ty, options } => {
930
258
                let InterfaceType::Future(ty) =
931
258
                    types.defined_type(frame.translation.types_ref(), *ty)?
932
                else {
933
0
                    unreachable!()
934
                };
935
258
                let func = options.core_type;
936
258
                let options = self.adapter_options(frames, types, options);
937
258
                let (frame, _) = frames.last_mut().unwrap();
938
258
                let options = self.canonical_options(options);
939
258
                let index = self.result.trampolines.push((
940
258
                    func,
941
258
                    dfg::Trampoline::FutureRead {
942
258
                        instance: frame.instance,
943
258
                        ty,
944
258
                        options,
945
258
                    },
946
258
                ));
947
258
                frame.funcs.push((func, dfg::CoreDef::Trampoline(index)));
948
            }
949
224
            FutureWrite { ty, options } => {
950
224
                let InterfaceType::Future(ty) =
951
224
                    types.defined_type(frame.translation.types_ref(), *ty)?
952
                else {
953
0
                    unreachable!()
954
                };
955
224
                let func = options.core_type;
956
224
                let options = self.adapter_options(frames, types, options);
957
224
                let (frame, _) = frames.last_mut().unwrap();
958
224
                let options = self.canonical_options(options);
959
224
                let index = self.result.trampolines.push((
960
224
                    func,
961
224
                    dfg::Trampoline::FutureWrite {
962
224
                        instance: frame.instance,
963
224
                        ty,
964
224
                        options,
965
224
                    },
966
224
                ));
967
224
                frame.funcs.push((func, dfg::CoreDef::Trampoline(index)));
968
            }
969
33
            FutureCancelRead { ty, func, async_ } => {
970
33
                let InterfaceType::Future(ty) =
971
33
                    types.defined_type(frame.translation.types_ref(), *ty)?
972
                else {
973
0
                    unreachable!()
974
                };
975
33
                let index = self.result.trampolines.push((
976
33
                    *func,
977
33
                    dfg::Trampoline::FutureCancelRead {
978
33
                        instance: frame.instance,
979
33
                        ty,
980
33
                        async_: *async_,
981
33
                    },
982
33
                ));
983
33
                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
984
            }
985
37
            FutureCancelWrite { ty, func, async_ } => {
986
37
                let InterfaceType::Future(ty) =
987
37
                    types.defined_type(frame.translation.types_ref(), *ty)?
988
                else {
989
0
                    unreachable!()
990
                };
991
37
                let index = self.result.trampolines.push((
992
37
                    *func,
993
37
                    dfg::Trampoline::FutureCancelWrite {
994
37
                        instance: frame.instance,
995
37
                        ty,
996
37
                        async_: *async_,
997
37
                    },
998
37
                ));
999
37
                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1000
            }
1001
76
            FutureDropReadable { ty, func } => {
1002
76
                let InterfaceType::Future(ty) =
1003
76
                    types.defined_type(frame.translation.types_ref(), *ty)?
1004
                else {
1005
0
                    unreachable!()
1006
                };
1007
76
                let index = self.result.trampolines.push((
1008
76
                    *func,
1009
76
                    dfg::Trampoline::FutureDropReadable {
1010
76
                        instance: frame.instance,
1011
76
                        ty,
1012
76
                    },
1013
76
                ));
1014
76
                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1015
            }
1016
67
            FutureDropWritable { ty, func } => {
1017
67
                let InterfaceType::Future(ty) =
1018
67
                    types.defined_type(frame.translation.types_ref(), *ty)?
1019
                else {
1020
0
                    unreachable!()
1021
                };
1022
67
                let index = self.result.trampolines.push((
1023
67
                    *func,
1024
67
                    dfg::Trampoline::FutureDropWritable {
1025
67
                        instance: frame.instance,
1026
67
                        ty,
1027
67
                    },
1028
67
                ));
1029
67
                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1030
            }
1031
10
            ErrorContextNew { options } => {
1032
10
                let ty = types.error_context_table_type()?;
1033
10
                let func = options.core_type;
1034
10
                let options = self.adapter_options(frames, types, options);
1035
10
                let (frame, _) = frames.last_mut().unwrap();
1036
10
                let options = self.canonical_options(options);
1037
10
                let index = self.result.trampolines.push((
1038
10
                    func,
1039
10
                    dfg::Trampoline::ErrorContextNew {
1040
10
                        instance: frame.instance,
1041
10
                        ty,
1042
10
                        options,
1043
10
                    },
1044
10
                ));
1045
10
                frame.funcs.push((func, dfg::CoreDef::Trampoline(index)));
1046
            }
1047
10
            ErrorContextDebugMessage { options } => {
1048
10
                let ty = types.error_context_table_type()?;
1049
10
                let func = options.core_type;
1050
10
                let options = self.adapter_options(frames, types, options);
1051
10
                let (frame, _) = frames.last_mut().unwrap();
1052
10
                let options = self.canonical_options(options);
1053
10
                let index = self.result.trampolines.push((
1054
10
                    func,
1055
10
                    dfg::Trampoline::ErrorContextDebugMessage {
1056
10
                        instance: frame.instance,
1057
10
                        ty,
1058
10
                        options,
1059
10
                    },
1060
10
                ));
1061
10
                frame.funcs.push((func, dfg::CoreDef::Trampoline(index)));
1062
            }
1063
10
            ErrorContextDrop { func } => {
1064
10
                let ty = types.error_context_table_type()?;
1065
10
                let index = self.result.trampolines.push((
1066
10
                    *func,
1067
10
                    dfg::Trampoline::ErrorContextDrop {
1068
10
                        instance: frame.instance,
1069
10
                        ty,
1070
10
                    },
1071
10
                ));
1072
10
                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1073
            }
1074
2.13k
            ContextGet { func, i } => {
1075
2.13k
                let intrinsic = match i {
1076
2.12k
                    0 => UnsafeIntrinsic::ContextGetI32_0,
1077
16
                    1 => UnsafeIntrinsic::ContextGetI32_1,
1078
0
                    _ => unreachable!(),
1079
                };
1080
2.13k
                frame
1081
2.13k
                    .funcs
1082
2.13k
                    .push((*func, dfg::CoreDef::UnsafeIntrinsic(*func, intrinsic)));
1083
            }
1084
2.16k
            ContextSet { func, i } => {
1085
2.16k
                let intrinsic = match i {
1086
2.15k
                    0 => UnsafeIntrinsic::ContextSetI32_0,
1087
16
                    1 => UnsafeIntrinsic::ContextSetI32_1,
1088
0
                    _ => unreachable!(),
1089
                };
1090
2.16k
                frame
1091
2.16k
                    .funcs
1092
2.16k
                    .push((*func, dfg::CoreDef::UnsafeIntrinsic(*func, intrinsic)));
1093
            }
1094
107
            ThreadIndex { func } => {
1095
107
                let index = self.result.trampolines.push((
1096
107
                    *func,
1097
107
                    dfg::Trampoline::ThreadIndex {
1098
107
                        instance: frame.instance,
1099
107
                    },
1100
107
                ));
1101
107
                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1102
107
            }
1103
            ThreadNewIndirect {
1104
130
                func,
1105
130
                start_func_table_index,
1106
130
                start_func_ty,
1107
            } => {
1108
130
                let table_export = frame.tables[*start_func_table_index]
1109
130
                    .clone()
1110
130
                    .map_index(|i| match i {
1111
130
                        EntityIndex::Table(i) => i,
1112
0
                        _ => unreachable!(),
1113
130
                    });
1114
1115
130
                let table_id = self.result.tables.push(table_export);
1116
130
                let index = self.result.trampolines.push((
1117
130
                    *func,
1118
130
                    dfg::Trampoline::ThreadNewIndirect {
1119
130
                        instance: frame.instance,
1120
130
                        start_func_ty_idx: *start_func_ty,
1121
130
                        start_func_table_id: table_id,
1122
130
                    },
1123
130
                ));
1124
130
                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1125
            }
1126
137
            ThreadResumeLater { func } => {
1127
137
                let index = self.result.trampolines.push((
1128
137
                    *func,
1129
137
                    dfg::Trampoline::ThreadResumeLater {
1130
137
                        instance: frame.instance,
1131
137
                    },
1132
137
                ));
1133
137
                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1134
137
            }
1135
73
            ThreadSuspend { func } => {
1136
73
                let index = self.result.trampolines.push((
1137
73
                    *func,
1138
73
                    dfg::Trampoline::ThreadSuspend {
1139
73
                        instance: frame.instance,
1140
73
                    },
1141
73
                ));
1142
73
                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1143
73
            }
1144
152
            ThreadYield { func } => {
1145
152
                let index = self.result.trampolines.push((
1146
152
                    *func,
1147
152
                    dfg::Trampoline::ThreadYield {
1148
152
                        instance: frame.instance,
1149
152
                    },
1150
152
                ));
1151
152
                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1152
152
            }
1153
52
            ThreadSuspendThenResume { func } => {
1154
52
                let index = self.result.trampolines.push((
1155
52
                    *func,
1156
52
                    dfg::Trampoline::ThreadSuspendThenResume {
1157
52
                        instance: frame.instance,
1158
52
                    },
1159
52
                ));
1160
52
                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1161
52
            }
1162
66
            ThreadYieldThenResume { func } => {
1163
66
                let index = self.result.trampolines.push((
1164
66
                    *func,
1165
66
                    dfg::Trampoline::ThreadYieldThenResume {
1166
66
                        instance: frame.instance,
1167
66
                    },
1168
66
                ));
1169
66
                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1170
66
            }
1171
53
            ThreadSuspendThenPromote { func } => {
1172
53
                let index = self.result.trampolines.push((
1173
53
                    *func,
1174
53
                    dfg::Trampoline::ThreadSuspendThenPromote {
1175
53
                        instance: frame.instance,
1176
53
                    },
1177
53
                ));
1178
53
                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1179
53
            }
1180
105
            ThreadYieldThenPromote { func } => {
1181
105
                let index = self.result.trampolines.push((
1182
105
                    *func,
1183
105
                    dfg::Trampoline::ThreadYieldThenPromote {
1184
105
                        instance: frame.instance,
1185
105
                    },
1186
105
                ));
1187
105
                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1188
105
            }
1189
20.9k
            ModuleStatic(idx, ty) => {
1190
20.9k
                frame.modules.push(ModuleDef::Static(*idx, *ty));
1191
20.9k
            }
1192
1193
            // Instantiation of a module is one of the meatier initializers that
1194
            // we'll generate. The main magic here is that for a statically
1195
            // known module we can order the imports as a list to exactly what
1196
            // the static module needs to be instantiated. For imported modules,
1197
            // however, the runtime string resolution must happen at runtime so
1198
            // that is deferred here by organizing the arguments as a two-layer
1199
            // `IndexMap` of what we're providing.
1200
            //
1201
            // In both cases though a new `RuntimeInstanceIndex` is allocated
1202
            // and an initializer is recorded to indicate that it's being
1203
            // instantiated.
1204
21.7k
            ModuleInstantiate(module, args) => {
1205
21.7k
                let (instance_module, init) = match &frame.modules[*module] {
1206
21.7k
                    ModuleDef::Static(idx, _ty) => {
1207
21.7k
                        let mut defs = Vec::new();
1208
43.9k
                        for (module, name, _ty) in self.nested_modules[*idx].module.imports() {
1209
43.9k
                            let instance = args[module];
1210
43.9k
                            defs.push(
1211
43.9k
                                self.core_def_of_module_instance_export(frame, instance, name),
1212
43.9k
                            );
1213
43.9k
                        }
1214
21.7k
                        (
1215
21.7k
                            InstanceModule::Static(*idx),
1216
21.7k
                            dfg::Instance::Static(*idx, defs.into()),
1217
21.7k
                        )
1218
                    }
1219
33
                    ModuleDef::Import(path, ty) => {
1220
33
                        let mut defs = IndexMap::new();
1221
33
                        for ((module, name), _) in types[*ty].imports.iter() {
1222
21
                            let instance = args[module.as_str()];
1223
21
                            let def =
1224
21
                                self.core_def_of_module_instance_export(frame, instance, name);
1225
21
                            defs.entry(module.to_string())
1226
21
                                .or_insert(IndexMap::new())
1227
21
                                .insert(name.to_string(), def);
1228
21
                        }
1229
33
                        let index = self.runtime_import(path);
1230
33
                        (
1231
33
                            InstanceModule::Import(*ty),
1232
33
                            dfg::Instance::Import(index, defs),
1233
33
                        )
1234
                    }
1235
                };
1236
1237
21.7k
                let instance = self.result.instances.push(init);
1238
21.7k
                let instance2 = self.runtime_instances.push(instance_module);
1239
21.7k
                assert_eq!(instance, instance2);
1240
1241
21.7k
                self.result
1242
21.7k
                    .side_effects
1243
21.7k
                    .push(dfg::SideEffect::Instance(instance, frame.instance));
1244
1245
21.7k
                frame
1246
21.7k
                    .module_instances
1247
21.7k
                    .push(ModuleInstanceDef::Instantiated(instance, *module));
1248
            }
1249
1250
12.5k
            ModuleSynthetic(map) => {
1251
12.5k
                frame
1252
12.5k
                    .module_instances
1253
12.5k
                    .push(ModuleInstanceDef::Synthetic(map));
1254
12.5k
            }
1255
1256
            // This is one of the stages of the "magic" of implementing outer
1257
            // aliases to components and modules. For more information on this
1258
            // see the documentation on `LexicalScope`. This stage of the
1259
            // implementation of outer aliases is where the `ClosedOverVars` is
1260
            // transformed into a `ComponentClosure` state using the current
1261
            // `InlinerFrame`'s state. This will capture the "runtime" state of
1262
            // outer components and upvars and such naturally as part of the
1263
            // inlining process.
1264
9.95k
            ComponentStatic(index, vars) => {
1265
9.95k
                frame.components.push(ComponentDef {
1266
9.95k
                    index: *index,
1267
                    closure: ComponentClosure {
1268
9.95k
                        modules: vars
1269
9.95k
                            .modules
1270
9.95k
                            .iter()
1271
9.95k
                            .map(|(_, m)| frame.closed_over_module(m))
1272
9.95k
                            .collect(),
1273
9.95k
                        components: vars
1274
9.95k
                            .components
1275
9.95k
                            .iter()
1276
9.95k
                            .map(|(_, m)| frame.closed_over_component(m))
1277
9.95k
                            .collect(),
1278
                    },
1279
                });
1280
            }
1281
1282
            // Like module instantiation is this is a "meaty" part, and don't be
1283
            // fooled by the relative simplicity of this case. This is
1284
            // implemented primarily by the `Inliner` structure and the design
1285
            // of this entire module, so the "easy" step here is to simply
1286
            // create a new inliner frame and return it to get pushed onto the
1287
            // stack.
1288
15.5k
            ComponentInstantiate(component, args, ty) => {
1289
15.5k
                let component: &ComponentDef<'a> = &frame.components[*component];
1290
15.5k
                let index = RuntimeComponentInstanceIndex::from_u32(
1291
15.5k
                    self.result.num_runtime_component_instances,
1292
                );
1293
15.5k
                self.result.num_runtime_component_instances += 1;
1294
15.5k
                let frame = InlinerFrame::new(
1295
15.5k
                    index,
1296
15.5k
                    &self.nested_components[component.index],
1297
15.5k
                    component.closure.clone(),
1298
15.5k
                    args.iter()
1299
15.5k
                        .map(|(name, item)| Ok((*name, frame.item(*item, types)?)))
1300
15.5k
                        .collect::<Result<_>>()?,
1301
15.5k
                    Some(*ty),
1302
                );
1303
15.5k
                return Ok(Some(frame));
1304
            }
1305
1306
241
            ComponentSynthetic(map, ty) => {
1307
241
                let items = map
1308
241
                    .iter()
1309
242
                    .map(|(name, (index, data))| Ok((*name, (frame.item(*index, types)?, *data))))
1310
241
                    .collect::<Result<_>>()?;
1311
241
                let types_ref = frame.translation.types_ref();
1312
241
                let ty = types.convert_instance(types_ref, *ty)?;
1313
241
                frame
1314
241
                    .component_instances
1315
241
                    .push(ComponentInstanceDef::Items(items, ty));
1316
            }
1317
1318
            // Core wasm aliases, this and the cases below, are creating
1319
            // `CoreExport` items primarily to insert into the index space so we
1320
            // can create a unique identifier pointing to each core wasm export
1321
            // with the instance and relevant index/name as necessary.
1322
32.0k
            AliasExportFunc(instance, name) => {
1323
32.0k
                let (ty, def) = match &frame.module_instances[*instance] {
1324
32.0k
                    ModuleInstanceDef::Instantiated(instance, module) => {
1325
32.0k
                        let (ty, item) = match &frame.modules[*module] {
1326
32.0k
                            ModuleDef::Static(idx, _ty) => {
1327
32.0k
                                let name = self.nested_modules[*idx]
1328
32.0k
                                    .module
1329
32.0k
                                    .strings
1330
32.0k
                                    .get_atom(name)
1331
32.0k
                                    .unwrap();
1332
32.0k
                                let entity = self.nested_modules[*idx].module.exports[&name];
1333
32.0k
                                let ty = match entity {
1334
32.0k
                                    EntityIndex::Function(f) => {
1335
32.0k
                                        self.nested_modules[*idx].module.functions[f]
1336
32.0k
                                            .signature
1337
32.0k
                                            .unwrap_module_type_index()
1338
                                    }
1339
0
                                    _ => unreachable!(),
1340
                                };
1341
32.0k
                                (ty, ExportItem::Index(entity))
1342
                            }
1343
0
                            ModuleDef::Import(_path, module_ty) => {
1344
0
                                let module_ty = &types.component_types()[*module_ty];
1345
0
                                let entity_ty = &module_ty.exports[&**name];
1346
0
                                let ty = entity_ty.unwrap_func().unwrap_module_type_index();
1347
0
                                (ty, ExportItem::Name((*name).to_string()))
1348
                            }
1349
                        };
1350
32.0k
                        let def = dfg::CoreExport {
1351
32.0k
                            instance: *instance,
1352
32.0k
                            item,
1353
32.0k
                        }
1354
32.0k
                        .into();
1355
32.0k
                        (ty, def)
1356
                    }
1357
9
                    ModuleInstanceDef::Synthetic(instance) => match instance[*name] {
1358
9
                        EntityIndex::Function(i) => frame.funcs[i].clone(),
1359
0
                        _ => unreachable!(),
1360
                    },
1361
                };
1362
32.0k
                frame.funcs.push((ty, def));
1363
            }
1364
1365
287
            AliasExportTable(instance, name) => {
1366
287
                frame.tables.push(
1367
287
                    match self.core_def_of_module_instance_export(frame, *instance, *name) {
1368
287
                        dfg::CoreDef::Export(e) => e,
1369
0
                        _ => unreachable!(),
1370
                    },
1371
                );
1372
            }
1373
1374
158
            AliasExportGlobal(instance, name) => {
1375
158
                frame.globals.push(
1376
158
                    match self.core_def_of_module_instance_export(frame, *instance, *name) {
1377
158
                        dfg::CoreDef::Export(e) => e,
1378
0
                        _ => unreachable!(),
1379
                    },
1380
                );
1381
            }
1382
1383
10.4k
            AliasExportMemory(instance, name) => {
1384
10.4k
                frame.memories.push(
1385
10.4k
                    match self.core_def_of_module_instance_export(frame, *instance, *name) {
1386
10.4k
                        dfg::CoreDef::Export(e) => e,
1387
0
                        _ => unreachable!(),
1388
                    },
1389
                );
1390
            }
1391
1392
54
            AliasExportTag(instance, name) => {
1393
54
                frame.tags.push(
1394
54
                    match self.core_def_of_module_instance_export(frame, *instance, *name) {
1395
54
                        dfg::CoreDef::Export(e) => e,
1396
0
                        _ => unreachable!(),
1397
                    },
1398
                );
1399
            }
1400
1401
24.9k
            AliasComponentExport(instance, name) => {
1402
24.9k
                match &frame.component_instances[*instance] {
1403
                    ComponentInstanceDef::Intrinsics => {
1404
0
                        frame.push_item(ComponentItemDef::Func(ComponentFuncDef::UnsafeIntrinsic(
1405
0
                            UnsafeIntrinsic::from_str(name)?,
1406
                        )));
1407
                    }
1408
1409
                    // Aliasing an export from an imported instance means that
1410
                    // we're extending the `ImportPath` by one name, represented
1411
                    // with the clone + push here. Afterwards an appropriate
1412
                    // item is then pushed in the relevant index space.
1413
431
                    ComponentInstanceDef::Import(path, ty) => {
1414
431
                        let path = path.push(*name);
1415
431
                        let def =
1416
431
                            ComponentItemDef::from_import(path, types[*ty].exports[*name].ty)?;
1417
431
                        frame.push_item(def);
1418
                    }
1419
1420
                    // Given a component instance which was either created
1421
                    // through instantiation of a component or through a
1422
                    // synthetic renaming of items we just schlep around the
1423
                    // definitions of various items here.
1424
24.4k
                    ComponentInstanceDef::Items(map, _) => frame.push_item(map[*name].0.clone()),
1425
                }
1426
            }
1427
1428
            // For more information on these see `LexicalScope` but otherwise
1429
            // this is just taking a closed over variable and inserting the
1430
            // actual definition into the local index space since this
1431
            // represents an outer alias to a module/component
1432
246
            AliasModule(idx) => {
1433
246
                frame.modules.push(frame.closed_over_module(idx));
1434
246
            }
1435
109
            AliasComponent(idx) => {
1436
109
                frame.components.push(frame.closed_over_component(idx));
1437
109
            }
1438
1439
33.1k
            Export(item) => match item {
1440
30.8k
                ComponentItem::Func(i) => {
1441
30.8k
                    frame
1442
30.8k
                        .component_funcs
1443
30.8k
                        .push(frame.component_funcs[*i].clone());
1444
30.8k
                }
1445
357
                ComponentItem::Module(i) => {
1446
357
                    frame.modules.push(frame.modules[*i].clone());
1447
357
                }
1448
378
                ComponentItem::Component(i) => {
1449
378
                    frame.components.push(frame.components[*i].clone());
1450
378
                }
1451
263
                ComponentItem::ComponentInstance(i) => {
1452
263
                    frame
1453
263
                        .component_instances
1454
263
                        .push(frame.component_instances[*i].clone());
1455
263
                }
1456
1457
                // Type index spaces aren't maintained during this inlining pass
1458
                // so ignore this.
1459
1.23k
                ComponentItem::Type(_) => {}
1460
            },
1461
        }
1462
1463
244k
        Ok(None)
1464
260k
    }
1465
1466
    /// "Commits" a path of an import to an actual index which is something that
1467
    /// will be calculated at runtime.
1468
    ///
1469
    /// Note that the cost of calculating an item for a `RuntimeImportIndex` at
1470
    /// runtime is amortized with an `InstancePre` which represents "all the
1471
    /// runtime imports are lined up" and after that no more name resolution is
1472
    /// necessary.
1473
648
    fn runtime_import(&mut self, path: &ImportPath<'a>) -> RuntimeImportIndex {
1474
648
        *self
1475
648
            .import_path_interner
1476
648
            .entry(path.clone())
1477
648
            .or_insert_with(|| {
1478
632
                self.result.imports.push((
1479
632
                    path.index,
1480
632
                    path.path.iter().map(|s| s.to_string()).collect(),
1481
                ))
1482
632
            })
1483
648
    }
1484
1485
    /// Returns the `CoreDef`, the canonical definition for a core wasm item,
1486
    /// for the export `name` of `instance` within `frame`.
1487
54.9k
    fn core_def_of_module_instance_export(
1488
54.9k
        &self,
1489
54.9k
        frame: &InlinerFrame<'a>,
1490
54.9k
        instance: ModuleInstanceIndex,
1491
54.9k
        name: &'a str,
1492
54.9k
    ) -> dfg::CoreDef {
1493
54.9k
        match &frame.module_instances[instance] {
1494
            // Instantiations of a statically known module means that we can
1495
            // refer to the exported item by a precise index, skipping name
1496
            // lookups at runtime.
1497
            //
1498
            // Instantiations of an imported module, however, must do name
1499
            // lookups at runtime since we don't know the structure ahead of
1500
            // time here.
1501
13.0k
            ModuleInstanceDef::Instantiated(instance, module) => {
1502
13.0k
                let item = match frame.modules[*module] {
1503
13.0k
                    ModuleDef::Static(idx, _ty) => {
1504
13.0k
                        let name = self.nested_modules[idx]
1505
13.0k
                            .module
1506
13.0k
                            .strings
1507
13.0k
                            .get_atom(name)
1508
13.0k
                            .unwrap();
1509
13.0k
                        let entity = self.nested_modules[idx].module.exports[&name];
1510
13.0k
                        ExportItem::Index(entity)
1511
                    }
1512
29
                    ModuleDef::Import(..) => ExportItem::Name(name.to_string()),
1513
                };
1514
13.0k
                dfg::CoreExport {
1515
13.0k
                    instance: *instance,
1516
13.0k
                    item,
1517
13.0k
                }
1518
13.0k
                .into()
1519
            }
1520
1521
            // This is a synthetic instance so the canonical definition of the
1522
            // original item is returned.
1523
41.8k
            ModuleInstanceDef::Synthetic(instance) => match instance[name] {
1524
38.7k
                EntityIndex::Function(i) => frame.funcs[i].1.clone(),
1525
231
                EntityIndex::Table(i) => frame.tables[i].clone().into(),
1526
147
                EntityIndex::Global(i) => frame.globals[i].clone().into(),
1527
2.64k
                EntityIndex::Memory(i) => frame.memories[i].clone().into(),
1528
68
                EntityIndex::Tag(i) => frame.tags[i].clone().into(),
1529
            },
1530
        }
1531
54.9k
    }
1532
1533
7.83k
    fn memory(
1534
7.83k
        &mut self,
1535
7.83k
        frame: &InlinerFrame<'a>,
1536
7.83k
        types: &ComponentTypesBuilder,
1537
7.83k
        memory: MemoryIndex,
1538
7.83k
    ) -> (dfg::CoreExport<MemoryIndex>, Memory) {
1539
7.83k
        let memory = frame.memories[memory].clone().map_index(|i| match i {
1540
7.83k
            EntityIndex::Memory(i) => i,
1541
0
            _ => unreachable!(),
1542
7.83k
        });
1543
7.83k
        let ty = match &self.runtime_instances[memory.instance] {
1544
7.83k
            InstanceModule::Static(idx) => match &memory.item {
1545
7.83k
                ExportItem::Index(i) => self.nested_modules[*idx].module.memories[*i],
1546
0
                ExportItem::Name(_) => unreachable!(),
1547
            },
1548
0
            InstanceModule::Import(ty) => match &memory.item {
1549
0
                ExportItem::Name(name) => match types[*ty].exports[name] {
1550
0
                    EntityType::Memory(m) => m,
1551
0
                    _ => unreachable!(),
1552
                },
1553
0
                ExportItem::Index(_) => unreachable!(),
1554
            },
1555
        };
1556
7.83k
        (memory, ty)
1557
7.83k
    }
1558
1559
    /// Translates a `LocalCanonicalOptions` which indexes into the `frame`
1560
    /// specified into a runtime representation.
1561
45.4k
    fn adapter_options(
1562
45.4k
        &mut self,
1563
45.4k
        frames: &mut Vec<(InlinerFrame<'a>, ResourcesBuilder)>,
1564
45.4k
        types: &ComponentTypesBuilder,
1565
45.4k
        options: &LocalCanonicalOptions,
1566
45.4k
    ) -> AdapterOptions {
1567
45.4k
        let (frame, _) = frames.last_mut().unwrap();
1568
45.4k
        let data_model = match options.data_model {
1569
4
            LocalDataModel::Gc {} => DataModel::Gc {},
1570
45.4k
            LocalDataModel::LinearMemory { memory, realloc } => {
1571
45.4k
                let memory = memory.map(|i| self.memory(frame, types, i));
1572
45.4k
                let realloc = realloc.map(|i| frame.funcs[i].1.clone());
1573
45.4k
                DataModel::LinearMemory { memory, realloc }
1574
            }
1575
        };
1576
45.4k
        let callback = options.callback.map(|i| frame.funcs[i].1.clone());
1577
45.4k
        let post_return = options.post_return.map(|i| frame.funcs[i].1.clone());
1578
45.4k
        AdapterOptions {
1579
45.4k
            instance: frame.instance,
1580
45.4k
            string_encoding: options.string_encoding,
1581
45.4k
            callback,
1582
45.4k
            post_return,
1583
45.4k
            async_: options.async_,
1584
45.4k
            core_type: options.core_type,
1585
45.4k
            data_model,
1586
45.4k
        }
1587
45.4k
    }
1588
1589
    /// Translates an `AdapterOptions` into a `CanonicalOptions` where
1590
    /// memories/functions are inserted into the global initializer list for
1591
    /// use at runtime. This is only used for lowered host functions and lifted
1592
    /// functions exported to the host.
1593
19.3k
    fn canonical_options(&mut self, options: AdapterOptions) -> dfg::OptionsId {
1594
19.3k
        let data_model = match options.data_model {
1595
0
            DataModel::Gc {} => dfg::CanonicalOptionsDataModel::Gc {},
1596
19.3k
            DataModel::LinearMemory { memory, realloc } => {
1597
                dfg::CanonicalOptionsDataModel::LinearMemory {
1598
19.3k
                    memory: memory.map(|(export, _)| self.result.memories.push(export)),
1599
19.3k
                    realloc: realloc.map(|def| self.result.reallocs.push(def)),
1600
                }
1601
            }
1602
        };
1603
19.3k
        let callback = options.callback.map(|def| self.result.callbacks.push(def));
1604
19.3k
        let post_return = options
1605
19.3k
            .post_return
1606
19.3k
            .map(|def| self.result.post_returns.push(def));
1607
19.3k
        self.result.options.push(dfg::CanonicalOptions {
1608
19.3k
            instance: options.instance,
1609
19.3k
            string_encoding: options.string_encoding,
1610
19.3k
            callback,
1611
19.3k
            post_return,
1612
19.3k
            async_: options.async_,
1613
19.3k
            core_type: options.core_type,
1614
19.3k
            data_model,
1615
19.3k
        })
1616
19.3k
    }
1617
1618
11.0k
    fn record_export(
1619
11.0k
        &mut self,
1620
11.0k
        name: &str,
1621
11.0k
        def: ComponentItemDef<'a>,
1622
11.0k
        data: ComponentExternData,
1623
11.0k
        types: &'a ComponentTypesBuilder,
1624
11.0k
        map: &mut IndexMap<String, (dfg::Export, ComponentExternData)>,
1625
11.0k
    ) -> Result<()> {
1626
11.0k
        let export = match def {
1627
            // Exported modules are currently saved in a `PrimaryMap`, at
1628
            // runtime, so an index (`RuntimeModuleIndex`) is assigned here and
1629
            // then an initializer is recorded about where the module comes
1630
            // from.
1631
46
            ComponentItemDef::Module(module) => match module {
1632
45
                ModuleDef::Static(index, ty) => dfg::Export::ModuleStatic { ty, index },
1633
1
                ModuleDef::Import(path, ty) => dfg::Export::ModuleImport {
1634
1
                    ty,
1635
1
                    import: self.runtime_import(&path),
1636
1
                },
1637
            },
1638
1639
10.5k
            ComponentItemDef::Func(func) => match func {
1640
                // If this is a lifted function from something lowered in this
1641
                // component then the configured options are plumbed through
1642
                // here.
1643
10.5k
                ComponentFuncDef::Lifted { ty, func, options } => {
1644
10.5k
                    let options = self.canonical_options(options);
1645
10.5k
                    dfg::Export::LiftedFunction { ty, func, options }
1646
                }
1647
1648
                // Currently reexported functions from an import are not
1649
                // supported. Being able to actually call these functions is
1650
                // somewhat tricky and needs something like temporary scratch
1651
                // space that isn't implemented.
1652
                ComponentFuncDef::Import(_) => {
1653
4
                    bail!(
1654
                        "component export `{name}` is a reexport of an imported function which is not implemented"
1655
                    )
1656
                }
1657
1658
                ComponentFuncDef::UnsafeIntrinsic(_) => {
1659
0
                    bail!(
1660
                        "component export `{name}` is a reexport of an intrinsic function which is not supported"
1661
                    )
1662
                }
1663
            },
1664
1665
73
            ComponentItemDef::Instance(instance) => {
1666
73
                let mut exports = IndexMap::new();
1667
73
                match instance {
1668
                    ComponentInstanceDef::Intrinsics => {
1669
0
                        bail!(
1670
                            "component export `{name}` is a reexport of the intrinsics instance which is not supported"
1671
                        )
1672
                    }
1673
1674
                    // If this instance is one that was originally imported by
1675
                    // the component itself then the imports are translated here
1676
                    // by converting to a `ComponentItemDef` and then
1677
                    // recursively recording the export as a reexport.
1678
                    //
1679
                    // Note that for now this would only work with
1680
                    // module-exporting instances.
1681
9
                    ComponentInstanceDef::Import(path, ty) => {
1682
9
                        for (name, ty) in types[ty].exports.iter() {
1683
0
                            let path = path.push(name);
1684
0
                            let def = ComponentItemDef::from_import(path, ty.ty)?;
1685
0
                            self.record_export(name, def, ty.data.clone(), types, &mut exports)?;
1686
                        }
1687
9
                        dfg::Export::Instance { ty, exports }
1688
                    }
1689
1690
                    // An exported instance which is itself a bag of items is
1691
                    // translated recursively here to our `exports` map which is
1692
                    // the bag of items we're exporting.
1693
64
                    ComponentInstanceDef::Items(map, ty) => {
1694
64
                        for (name, (def, data)) in map {
1695
40
                            let data = ComponentExternData::new(data);
1696
40
                            self.record_export(name, def, data.clone(), types, &mut exports)?;
1697
                        }
1698
64
                        dfg::Export::Instance { ty, exports }
1699
                    }
1700
                }
1701
            }
1702
1703
            // FIXME(#4283) should make an official decision on whether this is
1704
            // the final treatment of this or not.
1705
            ComponentItemDef::Component(_) => {
1706
4
                bail!("exporting a component from the root component is not supported")
1707
            }
1708
1709
340
            ComponentItemDef::Type(def) => dfg::Export::Type(def),
1710
        };
1711
1712
11.0k
        map.insert(name.to_string(), (export, data));
1713
11.0k
        Ok(())
1714
11.0k
    }
1715
}
1716
1717
impl<'a> InlinerFrame<'a> {
1718
21.6k
    fn new(
1719
21.6k
        instance: RuntimeComponentInstanceIndex,
1720
21.6k
        translation: &'a Translation<'a>,
1721
21.6k
        closure: ComponentClosure<'a>,
1722
21.6k
        args: HashMap<&'a str, ComponentItemDef<'a>>,
1723
21.6k
        instance_ty: Option<ComponentInstanceTypeId>,
1724
21.6k
    ) -> Self {
1725
        // FIXME: should iterate over the initializers of `translation` and
1726
        // calculate the size of each index space to use `with_capacity` for
1727
        // all the maps below. Given that doing such would be wordy and compile
1728
        // time is otherwise not super crucial it's not done at this time.
1729
21.6k
        InlinerFrame {
1730
21.6k
            instance,
1731
21.6k
            translation,
1732
21.6k
            closure,
1733
21.6k
            args,
1734
21.6k
            instance_ty,
1735
21.6k
            initializers: translation.initializers.iter(),
1736
21.6k
1737
21.6k
            funcs: Default::default(),
1738
21.6k
            memories: Default::default(),
1739
21.6k
            tables: Default::default(),
1740
21.6k
            globals: Default::default(),
1741
21.6k
            tags: Default::default(),
1742
21.6k
1743
21.6k
            component_instances: Default::default(),
1744
21.6k
            component_funcs: Default::default(),
1745
21.6k
            module_instances: Default::default(),
1746
21.6k
            components: Default::default(),
1747
21.6k
            modules: Default::default(),
1748
21.6k
        }
1749
21.6k
    }
1750
1751
48.1k
    fn item(
1752
48.1k
        &self,
1753
48.1k
        index: ComponentItem,
1754
48.1k
        types: &mut ComponentTypesBuilder,
1755
48.1k
    ) -> Result<ComponentItemDef<'a>> {
1756
48.1k
        Ok(match index {
1757
42.5k
            ComponentItem::Func(i) => ComponentItemDef::Func(self.component_funcs[i].clone()),
1758
789
            ComponentItem::Component(i) => ComponentItemDef::Component(self.components[i].clone()),
1759
2.19k
            ComponentItem::ComponentInstance(i) => {
1760
2.19k
                ComponentItemDef::Instance(self.component_instances[i].clone())
1761
            }
1762
998
            ComponentItem::Module(i) => ComponentItemDef::Module(self.modules[i].clone()),
1763
1.66k
            ComponentItem::Type(t) => {
1764
1.66k
                let types_ref = self.translation.types_ref();
1765
1.66k
                ComponentItemDef::Type(types.convert_type(types_ref, t)?)
1766
            }
1767
        })
1768
48.1k
    }
1769
1770
    /// Pushes the component `item` definition provided into the appropriate
1771
    /// index space within this component.
1772
56.0k
    fn push_item(&mut self, item: ComponentItemDef<'a>) {
1773
56.0k
        match item {
1774
34.5k
            ComponentItemDef::Func(i) => {
1775
34.5k
                self.component_funcs.push(i);
1776
34.5k
            }
1777
997
            ComponentItemDef::Module(i) => {
1778
997
                self.modules.push(i);
1779
997
            }
1780
773
            ComponentItemDef::Component(i) => {
1781
773
                self.components.push(i);
1782
773
            }
1783
18.1k
            ComponentItemDef::Instance(i) => {
1784
18.1k
                self.component_instances.push(i);
1785
18.1k
            }
1786
1787
            // In short, type definitions aren't tracked here.
1788
            //
1789
            // The longer form explanation for this is that structural types
1790
            // like lists and records don't need to be tracked at all and the
1791
            // only significant type which needs tracking is resource types
1792
            // themselves. Resource types, however, are tracked within the
1793
            // `ResourcesBuilder` state rather than an `InlinerFrame` so they're
1794
            // ignored here as well. The general reason for that is that type
1795
            // information is everywhere and this `InlinerFrame` is not
1796
            // everywhere so it seemed like it would make sense to split the
1797
            // two.
1798
            //
1799
            // Note though that this case is actually frequently hit, so it
1800
            // can't be `unreachable!()`. Instead callers are responsible for
1801
            // handling this appropriately with respect to resources.
1802
1.55k
            ComponentItemDef::Type(_ty) => {}
1803
        }
1804
56.0k
    }
1805
1806
552
    fn closed_over_module(&self, index: &ClosedOverModule) -> ModuleDef<'a> {
1807
552
        match *index {
1808
214
            ClosedOverModule::Local(i) => self.modules[i].clone(),
1809
338
            ClosedOverModule::Upvar(i) => self.closure.modules[i].clone(),
1810
        }
1811
552
    }
1812
1813
160
    fn closed_over_component(&self, index: &ClosedOverComponent) -> ComponentDef<'a> {
1814
160
        match *index {
1815
64
            ClosedOverComponent::Local(i) => self.components[i].clone(),
1816
96
            ClosedOverComponent::Upvar(i) => self.closure.components[i].clone(),
1817
        }
1818
160
    }
1819
1820
    /// Completes the instantiation of a subcomponent and records type
1821
    /// information for the instance that was produced.
1822
    ///
1823
    /// This method is invoked when an `InlinerFrame` finishes for a
1824
    /// subcomponent. The `def` provided represents the instance that was
1825
    /// produced from instantiation, and `ty` is the wasmparser-defined type of
1826
    /// the instance produced.
1827
    ///
1828
    /// The purpose of this method is to record type information about resources
1829
    /// in the instance produced. In the component model all instantiations of a
1830
    /// component produce fresh new types for all resources which are unequal to
1831
    /// all prior resources. This means that if wasmparser's `ty` type
1832
    /// information references a unique resource within `def` that has never
1833
    /// been registered before then that means it's a defined resource within
1834
    /// the component that was just instantiated (as opposed to an imported
1835
    /// resource which was reexported).
1836
    ///
1837
    /// Further type translation after this instantiation can refer to these
1838
    /// resource types and a mapping from those types to the wasmtime-internal
1839
    /// types is required, so this method builds up those mappings.
1840
    ///
1841
    /// Essentially what happens here is that the `ty` type is registered and
1842
    /// any new unique resources are registered so new tables can be introduced
1843
    /// along with origin information about the actual underlying resource type
1844
    /// and which component instantiated it.
1845
15.5k
    fn finish_instantiate(
1846
15.5k
        &mut self,
1847
15.5k
        exports: IndexMap<&'a str, (ComponentItemDef<'a>, wasmparser::ComponentExternName<'a>)>,
1848
15.5k
        ty: ComponentInstanceTypeId,
1849
15.5k
        types: &mut ComponentTypesBuilder,
1850
15.5k
    ) -> Result<()> {
1851
15.5k
        let types_ref = self.translation.types_ref();
1852
        {
1853
15.5k
            let (resources, types) = types.resources_mut_and_types();
1854
15.5k
            let mut path = Vec::new();
1855
15.5k
            resources.register_component_entity_type(
1856
15.5k
                &types_ref,
1857
15.5k
                ComponentEntityType::Instance(ty),
1858
15.5k
                &mut path,
1859
669
                &mut |path| match path {
1860
669
                    [] => unreachable!(),
1861
669
                    [name, rest @ ..] => exports[name].0.lookup_resource(rest, types),
1862
669
                },
1863
            );
1864
        }
1865
15.5k
        let ty = types.convert_instance(types_ref, ty)?;
1866
15.5k
        let def = ComponentInstanceDef::Items(exports, ty);
1867
15.5k
        let arg = ComponentItemDef::Instance(def);
1868
15.5k
        self.push_item(arg);
1869
15.5k
        Ok(())
1870
15.5k
    }
1871
}
1872
1873
impl<'a> ImportPath<'a> {
1874
801
    fn root(index: ImportIndex) -> ImportPath<'a> {
1875
801
        ImportPath {
1876
801
            index,
1877
801
            path: Vec::new(),
1878
801
        }
1879
801
    }
1880
1881
440
    fn push(&self, s: impl Into<Cow<'a, str>>) -> ImportPath<'a> {
1882
440
        let mut new = self.clone();
1883
440
        new.path.push(s.into());
1884
440
        new
1885
440
    }
Unexecuted instantiation: <wasmtime_environ::component::translate::inline::ImportPath>::push::<&alloc::string::String>
<wasmtime_environ::component::translate::inline::ImportPath>::push::<&str>
Line
Count
Source
1881
440
    fn push(&self, s: impl Into<Cow<'a, str>>) -> ImportPath<'a> {
1882
440
        let mut new = self.clone();
1883
440
        new.path.push(s.into());
1884
440
        new
1885
440
    }
1886
}
1887
1888
impl<'a> ComponentItemDef<'a> {
1889
1.24k
    fn from_import(path: ImportPath<'a>, ty: TypeDef) -> Result<ComponentItemDef<'a>> {
1890
1.24k
        let item = match ty {
1891
57
            TypeDef::Module(ty) => ComponentItemDef::Module(ModuleDef::Import(path, ty)),
1892
471
            TypeDef::ComponentInstance(ty) => {
1893
471
                ComponentItemDef::Instance(ComponentInstanceDef::Import(path, ty))
1894
            }
1895
386
            TypeDef::ComponentFunc(_ty) => ComponentItemDef::Func(ComponentFuncDef::Import(path)),
1896
            // FIXME(#4283) should commit one way or another to how this
1897
            // should be treated.
1898
6
            TypeDef::Component(_ty) => bail!("root-level component imports are not supported"),
1899
321
            TypeDef::Interface(_) | TypeDef::Resource(_) => ComponentItemDef::Type(ty),
1900
0
            TypeDef::CoreFunc(_) => unreachable!(),
1901
        };
1902
1.23k
        Ok(item)
1903
1.24k
    }
1904
1905
    /// Walks the `path` within `self` to find a resource at that path.
1906
    ///
1907
    /// This method is used when resources are found within wasmparser's type
1908
    /// information and they need to be correlated with actual concrete
1909
    /// definitions from this inlining pass. The `path` here is a list of
1910
    /// instance export names (or empty) to walk to reach down into the final
1911
    /// definition which should refer to a resource itself.
1912
1.61k
    fn lookup_resource(&self, path: &[&str], types: &ComponentTypes) -> ResourceIndex {
1913
1.61k
        let mut cur = self.clone();
1914
1915
        // Each element of `path` represents unwrapping a layer of an instance
1916
        // type, so handle those here by updating `cur` iteratively.
1917
1.61k
        for element in path.iter().copied() {
1918
670
            let instance = match cur {
1919
670
                ComponentItemDef::Instance(def) => def,
1920
0
                _ => unreachable!(),
1921
            };
1922
670
            cur = match instance {
1923
                // If this instance is a "bag of things" then this is as easy as
1924
                // looking up the name in the bag of names.
1925
661
                ComponentInstanceDef::Items(names, _) => names[element].0.clone(),
1926
1927
                // If, however, this instance is an imported instance then this
1928
                // is a further projection within the import with one more path
1929
                // element. The `types` type information is used to lookup the
1930
                // type of `element` within the instance type, and that's used
1931
                // in conjunction with a one-longer `path` to produce a new item
1932
                // definition.
1933
9
                ComponentInstanceDef::Import(path, ty) => {
1934
9
                    ComponentItemDef::from_import(path.push(element), types[ty].exports[element].ty)
1935
9
                        .unwrap()
1936
                }
1937
                ComponentInstanceDef::Intrinsics => {
1938
0
                    unreachable!("intrinsics do not define resources")
1939
                }
1940
            };
1941
        }
1942
1943
        // Once `path` has been iterated over it must be the case that the final
1944
        // item is a resource type, in which case a lookup can be performed.
1945
1.61k
        match cur {
1946
1.61k
            ComponentItemDef::Type(TypeDef::Resource(idx)) => types[idx].unwrap_concrete_ty(),
1947
0
            _ => unreachable!(),
1948
        }
1949
1.61k
    }
1950
}
1951
1952
#[derive(Clone, Copy)]
1953
enum InstanceModule {
1954
    Static(StaticModuleIndex),
1955
    Import(TypeModuleIndex),
1956
}
1957
1958
impl ComponentExternData {
1959
11.8k
    fn new(data: wasmparser::ComponentExternName<'_>) -> Self {
1960
        ComponentExternData {
1961
11.8k
            implements: data.implements.map(|s| s.to_string()),
1962
11.8k
            external_id: data.external_id.map(|s| s.to_string()),
1963
        }
1964
11.8k
    }
1965
}