@@ -11,44 +11,100 @@ use atomic::Atomic;
1111use crate :: util:: constants:: { BYTES_IN_ADDRESS , LOG_BYTES_IN_ADDRESS } ;
1212use crate :: util:: { Address , ObjectReference } ;
1313
14- /// A `Slot` represents a slot in an object (a.k.a. a field), on the stack (i.e. a local variable)
15- /// or any other places (such as global variables). A slot may hold an object reference. We can
16- /// load the object reference from it, and we can update the object reference in it after the GC
17- /// moves the object.
14+ /// `Slot` is an abstraction for MMTk to load and update object references in memory.
1815///
19- /// For some VMs, a slot may sometimes not hold an object reference. For example, it can hold a
20- /// special `NULL` pointer which does not point to any object, or it can hold a tagged
21- /// non-reference value, such as small integers and special values such as `true`, `false`, `null`
22- /// (a.k.a. "none", "nil", etc. for other VMs), `undefined`, etc.
16+ /// # Slots and the `Slot` trait
2317///
24- /// This intends to abstract out the differences of reference field representation among different
25- /// VMs. If the VM represent a reference field as a word that holds the pointer to the object, it
26- /// can use the default `SimpleSlot` we provide. In some cases, the VM need to implement its own
27- /// `Slot` instances.
18+ /// In a VM, a slot can contain an object reference or a non-reference value. It can be in an
19+ /// object (a.k.a. a field), on the stack (i.e. a local variable) or in any other places (such as
20+ /// global variables). It may have different representations in different VMs. Some VMs put a
21+ /// direct pointer to an object into a slot, while others may use compressed pointers, tagged
22+ /// pointers, offsetted pointers, etc. Some VMs (such as JVM) have null references, and others
23+ /// (such as CRuby and JavaScript engines) can also use tagged bits to represent non-reference
24+ /// values such as small integers, `true`, `false`, `null` (a.k.a. "none", "nil", etc.),
25+ /// `undefined`, etc.
26+ ///
27+ /// In MMTk, the `Slot` trait is intended to abstract out such different representations of
28+ /// reference fields (compressed, tagged, offsetted, etc.) among different VMs. From MMTk's point
29+ /// of view, **MMTk only cares about the object reference held inside the slot, but not
30+ /// non-reference values**, such as `null`, `true`, etc. When the slot is holding an object
31+ /// reference, we can load the object reference from it, and we can update the object reference in
32+ /// it after the GC moves the object.
33+ ///
34+ /// # The `Slot` trait has pointer semantics
35+ ///
36+ /// A `Slot` value *points to* a slot, and is not the slot itself. In fact, the simplest
37+ /// implementation of the `Slot` trait ([`SimpleSlot`], see below) can simply contain the address of
38+ /// the slot.
39+ ///
40+ /// A `Slot` can be [copied](std::marker::Copy), and the copied `Slot` instance points to the same
41+ /// slot.
42+ ///
43+ /// # How to implement `Slot`?
44+ ///
45+ /// If a reference field of a VM is word-sized and holds the raw pointer to an object, and uses the
46+ /// 0 word as the null pointer, it can use the default [`SimpleSlot`] we provide. It simply
47+ /// contains a pointer to a memory location that holds an address.
48+ ///
49+ /// ```rust
50+ /// pub struct SimpleSlot {
51+ /// slot_addr: *mut Atomic<Address>,
52+ /// }
53+ /// ```
54+ ///
55+ /// In other cases, the VM need to implement its own `Slot` instances.
2856///
2957/// For example:
30- /// - The VM uses compressed pointer (Compressed OOP in OpenJDK's terminology), where the heap
31- /// size is limited, and a 64-bit pointer is stored in a 32-bit slot.
32- /// - The VM uses tagged pointer, where some bits of a word are used as metadata while the rest
33- /// are used as pointer.
34- /// - A field holds a pointer to the middle of an object (an object field, or an array element,
35- /// or some arbitrary offset) for some reasons.
58+ /// - The VM uses **compressed pointers** (Compressed OOPs in OpenJDK's terminology), where the
59+ /// heap size is limited, and a 64-bit pointer is stored in a 32-bit slot.
60+ /// - The VM uses **tagged pointers**, where some bits of a word are used as metadata while the
61+ /// rest are used as pointer.
62+ /// - The VM uses **offsetted pointers**, i.e. the value of the field is an address at an offset
63+ /// from the [`ObjectReference`] of the target object. Such offsetted pointers are usually used
64+ /// to represent **interior pointers**, i.e. pointers to an object field, an array element, etc.
65+ ///
66+ /// If needed, the implementation of `Slot` can contain not only the pointer, but also additional
67+ /// information. The `OffsetSlot` example below also contains an offset which can be used when
68+ /// decoding the pointer. See `src/vm/tests/mock_tests/mock_test_slots.rs` for more concrete
69+ /// examples, such as `CompressedOopSlot` and `TaggedSlot`.
3670///
37- /// When loading, `Slot::load` shall decode its internal representation to a "regular"
38- /// `ObjectReference`. The implementation can do this with any appropriate operations, usually
39- /// shifting and masking bits or subtracting offset from the address. By doing this conversion,
40- /// MMTk can implement GC algorithms in a VM-neutral way, knowing only `ObjectReference`.
71+ /// ```rust
72+ /// pub struct OffsetSlot {
73+ /// slot_addr: *mut Atomic<Address>,
74+ /// offset: usize,
75+ /// }
76+ /// ```
77+ ///
78+ /// When loading, `Slot::load` shall load the value from the slot and decode the value into a
79+ /// regular `ObjectReference` (note that MMTk has specific requirements for `ObjectReference`, such
80+ /// as being aligned, pointing inside an object, and cannot be null. Please read the doc comments
81+ /// of [`ObjectReference`] for details). The decoding is VM-specific, but usually involves removing
82+ /// tag bits and/or adding an offset to the word, and (in the case of compressed pointers) extending
83+ /// the word size. By doing this conversion, MMTk can implement GC algorithms in a VM-neutral way,
84+ /// knowing only `ObjectReference`.
4185///
4286/// When GC moves object, `Slot::store` shall convert the updated `ObjectReference` back to the
4387/// slot-specific representation. Compressed pointers remain compressed; tagged pointers preserve
4488/// their tag bits; and offsetted pointers keep their offsets.
4589///
90+ /// # Performance notes
91+ ///
4692/// The methods of this trait are called on hot paths. Please ensure they have high performance.
47- /// Use inlining when appropriate.
4893///
49- /// Note: this trait only concerns the representation (i.e. the shape) of the slot, not its
50- /// semantics, such as whether it holds strong or weak references. If a VM holds a weak reference
51- /// in a word as a pointer, it can also use `SimpleSlot` for weak reference fields.
94+ /// The size of the data structure of the `Slot` implementation may affect the performance as well.
95+ /// During GC, MMTk enqueues `Slot` instances, and its size affects the overhead of copying. If
96+ /// your `Slot` implementation has multiple fields or uses `enum` for multiple kinds of slots, it
97+ /// may have extra cost when copying or decoding. You should measure it. If the cost is too much,
98+ /// you can implement `Slot` with a tagged word. For example, the [mmtk-openjdk] binding uses the
99+ /// low order bit to encode whether the slot is compressed or not.
100+ ///
101+ /// [mmtk-openjdk]: https://github.com/mmtk/mmtk-openjdk/blob/master/mmtk/src/slots.rs
102+ ///
103+ /// # About weak references
104+ ///
105+ /// This trait only concerns the representation (i.e. the shape) of the slot, not its semantics,
106+ /// such as whether it holds strong or weak references. Therefore, one `Slot` implementation can be
107+ /// used for both slots that hold strong references and slots that hold weak references.
52108pub trait Slot : Copy + Send + Debug + PartialEq + Eq + Hash {
53109 /// Load object reference from the slot.
54110 ///
0 commit comments