fix hashstate

This commit is contained in:
playX18 2025-02-15 12:56:49 +07:00
parent 6e294ecaf9
commit cd0e1344e4
8 changed files with 132 additions and 43 deletions

View file

@ -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 = ["object_pinning", "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"]
# 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.

View file

@ -126,7 +126,7 @@ impl NodeRef {
&METADATA,
AllocationSemantics::Default,
);
//node.hashcode::<BenchVM>();
node.set_field_object::<BenchVM, false>(offset_of!(Node, left), left.0);
node.set_field_object::<BenchVM, false>(offset_of!(Node, right), right.0);
@ -188,15 +188,8 @@ fn main() {
.parse::<usize>()
.unwrap();
let mut builder = MMTKBuilder::new();
builder.options.plan.set(PlanSelector::Immix);
builder.options.plan.set(PlanSelector::StickyImmix);
builder.options.threads.set(nthreads);
builder
.options
.gc_trigger
.set(mmtk::util::options::GCTriggerSelector::DynamicHeapSize(
4 * 1024 * 1024 * 1024,
16 * 1024 * 1024 * 1024,
));
VM.set(BenchVM {
vmkit: VMKit::new(&mut builder),
})

View file

@ -20,6 +20,8 @@ pub mod threading;
#[cfg(feature = "uncooperative")]
pub mod bdwgc_shim;
pub use mmtk;
pub trait VirtualMachine: Sized + 'static + Send + Sync {
type ThreadContext: threading::ThreadContext<Self>;
type BlockAdapterList: threading::BlockAdapterList<Self>;
@ -27,6 +29,8 @@ pub trait VirtualMachine: Sized + 'static + Send + Sync {
type Slot: SlotExtra;
type MemorySlice: MemorySlice<SlotType = Self::Slot>;
/*#[cfg(feature = "address_based_hashing")]
const HASH_STATE_SPEC: VMLocalHashStateSpec = VMLocalHashStateSpec::in_header(61);*/
/// 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.

View file

@ -57,6 +57,7 @@ pub mod scanning;
pub mod stack_bounds;
pub mod tlab;
pub mod traits;
pub mod spec;
impl<VM: VirtualMachine> MemoryManager<VM> {
pub extern "C-unwind" fn request_gc() -> bool {
@ -100,10 +101,7 @@ impl<VM: VirtualMachine> MemoryManager<VM> {
let object_start =
mmtk::memory_manager::alloc(thread.mutator(), size, alignment, 0, semantics);
object_start.store(HeapObjectHeader::<VM> {
metadata: AtomicBitfieldContainer::new(metadata.to_bitfield()),
marker: PhantomData,
});
object_start.store(HeapObjectHeader::<VM>::new(metadata));
let object = VMKitObject::from_address(object_start + OBJECT_REF_OFFSET);
Self::set_vo_bit(object);
Self::refill_tlab(thread);
@ -146,10 +144,7 @@ impl<VM: VirtualMachine> MemoryManager<VM> {
tlab.allocate::<VM>(size, alignment, OBJECT_REF_OFFSET as usize);
if !object_start.is_zero() {
object_start.store(HeapObjectHeader::<VM> {
metadata: AtomicBitfieldContainer::new(metadata.to_bitfield()),
marker: PhantomData,
});
object_start.store(HeapObjectHeader::<VM>::new(metadata));
let object = VMKitObject::from_address(object_start + OBJECT_REF_OFFSET);
Self::set_vo_bit(object);
return object;
@ -185,10 +180,7 @@ impl<VM: VirtualMachine> MemoryManager<VM> {
);
let object = VMKitObject::from_address(object_start + OBJECT_REF_OFFSET);
object_start.store(HeapObjectHeader::<VM> {
metadata: AtomicBitfieldContainer::new(metadata.to_bitfield()),
marker: PhantomData,
});
object_start.store(HeapObjectHeader::<VM>::new(metadata));
//Self::set_vo_bit(object);
Self::refill_tlab(thread);
@ -222,10 +214,7 @@ impl<VM: VirtualMachine> MemoryManager<VM> {
);
let object = VMKitObject::from_address(object_start + OBJECT_REF_OFFSET);
object_start.store(HeapObjectHeader::<VM> {
metadata: AtomicBitfieldContainer::new(metadata.to_bitfield()),
marker: PhantomData,
});
object_start.store(HeapObjectHeader::<VM>::new(metadata));
Self::set_vo_bit(object);
Self::refill_tlab(thread);
object
@ -252,10 +241,7 @@ impl<VM: VirtualMachine> MemoryManager<VM> {
);
let object = VMKitObject::from_address(object_start + OBJECT_REF_OFFSET);
object_start.store(HeapObjectHeader::<VM> {
metadata: AtomicBitfieldContainer::new(metadata.to_bitfield()),
marker: PhantomData,
});
object_start.store(HeapObjectHeader::<VM>::new(metadata));
Self::set_vo_bit(object);
Self::refill_tlab(thread);
object
@ -283,10 +269,7 @@ impl<VM: VirtualMachine> MemoryManager<VM> {
semantics,
);
object_start.store(HeapObjectHeader::<VM> {
metadata: AtomicBitfieldContainer::new(metadata.to_bitfield()),
marker: PhantomData,
});
object_start.store(HeapObjectHeader::<VM>::new(metadata));
let object = VMKitObject::from_address(object_start + OBJECT_REF_OFFSET);
Self::set_vo_bit(object);
Self::refill_tlab(thread);

View file

@ -14,7 +14,7 @@ use mmtk::{
MutatorContext,
};
use super::{conservative_roots::ConservativeRoots, traits::ToSlot};
use super::traits::ToSlot;
pub struct VMKitScanning<VM: VirtualMachine>(PhantomData<VM>);
@ -95,13 +95,15 @@ impl<VM: VirtualMachine> Scanning<MemoryManager<VM>> for VMKitScanning<VM> {
fn scan_roots_in_mutator_thread(
_tls: mmtk::util::VMWorkerThread,
mutator: &'static mut mmtk::Mutator<MemoryManager<VM>>,
mut factory: impl mmtk::vm::RootsWorkFactory<VM::Slot>,
factory: impl mmtk::vm::RootsWorkFactory<VM::Slot>,
) {
let tls = Thread::<VM>::from_vm_mutator_thread(mutator.get_tls());
tls.context.scan_roots(factory.clone());
#[cfg(not(feature = "full-precise"))]
{
let mut factory = factory;
use super::conservative_roots::ConservativeRoots;
let mut croots = ConservativeRoots::new(128);
let bounds = *tls.stack_bounds();
unsafe { croots.add_span(bounds.origin(), tls.stack_pointer()) };
@ -124,6 +126,7 @@ impl<VM: VirtualMachine> Scanning<MemoryManager<VM>> for VMKitScanning<VM> {
) -> bool {
let object = VMKitObject::from(object);
let metadata = object.header::<VM>().metadata();
matches!(metadata.gc_metadata().trace, TraceCallback::ScanSlots(_))
&& (!metadata.is_object() || metadata.to_slot().is_some())
}

93
vmkit/src/mm/spec.rs Normal file
View file

@ -0,0 +1,93 @@
/// Define a VM metadata spec. This is essentially bitfields for storing object metadata.
/// Using this your VM can declare side metadata or local (header) metadata with ease.
///
/// This macro is copied from mmtk-core source code.
#[macro_export]
macro_rules! define_vm_metadata_spec {
($(#[$outer:meta])*$spec_name: ident, $is_global: expr, $log_num_bits: expr, $side_min_obj_size: expr) => {
$(#[$outer])*
pub struct $spec_name($crate::mmtk::util::metadata::MetadataSpec);
impl $spec_name {
/// The number of bits (in log2) that are needed for the spec.
pub const LOG_NUM_BITS: usize = $log_num_bits;
/// Whether this spec is global or local. For side metadata, the binding needs to make sure
/// global specs are laid out after another global spec, and local specs are laid
/// out after another local spec. Otherwise, there will be an assertion failure.
pub const IS_GLOBAL: bool = $is_global;
/// Declare that the VM uses in-header metadata for this metadata type.
/// For the specification of the `bit_offset` argument, please refer to
/// the document of `[crate::util::metadata::header_metadata::HeaderMetadataSpec.bit_offset]`.
/// The binding needs to make sure that the bits used for a spec in the header do not conflict with
/// the bits of another spec (unless it is specified that some bits may be reused).
pub const fn in_header(bit_offset: isize) -> Self {
Self($crate::mmtk::util::metadata::MetadataSpec::InHeader($crate::mmtk::util::metadata::header_metadata::HeaderMetadataSpec {
bit_offset,
num_of_bits: 1 << Self::LOG_NUM_BITS,
}))
}
/// Declare that the VM uses side metadata for this metadata type,
/// and the side metadata is the first of its kind (global or local).
/// The first global or local side metadata should be declared with `side_first()`,
/// and the rest side metadata should be declared with `side_after()` after a defined
/// side metadata of the same kind (global or local). Logically, all the declarations
/// create two list of side metadata, one for global, and one for local.
pub const fn side_first() -> Self {
if Self::IS_GLOBAL {
Self($crate::mmtk::util::metadata::MetadataSpec::OnSide($crate::mmtk::util::metadata::side_metadata::SideMetadataSpec {
name: stringify!($spec_name),
is_global: Self::IS_GLOBAL,
offset: $crate::mmtk::util::metadata::side_metadata::GLOBAL_SIDE_METADATA_VM_BASE_OFFSET,
log_num_of_bits: Self::LOG_NUM_BITS,
log_bytes_in_region: $side_min_obj_size as usize,
}))
} else {
Self($crate::mmtk::util::metadata::MetadataSpec::OnSide($crate::mmtk::util::metadata::side_metadata::SideMetadataSpec {
name: stringify!($spec_name),
is_global: Self::IS_GLOBAL,
offset: $crate::mmtk::util::metadata::side_metadata::LOCAL_SIDE_METADATA_VM_BASE_OFFSET,
log_num_of_bits: Self::LOG_NUM_BITS,
log_bytes_in_region: $side_min_obj_size as usize,
}))
}
}
/// Declare that the VM uses side metadata for this metadata type,
/// and the side metadata should be laid out after the given side metadata spec.
/// The first global or local side metadata should be declared with `side_first()`,
/// and the rest side metadata should be declared with `side_after()` after a defined
/// side metadata of the same kind (global or local). Logically, all the declarations
/// create two list of side metadata, one for global, and one for local.
pub const fn side_after(spec: &$crate::mmtk::util::metadata::MetadataSpec) -> Self {
assert!(spec.is_on_side());
let side_spec = spec.extract_side_spec();
assert!(side_spec.is_global == Self::IS_GLOBAL);
Self($crate::mmtk::util::metadata::MetadataSpec::OnSide($crate::mmtk::util::metadata::side_metadata::SideMetadataSpec {
name: stringify!($spec_name),
is_global: Self::IS_GLOBAL,
offset: $crate::mmtk::util::metadata::side_metadata::SideMetadataOffset::layout_after(side_spec),
log_num_of_bits: Self::LOG_NUM_BITS,
log_bytes_in_region: $side_min_obj_size as usize,
}))
}
/// Return the inner `[crate::util::metadata::MetadataSpec]` for the metadata type.
pub const fn as_spec(&self) -> &$crate::mmtk::util::metadata::MetadataSpec {
&self.0
}
/// Return the number of bits for the metadata type.
pub const fn num_bits(&self) -> usize {
1 << $log_num_bits
}
}
impl std::ops::Deref for $spec_name {
type Target = $crate::mmtk::util::metadata::MetadataSpec;
fn deref(&self) -> &Self::Target {
self.as_spec()
}
}
};
}

View file

@ -3,7 +3,7 @@ use std::marker::PhantomData;
use crate::{mm::MemoryManager, VirtualMachine};
use header::{HashState, HASHCODE_OFFSET, OBJECT_HEADER_OFFSET, OBJECT_REF_OFFSET};
use mmtk::{
util::{alloc::fill_alignment_gap, constants::LOG_BYTES_IN_ADDRESS, ObjectReference},
util::{alloc::fill_alignment_gap, constants::LOG_BYTES_IN_ADDRESS, metadata::MetadataSpec, ObjectReference},
vm::*,
};
use object::{MoveTarget, VMKitObject};
@ -159,7 +159,7 @@ impl<VM: VirtualMachine> ObjectModel<MemoryManager<VM>> for VMKitObjectModel<VM>
}
impl<VM: VirtualMachine> VMKitObjectModel<VM> {
fn move_object(from_obj: VMKitObject, mut to: MoveTarget, num_bytes: usize) -> VMKitObject {
log::trace!(
log::debug!(
"move_object: from_obj: {}, to: {}, bytes={}",
from_obj.as_address(),
to,
@ -209,7 +209,9 @@ impl<VM: VirtualMachine> VMKitObjectModel<VM> {
// Update hash state if necessary
if hash_state == HashState::Hashed {
unsafe {
let hash_code = from_obj.as_address().as_usize() >> LOG_BYTES_IN_ADDRESS;
to_obj
.as_address()
.offset(HASHCODE_OFFSET)
@ -224,4 +226,16 @@ impl<VM: VirtualMachine> VMKitObjectModel<VM> {
to_obj
}
pub const fn last_side_metadata_spec() -> &'static MetadataSpec {
#[cfg(feature="object_pinning")]
{
Self::LOCAL_PINNING_BIT_SPEC.as_spec()
}
#[cfg(not(feature="object_pinning"))]
{
Self::LOCAL_LOS_MARK_NURSERY_SPEC.as_spec()
}
}
}

View file

@ -1,6 +1,6 @@
use std::marker::PhantomData;
use crate::VirtualMachine;
use crate::{define_vm_metadata_spec, VirtualMachine};
use easy_bitfield::*;
use super::object::ADDRESS_BASED_HASHING;
@ -13,7 +13,7 @@ pub const HASHCODE_OFFSET: isize = -(OBJECT_REF_OFFSET + size_of::<usize>() as i
pub const METADATA_BIT_LIMIT: usize = if ADDRESS_BASED_HASHING {
61
60
} else {
63
};
@ -21,6 +21,7 @@ pub const METADATA_BIT_LIMIT: usize = if ADDRESS_BASED_HASHING {
pub type MetadataField = BitField<u64, usize, 0, METADATA_BIT_LIMIT, false>;
pub type HashStateField = BitField<u64, HashState, { MetadataField::NEXT_BIT }, 2, false>;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HashState {
Unhashed,
@ -98,6 +99,4 @@ impl<VM: VirtualMachine> HeapObjectHeader<VM> {
self.metadata.update_synchronized::<MetadataField>(metadata.to_bitfield() as _);
}
}