@@ -588,40 +588,56 @@ pub fn is_live_object<VM: VMBinding>(object: ObjectReference) -> bool {
588588/// Concretely:
589589/// 1. Return true if `ObjectReference::from_raw_address(addr)` is a valid object reference to an
590590/// object in any space in MMTk.
591- /// 2. Also return true if there exists an `objref: ObjectReference` such that
592- /// - `objref` is a valid object reference to an object in any space in MMTk, and
593- /// - `lo <= objref.to_address() < hi`, where
594- /// - `lo = addr.align_down(VO_BIT_REGION_SIZE)` and
595- /// - `hi = lo + VO_BIT_REGION_SIZE` and
596- /// - `VO_BIT_REGION_SIZE` is [`crate::util::is_mmtk_object::VO_BIT_REGION_SIZE`].
597- /// It is the byte granularity of the valid object (VO) bit.
598- /// 3. Return false otherwise. This function never panics.
599- ///
600- /// This function uses the "valid object (VO) bits" side metadata, i.e. a bitmap.
601- /// For space efficiency, each bit of the bitmap governs a small region of memory.
602- /// The size of a region is currently defined as the [minimum object size](crate::util::constants::MIN_OBJECT_SIZE),
603- /// which is currently defined as the [word size](crate::util::constants::BYTES_IN_WORD),
604- /// which is 4 bytes on 32-bit systems or 8 bytes on 64-bit systems.
605- /// The alignment of a region is also the region size.
606- /// If a VO bit is `1`, the bitmap cannot tell which address within the 4-byte or 8-byte region
607- /// is the valid object reference.
608- /// Therefore, if this method returns true, the binding can compute the object reference by
609- /// aligning the address to [`crate::util::ObjectReference::ALIGNMENT`].
591+ /// 2. Return false otherwise.
610592///
611593/// This function is useful for conservative root scanning. The VM can iterate through all words in
612594/// a stack, filter out zeros, misaligned words, obviously out-of-range words (such as addresses
613595/// greater than `0x0000_7fff_ffff_ffff` on Linux on x86_64), and use this function to deside if the
614596/// word is really a reference.
615597///
598+ /// This function does not handle internal pointers. If a binding may have internal pointers on
599+ /// the stack, and requires identifying the base reference for an internal pointer, they should use
600+ /// [`find_object_from_internal_pointer`] instead.
601+ ///
616602/// Note: This function has special behaviors if the VM space (enabled by the `vm_space` feature)
617603/// is present. See `crate::plan::global::BasePlan::vm_space`.
618604///
619605/// Argument:
620606/// * `addr`: An arbitrary address.
621607#[ cfg( feature = "is_mmtk_object" ) ]
622- pub fn is_mmtk_object ( addr : Address ) -> bool {
623- use crate :: mmtk:: SFT_MAP ;
624- SFT_MAP . get_checked ( addr) . is_mmtk_object ( addr)
608+ pub fn is_mmtk_object ( addr : Address ) -> Option < ObjectReference > {
609+ crate :: util:: is_mmtk_object:: check_object_reference ( addr)
610+ }
611+
612+ /// Find if there is an object with VO bit set for the given address range.
613+ /// This should be used instead of [`crate::memory_manager::is_mmtk_object`] for conservative stack scanning if
614+ /// the binding may have internal pointers on the stack.
615+ ///
616+ /// Note that, we only consider pointers that point to addresses that are equal or greater than the in-object addresss
617+ /// (i.e. [`crate::util::ObjectReference::to_address()`] which is the same as `object_ref.to_raw_address() + ObjectModel::IN_OBJECT_ADDRESS_OFFSET`),
618+ /// and within the allocation as 'internal pointers'. To be precise, for each object ref `obj_ref`, internal pointers are in the range
619+ /// `[obj_ref + ObjectModel::IN_OBJECT_ADDRESS_OFFSET, ObjectModel::ref_to_object_start(obj_ref) + ObjectModel::get_current_size(obj_ref))`.
620+ /// If a binding defines internal pointers differently, calling this method is undefined behavior.
621+ /// If this is the case for you, please submit an issue or engage us on Zulip to discuss more.
622+ ///
623+ /// Note that, in the similar situation as [`crate::memory_manager::is_mmtk_object`], the binding should filter
624+ /// out obvious non-pointers (e.g. alignment check, bound check, etc) before calling this function to avoid unnecessary
625+ /// cost. This method is not cheap.
626+ ///
627+ /// To minimize the cost, the user should also use a small `max_search_bytes`.
628+ ///
629+ /// Note: This function has special behaviors if the VM space (enabled by the `vm_space` feature)
630+ /// is present. See `crate::plan::global::BasePlan::vm_space`.
631+ ///
632+ /// Argument:
633+ /// * `internal_ptr`: The address to start searching. We search backwards from this address (including this address) to find the base reference.
634+ /// * `max_search_bytes`: The maximum number of bytes we may search for an object with VO bit set. `internal_ptr - max_search_bytes` is not included.
635+ #[ cfg( feature = "is_mmtk_object" ) ]
636+ pub fn find_object_from_internal_pointer < VM : VMBinding > (
637+ internal_ptr : Address ,
638+ max_search_bytes : usize ,
639+ ) -> Option < ObjectReference > {
640+ crate :: util:: is_mmtk_object:: check_internal_reference ( internal_ptr, max_search_bytes)
625641}
626642
627643/// Return true if the `object` lies in a region of memory where
0 commit comments