@@ -8,10 +8,10 @@ use proc_macro_error::proc_macro_error;
88use syn:: { parse_macro_input} ;
99use proc_macro_error:: abort_call_site;
1010use quote:: quote;
11- use syn:: { DeriveInput , Field , TypeGenerics } ;
12- use syn:: __private:: TokenStream2 ;
11+ use syn:: DeriveInput ;
1312
1413mod util;
14+ mod derive_impl;
1515
1616/// Generally a plan needs to add these attributes in order for the macro to work:
1717/// * add `#[derive(PlanTraceObject)]` to the plan struct.
@@ -23,7 +23,7 @@ mod util;
2323/// * add `#[policy_scan]` to any space field that has some policy-specific scan_object(). For objects in those spaces,
2424/// `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, policy_scan, copy , fallback_trace) ) ]
26+ #[ proc_macro_derive( PlanTraceObject , attributes( trace, policy_scan, 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 ;
@@ -37,9 +37,9 @@ pub fn derive_plan_trace_object(input: TokenStream) -> TokenStream {
3737 let scan_spaces = util:: get_fields_with_attribute ( fields, "policy_scan" ) ;
3838 let fallback = util:: get_unique_field_with_attribute ( fields, "fallback_trace" ) ;
3939
40- let trace_object_function = generate_trace_object ( & spaces, & fallback, & ty_generics) ;
41- let scan_object_function = generate_scan_object ( & scan_spaces, & ty_generics) ;
42- let may_move_objects_function = generate_may_move_objects ( & spaces, & fallback, & ty_generics) ;
40+ let trace_object_function = derive_impl :: generate_trace_object ( & spaces, & fallback, & ty_generics) ;
41+ let scan_object_function = derive_impl :: generate_scan_object ( & scan_spaces, & ty_generics) ;
42+ let may_move_objects_function = derive_impl :: 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) ]
@@ -61,128 +61,3 @@ pub fn derive_plan_trace_object(input: TokenStream) -> TokenStream {
6161
6262 output. into ( )
6363}
64-
65- fn generate_trace_object < ' a > (
66- space_fields : & [ & ' a Field ] ,
67- parent_field : & Option < & ' a Field > ,
68- ty_generics : & TypeGenerics ,
69- ) -> TokenStream2 {
70- // Generate a check with early return for each space
71- let space_field_handler = space_fields. iter ( ) . map ( |f| {
72- let f_ident = f. ident . as_ref ( ) . unwrap ( ) ;
73- let ref f_ty = f. ty ;
74-
75- // Figure out copy
76- let trace_attr = util:: get_field_attribute ( f, "trace" ) . unwrap ( ) ;
77- let copy = if !trace_attr. tokens . is_empty ( ) {
78- use syn:: Token ;
79- use syn:: NestedMeta ;
80- use syn:: punctuated:: Punctuated ;
81-
82- let args = trace_attr. parse_args_with ( Punctuated :: < NestedMeta , Token ! [ , ] > :: parse_terminated) . unwrap ( ) ;
83- // CopySemantics::X is a path.
84- if let Some ( NestedMeta :: Meta ( syn:: Meta :: Path ( p) ) ) = args. first ( ) {
85- quote ! { Some ( #p) }
86- } else {
87- quote ! { None }
88- }
89- } else {
90- quote ! { None }
91- } ;
92-
93- quote ! {
94- if self . #f_ident. in_space( __mmtk_objref) {
95- return <#f_ty as PolicyTraceObject #ty_generics>:: trace_object:: <T , KIND >( & self . #f_ident, __mmtk_trace, __mmtk_objref, #copy, __mmtk_worker) ;
96- }
97- }
98- } ) ;
99-
100- // Generate a fallback to the parent plan
101- let parent_field_delegator = if let Some ( f) = parent_field {
102- let f_ident = f. ident . as_ref ( ) . unwrap ( ) ;
103- let ref f_ty = f. ty ;
104- quote ! {
105- <#f_ty as PlanTraceObject #ty_generics>:: trace_object:: <T , KIND >( & self . #f_ident, __mmtk_trace, __mmtk_objref, __mmtk_worker)
106- }
107- } else {
108- quote ! {
109- panic!( "No more spaces to try" )
110- }
111- } ;
112-
113- quote ! {
114- fn trace_object<T : crate :: plan:: TransitiveClosure , const KIND : crate :: policy:: gc_work:: TraceKind >( & self , __mmtk_trace: & mut T , __mmtk_objref: crate :: util:: ObjectReference , __mmtk_worker: & mut crate :: scheduler:: GCWorker <VM >) -> crate :: util:: ObjectReference {
115- use crate :: policy:: space:: Space ;
116- use crate :: policy:: gc_work:: PolicyTraceObject ;
117- use crate :: plan:: transitive_closure:: PlanTraceObject ;
118- #( #space_field_handler) *
119- #parent_field_delegator
120- }
121- }
122- }
123-
124- fn generate_scan_object < ' a > (
125- scan_object_fields : & [ & ' a Field ] ,
126- ty_generics : & TypeGenerics ,
127- ) -> TokenStream2 {
128- let scan_field_handler = scan_object_fields. iter ( ) . map ( |f| {
129- let f_ident = f. ident . as_ref ( ) . unwrap ( ) ;
130- let ref f_ty = f. ty ;
131-
132- quote ! {
133- if self . #f_ident. in_space( __mmtk_objref) {
134- use crate :: policy:: gc_work:: PolicyTraceObject ;
135- <#f_ty as PolicyTraceObject #ty_generics>:: scan_object:: <EV >( & self . #f_ident, __mmtk_worker_tls, __mmtk_objref, __mmtk_ev) ;
136- return ;
137- }
138- }
139- } ) ;
140-
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) ;
150- }
151- }
152- }
153-
154- // The generated function needs to be inlined and constant folded. Otherwise, there will be a huge
155- // performance penalty.
156- fn generate_may_move_objects < ' a > (
157- space_fields : & [ & ' a Field ] ,
158- parent_field : & Option < & ' a Field > ,
159- ty_generics : & TypeGenerics ,
160- ) -> TokenStream2 {
161- // If any space or the parent may move objects, the plan may move objects
162- let space_handlers = space_fields. iter ( ) . map ( |f| {
163- let ref f_ty = f. ty ;
164-
165- quote ! {
166- || <#f_ty as PolicyTraceObject #ty_generics>:: may_move_objects:: <KIND >( )
167- }
168- } ) ;
169-
170- let parent_handler = if let Some ( p) = parent_field {
171- let ref p_ty = p. ty ;
172-
173- quote ! {
174- || <#p_ty as PlanTraceObject #ty_generics>:: may_move_objects:: <KIND >( )
175- }
176- } else {
177- TokenStream2 :: new ( )
178- } ;
179-
180- quote ! {
181- fn may_move_objects<const KIND : crate :: policy:: gc_work:: TraceKind >( ) -> bool {
182- use crate :: policy:: gc_work:: PolicyTraceObject ;
183- use crate :: plan:: transitive_closure:: PlanTraceObject ;
184-
185- false #( #space_handlers) * #parent_handler
186- }
187- }
188- }
0 commit comments