Closed wks closed 3 months ago
This is my first attempt to create a heap traversal API. The implementation is probably right, but we may need to refactor our current mechanism for visiting metadata in bulk (including reading, zeroing, setting, copying, as well as finding the last non-zero value, and finding all non-zero values in a range for heap traversal). The main problem is that iterate_meta_bits
has two call-back closures, and they can't share mutable borrows well. We have already seen its consequence because find_prev_non_zero_value_fast
needs to use a Cell
to store the return value. Heap traversal will need to use a Cell
or RefCell
for similar reason, and that won't perform well.
And things can be further simplified if we unify ObjectReference
and the "in-object address" (see https://github.com/mmtk/mmtk-core/issues/1170). Then the linear scanner will no longer depend on the <VM: VMBinding>
type (for using ObjectReference::from_address<VM>
).
... The main problem is that
iterate_meta_bits
has two call-back closures, and they can't share mutable borrows well. We have already seen its consequence becausefind_prev_non_zero_value_fast
needs to use aCell
to store the return value. Heap traversal will need to use aCell
orRefCell
for similar reason, and that won't perform well.
I reimplemented it upon https://github.com/mmtk/mmtk-core/pull/1181 and now we no longer use RefCell
.
Benchmark (taskset -c 0 cargo bench --features test_private -- bscan
) shows that it can scan an Immix block with 200 objects in 268 ns in the steady state. In reality, it may take much longer due to cache misses.
GitHub CI reported an added API function SideMetadataSpec::scan_non_zero_values
which is intended. It did not report the added public method MMTK::enumerate_objects
, probably because it is guarded by the feature "vo_bit".
We have an old
ObjectIterator
, which is very similar to the simple version ofscan_non_zero_values
(expect that it skips the object size when it finds an object). After introducingtrait ObjectEnumerator
, it becomes confusing that we haveObjectIterator
andObjectEnuemrator
and they have nothing to do with each other.It would be good if we can simply remove
ObjectIterator
and replace its uses with the newly introduced enumerator. If this cannot be done in this PR, we should at least document the code to state what we plan to do with the oldObjectIterator
.
I think linear_scan::ObjectIterator
works similarly as the algorithm in this PR. ObjectIterator
outputs ObjectReference
, too, and it also scans from low to high addresses. A minor difference is that ObjectIterator
attempts to jump a longer distance by calling ObjectModel::get_current_size
. I am not sure whether ObjectModel::get_current_size
is faster than blindly scanning the VO bits at word granularity. We need benchmarks for that.
Since removing ObjectIterator
will involve refactoring MarkCompact, too, I'll do it in a separate PR.
This PR adds a heap traversal API
MMTK::enumerate_objects
which enumerates all objects in the MMTk heap at the time of calling.We added
SideMetadataSpec::scan_non_zero_values
to support enumerating objects by scanning the VO bit metadata. It can also be used for scanning other side metadata when needed. Note, however, that it is inefficient (but should work correctly) if the metadata is not contiguous or the metadata has more than one bit per region. If there is any need for scanning such metadata, we need further refactoring.