diff --git a/vmkit/Cargo.toml b/vmkit/Cargo.toml index 4fa17fc..ca7c43e 100644 --- a/vmkit/Cargo.toml +++ b/vmkit/Cargo.toml @@ -32,7 +32,7 @@ uncooperative = ["cooperative", "mmtk/immix_non_moving", "mmtk/immix_zero_on_rel # VMKit is built for use in cooperative runtime. Such runtime # would be able to use write barriers and safepoints. Such environment # must also provide precise object layout (stack can be uncooperative). -cooperative = ["mmtk/vo_bit", "mmtk/is_mmtk_object", "mmtk/vo_bit_access", "mmtk/immix_non_moving"] +cooperative = ["object_pinning", "mmtk/vo_bit", "mmtk/is_mmtk_object", "mmtk/vo_bit_access", "mmtk/immix_non_moving"] # VMKit is built for use in full-precise runtime. Such runtime # would be able to use precise write barriers and safepoints, object # layout is fully precise. diff --git a/vmkit/examples/binarytrees.rs b/vmkit/examples/binarytrees.rs index 97a5693..70237ba 100644 --- a/vmkit/examples/binarytrees.rs +++ b/vmkit/examples/binarytrees.rs @@ -72,7 +72,7 @@ impl VirtualMachine for BenchVM { #[cfg(feature="vmside_forwarding")] const LOCAL_FORWARDING_POINTER_SPEC: mmtk::vm::VMLocalForwardingPointerSpec = mmtk::vm::VMLocalForwardingPointerSpec::in_header(0); #[cfg(feature="vmside_forwarding")] - const LOCAL_FORWARDING_BITS_SPEC: mmtk::vm::VMLocalForwardingBitsSpec = mmtk::vm::VMLocalForwardingBitsSpec::side_first(); + const LOCAL_FORWARDING_BITS_SPEC: mmtk::vm::VMLocalForwardingBitsSpec = mmtk::vm::VMLocalForwardingBitsSpec::in_header(62); fn get() -> &'static Self { VM.get().unwrap() diff --git a/vmkit/src/lib.rs b/vmkit/src/lib.rs index cac66e3..c895610 100644 --- a/vmkit/src/lib.rs +++ b/vmkit/src/lib.rs @@ -27,13 +27,20 @@ pub trait VirtualMachine: Sized + 'static + Send + Sync { type Slot: SlotExtra; type MemorySlice: MemorySlice; - - #[cfg(feature="vmside_forwarding")] + /// 1-word local metadata for spaces that may copy objects. + /// This metadata has to be stored in the header. + /// This metadata can be defined at a position within the object payload. + /// As a forwarding pointer is only stored in dead objects which is not + /// accessible by the language, it is okay that store a forwarding pointer overwrites object payload + /// + #[cfg(feature = "vmside_forwarding")] const LOCAL_FORWARDING_POINTER_SPEC: mmtk::vm::VMLocalForwardingPointerSpec; - #[cfg(feature="vmside_forwarding")] + /// 2-bit local metadata for spaces that store a forwarding state for objects. + /// If this spec is defined in the header, it can be defined with a position of the lowest 2 bits in the forwarding pointer. + /// If this spec is defined on the side it must be defined after the [`MARK_BIT_SPEC`](crate::object_model::MARK_BIT_SPEC). + #[cfg(feature = "vmside_forwarding")] const LOCAL_FORWARDING_BITS_SPEC: mmtk::vm::VMLocalForwardingBitsSpec; - const ALIGNMENT_VALUE: u32 = 0xdead_beef; const MAX_ALIGNMENT: usize = 32; const MIN_ALIGNMENT: usize = 8; @@ -157,14 +164,16 @@ pub trait VirtualMachine: Sized + 'static + Send + Sync { /// Compute the hashcode of an object. When feature `address_based_hashing` is enabled, /// this function is ignored. Otherwise VMKit calls into this function to compute hashcode of an object. - /// + /// /// In case VM uses moving plans it's strongly advised to *not* compute hashcode based on address /// as the object's address may change during GC, instead store hashcode as a field or use some bits - /// in header to store the hashcode. This function must be fast as it's called for each `VMKitObject::hashcode()` + /// in header to store the hashcode. This function must be fast as it's called for each `VMKitObject::hashcode()` /// invocation. fn compute_hashcode(object: VMKitObject) -> usize { let _ = object; - unimplemented!("VM currently does not support hashcode computation, override this method to do so"); + unimplemented!( + "VM currently does not support hashcode computation, override this method to do so" + ); } } diff --git a/vmkit/src/object_model.rs b/vmkit/src/object_model.rs index 7b081ba..ce80dc9 100644 --- a/vmkit/src/object_model.rs +++ b/vmkit/src/object_model.rs @@ -16,55 +16,53 @@ pub mod object; pub struct VMKitObjectModel(PhantomData); -/* -pub const LOGGING_SIDE_METADATA_SPEC: VMGlobalLogBitSpec = VMGlobalLogBitSpec::side_first(); -pub const FORWARDING_POINTER_METADATA_SPEC: VMLocalForwardingPointerSpec = - VMLocalForwardingPointerSpec::in_header(0); -pub const FORWARDING_BITS_METADATA_SPEC: VMLocalForwardingBitsSpec = - VMLocalForwardingBitsSpec::in_header(HashStateField::NEXT_BIT as _); -pub const MARKING_METADATA_SPEC: VMLocalMarkBitSpec = VMLocalMarkBitSpec::side_first(); -pub const LOS_METADATA_SPEC: VMLocalLOSMarkNurserySpec = - VMLocalLOSMarkNurserySpec::in_header(HashStateField::NEXT_BIT as _);*/ - -pub const LOGGING_SIDE_METADATA_SPEC: VMGlobalLogBitSpec = VMGlobalLogBitSpec::side_first(); -/// Overwrite first field of the object header -pub const LOCAL_FORWARDING_POINTER_SPEC: VMLocalForwardingPointerSpec = - VMLocalForwardingPointerSpec::in_header(OBJECT_REF_OFFSET); +/// 1-bit local metadata for spaces that need to mark an object. +/// +/// Always defined on the side in VMKit. +pub const MARK_BIT_SPEC: VMLocalMarkBitSpec = VMLocalMarkBitSpec::side_first(); impl ObjectModel> for VMKitObjectModel { - /*const GLOBAL_LOG_BIT_SPEC: mmtk::vm::VMGlobalLogBitSpec = LOGGING_SIDE_METADATA_SPEC; - const LOCAL_FORWARDING_POINTER_SPEC: mmtk::vm::VMLocalForwardingPointerSpec = - FORWARDING_POINTER_METADATA_SPEC; - const LOCAL_FORWARDING_BITS_SPEC: mmtk::vm::VMLocalForwardingBitsSpec = - FORWARDING_BITS_METADATA_SPEC; - const LOCAL_MARK_BIT_SPEC: mmtk::vm::VMLocalMarkBitSpec = MARKING_METADATA_SPEC; - const LOCAL_LOS_MARK_NURSERY_SPEC: mmtk::vm::VMLocalLOSMarkNurserySpec = LOS_METADATA_SPEC;*/ const GLOBAL_LOG_BIT_SPEC: VMGlobalLogBitSpec = VMGlobalLogBitSpec::side_first(); - #[cfg(not(feature = "vmside_forwarding"))] - const LOCAL_FORWARDING_BITS_SPEC: VMLocalForwardingBitsSpec = - VMLocalForwardingBitsSpec::side_first(); - #[cfg(not(feature = "vmside_forwarding"))] - const LOCAL_FORWARDING_POINTER_SPEC: VMLocalForwardingPointerSpec = - VMLocalForwardingPointerSpec::in_header(0); + const LOCAL_MARK_BIT_SPEC: VMLocalMarkBitSpec = MARK_BIT_SPEC; + const LOCAL_FORWARDING_BITS_SPEC: VMLocalForwardingBitsSpec = { + #[cfg(feature = "vmside_forwarding")] + { + VM::LOCAL_FORWARDING_BITS_SPEC + } + #[cfg(not(feature = "vmside_forwarding"))] + { + VMLocalForwardingBitsSpec::side_after(&MARK_BIT_SPEC.as_spec()) + } + }; - #[cfg(feature = "vmside_forwarding")] - const LOCAL_FORWARDING_BITS_SPEC: VMLocalForwardingBitsSpec = VM::LOCAL_FORWARDING_BITS_SPEC; - #[cfg(feature = "vmside_forwarding")] - const LOCAL_FORWARDING_POINTER_SPEC: VMLocalForwardingPointerSpec = - VM::LOCAL_FORWARDING_POINTER_SPEC; - const LOCAL_MARK_BIT_SPEC: VMLocalMarkBitSpec = - if Self::LOCAL_FORWARDING_BITS_SPEC.as_spec().is_on_side() { - VMLocalMarkBitSpec::side_after(&Self::LOCAL_FORWARDING_BITS_SPEC.as_spec()) + const LOCAL_FORWARDING_POINTER_SPEC: VMLocalForwardingPointerSpec = { + #[cfg(feature = "vmside_forwarding")] + { + VM::LOCAL_FORWARDING_POINTER_SPEC + } + #[cfg(not(feature = "vmside_forwarding"))] + { + VMLocalForwardingPointerSpec::in_header(0) + } + }; + + const LOCAL_LOS_MARK_NURSERY_SPEC: VMLocalLOSMarkNurserySpec = { + let spec_after = if Self::LOCAL_FORWARDING_BITS_SPEC.as_spec().is_in_header() { + Self::LOCAL_MARK_BIT_SPEC.as_spec() } else { - VMLocalMarkBitSpec::side_first() + Self::LOCAL_FORWARDING_BITS_SPEC.as_spec() }; + VMLocalLOSMarkNurserySpec::side_after(&spec_after) + }; + + #[cfg(feature="object_pinning")] + const LOCAL_PINNING_BIT_SPEC: VMLocalPinningBitSpec = { + VMLocalPinningBitSpec::side_after(&Self::LOCAL_LOS_MARK_NURSERY_SPEC.as_spec()) + }; + - const LOCAL_LOS_MARK_NURSERY_SPEC: VMLocalLOSMarkNurserySpec = - VMLocalLOSMarkNurserySpec::side_after(&Self::LOCAL_MARK_BIT_SPEC.as_spec()); - const LOCAL_PINNING_BIT_SPEC: VMLocalPinningBitSpec = - VMLocalPinningBitSpec::side_after(&Self::LOCAL_LOS_MARK_NURSERY_SPEC.as_spec()); const OBJECT_REF_OFFSET_LOWER_BOUND: isize = OBJECT_REF_OFFSET; const UNIFIED_OBJECT_REFERENCE_ADDRESS: bool = false;