From 761c99a6e8ee1a7918d704138c0f35bfc72cd73c Mon Sep 17 00:00:00 2001 From: Kunshan Wang Date: Mon, 2 Sep 2024 14:46:57 +0800 Subject: [PATCH] Use JavaHeader address as ObjectReference This will guarantee that the MMTk-level ObjectReference is always inside an object. --- mmtk/src/lib.rs | 8 ++++---- mmtk/src/object_model.rs | 28 ++++++++++++++++++++-------- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/mmtk/src/lib.rs b/mmtk/src/lib.rs index 5530c30..2815bfd 100644 --- a/mmtk/src/lib.rs +++ b/mmtk/src/lib.rs @@ -48,10 +48,10 @@ pub struct JikesRVM; /// The type of slots in JikesRVM. /// -/// Each slot holds a `JikesObj` value, which is equal to the JikesRVM-level `ObjectReference`. The -/// Java parts of the binding may insert `Address` values into native arrays of `JikesRVMSlot` -/// passed from Rust code, so this type has `repr(transparent)` to make sure it has the same layout -/// as `Address` +/// Each slot holds a `JikesObj` value. Conversion between `JikesObj` and the MMTk-level +/// `ObjectRefernece` happens when loading from or storing to a slot. The Java parts of the binding may +/// insert `Address` values into native arrays of `JikesRVMSlot` passed from Rust code, so this type +/// has `repr(transparent)` to make sure it has the same layout as `Address` #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[repr(transparent)] pub struct JikesRVMSlot(Address); diff --git a/mmtk/src/object_model.rs b/mmtk/src/object_model.rs index 03af439..442afde 100644 --- a/mmtk/src/object_model.rs +++ b/mmtk/src/object_model.rs @@ -2,6 +2,7 @@ use libc::*; use std::convert::{TryFrom, TryInto}; use std::sync::atomic::{AtomicUsize, Ordering}; +use crate::java_header_constants::JAVA_HEADER_OFFSET; use crate::unboxed_size_constants::*; use crate::vm_metadata; use mmtk::util::alloc::fill_alignment_gap; @@ -24,17 +25,18 @@ use JikesRVM; /// This type represents a JikesRVM-level `ObjectReference`. /// -/// Currently, it has the same value as the MMTk-level `mmtk::util::address::ObjectReference`, but -/// can be null (has the value of 0). Therefore, an MMTk-level `ObjectReference` can always safely -/// converted to a `JikesObj`, but safely converting a `JikesObj` to an MMTk-level `ObjectReference` -/// will involve a null check. +/// A `JikesObj` has the same value as the JikesRVM-level `ObjectReference`, while an MMTk-level +/// `ObjectReference` points at the JavaHeader of an object. Converting between the two types +/// involves adding/subtracting an offset. Because JikesRVM-level `ObjectReference` (and therefore +/// `JikesObj`) can be null, safely converting a `JikesObj` to an MMTk-level `ObjectReference` will +/// involve a null check. #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(transparent)] pub struct JikesObj(Address); impl From for JikesObj { fn from(value: ObjectReference) -> Self { - Self(value.to_raw_address()) + Self(value.to_raw_address().offset(-JAVA_HEADER_OFFSET)) } } @@ -42,7 +44,14 @@ impl TryFrom for ObjectReference { type Error = NullRefError; fn try_from(value: JikesObj) -> Result { - ObjectReference::from_raw_address(value.0).ok_or(NullRefError) + if value.is_null() { + Err(NullRefError) + } else { + let objref_addr = value.0.offset(JAVA_HEADER_OFFSET); + debug_assert!(!objref_addr.is_zero()); + let result = unsafe { ObjectReference::from_raw_address_unchecked(objref_addr) }; + Ok(result) + } } } @@ -449,9 +458,12 @@ impl ObjectModel for VMObjectModel { JikesObj::from(object).to_address() } - const OBJECT_REF_OFFSET_LOWER_BOUND: isize = OBJECT_REF_OFFSET; + /// This is the offset from the start to the JavaHeader when the object does not have the hash + /// code in the front. Its value zero for now. + const OBJECT_REF_OFFSET_LOWER_BOUND: isize = OBJECT_REF_OFFSET + JAVA_HEADER_OFFSET; - const IN_OBJECT_ADDRESS_OFFSET: isize = TIB_OFFSET; + /// MMTk-level `ObjectReference` points at the JavaHeader which is always inside the object. + const IN_OBJECT_ADDRESS_OFFSET: isize = 0; fn dump_object(_object: ObjectReference) { unimplemented!()