Skip to content

Commit 078002a

Browse files
committed
stack-switching: define VMContObj as two words
This change migrates VMContObj and its usages in cranelift and runtime to work with the VMContObj fat pointer as two words in order to better target different architectures (still gated to x86_64 for now). To support this, a size type was plumbed into the builtins function signature types (as is done for component types) that maps to usize.
1 parent 61d22a6 commit 078002a

8 files changed

Lines changed: 49 additions & 31 deletions

File tree

crates/cranelift/src/func_environ.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2397,7 +2397,7 @@ impl FuncEnvironment<'_> {
23972397
WasmHeapTopType::Cont => {
23982398
let (elem_addr, flags) = table_data.prepare_table_addr(self, builder, index);
23992399
Ok(builder.ins().load(
2400-
stack_switching::fatpointer::POINTER_TYPE,
2400+
stack_switching::fatpointer::fatpointer_type(self),
24012401
flags,
24022402
elem_addr,
24032403
0,

crates/cranelift/src/func_environ/stack_switching/fatpointer.rs

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
use cranelift_codegen::ir;
22
use cranelift_codegen::ir::InstBuilder;
33

4-
/// The Cranelift type used to represent all of the following:
4+
/// Returns the Cranelift type used to represent all of the following:
55
/// - wasm values of type `(ref null $ct)` and `(ref $ct)`
66
/// - equivalently: runtime values of type `Option<VMContObj>` and `VMContObj`
7-
/// Note that a `VMContObj` is a fat pointer
8-
/// consisting of a pointer to `VMContRef` and a 64 bit sequence
9-
/// counter.
10-
/// We represent this here as a 128bit value, with the same representation as
11-
/// `core::mem::transmute::<i128, VMContObj>`.
12-
pub const POINTER_TYPE: ir::Type = ir::types::I128;
7+
/// Note that a `VMContObj` is a fat pointer consisting of a pointer to
8+
/// `VMContRef` and a pointer-sized revision counter. We represent this as 2 words
9+
/// (pointer and usize).
10+
pub fn fatpointer_type(env: &crate::func_environ::FuncEnvironment) -> ir::Type {
11+
let ptr_bits = env.pointer_type().bits();
12+
ir::Type::int((2 * ptr_bits).try_into().unwrap()).unwrap()
13+
}
1314

1415
/// Turns a (possibly null) reference to a continuation object into a tuple
1516
/// (revision, contref_ptr). If `contobj` denotes a wasm null reference, the
@@ -19,13 +20,13 @@ pub(crate) fn deconstruct<'a>(
1920
pos: &mut cranelift_codegen::cursor::FuncCursor,
2021
contobj: ir::Value,
2122
) -> (ir::Value, ir::Value) {
22-
debug_assert_eq!(pos.func.dfg.value_type(contobj), POINTER_TYPE);
23+
debug_assert_eq!(pos.func.dfg.value_type(contobj), fatpointer_type(env));
2324
let ptr_ty = env.pointer_type();
24-
assert!(ptr_ty.bits() <= 64);
25+
let ptr_bits = ptr_ty.bits();
2526

2627
let contref = pos.ins().ireduce(ptr_ty, contobj);
27-
let shifted = pos.ins().ushr_imm(contobj, 64);
28-
let revision_counter = pos.ins().ireduce(ir::types::I64, shifted);
28+
let shifted = pos.ins().ushr_imm(contobj, i64::from(ptr_bits));
29+
let revision_counter = pos.ins().ireduce(ptr_ty, shifted);
2930

3031
(revision_counter, contref)
3132
}
@@ -38,13 +39,16 @@ pub(crate) fn construct<'a>(
3839
revision_counter: ir::Value,
3940
contref_addr: ir::Value,
4041
) -> ir::Value {
41-
debug_assert_eq!(pos.func.dfg.value_type(contref_addr), env.pointer_type());
42-
debug_assert_eq!(pos.func.dfg.value_type(revision_counter), ir::types::I64);
43-
assert!(env.pointer_type().bits() <= 64);
42+
let ptr_ty = env.pointer_type();
43+
let ptr_bits = ptr_ty.bits();
44+
let fat_ptr_ty = fatpointer_type(env);
45+
46+
debug_assert_eq!(pos.func.dfg.value_type(contref_addr), ptr_ty);
47+
debug_assert_eq!(pos.func.dfg.value_type(revision_counter), ptr_ty);
4448

45-
let contref_addr = pos.ins().uextend(ir::types::I128, contref_addr);
46-
let revision_counter = pos.ins().uextend(ir::types::I128, revision_counter);
47-
let shifted_counter = pos.ins().ishl_imm(revision_counter, 64);
49+
let contref_addr = pos.ins().uextend(fat_ptr_ty, contref_addr);
50+
let revision_counter = pos.ins().uextend(fat_ptr_ty, revision_counter);
51+
let shifted_counter = pos.ins().ishl_imm(revision_counter, i64::from(ptr_bits));
4852
let contobj = pos.ins().bor(shifted_counter, contref_addr);
4953

5054
contobj

crates/cranelift/src/lib.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,10 @@ fn reference_type(wasm_ht: WasmHeapType, pointer_type: ir::Type) -> ir::Type {
213213
match wasm_ht.top() {
214214
WasmHeapTopType::Func => pointer_type,
215215
WasmHeapTopType::Any | WasmHeapTopType::Extern | WasmHeapTopType::Exn => ir::types::I32,
216-
WasmHeapTopType::Cont => func_environ::stack_switching::fatpointer::POINTER_TYPE,
216+
WasmHeapTopType::Cont => {
217+
// VMContObj is 2 * pointer_size (pointer + usize revision)
218+
ir::Type::int((2 * pointer_type.bits()).try_into().unwrap()).unwrap()
219+
}
217220
}
218221
}
219222

@@ -372,6 +375,10 @@ impl BuiltinFunctionSignatures {
372375
AbiParam::new(ir::types::I8)
373376
}
374377

378+
fn size(&self) -> AbiParam {
379+
AbiParam::new(self.pointer_type)
380+
}
381+
375382
fn wasm_signature(&self, builtin: BuiltinFunctionIndex) -> Signature {
376383
let mut _cur = 0;
377384
macro_rules! iter {

crates/environ/src/builtin.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,12 +233,12 @@ macro_rules! foreach_builtin_function {
233233
// denote the continuation being `None`, `init_contref`
234234
// may be 0.
235235
#[cfg(feature = "stack-switching")]
236-
table_grow_cont_obj(vmctx: vmctx, table: u32, delta: u64, init_contref: pointer, init_revision: u64) -> pointer;
236+
table_grow_cont_obj(vmctx: vmctx, table: u32, delta: u64, init_contref: pointer, init_revision: size) -> pointer;
237237

238238
// `value_contref` and `value_revision` together encode
239239
// the Option<VMContObj>, as in previous libcall.
240240
#[cfg(feature = "stack-switching")]
241-
table_fill_cont_obj(vmctx: vmctx, table: u32, dst: u64, value_contref: pointer, value_revision: u64, len: u64) -> bool;
241+
table_fill_cont_obj(vmctx: vmctx, table: u32, dst: u64, value_contref: pointer, value_revision: size, len: u64) -> bool;
242242

243243
// Return the instance ID for a given vmctx.
244244
#[cfg(feature = "gc")]

crates/environ/src/vmoffsets.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -348,12 +348,17 @@ pub trait PtrSize {
348348

349349
/// Return the offset of `VMContObj::revision`
350350
fn vmcontobj_revision(&self) -> u8 {
351-
8
351+
self.size()
352352
}
353353

354-
/// Return the size of `VMHostArray`.
354+
/// Return the size of `VMContObj`.
355355
fn size_of_vmcontobj(&self) -> u8 {
356-
16
356+
u8::try_from(align(
357+
u32::from(self.vmcontobj_revision())
358+
+ u32::try_from(core::mem::size_of::<usize>()).unwrap(),
359+
u32::from(self.size()),
360+
))
361+
.unwrap()
357362
}
358363

359364
// Offsets within `VMContRef`

crates/wasmtime/src/runtime/vm/libcalls.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ pub mod raw {
157157
(@ty f64x2) => (f64x2);
158158
(@ty bool) => (bool);
159159
(@ty pointer) => (*mut u8);
160+
(@ty size) => (usize);
160161
}
161162

162163
wasmtime_environ::foreach_builtin_function!(libcall);
@@ -339,7 +340,7 @@ unsafe fn table_grow_cont_obj(
339340
// The following two values together form the initial Option<VMContObj>.
340341
// A None value is indicated by the pointer being null.
341342
init_value_contref: *mut u8,
342-
init_value_revision: u64,
343+
init_value_revision: usize,
343344
) -> Result<Option<AllocationSize>> {
344345
let defined_table_index = DefinedTableIndex::from_u32(defined_table_index);
345346
let element = unsafe { VMContObj::from_raw_parts(init_value_contref, init_value_revision) };
@@ -416,7 +417,7 @@ unsafe fn table_fill_cont_obj(
416417
table_index: u32,
417418
dst: u64,
418419
value_contref: *mut u8,
419-
value_revision: u64,
420+
value_revision: usize,
420421
len: u64,
421422
) -> Result<()> {
422423
let instance = store.instance_mut(instance);

crates/wasmtime/src/runtime/vm/stack_switching.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,15 @@ pub use stack::*;
3939
/// For performance reasons, the VMContRef at the bottom of this chain
4040
/// (i.e., the one pointed to by the VMContObj) has a pointer to the
4141
/// other end of the chain (i.e., its last ancestor).
42-
#[repr(C, align(16))]
42+
#[repr(C)]
4343
#[derive(Debug, Clone, Copy)]
4444
pub struct VMContObj {
4545
pub contref: NonNull<VMContRef>,
46-
pub revision: u64,
46+
pub revision: usize,
4747
}
4848

4949
impl VMContObj {
50-
pub fn new(contref: NonNull<VMContRef>, revision: u64) -> Self {
50+
pub fn new(contref: NonNull<VMContRef>, revision: usize) -> Self {
5151
Self { contref, revision }
5252
}
5353

@@ -59,7 +59,7 @@ impl VMContObj {
5959
///
6060
/// Behavior will be undefined if a pointer to data that is not a
6161
/// VMContRef is provided.
62-
pub unsafe fn from_raw_parts(contref: *mut u8, revision: u64) -> Option<Self> {
62+
pub unsafe fn from_raw_parts(contref: *mut u8, revision: usize) -> Option<Self> {
6363
NonNull::new(contref.cast::<VMContRef>()).map(|contref| Self::new(contref, revision))
6464
}
6565
}
@@ -204,7 +204,7 @@ pub struct VMContRef {
204204
pub last_ancestor: *mut VMContRef,
205205

206206
/// Revision counter.
207-
pub revision: u64,
207+
pub revision: usize,
208208

209209
/// The underlying stack.
210210
pub stack: VMContinuationStack,

crates/wasmtime/src/runtime/vm/vmcontext.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,6 +1056,7 @@ macro_rules! define_builtin_array {
10561056
(@ty f64x2) => (f64x2);
10571057
(@ty bool) => (bool);
10581058
(@ty pointer) => (*mut u8);
1059+
(@ty size) => (usize);
10591060
(@ty vmctx) => (NonNull<VMContext>);
10601061
}
10611062

0 commit comments

Comments
 (0)