use atomic::Ordering;
use self::specs::*;
use crate::util::copy::*;
use crate::util::metadata::header_metadata::HeaderMetadataSpec;
use crate::util::metadata::MetadataValue;
use crate::util::{Address, ObjectReference};
use crate::vm::VMBinding;
pub trait ObjectModel<VM: VMBinding> {
const GLOBAL_LOG_BIT_SPEC: VMGlobalLogBitSpec;
const LOCAL_FORWARDING_POINTER_SPEC: VMLocalForwardingPointerSpec;
const LOCAL_FORWARDING_BITS_SPEC: VMLocalForwardingBitsSpec;
const LOCAL_MARK_BIT_SPEC: VMLocalMarkBitSpec;
#[cfg(feature = "object_pinning")]
const LOCAL_PINNING_BIT_SPEC: VMLocalPinningBitSpec;
const LOCAL_LOS_MARK_NURSERY_SPEC: VMLocalLOSMarkNurserySpec;
#[cfg(feature = "vo_bit")]
const NEED_VO_BITS_DURING_TRACING: bool = false;
unsafe fn load_metadata<T: MetadataValue>(
metadata_spec: &HeaderMetadataSpec,
object: ObjectReference,
mask: Option<T>,
) -> T {
metadata_spec.load::<T>(object.to_header::<VM>(), mask)
}
fn load_metadata_atomic<T: MetadataValue>(
metadata_spec: &HeaderMetadataSpec,
object: ObjectReference,
mask: Option<T>,
ordering: Ordering,
) -> T {
metadata_spec.load_atomic::<T>(object.to_header::<VM>(), mask, ordering)
}
unsafe fn store_metadata<T: MetadataValue>(
metadata_spec: &HeaderMetadataSpec,
object: ObjectReference,
val: T,
mask: Option<T>,
) {
metadata_spec.store::<T>(object.to_header::<VM>(), val, mask)
}
fn store_metadata_atomic<T: MetadataValue>(
metadata_spec: &HeaderMetadataSpec,
object: ObjectReference,
val: T,
mask: Option<T>,
ordering: Ordering,
) {
metadata_spec.store_atomic::<T>(object.to_header::<VM>(), val, mask, ordering)
}
fn compare_exchange_metadata<T: MetadataValue>(
metadata_spec: &HeaderMetadataSpec,
object: ObjectReference,
old_val: T,
new_val: T,
mask: Option<T>,
success_order: Ordering,
failure_order: Ordering,
) -> std::result::Result<T, T> {
metadata_spec.compare_exchange::<T>(
object.to_header::<VM>(),
old_val,
new_val,
mask,
success_order,
failure_order,
)
}
fn fetch_add_metadata<T: MetadataValue>(
metadata_spec: &HeaderMetadataSpec,
object: ObjectReference,
val: T,
order: Ordering,
) -> T {
metadata_spec.fetch_add::<T>(object.to_header::<VM>(), val, order)
}
fn fetch_sub_metadata<T: MetadataValue>(
metadata_spec: &HeaderMetadataSpec,
object: ObjectReference,
val: T,
order: Ordering,
) -> T {
metadata_spec.fetch_sub::<T>(object.to_header::<VM>(), val, order)
}
fn fetch_and_metadata<T: MetadataValue>(
metadata_spec: &HeaderMetadataSpec,
object: ObjectReference,
val: T,
order: Ordering,
) -> T {
metadata_spec.fetch_and::<T>(object.to_header::<VM>(), val, order)
}
fn fetch_or_metadata<T: MetadataValue>(
metadata_spec: &HeaderMetadataSpec,
object: ObjectReference,
val: T,
order: Ordering,
) -> T {
metadata_spec.fetch_or::<T>(object.to_header::<VM>(), val, order)
}
fn fetch_update_metadata<T: MetadataValue, F: FnMut(T) -> Option<T> + Copy>(
metadata_spec: &HeaderMetadataSpec,
object: ObjectReference,
set_order: Ordering,
fetch_order: Ordering,
f: F,
) -> std::result::Result<T, T> {
metadata_spec.fetch_update::<T, F>(object.to_header::<VM>(), set_order, fetch_order, f)
}
fn copy(
from: ObjectReference,
semantics: CopySemantics,
copy_context: &mut GCWorkerCopyContext<VM>,
) -> ObjectReference;
fn copy_to(from: ObjectReference, to: ObjectReference, region: Address) -> Address;
fn get_reference_when_copied_to(from: ObjectReference, to: Address) -> ObjectReference;
fn get_current_size(object: ObjectReference) -> usize;
fn get_size_when_copied(object: ObjectReference) -> usize;
fn get_align_when_copied(object: ObjectReference) -> usize;
fn get_align_offset_when_copied(object: ObjectReference) -> usize;
fn get_type_descriptor(reference: ObjectReference) -> &'static [i8];
const VM_WORST_CASE_COPY_EXPANSION: f64 = 1.5;
const UNIFIED_OBJECT_REFERENCE_ADDRESS: bool = false;
const OBJECT_REF_OFFSET_LOWER_BOUND: isize;
fn ref_to_object_start(object: ObjectReference) -> Address;
fn ref_to_header(object: ObjectReference) -> Address;
fn dump_object(object: ObjectReference);
fn is_object_sane(_object: ObjectReference) -> bool {
true
}
}
pub mod specs {
use crate::util::constants::LOG_BITS_IN_WORD;
use crate::util::constants::LOG_BYTES_IN_PAGE;
use crate::util::constants::LOG_MIN_OBJECT_SIZE;
use crate::util::metadata::side_metadata::*;
use crate::util::metadata::{
header_metadata::HeaderMetadataSpec,
side_metadata::{SideMetadataOffset, SideMetadataSpec},
MetadataSpec,
};
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(MetadataSpec);
impl $spec_name {
pub const LOG_NUM_BITS: usize = $log_num_bits;
pub const IS_GLOBAL: bool = $is_global;
pub const fn in_header(bit_offset: isize) -> Self {
Self(MetadataSpec::InHeader(HeaderMetadataSpec {
bit_offset,
num_of_bits: 1 << Self::LOG_NUM_BITS,
}))
}
pub const fn side_first() -> Self {
if Self::IS_GLOBAL {
Self(MetadataSpec::OnSide(SideMetadataSpec {
name: stringify!($spec_name),
is_global: Self::IS_GLOBAL,
offset: 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(MetadataSpec::OnSide(SideMetadataSpec {
name: stringify!($spec_name),
is_global: Self::IS_GLOBAL,
offset: LOCAL_SIDE_METADATA_VM_BASE_OFFSET,
log_num_of_bits: Self::LOG_NUM_BITS,
log_bytes_in_region: $side_min_obj_size as usize,
}))
}
}
pub const fn side_after(spec: &MetadataSpec) -> Self {
assert!(spec.is_on_side());
let side_spec = spec.extract_side_spec();
assert!(side_spec.is_global == Self::IS_GLOBAL);
Self(MetadataSpec::OnSide(SideMetadataSpec {
name: stringify!($spec_name),
is_global: Self::IS_GLOBAL,
offset: SideMetadataOffset::layout_after(side_spec),
log_num_of_bits: Self::LOG_NUM_BITS,
log_bytes_in_region: $side_min_obj_size as usize,
}))
}
pub const fn as_spec(&self) -> &MetadataSpec {
&self.0
}
pub const fn num_bits(&self) -> usize {
1 << $log_num_bits
}
}
impl std::ops::Deref for $spec_name {
type Target = MetadataSpec;
fn deref(&self) -> &Self::Target {
self.as_spec()
}
}
};
}
define_vm_metadata_spec!(
VMGlobalLogBitSpec,
true,
0,
LOG_MIN_OBJECT_SIZE
);
define_vm_metadata_spec!(
VMLocalForwardingPointerSpec,
false,
LOG_BITS_IN_WORD,
LOG_MIN_OBJECT_SIZE
);
define_vm_metadata_spec!(
VMLocalForwardingBitsSpec,
false,
1,
LOG_MIN_OBJECT_SIZE
);
define_vm_metadata_spec!(
VMLocalMarkBitSpec,
false,
0,
LOG_MIN_OBJECT_SIZE
);
define_vm_metadata_spec!(
VMLocalPinningBitSpec,
false,
0,
LOG_MIN_OBJECT_SIZE
);
define_vm_metadata_spec!(
VMLocalLOSMarkNurserySpec,
false,
1,
LOG_BYTES_IN_PAGE
);
}