Annotate mutators that use methods that prevent mutator coalescing
Mutator coalescing reduces the overhead of visiting every module
for every mutator by calling a series of mutator methods on a
a single module in a row. This is only valid for well-behaved
mutators. Add methods on MutatorHandle that allow annotating
mutators that are not well behaved, and use that to prevent
coalescing mutators.
Bug: 372076859
Test: all soong tests pass with race detector on
Flag: EXEMPT refactor
Change-Id: Id9b005f05227e5558cac6d488030a7398af13fb8
diff --git a/android/defaults.go b/android/defaults.go
index 3d06c69..8fe2879 100644
--- a/android/defaults.go
+++ b/android/defaults.go
@@ -274,7 +274,7 @@
func RegisterDefaultsPreArchMutators(ctx RegisterMutatorsContext) {
ctx.BottomUp("defaults_deps", defaultsDepsMutator).Parallel()
- ctx.BottomUp("defaults", defaultsMutator).Parallel()
+ ctx.BottomUp("defaults", defaultsMutator).Parallel().UsesCreateModule()
}
func defaultsDepsMutator(ctx BottomUpMutatorContext) {
diff --git a/android/mutator.go b/android/mutator.go
index ebe03a4..0da3ec7 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -221,7 +221,8 @@
// Does not affect the ordering of the current mutator pass, but will be ordered
// correctly for all future mutator passes. All reverse dependencies for a destination module are
// collected until the end of the mutator pass, sorted by name, and then appended to the destination
- // module's dependency list.
+ // module's dependency list. May only be called by mutators that were marked with
+ // UsesReverseDependencies during registration.
AddReverseDependency(module blueprint.Module, tag blueprint.DependencyTag, name string)
// AddVariationDependencies adds deps as dependencies of the current module, but uses the variations
@@ -235,14 +236,15 @@
// be ordered correctly for all future mutator passes.
AddVariationDependencies(variations []blueprint.Variation, tag blueprint.DependencyTag, names ...string) []blueprint.Module
- // AddReverseVariationDependencies adds a dependency from the named module to the current
+ // AddReverseVariationDependency adds a dependency from the named module to the current
// module. The given variations will be added to the current module's varations, and then the
// result will be used to find the correct variation of the depending module, which must exist.
//
// Does not affect the ordering of the current mutator pass, but will be ordered
// correctly for all future mutator passes. All reverse dependencies for a destination module are
// collected until the end of the mutator pass, sorted by name, and then appended to the destination
- // module's dependency list.
+ // module's dependency list. May only be called by mutators that were marked with
+ // UsesReverseDependencies during registration.
AddReverseVariationDependency([]blueprint.Variation, blueprint.DependencyTag, string)
// AddFarVariationDependencies adds deps as dependencies of the current module, but uses the
@@ -262,21 +264,25 @@
// ReplaceDependencies finds all the variants of the module with the specified name, then
// replaces all dependencies onto those variants with the current variant of this module.
- // Replacements don't take effect until after the mutator pass is finished.
+ // Replacements don't take effect until after the mutator pass is finished. May only
+ // be called by mutators that were marked with UsesReplaceDependencies during registration.
ReplaceDependencies(string)
// ReplaceDependenciesIf finds all the variants of the module with the specified name, then
// replaces all dependencies onto those variants with the current variant of this module
// as long as the supplied predicate returns true.
- // Replacements don't take effect until after the mutator pass is finished.
+ // Replacements don't take effect until after the mutator pass is finished. May only
+ // be called by mutators that were marked with UsesReplaceDependencies during registration.
ReplaceDependenciesIf(string, blueprint.ReplaceDependencyPredicate)
// Rename all variants of a module. The new name is not visible to calls to ModuleName,
- // AddDependency or OtherModuleName until after this mutator pass is complete.
+ // AddDependency or OtherModuleName until after this mutator pass is complete. May only be called
+ // by mutators that were marked with UsesRename during registration.
Rename(name string)
// CreateModule creates a new module by calling the factory method for the specified moduleType, and applies
- // the specified property structs to it as if the properties were set in a blueprint file.
+ // the specified property structs to it as if the properties were set in a blueprint file. May only
+ // be called by mutators that were marked with UsesCreateModule during registration.
CreateModule(ModuleFactory, ...interface{}) Module
}
@@ -620,13 +626,60 @@
} else if mutator.transitionMutator != nil {
blueprintCtx.RegisterTransitionMutator(mutator.name, mutator.transitionMutator)
}
+
+ // Forward booleans set on the MutatorHandle to the blueprint.MutatorHandle.
if mutator.parallel {
handle.Parallel()
}
+ if mutator.usesRename {
+ handle.UsesRename()
+ }
+ if mutator.usesReverseDependencies {
+ handle.UsesReverseDependencies()
+ }
+ if mutator.usesReplaceDependencies {
+ handle.UsesReplaceDependencies()
+ }
+ if mutator.usesCreateModule {
+ handle.UsesCreateModule()
+ }
+ if mutator.mutatesDependencies {
+ handle.MutatesDependencies()
+ }
+ if mutator.mutatesGlobalState {
+ handle.MutatesGlobalState()
+ }
}
type MutatorHandle interface {
+ // Parallel sets the mutator to visit modules in parallel while maintaining ordering. Calling any
+ // method on the mutator context is thread-safe, but the mutator must handle synchronization
+ // for any modifications to global state or any modules outside the one it was invoked on.
Parallel() MutatorHandle
+
+ // UsesRename marks the mutator as using the BottomUpMutatorContext.Rename method, which prevents
+ // coalescing adjacent mutators into a single mutator pass.
+ UsesRename() MutatorHandle
+
+ // UsesReverseDependencies marks the mutator as using the BottomUpMutatorContext.AddReverseDependency
+ // method, which prevents coalescing adjacent mutators into a single mutator pass.
+ UsesReverseDependencies() MutatorHandle
+
+ // UsesReplaceDependencies marks the mutator as using the BottomUpMutatorContext.ReplaceDependencies
+ // method, which prevents coalescing adjacent mutators into a single mutator pass.
+ UsesReplaceDependencies() MutatorHandle
+
+ // UsesCreateModule marks the mutator as using the BottomUpMutatorContext.CreateModule method,
+ // which prevents coalescing adjacent mutators into a single mutator pass.
+ UsesCreateModule() MutatorHandle
+
+ // MutatesDependencies marks the mutator as modifying properties in dependencies, which prevents
+ // coalescing adjacent mutators into a single mutator pass.
+ MutatesDependencies() MutatorHandle
+
+ // MutatesGlobalState marks the mutator as modifying global state, which prevents coalescing
+ // adjacent mutators into a single mutator pass.
+ MutatesGlobalState() MutatorHandle
}
func (mutator *mutator) Parallel() MutatorHandle {
@@ -634,6 +687,36 @@
return mutator
}
+func (mutator *mutator) UsesRename() MutatorHandle {
+ mutator.usesRename = true
+ return mutator
+}
+
+func (mutator *mutator) UsesReverseDependencies() MutatorHandle {
+ mutator.usesReverseDependencies = true
+ return mutator
+}
+
+func (mutator *mutator) UsesReplaceDependencies() MutatorHandle {
+ mutator.usesReplaceDependencies = true
+ return mutator
+}
+
+func (mutator *mutator) UsesCreateModule() MutatorHandle {
+ mutator.usesCreateModule = true
+ return mutator
+}
+
+func (mutator *mutator) MutatesDependencies() MutatorHandle {
+ mutator.mutatesDependencies = true
+ return mutator
+}
+
+func (mutator *mutator) MutatesGlobalState() MutatorHandle {
+ mutator.mutatesGlobalState = true
+ return mutator
+}
+
func RegisterComponentsMutator(ctx RegisterMutatorsContext) {
ctx.BottomUp("component-deps", componentDepsMutator).Parallel()
}
@@ -653,7 +736,7 @@
}
func registerDepsMutator(ctx RegisterMutatorsContext) {
- ctx.BottomUp("deps", depsMutator).Parallel()
+ ctx.BottomUp("deps", depsMutator).Parallel().UsesReverseDependencies()
}
// android.topDownMutatorContext either has to embed blueprint.TopDownMutatorContext, in which case every method that
diff --git a/android/mutator_test.go b/android/mutator_test.go
index 88bf1d2..33fca9e 100644
--- a/android/mutator_test.go
+++ b/android/mutator_test.go
@@ -158,7 +158,7 @@
ctx.BottomUp("rename_bottom_up", func(ctx BottomUpMutatorContext) {
moduleStrings = append(moduleStrings, ctx.Module().String())
ctx.Rename(ctx.Module().base().Name() + "_renamed1")
- })
+ }).UsesRename()
ctx.BottomUp("final", func(ctx BottomUpMutatorContext) {
moduleStrings = append(moduleStrings, ctx.Module().String())
})
diff --git a/android/namespace.go b/android/namespace.go
index ebf85a1..866d125 100644
--- a/android/namespace.go
+++ b/android/namespace.go
@@ -457,7 +457,7 @@
}
func RegisterNamespaceMutator(ctx RegisterMutatorsContext) {
- ctx.BottomUp("namespace_deps", namespaceMutator).Parallel()
+ ctx.BottomUp("namespace_deps", namespaceMutator).Parallel().MutatesGlobalState()
}
func namespaceMutator(ctx BottomUpMutatorContext) {
diff --git a/android/namespace_test.go b/android/namespace_test.go
index ea51c6e..0327e78 100644
--- a/android/namespace_test.go
+++ b/android/namespace_test.go
@@ -646,7 +646,7 @@
ctx.RegisterModuleType("test_module", newTestModule)
ctx.Context.RegisterModuleType("blueprint_test_module", newBlueprintTestModule)
ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
- ctx.BottomUp("rename", renameMutator)
+ ctx.BottomUp("rename", renameMutator).UsesRename()
})
}),
)
@@ -709,9 +709,6 @@
}
func (m *testModule) DepsMutator(ctx BottomUpMutatorContext) {
- if m.properties.Rename != "" {
- ctx.Rename(m.properties.Rename)
- }
for _, d := range m.properties.Deps {
ctx.AddDependency(ctx.Module(), nil, d)
}
diff --git a/android/override_module.go b/android/override_module.go
index f69f963..d844da6 100644
--- a/android/override_module.go
+++ b/android/override_module.go
@@ -234,8 +234,9 @@
// Mutators for override/overridable modules. All the fun happens in these functions. It is critical
// to keep them in this order and not put any order mutators between them.
func RegisterOverridePostDepsMutators(ctx RegisterMutatorsContext) {
- ctx.BottomUp("override_deps", overrideModuleDepsMutator).Parallel()
+ ctx.BottomUp("override_deps", overrideModuleDepsMutator).Parallel().MutatesDependencies() // modifies deps via addOverride
ctx.Transition("override", &overrideTransitionMutator{})
+ ctx.BottomUp("override_apply", overrideApplyMutator).Parallel().MutatesDependencies()
// overridableModuleDepsMutator calls OverridablePropertiesDepsMutator so that overridable modules can
// add deps from overridable properties.
ctx.BottomUp("overridable_deps", overridableModuleDepsMutator).Parallel()
@@ -243,8 +244,8 @@
// prebuilt's ReplaceDependencies doesn't affect to those deps added by overridable properties.
// By running PrebuiltPostDepsMutator again after overridableModuleDepsMutator, deps via overridable properties
// can be replaced with prebuilts.
- ctx.BottomUp("replace_deps_on_prebuilts_for_overridable_deps_again", PrebuiltPostDepsMutator).Parallel()
- ctx.BottomUp("replace_deps_on_override", replaceDepsOnOverridingModuleMutator).Parallel()
+ ctx.BottomUp("replace_deps_on_prebuilts_for_overridable_deps_again", PrebuiltPostDepsMutator).Parallel().UsesReplaceDependencies()
+ ctx.BottomUp("replace_deps_on_override", replaceDepsOnOverridingModuleMutator).Parallel().UsesReplaceDependencies()
}
type overrideBaseDependencyTag struct {
@@ -330,6 +331,9 @@
}
func (overrideTransitionMutator) Mutate(ctx BottomUpMutatorContext, variation string) {
+}
+
+func overrideApplyMutator(ctx BottomUpMutatorContext) {
if o, ok := ctx.Module().(OverrideModule); ok {
overridableDeps := ctx.GetDirectDepsWithTag(overrideBaseDepTag)
if len(overridableDeps) > 1 {
diff --git a/android/prebuilt.go b/android/prebuilt.go
index e5d06dd..017ba76 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -400,13 +400,13 @@
}
func RegisterPrebuiltsPreArchMutators(ctx RegisterMutatorsContext) {
- ctx.BottomUp("prebuilt_rename", PrebuiltRenameMutator).Parallel()
+ ctx.BottomUp("prebuilt_rename", PrebuiltRenameMutator).Parallel().UsesRename()
}
func RegisterPrebuiltsPostDepsMutators(ctx RegisterMutatorsContext) {
- ctx.BottomUp("prebuilt_source", PrebuiltSourceDepsMutator).Parallel()
+ ctx.BottomUp("prebuilt_source", PrebuiltSourceDepsMutator).Parallel().UsesReverseDependencies()
ctx.BottomUp("prebuilt_select", PrebuiltSelectModuleMutator).Parallel()
- ctx.BottomUp("prebuilt_postdeps", PrebuiltPostDepsMutator).Parallel()
+ ctx.BottomUp("prebuilt_postdeps", PrebuiltPostDepsMutator).Parallel().UsesReplaceDependencies()
}
// Returns the name of the source module corresponding to a prebuilt module
diff --git a/android/register.go b/android/register.go
index 2ce6025..94d875d 100644
--- a/android/register.go
+++ b/android/register.go
@@ -91,7 +91,14 @@
bottomUpMutator blueprint.BottomUpMutator
topDownMutator blueprint.TopDownMutator
transitionMutator blueprint.TransitionMutator
- parallel bool
+
+ parallel bool
+ usesRename bool
+ usesReverseDependencies bool
+ usesReplaceDependencies bool
+ usesCreateModule bool
+ mutatesDependencies bool
+ mutatesGlobalState bool
}
var _ sortableComponent = &mutator{}
diff --git a/apex/apex.go b/apex/apex.go
index b53cb0f..6bb2a1a 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -55,7 +55,7 @@
}
func RegisterPreDepsMutators(ctx android.RegisterMutatorsContext) {
- ctx.BottomUp("apex_vndk_deps", apexVndkDepsMutator).Parallel()
+ ctx.BottomUp("apex_vndk_deps", apexVndkDepsMutator).Parallel().UsesReverseDependencies()
}
func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
@@ -67,7 +67,7 @@
// it should create a platform variant.
ctx.BottomUp("mark_platform_availability", markPlatformAvailability).Parallel()
ctx.Transition("apex", &apexTransitionMutator{})
- ctx.BottomUp("apex_directly_in_any", apexDirectlyInAnyMutator).Parallel()
+ ctx.BottomUp("apex_directly_in_any", apexDirectlyInAnyMutator).Parallel().MutatesDependencies()
ctx.BottomUp("apex_dcla_deps", apexDCLADepsMutator).Parallel()
}
diff --git a/golang/golang_test.go b/golang/golang_test.go
index b512144..b909f59 100644
--- a/golang/golang_test.go
+++ b/golang/golang_test.go
@@ -39,7 +39,7 @@
android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
RegisterGoModuleTypes(ctx)
ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.BottomUpBlueprint("bootstrap_deps", bootstrap.BootstrapDeps)
+ ctx.BottomUpBlueprint("bootstrap_deps", bootstrap.BootstrapDeps).UsesReverseDependencies()
})
}),
).RunTestWithBp(t, bp)