@@ -20,10 +20,10 @@ mod util;
2020/// * add `#[fallback_trace]` to the parent plan if the plan is composed with other plans (or parent plans).
2121/// For example, `GenImmix` is composed with `Gen`, `Gen` is composed with `CommonPlan`, `CommonPlan` is composed
2222/// with `BasePlan`.
23- /// * (optional) add `#[scan_work ]` to _one_ space field in the plan. `create_scan_work` will be generated based
24- /// on the space .
23+ /// * add `#[policy_scan ]` to any space field that has some policy-specific scan_object(). For objects in those spaces,
24+ /// `scan_object()` in the policy will be called. For other objects, directly call `VM::VMScanning::scan_object()` .
2525#[ proc_macro_error]
26- #[ proc_macro_derive( PlanTraceObject , attributes( trace, scan_work , copy, fallback_trace) ) ]
26+ #[ proc_macro_derive( PlanTraceObject , attributes( trace, policy_scan , copy, fallback_trace) ) ]
2727pub fn derive_plan_trace_object ( input : TokenStream ) -> TokenStream {
2828 let input = parse_macro_input ! ( input as DeriveInput ) ;
2929 let ident = input. ident ;
@@ -34,19 +34,19 @@ pub fn derive_plan_trace_object(input: TokenStream) -> TokenStream {
3434 ..
3535 } ) = input. data {
3636 let spaces = util:: get_fields_with_attribute ( fields, "trace" ) ;
37- let scan_work = util:: get_unique_field_with_attribute ( fields, "scan_work " ) ;
37+ let scan_spaces = util:: get_fields_with_attribute ( fields, "policy_scan " ) ;
3838 let fallback = util:: get_unique_field_with_attribute ( fields, "fallback_trace" ) ;
3939
4040 let trace_object_function = generate_trace_object ( & spaces, & fallback, & ty_generics) ;
41- let create_scan_work_function = generate_create_scan_work ( & spaces , & scan_work , & ty_generics) ;
41+ let scan_object_function = generate_scan_object ( & scan_spaces , & ty_generics) ;
4242 let may_move_objects_function = generate_may_move_objects ( & spaces, & fallback, & ty_generics) ;
4343 quote ! {
4444 impl #impl_generics crate :: plan:: transitive_closure:: PlanTraceObject #ty_generics for #ident #ty_generics #where_clause {
4545 #[ inline( always) ]
4646 #trace_object_function
4747
4848 #[ inline( always) ]
49- #create_scan_work_function
49+ #scan_object_function
5050
5151 #[ inline( always) ]
5252 #may_move_objects_function
@@ -121,40 +121,32 @@ fn generate_trace_object<'a>(
121121 }
122122}
123123
124- fn generate_create_scan_work < ' a > (
125- space_fields : & [ & ' a Field ] ,
126- scan_work_field : & Option < & ' a Field > ,
124+ fn generate_scan_object < ' a > (
125+ scan_object_fields : & [ & ' a Field ] ,
127126 ty_generics : & TypeGenerics ,
128127) -> TokenStream2 {
129- if let Some ( f) = scan_work_field {
130- // If the plan names a field for scan work, use it
128+ let scan_field_handler = scan_object_fields. iter ( ) . map ( |f| {
131129 let f_ident = f. ident . as_ref ( ) . unwrap ( ) ;
132130 let ref f_ty = f. ty ;
133131
134132 quote ! {
135- fn create_scan_work< E : crate :: scheduler :: gc_work :: ProcessEdgesWork < VM = VM >> ( & ' static self , nodes : Vec < crate :: util :: ObjectReference > ) -> Box <dyn crate :: scheduler :: GCWork < VM >> {
133+ if self . #f_ident . in_space ( __mmtk_objref ) {
136134 use crate :: policy:: gc_work:: PolicyTraceObject ;
137- <#f_ty as PolicyTraceObject #ty_generics>:: create_scan_work:: <E >( & self . #f_ident, nodes)
135+ <#f_ty as PolicyTraceObject #ty_generics>:: scan_object:: <EV >( & self . #f_ident, __mmtk_worker_tls, __mmtk_objref, __mmtk_ev) ;
136+ return ;
138137 }
139138 }
140- } else if !space_fields. is_empty ( ) {
141- // If the plan does not name a specific field for scan work, just use the first space for scan work
142- let f = space_fields[ 0 ] ;
143- let f_ident = f. ident . as_ref ( ) . unwrap ( ) ;
144- let ref f_ty = f. ty ;
139+ } ) ;
145140
146- quote ! {
147- fn create_scan_work<E : crate :: scheduler:: gc_work:: ProcessEdgesWork <VM = VM >>( & ' static self , nodes: Vec <crate :: util:: ObjectReference >) -> Box <dyn crate :: scheduler:: GCWork <VM >> {
148- use crate :: policy:: gc_work:: PolicyTraceObject ;
149- <#f_ty as PolicyTraceObject #ty_generics>:: create_scan_work:: <E >( & self . #f_ident, nodes)
150- }
151- }
152- } else {
153- // Otherwise, just panic
154- quote ! {
155- fn create_scan_work<E : crate :: scheduler:: gc_work:: ProcessEdgesWork <VM = VM >>( & ' static self , nodes: Vec <crate :: util:: ObjectReference >) -> Box <dyn crate :: scheduler:: GCWork <VM >> {
156- panic!( "Unable to create a scan work packet for the plan (the plan does not name a #[scan_work] field, or a #[trace] field" )
157- }
141+ quote ! {
142+ 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 ) {
143+ use crate :: vm:: Scanning ;
144+
145+ // Plan specific
146+ #( #scan_field_handler) *
147+
148+ // Default
149+ VM :: VMScanning :: scan_object( __mmtk_worker_tls, __mmtk_objref, __mmtk_ev) ;
158150 }
159151 }
160152}
0 commit comments