-
Notifications
You must be signed in to change notification settings - Fork 66
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor: Change ActivePlan::mutators()
's return type
#817
Conversation
* rust-toolchain: Update rust-toolchain to nightly version for RPITIT. * src/lib: Update crate attribute. * vm/active_plan.rs: Remove SynchronizedMutatorIterator and related trait function. Change the return type of mutators function. Signed-off-by: Zheyuan Chen <sephirotheca17@gmail.com>
* active_plan.rs: update correct lifetime for mutators function. Signed-off-by: Zheyuan Chen <sephirotheca17@gmail.com>
* rust-toolchain: Change back to stable version. * src/lib.rs: Remove unused crate attribute. * src/vm/active_plan.rs: Boxes the return of mutuators function to avoid using unstable feature. Signed-off-by: Zheyuan Chen <sephirotheca17@gmail.com>
binding-refs |
I suggest a different API. Instead of creating an iterator, we let the VM binding call back to MMTk core for each mutator. trait ActivePlan<VM> {
fn mutators<F>(visit_mutator: F)
where
F: FnMut(&mut MMTkMutator<VM>);
} It is basically the classic internal iteration vs external iteration problem. An
rb_thread_t *th = NULL;
ccan_list_for_each(&main_ractor->threads.set, th, lt_node) {
// Each thread is assigned to th. Visit th here.
} The advantage of external iteration is, The advantages of internal iteration are
For example, given an external iterator void visit_mutators(void (*visit_mutator)(Mutator *mutator)) {
JavaThreadIteratorWithHandle jtiwh; // Create external iterator
JavaThread *thr;
while ((thr = jtiwh->next()) != nullptr) {
visit_mutator(&thr->third_part_heap_mutator); // Call back
}
} But converting internal iterator to external iterator is not easy. For example, given Ruby's void rb_mmtk_get_mutators(void (*visit_mutator)(RubyMutator *mutator)) {
rb_thread_t *th = NULL;
ccan_list_for_each(&main_ractor->threads.set, th, lt_node) {
visit_mutator(th->mutator);
}
} The call site of impl ActivePlan<Ruby> for VMActivePlan {
fn mutators() -> Box<dyn Iterator<...>> {
// Collect the mutator pointers
let mut mutators = vec![];
(upcalls().get_mutators)(|mutator_ptr| { // For clearness, I just write it as a closure. In the real code, it needs to be an extern "C" fn.
mutators.push(mutator_ptr);
});
// Wrap the vector into an iterator struct.
RubyMutatorIterator {
mutator_pointer: mutators,
cursor: 0,
}
}
} It works for now. But I think we should discuss this internal vs external iterator issue in a group. I suggest we hold this PR until we have a clearer conclusion. |
Using I am not seeing strong advantages that internal iterator would be better in this case in your arguments.
Each binding can implement its own
If a binding can implement the old API, they can implement the new API with |
That's true, but the Ruby binding always used the hack of storing mutator pointers into an intermediate vector in the But anyway, the API introduced by this PR is still an improvement over the previous API that assumed a global iterator instance. I am OK with this PR now, and let's worry about the internal vs external iteration problem if we encounter a particular VM or use case where |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, but we may consider switching to internal iteration API (call-back style) if we encounter a VM that is inconvenient to implement external iteration of mutators using its API.
This is an alternative approach for #218 that addresses the upstream API change in mmtk/mmtk-core#817. This PR simply saves the mutator pointers into a `VecDeque` and embeds it into the iterator.
To reflect upstream changes made in mmtk/mmtk-core#817.
Close #784