-
Notifications
You must be signed in to change notification settings - Fork 74
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use macro to generate process edges for plans (#575)
This PR adds `PlanProcessEdges`, and a few macros/traits that are used in `PlanProcessEdges`. This PR removes policy-specific code from plan, and use macros to generate trace object work for each plan. This PR closes #258, and closes #576. * add a trait `PolicyTraceObject`. Each policy provides an implementation of this. With this trait, a plan no longer include any policy-specific code in trace object. * add a trait `PlanTraceObject` and related macros. With the macro, plan implementer can declaratively specify trace object behavior with attributes, and the implementation of `PlanTraceObject` will be generated by the macro. * add a type `PlanProcessEdges`. This uses `PlanTraceObject` to provide a general implementation of `ProcessEdgesWork`. We no longer need any plan-specific process edges work.
Showing
38 changed files
with
953 additions
and
389 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
[package] | ||
name = "mmtk-macros" | ||
# the macro crate uses the same version as mmtk-core | ||
version = "0.11.0" | ||
edition = "2021" | ||
license = "MIT OR Apache-2.0" | ||
description = "MMTk macros provides procedural macros used by mmtk-core." | ||
homepage = "https://www.mmtk.io" | ||
repository = "https://github.com/mmtk/mmtk-core/tree/master/macros" | ||
|
||
[lib] | ||
proc-macro = true | ||
|
||
[dependencies] | ||
proc-macro2 = "1.0.37" | ||
syn = { version = "1.0.91", features = ["extra-traits"] } | ||
quote = "1.0.18" | ||
proc-macro-error = "1.0.4" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
extern crate proc_macro; | ||
extern crate syn; | ||
extern crate proc_macro_error; | ||
extern crate quote; | ||
|
||
use proc_macro::TokenStream; | ||
use proc_macro_error::proc_macro_error; | ||
use syn::{parse_macro_input}; | ||
use proc_macro_error::abort_call_site; | ||
use quote::quote; | ||
use syn::DeriveInput; | ||
|
||
mod util; | ||
mod plan_trace_object_impl; | ||
|
||
const DEBUG_MACRO_OUTPUT: bool = false; | ||
|
||
/// Generally a plan needs to add these attributes in order for the macro to work. The macro will | ||
/// generate an implementation of `PlanTraceObject` for the plan. With `PlanTraceObject`, the plan use | ||
/// `PlanProcessEdges` for GC tracing. The attributes only affects code generation in the macro, thus | ||
/// only affects the generated `PlanTraceObject` implementation. | ||
/// * add `#[derive(PlanTraceObject)]` to the plan struct. | ||
/// * add `#[trace]` to each space field the plan struct has. If the policy is a copying policy, | ||
/// it needs to further specify the copy semantic (`#[trace(CopySemantics::X)]`) | ||
/// * 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 `#[post_scan]` 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, post_scan, fallback_trace))] | ||
pub fn derive_plan_trace_object(input: TokenStream) -> TokenStream { | ||
let input = parse_macro_input!(input as DeriveInput); | ||
let ident = input.ident; | ||
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); | ||
|
||
let output = if let syn::Data::Struct(syn::DataStruct { | ||
fields: syn::Fields::Named(ref fields), | ||
.. | ||
}) = input.data { | ||
let spaces = util::get_fields_with_attribute(fields, "trace"); | ||
let post_scan_spaces = util::get_fields_with_attribute(fields, "post_scan"); | ||
let fallback = util::get_unique_field_with_attribute(fields, "fallback_trace"); | ||
|
||
let trace_object_function = plan_trace_object_impl::generate_trace_object(&spaces, &fallback, &ty_generics); | ||
let post_scan_object_function = plan_trace_object_impl::generate_post_scan_object(&post_scan_spaces, &ty_generics); | ||
let may_move_objects_function = plan_trace_object_impl::generate_may_move_objects(&spaces, &fallback, &ty_generics); | ||
quote!{ | ||
impl #impl_generics crate::plan::PlanTraceObject #ty_generics for #ident #ty_generics #where_clause { | ||
#trace_object_function | ||
|
||
#post_scan_object_function | ||
|
||
#may_move_objects_function | ||
} | ||
} | ||
} else { | ||
abort_call_site!("`#[derive(PlanTraceObject)]` only supports structs with named fields.") | ||
}; | ||
|
||
// Debug the output - use the following code to debug the generated code (when cargo exapand is not working) | ||
if DEBUG_MACRO_OUTPUT { | ||
use quote::ToTokens; | ||
println!("{}", output.to_token_stream()); | ||
} | ||
|
||
output.into() | ||
} |
Oops, something went wrong.