Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

threads: add WasmCompositeInnerType layer #9520

Merged
merged 12 commits into from
Nov 2, 2024
6 changes: 3 additions & 3 deletions crates/cranelift/src/func_environ.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use wasmtime_environ::{
BuiltinFunctionIndex, DataIndex, ElemIndex, EngineOrModuleTypeIndex, FuncIndex, GlobalIndex,
IndexType, Memory, MemoryIndex, MemoryPlan, MemoryStyle, Module, ModuleInternedTypeIndex,
ModuleTranslation, ModuleTypesBuilder, PtrSize, Table, TableIndex, TableStyle, Tunables,
TypeConvert, TypeIndex, VMOffsets, WasmCompositeType, WasmFuncType, WasmHeapTopType,
TypeConvert, TypeIndex, VMOffsets, WasmCompositeInnerType, WasmFuncType, WasmHeapTopType,
WasmHeapType, WasmRefType, WasmResult, WasmValType,
};
use wasmtime_environ::{FUNCREF_INIT_BIT, FUNCREF_MASK};
Expand Down Expand Up @@ -1932,8 +1932,8 @@ impl<'module_environment> crate::translate::FuncEnvironment

fn struct_fields_len(&mut self, struct_type_index: TypeIndex) -> WasmResult<usize> {
let ty = self.module.types[struct_type_index];
match &self.types[ty].composite_type {
WasmCompositeType::Struct(s) => Ok(s.fields.len()),
match &self.types[ty].composite_type.inner {
WasmCompositeInnerType::Struct(s) => Ok(s.fields.len()),
_ => unreachable!(),
}
}
Expand Down
56 changes: 14 additions & 42 deletions crates/cranelift/src/gc/enabled.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ use cranelift_entity::packed_option::ReservedValue;
use cranelift_frontend::FunctionBuilder;
use wasmtime_environ::{
GcArrayLayout, GcLayout, GcStructLayout, ModuleInternedTypeIndex, PtrSize, TypeIndex, VMGcKind,
WasmCompositeType, WasmHeapTopType, WasmHeapType, WasmRefType, WasmResult, WasmStorageType,
WasmValType, I31_DISCRIMINANT, NON_NULL_NON_I31_MASK,
WasmHeapTopType, WasmHeapType, WasmRefType, WasmResult, WasmStorageType, WasmValType,
I31_DISCRIMINANT, NON_NULL_NON_I31_MASK,
};

mod drc;
Expand Down Expand Up @@ -252,10 +252,7 @@ pub fn translate_struct_new_default(
struct_type_index: TypeIndex,
) -> WasmResult<ir::Value> {
let interned_ty = func_env.module.types[struct_type_index];
let struct_ty = match &func_env.types[interned_ty].composite_type {
WasmCompositeType::Struct(s) => s,
_ => unreachable!(),
};
let struct_ty = func_env.types.unwrap_struct(interned_ty)?;
let fields = struct_ty
.fields
.iter()
Expand Down Expand Up @@ -284,12 +281,7 @@ pub fn translate_struct_get(
let struct_size_val = builder.ins().iconst(ir::types::I32, i64::from(struct_size));

let field_offset = struct_layout.fields[field_index];

let field_ty = match &func_env.types[interned_type_index].composite_type {
WasmCompositeType::Struct(s) => &s.fields[field_index],
_ => unreachable!(),
};

let field_ty = &func_env.types.unwrap_struct(interned_type_index)?.fields[field_index];
let field_size = wasmtime_environ::byte_size_of_wasm_ty_in_gc_heap(&field_ty.element_type);
assert!(field_offset + field_size <= struct_size);

Expand Down Expand Up @@ -322,12 +314,7 @@ fn translate_struct_get_and_extend(
let struct_size_val = builder.ins().iconst(ir::types::I32, i64::from(struct_size));

let field_offset = struct_layout.fields[field_index];

let field_ty = match &func_env.types[interned_type_index].composite_type {
WasmCompositeType::Struct(s) => &s.fields[field_index],
_ => unreachable!(),
};

let field_ty = &func_env.types.unwrap_struct(interned_type_index)?.fields[field_index];
let field_size = wasmtime_environ::byte_size_of_wasm_ty_in_gc_heap(&field_ty.element_type);
assert!(field_offset + field_size <= struct_size);

Expand Down Expand Up @@ -400,12 +387,7 @@ pub fn translate_struct_set(
let struct_size_val = builder.ins().iconst(ir::types::I32, i64::from(struct_size));

let field_offset = struct_layout.fields[field_index];

let field_ty = match &func_env.types[interned_type_index].composite_type {
WasmCompositeType::Struct(s) => &s.fields[field_index],
_ => unreachable!(),
};

let field_ty = &func_env.types.unwrap_struct(interned_type_index)?.fields[field_index];
let field_size = wasmtime_environ::byte_size_of_wasm_ty_in_gc_heap(&field_ty.element_type);
assert!(field_offset + field_size <= struct_size);

Expand Down Expand Up @@ -447,9 +429,7 @@ pub fn translate_array_new_default(
len: ir::Value,
) -> WasmResult<ir::Value> {
let interned_ty = func_env.module.types[array_type_index];
let WasmCompositeType::Array(array_ty) = &func_env.types[interned_ty].composite_type else {
unreachable!()
};
let array_ty = func_env.types.unwrap_array(interned_ty)?;
let elem = default_value(&mut builder.cursor(), func_env, &array_ty.0.element_type);
gc_compiler(func_env)?.alloc_array(
func_env,
Expand Down Expand Up @@ -596,9 +576,9 @@ pub fn translate_array_fill(
one_elem_size,
fill_end,
|func_env, builder, elem_addr| {
let elem_ty = func_env.types[interned_type_index]
.composite_type
.unwrap_array()
let elem_ty = func_env
.types
.unwrap_array(interned_type_index)?
.0
.element_type;
write_field_at_addr(func_env, builder, elem_ty, elem_addr, value)
Expand Down Expand Up @@ -763,9 +743,7 @@ pub fn translate_array_get(
let array_type_index = func_env.module.types[array_type_index];
let elem_addr = array_elem_addr(func_env, builder, array_type_index, array_ref, index);

let array_ty = func_env.types[array_type_index]
.composite_type
.unwrap_array();
let array_ty = func_env.types.unwrap_array(array_type_index)?;
let elem_ty = array_ty.0.element_type;

read_field_at_addr(func_env, builder, elem_ty, elem_addr, None)
Expand All @@ -781,9 +759,7 @@ pub fn translate_array_get_s(
let array_type_index = func_env.module.types[array_type_index];
let elem_addr = array_elem_addr(func_env, builder, array_type_index, array_ref, index);

let array_ty = func_env.types[array_type_index]
.composite_type
.unwrap_array();
let array_ty = func_env.types.unwrap_array(array_type_index)?;
let elem_ty = array_ty.0.element_type;

read_field_at_addr(func_env, builder, elem_ty, elem_addr, Some(Extension::Sign))
Expand All @@ -799,9 +775,7 @@ pub fn translate_array_get_u(
let array_type_index = func_env.module.types[array_type_index];
let elem_addr = array_elem_addr(func_env, builder, array_type_index, array_ref, index);

let array_ty = func_env.types[array_type_index]
.composite_type
.unwrap_array();
let array_ty = func_env.types.unwrap_array(array_type_index)?;
let elem_ty = array_ty.0.element_type;

read_field_at_addr(func_env, builder, elem_ty, elem_addr, Some(Extension::Zero))
Expand All @@ -818,9 +792,7 @@ pub fn translate_array_set(
let array_type_index = func_env.module.types[array_type_index];
let elem_addr = array_elem_addr(func_env, builder, array_type_index, array_ref, index);

let array_ty = func_env.types[array_type_index]
.composite_type
.unwrap_array();
let array_ty = func_env.types.unwrap_array(array_type_index)?;
let elem_ty = array_ty.0.element_type;

write_field_at_addr(func_env, builder, elem_ty, elem_addr, value)
Expand Down
12 changes: 3 additions & 9 deletions crates/cranelift/src/gc/enabled/drc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ use cranelift_frontend::FunctionBuilder;
use smallvec::SmallVec;
use wasmtime_environ::{
drc::DrcTypeLayouts, GcArrayLayout, GcTypeLayouts, ModuleInternedTypeIndex, PtrSize, TypeIndex,
VMGcKind, WasmCompositeType, WasmHeapTopType, WasmHeapType, WasmRefType, WasmResult,
WasmStorageType, WasmValType,
VMGcKind, WasmHeapTopType, WasmHeapType, WasmRefType, WasmResult, WasmStorageType, WasmValType,
};

#[derive(Default)]
Expand Down Expand Up @@ -413,9 +412,7 @@ impl GcCompiler for DrcCompiler {

// Finally, initialize each of the newly-allocated array's elements.

let array_ty = func_env.types[interned_type_index]
.composite_type
.unwrap_array();
let array_ty = func_env.types.unwrap_array(interned_type_index)?;
let elem_ty = array_ty.0.element_type;

let pointer_type = func_env.pointer_type();
Expand Down Expand Up @@ -493,10 +490,7 @@ impl GcCompiler for DrcCompiler {
uextend_i32_to_pointer_type(builder, func_env.pointer_type(), struct_ref);
let struct_addr = builder.ins().iadd(base, extended_struct_ref);

let struct_ty = match &func_env.types[interned_type_index].composite_type {
WasmCompositeType::Struct(s) => s,
_ => unreachable!(),
};
let struct_ty = func_env.types.unwrap_struct(interned_type_index)?;
let field_types: SmallVec<[_; 8]> = struct_ty.fields.iter().cloned().collect();
assert_eq!(field_vals.len(), field_types.len());

Expand Down
73 changes: 60 additions & 13 deletions crates/environ/src/compile/module_types.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::{
EngineOrModuleTypeIndex, EntityRef, ModuleInternedRecGroupIndex, ModuleInternedTypeIndex,
ModuleTypes, TypeConvert, TypeIndex, WasmCompositeType, WasmFuncType, WasmHeapType, WasmResult,
WasmSubType,
wasm_unsupported, EngineOrModuleTypeIndex, EntityRef, ModuleInternedRecGroupIndex,
ModuleInternedTypeIndex, ModuleTypes, TypeConvert, TypeIndex, WasmArrayType,
WasmCompositeInnerType, WasmCompositeType, WasmFuncType, WasmHeapType, WasmResult,
WasmStructType, WasmSubType,
};
use std::{borrow::Cow, collections::HashMap, ops::Index};
use wasmparser::{UnpackedIndex, Validator, ValidatorId};
Expand Down Expand Up @@ -140,7 +141,8 @@ impl ModuleTypesBuilder {
&mut self,
for_func_ty: ModuleInternedTypeIndex,
) -> ModuleInternedTypeIndex {
let trampoline = self.types[for_func_ty].unwrap_func().trampoline_type();
let sub_ty = &self.types[for_func_ty];
let trampoline = sub_ty.unwrap_func().trampoline_type();

if let Some(idx) = self.trampoline_types.get(&trampoline) {
// We've already interned this trampoline type; reuse it.
Expand All @@ -163,7 +165,10 @@ impl ModuleTypesBuilder {
let idx = self.types.push(WasmSubType {
is_final: true,
supertype: None,
composite_type: WasmCompositeType::Func(f.clone()),
composite_type: WasmCompositeType {
inner: WasmCompositeInnerType::Func(f.clone()),
shared: sub_ty.composite_type.shared,
},
});

// The trampoline type is its own trampoline type.
Expand Down Expand Up @@ -325,6 +330,46 @@ impl ModuleTypesBuilder {
pub fn trampoline_type(&self, ty: ModuleInternedTypeIndex) -> ModuleInternedTypeIndex {
self.types.trampoline_type(ty)
}

/// Get and unwrap a [`WasmStructType`] for the given struct index.
///
/// # Panics
///
/// Panics if the unwrapped type is not a struct.
///
/// # Errors
///
/// For now, fails with an unsupported error if the type is shared.
pub fn unwrap_struct(&self, ty: ModuleInternedTypeIndex) -> WasmResult<&WasmStructType> {
let composite_type = &self.types[ty].composite_type;
if composite_type.shared {
return Err(wasm_unsupported!("shared structs are not yet implemented"));
}
match &composite_type.inner {
WasmCompositeInnerType::Struct(s) => Ok(s),
_ => unreachable!(),
}
}

/// Get and unwrap a [`WasmArrayType`] for the given array index.
///
/// # Panics
///
/// Panics if the unwrapped type is not an array.
///
/// # Errors
///
/// For now, fails with an unsupported error if the type is shared.
pub fn unwrap_array(&self, interned_ty: ModuleInternedTypeIndex) -> WasmResult<&WasmArrayType> {
let composite_type = &self.types[interned_ty].composite_type;
if composite_type.shared {
return Err(wasm_unsupported!("shared arrays are not yet implemented"));
}
match &composite_type.inner {
WasmCompositeInnerType::Array(a) => Ok(a),
_ => unreachable!(),
}
}
}

// Forward the indexing impl to the internal `ModuleTypes`
Expand Down Expand Up @@ -388,10 +433,11 @@ where
// array vs struct vs func reference. In this case, we can use
// the validator's type context.
if let Some(ty) = self.types.types.get(interned) {
match &ty.composite_type {
abrown marked this conversation as resolved.
Show resolved Hide resolved
WasmCompositeType::Array(_) => WasmHeapType::ConcreteArray(index),
WasmCompositeType::Func(_) => WasmHeapType::ConcreteFunc(index),
WasmCompositeType::Struct(_) => WasmHeapType::ConcreteStruct(index),
assert!(!ty.composite_type.shared);
match &ty.composite_type.inner {
WasmCompositeInnerType::Array(_) => WasmHeapType::ConcreteArray(index),
WasmCompositeInnerType::Func(_) => WasmHeapType::ConcreteFunc(index),
WasmCompositeInnerType::Struct(_) => WasmHeapType::ConcreteStruct(index),
}
} else if let Some((wasmparser_types, _)) = self.rec_group_context.as_ref() {
let wasmparser_ty = &wasmparser_types[id].composite_type;
Expand Down Expand Up @@ -426,10 +472,11 @@ where
// indirectly get one by looking it up inside the current rec
// group.
if let Some(ty) = self.types.types.get(interned) {
match &ty.composite_type {
WasmCompositeType::Array(_) => WasmHeapType::ConcreteArray(index),
WasmCompositeType::Func(_) => WasmHeapType::ConcreteFunc(index),
WasmCompositeType::Struct(_) => WasmHeapType::ConcreteStruct(index),
assert!(!ty.composite_type.shared);
match &ty.composite_type.inner {
WasmCompositeInnerType::Array(_) => WasmHeapType::ConcreteArray(index),
WasmCompositeInnerType::Func(_) => WasmHeapType::ConcreteFunc(index),
WasmCompositeInnerType::Struct(_) => WasmHeapType::ConcreteStruct(index),
}
} else if let Some((parser_types, rec_group)) = self.rec_group_context.as_ref() {
let rec_group_index = interned.index() - self.types.types.len_types();
Expand Down
14 changes: 9 additions & 5 deletions crates/environ/src/gc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@
pub mod drc;

use crate::prelude::*;
use crate::{WasmArrayType, WasmCompositeType, WasmStorageType, WasmStructType, WasmValType};
use crate::{
WasmArrayType, WasmCompositeInnerType, WasmCompositeType, WasmStorageType, WasmStructType,
WasmValType,
};
use core::alloc::Layout;

/// Discriminant to check whether GC reference is an `i31ref` or not.
Expand Down Expand Up @@ -63,10 +66,11 @@ pub trait GcTypeLayouts {
/// Returns `None` if the type is a function type, as functions are not
/// managed by the GC.
fn gc_layout(&self, ty: &WasmCompositeType) -> Option<GcLayout> {
match ty {
WasmCompositeType::Array(ty) => Some(self.array_layout(ty).into()),
WasmCompositeType::Struct(ty) => Some(self.struct_layout(ty).into()),
WasmCompositeType::Func(_) => None,
assert!(!ty.shared);
match &ty.inner {
WasmCompositeInnerType::Array(ty) => Some(self.array_layout(ty).into()),
WasmCompositeInnerType::Struct(ty) => Some(self.struct_layout(ty).into()),
WasmCompositeInnerType::Func(_) => None,
abrown marked this conversation as resolved.
Show resolved Hide resolved
}
}

Expand Down
Loading