Clear as much of cc.Module as possible after GenerateBuildActions

Reduce peak memory usage by adding a CleanupAfterBuildActions method
that is called at the end GenerateBuidlActions, nad use it to clear as
much of cc.Module as possible.

This is a temporary measure, eventually the entire module should be
released by blueprint once all interactions are performed through
providers.

Test: all soong tests pass
Change-Id: Idc3390ae4506ff2eef3231691e1de7446067961a
diff --git a/android/module.go b/android/module.go
index ecd0f23..c0abfd0 100644
--- a/android/module.go
+++ b/android/module.go
@@ -45,6 +45,14 @@
 	// For more information, see Module.GenerateBuildActions within Blueprint's module_ctx.go
 	GenerateAndroidBuildActions(ModuleContext)
 
+	// CleanupAfterBuildActions is called after ModuleBase.GenerateBuildActions is finished.
+	// If all interactions with this module are handled via providers instead of direct access
+	// to the module then it can free memory attached to the module.
+	// This is a temporary measure to reduce memory usage, eventually blueprint's reference
+	// to the Module should be dropped after GenerateAndroidBuildActions once all accesses
+	// can be done through providers.
+	CleanupAfterBuildActions()
+
 	// Add dependencies to the components of a module, i.e. modules that are created
 	// by the module and which are considered to be part of the creating module.
 	//
@@ -2387,8 +2395,12 @@
 			})
 		}
 	}
+
+	m.module.CleanupAfterBuildActions()
 }
 
+func (m *ModuleBase) CleanupAfterBuildActions() {}
+
 func SetJarJarPrefixHandler(handler func(ModuleContext)) {
 	if jarJarPrefixHandler != nil {
 		panic("jarJarPrefixHandler already set")
diff --git a/android/module_proxy.go b/android/module_proxy.go
index 561c477..81d90e9 100644
--- a/android/module_proxy.go
+++ b/android/module_proxy.go
@@ -27,6 +27,10 @@
 	panic("method is not implemented on ModuleProxy")
 }
 
+func (m ModuleProxy) CleanupAfterBuildActions() {
+	panic("method is not implemented on ModuleProxy")
+}
+
 func (m ModuleProxy) ComponentDepsMutator(ctx BottomUpMutatorContext) {
 	panic("method is not implemented on ModuleProxy")
 }
diff --git a/cc/cc.go b/cc/cc.go
index 85d2ebf..c616165 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -2438,6 +2438,27 @@
 	}
 }
 
+func (c *Module) CleanupAfterBuildActions() {
+	// Clear as much of Module as possible to reduce memory usage.
+	c.generators = nil
+	c.compiler = nil
+	c.installer = nil
+	c.features = nil
+	c.coverage = nil
+	c.fuzzer = nil
+	c.sabi = nil
+	c.lto = nil
+	c.afdo = nil
+	c.orderfile = nil
+
+	// TODO: these can be cleared after nativeBinaryInfoProperties and nativeLibInfoProperties are switched to
+	//  using providers.
+	// c.linker = nil
+	// c.stl = nil
+	// c.sanitize = nil
+	// c.library = nil
+}
+
 func CreateCommonLinkableInfo(ctx android.ModuleContext, mod VersionedLinkableInterface) *LinkableInfo {
 	info := &LinkableInfo{
 		StaticExecutable:     mod.StaticExecutable(),
diff --git a/rust/fuzz_test.go b/rust/fuzz_test.go
index bdcfbbb..f462795 100644
--- a/rust/fuzz_test.go
+++ b/rust/fuzz_test.go
@@ -134,17 +134,24 @@
 			}
 	`)
 
-	fuzz_shared_libtest := ctx.ModuleForTests(t, "fuzz_shared_libtest", "android_arm64_armv8-a_fuzzer").Module().(cc.LinkableInterface)
-	fuzz_static_libtest := ctx.ModuleForTests(t, "fuzz_static_libtest", "android_arm64_armv8-a_fuzzer").Module().(cc.LinkableInterface)
-	fuzz_staticffi_libtest := ctx.ModuleForTests(t, "fuzz_staticffi_libtest", "android_arm64_armv8-a_fuzzer").Module().(cc.LinkableInterface)
+	fuzz_shared_libtest := ctx.ModuleForTests(t, "fuzz_shared_libtest", "android_arm64_armv8-a_fuzzer").Module()
+	fuzz_static_libtest := ctx.ModuleForTests(t, "fuzz_static_libtest", "android_arm64_armv8-a_fuzzer").Module()
+	fuzz_staticffi_libtest := ctx.ModuleForTests(t, "fuzz_staticffi_libtest", "android_arm64_armv8-a_fuzzer").Module()
 
-	if !strings.Contains(fuzz_shared_libtest.FuzzSharedLibraries().String(), ":libcc_transitive_dep.so") {
-		t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_shared ('libcc_transitive_dep'): %#v", fuzz_shared_libtest.FuzzSharedLibraries().String())
+	fuzzSharedLibraries := func(module android.Module) string {
+		if info, ok := android.OtherModuleProvider(ctx, module, cc.LinkableInfoProvider); ok {
+			return info.FuzzSharedLibraries.String()
+		}
+		return ""
 	}
-	if !strings.Contains(fuzz_static_libtest.FuzzSharedLibraries().String(), ":libcc_transitive_dep.so") {
-		t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_static ('libcc_transitive_dep'): %#v", fuzz_static_libtest.FuzzSharedLibraries().String())
+
+	if libs := fuzzSharedLibraries(fuzz_shared_libtest); !strings.Contains(libs, ":libcc_transitive_dep.so") {
+		t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_shared ('libcc_transitive_dep'): %#v", libs)
 	}
-	if !strings.Contains(fuzz_staticffi_libtest.FuzzSharedLibraries().String(), ":libcc_transitive_dep.so") {
-		t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_static ('libcc_transitive_dep'): %#v", fuzz_staticffi_libtest.FuzzSharedLibraries().String())
+	if libs := fuzzSharedLibraries(fuzz_static_libtest); !strings.Contains(libs, ":libcc_transitive_dep.so") {
+		t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_static ('libcc_transitive_dep'): %#v", libs)
+	}
+	if libs := fuzzSharedLibraries(fuzz_staticffi_libtest); !strings.Contains(libs, ":libcc_transitive_dep.so") {
+		t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_static ('libcc_transitive_dep'): %#v", libs)
 	}
 }