Skip to content

Commit e37b3b0

Browse files
sunfishcodeCryZe
authored andcommitted
* Compute instance exports on demand. Instead having instances eagerly compute a Vec of Externs, and bumping the refcount for each Extern, compute Externs on demand. This also enables `Instance::get_export` to avoid doing a linear search. This also means that the closure returned by `get0` and friends now holds an `InstanceHandle` to dynamically hold the instance live rather than being scoped to a lifetime. * Compute module imports and exports on demand too. And compute Extern::ty on demand too. * Add a utility function for computing an ExternType. * Add a utility function for looking up a function's signature. * Add a utility function for computing the ValType of a Global. * Rename wasmtime_environ::Export to EntityIndex. This helps differentiate it from other Export types in the tree, and describes what it is. * Fix a typo in a comment. * Simplify module imports and exports. * Make `Instance::exports` return the export names. This significantly simplifies the public API, as it's relatively common to need the names, and this avoids the need to do a zip with `Module::exports`. This also changes `ImportType` and `ExportType` to have public members instead of private members and accessors, as I find that simplifies the usage particularly in cases where there are temporary instances. * Remove `Instance::module`. This doesn't quite remove `Instance`'s `module` member, it gets a step closer. * Use a InstanceHandle utility function. * Don't consume self in the `Func::get*` methods. Instead, just create a closure containing the instance handle and the export for them to call. * Use `ExactSizeIterator` to avoid needing separate `num_*` methods. * Rename `Extern::func()` etc. to `into_func()` etc. * Revise examples to avoid using `nth`. * Add convenience methods to instance for getting specific extern types. * Use the convenience functions in more tests and examples. * Avoid cloning strings for `ImportType` and `ExportType`. * Remove more obviated clone() calls. * Simplify `Func`'s closure state. * Make wasmtime::Export's fields private. This makes them more consistent with ExportType. * Fix compilation error. * Make a lifetime parameter explicit, and use better lifetime names. Instead of 'me, use 'instance and 'module to make it clear what the lifetime is. * More lifetime cleanups.
1 parent 63c97e3 commit e37b3b0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+787
-874
lines changed

cranelift/wasm/src/translation_utils.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ pub struct ElemIndex(u32);
6868
entity_impl!(ElemIndex);
6969

7070
/// WebAssembly global.
71-
#[derive(Debug, Clone, Copy, Hash)]
71+
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
7272
pub struct Global {
7373
/// The type of the value stored in the global.
7474
pub ty: ir::Type,
@@ -79,7 +79,7 @@ pub struct Global {
7979
}
8080

8181
/// Globals are initialized via the `const` operators or by referring to another import.
82-
#[derive(Debug, Clone, Copy, Hash)]
82+
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
8383
pub enum GlobalInit {
8484
/// An `i32.const`.
8585
I32Const(i32),
@@ -102,7 +102,7 @@ pub enum GlobalInit {
102102
}
103103

104104
/// WebAssembly table.
105-
#[derive(Debug, Clone, Copy, Hash)]
105+
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
106106
pub struct Table {
107107
/// The type of data stored in elements of the table.
108108
pub ty: TableElementType,
@@ -113,7 +113,7 @@ pub struct Table {
113113
}
114114

115115
/// WebAssembly table element. Can be a function or a scalar type.
116-
#[derive(Debug, Clone, Copy, Hash)]
116+
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
117117
pub enum TableElementType {
118118
/// A scalar type.
119119
Val(ir::Type),
@@ -122,7 +122,7 @@ pub enum TableElementType {
122122
}
123123

124124
/// WebAssembly linear memory.
125-
#[derive(Debug, Clone, Copy, Hash)]
125+
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
126126
pub struct Memory {
127127
/// The minimum number of pages in the memory.
128128
pub minimum: u32,

crates/api/src/externals.rs

Lines changed: 106 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ impl Extern {
3434
/// Returns the underlying `Func`, if this external is a function.
3535
///
3636
/// Returns `None` if this is not a function.
37-
pub fn func(&self) -> Option<&Func> {
37+
pub fn into_func(self) -> Option<Func> {
3838
match self {
3939
Extern::Func(func) => Some(func),
4040
_ => None,
@@ -44,7 +44,7 @@ impl Extern {
4444
/// Returns the underlying `Global`, if this external is a global.
4545
///
4646
/// Returns `None` if this is not a global.
47-
pub fn global(&self) -> Option<&Global> {
47+
pub fn into_global(self) -> Option<Global> {
4848
match self {
4949
Extern::Global(global) => Some(global),
5050
_ => None,
@@ -54,7 +54,7 @@ impl Extern {
5454
/// Returns the underlying `Table`, if this external is a table.
5555
///
5656
/// Returns `None` if this is not a table.
57-
pub fn table(&self) -> Option<&Table> {
57+
pub fn into_table(self) -> Option<Table> {
5858
match self {
5959
Extern::Table(table) => Some(table),
6060
_ => None,
@@ -64,7 +64,7 @@ impl Extern {
6464
/// Returns the underlying `Memory`, if this external is a memory.
6565
///
6666
/// Returns `None` if this is not a memory.
67-
pub fn memory(&self) -> Option<&Memory> {
67+
pub fn into_memory(self) -> Option<Memory> {
6868
match self {
6969
Extern::Memory(memory) => Some(memory),
7070
_ => None,
@@ -74,10 +74,10 @@ impl Extern {
7474
/// Returns the type associated with this `Extern`.
7575
pub fn ty(&self) -> ExternType {
7676
match self {
77-
Extern::Func(ft) => ExternType::Func(ft.ty().clone()),
78-
Extern::Memory(ft) => ExternType::Memory(ft.ty().clone()),
79-
Extern::Table(tt) => ExternType::Table(tt.ty().clone()),
80-
Extern::Global(gt) => ExternType::Global(gt.ty().clone()),
77+
Extern::Func(ft) => ExternType::Func(ft.ty()),
78+
Extern::Memory(ft) => ExternType::Memory(ft.ty()),
79+
Extern::Table(tt) => ExternType::Table(tt.ty()),
80+
Extern::Global(gt) => ExternType::Global(gt.ty()),
8181
}
8282
}
8383

@@ -91,11 +91,11 @@ impl Extern {
9191
}
9292

9393
pub(crate) fn from_wasmtime_export(
94+
wasmtime_export: wasmtime_runtime::Export,
9495
store: &Store,
9596
instance_handle: InstanceHandle,
96-
export: wasmtime_runtime::Export,
9797
) -> Extern {
98-
match export {
98+
match wasmtime_export {
9999
wasmtime_runtime::Export::Function(f) => {
100100
Extern::Func(Func::from_wasmtime_function(f, store, instance_handle))
101101
}
@@ -164,7 +164,6 @@ impl From<Table> for Extern {
164164
#[derive(Clone)]
165165
pub struct Global {
166166
store: Store,
167-
ty: GlobalType,
168167
wasmtime_export: wasmtime_runtime::ExportGlobal,
169168
wasmtime_handle: InstanceHandle,
170169
}
@@ -191,27 +190,44 @@ impl Global {
191190
let (wasmtime_handle, wasmtime_export) = generate_global_export(store, &ty, val)?;
192191
Ok(Global {
193192
store: store.clone(),
194-
ty,
195193
wasmtime_export,
196194
wasmtime_handle,
197195
})
198196
}
199197

200198
/// Returns the underlying type of this `global`.
201-
pub fn ty(&self) -> &GlobalType {
202-
&self.ty
199+
pub fn ty(&self) -> GlobalType {
200+
// The original export is coming from wasmtime_runtime itself we should
201+
// support all the types coming out of it, so assert such here.
202+
GlobalType::from_wasmtime_global(&self.wasmtime_export.global)
203+
.expect("core wasm global type should be supported")
204+
}
205+
206+
/// Returns the value type of this `global`.
207+
pub fn val_type(&self) -> ValType {
208+
ValType::from_wasmtime_type(self.wasmtime_export.global.ty)
209+
.expect("core wasm type should be supported")
210+
}
211+
212+
/// Returns the underlying mutability of this `global`.
213+
pub fn mutability(&self) -> Mutability {
214+
if self.wasmtime_export.global.mutability {
215+
Mutability::Var
216+
} else {
217+
Mutability::Const
218+
}
203219
}
204220

205221
/// Returns the current [`Val`] of this global.
206222
pub fn get(&self) -> Val {
207223
unsafe {
208224
let definition = &mut *self.wasmtime_export.definition;
209-
match self.ty().content() {
225+
match self.val_type() {
210226
ValType::I32 => Val::from(*definition.as_i32()),
211227
ValType::I64 => Val::from(*definition.as_i64()),
212228
ValType::F32 => Val::F32(*definition.as_u32()),
213229
ValType::F64 => Val::F64(*definition.as_u64()),
214-
_ => unimplemented!("Global::get for {:?}", self.ty().content()),
230+
ty => unimplemented!("Global::get for {:?}", ty),
215231
}
216232
}
217233
}
@@ -223,15 +239,12 @@ impl Global {
223239
/// Returns an error if this global has a different type than `Val`, or if
224240
/// it's not a mutable global.
225241
pub fn set(&self, val: Val) -> Result<()> {
226-
if self.ty().mutability() != Mutability::Var {
242+
if self.mutability() != Mutability::Var {
227243
bail!("immutable global cannot be set");
228244
}
229-
if val.ty() != *self.ty().content() {
230-
bail!(
231-
"global of type {:?} cannot be set to {:?}",
232-
self.ty().content(),
233-
val.ty()
234-
);
245+
let ty = self.val_type();
246+
if val.ty() != ty {
247+
bail!("global of type {:?} cannot be set to {:?}", ty, val.ty());
235248
}
236249
if !val.comes_from_same_store(&self.store) {
237250
bail!("cross-`Store` values are not supported");
@@ -254,13 +267,8 @@ impl Global {
254267
store: &Store,
255268
wasmtime_handle: InstanceHandle,
256269
) -> Global {
257-
// The original export is coming from wasmtime_runtime itself we should
258-
// support all the types coming out of it, so assert such here.
259-
let ty = GlobalType::from_wasmtime_global(&wasmtime_export.global)
260-
.expect("core wasm global type should be supported");
261270
Global {
262271
store: store.clone(),
263-
ty: ty,
264272
wasmtime_export,
265273
wasmtime_handle,
266274
}
@@ -285,7 +293,6 @@ impl Global {
285293
#[derive(Clone)]
286294
pub struct Table {
287295
store: Store,
288-
ty: TableType,
289296
wasmtime_handle: InstanceHandle,
290297
wasmtime_export: wasmtime_runtime::ExportTable,
291298
}
@@ -326,16 +333,15 @@ impl Table {
326333

327334
Ok(Table {
328335
store: store.clone(),
329-
ty,
330336
wasmtime_handle,
331337
wasmtime_export,
332338
})
333339
}
334340

335341
/// Returns the underlying type of this table, including its element type as
336342
/// well as the maximum/minimum lower bounds.
337-
pub fn ty(&self) -> &TableType {
338-
&self.ty
343+
pub fn ty(&self) -> TableType {
344+
TableType::from_wasmtime_table(&self.wasmtime_export.table.table)
339345
}
340346

341347
fn wasmtime_table_index(&self) -> wasm::DefinedTableIndex {
@@ -368,7 +374,7 @@ impl Table {
368374

369375
/// Returns the current size of this table.
370376
pub fn size(&self) -> u32 {
371-
unsafe { (&*self.wasmtime_export.definition).current_elements }
377+
unsafe { (*self.wasmtime_export.definition).current_elements }
372378
}
373379

374380
/// Grows the size of this table by `delta` more elements, initialization
@@ -438,10 +444,8 @@ impl Table {
438444
store: &Store,
439445
wasmtime_handle: wasmtime_runtime::InstanceHandle,
440446
) -> Table {
441-
let ty = TableType::from_wasmtime_table(&wasmtime_export.table.table);
442447
Table {
443448
store: store.clone(),
444-
ty,
445449
wasmtime_handle,
446450
wasmtime_export,
447451
}
@@ -657,7 +661,6 @@ impl Table {
657661
#[derive(Clone)]
658662
pub struct Memory {
659663
store: Store,
660-
ty: MemoryType,
661664
wasmtime_handle: InstanceHandle,
662665
wasmtime_export: wasmtime_runtime::ExportMemory,
663666
}
@@ -690,7 +693,6 @@ impl Memory {
690693
generate_memory_export(store, &ty).expect("generated memory");
691694
Memory {
692695
store: store.clone(),
693-
ty,
694696
wasmtime_handle,
695697
wasmtime_export,
696698
}
@@ -706,14 +708,14 @@ impl Memory {
706708
/// let store = Store::default();
707709
/// let module = Module::new(&store, "(module (memory (export \"mem\") 1))")?;
708710
/// let instance = Instance::new(&module, &[])?;
709-
/// let memory = instance.get_export("mem").unwrap().memory().unwrap();
711+
/// let memory = instance.get_memory("mem").unwrap();
710712
/// let ty = memory.ty();
711713
/// assert_eq!(ty.limits().min(), 1);
712714
/// # Ok(())
713715
/// # }
714716
/// ```
715-
pub fn ty(&self) -> &MemoryType {
716-
&self.ty
717+
pub fn ty(&self) -> MemoryType {
718+
MemoryType::from_wasmtime_memory(&self.wasmtime_export.memory.memory)
717719
}
718720

719721
/// Returns this memory as a slice view that can be read natively in Rust.
@@ -818,7 +820,7 @@ impl Memory {
818820
/// let store = Store::default();
819821
/// let module = Module::new(&store, "(module (memory (export \"mem\") 1 2))")?;
820822
/// let instance = Instance::new(&module, &[])?;
821-
/// let memory = instance.get_export("mem").unwrap().memory().unwrap();
823+
/// let memory = instance.get_memory("mem").unwrap();
822824
///
823825
/// assert_eq!(memory.size(), 1);
824826
/// assert_eq!(memory.grow(1)?, 1);
@@ -844,10 +846,8 @@ impl Memory {
844846
store: &Store,
845847
wasmtime_handle: wasmtime_runtime::InstanceHandle,
846848
) -> Memory {
847-
let ty = MemoryType::from_wasmtime_memory(&wasmtime_export.memory.memory);
848849
Memory {
849850
store: store.clone(),
850-
ty: ty,
851851
wasmtime_handle,
852852
wasmtime_export,
853853
}
@@ -896,3 +896,66 @@ pub unsafe trait MemoryCreator: Send + Sync {
896896
/// Create new LinearMemory
897897
fn new_memory(&self, ty: MemoryType) -> Result<Box<dyn LinearMemory>, String>;
898898
}
899+
900+
// Exports
901+
902+
/// An exported WebAssembly value.
903+
///
904+
/// This type is primarily accessed from the
905+
/// [`Instance::exports`](crate::Instance::exports) accessor and describes what
906+
/// names and items are exported from a wasm instance.
907+
#[derive(Clone)]
908+
pub struct Export<'instance> {
909+
/// The name of the export.
910+
name: &'instance str,
911+
912+
/// The definition of the export.
913+
definition: Extern,
914+
}
915+
916+
impl<'instance> Export<'instance> {
917+
/// Creates a new export which is exported with the given `name` and has the
918+
/// given `definition`.
919+
pub(crate) fn new(name: &'instance str, definition: Extern) -> Export<'instance> {
920+
Export { name, definition }
921+
}
922+
923+
/// Returns the name by which this export is known.
924+
pub fn name(&self) -> &'instance str {
925+
self.name
926+
}
927+
928+
/// Return the `ExternType` of this export.
929+
pub fn ty(&self) -> ExternType {
930+
self.definition.ty()
931+
}
932+
933+
/// Consume this `Export` and return the contained `Extern`.
934+
pub fn into_extern(self) -> Extern {
935+
self.definition
936+
}
937+
938+
/// Consume this `Export` and return the contained `Func`, if it's a function,
939+
/// or `None` otherwise.
940+
pub fn into_func(self) -> Option<Func> {
941+
self.definition.into_func()
942+
}
943+
944+
/// Consume this `Export` and return the contained `Table`, if it's a table,
945+
/// or `None` otherwise.
946+
pub fn into_table(self) -> Option<Table> {
947+
self.definition.into_table()
948+
}
949+
950+
/// Consume this `Export` and return the contained `Memory`, if it's a memory,
951+
/// or `None` otherwise.
952+
pub fn into_memory(self) -> Option<Memory> {
953+
self.definition.into_memory()
954+
}
955+
956+
/// Consume this `Export` and return the contained `Global`, if it's a global,
957+
/// or `None` otherwise.
958+
pub fn into_global(self) -> Option<Global> {
959+
self.definition.into_global()
960+
}
961+
}

0 commit comments

Comments
 (0)