Skip to main content

wasmtime_environ/gc/
copying.rs

1//! Layout of Wasm GC objects in the copying garbage collector.
2
3use super::*;
4use core::mem;
5
6/// The size of the `VMCopyingHeader` header for GC objects.
7///
8/// Note: This is 16 (not 12) because `VMGcHeader` has `align(8)`, so the
9/// `repr(C)` struct has 4 bytes of trailing padding after the `object_size`
10/// field.
11pub const HEADER_SIZE: u32 = 16;
12
13/// The alignment of all GC objects in the copying collector.
14///
15/// All objects and all layouts must be a multiple of this alignment.
16pub const ALIGN: u32 = 16;
17
18/// The offset of the length field in a `VMCopyingArrayHeader`.
19pub const ARRAY_LENGTH_OFFSET: u32 = HEADER_SIZE;
20
21/// The offset of the tag-instance-index field in an exception header.
22pub const EXCEPTION_TAG_INSTANCE_OFFSET: u32 = HEADER_SIZE;
23
24/// The offset of the tag-defined-index field in an exception header.
25pub const EXCEPTION_TAG_DEFINED_OFFSET: u32 = HEADER_SIZE + 4;
26
27/// The bit within a `VMCopyingHeader`'s reserved bits that represents whether,
28/// during a collection, the object has already been copied into the new
29/// semi-space.
30pub const HEADER_COPIED_BIT: u32 = 1 << 0;
31
32/// The offset within this GC object, which must have the `HEADER_COPIED_BIT`
33/// set and must reside within the old semi-space, where the new copy of this
34/// object is located within the new semi-space.
35pub const FORWARDING_REF_OFFSET: u32 = HEADER_SIZE;
36
37/// The minimum object size: every object must have enough room for the
38/// forwarding reference that the copying collector writes during collection.
39pub const MIN_OBJECT_SIZE: u32 = FORWARDING_REF_OFFSET + mem::size_of::<u32>() as u32;
40
41/// The layout of Wasm GC objects in the copying collector.
42#[derive(Default)]
43pub struct CopyingTypeLayouts;
44
45impl GcTypeLayouts for CopyingTypeLayouts {
46    fn array_length_field_offset(&self) -> u32 {
47        ARRAY_LENGTH_OFFSET
48    }
49
50    fn exception_tag_instance_offset(&self) -> u32 {
51        EXCEPTION_TAG_INSTANCE_OFFSET
52    }
53
54    fn exception_tag_defined_offset(&self) -> u32 {
55        EXCEPTION_TAG_DEFINED_OFFSET
56    }
57
58    fn array_layout(&self, ty: &WasmArrayType) -> GcArrayLayout {
59        let mut layout = common_array_layout(ty, HEADER_SIZE, ALIGN, ARRAY_LENGTH_OFFSET);
60        debug_assert!(layout.align <= ALIGN);
61        layout.align = ALIGN;
62        debug_assert!(layout.base_size >= MIN_OBJECT_SIZE);
63        layout
64    }
65
66    fn struct_layout(&self, ty: &WasmStructType) -> GcStructLayout {
67        let mut layout = common_struct_layout(ty, HEADER_SIZE, ALIGN);
68        // Ensure there is always space for the forwarding reference, even if
69        // the struct has no fields.
70        if layout.size < MIN_OBJECT_SIZE {
71            layout.size = MIN_OBJECT_SIZE;
72        }
73        layout.size = layout.size.next_multiple_of(ALIGN);
74        debug_assert!(layout.align <= ALIGN);
75        layout.align = ALIGN;
76        debug_assert!(layout.size >= MIN_OBJECT_SIZE);
77        layout
78    }
79
80    fn exn_layout(&self, ty: &WasmExnType) -> GcStructLayout {
81        let mut layout = common_exn_layout(ty, HEADER_SIZE, ALIGN);
82        layout.size = layout.size.next_multiple_of(ALIGN);
83        debug_assert!(layout.align <= ALIGN);
84        layout.align = ALIGN;
85        debug_assert!(layout.size >= MIN_OBJECT_SIZE);
86        layout
87    }
88}