Skip to content

Commit 8d5365f

Browse files
committed
Make resources substitution table optional in type-checking
There's already a few locations that test for a fallible lookup in this table and those are effectively better handled with a first-class `Option` type of whether the table is present at all. This additionally removes the need to allocate in this method along with the need for bytecodealliance#13090.
1 parent 1cc2930 commit 8d5365f

File tree

5 files changed

+34
-25
lines changed

5 files changed

+34
-25
lines changed

crates/wasmtime/src/runtime/component/component.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -388,10 +388,9 @@ impl Component {
388388
}
389389

390390
fn with_uninstantiated_instance_type<R>(&self, f: impl FnOnce(&InstanceType<'_>) -> R) -> R {
391-
let resources = Arc::new(TryPrimaryMap::new());
392391
f(&InstanceType {
393392
types: self.types(),
394-
resources: &resources,
393+
resources: None,
395394
})
396395
}
397396

crates/wasmtime/src/runtime/component/instance.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1149,7 +1149,7 @@ impl<T: 'static> InstancePre<T> {
11491149
pub fn instance_type(&self) -> InstanceType<'_> {
11501150
InstanceType {
11511151
types: &self.component.types(),
1152-
resources: &self.resource_types,
1152+
resources: Some(&self.resource_types),
11531153
}
11541154
}
11551155

crates/wasmtime/src/runtime/component/linker.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ impl<T: 'static> Linker<T> {
192192
component.ty(),
193193
&InstanceType {
194194
types: cx.types,
195-
resources: &cx.imported_resources,
195+
resources: Some(&cx.imported_resources),
196196
},
197197
))
198198
}

crates/wasmtime/src/runtime/component/matching.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,13 @@ pub struct TypeChecker<'a> {
2626
#[doc(hidden)]
2727
pub struct InstanceType<'a> {
2828
pub types: &'a Arc<ComponentTypes>,
29-
pub resources: &'a Arc<TryPrimaryMap<ResourceIndex, ResourceType>>,
29+
/// Resource type substitutions for resources within `ComponentTypes`, if
30+
/// any.
31+
///
32+
/// If this isn't present then resource types are considered "abstract" and
33+
/// un-intantiated. This doesn't refer to a concrete instantiated component,
34+
/// but rather an abstract component type.
35+
pub resources: Option<&'a Arc<TryPrimaryMap<ResourceIndex, ResourceType>>>,
3036
}
3137

3238
impl TypeChecker<'_> {
@@ -170,7 +176,7 @@ impl TypeChecker<'_> {
170176
fn func(&self, expected: TypeFuncIndex, actual: &HostFunc) -> Result<()> {
171177
let instance_type = InstanceType {
172178
types: self.types,
173-
resources: &self.imported_resources,
179+
resources: Some(&self.imported_resources),
174180
};
175181
actual.typecheck(expected, &instance_type)
176182
}
@@ -191,16 +197,15 @@ impl<'a> InstanceType<'a> {
191197
pub fn new(instance: &'a ComponentInstance) -> InstanceType<'a> {
192198
InstanceType {
193199
types: instance.component().types(),
194-
resources: instance.resource_types(),
200+
resources: Some(instance.resource_types()),
195201
}
196202
}
197203

198204
pub fn resource_type(&self, index: TypeResourceTableIndex) -> ResourceType {
199205
match self.types[index] {
200206
TypeResourceTable::Concrete { ty, .. } => self
201207
.resources
202-
.get(ty)
203-
.copied()
208+
.map(|t| t[ty])
204209
.unwrap_or_else(|| ResourceType::uninstantiated(&self.types, ty)),
205210
TypeResourceTable::Abstract(ty) => ResourceType::abstract_(&self.types, ty),
206211
}

crates/wasmtime/src/runtime/component/types.rs

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -35,27 +35,28 @@ pub use crate::component::resources::ResourceType;
3535
/// component with different resources produces different instance types but
3636
/// the same underlying component type, so this field serves the purpose to
3737
/// distinguish instance types from one another. This is runtime state created
38-
/// during instantiation and threaded through here.
38+
/// during instantiation and threaded through here. Note that if this field
39+
/// is `None` then this represents an abstract uninstantiated component type.
3940
#[derive(Clone)]
4041
struct Handle<T> {
4142
index: T,
4243
types: Arc<ComponentTypes>,
43-
resources: Arc<TryPrimaryMap<ResourceIndex, ResourceType>>,
44+
resources: Option<Arc<TryPrimaryMap<ResourceIndex, ResourceType>>>,
4445
}
4546

4647
impl<T> Handle<T> {
4748
fn new(index: T, ty: &InstanceType<'_>) -> Handle<T> {
4849
Handle {
4950
index,
5051
types: ty.types.clone(),
51-
resources: ty.resources.clone(),
52+
resources: ty.resources.cloned(),
5253
}
5354
}
5455

5556
fn instance(&self) -> InstanceType<'_> {
5657
InstanceType {
5758
types: &self.types,
58-
resources: &self.resources,
59+
resources: self.resources.as_ref(),
5960
}
6061
}
6162

@@ -69,13 +70,17 @@ impl<T> Handle<T> {
6970
{
7071
(self.index == other.index
7172
&& Arc::ptr_eq(&self.types, &other.types)
72-
&& Arc::ptr_eq(&self.resources, &other.resources))
73+
&& match (&self.resources, &other.resources) {
74+
(Some(a), Some(b)) => Arc::ptr_eq(a, b),
75+
(None, None) => true,
76+
_ => false,
77+
})
7378
|| type_check(
7479
&TypeChecker {
7580
a_types: &self.types,
7681
b_types: &other.types,
77-
a_resource: &self.resources,
78-
b_resource: &other.resources,
82+
a_resource: self.resources.as_deref(),
83+
b_resource: other.resources.as_deref(),
7984
},
8085
self.index,
8186
other.index,
@@ -94,9 +99,9 @@ impl<T: fmt::Debug> fmt::Debug for Handle<T> {
9499
/// Type checker between two `Handle`s
95100
struct TypeChecker<'a> {
96101
a_types: &'a ComponentTypes,
97-
a_resource: &'a TryPrimaryMap<ResourceIndex, ResourceType>,
102+
a_resource: Option<&'a TryPrimaryMap<ResourceIndex, ResourceType>>,
98103
b_types: &'a ComponentTypes,
99-
b_resource: &'a TryPrimaryMap<ResourceIndex, ResourceType>,
104+
b_resource: Option<&'a TryPrimaryMap<ResourceIndex, ResourceType>>,
100105
}
101106

102107
impl TypeChecker<'_> {
@@ -184,7 +189,7 @@ impl TypeChecker<'_> {
184189
(
185190
TypeResourceTable::Concrete { ty: a, .. },
186191
TypeResourceTable::Concrete { ty: b, .. },
187-
) => self.a_resource[*a] == self.b_resource[*b],
192+
) => self.a_resource.unwrap()[*a] == self.b_resource.unwrap()[*b],
188193
(TypeResourceTable::Concrete { .. }, _) => false,
189194

190195
// Abstract resource types are only the same if they have the same
@@ -615,9 +620,9 @@ impl FutureType {
615620
match (my_payload, payload) {
616621
(Some(a), Some(b)) => TypeChecker {
617622
a_types: &self.0.types,
618-
a_resource: &self.0.resources,
623+
a_resource: self.0.resources.as_deref(),
619624
b_types: ty.types,
620-
b_resource: ty.resources,
625+
b_resource: ty.resources.map(|p| &**p),
621626
}
622627
.interface_types_equal(*a, *b),
623628
(None, None) => true,
@@ -672,9 +677,9 @@ impl StreamType {
672677
match (my_payload, payload) {
673678
(Some(a), Some(b)) => TypeChecker {
674679
a_types: &self.0.types,
675-
a_resource: &self.0.resources,
680+
a_resource: self.0.resources.as_deref(),
676681
b_types: ty.types,
677-
b_resource: ty.resources,
682+
b_resource: ty.resources.map(|p| &**p),
678683
}
679684
.interface_types_equal(*a, *b),
680685
(None, None) => true,
@@ -1071,7 +1076,7 @@ impl Component {
10711076
pub fn instance_type(&self) -> InstanceType<'_> {
10721077
InstanceType {
10731078
types: &self.0.types,
1074-
resources: &self.0.resources,
1079+
resources: self.0.resources.as_ref(),
10751080
}
10761081
}
10771082
}
@@ -1152,7 +1157,7 @@ impl ComponentItem {
11521157
TypeResourceTable::Concrete {
11531158
ty: resource_index, ..
11541159
} => {
1155-
let ty = match ty.resources.get(resource_index) {
1160+
let ty = match ty.resources.and_then(|t| t.get(resource_index)) {
11561161
// This resource type was substituted by a linker for
11571162
// example so it's replaced here.
11581163
Some(ty) => *ty,

0 commit comments

Comments
 (0)