Skip to content

Commit

Permalink
Change to PolicyTraceObject::post_scan_object
Browse files Browse the repository at this point in the history
Now it is provided as a hook **after** scan_object.  It no longer
customises how to do scan_object.
  • Loading branch information
wks committed May 5, 2022
1 parent 506757d commit 226994a
Show file tree
Hide file tree
Showing 7 changed files with 26 additions and 46 deletions.
17 changes: 6 additions & 11 deletions macros/trace_object/src/derive_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,32 +63,27 @@ pub fn generate_trace_object<'a>(
}
}

pub fn generate_scan_object<'a>(
scan_object_fields: &[&'a Field],
pub fn generate_post_scan_object<'a>(
post_scan_object_fields: &[&'a Field],
ty_generics: &TypeGenerics,
) -> TokenStream2 {
let scan_field_handler = scan_object_fields.iter().map(|f| {
let scan_field_handler = post_scan_object_fields.iter().map(|f| {
let f_ident = f.ident.as_ref().unwrap();
let ref f_ty = f.ty;

quote! {
if self.#f_ident.in_space(__mmtk_objref) {
use crate::policy::gc_work::PolicyTraceObject;
<#f_ty as PolicyTraceObject #ty_generics>::scan_object::<EV>(&self.#f_ident, __mmtk_worker_tls, __mmtk_objref, __mmtk_ev);
<#f_ty as PolicyTraceObject #ty_generics>::post_scan_object(&self.#f_ident, __mmtk_objref);
return;
}
}
});

quote! {
fn scan_object<EV: crate::vm::EdgeVisitor>(&self, __mmtk_worker_tls: crate::util::opaque_pointer::VMWorkerThread, __mmtk_objref: crate::util::ObjectReference, __mmtk_ev: &mut EV) {
use crate::vm::Scanning;

// Plan specific
#[inline(always)]
fn post_scan_object(&self, __mmtk_objref: crate::util::ObjectReference) {
#(#scan_field_handler)*

// Default
VM::VMScanning::scan_object(__mmtk_worker_tls, __mmtk_objref, __mmtk_ev);
}
}
}
Expand Down
12 changes: 6 additions & 6 deletions macros/trace_object/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ mod derive_impl;
/// * add `#[fallback_trace]` to the parent plan if the plan is composed with other plans (or parent plans).
/// For example, `GenImmix` is composed with `Gen`, `Gen` is composed with `CommonPlan`, `CommonPlan` is composed
/// with `BasePlan`.
/// * add `#[policy_scan]` to any space field that has some policy-specific scan_object(). For objects in those spaces,
/// `scan_object()` in the policy will be called. For other objects, directly call `VM::VMScanning::scan_object()`.
/// * add `#[post_scan_hook]` to any space field that has some policy-specific post_scan_object(). For objects in those spaces,
/// `post_scan_object()` in the policy will be called after `VM::VMScanning::scan_object()`.
#[proc_macro_error]
#[proc_macro_derive(PlanTraceObject, attributes(trace, policy_scan, fallback_trace))]
#[proc_macro_derive(PlanTraceObject, attributes(trace, post_scan_hook, fallback_trace))]
pub fn derive_plan_trace_object(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let ident = input.ident;
Expand All @@ -34,19 +34,19 @@ pub fn derive_plan_trace_object(input: TokenStream) -> TokenStream {
..
}) = input.data {
let spaces = util::get_fields_with_attribute(fields, "trace");
let scan_spaces = util::get_fields_with_attribute(fields, "policy_scan");
let post_scan_hook_spaces = util::get_fields_with_attribute(fields, "post_scan_hook");
let fallback = util::get_unique_field_with_attribute(fields, "fallback_trace");

let trace_object_function = derive_impl::generate_trace_object(&spaces, &fallback, &ty_generics);
let scan_object_function = derive_impl::generate_scan_object(&scan_spaces, &ty_generics);
let post_scan_object_function = derive_impl::generate_post_scan_object(&post_scan_hook_spaces, &ty_generics);
let may_move_objects_function = derive_impl::generate_may_move_objects(&spaces, &fallback, &ty_generics);
quote!{
impl #impl_generics crate::plan::transitive_closure::PlanTraceObject #ty_generics for #ident #ty_generics #where_clause {
#[inline(always)]
#trace_object_function

#[inline(always)]
#scan_object_function
#post_scan_object_function

#[inline(always)]
#may_move_objects_function
Expand Down
2 changes: 1 addition & 1 deletion src/plan/generational/immix/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ pub struct GenImmix<VM: VMBinding> {
#[fallback_trace]
pub gen: Gen<VM>,
/// An immix space as the mature space.
#[policy_scan]
#[post_scan_hook]
#[trace(CopySemantics::Mature)]
pub immix: ImmixSpace<VM>,
/// Whether the last GC was a defrag GC for the immix space.
Expand Down
2 changes: 1 addition & 1 deletion src/plan/immix/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use mmtk_macro_trace_object::PlanTraceObject;

#[derive(PlanTraceObject)]
pub struct Immix<VM: VMBinding> {
#[policy_scan]
#[post_scan_hook]
#[trace(CopySemantics::DefaultCopy)]
pub immix_space: ImmixSpace<VM>,
#[fallback_trace]
Expand Down
13 changes: 5 additions & 8 deletions src/plan/transitive_closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ impl<'a, E: ProcessEdgesWork> Drop for ObjectsClosure<'a, E> {

use crate::policy::gc_work::TraceKind;
use crate::scheduler::GCWork;
use crate::util::VMWorkerThread;

use crate::vm::VMBinding;

/// A plan that uses `PlanProcessEdges` needs to provide an implementation for this trait.
Expand All @@ -97,12 +97,7 @@ pub trait PlanTraceObject<VM: VMBinding> {
/// Scan objects in the plan. It is expected that each object will be scanned by `VM::VMScanning::scan_object()`.
/// If the object is in a policy that has some policy specific behaviors for scanning (e.g. mark lines in Immix),
/// this method should also invoke those policy specific methods.
fn scan_object<EV: EdgeVisitor>(
&self,
tls: VMWorkerThread,
object: ObjectReference,
edge_visitor: &mut EV,
);
fn post_scan_object(&self, object: ObjectReference);

/// Whether objects in this plan may move. If any of the spaces used by the plan may move objects, this should
/// return true.
Expand Down Expand Up @@ -226,7 +221,9 @@ impl<E: ProcessEdgesWork, P: 'static + Plan<VM = E::VM> + PlanTraceObject<E::VM>
let tls = worker.tls;
let mut closure = ObjectsClosure::<E>::new(worker);
for object in &self.buffer {
self.plan.scan_object(tls, *object, &mut closure);
use crate::vm::Scanning;
<E::VM as VMBinding>::VMScanning::scan_object(tls, *object, &mut closure);
self.plan.post_scan_object(*object);
}
}
trace!("PlanScanObjects End");
Expand Down
18 changes: 6 additions & 12 deletions src/policy/gc_work.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ pub const DEFAULT_TRACE: u8 = u8::MAX;
use crate::plan::TransitiveClosure;
use crate::scheduler::GCWorker;
use crate::util::copy::CopySemantics;
use crate::util::opaque_pointer::VMWorkerThread;

use crate::util::ObjectReference;
use crate::vm::EdgeVisitor;

use crate::vm::VMBinding;

/// This trait defines policy-specific behavior for tracing objects.
Expand All @@ -28,17 +28,11 @@ pub trait PolicyTraceObject<VM: VMBinding> {
worker: &mut GCWorker<VM>,
) -> ObjectReference;

/// Policy-specific scan object. The implementation needs to guarantee that
/// they will call `VM::VMScanning::scan_object()` (or `Self::vm_scan_object()`) besides any space-specific work for the object.
/// Policy-specific post-scan-object hook. It is called after scanning
/// each object in this space.
#[inline(always)]
fn scan_object<EV: EdgeVisitor>(
&self,
tls: VMWorkerThread,
object: ObjectReference,
edge_visitor: &mut EV,
) {
use crate::vm::Scanning;
VM::VMScanning::scan_object(tls, object, edge_visitor)
fn post_scan_object(&self, _object: ObjectReference) {
// Do nothing.
}

/// Return whether the policy moves objects.
Expand Down
8 changes: 1 addition & 7 deletions src/policy/immix/immixspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,13 +135,7 @@ impl<VM: VMBinding> crate::policy::gc_work::PolicyTraceObject<VM> for ImmixSpace
}

#[inline(always)]
fn scan_object<EV: EdgeVisitor>(
&self,
tls: VMWorkerThread,
object: ObjectReference,
edge_visitor: &mut EV,
) {
VM::VMScanning::scan_object(tls, object, edge_visitor);
fn post_scan_object(&self, object: ObjectReference) {
if super::MARK_LINE_AT_SCAN_TIME && !super::BLOCK_ONLY {
debug_assert!(self.in_space(object));
self.mark_lines(object);
Expand Down

0 comments on commit 226994a

Please sign in to comment.