Merge commit 'fb3d2d71009af3eb1fc32c5c9a5826ac1fbb1e98' into dev-release Change-Id: I1f5de7705e86c4596d2d5986316ec49d6381a06d
diff --git a/src/main/java/com/android/tools/r8/D8.java b/src/main/java/com/android/tools/r8/D8.java index 8fccc8d..ae6a649 100644 --- a/src/main/java/com/android/tools/r8/D8.java +++ b/src/main/java/com/android/tools/r8/D8.java
@@ -328,7 +328,8 @@ reportSyntheticInformation(appView); if (options.isGeneratingClassFiles()) { - new CfApplicationWriter(appView, marker).write(options.getClassFileConsumer(), inputApp); + new CfApplicationWriter(appView, marker) + .write(options.getClassFileConsumer(), executor, inputApp); } else { ApplicationWriter.create(appView, marker).write(executor, inputApp); }
diff --git a/src/main/java/com/android/tools/r8/GlobalSyntheticsGenerator.java b/src/main/java/com/android/tools/r8/GlobalSyntheticsGenerator.java index 4b2ab5a..f0445dd 100644 --- a/src/main/java/com/android/tools/r8/GlobalSyntheticsGenerator.java +++ b/src/main/java/com/android/tools/r8/GlobalSyntheticsGenerator.java
@@ -135,7 +135,7 @@ } else { assert options.isGeneratingClassFiles(); new CfApplicationWriter(appView, options.getMarker()) - .write(options.getClassFileConsumer(), app); + .write(options.getClassFileConsumer(), executorService, app); } } catch (ExecutionException e) { throw unwrapExecutionException(e);
diff --git a/src/main/java/com/android/tools/r8/L8.java b/src/main/java/com/android/tools/r8/L8.java index 1c1e64c..f744a67 100644 --- a/src/main/java/com/android/tools/r8/L8.java +++ b/src/main/java/com/android/tools/r8/L8.java
@@ -149,7 +149,8 @@ appView)); new GenericSignatureRewriter(appView).run(appView.appInfo().classes(), executor); - new CfApplicationWriter(appView, options.getMarker()).write(options.getClassFileConsumer()); + new CfApplicationWriter(appView, options.getMarker()) + .write(options.getClassFileConsumer(), executor); options.printWarnings(); } catch (ExecutionException e) { throw unwrapExecutionException(e);
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java index 93926dd..46f11fd 100644 --- a/src/main/java/com/android/tools/r8/R8.java +++ b/src/main/java/com/android/tools/r8/R8.java
@@ -222,7 +222,8 @@ Marker marker = options.getMarker(); assert marker != null; if (options.isGeneratingClassFiles()) { - new CfApplicationWriter(appView, marker).write(options.getClassFileConsumer(), inputApp); + new CfApplicationWriter(appView, marker) + .write(options.getClassFileConsumer(), executorService, inputApp); } else { ApplicationWriter.create(appView, marker).write(executorService, inputApp); }
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java index b6c9ae4..52ae388 100644 --- a/src/main/java/com/android/tools/r8/R8Command.java +++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -739,6 +739,7 @@ } private R8Command makeR8Command() { + long created = System.nanoTime(); Reporter reporter = getReporter(); DexItemFactory factory = new DexItemFactory(); List<ProguardConfigurationRule> mainDexKeepRules = @@ -839,7 +840,8 @@ resourceShrinkerConfiguration, keepSpecifications, buildMetadataConsumer, - partialCompilationConfiguration); + partialCompilationConfiguration, + created); if (inputDependencyGraphConsumer != null) { inputDependencyGraphConsumer.finished(); @@ -1062,6 +1064,7 @@ private final ResourceShrinkerConfiguration resourceShrinkerConfiguration; private final Consumer<? super R8BuildMetadata> buildMetadataConsumer; private final R8PartialCompilationConfiguration partialCompilationConfiguration; + private final long created; /** Get a new {@link R8Command.Builder}. */ public static Builder builder() { @@ -1162,7 +1165,8 @@ ResourceShrinkerConfiguration resourceShrinkerConfiguration, List<KeepSpecificationSource> keepSpecifications, Consumer<? super R8BuildMetadata> buildMetadataConsumer, - R8PartialCompilationConfiguration partialCompilationConfiguration) { + R8PartialCompilationConfiguration partialCompilationConfiguration, + long created) { super( inputApp, mode, @@ -1213,6 +1217,7 @@ this.resourceShrinkerConfiguration = resourceShrinkerConfiguration; this.buildMetadataConsumer = buildMetadataConsumer; this.partialCompilationConfiguration = partialCompilationConfiguration; + this.created = created; } private R8Command(boolean printHelp, boolean printVersion) { @@ -1243,6 +1248,7 @@ resourceShrinkerConfiguration = null; buildMetadataConsumer = null; partialCompilationConfiguration = null; + created = -1; } public DexItemFactory getDexItemFactory() { @@ -1267,6 +1273,7 @@ @Override InternalOptions getInternalOptions() { InternalOptions internal = new InternalOptions(getMode(), proguardConfiguration, getReporter()); + internal.created = created; assert !internal.testing.allowOutlinerInterfaceArrayArguments; // Only allow in tests. internal.programConsumer = getProgramConsumer(); internal.setMinApiLevel(AndroidApiLevel.getAndroidApiLevel(getMinApiLevel()));
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java index 9554f4e..55274e8 100644 --- a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java +++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
@@ -213,8 +213,7 @@ return desugaredLibraryCodeToKeep; } - private List<VirtualFile> distribute(ExecutorService executorService) - throws ExecutionException, IOException { + private List<VirtualFile> distribute(ExecutorService executorService) { Collection<DexProgramClass> classes = appView.appInfo().classes(); Collection<DexProgramClass> globalSynthetics = new ArrayList<>(); if (appView.options().intermediate && appView.options().hasGlobalSyntheticsConsumer()) { @@ -452,7 +451,7 @@ options.reporter.failIfPendingErrors(); // Supply info to all additional resource consumers. if (!(programConsumer instanceof ConvertedCfFiles)) { - supplyAdditionalConsumers(appView, virtualFiles); + supplyAdditionalConsumers(appView, executorService, virtualFiles); } } finally { timing.end(); @@ -655,7 +654,8 @@ } @SuppressWarnings("DefaultCharset") - public static void supplyAdditionalConsumers(AppView<?> appView, List<VirtualFile> virtualFiles) { + public static void supplyAdditionalConsumers( + AppView<?> appView, ExecutorService executorService, List<VirtualFile> virtualFiles) { InternalOptions options = appView.options(); Reporter reporter = options.reporter; appView.getArtProfileCollection().supplyConsumers(appView); @@ -711,7 +711,7 @@ if (options.r8BuildMetadataConsumer != null) { assert appView.hasClassHierarchy(); options.r8BuildMetadataConsumer.accept( - BuildMetadataFactory.create(appView.withClassHierarchy(), virtualFiles)); + BuildMetadataFactory.create(appView.withClassHierarchy(), executorService, virtualFiles)); } }
diff --git a/src/main/java/com/android/tools/r8/dex/VirtualFile.java b/src/main/java/com/android/tools/r8/dex/VirtualFile.java index 2d96710..c8f16fc 100644 --- a/src/main/java/com/android/tools/r8/dex/VirtualFile.java +++ b/src/main/java/com/android/tools/r8/dex/VirtualFile.java
@@ -161,6 +161,10 @@ return featureSplit; } + public FeatureSplit getFeatureSplitOrBase() { + return featureSplit != null ? featureSplit : FeatureSplit.BASE; + } + public StartupProfile getStartupProfile() { return startupProfile; }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/analysis/TransferFunction.java b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/analysis/TransferFunction.java index 6e1643e..71b7edb 100644 --- a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/analysis/TransferFunction.java +++ b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/analysis/TransferFunction.java
@@ -4,6 +4,7 @@ package com.android.tools.r8.ir.optimize.classinliner.analysis; +import static com.android.tools.r8.graph.DexProgramClass.asProgramClassOrNull; import static com.android.tools.r8.ir.code.Opcodes.ASSUME; import static com.android.tools.r8.ir.code.Opcodes.CHECK_CAST; import static com.android.tools.r8.ir.code.Opcodes.IF; @@ -394,21 +395,21 @@ : isMaybeEligibleForClassInlining(clazz.asClasspathOrLibraryClass()); } - @SuppressWarnings("ReferenceEquality") private boolean isMaybeEligibleForClassInlining(DexProgramClass clazz) { // We can only class inline parameters that does not inherit from other classpath or library // classes than java.lang.Object. - DexType superType = clazz.getSuperType(); - do { - DexClass superClass = appView.definitionFor(superType); + while (clazz.hasSuperType()) { + DexType superType = clazz.getSuperType(); + if (superType.isIdenticalTo(dexItemFactory.objectType)) { + break; + } + DexProgramClass superClass = asProgramClassOrNull(appView.definitionFor(superType)); if (superClass == null) { return false; } - if (!superClass.isProgramClass()) { - return superClass.getType() == dexItemFactory.objectType; - } - superType = superClass.getSuperType(); - } while (true); + clazz = superClass; + } + return true; } @SuppressWarnings("ReferenceEquality")
diff --git a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java index 20de02a..6ccbf71 100644 --- a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java +++ b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
@@ -66,6 +66,7 @@ import java.util.Comparator; import java.util.List; import java.util.Optional; +import java.util.concurrent.ExecutorService; import java.util.function.Consumer; import java.util.function.Predicate; import org.objectweb.asm.AnnotationVisitor; @@ -113,15 +114,16 @@ return appView.getNamingLens(); } - public void write(ClassFileConsumer consumer) { + public void write(ClassFileConsumer consumer, ExecutorService executorService) { assert !options.hasMappingFileSupport(); - write(consumer, null); + write(consumer, executorService, null); } - public void write(ClassFileConsumer consumer, AndroidApp inputApp) { + public void write( + ClassFileConsumer consumer, ExecutorService executorService, AndroidApp inputApp) { application.timing.begin("CfApplicationWriter.write"); try { - writeApplication(inputApp, consumer); + writeApplication(inputApp, consumer, executorService); } finally { application.timing.end(); } @@ -138,7 +140,8 @@ return true; } - private void writeApplication(AndroidApp inputApp, ClassFileConsumer consumer) { + private void writeApplication( + AndroidApp inputApp, ClassFileConsumer consumer, ExecutorService executorService) { ProguardMapId proguardMapId = null; if (options.hasMappingFileSupport()) { assert marker.isPresent(); @@ -187,7 +190,7 @@ } globalsConsumer.finished(appView); } - ApplicationWriter.supplyAdditionalConsumers(appView, Collections.emptyList()); + ApplicationWriter.supplyAdditionalConsumers(appView, executorService, Collections.emptyList()); } private void writeClassCatchingErrors(
diff --git a/src/main/java/com/android/tools/r8/metadata/R8ApiModelingOptions.java b/src/main/java/com/android/tools/r8/metadata/D8ApiModelingMetadata.java similarity index 88% rename from src/main/java/com/android/tools/r8/metadata/R8ApiModelingOptions.java rename to src/main/java/com/android/tools/r8/metadata/D8ApiModelingMetadata.java index 8d175f3..cc73c5b 100644 --- a/src/main/java/com/android/tools/r8/metadata/R8ApiModelingOptions.java +++ b/src/main/java/com/android/tools/r8/metadata/D8ApiModelingMetadata.java
@@ -6,4 +6,4 @@ import com.android.tools.r8.keepanno.annotations.KeepForApi; @KeepForApi -public interface R8ApiModelingOptions {} +public interface D8ApiModelingMetadata {}
diff --git a/src/main/java/com/android/tools/r8/metadata/D8ApiModelingOptions.java b/src/main/java/com/android/tools/r8/metadata/D8ApiModelingOptions.java deleted file mode 100644 index 4531502..0000000 --- a/src/main/java/com/android/tools/r8/metadata/D8ApiModelingOptions.java +++ /dev/null
@@ -1,9 +0,0 @@ -// Copyright (c) 2024, the R8 project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. -package com.android.tools.r8.metadata; - -import com.android.tools.r8.keepanno.annotations.KeepForApi; - -@KeepForApi -public interface D8ApiModelingOptions {}
diff --git a/src/main/java/com/android/tools/r8/metadata/D8BuildMetadata.java b/src/main/java/com/android/tools/r8/metadata/D8BuildMetadata.java index 765c05c..2008658 100644 --- a/src/main/java/com/android/tools/r8/metadata/D8BuildMetadata.java +++ b/src/main/java/com/android/tools/r8/metadata/D8BuildMetadata.java
@@ -4,10 +4,10 @@ package com.android.tools.r8.metadata; import com.android.tools.r8.keepanno.annotations.KeepForApi; -import com.android.tools.r8.metadata.impl.D8ApiModelingOptionsImpl; +import com.android.tools.r8.metadata.impl.D8ApiModelingMetadataImpl; import com.android.tools.r8.metadata.impl.D8BuildMetadataImpl; -import com.android.tools.r8.metadata.impl.D8LibraryDesugaringOptionsImpl; -import com.android.tools.r8.metadata.impl.D8OptionsImpl; +import com.android.tools.r8.metadata.impl.D8LibraryDesugaringMetadataImpl; +import com.android.tools.r8.metadata.impl.D8OptionsMetadataImpl; import com.google.gson.GsonBuilder; import com.google.gson.JsonDeserializer; @@ -17,11 +17,11 @@ static D8BuildMetadata fromJson(String json) { return new GsonBuilder() .excludeFieldsWithoutExposeAnnotation() - .registerTypeAdapter(D8Options.class, deserializeTo(D8OptionsImpl.class)) + .registerTypeAdapter(D8OptionsMetadata.class, deserializeTo(D8OptionsMetadataImpl.class)) .registerTypeAdapter( - D8ApiModelingOptions.class, deserializeTo(D8ApiModelingOptionsImpl.class)) + D8ApiModelingMetadata.class, deserializeTo(D8ApiModelingMetadataImpl.class)) .registerTypeAdapter( - D8LibraryDesugaringOptions.class, deserializeTo(D8LibraryDesugaringOptionsImpl.class)) + D8LibraryDesugaringMetadata.class, deserializeTo(D8LibraryDesugaringMetadataImpl.class)) .create() .fromJson(json, D8BuildMetadataImpl.class); } @@ -30,7 +30,7 @@ return (element, type, context) -> context.deserialize(element, implClass); } - D8Options getOptions(); + D8OptionsMetadata getOptions(); String getVersion();
diff --git a/src/main/java/com/android/tools/r8/metadata/D8LibraryDesugaringOptions.java b/src/main/java/com/android/tools/r8/metadata/D8LibraryDesugaringMetadata.java similarity index 67% rename from src/main/java/com/android/tools/r8/metadata/D8LibraryDesugaringOptions.java rename to src/main/java/com/android/tools/r8/metadata/D8LibraryDesugaringMetadata.java index 30adb4a..8cc342c 100644 --- a/src/main/java/com/android/tools/r8/metadata/D8LibraryDesugaringOptions.java +++ b/src/main/java/com/android/tools/r8/metadata/D8LibraryDesugaringMetadata.java
@@ -4,7 +4,7 @@ package com.android.tools.r8.metadata; import com.android.tools.r8.keepanno.annotations.KeepForApi; -import com.android.tools.r8.metadata.impl.D8R8LibraryDesugaringOptions; +import com.android.tools.r8.metadata.impl.D8R8LibraryDesugaringMetadata; @KeepForApi -public interface D8LibraryDesugaringOptions extends D8R8LibraryDesugaringOptions {} +public interface D8LibraryDesugaringMetadata extends D8R8LibraryDesugaringMetadata {}
diff --git a/src/main/java/com/android/tools/r8/metadata/D8Options.java b/src/main/java/com/android/tools/r8/metadata/D8Options.java deleted file mode 100644 index b09f4b4..0000000 --- a/src/main/java/com/android/tools/r8/metadata/D8Options.java +++ /dev/null
@@ -1,10 +0,0 @@ -// Copyright (c) 2024, the R8 project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. -package com.android.tools.r8.metadata; - -import com.android.tools.r8.keepanno.annotations.KeepForApi; -import com.android.tools.r8.metadata.impl.D8R8Options; - -@KeepForApi -public interface D8Options extends D8R8Options<D8ApiModelingOptions, D8LibraryDesugaringOptions> {}
diff --git a/src/main/java/com/android/tools/r8/metadata/D8LibraryDesugaringOptions.java b/src/main/java/com/android/tools/r8/metadata/D8OptionsMetadata.java similarity index 63% copy from src/main/java/com/android/tools/r8/metadata/D8LibraryDesugaringOptions.java copy to src/main/java/com/android/tools/r8/metadata/D8OptionsMetadata.java index 30adb4a..0b9c4f9 100644 --- a/src/main/java/com/android/tools/r8/metadata/D8LibraryDesugaringOptions.java +++ b/src/main/java/com/android/tools/r8/metadata/D8OptionsMetadata.java
@@ -4,7 +4,8 @@ package com.android.tools.r8.metadata; import com.android.tools.r8.keepanno.annotations.KeepForApi; -import com.android.tools.r8.metadata.impl.D8R8LibraryDesugaringOptions; +import com.android.tools.r8.metadata.impl.D8R8OptionsMetadata; @KeepForApi -public interface D8LibraryDesugaringOptions extends D8R8LibraryDesugaringOptions {} +public interface D8OptionsMetadata + extends D8R8OptionsMetadata<D8ApiModelingMetadata, D8LibraryDesugaringMetadata> {}
diff --git a/src/main/java/com/android/tools/r8/metadata/R8ApiModelingOptions.java b/src/main/java/com/android/tools/r8/metadata/R8ApiModelingMetadata.java similarity index 88% copy from src/main/java/com/android/tools/r8/metadata/R8ApiModelingOptions.java copy to src/main/java/com/android/tools/r8/metadata/R8ApiModelingMetadata.java index 8d175f3..19c62b1 100644 --- a/src/main/java/com/android/tools/r8/metadata/R8ApiModelingOptions.java +++ b/src/main/java/com/android/tools/r8/metadata/R8ApiModelingMetadata.java
@@ -6,4 +6,4 @@ import com.android.tools.r8.keepanno.annotations.KeepForApi; @KeepForApi -public interface R8ApiModelingOptions {} +public interface R8ApiModelingMetadata {}
diff --git a/src/main/java/com/android/tools/r8/metadata/R8ApiModelingOptions.java b/src/main/java/com/android/tools/r8/metadata/R8BaselineProfileRewritingMetadata.java similarity index 85% copy from src/main/java/com/android/tools/r8/metadata/R8ApiModelingOptions.java copy to src/main/java/com/android/tools/r8/metadata/R8BaselineProfileRewritingMetadata.java index 8d175f3..0b24945 100644 --- a/src/main/java/com/android/tools/r8/metadata/R8ApiModelingOptions.java +++ b/src/main/java/com/android/tools/r8/metadata/R8BaselineProfileRewritingMetadata.java
@@ -6,4 +6,4 @@ import com.android.tools.r8.keepanno.annotations.KeepForApi; @KeepForApi -public interface R8ApiModelingOptions {} +public interface R8BaselineProfileRewritingMetadata {}
diff --git a/src/main/java/com/android/tools/r8/metadata/R8BaselineProfileRewritingOptions.java b/src/main/java/com/android/tools/r8/metadata/R8BaselineProfileRewritingOptions.java deleted file mode 100644 index 7598aee..0000000 --- a/src/main/java/com/android/tools/r8/metadata/R8BaselineProfileRewritingOptions.java +++ /dev/null
@@ -1,9 +0,0 @@ -// Copyright (c) 2024, the R8 project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. -package com.android.tools.r8.metadata; - -import com.android.tools.r8.keepanno.annotations.KeepForApi; - -@KeepForApi -public interface R8BaselineProfileRewritingOptions {}
diff --git a/src/main/java/com/android/tools/r8/metadata/R8BuildMetadata.java b/src/main/java/com/android/tools/r8/metadata/R8BuildMetadata.java index c3f13b0..153dd1e 100644 --- a/src/main/java/com/android/tools/r8/metadata/R8BuildMetadata.java +++ b/src/main/java/com/android/tools/r8/metadata/R8BuildMetadata.java
@@ -4,14 +4,19 @@ package com.android.tools.r8.metadata; import com.android.tools.r8.keepanno.annotations.KeepForApi; -import com.android.tools.r8.metadata.impl.R8ApiModelingOptionsImpl; -import com.android.tools.r8.metadata.impl.R8BaselineProfileRewritingOptionsImpl; +import com.android.tools.r8.metadata.impl.R8ApiModelingMetadataImpl; +import com.android.tools.r8.metadata.impl.R8BaselineProfileRewritingMetadataImpl; import com.android.tools.r8.metadata.impl.R8BuildMetadataImpl; -import com.android.tools.r8.metadata.impl.R8KeepAttributesOptionsImpl; -import com.android.tools.r8.metadata.impl.R8LibraryDesugaringOptionsImpl; -import com.android.tools.r8.metadata.impl.R8OptionsImpl; -import com.android.tools.r8.metadata.impl.R8ResourceOptimizationOptionsImpl; -import com.android.tools.r8.metadata.impl.R8StartupOptimizationOptionsImpl; +import com.android.tools.r8.metadata.impl.R8CompilationMetadataImpl; +import com.android.tools.r8.metadata.impl.R8DexFileMetadataImpl; +import com.android.tools.r8.metadata.impl.R8FeatureSplitMetadataImpl; +import com.android.tools.r8.metadata.impl.R8FeatureSplitsMetadataImpl; +import com.android.tools.r8.metadata.impl.R8KeepAttributesMetadataImpl; +import com.android.tools.r8.metadata.impl.R8LibraryDesugaringMetadataImpl; +import com.android.tools.r8.metadata.impl.R8OptionsMetadataImpl; +import com.android.tools.r8.metadata.impl.R8ResourceOptimizationMetadataImpl; +import com.android.tools.r8.metadata.impl.R8StartupOptimizationMetadataImpl; +import com.android.tools.r8.metadata.impl.R8StatsMetadataImpl; import com.google.gson.GsonBuilder; import com.google.gson.JsonDeserializer; import java.util.List; @@ -22,22 +27,30 @@ static R8BuildMetadata fromJson(String json) { return new GsonBuilder() .excludeFieldsWithoutExposeAnnotation() - .registerTypeAdapter(R8Options.class, deserializeTo(R8OptionsImpl.class)) + .registerTypeAdapter(R8OptionsMetadata.class, deserializeTo(R8OptionsMetadataImpl.class)) .registerTypeAdapter( - R8ApiModelingOptions.class, deserializeTo(R8ApiModelingOptionsImpl.class)) + R8ApiModelingMetadata.class, deserializeTo(R8ApiModelingMetadataImpl.class)) .registerTypeAdapter( - R8BaselineProfileRewritingOptions.class, - deserializeTo(R8BaselineProfileRewritingOptionsImpl.class)) + R8BaselineProfileRewritingMetadata.class, + deserializeTo(R8BaselineProfileRewritingMetadataImpl.class)) .registerTypeAdapter( - R8KeepAttributesOptions.class, deserializeTo(R8KeepAttributesOptionsImpl.class)) + R8CompilationMetadata.class, deserializeTo(R8CompilationMetadataImpl.class)) + .registerTypeAdapter(R8DexFileMetadata.class, deserializeTo(R8DexFileMetadataImpl.class)) + .registerTypeAdapter(R8StatsMetadata.class, deserializeTo(R8StatsMetadataImpl.class)) .registerTypeAdapter( - R8LibraryDesugaringOptions.class, deserializeTo(R8LibraryDesugaringOptionsImpl.class)) + R8FeatureSplitMetadata.class, deserializeTo(R8FeatureSplitMetadataImpl.class)) .registerTypeAdapter( - R8ResourceOptimizationOptions.class, - deserializeTo(R8ResourceOptimizationOptionsImpl.class)) + R8FeatureSplitsMetadata.class, deserializeTo(R8FeatureSplitsMetadataImpl.class)) .registerTypeAdapter( - R8StartupOptimizationOptions.class, - deserializeTo(R8StartupOptimizationOptionsImpl.class)) + R8KeepAttributesMetadata.class, deserializeTo(R8KeepAttributesMetadataImpl.class)) + .registerTypeAdapter( + R8LibraryDesugaringMetadata.class, deserializeTo(R8LibraryDesugaringMetadataImpl.class)) + .registerTypeAdapter( + R8ResourceOptimizationMetadata.class, + deserializeTo(R8ResourceOptimizationMetadataImpl.class)) + .registerTypeAdapter( + R8StartupOptimizationMetadata.class, + deserializeTo(R8StartupOptimizationMetadataImpl.class)) .create() .fromJson(json, R8BuildMetadataImpl.class); } @@ -46,27 +59,36 @@ return (element, type, context) -> context.deserialize(element, implClass); } - R8Options getOptions(); + R8OptionsMetadata getOptionsMetadata(); /** * @return null if baseline profile rewriting is disabled. */ - R8BaselineProfileRewritingOptions getBaselineProfileRewritingOptions(); + R8BaselineProfileRewritingMetadata getBaselineProfileRewritingMetadata(); + + R8CompilationMetadata getCompilationMetadata(); /** * @return null if not compiling to dex. */ - List<String> getDexChecksums(); + List<R8DexFileMetadata> getDexFilesMetadata(); + + /** + * @return null if not using feature splits. + */ + R8FeatureSplitsMetadata getFeatureSplitsMetadata(); /** * @return null if resource optimization is disabled. */ - R8ResourceOptimizationOptions getResourceOptimizationOptions(); + R8ResourceOptimizationMetadata getResourceOptimizationMetadata(); /** * @return null if startup optimization is disabled. */ - R8StartupOptimizationOptions getStartupOptizationOptions(); + R8StartupOptimizationMetadata getStartupOptizationOptions(); + + R8StatsMetadata getStatsMetadata(); String getVersion();
diff --git a/src/main/java/com/android/tools/r8/metadata/R8ResourceOptimizationOptions.java b/src/main/java/com/android/tools/r8/metadata/R8CompilationMetadata.java similarity index 77% copy from src/main/java/com/android/tools/r8/metadata/R8ResourceOptimizationOptions.java copy to src/main/java/com/android/tools/r8/metadata/R8CompilationMetadata.java index 693286e..a4ce3aa 100644 --- a/src/main/java/com/android/tools/r8/metadata/R8ResourceOptimizationOptions.java +++ b/src/main/java/com/android/tools/r8/metadata/R8CompilationMetadata.java
@@ -6,7 +6,9 @@ import com.android.tools.r8.keepanno.annotations.KeepForApi; @KeepForApi -public interface R8ResourceOptimizationOptions { +public interface R8CompilationMetadata { - boolean isOptimizedShrinkingEnabled(); + long getBuildTime(); + + long getNumberOfThreads(); }
diff --git a/src/main/java/com/android/tools/r8/metadata/R8DexFileMetadata.java b/src/main/java/com/android/tools/r8/metadata/R8DexFileMetadata.java new file mode 100644 index 0000000..fc841d0 --- /dev/null +++ b/src/main/java/com/android/tools/r8/metadata/R8DexFileMetadata.java
@@ -0,0 +1,21 @@ +// Copyright (c) 2024, the R8 project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. +package com.android.tools.r8.metadata; + +import com.android.tools.r8.keepanno.annotations.KeepForApi; + +@KeepForApi +public interface R8DexFileMetadata { + + /** + * Returns the SHA-256 checksum of the entire dex file. + * + * <p>This can be used to check if the given dex file has been tampered with after compilation. + * + * <p>Note: This differs from the checksum in the dex format, as the checksum embedded in the dex + * is the adler32 checksum of the dex file excluding the magic value and the checksum itself. See + * also https://source.android.com/docs/core/runtime/dex-format. + */ + String getChecksum(); +}
diff --git a/src/main/java/com/android/tools/r8/metadata/R8ResourceOptimizationOptions.java b/src/main/java/com/android/tools/r8/metadata/R8FeatureSplitMetadata.java similarity index 74% copy from src/main/java/com/android/tools/r8/metadata/R8ResourceOptimizationOptions.java copy to src/main/java/com/android/tools/r8/metadata/R8FeatureSplitMetadata.java index 693286e..f9c5d47 100644 --- a/src/main/java/com/android/tools/r8/metadata/R8ResourceOptimizationOptions.java +++ b/src/main/java/com/android/tools/r8/metadata/R8FeatureSplitMetadata.java
@@ -4,9 +4,10 @@ package com.android.tools.r8.metadata; import com.android.tools.r8.keepanno.annotations.KeepForApi; +import java.util.List; @KeepForApi -public interface R8ResourceOptimizationOptions { +public interface R8FeatureSplitMetadata { - boolean isOptimizedShrinkingEnabled(); + List<R8DexFileMetadata> getDexFilesMetadata(); }
diff --git a/src/main/java/com/android/tools/r8/metadata/D8LibraryDesugaringOptions.java b/src/main/java/com/android/tools/r8/metadata/R8FeatureSplitsMetadata.java similarity index 67% copy from src/main/java/com/android/tools/r8/metadata/D8LibraryDesugaringOptions.java copy to src/main/java/com/android/tools/r8/metadata/R8FeatureSplitsMetadata.java index 30adb4a..66fd1e2 100644 --- a/src/main/java/com/android/tools/r8/metadata/D8LibraryDesugaringOptions.java +++ b/src/main/java/com/android/tools/r8/metadata/R8FeatureSplitsMetadata.java
@@ -4,7 +4,12 @@ package com.android.tools.r8.metadata; import com.android.tools.r8.keepanno.annotations.KeepForApi; -import com.android.tools.r8.metadata.impl.D8R8LibraryDesugaringOptions; +import java.util.List; @KeepForApi -public interface D8LibraryDesugaringOptions extends D8R8LibraryDesugaringOptions {} +public interface R8FeatureSplitsMetadata { + + List<R8FeatureSplitMetadata> getFeatureSplits(); + + boolean isIsolatedSplitsEnabled(); +}
diff --git a/src/main/java/com/android/tools/r8/metadata/R8KeepAttributesOptions.java b/src/main/java/com/android/tools/r8/metadata/R8KeepAttributesMetadata.java similarity index 95% rename from src/main/java/com/android/tools/r8/metadata/R8KeepAttributesOptions.java rename to src/main/java/com/android/tools/r8/metadata/R8KeepAttributesMetadata.java index b590c7e..fa58986 100644 --- a/src/main/java/com/android/tools/r8/metadata/R8KeepAttributesOptions.java +++ b/src/main/java/com/android/tools/r8/metadata/R8KeepAttributesMetadata.java
@@ -6,7 +6,7 @@ import com.android.tools.r8.keepanno.annotations.KeepForApi; @KeepForApi -public interface R8KeepAttributesOptions { +public interface R8KeepAttributesMetadata { boolean isAnnotationDefaultKept();
diff --git a/src/main/java/com/android/tools/r8/metadata/D8LibraryDesugaringOptions.java b/src/main/java/com/android/tools/r8/metadata/R8LibraryDesugaringMetadata.java similarity index 67% copy from src/main/java/com/android/tools/r8/metadata/D8LibraryDesugaringOptions.java copy to src/main/java/com/android/tools/r8/metadata/R8LibraryDesugaringMetadata.java index 30adb4a..c577d7d 100644 --- a/src/main/java/com/android/tools/r8/metadata/D8LibraryDesugaringOptions.java +++ b/src/main/java/com/android/tools/r8/metadata/R8LibraryDesugaringMetadata.java
@@ -4,7 +4,7 @@ package com.android.tools.r8.metadata; import com.android.tools.r8.keepanno.annotations.KeepForApi; -import com.android.tools.r8.metadata.impl.D8R8LibraryDesugaringOptions; +import com.android.tools.r8.metadata.impl.D8R8LibraryDesugaringMetadata; @KeepForApi -public interface D8LibraryDesugaringOptions extends D8R8LibraryDesugaringOptions {} +public interface R8LibraryDesugaringMetadata extends D8R8LibraryDesugaringMetadata {}
diff --git a/src/main/java/com/android/tools/r8/metadata/R8LibraryDesugaringOptions.java b/src/main/java/com/android/tools/r8/metadata/R8LibraryDesugaringOptions.java deleted file mode 100644 index 6a9df33..0000000 --- a/src/main/java/com/android/tools/r8/metadata/R8LibraryDesugaringOptions.java +++ /dev/null
@@ -1,10 +0,0 @@ -// Copyright (c) 2024, the R8 project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. -package com.android.tools.r8.metadata; - -import com.android.tools.r8.keepanno.annotations.KeepForApi; -import com.android.tools.r8.metadata.impl.D8R8LibraryDesugaringOptions; - -@KeepForApi -public interface R8LibraryDesugaringOptions extends D8R8LibraryDesugaringOptions {}
diff --git a/src/main/java/com/android/tools/r8/metadata/R8Options.java b/src/main/java/com/android/tools/r8/metadata/R8OptionsMetadata.java similarity index 79% rename from src/main/java/com/android/tools/r8/metadata/R8Options.java rename to src/main/java/com/android/tools/r8/metadata/R8OptionsMetadata.java index 697af39..c9279c2 100644 --- a/src/main/java/com/android/tools/r8/metadata/R8Options.java +++ b/src/main/java/com/android/tools/r8/metadata/R8OptionsMetadata.java
@@ -6,22 +6,22 @@ import com.android.tools.r8.keepanno.annotations.KeepForApi; @KeepForApi -public interface R8Options { +public interface R8OptionsMetadata { /** * @return null if API modeling is disabled. */ - R8ApiModelingOptions getApiModelingOptions(); + R8ApiModelingMetadata getApiModelingMetadata(); /** * @return null if no ProGuard configuration is provided. */ - R8KeepAttributesOptions getKeepAttributesOptions(); + R8KeepAttributesMetadata getKeepAttributesMetadata(); /** * @return null if library desugaring is disabled. */ - R8LibraryDesugaringOptions getLibraryDesugaringOptions(); + R8LibraryDesugaringMetadata getLibraryDesugaringMetadata(); int getMinApiLevel();
diff --git a/src/main/java/com/android/tools/r8/metadata/R8ResourceOptimizationOptions.java b/src/main/java/com/android/tools/r8/metadata/R8ResourceOptimizationMetadata.java similarity index 87% rename from src/main/java/com/android/tools/r8/metadata/R8ResourceOptimizationOptions.java rename to src/main/java/com/android/tools/r8/metadata/R8ResourceOptimizationMetadata.java index 693286e..1dd29f1 100644 --- a/src/main/java/com/android/tools/r8/metadata/R8ResourceOptimizationOptions.java +++ b/src/main/java/com/android/tools/r8/metadata/R8ResourceOptimizationMetadata.java
@@ -6,7 +6,7 @@ import com.android.tools.r8.keepanno.annotations.KeepForApi; @KeepForApi -public interface R8ResourceOptimizationOptions { +public interface R8ResourceOptimizationMetadata { boolean isOptimizedShrinkingEnabled(); }
diff --git a/src/main/java/com/android/tools/r8/metadata/R8StartupOptimizationOptions.java b/src/main/java/com/android/tools/r8/metadata/R8StartupOptimizationMetadata.java similarity index 87% rename from src/main/java/com/android/tools/r8/metadata/R8StartupOptimizationOptions.java rename to src/main/java/com/android/tools/r8/metadata/R8StartupOptimizationMetadata.java index a57b01e..608d05f 100644 --- a/src/main/java/com/android/tools/r8/metadata/R8StartupOptimizationOptions.java +++ b/src/main/java/com/android/tools/r8/metadata/R8StartupOptimizationMetadata.java
@@ -6,7 +6,7 @@ import com.android.tools.r8.keepanno.annotations.KeepForApi; @KeepForApi -public interface R8StartupOptimizationOptions { +public interface R8StartupOptimizationMetadata { int getNumberOfStartupDexFiles(); }
diff --git a/src/main/java/com/android/tools/r8/metadata/R8ApiModelingOptions.java b/src/main/java/com/android/tools/r8/metadata/R8StatsMetadata.java similarity index 68% copy from src/main/java/com/android/tools/r8/metadata/R8ApiModelingOptions.java copy to src/main/java/com/android/tools/r8/metadata/R8StatsMetadata.java index 8d175f3..6b446ba 100644 --- a/src/main/java/com/android/tools/r8/metadata/R8ApiModelingOptions.java +++ b/src/main/java/com/android/tools/r8/metadata/R8StatsMetadata.java
@@ -6,4 +6,11 @@ import com.android.tools.r8.keepanno.annotations.KeepForApi; @KeepForApi -public interface R8ApiModelingOptions {} +public interface R8StatsMetadata { + + float getNoObfuscationPercentage(); + + float getNoOptimizationPercentage(); + + float getNoShrinkingPercentage(); +}
diff --git a/src/main/java/com/android/tools/r8/metadata/impl/BuildMetadataFactory.java b/src/main/java/com/android/tools/r8/metadata/impl/BuildMetadataFactory.java index 69e906c..e40691b 100644 --- a/src/main/java/com/android/tools/r8/metadata/impl/BuildMetadataFactory.java +++ b/src/main/java/com/android/tools/r8/metadata/impl/BuildMetadataFactory.java
@@ -3,6 +3,9 @@ // BSD-style license that can be found in the LICENSE file. package com.android.tools.r8.metadata.impl; +import static com.android.tools.r8.utils.MapUtils.ignoreKey; + +import com.android.tools.r8.FeatureSplit; import com.android.tools.r8.Version; import com.android.tools.r8.dex.VirtualFile; import com.android.tools.r8.graph.AppInfo; @@ -11,27 +14,51 @@ import com.android.tools.r8.metadata.D8BuildMetadata; import com.android.tools.r8.metadata.R8BuildMetadata; import com.android.tools.r8.utils.InternalOptions; +import java.util.ArrayList; +import java.util.Collections; +import java.util.IdentityHashMap; import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutorService; public class BuildMetadataFactory { public static D8BuildMetadata create(AppView<AppInfo> appView) { return D8BuildMetadataImpl.builder() - .setOptions(new D8OptionsImpl(appView.options())) + .setOptions(new D8OptionsMetadataImpl(appView.options())) .setVersion(Version.LABEL) .build(); } public static R8BuildMetadata create( - AppView<? extends AppInfoWithClassHierarchy> appView, List<VirtualFile> virtualFiles) { + AppView<? extends AppInfoWithClassHierarchy> appView, + ExecutorService executorService, + List<VirtualFile> virtualFiles) { + Map<FeatureSplit, List<VirtualFile>> virtualFilesForFeatureSplit = new IdentityHashMap<>(); + for (VirtualFile virtualFile : virtualFiles) { + FeatureSplit featureSplit = virtualFile.getFeatureSplitOrBase(); + virtualFilesForFeatureSplit + .computeIfAbsent(featureSplit, ignoreKey(ArrayList::new)) + .add(virtualFile); + } + List<VirtualFile> baseVirtualFiles = + virtualFilesForFeatureSplit.getOrDefault(FeatureSplit.BASE, Collections.emptyList()); InternalOptions options = appView.options(); return R8BuildMetadataImpl.builder() - .setOptions(new R8OptionsImpl(options)) - .setBaselineProfileRewritingOptions(R8BaselineProfileRewritingOptionsImpl.create(options)) - .applyIf(options.isGeneratingDex(), builder -> builder.setDexChecksums(virtualFiles)) - .setResourceOptimizationOptions(R8ResourceOptimizationOptionsImpl.create(options)) + .setOptions(new R8OptionsMetadataImpl(options)) + .setBaselineProfileRewritingOptions(R8BaselineProfileRewritingMetadataImpl.create(options)) + .setCompilationInfo(R8CompilationMetadataImpl.create(appView, executorService)) + .applyIf( + options.isGeneratingDex(), builder -> builder.setDexFilesMetadata(baseVirtualFiles)) + .applyIf( + options.hasFeatureSplitConfiguration(), + builder -> + builder.setFeatureSplitsMetadata( + R8FeatureSplitsMetadataImpl.create(appView, virtualFilesForFeatureSplit))) + .setResourceOptimizationOptions(R8ResourceOptimizationMetadataImpl.create(options)) .setStartupOptimizationOptions( - R8StartupOptimizationOptionsImpl.create(options, virtualFiles)) + R8StartupOptimizationMetadataImpl.create(options, baseVirtualFiles)) + .setStatsMetadata(R8StatsMetadataImpl.create(appView)) .setVersion(Version.LABEL) .build(); }
diff --git a/src/main/java/com/android/tools/r8/metadata/impl/R8ApiModelingOptionsImpl.java b/src/main/java/com/android/tools/r8/metadata/impl/D8ApiModelingMetadataImpl.java similarity index 79% copy from src/main/java/com/android/tools/r8/metadata/impl/R8ApiModelingOptionsImpl.java copy to src/main/java/com/android/tools/r8/metadata/impl/D8ApiModelingMetadataImpl.java index c1ed920..4f252c3 100644 --- a/src/main/java/com/android/tools/r8/metadata/impl/R8ApiModelingOptionsImpl.java +++ b/src/main/java/com/android/tools/r8/metadata/impl/D8ApiModelingMetadataImpl.java
@@ -8,7 +8,7 @@ import com.android.tools.r8.keepanno.annotations.KeepConstraint; import com.android.tools.r8.keepanno.annotations.KeepItemKind; import com.android.tools.r8.keepanno.annotations.UsedByReflection; -import com.android.tools.r8.metadata.R8ApiModelingOptions; +import com.android.tools.r8.metadata.D8ApiModelingMetadata; import com.android.tools.r8.utils.InternalOptions; import com.google.gson.annotations.SerializedName; @@ -19,13 +19,13 @@ kind = KeepItemKind.CLASS_AND_FIELDS, fieldAccess = {FieldAccessFlags.PRIVATE}, fieldAnnotatedByClassConstant = SerializedName.class) -public class R8ApiModelingOptionsImpl implements R8ApiModelingOptions { +public class D8ApiModelingMetadataImpl implements D8ApiModelingMetadata { - private R8ApiModelingOptionsImpl() {} + private D8ApiModelingMetadataImpl() {} - public static R8ApiModelingOptionsImpl create(InternalOptions options) { + public static D8ApiModelingMetadataImpl create(InternalOptions options) { return options.apiModelingOptions().enableLibraryApiModeling - ? new R8ApiModelingOptionsImpl() + ? new D8ApiModelingMetadataImpl() : null; } }
diff --git a/src/main/java/com/android/tools/r8/metadata/impl/D8ApiModelingOptionsImpl.java b/src/main/java/com/android/tools/r8/metadata/impl/D8ApiModelingOptionsImpl.java deleted file mode 100644 index 64a6302..0000000 --- a/src/main/java/com/android/tools/r8/metadata/impl/D8ApiModelingOptionsImpl.java +++ /dev/null
@@ -1,31 +0,0 @@ -// Copyright (c) 2024, the R8 project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. -package com.android.tools.r8.metadata.impl; - -import com.android.tools.r8.keepanno.annotations.AnnotationPattern; -import com.android.tools.r8.keepanno.annotations.FieldAccessFlags; -import com.android.tools.r8.keepanno.annotations.KeepConstraint; -import com.android.tools.r8.keepanno.annotations.KeepItemKind; -import com.android.tools.r8.keepanno.annotations.UsedByReflection; -import com.android.tools.r8.metadata.D8ApiModelingOptions; -import com.android.tools.r8.utils.InternalOptions; -import com.google.gson.annotations.SerializedName; - -@UsedByReflection( - description = "Keep and preserve @SerializedName for correct (de)serialization", - constraints = {KeepConstraint.LOOKUP}, - constrainAnnotations = @AnnotationPattern(constant = SerializedName.class), - kind = KeepItemKind.CLASS_AND_FIELDS, - fieldAccess = {FieldAccessFlags.PRIVATE}, - fieldAnnotatedByClassConstant = SerializedName.class) -public class D8ApiModelingOptionsImpl implements D8ApiModelingOptions { - - private D8ApiModelingOptionsImpl() {} - - public static D8ApiModelingOptionsImpl create(InternalOptions options) { - return options.apiModelingOptions().enableLibraryApiModeling - ? new D8ApiModelingOptionsImpl() - : null; - } -}
diff --git a/src/main/java/com/android/tools/r8/metadata/impl/D8BuildMetadataImpl.java b/src/main/java/com/android/tools/r8/metadata/impl/D8BuildMetadataImpl.java index 9f4bd36..22b91ed 100644 --- a/src/main/java/com/android/tools/r8/metadata/impl/D8BuildMetadataImpl.java +++ b/src/main/java/com/android/tools/r8/metadata/impl/D8BuildMetadataImpl.java
@@ -9,7 +9,7 @@ import com.android.tools.r8.keepanno.annotations.KeepItemKind; import com.android.tools.r8.keepanno.annotations.UsedByReflection; import com.android.tools.r8.metadata.D8BuildMetadata; -import com.android.tools.r8.metadata.D8Options; +import com.android.tools.r8.metadata.D8OptionsMetadata; import com.google.gson.Gson; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; @@ -25,13 +25,13 @@ @Expose @SerializedName("options") - private final D8Options options; + private final D8OptionsMetadata options; @Expose @SerializedName("version") private final String version; - public D8BuildMetadataImpl(D8Options options, String version) { + public D8BuildMetadataImpl(D8OptionsMetadata options, String version) { this.options = options; this.version = version; } @@ -41,7 +41,7 @@ } @Override - public D8Options getOptions() { + public D8OptionsMetadata getOptions() { return options; } @@ -57,10 +57,10 @@ public static class Builder { - private D8Options options; + private D8OptionsMetadata options; private String version; - public Builder setOptions(D8Options options) { + public Builder setOptions(D8OptionsMetadata options) { this.options = options; return this; }
diff --git a/src/main/java/com/android/tools/r8/metadata/impl/R8LibraryDesugaringOptionsImpl.java b/src/main/java/com/android/tools/r8/metadata/impl/D8LibraryDesugaringMetadataImpl.java similarity index 74% copy from src/main/java/com/android/tools/r8/metadata/impl/R8LibraryDesugaringOptionsImpl.java copy to src/main/java/com/android/tools/r8/metadata/impl/D8LibraryDesugaringMetadataImpl.java index cad11e6..4b61718 100644 --- a/src/main/java/com/android/tools/r8/metadata/impl/R8LibraryDesugaringOptionsImpl.java +++ b/src/main/java/com/android/tools/r8/metadata/impl/D8LibraryDesugaringMetadataImpl.java
@@ -8,7 +8,7 @@ import com.android.tools.r8.keepanno.annotations.KeepConstraint; import com.android.tools.r8.keepanno.annotations.KeepItemKind; import com.android.tools.r8.keepanno.annotations.UsedByReflection; -import com.android.tools.r8.metadata.R8LibraryDesugaringOptions; +import com.android.tools.r8.metadata.D8LibraryDesugaringMetadata; import com.android.tools.r8.utils.InternalOptions; import com.google.gson.annotations.SerializedName; @@ -19,16 +19,16 @@ kind = KeepItemKind.CLASS_AND_FIELDS, fieldAccess = {FieldAccessFlags.PRIVATE}, fieldAnnotatedByClassConstant = SerializedName.class) -public class R8LibraryDesugaringOptionsImpl extends D8R8LibraryDesugaringOptionsImpl - implements R8LibraryDesugaringOptions { +public class D8LibraryDesugaringMetadataImpl extends D8R8LibraryDesugaringMetadataImpl + implements D8LibraryDesugaringMetadata { - private R8LibraryDesugaringOptionsImpl(InternalOptions options) { + private D8LibraryDesugaringMetadataImpl(InternalOptions options) { super(options); } - public static R8LibraryDesugaringOptionsImpl create(InternalOptions options) { + public static D8LibraryDesugaringMetadataImpl create(InternalOptions options) { return !options.machineDesugaredLibrarySpecification.isEmpty() - ? new R8LibraryDesugaringOptionsImpl(options) + ? new D8LibraryDesugaringMetadataImpl(options) : null; } }
diff --git a/src/main/java/com/android/tools/r8/metadata/impl/D8LibraryDesugaringOptionsImpl.java b/src/main/java/com/android/tools/r8/metadata/impl/D8LibraryDesugaringOptionsImpl.java deleted file mode 100644 index 0571af6..0000000 --- a/src/main/java/com/android/tools/r8/metadata/impl/D8LibraryDesugaringOptionsImpl.java +++ /dev/null
@@ -1,34 +0,0 @@ -// Copyright (c) 2024, the R8 project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. -package com.android.tools.r8.metadata.impl; - -import com.android.tools.r8.keepanno.annotations.AnnotationPattern; -import com.android.tools.r8.keepanno.annotations.FieldAccessFlags; -import com.android.tools.r8.keepanno.annotations.KeepConstraint; -import com.android.tools.r8.keepanno.annotations.KeepItemKind; -import com.android.tools.r8.keepanno.annotations.UsedByReflection; -import com.android.tools.r8.metadata.D8LibraryDesugaringOptions; -import com.android.tools.r8.utils.InternalOptions; -import com.google.gson.annotations.SerializedName; - -@UsedByReflection( - description = "Keep and preserve @SerializedName for correct (de)serialization", - constraints = {KeepConstraint.LOOKUP}, - constrainAnnotations = @AnnotationPattern(constant = SerializedName.class), - kind = KeepItemKind.CLASS_AND_FIELDS, - fieldAccess = {FieldAccessFlags.PRIVATE}, - fieldAnnotatedByClassConstant = SerializedName.class) -public class D8LibraryDesugaringOptionsImpl extends D8R8LibraryDesugaringOptionsImpl - implements D8LibraryDesugaringOptions { - - private D8LibraryDesugaringOptionsImpl(InternalOptions options) { - super(options); - } - - public static D8LibraryDesugaringOptionsImpl create(InternalOptions options) { - return !options.machineDesugaredLibrarySpecification.isEmpty() - ? new D8LibraryDesugaringOptionsImpl(options) - : null; - } -}
diff --git a/src/main/java/com/android/tools/r8/metadata/impl/D8OptionsImpl.java b/src/main/java/com/android/tools/r8/metadata/impl/D8OptionsMetadataImpl.java similarity index 68% rename from src/main/java/com/android/tools/r8/metadata/impl/D8OptionsImpl.java rename to src/main/java/com/android/tools/r8/metadata/impl/D8OptionsMetadataImpl.java index 39210bd..76640a5 100644 --- a/src/main/java/com/android/tools/r8/metadata/impl/D8OptionsImpl.java +++ b/src/main/java/com/android/tools/r8/metadata/impl/D8OptionsMetadataImpl.java
@@ -8,9 +8,9 @@ import com.android.tools.r8.keepanno.annotations.KeepConstraint; import com.android.tools.r8.keepanno.annotations.KeepItemKind; import com.android.tools.r8.keepanno.annotations.UsedByReflection; -import com.android.tools.r8.metadata.D8ApiModelingOptions; -import com.android.tools.r8.metadata.D8LibraryDesugaringOptions; -import com.android.tools.r8.metadata.D8Options; +import com.android.tools.r8.metadata.D8ApiModelingMetadata; +import com.android.tools.r8.metadata.D8LibraryDesugaringMetadata; +import com.android.tools.r8.metadata.D8OptionsMetadata; import com.android.tools.r8.utils.InternalOptions; import com.google.gson.annotations.SerializedName; @@ -21,13 +21,14 @@ kind = KeepItemKind.CLASS_AND_FIELDS, fieldAccess = {FieldAccessFlags.PRIVATE}, fieldAnnotatedByClassConstant = SerializedName.class) -public class D8OptionsImpl extends D8R8OptionsImpl<D8ApiModelingOptions, D8LibraryDesugaringOptions> - implements D8Options { +public class D8OptionsMetadataImpl + extends D8R8OptionsMetadataImpl<D8ApiModelingMetadata, D8LibraryDesugaringMetadata> + implements D8OptionsMetadata { - public D8OptionsImpl(InternalOptions options) { + public D8OptionsMetadataImpl(InternalOptions options) { super( - D8ApiModelingOptionsImpl.create(options), - D8LibraryDesugaringOptionsImpl.create(options), + D8ApiModelingMetadataImpl.create(options), + D8LibraryDesugaringMetadataImpl.create(options), options); } }
diff --git a/src/main/java/com/android/tools/r8/metadata/impl/D8R8LibraryDesugaringOptions.java b/src/main/java/com/android/tools/r8/metadata/impl/D8R8LibraryDesugaringMetadata.java similarity index 85% rename from src/main/java/com/android/tools/r8/metadata/impl/D8R8LibraryDesugaringOptions.java rename to src/main/java/com/android/tools/r8/metadata/impl/D8R8LibraryDesugaringMetadata.java index 8ea55df..4070510 100644 --- a/src/main/java/com/android/tools/r8/metadata/impl/D8R8LibraryDesugaringOptions.java +++ b/src/main/java/com/android/tools/r8/metadata/impl/D8R8LibraryDesugaringMetadata.java
@@ -3,7 +3,7 @@ // BSD-style license that can be found in the LICENSE file. package com.android.tools.r8.metadata.impl; -public interface D8R8LibraryDesugaringOptions { +public interface D8R8LibraryDesugaringMetadata { String getIdentifier(); }
diff --git a/src/main/java/com/android/tools/r8/metadata/impl/D8R8LibraryDesugaringOptionsImpl.java b/src/main/java/com/android/tools/r8/metadata/impl/D8R8LibraryDesugaringMetadataImpl.java similarity index 88% rename from src/main/java/com/android/tools/r8/metadata/impl/D8R8LibraryDesugaringOptionsImpl.java rename to src/main/java/com/android/tools/r8/metadata/impl/D8R8LibraryDesugaringMetadataImpl.java index 8cc4c8b..4ec551c 100644 --- a/src/main/java/com/android/tools/r8/metadata/impl/D8R8LibraryDesugaringOptionsImpl.java +++ b/src/main/java/com/android/tools/r8/metadata/impl/D8R8LibraryDesugaringMetadataImpl.java
@@ -19,13 +19,13 @@ kind = KeepItemKind.CLASS_AND_FIELDS, fieldAccess = {FieldAccessFlags.PRIVATE}, fieldAnnotatedByClassConstant = SerializedName.class) -abstract class D8R8LibraryDesugaringOptionsImpl implements D8R8LibraryDesugaringOptions { +abstract class D8R8LibraryDesugaringMetadataImpl implements D8R8LibraryDesugaringMetadata { @Expose @SerializedName("identifier") private final String identifier; - public D8R8LibraryDesugaringOptionsImpl(InternalOptions options) { + public D8R8LibraryDesugaringMetadataImpl(InternalOptions options) { this.identifier = options.machineDesugaredLibrarySpecification.getIdentifier(); }
diff --git a/src/main/java/com/android/tools/r8/metadata/impl/D8R8Options.java b/src/main/java/com/android/tools/r8/metadata/impl/D8R8OptionsMetadata.java similarity index 65% rename from src/main/java/com/android/tools/r8/metadata/impl/D8R8Options.java rename to src/main/java/com/android/tools/r8/metadata/impl/D8R8OptionsMetadata.java index 6b7f8fc..0ec0446 100644 --- a/src/main/java/com/android/tools/r8/metadata/impl/D8R8Options.java +++ b/src/main/java/com/android/tools/r8/metadata/impl/D8R8OptionsMetadata.java
@@ -3,18 +3,18 @@ // BSD-style license that can be found in the LICENSE file. package com.android.tools.r8.metadata.impl; -public interface D8R8Options< - ApiModelingOptions, LibraryDesugaringOptions extends D8R8LibraryDesugaringOptions> { +public interface D8R8OptionsMetadata< + ApiModelingMetadata, LibraryDesugaringMetadata extends D8R8LibraryDesugaringMetadata> { /** * @return null if API modeling is disabled. */ - ApiModelingOptions getApiModelingOptions(); + ApiModelingMetadata getApiModelingMetadata(); /** * @return null if library desugaring is disabled. */ - LibraryDesugaringOptions getLibraryDesugaringOptions(); + LibraryDesugaringMetadata getLibraryDesugaringMetadata(); int getMinApiLevel();
diff --git a/src/main/java/com/android/tools/r8/metadata/impl/D8R8OptionsImpl.java b/src/main/java/com/android/tools/r8/metadata/impl/D8R8OptionsMetadataImpl.java similarity index 65% rename from src/main/java/com/android/tools/r8/metadata/impl/D8R8OptionsImpl.java rename to src/main/java/com/android/tools/r8/metadata/impl/D8R8OptionsMetadataImpl.java index adc01e3..00b0527 100644 --- a/src/main/java/com/android/tools/r8/metadata/impl/D8R8OptionsImpl.java +++ b/src/main/java/com/android/tools/r8/metadata/impl/D8R8OptionsMetadataImpl.java
@@ -19,17 +19,17 @@ kind = KeepItemKind.CLASS_AND_FIELDS, fieldAccess = {FieldAccessFlags.PRIVATE}, fieldAnnotatedByClassConstant = SerializedName.class) -abstract class D8R8OptionsImpl< - ApiModelingOptions, LibraryDesugaringOptions extends D8R8LibraryDesugaringOptions> - implements D8R8Options<ApiModelingOptions, LibraryDesugaringOptions> { +abstract class D8R8OptionsMetadataImpl< + ApiModelingMetadata, LibraryDesugaringMetadata extends D8R8LibraryDesugaringMetadata> + implements D8R8OptionsMetadata<ApiModelingMetadata, LibraryDesugaringMetadata> { @Expose - @SerializedName("apiModelingOptions") - private final ApiModelingOptions apiModelingOptions; + @SerializedName("apiModeling") + private final ApiModelingMetadata apiModelingMetadata; @Expose - @SerializedName("libraryDesugaringOptions") - private final LibraryDesugaringOptions libraryDesugaringOptions; + @SerializedName("libraryDesugaring") + private final LibraryDesugaringMetadata libraryDesugaringMetadata; @Expose @SerializedName("minApiLevel") @@ -39,24 +39,24 @@ @SerializedName("isDebugModeEnabled") private final boolean isDebugModeEnabled; - public D8R8OptionsImpl( - ApiModelingOptions apiModelingOptions, - LibraryDesugaringOptions libraryDesugaringOptions, + public D8R8OptionsMetadataImpl( + ApiModelingMetadata apiModelingMetadata, + LibraryDesugaringMetadata libraryDesugaringMetadata, InternalOptions options) { - this.apiModelingOptions = apiModelingOptions; - this.libraryDesugaringOptions = libraryDesugaringOptions; + this.apiModelingMetadata = apiModelingMetadata; + this.libraryDesugaringMetadata = libraryDesugaringMetadata; this.minApiLevel = options.isGeneratingDex() ? options.getMinApiLevel().getLevel() : -1; this.isDebugModeEnabled = options.debug; } @Override - public ApiModelingOptions getApiModelingOptions() { - return apiModelingOptions; + public ApiModelingMetadata getApiModelingMetadata() { + return apiModelingMetadata; } @Override - public LibraryDesugaringOptions getLibraryDesugaringOptions() { - return libraryDesugaringOptions; + public LibraryDesugaringMetadata getLibraryDesugaringMetadata() { + return libraryDesugaringMetadata; } @Override
diff --git a/src/main/java/com/android/tools/r8/metadata/impl/R8ApiModelingOptionsImpl.java b/src/main/java/com/android/tools/r8/metadata/impl/R8ApiModelingMetadataImpl.java similarity index 79% rename from src/main/java/com/android/tools/r8/metadata/impl/R8ApiModelingOptionsImpl.java rename to src/main/java/com/android/tools/r8/metadata/impl/R8ApiModelingMetadataImpl.java index c1ed920..28f388a 100644 --- a/src/main/java/com/android/tools/r8/metadata/impl/R8ApiModelingOptionsImpl.java +++ b/src/main/java/com/android/tools/r8/metadata/impl/R8ApiModelingMetadataImpl.java
@@ -8,7 +8,7 @@ import com.android.tools.r8.keepanno.annotations.KeepConstraint; import com.android.tools.r8.keepanno.annotations.KeepItemKind; import com.android.tools.r8.keepanno.annotations.UsedByReflection; -import com.android.tools.r8.metadata.R8ApiModelingOptions; +import com.android.tools.r8.metadata.R8ApiModelingMetadata; import com.android.tools.r8.utils.InternalOptions; import com.google.gson.annotations.SerializedName; @@ -19,13 +19,13 @@ kind = KeepItemKind.CLASS_AND_FIELDS, fieldAccess = {FieldAccessFlags.PRIVATE}, fieldAnnotatedByClassConstant = SerializedName.class) -public class R8ApiModelingOptionsImpl implements R8ApiModelingOptions { +public class R8ApiModelingMetadataImpl implements R8ApiModelingMetadata { - private R8ApiModelingOptionsImpl() {} + private R8ApiModelingMetadataImpl() {} - public static R8ApiModelingOptionsImpl create(InternalOptions options) { + public static R8ApiModelingMetadataImpl create(InternalOptions options) { return options.apiModelingOptions().enableLibraryApiModeling - ? new R8ApiModelingOptionsImpl() + ? new R8ApiModelingMetadataImpl() : null; } }
diff --git a/src/main/java/com/android/tools/r8/metadata/impl/R8BaselineProfileRewritingOptionsImpl.java b/src/main/java/com/android/tools/r8/metadata/impl/R8BaselineProfileRewritingMetadataImpl.java similarity index 75% rename from src/main/java/com/android/tools/r8/metadata/impl/R8BaselineProfileRewritingOptionsImpl.java rename to src/main/java/com/android/tools/r8/metadata/impl/R8BaselineProfileRewritingMetadataImpl.java index 36b7683..9b2b20b 100644 --- a/src/main/java/com/android/tools/r8/metadata/impl/R8BaselineProfileRewritingOptionsImpl.java +++ b/src/main/java/com/android/tools/r8/metadata/impl/R8BaselineProfileRewritingMetadataImpl.java
@@ -8,7 +8,7 @@ import com.android.tools.r8.keepanno.annotations.KeepConstraint; import com.android.tools.r8.keepanno.annotations.KeepItemKind; import com.android.tools.r8.keepanno.annotations.UsedByReflection; -import com.android.tools.r8.metadata.R8BaselineProfileRewritingOptions; +import com.android.tools.r8.metadata.R8BaselineProfileRewritingMetadata; import com.android.tools.r8.utils.InternalOptions; import com.google.gson.annotations.SerializedName; @@ -19,14 +19,14 @@ kind = KeepItemKind.CLASS_AND_FIELDS, fieldAccess = {FieldAccessFlags.PRIVATE}, fieldAnnotatedByClassConstant = SerializedName.class) -public class R8BaselineProfileRewritingOptionsImpl implements R8BaselineProfileRewritingOptions { +public class R8BaselineProfileRewritingMetadataImpl implements R8BaselineProfileRewritingMetadata { - private R8BaselineProfileRewritingOptionsImpl() {} + private R8BaselineProfileRewritingMetadataImpl() {} - public static R8BaselineProfileRewritingOptionsImpl create(InternalOptions options) { + public static R8BaselineProfileRewritingMetadataImpl create(InternalOptions options) { if (options.getArtProfileOptions().getArtProfilesForRewriting().isEmpty()) { return null; } - return new R8BaselineProfileRewritingOptionsImpl(); + return new R8BaselineProfileRewritingMetadataImpl(); } }
diff --git a/src/main/java/com/android/tools/r8/metadata/impl/R8BuildMetadataImpl.java b/src/main/java/com/android/tools/r8/metadata/impl/R8BuildMetadataImpl.java index 47d97b5..38cb87d 100644 --- a/src/main/java/com/android/tools/r8/metadata/impl/R8BuildMetadataImpl.java +++ b/src/main/java/com/android/tools/r8/metadata/impl/R8BuildMetadataImpl.java
@@ -11,11 +11,16 @@ import com.android.tools.r8.keepanno.annotations.KeepConstraint; import com.android.tools.r8.keepanno.annotations.KeepItemKind; import com.android.tools.r8.keepanno.annotations.UsedByReflection; -import com.android.tools.r8.metadata.R8BaselineProfileRewritingOptions; +import com.android.tools.r8.metadata.R8BaselineProfileRewritingMetadata; import com.android.tools.r8.metadata.R8BuildMetadata; -import com.android.tools.r8.metadata.R8Options; -import com.android.tools.r8.metadata.R8ResourceOptimizationOptions; -import com.android.tools.r8.metadata.R8StartupOptimizationOptions; +import com.android.tools.r8.metadata.R8CompilationMetadata; +import com.android.tools.r8.metadata.R8DexFileMetadata; +import com.android.tools.r8.metadata.R8FeatureSplitsMetadata; +import com.android.tools.r8.metadata.R8OptionsMetadata; +import com.android.tools.r8.metadata.R8ResourceOptimizationMetadata; +import com.android.tools.r8.metadata.R8StartupOptimizationMetadata; +import com.android.tools.r8.metadata.R8StatsMetadata; +import com.android.tools.r8.utils.ListUtils; import com.google.gson.Gson; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; @@ -34,40 +39,58 @@ @Expose @SerializedName("options") - private final R8Options options; + private final R8OptionsMetadata optionsMetadata; @Expose - @SerializedName("baselineProfileRewritingOptions") - private final R8BaselineProfileRewritingOptions baselineProfileRewritingOptions; + @SerializedName("baselineProfileRewriting") + private final R8BaselineProfileRewritingMetadata baselineProfileRewritingMetadata; @Expose - @SerializedName("dexChecksums") - private final List<String> dexChecksums; + @SerializedName("compilation") + private final R8CompilationMetadata compilationMetadata; @Expose - @SerializedName("resourceOptimizationOptions") - private final R8ResourceOptimizationOptions resourceOptimizationOptions; + @SerializedName("dexFiles") + private final List<R8DexFileMetadata> dexFilesMetadata; @Expose - @SerializedName("startupOptimizationOptions") - private final R8StartupOptimizationOptions startupOptimizationOptions; + @SerializedName("stats") + private final R8StatsMetadata statsMetadata; + + @Expose + @SerializedName("featureSplits") + private final R8FeatureSplitsMetadata featureSplitsMetadata; + + @Expose + @SerializedName("resourceOptimization") + private final R8ResourceOptimizationMetadata resourceOptimizationMetadata; + + @Expose + @SerializedName("startupOptimization") + private final R8StartupOptimizationMetadata startupOptimizationMetadata; @Expose @SerializedName("version") private final String version; public R8BuildMetadataImpl( - R8Options options, - R8BaselineProfileRewritingOptions baselineProfileRewritingOptions, - List<String> dexChecksums, - R8ResourceOptimizationOptions resourceOptimizationOptions, - R8StartupOptimizationOptions startupOptimizationOptions, + R8OptionsMetadata options, + R8BaselineProfileRewritingMetadata baselineProfileRewritingOptions, + R8CompilationMetadata compilationMetadata, + List<R8DexFileMetadata> dexFilesMetadata, + R8StatsMetadata statsMetadata, + R8FeatureSplitsMetadata featureSplitsMetadata, + R8ResourceOptimizationMetadata resourceOptimizationMetadata, + R8StartupOptimizationMetadata startupOptimizationMetadata, String version) { - this.options = options; - this.baselineProfileRewritingOptions = baselineProfileRewritingOptions; - this.dexChecksums = dexChecksums; - this.resourceOptimizationOptions = resourceOptimizationOptions; - this.startupOptimizationOptions = startupOptimizationOptions; + this.optionsMetadata = options; + this.baselineProfileRewritingMetadata = baselineProfileRewritingOptions; + this.compilationMetadata = compilationMetadata; + this.dexFilesMetadata = dexFilesMetadata; + this.statsMetadata = statsMetadata; + this.featureSplitsMetadata = featureSplitsMetadata; + this.resourceOptimizationMetadata = resourceOptimizationMetadata; + this.startupOptimizationMetadata = startupOptimizationMetadata; this.version = version; } @@ -76,28 +99,43 @@ } @Override - public R8Options getOptions() { - return options; + public R8OptionsMetadata getOptionsMetadata() { + return optionsMetadata; } @Override - public R8BaselineProfileRewritingOptions getBaselineProfileRewritingOptions() { - return baselineProfileRewritingOptions; + public R8BaselineProfileRewritingMetadata getBaselineProfileRewritingMetadata() { + return baselineProfileRewritingMetadata; } @Override - public List<String> getDexChecksums() { - return dexChecksums; + public R8CompilationMetadata getCompilationMetadata() { + return compilationMetadata; } @Override - public R8ResourceOptimizationOptions getResourceOptimizationOptions() { - return resourceOptimizationOptions; + public List<R8DexFileMetadata> getDexFilesMetadata() { + return dexFilesMetadata; } @Override - public R8StartupOptimizationOptions getStartupOptizationOptions() { - return startupOptimizationOptions; + public R8FeatureSplitsMetadata getFeatureSplitsMetadata() { + return featureSplitsMetadata; + } + + @Override + public R8ResourceOptimizationMetadata getResourceOptimizationMetadata() { + return resourceOptimizationMetadata; + } + + @Override + public R8StartupOptimizationMetadata getStartupOptizationOptions() { + return startupOptimizationMetadata; + } + + @Override + public R8StatsMetadata getStatsMetadata() { + return statsMetadata; } @Override @@ -112,11 +150,14 @@ public static class Builder { - private R8Options options; - private R8BaselineProfileRewritingOptions baselineProfileRewritingOptions; - private List<String> dexChecksums; - private R8ResourceOptimizationOptions resourceOptimizationOptions; - private R8StartupOptimizationOptions startupOptimizationOptions; + private R8OptionsMetadata options; + private R8BaselineProfileRewritingMetadata baselineProfileRewritingOptions; + private R8CompilationMetadata compilationInfo; + private List<R8DexFileMetadata> dexFilesMetadata; + private R8StatsMetadata statsMetadata; + private R8FeatureSplitsMetadata featureSplitsMetadata; + private R8ResourceOptimizationMetadata resourceOptimizationOptions; + private R8StartupOptimizationMetadata startupOptimizationOptions; private String version; public Builder applyIf(boolean condition, Consumer<Builder> thenConsumer) { @@ -126,34 +167,50 @@ return this; } - public Builder setOptions(R8Options options) { + public Builder setOptions(R8OptionsMetadata options) { this.options = options; return this; } public Builder setBaselineProfileRewritingOptions( - R8BaselineProfileRewritingOptions baselineProfileRewritingOptions) { + R8BaselineProfileRewritingMetadata baselineProfileRewritingOptions) { this.baselineProfileRewritingOptions = baselineProfileRewritingOptions; return this; } - public Builder setDexChecksums(List<VirtualFile> virtualFiles) { - this.dexChecksums = + public Builder setCompilationInfo(R8CompilationMetadata compilationInfo) { + this.compilationInfo = compilationInfo; + return this; + } + + public Builder setDexFilesMetadata(List<VirtualFile> virtualFiles) { + List<String> checksums = virtualFiles.stream() .filter(not(VirtualFile::isEmpty)) .map(virtualFile -> virtualFile.getChecksumForBuildMetadata().toString()) .collect(Collectors.toList()); + this.dexFilesMetadata = ListUtils.map(checksums, R8DexFileMetadataImpl::new); + return this; + } + + public Builder setStatsMetadata(R8StatsMetadata statsMetadata) { + this.statsMetadata = statsMetadata; + return this; + } + + public Builder setFeatureSplitsMetadata(R8FeatureSplitsMetadata featureSplitsMetadata) { + this.featureSplitsMetadata = featureSplitsMetadata; return this; } public Builder setResourceOptimizationOptions( - R8ResourceOptimizationOptions resourceOptimizationOptions) { + R8ResourceOptimizationMetadata resourceOptimizationOptions) { this.resourceOptimizationOptions = resourceOptimizationOptions; return this; } public Builder setStartupOptimizationOptions( - R8StartupOptimizationOptions startupOptimizationOptions) { + R8StartupOptimizationMetadata startupOptimizationOptions) { this.startupOptimizationOptions = startupOptimizationOptions; return this; } @@ -167,7 +224,10 @@ return new R8BuildMetadataImpl( options, baselineProfileRewritingOptions, - dexChecksums, + compilationInfo, + dexFilesMetadata, + statsMetadata, + featureSplitsMetadata, resourceOptimizationOptions, startupOptimizationOptions, version);
diff --git a/src/main/java/com/android/tools/r8/metadata/impl/R8CompilationMetadataImpl.java b/src/main/java/com/android/tools/r8/metadata/impl/R8CompilationMetadataImpl.java new file mode 100644 index 0000000..4be7d15 --- /dev/null +++ b/src/main/java/com/android/tools/r8/metadata/impl/R8CompilationMetadataImpl.java
@@ -0,0 +1,60 @@ +// Copyright (c) 2024, the R8 project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. +package com.android.tools.r8.metadata.impl; + +import com.android.tools.r8.graph.AppInfoWithClassHierarchy; +import com.android.tools.r8.graph.AppView; +import com.android.tools.r8.keepanno.annotations.AnnotationPattern; +import com.android.tools.r8.keepanno.annotations.FieldAccessFlags; +import com.android.tools.r8.keepanno.annotations.KeepConstraint; +import com.android.tools.r8.keepanno.annotations.KeepItemKind; +import com.android.tools.r8.keepanno.annotations.UsedByReflection; +import com.android.tools.r8.metadata.R8CompilationMetadata; +import com.android.tools.r8.utils.InternalOptions; +import com.android.tools.r8.utils.ThreadUtils; +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; +import java.util.concurrent.ExecutorService; + +@UsedByReflection( + description = "Keep and preserve @SerializedName for correct (de)serialization", + constraints = {KeepConstraint.LOOKUP}, + constrainAnnotations = @AnnotationPattern(constant = SerializedName.class), + kind = KeepItemKind.CLASS_AND_FIELDS, + fieldAccess = {FieldAccessFlags.PRIVATE}, + fieldAnnotatedByClassConstant = SerializedName.class) +public class R8CompilationMetadataImpl implements R8CompilationMetadata { + + @Expose + @SerializedName("buildTime") + private final long buildTime; + + @Expose + @SerializedName("numberOfThreads") + private final long numberOfThreads; + + private R8CompilationMetadataImpl(long buildTime, int numberOfThreads) { + this.buildTime = buildTime; + this.numberOfThreads = numberOfThreads; + } + + public static R8CompilationMetadataImpl create( + AppView<? extends AppInfoWithClassHierarchy> appView, ExecutorService executorService) { + InternalOptions options = appView.options(); + assert options.created > 0; + long buildTime = System.nanoTime() - options.created; + return new R8CompilationMetadataImpl( + buildTime, ThreadUtils.getNumberOfThreads(executorService)); + } + + @Override + public long getBuildTime() { + return buildTime; + } + + @Override + public long getNumberOfThreads() { + return numberOfThreads; + } +}
diff --git a/src/main/java/com/android/tools/r8/metadata/impl/D8R8LibraryDesugaringOptionsImpl.java b/src/main/java/com/android/tools/r8/metadata/impl/R8DexFileMetadataImpl.java similarity index 72% copy from src/main/java/com/android/tools/r8/metadata/impl/D8R8LibraryDesugaringOptionsImpl.java copy to src/main/java/com/android/tools/r8/metadata/impl/R8DexFileMetadataImpl.java index 8cc4c8b..e0680dc 100644 --- a/src/main/java/com/android/tools/r8/metadata/impl/D8R8LibraryDesugaringOptionsImpl.java +++ b/src/main/java/com/android/tools/r8/metadata/impl/R8DexFileMetadataImpl.java
@@ -8,7 +8,7 @@ import com.android.tools.r8.keepanno.annotations.KeepConstraint; import com.android.tools.r8.keepanno.annotations.KeepItemKind; import com.android.tools.r8.keepanno.annotations.UsedByReflection; -import com.android.tools.r8.utils.InternalOptions; +import com.android.tools.r8.metadata.R8DexFileMetadata; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; @@ -19,18 +19,18 @@ kind = KeepItemKind.CLASS_AND_FIELDS, fieldAccess = {FieldAccessFlags.PRIVATE}, fieldAnnotatedByClassConstant = SerializedName.class) -abstract class D8R8LibraryDesugaringOptionsImpl implements D8R8LibraryDesugaringOptions { +public class R8DexFileMetadataImpl implements R8DexFileMetadata { @Expose - @SerializedName("identifier") - private final String identifier; + @SerializedName("checksum") + private final String checksum; - public D8R8LibraryDesugaringOptionsImpl(InternalOptions options) { - this.identifier = options.machineDesugaredLibrarySpecification.getIdentifier(); + public R8DexFileMetadataImpl(String checksum) { + this.checksum = checksum; } @Override - public String getIdentifier() { - return identifier; + public String getChecksum() { + return checksum; } }
diff --git a/src/main/java/com/android/tools/r8/metadata/impl/D8R8LibraryDesugaringOptionsImpl.java b/src/main/java/com/android/tools/r8/metadata/impl/R8FeatureSplitMetadataImpl.java similarity index 67% copy from src/main/java/com/android/tools/r8/metadata/impl/D8R8LibraryDesugaringOptionsImpl.java copy to src/main/java/com/android/tools/r8/metadata/impl/R8FeatureSplitMetadataImpl.java index 8cc4c8b..521642e 100644 --- a/src/main/java/com/android/tools/r8/metadata/impl/D8R8LibraryDesugaringOptionsImpl.java +++ b/src/main/java/com/android/tools/r8/metadata/impl/R8FeatureSplitMetadataImpl.java
@@ -8,9 +8,11 @@ import com.android.tools.r8.keepanno.annotations.KeepConstraint; import com.android.tools.r8.keepanno.annotations.KeepItemKind; import com.android.tools.r8.keepanno.annotations.UsedByReflection; -import com.android.tools.r8.utils.InternalOptions; +import com.android.tools.r8.metadata.R8DexFileMetadata; +import com.android.tools.r8.metadata.R8FeatureSplitMetadata; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; +import java.util.List; @UsedByReflection( description = "Keep and preserve @SerializedName for correct (de)serialization", @@ -19,18 +21,18 @@ kind = KeepItemKind.CLASS_AND_FIELDS, fieldAccess = {FieldAccessFlags.PRIVATE}, fieldAnnotatedByClassConstant = SerializedName.class) -abstract class D8R8LibraryDesugaringOptionsImpl implements D8R8LibraryDesugaringOptions { +public class R8FeatureSplitMetadataImpl implements R8FeatureSplitMetadata { @Expose - @SerializedName("identifier") - private final String identifier; + @SerializedName("dexFiles") + private final List<R8DexFileMetadata> dexFilesMetadata; - public D8R8LibraryDesugaringOptionsImpl(InternalOptions options) { - this.identifier = options.machineDesugaredLibrarySpecification.getIdentifier(); + public R8FeatureSplitMetadataImpl(List<R8DexFileMetadata> dexFilesMetadata) { + this.dexFilesMetadata = dexFilesMetadata; } @Override - public String getIdentifier() { - return identifier; + public List<R8DexFileMetadata> getDexFilesMetadata() { + return dexFilesMetadata; } }
diff --git a/src/main/java/com/android/tools/r8/metadata/impl/R8FeatureSplitsMetadataImpl.java b/src/main/java/com/android/tools/r8/metadata/impl/R8FeatureSplitsMetadataImpl.java new file mode 100644 index 0000000..d3b6b7a --- /dev/null +++ b/src/main/java/com/android/tools/r8/metadata/impl/R8FeatureSplitsMetadataImpl.java
@@ -0,0 +1,82 @@ +// Copyright (c) 2024, the R8 project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. +package com.android.tools.r8.metadata.impl; + +import com.android.tools.r8.FeatureSplit; +import com.android.tools.r8.dex.VirtualFile; +import com.android.tools.r8.features.FeatureSplitConfiguration; +import com.android.tools.r8.graph.AppInfoWithClassHierarchy; +import com.android.tools.r8.graph.AppView; +import com.android.tools.r8.keepanno.annotations.AnnotationPattern; +import com.android.tools.r8.keepanno.annotations.FieldAccessFlags; +import com.android.tools.r8.keepanno.annotations.KeepConstraint; +import com.android.tools.r8.keepanno.annotations.KeepItemKind; +import com.android.tools.r8.keepanno.annotations.UsedByReflection; +import com.android.tools.r8.metadata.R8DexFileMetadata; +import com.android.tools.r8.metadata.R8FeatureSplitMetadata; +import com.android.tools.r8.metadata.R8FeatureSplitsMetadata; +import com.android.tools.r8.utils.InternalOptions; +import com.android.tools.r8.utils.ListUtils; +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +@UsedByReflection( + description = "Keep and preserve @SerializedName for correct (de)serialization", + constraints = {KeepConstraint.LOOKUP}, + constrainAnnotations = @AnnotationPattern(constant = SerializedName.class), + kind = KeepItemKind.CLASS_AND_FIELDS, + fieldAccess = {FieldAccessFlags.PRIVATE}, + fieldAnnotatedByClassConstant = SerializedName.class) +public class R8FeatureSplitsMetadataImpl implements R8FeatureSplitsMetadata { + + @Expose + @SerializedName("featureSplits") + private final List<R8FeatureSplitMetadata> featureSplitsMetadata; + + @Expose + @SerializedName("isolatedSplits") + private final boolean isolatedSplits; + + public R8FeatureSplitsMetadataImpl( + FeatureSplitConfiguration configuration, List<R8FeatureSplitMetadata> featureSplitsMetadata) { + this.featureSplitsMetadata = featureSplitsMetadata; + this.isolatedSplits = configuration.isIsolatedSplitsEnabled(); + } + + public static R8FeatureSplitsMetadataImpl create( + AppView<? extends AppInfoWithClassHierarchy> appView, + Map<FeatureSplit, List<VirtualFile>> virtualFilesForFeatureSplit) { + InternalOptions options = appView.options(); + assert options.hasFeatureSplitConfiguration(); + FeatureSplitConfiguration configuration = options.getFeatureSplitConfiguration(); + List<FeatureSplit> featureSplits = configuration.getFeatureSplits(); + List<R8FeatureSplitMetadata> featureSplitsMetadata = new ArrayList<>(); + for (FeatureSplit featureSplit : featureSplits) { + List<VirtualFile> featureSplitVirtualFiles = + virtualFilesForFeatureSplit.getOrDefault(featureSplit, Collections.emptyList()); + List<R8DexFileMetadata> dexFilesMetadata = + ListUtils.map( + featureSplitVirtualFiles, + featureSplitVirtualFile -> + new R8DexFileMetadataImpl( + featureSplitVirtualFile.getChecksumForBuildMetadata().toString())); + featureSplitsMetadata.add(new R8FeatureSplitMetadataImpl(dexFilesMetadata)); + } + return new R8FeatureSplitsMetadataImpl(configuration, featureSplitsMetadata); + } + + @Override + public List<R8FeatureSplitMetadata> getFeatureSplits() { + return featureSplitsMetadata; + } + + @Override + public boolean isIsolatedSplitsEnabled() { + return isolatedSplits; + } +}
diff --git a/src/main/java/com/android/tools/r8/metadata/impl/R8KeepAttributesOptionsImpl.java b/src/main/java/com/android/tools/r8/metadata/impl/R8KeepAttributesMetadataImpl.java similarity index 96% rename from src/main/java/com/android/tools/r8/metadata/impl/R8KeepAttributesOptionsImpl.java rename to src/main/java/com/android/tools/r8/metadata/impl/R8KeepAttributesMetadataImpl.java index ccec35f..ee9f918 100644 --- a/src/main/java/com/android/tools/r8/metadata/impl/R8KeepAttributesOptionsImpl.java +++ b/src/main/java/com/android/tools/r8/metadata/impl/R8KeepAttributesMetadataImpl.java
@@ -8,7 +8,7 @@ import com.android.tools.r8.keepanno.annotations.KeepConstraint; import com.android.tools.r8.keepanno.annotations.KeepItemKind; import com.android.tools.r8.keepanno.annotations.UsedByReflection; -import com.android.tools.r8.metadata.R8KeepAttributesOptions; +import com.android.tools.r8.metadata.R8KeepAttributesMetadata; import com.android.tools.r8.shaking.ProguardKeepAttributes; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; @@ -20,7 +20,7 @@ kind = KeepItemKind.CLASS_AND_FIELDS, fieldAccess = {FieldAccessFlags.PRIVATE}, fieldAnnotatedByClassConstant = SerializedName.class) -public class R8KeepAttributesOptionsImpl implements R8KeepAttributesOptions { +public class R8KeepAttributesMetadataImpl implements R8KeepAttributesMetadata { @Expose @SerializedName("isAnnotationDefaultKept") @@ -98,7 +98,7 @@ @SerializedName("isStackMapTableKept") private final boolean isStackMapTableKept; - public R8KeepAttributesOptionsImpl(ProguardKeepAttributes keepAttributes) { + public R8KeepAttributesMetadataImpl(ProguardKeepAttributes keepAttributes) { this.isAnnotationDefaultKept = keepAttributes.annotationDefault; this.isEnclosingMethodKept = keepAttributes.enclosingMethod; this.isExceptionsKept = keepAttributes.exceptions;
diff --git a/src/main/java/com/android/tools/r8/metadata/impl/R8LibraryDesugaringOptionsImpl.java b/src/main/java/com/android/tools/r8/metadata/impl/R8LibraryDesugaringMetadataImpl.java similarity index 74% rename from src/main/java/com/android/tools/r8/metadata/impl/R8LibraryDesugaringOptionsImpl.java rename to src/main/java/com/android/tools/r8/metadata/impl/R8LibraryDesugaringMetadataImpl.java index cad11e6..84059cd 100644 --- a/src/main/java/com/android/tools/r8/metadata/impl/R8LibraryDesugaringOptionsImpl.java +++ b/src/main/java/com/android/tools/r8/metadata/impl/R8LibraryDesugaringMetadataImpl.java
@@ -8,7 +8,7 @@ import com.android.tools.r8.keepanno.annotations.KeepConstraint; import com.android.tools.r8.keepanno.annotations.KeepItemKind; import com.android.tools.r8.keepanno.annotations.UsedByReflection; -import com.android.tools.r8.metadata.R8LibraryDesugaringOptions; +import com.android.tools.r8.metadata.R8LibraryDesugaringMetadata; import com.android.tools.r8.utils.InternalOptions; import com.google.gson.annotations.SerializedName; @@ -19,16 +19,16 @@ kind = KeepItemKind.CLASS_AND_FIELDS, fieldAccess = {FieldAccessFlags.PRIVATE}, fieldAnnotatedByClassConstant = SerializedName.class) -public class R8LibraryDesugaringOptionsImpl extends D8R8LibraryDesugaringOptionsImpl - implements R8LibraryDesugaringOptions { +public class R8LibraryDesugaringMetadataImpl extends D8R8LibraryDesugaringMetadataImpl + implements R8LibraryDesugaringMetadata { - private R8LibraryDesugaringOptionsImpl(InternalOptions options) { + private R8LibraryDesugaringMetadataImpl(InternalOptions options) { super(options); } - public static R8LibraryDesugaringOptionsImpl create(InternalOptions options) { + public static R8LibraryDesugaringMetadataImpl create(InternalOptions options) { return !options.machineDesugaredLibrarySpecification.isEmpty() - ? new R8LibraryDesugaringOptionsImpl(options) + ? new R8LibraryDesugaringMetadataImpl(options) : null; } }
diff --git a/src/main/java/com/android/tools/r8/metadata/impl/R8OptionsImpl.java b/src/main/java/com/android/tools/r8/metadata/impl/R8OptionsMetadataImpl.java similarity index 75% rename from src/main/java/com/android/tools/r8/metadata/impl/R8OptionsImpl.java rename to src/main/java/com/android/tools/r8/metadata/impl/R8OptionsMetadataImpl.java index 28e5e92..70cec6f 100644 --- a/src/main/java/com/android/tools/r8/metadata/impl/R8OptionsImpl.java +++ b/src/main/java/com/android/tools/r8/metadata/impl/R8OptionsMetadataImpl.java
@@ -8,10 +8,10 @@ import com.android.tools.r8.keepanno.annotations.KeepConstraint; import com.android.tools.r8.keepanno.annotations.KeepItemKind; import com.android.tools.r8.keepanno.annotations.UsedByReflection; -import com.android.tools.r8.metadata.R8ApiModelingOptions; -import com.android.tools.r8.metadata.R8KeepAttributesOptions; -import com.android.tools.r8.metadata.R8LibraryDesugaringOptions; -import com.android.tools.r8.metadata.R8Options; +import com.android.tools.r8.metadata.R8ApiModelingMetadata; +import com.android.tools.r8.metadata.R8KeepAttributesMetadata; +import com.android.tools.r8.metadata.R8LibraryDesugaringMetadata; +import com.android.tools.r8.metadata.R8OptionsMetadata; import com.android.tools.r8.utils.InternalOptions; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; @@ -23,12 +23,13 @@ kind = KeepItemKind.CLASS_AND_FIELDS, fieldAccess = {FieldAccessFlags.PRIVATE}, fieldAnnotatedByClassConstant = SerializedName.class) -public class R8OptionsImpl extends D8R8OptionsImpl<R8ApiModelingOptions, R8LibraryDesugaringOptions> - implements R8Options { +public class R8OptionsMetadataImpl + extends D8R8OptionsMetadataImpl<R8ApiModelingMetadata, R8LibraryDesugaringMetadata> + implements R8OptionsMetadata { @Expose - @SerializedName("keepAttributesOptions") - private final R8KeepAttributesOptions keepAttributesOptions; + @SerializedName("keepAttributes") + private final R8KeepAttributesMetadata keepAttributesMetadata; @Expose @SerializedName("isAccessModificationEnabled") @@ -50,14 +51,14 @@ @SerializedName("isShrinkingEnabled") private final boolean isShrinkingEnabled; - public R8OptionsImpl(InternalOptions options) { + public R8OptionsMetadataImpl(InternalOptions options) { super( - R8ApiModelingOptionsImpl.create(options), - R8LibraryDesugaringOptionsImpl.create(options), + R8ApiModelingMetadataImpl.create(options), + R8LibraryDesugaringMetadataImpl.create(options), options); - this.keepAttributesOptions = + this.keepAttributesMetadata = options.hasProguardConfiguration() - ? new R8KeepAttributesOptionsImpl( + ? new R8KeepAttributesMetadataImpl( options.getProguardConfiguration().getKeepAttributes()) : null; this.isAccessModificationEnabled = options.isAccessModificationEnabled(); @@ -68,8 +69,8 @@ } @Override - public R8KeepAttributesOptions getKeepAttributesOptions() { - return keepAttributesOptions; + public R8KeepAttributesMetadata getKeepAttributesMetadata() { + return keepAttributesMetadata; } @Override
diff --git a/src/main/java/com/android/tools/r8/metadata/impl/R8ResourceOptimizationOptionsImpl.java b/src/main/java/com/android/tools/r8/metadata/impl/R8ResourceOptimizationMetadataImpl.java similarity index 80% rename from src/main/java/com/android/tools/r8/metadata/impl/R8ResourceOptimizationOptionsImpl.java rename to src/main/java/com/android/tools/r8/metadata/impl/R8ResourceOptimizationMetadataImpl.java index 3507271..790557e 100644 --- a/src/main/java/com/android/tools/r8/metadata/impl/R8ResourceOptimizationOptionsImpl.java +++ b/src/main/java/com/android/tools/r8/metadata/impl/R8ResourceOptimizationMetadataImpl.java
@@ -9,7 +9,7 @@ import com.android.tools.r8.keepanno.annotations.KeepConstraint; import com.android.tools.r8.keepanno.annotations.KeepItemKind; import com.android.tools.r8.keepanno.annotations.UsedByReflection; -import com.android.tools.r8.metadata.R8ResourceOptimizationOptions; +import com.android.tools.r8.metadata.R8ResourceOptimizationMetadata; import com.android.tools.r8.utils.InternalOptions; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; @@ -21,22 +21,22 @@ kind = KeepItemKind.CLASS_AND_FIELDS, fieldAccess = {FieldAccessFlags.PRIVATE}, fieldAnnotatedByClassConstant = SerializedName.class) -public class R8ResourceOptimizationOptionsImpl implements R8ResourceOptimizationOptions { +public class R8ResourceOptimizationMetadataImpl implements R8ResourceOptimizationMetadata { @Expose @SerializedName("isOptimizedShrinkingEnabled") private final boolean isOptimizedShrinkingEnabled; - private R8ResourceOptimizationOptionsImpl( + private R8ResourceOptimizationMetadataImpl( ResourceShrinkerConfiguration resourceShrinkerConfiguration) { this.isOptimizedShrinkingEnabled = resourceShrinkerConfiguration.isOptimizedShrinking(); } - public static R8ResourceOptimizationOptionsImpl create(InternalOptions options) { + public static R8ResourceOptimizationMetadataImpl create(InternalOptions options) { if (options.androidResourceProvider == null) { return null; } - return new R8ResourceOptimizationOptionsImpl(options.resourceShrinkerConfiguration); + return new R8ResourceOptimizationMetadataImpl(options.resourceShrinkerConfiguration); } @Override
diff --git a/src/main/java/com/android/tools/r8/metadata/impl/R8StartupOptimizationOptionsImpl.java b/src/main/java/com/android/tools/r8/metadata/impl/R8StartupOptimizationMetadataImpl.java similarity index 82% rename from src/main/java/com/android/tools/r8/metadata/impl/R8StartupOptimizationOptionsImpl.java rename to src/main/java/com/android/tools/r8/metadata/impl/R8StartupOptimizationMetadataImpl.java index 0406f26..f18efd4 100644 --- a/src/main/java/com/android/tools/r8/metadata/impl/R8StartupOptimizationOptionsImpl.java +++ b/src/main/java/com/android/tools/r8/metadata/impl/R8StartupOptimizationMetadataImpl.java
@@ -9,7 +9,7 @@ import com.android.tools.r8.keepanno.annotations.KeepConstraint; import com.android.tools.r8.keepanno.annotations.KeepItemKind; import com.android.tools.r8.keepanno.annotations.UsedByReflection; -import com.android.tools.r8.metadata.R8StartupOptimizationOptions; +import com.android.tools.r8.metadata.R8StartupOptimizationMetadata; import com.android.tools.r8.utils.InternalOptions; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; @@ -22,23 +22,23 @@ kind = KeepItemKind.CLASS_AND_FIELDS, fieldAccess = {FieldAccessFlags.PRIVATE}, fieldAnnotatedByClassConstant = SerializedName.class) -public class R8StartupOptimizationOptionsImpl implements R8StartupOptimizationOptions { +public class R8StartupOptimizationMetadataImpl implements R8StartupOptimizationMetadata { @Expose @SerializedName("numberOfStartupDexFiles") private final int numberOfStartupDexFiles; - public R8StartupOptimizationOptionsImpl(List<VirtualFile> virtualFiles) { + public R8StartupOptimizationMetadataImpl(List<VirtualFile> virtualFiles) { this.numberOfStartupDexFiles = (int) virtualFiles.stream().filter(VirtualFile::isStartup).count(); } - public static R8StartupOptimizationOptionsImpl create( + public static R8StartupOptimizationMetadataImpl create( InternalOptions options, List<VirtualFile> virtualFiles) { if (options.getStartupOptions().getStartupProfileProviders().isEmpty()) { return null; } - return new R8StartupOptimizationOptionsImpl(virtualFiles); + return new R8StartupOptimizationMetadataImpl(virtualFiles); } @Override
diff --git a/src/main/java/com/android/tools/r8/metadata/impl/R8StatsMetadataImpl.java b/src/main/java/com/android/tools/r8/metadata/impl/R8StatsMetadataImpl.java new file mode 100644 index 0000000..05b8e2f --- /dev/null +++ b/src/main/java/com/android/tools/r8/metadata/impl/R8StatsMetadataImpl.java
@@ -0,0 +1,119 @@ +// Copyright (c) 2024, the R8 project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. +package com.android.tools.r8.metadata.impl; + +import com.android.tools.r8.graph.AppInfoWithClassHierarchy; +import com.android.tools.r8.graph.AppView; +import com.android.tools.r8.graph.DexProgramClass; +import com.android.tools.r8.graph.ProgramDefinition; +import com.android.tools.r8.keepanno.annotations.AnnotationPattern; +import com.android.tools.r8.keepanno.annotations.FieldAccessFlags; +import com.android.tools.r8.keepanno.annotations.KeepConstraint; +import com.android.tools.r8.keepanno.annotations.KeepItemKind; +import com.android.tools.r8.keepanno.annotations.UsedByReflection; +import com.android.tools.r8.metadata.R8StatsMetadata; +import com.android.tools.r8.shaking.KeepInfo; +import com.android.tools.r8.utils.BooleanUtils; +import com.android.tools.r8.utils.InternalOptions; +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +@UsedByReflection( + description = "Keep and preserve @SerializedName for correct (de)serialization", + constraints = {KeepConstraint.LOOKUP}, + constrainAnnotations = @AnnotationPattern(constant = SerializedName.class), + kind = KeepItemKind.CLASS_AND_FIELDS, + fieldAccess = {FieldAccessFlags.PRIVATE}, + fieldAnnotatedByClassConstant = SerializedName.class) +public class R8StatsMetadataImpl implements R8StatsMetadata { + + @Expose + @SerializedName("noObfuscationPercentage") + private final float noObfuscationPercentage; + + @Expose + @SerializedName("noOptimizationPercentage") + private final float noOptimizationPercentage; + + @Expose + @SerializedName("noShrinkingPercentage") + private final float noShrinkingPercentage; + + private R8StatsMetadataImpl( + float noObfuscationPercentage, float noOptimizationPercentage, float noShrinkingPercentage) { + this.noObfuscationPercentage = noObfuscationPercentage; + this.noOptimizationPercentage = noOptimizationPercentage; + this.noShrinkingPercentage = noShrinkingPercentage; + } + + public static R8StatsMetadataImpl create(AppView<? extends AppInfoWithClassHierarchy> appView) { + Counters counters = Counters.create(appView); + return new R8StatsMetadataImpl( + counters.getNoObfuscationPercentage(), + counters.getNoOptimizationPercentage(), + counters.getNoShrinkingPercentage()); + } + + @Override + public float getNoObfuscationPercentage() { + return noObfuscationPercentage; + } + + @Override + public float getNoOptimizationPercentage() { + return noOptimizationPercentage; + } + + @Override + public float getNoShrinkingPercentage() { + return noShrinkingPercentage; + } + + private static class Counters { + + private int itemsCount = 0; + private int noObfuscationCount = 0; + private int noOptimizationCount = 0; + private int noShrinkingCount = 0; + + private Counters() {} + + static Counters create(AppView<? extends AppInfoWithClassHierarchy> appView) { + Counters counters = new Counters(); + for (DexProgramClass clazz : appView.appInfo().classes()) { + counters.add(appView, clazz); + clazz.forEachProgramMember(member -> counters.add(appView, member)); + } + return counters; + } + + private void add( + AppView<? extends AppInfoWithClassHierarchy> appView, ProgramDefinition definition) { + KeepInfo<?, ?> keepInfo = appView.getKeepInfo(definition); + InternalOptions options = appView.options(); + itemsCount++; + noObfuscationCount += BooleanUtils.intValue(!keepInfo.isMinificationAllowed(options)); + noOptimizationCount += BooleanUtils.intValue(!keepInfo.isOptimizationAllowed(options)); + noShrinkingCount += BooleanUtils.intValue(!keepInfo.isShrinkingAllowed(options)); + } + + float getNoObfuscationPercentage() { + return toPercentageWithTwoDecimals(noObfuscationCount); + } + + float getNoOptimizationPercentage() { + return toPercentageWithTwoDecimals(noOptimizationCount); + } + + float getNoShrinkingPercentage() { + return toPercentageWithTwoDecimals(noShrinkingCount); + } + + float toPercentageWithTwoDecimals(int count) { + // Multiply by 100 twice to get percentage with two decimals. + float number = (float) (count * 100 * 100) / itemsCount; + return (float) Math.round(number) / 100; + } + } +}
diff --git a/src/main/java/com/android/tools/r8/relocator/Relocator.java b/src/main/java/com/android/tools/r8/relocator/Relocator.java index a0824ca..d74a6e9 100644 --- a/src/main/java/com/android/tools/r8/relocator/Relocator.java +++ b/src/main/java/com/android/tools/r8/relocator/Relocator.java
@@ -81,7 +81,8 @@ appView.setAppServices(AppServices.builder(appView).build()); appView.setNamingLens(command.getMapping().compute(appView)); new GenericSignatureRewriter(appView).run(appInfo.classes(), executor); - new CfApplicationWriter(appView, new Marker(Tool.Relocator)).write(command.getConsumer()); + new CfApplicationWriter(appView, new Marker(Tool.Relocator)) + .write(command.getConsumer(), executor); options.printWarnings(); } catch (ExecutionException e) { throw unwrapExecutionException(e);
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParserOptions.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParserOptions.java index 07bea60..02373b6 100644 --- a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParserOptions.java +++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParserOptions.java
@@ -11,6 +11,7 @@ public class ProguardConfigurationParserOptions { private final OptionalBool enableEmptyMemberRulesToDefaultInitRuleConversion; + private final boolean enableEmptyMemberRulesToDefaultInitRuleConversionWarnings; private final boolean enableExperimentalCheckEnumUnboxed; private final boolean enableExperimentalConvertCheckNotNull; private final boolean enableExperimentalWhyAreYouNotInlining; @@ -18,6 +19,7 @@ ProguardConfigurationParserOptions( OptionalBool enableEmptyMemberRulesToDefaultInitRuleConversion, + boolean enableEmptyMemberRulesToDefaultInitRuleConversionWarnings, boolean enableExperimentalCheckEnumUnboxed, boolean enableExperimentalConvertCheckNotNull, boolean enableExperimentalWhyAreYouNotInlining, @@ -28,6 +30,8 @@ this.enableTestingOptions = enableTestingOptions; this.enableEmptyMemberRulesToDefaultInitRuleConversion = enableEmptyMemberRulesToDefaultInitRuleConversion; + this.enableEmptyMemberRulesToDefaultInitRuleConversionWarnings = + enableEmptyMemberRulesToDefaultInitRuleConversionWarnings; } public static Builder builder() { @@ -45,7 +49,7 @@ ProguardConfiguration.Builder configurationBuilder) { assert isEmptyMemberRulesToDefaultInitRuleConversionEnabled(configurationBuilder); return !configurationBuilder.isForceProguardCompatibility() - && enableEmptyMemberRulesToDefaultInitRuleConversion.isUnknown(); + && enableEmptyMemberRulesToDefaultInitRuleConversionWarnings; } public boolean isExperimentalCheckEnumUnboxedEnabled() { @@ -67,6 +71,7 @@ public static class Builder { private OptionalBool enableEmptyMemberRulesToDefaultInitRuleConversion = OptionalBool.UNKNOWN; + private boolean enableEmptyMemberRulesToDefaultInitRuleConversionWarnings = false; private boolean enableExperimentalCheckEnumUnboxed; private boolean enableExperimentalConvertCheckNotNull; private boolean enableExperimentalWhyAreYouNotInlining; @@ -77,6 +82,10 @@ parseSystemPropertyOrDefault( "com.android.tools.r8.enableEmptyMemberRulesToDefaultInitRuleConversion", OptionalBool.UNKNOWN); + enableEmptyMemberRulesToDefaultInitRuleConversionWarnings = + parseSystemPropertyOrDefault( + "com.android.tools.r8.enableEmptyMemberRulesToDefaultInitRuleConversionWarnings", + false); enableExperimentalCheckEnumUnboxed = parseSystemPropertyOrDefault( "com.android.tools.r8.experimental.enablecheckenumunboxed", false); @@ -124,6 +133,7 @@ public ProguardConfigurationParserOptions build() { return new ProguardConfigurationParserOptions( enableEmptyMemberRulesToDefaultInitRuleConversion, + enableEmptyMemberRulesToDefaultInitRuleConversionWarnings, enableExperimentalCheckEnumUnboxed, enableExperimentalConvertCheckNotNull, enableExperimentalWhyAreYouNotInlining,
diff --git a/src/main/java/com/android/tools/r8/startup/diagnostic/MissingStartupProfileItemsDiagnostic.java b/src/main/java/com/android/tools/r8/startup/diagnostic/MissingStartupProfileItemsDiagnostic.java index c5ab7a9..1087442 100644 --- a/src/main/java/com/android/tools/r8/startup/diagnostic/MissingStartupProfileItemsDiagnostic.java +++ b/src/main/java/com/android/tools/r8/startup/diagnostic/MissingStartupProfileItemsDiagnostic.java
@@ -13,6 +13,7 @@ import com.android.tools.r8.position.Position; import com.android.tools.r8.profile.startup.profile.StartupProfileClassRule; import com.android.tools.r8.profile.startup.profile.StartupProfileMethodRule; +import com.android.tools.r8.utils.SystemPropertyUtils; import com.google.common.collect.Sets; import java.util.ArrayList; import java.util.Iterator; @@ -22,6 +23,10 @@ @KeepForApi public class MissingStartupProfileItemsDiagnostic implements Diagnostic { + private static final int THRESHOLD = + SystemPropertyUtils.parseSystemPropertyOrDefault( + "com.android.tools.r8.startup.diagnostic.limit", 100); + private final List<DexReference> missingStartupItems; private final Origin origin; @@ -43,6 +48,10 @@ @Override public String getDiagnosticMessage() { + if (THRESHOLD == 0) { + return "Found " + missingStartupItems.size() + " missing startup classes and methods"; + } + StringBuilder builder = new StringBuilder(); Iterator<DexReference> missingStartupItemIterator = missingStartupItems.iterator(); @@ -50,9 +59,21 @@ writeMissingStartupItem(builder, missingStartupItemIterator.next()); // Write remaining missing startup items with line separator before. - while (missingStartupItemIterator.hasNext()) { + int itemsToReport = (THRESHOLD > 0 ? THRESHOLD : Integer.MAX_VALUE) - 1; + while (missingStartupItemIterator.hasNext() && itemsToReport > 0) { writeMissingStartupItem( builder.append(System.lineSeparator()), missingStartupItemIterator.next()); + itemsToReport--; + } + + if (missingStartupItemIterator.hasNext()) { + assert THRESHOLD > 0; + int omittedItems = missingStartupItems.size() - THRESHOLD; + builder + .append(System.lineSeparator()) + .append("Found ") + .append(omittedItems) + .append(" other missing startup classes and methods"); } return builder.toString();
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java index 763198e..ad6845e 100644 --- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java +++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -241,6 +241,7 @@ return proguardConfiguration; } + public long created = -1; private final ProguardConfiguration proguardConfiguration; public final Reporter reporter;
diff --git a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsAdapterBase.java b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsAdapterBase.java new file mode 100644 index 0000000..ddc7b2d --- /dev/null +++ b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsAdapterBase.java
@@ -0,0 +1,30 @@ +// Copyright (c) 2024, the R8 project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. +package com.android.tools.r8.benchmarks; + +import com.google.gson.JsonObject; +import java.util.Collection; +import java.util.function.IntToLongFunction; + +public abstract class BenchmarkResultsAdapterBase { + + void addPropertyIfValueDifferentFromRepresentative( + JsonObject resultObject, + String propertyName, + int iteration, + Collection<?> results, + IntToLongFunction getter) { + if (results.isEmpty()) { + return; + } + long result = getter.applyAsLong(iteration); + if (iteration != 0) { + long representativeResult = getter.applyAsLong(0); + if (result == representativeResult) { + return; + } + } + resultObject.addProperty(propertyName, result); + } +}
diff --git a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsCollection.java b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsCollection.java index 7d006fc..9ca4f81 100644 --- a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsCollection.java +++ b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsCollection.java
@@ -86,11 +86,13 @@ } @Override - public void writeResults(Path path) throws IOException { + public void writeResults(Path path, BenchmarkResults warmupResults) throws IOException { for (Entry<String, BenchmarkResultsSingle> entry : results.entrySet()) { String name = entry.getKey(); BenchmarkResultsSingle result = entry.getValue(); - result.writeResults(path.resolve(name)); + BenchmarkResults warmupSubResults = + warmupResults != null ? warmupResults.getSubResults(name) : null; + result.writeResults(path.resolve(name), warmupSubResults); } } }
diff --git a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsSingle.java b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsSingle.java index e029bcd..22fbf4a 100644 --- a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsSingle.java +++ b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsSingle.java
@@ -10,6 +10,7 @@ import com.android.tools.r8.dex.DexSection; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import com.google.gson.JsonObject; import it.unimi.dsi.fastutil.ints.Int2ReferenceMap; import it.unimi.dsi.fastutil.longs.LongArrayList; import it.unimi.dsi.fastutil.longs.LongList; @@ -268,14 +269,20 @@ } @Override - public void writeResults(Path path) throws IOException { + public void writeResults(Path path, BenchmarkResults warmupResults) throws IOException { try (PrintStream out = new PrintStream(Files.newOutputStream(path))) { Gson gson = new GsonBuilder() .registerTypeAdapter( BenchmarkResultsSingle.class, new BenchmarkResultsSingleAdapter()) + .registerTypeAdapter( + BenchmarkResultsWarmup.class, new BenchmarkResultsWarmupAdapter()) .create(); - out.print(gson.toJson(this)); + JsonObject json = (JsonObject) gson.toJsonTree(this); + if (warmupResults != null) { + json.add("warmup", gson.toJsonTree(warmupResults)); + } + out.print(json); } } }
diff --git a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsSingleAdapter.java b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsSingleAdapter.java index 90a257c..7e62cfc 100644 --- a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsSingleAdapter.java +++ b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsSingleAdapter.java
@@ -11,10 +11,9 @@ import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; import java.lang.reflect.Type; -import java.util.Collection; -import java.util.function.IntToLongFunction; -public class BenchmarkResultsSingleAdapter implements JsonSerializer<BenchmarkResultsSingle> { +public class BenchmarkResultsSingleAdapter extends BenchmarkResultsAdapterBase + implements JsonSerializer<BenchmarkResultsSingle> { @Override public JsonElement serialize( @@ -43,7 +42,7 @@ for (int section : DexSection.getConstants()) { String sectionName = DexSection.typeName(section); String sectionNameUnderscore = - CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, sectionName); + CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, sectionName); addPropertyIfValueDifferentFromRepresentative( resultObject, "dex_" + sectionNameUnderscore + "_size", @@ -71,23 +70,4 @@ benchmarkObject.add("results", resultsArray); return benchmarkObject; } - - private void addPropertyIfValueDifferentFromRepresentative( - JsonObject resultObject, - String propertyName, - int iteration, - Collection<?> results, - IntToLongFunction getter) { - if (results.isEmpty()) { - return; - } - long result = getter.applyAsLong(iteration); - if (iteration != 0) { - long representativeResult = getter.applyAsLong(0); - if (result == representativeResult) { - return; - } - } - resultObject.addProperty(propertyName, result); - } }
diff --git a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsWarmup.java b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsWarmup.java index 16084c1..12e4b9a 100644 --- a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsWarmup.java +++ b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsWarmup.java
@@ -12,6 +12,9 @@ import it.unimi.dsi.fastutil.longs.LongArrayList; import it.unimi.dsi.fastutil.longs.LongList; import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; public class BenchmarkResultsWarmup implements BenchmarkResults { @@ -20,10 +23,19 @@ private long codeSizeResult = -1; private long resourceSizeResult = -1; + private final Map<String, BenchmarkResultsWarmup> results = new HashMap<>(); + public BenchmarkResultsWarmup(String name) { this.name = name; } + public BenchmarkResultsWarmup(String name, Map<String, Set<BenchmarkMetric>> benchmarks) { + this.name = name; + benchmarks.forEach( + (benchmarkName, metrics) -> + results.put(benchmarkName, new BenchmarkResultsWarmup(benchmarkName))); + } + @Override public void addRuntimeResult(long result) { runtimeResults.add(result); @@ -84,10 +96,13 @@ addRuntimeResult(averageRuntimeResult); } + public LongList getRuntimeResults() { + return runtimeResults; + } + @Override public BenchmarkResults getSubResults(String name) { - // When running warmups all results are amended to the single warmup result. - return this; + return results.get(name); } @Override @@ -95,6 +110,10 @@ return false; } + public int size() { + return runtimeResults.size(); + } + @Override public void printResults(ResultMode mode, boolean failOnCodeSizeDifferences) { if (runtimeResults.isEmpty()) { @@ -108,7 +127,7 @@ } @Override - public void writeResults(Path path) { + public void writeResults(Path path, BenchmarkResults warmupResults) { throw new Unimplemented(); } }
diff --git a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsWarmupAdapter.java b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsWarmupAdapter.java new file mode 100644 index 0000000..19cffef --- /dev/null +++ b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsWarmupAdapter.java
@@ -0,0 +1,32 @@ +// Copyright (c) 2024, the R8 project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. +package com.android.tools.r8.benchmarks; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import java.lang.reflect.Type; + +public class BenchmarkResultsWarmupAdapter extends BenchmarkResultsAdapterBase + implements JsonSerializer<BenchmarkResultsWarmup> { + + @Override + public JsonElement serialize( + BenchmarkResultsWarmup result, Type type, JsonSerializationContext jsonSerializationContext) { + JsonArray resultsArray = new JsonArray(); + for (int iteration = 0; iteration < result.size(); iteration++) { + JsonObject resultObject = new JsonObject(); + addPropertyIfValueDifferentFromRepresentative( + resultObject, + "runtime", + iteration, + result.getRuntimeResults(), + i -> result.getRuntimeResults().getLong(i)); + resultsArray.add(resultObject); + } + return resultsArray; + } +}
diff --git a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkRunner.java b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkRunner.java index 3f1db19..85ae724 100644 --- a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkRunner.java +++ b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkRunner.java
@@ -53,8 +53,12 @@ public void run(BenchmarkRunnerFunction fn) throws Exception { long warmupTotalTime = 0; BenchmarkConfig config = environment.getConfig(); - BenchmarkResults warmupResults = new BenchmarkResultsWarmup(config.getName()); + BenchmarkResultsWarmup warmupResults = null; if (warmups > 0) { + warmupResults = + config.isSingleBenchmark() + ? new BenchmarkResultsWarmup(config.getName()) + : new BenchmarkResultsWarmup(config.getName(), config.getSubBenchmarks()); long start = System.nanoTime(); for (int i = 0; i < warmups; i++) { fn.run(warmupResults); @@ -84,7 +88,7 @@ printMetaInfo("benchmark", getBenchmarkIterations(), benchmarkTotalTime); results.printResults(resultMode, environment.failOnCodeSizeDifferences()); if (environment.hasOutputPath()) { - results.writeResults(environment.getOutputPath()); + results.writeResults(environment.getOutputPath(), warmupResults); } System.out.println(); }
diff --git a/src/test/java/com/android/tools/r8/metadata/R8BuildMetadataTest.java b/src/test/java/com/android/tools/r8/metadata/R8BuildMetadataTest.java index 04b401c..24927fd 100644 --- a/src/test/java/com/android/tools/r8/metadata/R8BuildMetadataTest.java +++ b/src/test/java/com/android/tools/r8/metadata/R8BuildMetadataTest.java
@@ -51,15 +51,20 @@ ImmutableList.of(ExternalStartupClass.builder().setClassReference(mainReference).build()); R8BuildMetadata buildMetadata = testForR8(parameters.getBackend()) - .addInnerClasses(getClass()) + .addProgramClasses(Main.class) .addKeepMainRule(Main.class) .addArtProfileForRewriting( ExternalArtProfile.builder().addClassRule(mainReference).build()) - .apply(StartupTestingUtils.addStartupProfile(startupProfile)) .applyIf( parameters.isDexRuntime(), testBuilder -> - testBuilder.addAndroidResources(getTestResources()).enableOptimizedShrinking()) + testBuilder + .addAndroidResources(getTestResources()) + .addFeatureSplit(FeatureSplitMain.class) + .addKeepMainRule(FeatureSplitMain.class) + .apply(StartupTestingUtils.addStartupProfile(startupProfile)) + .enableIsolatedSplits(true) + .enableOptimizedShrinking()) .allowDiagnosticInfoMessages(parameters.canUseNativeMultidex()) .collectBuildMetadata() .setMinApi(parameters) @@ -86,27 +91,47 @@ } private void inspectDeserializedBuildMetadata(R8BuildMetadata buildMetadata) { - assertNotNull(buildMetadata.getBaselineProfileRewritingOptions()); - assertNotNull(buildMetadata.getOptions()); - assertNotNull(buildMetadata.getOptions().getKeepAttributesOptions()); + assertNotNull(buildMetadata.getBaselineProfileRewritingMetadata()); + assertNotNull(buildMetadata.getCompilationMetadata()); + R8FeatureSplitsMetadata featureSplitsMetadata = buildMetadata.getFeatureSplitsMetadata(); + if (parameters.isDexRuntime()) { + assertNotNull(featureSplitsMetadata); + assertTrue(featureSplitsMetadata.isIsolatedSplitsEnabled()); + assertEquals(1, featureSplitsMetadata.getFeatureSplits().size()); + R8FeatureSplitMetadata featureSplitMetadata = featureSplitsMetadata.getFeatureSplits().get(0); + assertNotNull(featureSplitMetadata); + assertEquals(1, featureSplitMetadata.getDexFilesMetadata().size()); + R8DexFileMetadata featureSplitDexFile = featureSplitMetadata.getDexFilesMetadata().get(0); + assertNotNull(featureSplitDexFile); + assertNotNull(featureSplitDexFile.getChecksum()); + } else { + assertNull(featureSplitsMetadata); + } + assertNotNull(buildMetadata.getOptionsMetadata()); + assertNotNull(buildMetadata.getOptionsMetadata().getKeepAttributesMetadata()); assertEquals( parameters.isCfRuntime() ? -1 : parameters.getApiLevel().getLevel(), - buildMetadata.getOptions().getMinApiLevel()); - assertFalse(buildMetadata.getOptions().isDebugModeEnabled()); + buildMetadata.getOptionsMetadata().getMinApiLevel()); + assertFalse(buildMetadata.getOptionsMetadata().isDebugModeEnabled()); if (parameters.isDexRuntime()) { - R8ResourceOptimizationOptions resourceOptimizationOptions = - buildMetadata.getResourceOptimizationOptions(); + R8ResourceOptimizationMetadata resourceOptimizationOptions = + buildMetadata.getResourceOptimizationMetadata(); assertNotNull(resourceOptimizationOptions); assertTrue(resourceOptimizationOptions.isOptimizedShrinkingEnabled()); } else { - assertNull(buildMetadata.getResourceOptimizationOptions()); + assertNull(buildMetadata.getResourceOptimizationMetadata()); } - R8StartupOptimizationOptions startupOptimizationOptions = + R8StartupOptimizationMetadata startupOptimizationOptions = buildMetadata.getStartupOptizationOptions(); - assertNotNull(startupOptimizationOptions); - assertEquals( - parameters.isDexRuntime() && parameters.canUseNativeMultidex() ? 1 : 0, - startupOptimizationOptions.getNumberOfStartupDexFiles()); + if (parameters.isDexRuntime()) { + assertNotNull(startupOptimizationOptions); + assertEquals( + parameters.isDexRuntime() && parameters.canUseNativeMultidex() ? 1 : 0, + startupOptimizationOptions.getNumberOfStartupDexFiles()); + } else { + assertNull(startupOptimizationOptions); + } + assertNotNull(buildMetadata.getStatsMetadata()); assertEquals(Version.LABEL, buildMetadata.getVersion()); } @@ -114,4 +139,9 @@ public static void main(String[] args) {} } + + static class FeatureSplitMain { + + public static void main(String[] args) {} + } }
diff --git a/src/test/java/com/android/tools/r8/regress/Regress371247958.java b/src/test/java/com/android/tools/r8/regress/Regress371247958.java new file mode 100644 index 0000000..96fc07d --- /dev/null +++ b/src/test/java/com/android/tools/r8/regress/Regress371247958.java
@@ -0,0 +1,61 @@ +// Copyright (c) 2024, the R8 project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. +package com.android.tools.r8.regress; + +import com.android.tools.r8.TestBase; +import com.android.tools.r8.TestParameters; +import com.android.tools.r8.TestParametersCollection; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) +public class Regress371247958 extends TestBase { + + private final TestParameters parameters; + + @Parameterized.Parameters(name = "{0}") + public static TestParametersCollection data() { + return getTestParameters().withDefaultRuntimes().withAllApiLevels().build(); + } + + public Regress371247958(TestParameters parameters) { + this.parameters = parameters; + } + + @Test + public void testR8() throws Exception { + testForR8(parameters.getBackend()) + .addProgramClasses(TestClass.class) + .addKeepMainRule(TestClass.class) + .setMinApi(parameters) + .compile() + .run(parameters.getRuntime(), TestClass.class) + // TODO(b/371247958): Should throw a RuntimeException + .assertSuccess(); + } + + @Test + public void testD8() throws Exception { + testForD8(parameters.getBackend()) + .addProgramClasses(TestClass.class) + .applyIf(parameters.isDexRuntime(), b -> b.setMinApi(parameters)) + .compile() + .run(parameters.getRuntime(), TestClass.class) + .assertFailureWithErrorThatThrows(RuntimeException.class); + } + + public static class TestClass { + static int throwException(RuntimeException runtimeException, boolean shouldReturnValue) { + if (shouldReturnValue) { + return 1; + } + throw runtimeException; + } + + public static void main(String[] p) throws Exception { + throwException(new RuntimeException("always thrown"), false); + } + } +}
diff --git a/src/test/java/com/android/tools/r8/shaking/EmptyMemberRulesToDefaultInitRuleConversionTest.java b/src/test/java/com/android/tools/r8/shaking/EmptyMemberRulesToDefaultInitRuleConversionTest.java index 564eac9..22a5d8a 100644 --- a/src/test/java/com/android/tools/r8/shaking/EmptyMemberRulesToDefaultInitRuleConversionTest.java +++ b/src/test/java/com/android/tools/r8/shaking/EmptyMemberRulesToDefaultInitRuleConversionTest.java
@@ -3,12 +3,8 @@ // BSD-style license that can be found in the LICENSE file. package com.android.tools.r8.shaking; -import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage; -import static com.android.tools.r8.DiagnosticsMatcher.diagnosticType; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentIf; -import static org.hamcrest.CoreMatchers.allOf; -import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assume.assumeTrue; @@ -17,9 +13,7 @@ import com.android.tools.r8.TestBase; import com.android.tools.r8.TestParameters; import com.android.tools.r8.ThrowableConsumer; -import com.android.tools.r8.errors.EmptyMemberRulesToDefaultInitRuleConversionDiagnostic; import com.android.tools.r8.utils.BooleanUtils; -import com.android.tools.r8.utils.StringUtils; import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; @@ -74,28 +68,9 @@ testForR8(parameters.getBackend()) .addInnerClasses(getClass()) .addKeepClassRules(Main.class) - .allowDiagnosticWarningMessages() .clearEnableEmptyMemberRulesToDefaultInitRuleConversion() .setMinApi(parameters) - .compileWithExpectedDiagnostics( - diagnostics -> - diagnostics - .assertOnlyWarnings() - .assertWarningsMatch( - allOf( - diagnosticType( - EmptyMemberRulesToDefaultInitRuleConversionDiagnostic.class), - diagnosticMessage( - equalTo( - StringUtils.joinLines( - "The current version of R8 implicitly keeps the default" - + " constructor for Proguard configuration rules that" - + " have no member pattern. If the following rule" - + " should continue to keep the default constructor in" - + " the next major version of R8, then it must be" - + " augmented with the member pattern `{ void <init>();" - + " }` to explicitly keep the default constructor:", - "-keep class " + Main.class.getTypeName())))))) + .compile() .inspect(inspector -> assertThat(inspector.clazz(Main.class).init(), isPresent())); }
diff --git a/src/test/testbase/java/com/android/tools/r8/benchmarks/BenchmarkResults.java b/src/test/testbase/java/com/android/tools/r8/benchmarks/BenchmarkResults.java index 42fb589..92cfd22 100644 --- a/src/test/testbase/java/com/android/tools/r8/benchmarks/BenchmarkResults.java +++ b/src/test/testbase/java/com/android/tools/r8/benchmarks/BenchmarkResults.java
@@ -40,7 +40,7 @@ void printResults(ResultMode resultMode, boolean failOnCodeSizeDifferences); - void writeResults(Path path) throws IOException; + void writeResults(Path path, BenchmarkResults warmupResults) throws IOException; static String prettyTime(long nanoTime) { return "" + (nanoTime / 1000000) + " ms";
diff --git a/tools/perf/d8.html b/tools/perf/d8.html index d495324..848ceea 100644 --- a/tools/perf/d8.html +++ b/tools/perf/d8.html
@@ -48,7 +48,8 @@ 'Dex size': { default: true }, 'Nondeterminism': { default: true }, 'Runtime': { default: true }, - 'Runtime variance': { default: false } + 'Runtime variance': { default: false }, + 'Warmup': { default: false } }); state.initializeZoom(); dom.initializeBenchmarkSelectors(); @@ -89,11 +90,9 @@ const runtimeData = filteredCommits.map( (c, i) => - selectedBenchmark in filteredCommits[i].benchmarks - ? getAllResults(selectedBenchmark, filteredCommits[i], "runtime", - results => dom.transformRuntimeData(results)) - .ns_to_s() - : NaN); + getAllResults( + selectedBenchmark, filteredCommits[i], "runtime", + results => dom.transformRuntimeData(results).ns_to_s())); const runtimeScatterData = []; for (const commit of filteredCommits.values()) { if (!(selectedBenchmark in commit.benchmarks)) { @@ -104,6 +103,12 @@ runtimeScatterData.push({ x: commit.index, y: runtime.ns_to_s() }); } } + const warmupData = + filteredCommits.map( + (c, i) => + getAllWarmupResults( + selectedBenchmark, filteredCommits[i], "runtime", + results => dom.transformRuntimeData(results).ns_to_s())); const skipped = (ctx, value) => ctx.p0.skip || ctx.p1.skip ? value : undefined; datasets.push(...[ @@ -176,6 +181,29 @@ } }, yAxisID: 'y_runtime' + }, + { + benchmark: selectedBenchmark, + type: 'line', + label: 'Warmup', + data: warmupData, + datalabels: { + labels: { + value: null + } + }, + tension: 0.1, + yAxisID: 'y_runtime', + segment: { + borderColor: ctx => + skipped( + ctx, + chart.get() + ? chart.get().data.datasets[ctx.datasetIndex].backgroundColor + : undefined), + borderDash: ctx => skipped(ctx, [6, 6]), + }, + spanGaps: true } ]); });
diff --git a/tools/perf/r8.html b/tools/perf/r8.html index 23b6c7b..a992005 100644 --- a/tools/perf/r8.html +++ b/tools/perf/r8.html
@@ -51,7 +51,8 @@ 'Oat size': { default: true }, 'Nondeterminism': { default: true }, 'Runtime': { default: true }, - 'Runtime variance': { default: false } + 'Runtime variance': { default: false }, + 'Warmup': { default: false } }); state.initializeZoom(); dom.initializeBenchmarkSelectors(); @@ -101,11 +102,9 @@ const runtimeData = filteredCommits.map( (c, i) => - selectedBenchmark in filteredCommits[i].benchmarks - ? getAllResults(selectedBenchmark, filteredCommits[i], "runtime", - results => dom.transformRuntimeData(results)) - .ns_to_s() - : NaN); + getAllResults( + selectedBenchmark, filteredCommits[i], "runtime", + results => dom.transformRuntimeData(results).ns_to_s())); const runtimeScatterData = []; for (const commit of filteredCommits.values()) { if (!(selectedBenchmark in commit.benchmarks)) { @@ -116,6 +115,12 @@ runtimeScatterData.push({ x: commit.index, y: runtime.ns_to_s() }); } } + const warmupData = + filteredCommits.map( + (c, i) => + getAllWarmupResults( + selectedBenchmark, filteredCommits[i], "runtime", + results => dom.transformRuntimeData(results).ns_to_s())); const skipped = (ctx, value) => ctx.p0.skip || ctx.p1.skip ? value : undefined; datasets.push(...[ @@ -254,6 +259,29 @@ } }, yAxisID: 'y_runtime' + }, + { + benchmark: selectedBenchmark, + type: 'line', + label: 'Warmup', + data: warmupData, + datalabels: { + labels: { + value: null + } + }, + tension: 0.1, + yAxisID: 'y_runtime', + segment: { + borderColor: ctx => + skipped( + ctx, + chart.get() + ? chart.get().data.datasets[ctx.datasetIndex].backgroundColor + : undefined), + borderDash: ctx => skipped(ctx, [6, 6]), + }, + spanGaps: true } ]); });
diff --git a/tools/perf/retrace.html b/tools/perf/retrace.html index 7437025..b6331c6 100644 --- a/tools/perf/retrace.html +++ b/tools/perf/retrace.html
@@ -46,7 +46,8 @@ state.initializeBenchmarks(); state.initializeLegends({ 'Runtime': { default: true }, - 'Runtime variance': { default: true } + 'Runtime variance': { default: true }, + 'Warmup': { default: false } }); state.initializeZoom(); dom.initializeBenchmarkSelectors(); @@ -69,11 +70,9 @@ const runtimeData = filteredCommits.map( (c, i) => - selectedBenchmark in filteredCommits[i].benchmarks - ? getAllResults(selectedBenchmark, filteredCommits[i], "runtime", - results => dom.transformRuntimeData(results)) - .ns_to_s() - : NaN); + getAllResults( + selectedBenchmark, filteredCommits[i], "runtime", + results => dom.transformRuntimeData(results).ns_to_s())); const runtimeScatterData = []; for (const commit of filteredCommits.values()) { if (!(selectedBenchmark in commit.benchmarks)) { @@ -84,6 +83,12 @@ runtimeScatterData.push({ x: commit.index, y: runtime.ns_to_s() }); } } + const warmupData = + filteredCommits.map( + (c, i) => + getAllWarmupResults( + selectedBenchmark, filteredCommits[i], "runtime", + results => dom.transformRuntimeData(results).ns_to_s())); const skipped = (ctx, value) => ctx.p0.skip || ctx.p1.skip ? value : undefined; datasets.push(...[ @@ -121,6 +126,29 @@ } }, yAxisID: 'y_runtime' + }, + { + benchmark: selectedBenchmark, + type: 'line', + label: 'Warmup', + data: warmupData, + datalabels: { + labels: { + value: null + } + }, + tension: 0.1, + yAxisID: 'y_runtime', + segment: { + borderColor: ctx => + skipped( + ctx, + chart.get() + ? chart.get().data.datasets[ctx.datasetIndex].backgroundColor + : undefined), + borderDash: ctx => skipped(ctx, [6, 6]), + }, + spanGaps: true } ]); });
diff --git a/tools/perf/scales.js b/tools/perf/scales.js index 8378e2f..bd3226a 100644 --- a/tools/perf/scales.js +++ b/tools/perf/scales.js
@@ -21,6 +21,7 @@ } console.assert(state.hasLegend('Runtime')); console.assert(state.hasLegend('Runtime variance')); + console.assert(state.hasLegend('Warmup')); scales.y_runtime = { position: state.hasLegend('Dex size') ? 'right' : 'left', title: { @@ -62,7 +63,9 @@ } if (scales.y_runtime) { scales.y_runtime.display = - state.isLegendSelected('Runtime') || state.isLegendSelected('Runtime variance'); + state.isLegendSelected('Runtime') + || state.isLegendSelected('Runtime variance') + || state.isLegendSelected('Warmup'); } }
diff --git a/tools/perf/utils.js b/tools/perf/utils.js index 13cd09c..e699f32 100644 --- a/tools/perf/utils.js +++ b/tools/perf/utils.js
@@ -1,11 +1,12 @@ // Copyright (c) 2024, the R8 project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -function getSingleResult(benchmark, commit, resultName, resultIteration = 0) { +function getSingleResult(benchmark, commit, resultName, resultIteration = 0, warmup = false) { if (!(benchmark in commit.benchmarks)) { return NaN; } - const allResults = commit.benchmarks[benchmark].results; + const benchmarkData = commit.benchmarks[benchmark]; + const allResults = warmup ? benchmarkData.warmup : benchmarkData.results; const resultsForIteration = allResults[resultIteration]; // If a given iteration does not declare a result, then the result // was the same as the first run. @@ -15,14 +16,25 @@ return resultsForIteration[resultName]; } -function getAllResults(benchmark, commit, resultName, transformation) { +function getAllResults(benchmark, commit, resultName, transformation, warmup = false) { + if (!(benchmark in commit.benchmarks)) { + return NaN; + } + const benchmarkData = commit.benchmarks[benchmark]; + if (warmup && !('warmup' in benchmarkData)) { + return NaN; + } const result = []; - const allResults = commit.benchmarks[benchmark].results; + const allResults = warmup ? benchmarkData.warmup : benchmarkData.results; for (var iteration = 0; iteration < allResults.length; iteration++) { - result.push(getSingleResult(benchmark, commit, resultName, iteration)); + result.push(getSingleResult(benchmark, commit, resultName, iteration, warmup)); } if (transformation) { return transformation(result); } return result; } + +function getAllWarmupResults(benchmark, commit, resultName, transformation) { + return getAllResults(benchmark, commit, resultName, transformation, true); +}