mmtk/util/
api_util.rs

1//! This module contain helpers for the convenience of exposing the MMTk API to native (usually
2//! C/C++) programs.
3
4use super::{Address, ObjectReference};
5
6/// An `Option<ObjectReference>` encoded as a `usize` (which is guaranteed to have the size of a
7/// native pointer).  It guarantees that `None` is encoded as 0, and `Some(objref)` is encoded as
8/// the underlying `usize` value of the `ObjectReference` itself.
9///
10/// Note: The Rust ABI currently doesn't guarantee the encoding of `None` even if the `T` in
11/// `Option<T>` is eligible for null pointer optimization.  Transmuting a `None` value of
12/// `Option<ObjectReference>` to `usize` still has undefined behavior.
13/// See: <https://doc.rust-lang.org/std/option/index.html#representation>
14///
15/// It is intended for passing an `Option<ObjectReference>` values to and from native programs
16/// (usually C or C++) that have null pointers.
17#[repr(transparent)]
18#[derive(Clone, Copy)]
19pub struct NullableObjectReference(usize);
20
21impl From<NullableObjectReference> for Option<ObjectReference> {
22    fn from(value: NullableObjectReference) -> Self {
23        ObjectReference::from_raw_address(unsafe { Address::from_usize(value.0) })
24    }
25}
26
27impl From<Option<ObjectReference>> for NullableObjectReference {
28    fn from(value: Option<ObjectReference>) -> Self {
29        let encoded = value
30            .map(|obj| obj.to_raw_address().as_usize())
31            .unwrap_or(0);
32        Self(encoded)
33    }
34}
35
36impl std::fmt::Display for NullableObjectReference {
37    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38        write!(f, "{:#x}", self.0)
39    }
40}
41
42impl std::fmt::Debug for NullableObjectReference {
43    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
44        std::fmt::Display::fmt(self, f)
45    }
46}