#[repr(transparent)]
pub struct ObjectReference(NonZeroUsize);
Expand description

ObjectReference represents address for an object. Compared with Address, operations allowed on ObjectReference are very limited. No address arithmetics are allowed for ObjectReference. The idea is from the paper Demystifying Magic: High-level Low-level Programming (VEE09) and JikesRVM.

In MMTk, ObjectReference holds a non-zero address, i.e. its raw address. It must satisfy the following requirements.

  • It uniquely references an MMTk object.
  • The address must be within the address range of the object it refers to.
  • The address must be word-aligned.
  • It must be efficient to access object metadata from an ObjectReference.

Each ObjectReference uniquely identifies exactly one MMTk object. There is no “null reference” (see below for details).

Conversely, each object has a unique (raw) address used for ObjectReference. That address is nominated by the VM binding right after an object is allocated in the MMTk heap (i.e. the argument of crate::memory_manager::post_alloc). The same address is used by all ObjectReference instances that refer to that object until the object is moved, at which time the VM binding shall choose another address to use as the ObjectReference of the new copy (in crate::vm::ObjectModel::copy or crate::vm::ObjectModel::get_reference_when_copied_to) until the object is moved again.

In addition to the raw address, there are also two addresses related to each object allocated in MMTk heap, namely starting address and header address. See the crate::vm::ObjectModel trait for their precise definition.

The VM binding may, in theory, pick any aligned address within the object, and it doesn’t have to be the starting address. However, during tracing, MMTk will need to access object metadata from a ObjectReference. Particularly, it needs to identify reference fields, and query information about the object, such as object size. Such information is usually accessed from object headers. The choice of ObjectReference must make such accesses efficient.

Because the raw address is within the object, MMTk will also use the raw address to identify the space or region (chunk, block, line, etc.) that contains the object, and to access side metadata and the SFTMap. If a VM binding needs to access side metadata directly (particularly, setting the “valid-object (VO) bit” in allocation fast paths), it shall use the raw address to compute the byte and bit address of the metadata bits.

§Notes

§About VMs own concepts of “object references”

A runtime may define its own concept of “object references” differently from MMTk’s ObjectReference type. It may define its object reference as

  • the starting address of an object,
  • an address inside an object,
  • an address at a certain offset outside an object,
  • a handle that points to an indirection table entry where a pointer to the object is held, or
  • anything else that refers to an object.

Regardless, when passing an ObjectReference value to MMTk through the API, MMTk expectes its value to satisfy MMTk’s definition. This means MMTk’s ObjectReference may not be the value held in an object field. Some VM bindings may need to do conversions when passing object references to MMTk. For example, adding an offset to the VM-level object reference so that the resulting address is within the object. When using handles, the VM binding may use the pointer stored in the entry of the indirection table instead of the pointer to the entry itself as MMTk-level ObjectReference.

§About null references

An ObjectReference always refers to an object. Some VMs have special values (such as null in Java) that do not refer to any object. Those values cannot be represented by ObjectReference. When scanning roots and object fields, the VM binding should ignore slots that do not hold a reference to an object. Specifically, crate::vm::slot::Slot::load returns Option<ObjectReference>. It can return None so that MMTk skips that slot.

Option<ObjectReference> should be used for the cases where a non-null object reference may or may not exist, That includes several API functions, including crate::vm::slot::Slot::load. ObjectReference is backed by NonZeroUsize which cannot be zero, and it has the #[repr(transparent)] attribute. Thanks to null pointer optimization (NPO), Option<ObjectReference> has the same size as NonZeroUsize and usize.

For the convenience of passing Option<ObjectReference> to and from native (C/C++) programs, mmtk-core provides crate::util::api_util::NullableObjectReference.

§About the VMSpace

The VMSpace is managed by the VM binding. The VM binding declare ranges of memory as part of the VMSpace, but MMTk never allocates into it. The VM binding allocates objects into the VMSpace (usually by mapping boot-images), and refers to objects in the VMSpace using ObjectReferences whose raw addresses point inside those objects (and must be word-aligned, too). MMTk will access metadata using methods of ObjectModel like other objects. MMTk also has side metadata available for objects in the VMSpace.

§About ObjectReference pointing outside MMTk spaces

If a VM binding implements crate::vm::ActivePlan::vm_trace_object, ObjectReference is allowed to point to locations outside any MMTk spaces. When tracing objects, such ObjectReference values will be processed by ActivePlan::vm_trace_object so that the VM binding can trace its own allocated objects during GC. However, this is an experimental feature, and may not interact well with other parts of MMTk. Notably, MMTk will not allocate side metadata for such ObjectReference, and attempts to access side metadata with a non-MMTk ObjectReference will result in crash. Use with caution.

Tuple Fields§

§0: NonZeroUsize

Implementations§

source§

impl ObjectReference

source

pub const ALIGNMENT: usize = 8usize

The required minimal alignment for object reference. If the object reference’s raw address is not aligned to this value, you will see an assertion failure in the debug build when constructing an object reference instance.

source

pub fn to_raw_address(self) -> Address

Cast the object reference to its raw address.

source

pub fn from_raw_address(addr: Address) -> Option<ObjectReference>

Cast a raw address to an object reference.

If addr is 0, the result is None.

source

pub unsafe fn from_raw_address_unchecked(addr: Address) -> ObjectReference

Like from_raw_address, but assume addr is not zero. This can be used to elide a check against zero for performance-critical code.

§Safety

This method assumes addr is not zero. It should only be used in cases where we know at compile time that the input cannot be zero. For example, if we compute the address by adding a positive offset to a non-zero address, we know the result must not be zero.

source

pub fn to_header<VM: VMBinding>(self) -> Address

Get the header base address from an object reference. This method is used by MMTk to get a base address for the object header, and access the object header. This method is syntactic sugar for crate::vm::ObjectModel::ref_to_header. See the comments on crate::vm::ObjectModel::ref_to_header.

source

pub fn to_object_start<VM: VMBinding>(self) -> Address

Get the start of the allocation address for the object. This method is used by MMTk to get the start of the allocation address originally returned from crate::memory_manager::alloc for the object. This method is syntactic sugar for crate::vm::ObjectModel::ref_to_object_start. See comments on crate::vm::ObjectModel::ref_to_object_start.

source

pub fn is_reachable(self) -> bool

Is the object reachable, determined by the policy? Note: Objects in ImmortalSpace may have is_live = true but are actually unreachable.

source

pub fn is_live(self) -> bool

Is the object live, determined by the policy?

source

pub fn is_movable(self) -> bool

Can the object be moved?

source

pub fn get_forwarded_object(self) -> Option<Self>

Get forwarding pointer if the object is forwarded.

source

pub fn is_in_any_space(self) -> bool

Is the object in any MMTk spaces?

source

pub fn is_sane(self) -> bool

Is the object sane?

Trait Implementations§

source§

impl Clone for ObjectReference

source§

fn clone(&self) -> ObjectReference

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for ObjectReference

allows Debug format the Address (as upper-case hex value with 0x prefix)

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Display for ObjectReference

allows Display format the Address (as upper-case hex value with 0x prefix)

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Finalizable for ObjectReference

This provides an implementation of Finalizable for ObjectReference. Most bindings should be able to use ObjectReference as ReferenceGlue::FinalizableType.

source§

fn get_reference(&self) -> ObjectReference

Load the object reference.
source§

fn set_reference(&mut self, object: ObjectReference)

Store the object reference.
source§

fn keep_alive<E: ProcessEdgesWork>(&mut self, trace: &mut E)

Keep the heap references in the finalizable object alive. For example, the reference itself needs to be traced. However, if the finalizable object includes other heap references, the implementation should trace them as well. Note that trace_object() may move objects so we need to write the new reference in case that it is moved.
source§

impl Hash for ObjectReference

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl LowerHex for ObjectReference

allows print Address as lower-case hex value

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter.
source§

impl Ord for ObjectReference

source§

fn cmp(&self, other: &ObjectReference) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · source§

fn min(self, other: Self) -> Self
where Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 · source§

fn clamp(self, min: Self, max: Self) -> Self
where Self: Sized + PartialOrd,

Restrict a value to a certain interval. Read more
source§

impl PartialEq for ObjectReference

source§

fn eq(&self, other: &ObjectReference) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl PartialOrd for ObjectReference

source§

fn partial_cmp(&self, other: &ObjectReference) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · source§

fn lt(&self, other: &Rhs) -> bool

This method tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · source§

fn le(&self, other: &Rhs) -> bool

This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 · source§

fn gt(&self, other: &Rhs) -> bool

This method tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · source§

fn ge(&self, other: &Rhs) -> bool

This method tests greater than or equal to (for self and other) and is used by the >= operator. Read more
source§

impl UpperHex for ObjectReference

allows print Address as upper-case hex value

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter.
source§

impl Copy for ObjectReference

source§

impl Eq for ObjectReference

source§

impl NoUninit for ObjectReference

source§

impl StructuralPartialEq for ObjectReference

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> Downcast for T
where T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Send + Sync>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T> ToString for T
where T: Display + ?Sized,

source§

default fn to_string(&self) -> String

Converts the given value to a String. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.