fix hashstate
This commit is contained in:
parent
6e294ecaf9
commit
cd0e1344e4
8 changed files with 132 additions and 43 deletions
|
@ -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.
|
||||
|
|
|
@ -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),
|
||||
})
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
93
vmkit/src/mm/spec.rs
Normal 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()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 _);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue