Merge commit '0b8f92c5d3b57c23eb2e0b0c7abf016c9451ee3f' into dev-release
diff --git a/.gitignore b/.gitignore index 13e30c3..b8c394a 100644 --- a/.gitignore +++ b/.gitignore
@@ -18,10 +18,12 @@ build/ buildSrc/out/ src/*/out +d8_r8/*/out gradle-app.setting gradle/* gradlew gradlew.bat +d8_r8/gradle* local.properties r8.ipr r8.iws @@ -295,7 +297,5 @@ tools/*/dalvik-4.0.4 tools/*/dalvik-4.0.4.tar.gz tools/*/dalvik.tar.gz -tools/*/dx -tools/*/dx.tar.gz tools/startup/__pycache__ venv/
diff --git a/build.gradle b/build.gradle index 11cc609..280db74 100644 --- a/build.gradle +++ b/build.gradle
@@ -5,8 +5,6 @@ import desugaredlibrary.CustomConversionAsmRewriterTask -import dx.DexMergerTask -import dx.DxTask import net.ltgt.gradle.errorprone.CheckSeverity import org.gradle.internal.os.OperatingSystem import tasks.DownloadDependency @@ -397,7 +395,6 @@ "linux/host/art-master", "linux/dalvik", "linux/dalvik-4.0.4", - "${osString}/dx", ] ] @@ -509,16 +506,6 @@ } } -task downloadDx { - cloudDependencies.each { entry -> - entry.value.each { entryFile -> - if (entryFile.endsWith("/dx")) { - dependsOn "${getDownloadDepsTaskName(entry.key, entryFile)}" - } - } - } -} - task downloadAndroidCts { cloudDependencies.each { entry -> entry.value.each { entryFile -> @@ -700,21 +687,17 @@ options.errorprone.check('MultipleTopLevelClasses', CheckSeverity.ERROR) options.errorprone.check('NarrowingCompoundAssignment', CheckSeverity.ERROR) - // TODO(b/270534077): These should likely be fixed/suppressed and become hard failures. - options.errorprone.check('JdkObsolete', CheckSeverity.OFF) + // TODO(b/270510095): These should likely be fixed/suppressed and become hard failures. options.errorprone.check('UnusedVariable', CheckSeverity.OFF) options.errorprone.check('EqualsUnsafeCast', CheckSeverity.OFF) options.errorprone.check('TypeParameterUnusedInFormals', CheckSeverity.OFF) - options.errorprone.check('LoopOverCharArray', CheckSeverity.OFF) options.errorprone.check('ImmutableEnumChecker', CheckSeverity.OFF) options.errorprone.check('BadImport', CheckSeverity.OFF) - options.errorprone.check('StringSplitter', CheckSeverity.OFF) options.errorprone.check('ComplexBooleanConstant', CheckSeverity.OFF) options.errorprone.check('StreamToIterable', CheckSeverity.OFF) options.errorprone.check('HidingField', CheckSeverity.OFF) options.errorprone.check('StreamResourceLeak', CheckSeverity.OFF) options.errorprone.check('CatchAndPrintStackTrace', CheckSeverity.OFF) - options.errorprone.check('ShortCircuitBoolean', CheckSeverity.OFF) options.errorprone.check('NonCanonicalType', CheckSeverity.OFF) options.errorprone.check('UnusedNestedClass', CheckSeverity.OFF) options.errorprone.check('AmbiguousMethodReference', CheckSeverity.OFF) @@ -1711,26 +1694,10 @@ dependsOn buildExampleJava18Jars dependsOn buildExampleAndroidApi def examplesDir = file("src/test/examples") - def noDexTests = [ - "multidex", - "multidex002", - "multidex004", - ] examplesDir.eachDir { dir -> - def name = dir.getName(); - if (!(name in noDexTests)) { - dependsOn "dex_example_${name}" - def exampleOutputDir = file("build/test/examples/" + name); - def dexPath = file("${exampleOutputDir}") - def debug = (name == "throwing") - if (!dexPath.exists()) { - dexPath.mkdirs() - } - task "dex_example_${name}"(type: DxTask, dependsOn: "jar_example_${name}") { - source = files(tasks.getByPath("jar_example_${name}")).asFileTree - destination = dexPath - debug = debug - } + def exampleOutputDir = file("build/test/examples/" + dir.getName()); + if (!exampleOutputDir.exists()) { + exampleOutputDir.mkdirs() } } } @@ -1759,10 +1726,11 @@ } } } else { - dependsOn "${taskName}_dexmerger" + dependsOn "${taskName}_smali" + dependsOn "${taskName}_jar" task "${taskName}_smali"(type: SmaliTask) { source = smaliFiles - destination = intermediateFile + destination = destFile } task "${taskName}_java"(type: JavaCompile) { source = javaFiles @@ -1777,15 +1745,6 @@ destinationDir = destDir from fileTree(dir: destDir, include: 'Test.class') } - task "${taskName}_dx"(type: DxTask, dependsOn: "${taskName}_jar") { - source = fileTree(dir: destDir, include: 'Test.jar') - destination = destDir - } - task "${taskName}_dexmerger"( - type: DexMergerTask, dependsOn: ["${taskName}_dx", "${taskName}_smali"]) { - source = fileTree(dir: destDir, include: ["classes.dex", intermediateFileName]) - destination = destFile - } } } }
diff --git a/buildSrc/src/main/java/dx/DexMergerTask.java b/buildSrc/src/main/java/dx/DexMergerTask.java deleted file mode 100644 index 409337c..0000000 --- a/buildSrc/src/main/java/dx/DexMergerTask.java +++ /dev/null
@@ -1,98 +0,0 @@ -// Copyright (c) 2019, 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 dx; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import javax.inject.Inject; -import org.gradle.api.DefaultTask; -import org.gradle.api.file.FileCollection; -import org.gradle.api.file.RegularFileProperty; -import org.gradle.api.provider.SetProperty; -import org.gradle.api.tasks.InputFiles; -import org.gradle.api.tasks.OutputFile; -import org.gradle.api.tasks.TaskAction; -import org.gradle.workers.WorkAction; -import org.gradle.workers.WorkParameters; -import org.gradle.workers.WorkerExecutor; -import utils.Utils; - -public class DexMergerTask extends DefaultTask { - - private final WorkerExecutor workerExecutor; - - private FileCollection source; - private File destination; - - @Inject - public DexMergerTask(WorkerExecutor workerExecutor) { - this.workerExecutor = workerExecutor; - } - - @InputFiles - public FileCollection getSource() { - return source; - } - - public void setSource(FileCollection source) { - this.source = source; - } - - @OutputFile - public File getDestination() { - return destination; - } - - public void setDestination(File destination) { - this.destination = destination; - } - - @TaskAction - void exec() { - workerExecutor - .noIsolation() - .submit( - RunDexMerger.class, - parameters -> { - parameters.getSources().set(source.getFiles()); - parameters.getDestination().set(destination); - }); - } - - public interface RunDexMergerParameters extends WorkParameters { - - SetProperty<File> getSources(); - - RegularFileProperty getDestination(); - - RegularFileProperty getDexMergerExecutable(); - } - - public abstract static class RunDexMerger implements WorkAction<RunDexMergerParameters> { - - @Override - public void execute() { - try { - RunDexMergerParameters parameters = getParameters(); - List<String> command = new ArrayList<>(); - command.add(Utils.dexMergerExecutable().toString()); - command.add(parameters.getDestination().getAsFile().get().getCanonicalPath()); - for (File source : parameters.getSources().get()) { - command.add(source.getCanonicalPath()); - } - Process dexMerger = new ProcessBuilder(command).inheritIO().start(); - int exitCode = dexMerger.waitFor(); - if (exitCode != 0) { - throw new RuntimeException("Dex merger failed with code " + exitCode); - } - } catch (IOException e) { - throw new java.io.UncheckedIOException(e); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } - } -}
diff --git a/buildSrc/src/main/java/dx/DxTask.java b/buildSrc/src/main/java/dx/DxTask.java deleted file mode 100644 index a66733a..0000000 --- a/buildSrc/src/main/java/dx/DxTask.java +++ /dev/null
@@ -1,118 +0,0 @@ -// Copyright (c) 2019, 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 dx; - -import java.io.File; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.util.ArrayList; -import java.util.List; -import javax.inject.Inject; -import org.gradle.api.DefaultTask; -import org.gradle.api.file.FileCollection; -import org.gradle.api.file.RegularFileProperty; -import org.gradle.api.provider.Property; -import org.gradle.api.provider.SetProperty; -import org.gradle.api.tasks.Input; -import org.gradle.api.tasks.InputFiles; -import org.gradle.api.tasks.OutputDirectory; -import org.gradle.api.tasks.TaskAction; -import org.gradle.workers.WorkAction; -import org.gradle.workers.WorkParameters; -import org.gradle.workers.WorkerExecutor; -import utils.Utils; - -public class DxTask extends DefaultTask { - - private final WorkerExecutor workerExecutor; - - private FileCollection source; - private File destination; - private boolean debug; - - @Inject - public DxTask(WorkerExecutor workerExecutor) { - this.workerExecutor = workerExecutor; - } - - @InputFiles - public FileCollection getSource() { - return source; - } - - public void setSource(FileCollection source) { - this.source = source; - } - - @OutputDirectory - public File getDestination() { - return destination; - } - - public void setDestination(File destination) { - this.destination = destination; - } - - @Input - public boolean isDebug() { - return debug; - } - - public void setDebug(boolean debug) { - this.debug = debug; - } - - @TaskAction - void exec() { - workerExecutor - .noIsolation() - .submit( - RunDx.class, - parameters -> { - parameters.getSources().set(source.getFiles()); - parameters.getDestination().set(destination); - parameters.getDebug().set(debug); - }); - } - - public interface RunDxParameters extends WorkParameters { - - SetProperty<File> getSources(); - - RegularFileProperty getDestination(); - - Property<Boolean> getDebug(); - } - - public abstract static class RunDx implements WorkAction<RunDxParameters> { - - @Override - public void execute() { - RunDxParameters parameters = getParameters(); - try { - List<String> command = new ArrayList<>(); - command.add(Utils.dxExecutable().toString()); - command.add("--dex"); - command.add("--output"); - command.add(parameters.getDestination().getAsFile().get().getCanonicalPath()); - if (parameters.getDebug().get()) { - command.add("--debug"); - } - for (File source : parameters.getSources().get()) { - command.add(source.getCanonicalPath()); - } - - Process dx = new ProcessBuilder(command).inheritIO().start(); - int exitCode = dx.waitFor(); - if (exitCode != 0) { - throw new RuntimeException("dx failed with code " + exitCode); - } - } catch (IOException e) { - throw new UncheckedIOException(e); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } - } -}
diff --git a/commonBuildSrc/src/main/kotlin/Dependencies.kt b/commonBuildSrc/src/main/kotlin/Dependencies.kt index b93dbcf..c10a576 100644 --- a/commonBuildSrc/src/main/kotlin/Dependencies.kt +++ b/commonBuildSrc/src/main/kotlin/Dependencies.kt
@@ -44,6 +44,7 @@ const val kotlinVersion = "1.8.0" const val kotlinMetadataVersion = "0.6.0" const val smaliVersion = "2.2b4" + const val errorproneVersion = "2.18.0" } object Deps { @@ -60,4 +61,5 @@ val kotlinStdLib by lazy { "org.jetbrains.kotlin:kotlin-stdlib:${Versions.kotlinVersion}" } val kotlinReflect by lazy { "org.jetbrains.kotlin:kotlin-reflect:${Versions.kotlinVersion}" } val smali by lazy { "org.smali:smali:${Versions.smaliVersion}" } + val errorprone by lazy { "com.google.errorprone:error_prone_core:${Versions.errorproneVersion}" } }
diff --git a/d8_r8/main/build.gradle.kts b/d8_r8/main/build.gradle.kts index e664753..10d4b2b 100644 --- a/d8_r8/main/build.gradle.kts +++ b/d8_r8/main/build.gradle.kts
@@ -2,9 +2,12 @@ // 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. +import net.ltgt.gradle.errorprone.errorprone + plugins { `kotlin-dsl` id("dependencies-plugin") + id("net.ltgt.errorprone") version "3.0.1" } java { @@ -26,8 +29,77 @@ implementation(Deps.guava) implementation(Deps.joptSimple) implementation(Deps.kotlinMetadata) + errorprone(Deps.errorprone) } tasks.withType<JavaCompile> { println("NOTE: Running with JDK: " + org.gradle.internal.jvm.Jvm.current().javaHome) + + // Enable error prone for D8/R8 main sources and make all warnings errors. + // Warnings that we have chosen not to fix (or suppress) are disabled outright below. + options.compilerArgs.add("-Werror") + options.errorprone.isEnabled.set(true) + + // Non-default / Experimental checks - explicitly enforced. + options.errorprone.error("RemoveUnusedImports") + options.errorprone.error("InconsistentOverloads") + options.errorprone.error("MissingDefault") + options.errorprone.error("MultipleTopLevelClasses") + options.errorprone.error("NarrowingCompoundAssignment") + + // TODO(b/270510095): These should likely be fixed/suppressed and become hard failures. + options.errorprone.disable("UnusedVariable") + options.errorprone.disable("EqualsUnsafeCast") + options.errorprone.disable("TypeParameterUnusedInFormals") + options.errorprone.disable("ImmutableEnumChecker") + options.errorprone.disable("BadImport") + options.errorprone.disable("ComplexBooleanConstant") + options.errorprone.disable("StreamToIterable") + options.errorprone.disable("HidingField") + options.errorprone.disable("StreamResourceLeak") + options.errorprone.disable("CatchAndPrintStackTrace") + options.errorprone.disable("NonCanonicalType") + options.errorprone.disable("UnusedNestedClass") + options.errorprone.disable("AmbiguousMethodReference") + options.errorprone.disable("InvalidParam") + options.errorprone.disable("CharacterGetNumericValue") + options.errorprone.disable("ModifyCollectionInEnhancedForLoop") + options.errorprone.disable("EmptyCatch") + options.errorprone.disable("ArgumentSelectionDefectChecker") + options.errorprone.disable("ImmutableAnnotationChecker") + options.errorprone.disable("ObjectToString") + options.errorprone.disable("DoNotClaimAnnotations") + options.errorprone.disable("AnnotateFormatMethod") + + // TODO(b/270537614): Remove finalize uses. + options.errorprone.disable("Finalize") + + // The following warnings could/should be active but are hit by R8 now so silence them. + options.errorprone.disable("EqualsGetClass") + options.errorprone.disable("MixedMutabilityReturnType") + options.errorprone.disable("UnnecessaryParentheses") + options.errorprone.disable("DoNotCallSuggester") + options.errorprone.disable("InlineMeSuggester") + options.errorprone.disable("MutablePublicArray") + options.errorprone.disable("DefaultCharset") + options.errorprone.disable("InconsistentCapitalization") + options.errorprone.disable("InlineFormatString") + options.errorprone.disable("MissingImplementsComparable") + + // Warnings that cause unwanted edits (e.g., inability to write informative asserts). + options.errorprone.disable("AlreadyChecked") + + // JavaDoc related warnings. Would be nice to resolve but of no real consequence. + options.errorprone.disable("InvalidLink") + options.errorprone.disable("InvalidBlockTag") + options.errorprone.disable("InvalidInlineTag") + options.errorprone.disable("EmptyBlockTag") + options.errorprone.disable("MissingSummary") + options.errorprone.disable("UnrecognisedJavadocTag") + options.errorprone.disable("AlmostJavadoc") + + // Moving away from identity and canonical items is not planned. + options.errorprone.disable("ReferenceEquality") + options.errorprone.disable("IdentityHashMapUsage") + }
diff --git a/scripts/update-host-dx.sh b/scripts/update-host-dx.sh deleted file mode 100755 index 6d4a3a8..0000000 --- a/scripts/update-host-dx.sh +++ /dev/null
@@ -1,51 +0,0 @@ -#! /bin/bash -# Copyright (c) 2016, 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. - -# This script will update the host dx and dexmerger tools in tools/linux/dx. - -# Before running this script make sure the dx and dexmerger versions required are built -# in ~/android/master (There are probably simpler ways to just build dx and dexmerger): -# -# m -j24 build-art -# -# Maybe also run the Art host tests: -# -# mm -j24 art-test-host -# - -ANDROID_CHECKOUT=~/android/master -ANDROID_HOST_BUILD=$ANDROID_CHECKOUT/out/host/linux-x86 -LINUX_TOOLS=tools/linux -DX_DIR=dx -DEST=$LINUX_TOOLS/$DX_DIR - -# Clean out the previous version of Art -rm -rf $DEST - -# Required binaries and scripts. -mkdir -p $DEST/bin -cp $ANDROID_HOST_BUILD/bin/dx $DEST/bin -cp $ANDROID_HOST_BUILD/bin/dexmerger $DEST/bin - -# Required framework files. -mkdir -p $DEST/framework -cp $ANDROID_HOST_BUILD/framework/dx.jar $DEST/framework - -# Build the tar to upload to Google Cloud Storage. -DX_ARCHIVE=$DX_DIR.tar.gz -pushd $LINUX_TOOLS > /dev/null -rm -f $DX_ARCHIVE -rm -f $DX_ARCHIVE.sha1 -tar caf $DX_ARCHIVE $DX_DIR -popd > /dev/null - -echo "New $LINUX_TOOLS/$DX_ARCHIVE archive created." -echo "" -echo "Now run:" -echo "" -echo " cd $LINUX_TOOLS" -echo " upload_to_google_storage.py --bucket r8-deps $DX_DIR.tar.gz" -echo "" -echo "to upload to Google Cloud Storage"
diff --git a/src/main/java/com/android/tools/r8/ClassFileConsumer.java b/src/main/java/com/android/tools/r8/ClassFileConsumer.java index 79330fb..fa3e5c4 100644 --- a/src/main/java/com/android/tools/r8/ClassFileConsumer.java +++ b/src/main/java/com/android/tools/r8/ClassFileConsumer.java
@@ -4,7 +4,6 @@ package com.android.tools.r8; import com.android.tools.r8.utils.ArchiveBuilder; -import com.android.tools.r8.utils.ClassFileConsumerDataImpl; import com.android.tools.r8.utils.DescriptorUtils; import com.android.tools.r8.utils.DirectoryBuilder; import com.android.tools.r8.utils.OutputBuilder; @@ -37,28 +36,22 @@ * {@param handler}. If an error is reported via {@param handler} and no exceptions are thrown, * then the compiler guaranties to exit with an error. * - * <p>The {@link ByteDataView} obtained by way of {@param data} object can only be assumed valid - * during the duration of the accept. If the bytes are needed beyond that, a copy must be made - * elsewhere. + * <p>The {@link ByteDataView} {@param data} object can only be assumed valid during the duration + * of the accept. If the bytes are needed beyond that, a copy must be made elsewhere. * - * @param data Java class-file encoded data and its meta-data. + * @param data Java class-file encoded data. + * @param descriptor Class descriptor of the class the data pertains to. + * @param handler Diagnostics handler for reporting. */ - default void acceptClassFile(ClassFileConsumerData data) { - accept(data.getByteDataView(), data.getClassDescriptor(), data.getDiagnosticsHandler()); - } - - @Deprecated - default void accept(ByteDataView data, String descriptor, DiagnosticsHandler handler) { - acceptClassFile(new ClassFileConsumerDataImpl(data, descriptor, handler)); - } + void accept(ByteDataView data, String descriptor, DiagnosticsHandler handler); /** Empty consumer to request the production of the resource but ignore its value. */ static ClassFileConsumer emptyConsumer() { return ForwardingConsumer.EMPTY_CONSUMER; } + /** Forwarding consumer to delegate to an optional existing consumer. */ @Keep - @Deprecated class ForwardingConsumer implements ClassFileConsumer { private static final ClassFileConsumer EMPTY_CONSUMER = new ForwardingConsumer(null); @@ -75,9 +68,9 @@ } @Override - public void acceptClassFile(ClassFileConsumerData data) { + public void accept(ByteDataView data, String descriptor, DiagnosticsHandler handler) { if (consumer != null) { - consumer.acceptClassFile(data); + consumer.accept(data, descriptor, handler); } } @@ -124,12 +117,9 @@ } @Override - public void acceptClassFile(ClassFileConsumerData data) { - super.acceptClassFile(data); - outputBuilder.addFile( - DescriptorUtils.getClassFileName(data.getClassDescriptor()), - data.getByteDataView(), - data.getDiagnosticsHandler()); + public void accept(ByteDataView data, String descriptor, DiagnosticsHandler handler) { + super.accept(data, descriptor, handler); + outputBuilder.addFile(DescriptorUtils.getClassFileName(descriptor), data, handler); } @Override @@ -204,12 +194,9 @@ } @Override - public void acceptClassFile(ClassFileConsumerData data) { - super.acceptClassFile(data); - outputBuilder.addFile( - DescriptorUtils.getClassFileName(data.getClassDescriptor()), - data.getByteDataView(), - data.getDiagnosticsHandler()); + public void accept(ByteDataView data, String descriptor, DiagnosticsHandler handler) { + super.accept(data, descriptor, handler); + outputBuilder.addFile(DescriptorUtils.getClassFileName(descriptor), data, handler); } @Override
diff --git a/src/main/java/com/android/tools/r8/ClassFileConsumerData.java b/src/main/java/com/android/tools/r8/ClassFileConsumerData.java deleted file mode 100644 index eeef801..0000000 --- a/src/main/java/com/android/tools/r8/ClassFileConsumerData.java +++ /dev/null
@@ -1,26 +0,0 @@ -// Copyright (c) 2023, 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; - -/** Data provided in the primary callback of {@link ClassFileConsumer}. */ -@Keep -public interface ClassFileConsumerData { - - /** - * View of the Java class-file encoded data. - * - * <p>The obtained {@link ByteDataView} object can only be assumed valid during the duration of - * the accept method. If the bytes are needed beyond that, a copy must be made elsewhere. - */ - ByteDataView getByteDataView(); - - /** Copy of the bytes for the Java class-file encoded data. */ - byte[] getByteDataCopy(); - - /** Class descriptor of the class the data pertains to. */ - String getClassDescriptor(); - - /** Diagnostics handler for reporting. */ - DiagnosticsHandler getDiagnosticsHandler(); -}
diff --git a/src/main/java/com/android/tools/r8/D8.java b/src/main/java/com/android/tools/r8/D8.java index 85a0fbf..52735a5 100644 --- a/src/main/java/com/android/tools/r8/D8.java +++ b/src/main/java/com/android/tools/r8/D8.java
@@ -53,6 +53,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; @@ -323,6 +324,8 @@ timing.end(); // post-converter + reportSyntheticInformation(appView); + if (options.isGeneratingClassFiles()) { new CfApplicationWriter(appView, marker).write(options.getClassFileConsumer(), inputApp); } else { @@ -341,6 +344,15 @@ } } + private static void reportSyntheticInformation(AppView<?> appView) { + SyntheticInfoConsumer consumer = appView.options().getSyntheticInfoConsumer(); + if (consumer == null || !appView.options().intermediate) { + return; + } + appView.getSyntheticItems().reportSyntheticsInformation(consumer); + consumer.finished(); + } + private static void initializeAssumeInfoCollection(AppView<AppInfo> appView) { AssumeInfoCollection.Builder assumeInfoCollectionBuilder = AssumeInfoCollection.builder(); AbstractValueFactory abstractValueFactory = appView.abstractValueFactory(); @@ -440,14 +452,12 @@ private final List<ProgramResource> resources = new ArrayList<>(); @Override - public synchronized void acceptDexIndexedFile(DexIndexedConsumerData data) { + public synchronized void accept( + int fileIndex, ByteDataView data, Set<String> descriptors, DiagnosticsHandler handler) { // TODO(b/154106502): Map Origin information. resources.add( ProgramResource.fromBytes( - Origin.unknown(), - ProgramResource.Kind.DEX, - data.getByteDataCopy(), - data.getClassDescriptors())); + Origin.unknown(), ProgramResource.Kind.DEX, data.copyByteData(), descriptors)); } @Override
diff --git a/src/main/java/com/android/tools/r8/D8Command.java b/src/main/java/com/android/tools/r8/D8Command.java index 13c12a2..d1495c2 100644 --- a/src/main/java/com/android/tools/r8/D8Command.java +++ b/src/main/java/com/android/tools/r8/D8Command.java
@@ -90,6 +90,7 @@ private List<GlobalSyntheticsResourceProvider> globalSyntheticsResourceProviders = new ArrayList<>(); private DesugarGraphConsumer desugarGraphConsumer = null; + private SyntheticInfoConsumer syntheticInfoConsumer = null; private StringConsumer desugaredLibraryKeepRuleConsumer = null; private String synthesizedClassPrefix = ""; private boolean enableMainDexListCheck = true; @@ -268,6 +269,21 @@ return self(); } + /** Get the consumer that will receive information about compiler synthesized classes. */ + public SyntheticInfoConsumer getSyntheticInfoConsumer() { + return syntheticInfoConsumer; + } + + /** + * Set the consumer that will receive information about compiler synthesized classes. + * + * <p>Setting the consumer will clear any previously set consumer. + */ + public Builder setSyntheticInfoConsumer(SyntheticInfoConsumer syntheticInfoConsumer) { + this.syntheticInfoConsumer = syntheticInfoConsumer; + return self(); + } + /** * Add a collection of startup profile providers that should be used for distributing the * program classes in dex. @@ -456,6 +472,7 @@ getIncludeClassesChecksum(), getDexClassChecksumFilter(), getDesugarGraphConsumer(), + getSyntheticInfoConsumer(), desugaredLibraryKeepRuleConsumer, desugaredLibrarySpecification, getAssertionsConfiguration(), @@ -479,6 +496,7 @@ private final boolean intermediate; private final GlobalSyntheticsConsumer globalSyntheticsConsumer; + private final SyntheticInfoConsumer syntheticInfoConsumer; private final DesugarGraphConsumer desugarGraphConsumer; private final StringConsumer desugaredLibraryKeepRuleConsumer; private final DesugaredLibrarySpecification desugaredLibrarySpecification; @@ -549,6 +567,7 @@ boolean encodeChecksum, BiPredicate<String, Long> dexClassChecksumFilter, DesugarGraphConsumer desugarGraphConsumer, + SyntheticInfoConsumer syntheticInfoConsumer, StringConsumer desugaredLibraryKeepRuleConsumer, DesugaredLibrarySpecification desugaredLibrarySpecification, List<AssertionsConfiguration> assertionsConfiguration, @@ -590,6 +609,7 @@ classConflictResolver); this.intermediate = intermediate; this.globalSyntheticsConsumer = globalSyntheticsConsumer; + this.syntheticInfoConsumer = syntheticInfoConsumer; this.desugarGraphConsumer = desugarGraphConsumer; this.desugaredLibraryKeepRuleConsumer = desugaredLibraryKeepRuleConsumer; this.desugaredLibrarySpecification = desugaredLibrarySpecification; @@ -606,6 +626,7 @@ super(printHelp, printVersion); intermediate = false; globalSyntheticsConsumer = null; + syntheticInfoConsumer = null; desugarGraphConsumer = null; desugaredLibraryKeepRuleConsumer = null; desugaredLibrarySpecification = null; @@ -641,6 +662,7 @@ internal.intermediate = intermediate; internal.retainCompileTimeAnnotations = intermediate; internal.setGlobalSyntheticsConsumer(globalSyntheticsConsumer); + internal.setSyntheticInfoConsumer(syntheticInfoConsumer); internal.desugarGraphConsumer = desugarGraphConsumer; internal.mainDexKeepRules = mainDexKeepRules; internal.proguardMapConsumer = proguardMapConsumer;
diff --git a/src/main/java/com/android/tools/r8/DexFilePerClassFileConsumer.java b/src/main/java/com/android/tools/r8/DexFilePerClassFileConsumer.java index 68e6f12..1675cb2 100644 --- a/src/main/java/com/android/tools/r8/DexFilePerClassFileConsumer.java +++ b/src/main/java/com/android/tools/r8/DexFilePerClassFileConsumer.java
@@ -34,7 +34,7 @@ @KeepForSubclassing public interface DexFilePerClassFileConsumer extends ProgramConsumer, ByteBufferProvider { - boolean SHOULD_COMBINE_SYNTHETIC_CLASSES = true; + static final boolean SHOULD_COMBINE_SYNTHETIC_CLASSES = true; /** * Callback to receive DEX data for a single Java class-file input and its companion classes. @@ -42,30 +42,24 @@ * <p>There is no guaranteed order and files might be written concurrently. * * <p>The consumer is expected not to throw, but instead report any errors via the diagnostics - * {@link DiagnosticsHandler} in the callback data. If an error is reported via handler and no - * exceptions are thrown, then the compiler guaranties to exit with an error. + * {@param handler}. If an error is reported via {@param handler} and no exceptions are thrown, + * then the compiler guaranties to exit with an error. * - * <p>The {@link ByteDataView} obtained from the {@param data} object can only be assumed valid - * during the duration of the accept. If the bytes are needed beyond that, a copy must be made - * elsewhere. + * <p>The {@link ByteDataView} {@param data} object can only be assumed valid during the duration + * of the accept. If the bytes are needed beyond that, a copy must be made elsewhere. + * + * @param primaryClassDescriptor Class descriptor of the class from the input class-file. + * @param data DEX encoded data in a ByteDataView wrapper. + * @param descriptors Class descriptors for all classes defined in the DEX data. + * @param handler Diagnostics handler for reporting. */ - default void acceptDexFile(DexFilePerClassFileConsumerData data) { - accept( - data.getPrimaryClassDescriptor(), - data.getByteDataView(), - data.getClassDescriptors(), - data.getDiagnosticsHandler()); - } - - // Any new implementation should not use or call the deprecated accept method. - @Deprecated default void accept( String primaryClassDescriptor, ByteDataView data, Set<String> descriptors, DiagnosticsHandler handler) { - // To avoid breaking binary compatibility, old consumers not implementing the new API will be - // forwarded to. New consumers must implement the accept method on the data object. + // To avoid breaking binary compatiblity, old consumers not implementing the new API will be + // forwarded to. New consumers must implement the accept on ByteDataView. accept(primaryClassDescriptor, data.copyByteData(), descriptors, handler); } @@ -98,8 +92,8 @@ return ForwardingConsumer.EMPTY_CONSUMER; } + /** Forwarding consumer to delegate to an optional existing consumer. */ @Keep - @Deprecated class ForwardingConsumer implements DexFilePerClassFileConsumer { private static final DexFilePerClassFileConsumer EMPTY_CONSUMER = new ForwardingConsumer(null); @@ -116,9 +110,13 @@ } @Override - public void acceptDexFile(DexFilePerClassFileConsumerData data) { + public void accept( + String primaryClassDescriptor, + ByteDataView data, + Set<String> descriptors, + DiagnosticsHandler handler) { if (consumer != null) { - consumer.acceptDexFile(data); + consumer.accept(primaryClassDescriptor, data, descriptors, handler); } } @@ -180,12 +178,13 @@ } @Override - public void acceptDexFile(DexFilePerClassFileConsumerData data) { - super.acceptDexFile(data); - outputBuilder.addFile( - getDexFileName(data.getPrimaryClassDescriptor()), - data.getByteDataView(), - data.getDiagnosticsHandler()); + public void accept( + String primaryClassDescriptor, + ByteDataView data, + Set<String> descriptors, + DiagnosticsHandler handler) { + super.accept(primaryClassDescriptor, data, descriptors, handler); + outputBuilder.addFile(getDexFileName(primaryClassDescriptor), data, handler); } @Override @@ -263,12 +262,13 @@ } @Override - public void acceptDexFile(DexFilePerClassFileConsumerData data) { - super.acceptDexFile(data); - outputBuilder.addFile( - getDexFileName(data.getPrimaryClassDescriptor()), - data.getByteDataView(), - data.getDiagnosticsHandler()); + public void accept( + String primaryClassDescriptor, + ByteDataView data, + Set<String> descriptors, + DiagnosticsHandler handler) { + super.accept(primaryClassDescriptor, data, descriptors, handler); + outputBuilder.addFile(getDexFileName(primaryClassDescriptor), data, handler); } @Override
diff --git a/src/main/java/com/android/tools/r8/DexFilePerClassFileConsumerData.java b/src/main/java/com/android/tools/r8/DexFilePerClassFileConsumerData.java index fba6b8d..e69de29 100644 --- a/src/main/java/com/android/tools/r8/DexFilePerClassFileConsumerData.java +++ b/src/main/java/com/android/tools/r8/DexFilePerClassFileConsumerData.java
@@ -1,35 +0,0 @@ -// Copyright (c) 2023, 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; - -import java.util.Set; - -/** Data provided in the primary callback of {@link DexFilePerClassFileConsumer}. */ -@Keep -public interface DexFilePerClassFileConsumerData { - - /** Class descriptor of the class from the input class-file. */ - String getPrimaryClassDescriptor(); - - /** DEX encoded data in a ByteDataView wrapper. */ - ByteDataView getByteDataView(); - - /** Copy of the bytes for the DEX encoded data. */ - byte[] getByteDataCopy(); - - /** Class descriptors for all classes defined in the DEX data. */ - Set<String> getClassDescriptors(); - - /** Diagnostics handler for reporting. */ - DiagnosticsHandler getDiagnosticsHandler(); - - /** - * Class descriptor of the primary-class's synthetic context. - * - * <p>If primary class is a compiler-synthesized class (i.e. it is an input that was synthesized - * by a prior D8 intermediate compilation) then the value is the descriptor of the class that - * caused the primary class to be synthesized. The value is null in all other cases. - */ - String getSynthesizingContextForPrimaryClass(); -}
diff --git a/src/main/java/com/android/tools/r8/DexIndexedConsumer.java b/src/main/java/com/android/tools/r8/DexIndexedConsumer.java index cbccf59..39f5b2e 100644 --- a/src/main/java/com/android/tools/r8/DexIndexedConsumer.java +++ b/src/main/java/com/android/tools/r8/DexIndexedConsumer.java
@@ -46,22 +46,17 @@ * <p>There is no guaranteed order and files might be written concurrently. * * <p>The consumer is expected not to throw, but instead report any errors via the diagnostics - * {@link DiagnosticsHandler} in the callback data. If an error is reported via handler and no - * exceptions are thrown, then the compiler guaranties to exit with an error. + * {@param handler}. If an error is reported via {@param handler} and no exceptions are thrown, + * then the compiler guaranties to exit with an error. * - * <p>The {@link ByteDataView} obtained from the {@param data} object can only be assumed valid - * during the duration of the accept. If the bytes are needed beyond that, a copy must be made - * elsewhere. + * <p>The {@link ByteDataView} {@param data} object can only be assumed valid during the duration + * of the accept. If the bytes are needed beyond that, a copy must be made elsewhere. + * + * @param fileIndex Index of the DEX file for multi-dexing. Files are zero-indexed. + * @param data DEX encoded data in a ByteDataView wrapper. + * @param descriptors Class descriptors for all classes defined in the DEX data. + * @param handler Diagnostics handler for reporting. */ - default void acceptDexIndexedFile(DexIndexedConsumerData data) { - accept( - data.getFileIndex(), - data.getByteDataView(), - data.getClassDescriptors(), - data.getDiagnosticsHandler()); - } - - @Deprecated default void accept( int fileIndex, ByteDataView data, Set<String> descriptors, DiagnosticsHandler handler) { // To avoid breaking binary compatiblity, old consumers not implementing the new API will be @@ -82,8 +77,8 @@ return ForwardingConsumer.EMPTY_CONSUMER; } + /** Forwarding consumer to delegate to an optional existing consumer. */ @Keep - @Deprecated class ForwardingConsumer implements DexIndexedConsumer { private static final DexIndexedConsumer EMPTY_CONSUMER = new ForwardingConsumer(null); @@ -100,9 +95,10 @@ } @Override - public void acceptDexIndexedFile(DexIndexedConsumerData data) { + public void accept( + int fileIndex, ByteDataView data, Set<String> descriptors, DiagnosticsHandler handler) { if (consumer != null) { - consumer.acceptDexIndexedFile(data); + consumer.accept(fileIndex, data, descriptors, handler); } } @@ -154,13 +150,11 @@ } @Override - public void acceptDexIndexedFile(DexIndexedConsumerData data) { - super.acceptDexIndexedFile(data); + public void accept( + int fileIndex, ByteDataView data, Set<String> descriptors, DiagnosticsHandler handler) { + super.accept(fileIndex, data, descriptors, handler); outputBuilder.addIndexedClassFile( - data.getFileIndex(), - DexUtils.getDefaultDexFileName(data.getFileIndex()), - data.getByteDataView(), - data.getDiagnosticsHandler()); + fileIndex, DexUtils.getDefaultDexFileName(fileIndex), data, handler); } @Override @@ -251,17 +245,15 @@ } @Override - public void acceptDexIndexedFile(DexIndexedConsumerData data) { - super.acceptDexIndexedFile(data); + public void accept( + int fileIndex, ByteDataView data, Set<String> descriptors, DiagnosticsHandler handler) { + super.accept(fileIndex, data, descriptors, handler); try { prepareDirectory(); } catch (IOException e) { - data.getDiagnosticsHandler().error(new ExceptionDiagnostic(e, new PathOrigin(directory))); + handler.error(new ExceptionDiagnostic(e, new PathOrigin(directory))); } - outputBuilder.addFile( - DexUtils.getDefaultDexFileName(data.getFileIndex()), - data.getByteDataView(), - data.getDiagnosticsHandler()); + outputBuilder.addFile(DexUtils.getDefaultDexFileName(fileIndex), data, handler); } @Override
diff --git a/src/main/java/com/android/tools/r8/DexIndexedConsumerData.java b/src/main/java/com/android/tools/r8/DexIndexedConsumerData.java deleted file mode 100644 index 1c46f8c..0000000 --- a/src/main/java/com/android/tools/r8/DexIndexedConsumerData.java +++ /dev/null
@@ -1,26 +0,0 @@ -// Copyright (c) 2023, 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; - -import java.util.Set; - -/** Data provided in the primary callback of {@link DexIndexedConsumer}. */ -@Keep -public interface DexIndexedConsumerData { - - /** Index of the DEX file for multi-dexing (Files are zero-indexed). */ - int getFileIndex(); - - /** DEX encoded data in a ByteDataView wrapper. */ - ByteDataView getByteDataView(); - - /** Copy of the bytes for the DEX encoded data. */ - byte[] getByteDataCopy(); - - /** Class descriptors for all classes defined in the DEX data. */ - Set<String> getClassDescriptors(); - - /** Diagnostics handler for reporting. */ - DiagnosticsHandler getDiagnosticsHandler(); -}
diff --git a/src/main/java/com/android/tools/r8/SyntheticInfoConsumer.java b/src/main/java/com/android/tools/r8/SyntheticInfoConsumer.java new file mode 100644 index 0000000..2bfc5b2 --- /dev/null +++ b/src/main/java/com/android/tools/r8/SyntheticInfoConsumer.java
@@ -0,0 +1,34 @@ +// Copyright (c) 2023, 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; + +@Keep +public interface SyntheticInfoConsumer { + + /** + * Callback with information about a compiler synthesized class. + * + * <p>This callback is only used in intermediate mode builds where the compiler may synthesize + * intermediate classes that can be de-duplicated and merged in a later non-incremental step. + * + * <p>This callback will always be called before the synthetic class is included in the data to + * any compiler outputs. Thus, it is safe to assume the information provided here is present when + * any compiler output consumers are called for the synthetic class. E.g., in the callbacks of + * {@link ClassFileConsumer} or {@link DexFilePerClassFileConsumer}. + * + * <p>Note: this callback may be called on multiple threads. + * + * <p>Note: this callback places no guarantees on order of calls or on duplicate calls. + * + * @param data Information about the synthetic class. + */ + void acceptSyntheticInfo(SyntheticInfoConsumerData data); + + /** + * Callback indicating no more synthetics will be generated for the active compilation unit. + * + * <p>Note: this callback places no other guarantees on number of calls or on which threads. + */ + void finished(); +}
diff --git a/src/main/java/com/android/tools/r8/SyntheticInfoConsumerData.java b/src/main/java/com/android/tools/r8/SyntheticInfoConsumerData.java new file mode 100644 index 0000000..be28596 --- /dev/null +++ b/src/main/java/com/android/tools/r8/SyntheticInfoConsumerData.java
@@ -0,0 +1,17 @@ +// Copyright (c) 2023, 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; + +import com.android.tools.r8.references.ClassReference; + +/** Information about a compiler synthesized class. */ +@Keep +public interface SyntheticInfoConsumerData { + + /** Get the reference for the compiler synthesized class. */ + ClassReference getSyntheticClass(); + + /** Get the reference for the context that gave rise to the synthesized class. */ + ClassReference getSynthesizingContextClass(); +}
diff --git a/src/main/java/com/android/tools/r8/cf/CfRegisterAllocator.java b/src/main/java/com/android/tools/r8/cf/CfRegisterAllocator.java index 6fd3574..8ec6ba4d 100644 --- a/src/main/java/com/android/tools/r8/cf/CfRegisterAllocator.java +++ b/src/main/java/com/android/tools/r8/cf/CfRegisterAllocator.java
@@ -96,9 +96,13 @@ private final List<LiveIntervals> liveIntervals = new ArrayList<>(); // List of active intervals. + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") private final List<LiveIntervals> active = new LinkedList<>(); // List of intervals where the current instruction falls into one of their live range holes. + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") private final List<LiveIntervals> inactive = new LinkedList<>(); // List of intervals that no register has been allocated to sorted by first live range.
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 d0daf58..99cb304 100644 --- a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java +++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
@@ -58,8 +58,6 @@ import com.android.tools.r8.utils.ArrayUtils; import com.android.tools.r8.utils.Box; import com.android.tools.r8.utils.DescriptorUtils; -import com.android.tools.r8.utils.DexFilePerClassFileConsumerDataImpl; -import com.android.tools.r8.utils.DexIndexedConsumerDataImpl; import com.android.tools.r8.utils.ExceptionUtils; import com.android.tools.r8.utils.IntBox; import com.android.tools.r8.utils.InternalGlobalSyntheticsProgramConsumer; @@ -588,14 +586,13 @@ ProgramConsumer consumer; ByteBufferProvider byteBufferProvider; - String primaryClassDescriptor = virtualFile.getPrimaryClassDescriptor(); if (globalSyntheticFiles != null && globalSyntheticFiles.contains(virtualFile)) { consumer = globalsSyntheticsConsumer; byteBufferProvider = globalsSyntheticsConsumer; } else if (programConsumer != null) { consumer = programConsumer; byteBufferProvider = programConsumer; - } else if (primaryClassDescriptor != null) { + } else if (virtualFile.getPrimaryClassDescriptor() != null) { consumer = options.getDexFilePerClassFileConsumer(); byteBufferProvider = options.getDexFilePerClassFileConsumer(); } else { @@ -623,18 +620,14 @@ timing.begin("Pass bytes to consumer"); if (consumer instanceof DexFilePerClassFileConsumer) { ((DexFilePerClassFileConsumer) consumer) - .acceptDexFile( - new DexFilePerClassFileConsumerDataImpl( - primaryClassDescriptor, - virtualFile.getPrimaryClassSynthesizingContextDescriptor(), - data, - virtualFile.getClassDescriptors(), - options.reporter)); + .accept( + virtualFile.getPrimaryClassDescriptor(), + data, + virtualFile.getClassDescriptors(), + options.reporter); } else { ((DexIndexedConsumer) consumer) - .acceptDexIndexedFile( - new DexIndexedConsumerDataImpl( - virtualFile.getId(), data, virtualFile.getClassDescriptors(), options.reporter)); + .accept(virtualFile.getId(), data, virtualFile.getClassDescriptors(), options.reporter); } timing.end(); // Release use of the backing buffer now that accept has returned.
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationWriterExperimental.java b/src/main/java/com/android/tools/r8/dex/ApplicationWriterExperimental.java index cdb74b5..0a81bd2 100644 --- a/src/main/java/com/android/tools/r8/dex/ApplicationWriterExperimental.java +++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriterExperimental.java
@@ -18,7 +18,6 @@ import com.android.tools.r8.graph.DexString; import com.android.tools.r8.graph.ObjectToOffsetMapping; import com.android.tools.r8.utils.BitUtils; -import com.android.tools.r8.utils.DexIndexedConsumerDataImpl; import com.android.tools.r8.utils.InternalOptions; import com.android.tools.r8.utils.ListUtils; import com.android.tools.r8.utils.ThreadUtils; @@ -173,9 +172,7 @@ if (consumer instanceof DexFilePerClassFileConsumer) { assert false; } else { - ((DexIndexedConsumer) consumer) - .acceptDexIndexedFile( - new DexIndexedConsumerDataImpl(0, data, Sets.newIdentityHashSet(), options.reporter)); + ((DexIndexedConsumer) consumer).accept(0, data, Sets.newIdentityHashSet(), options.reporter); } }
diff --git a/src/main/java/com/android/tools/r8/dex/InheritanceClassInDexDistributor.java b/src/main/java/com/android/tools/r8/dex/InheritanceClassInDexDistributor.java index 5a62bfb..4d10674 100644 --- a/src/main/java/com/android/tools/r8/dex/InheritanceClassInDexDistributor.java +++ b/src/main/java/com/android/tools/r8/dex/InheritanceClassInDexDistributor.java
@@ -514,6 +514,8 @@ * I5 --> I1, I2<br> * I3 and I4 will be in the same group even if they have no relation with each other. */ + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") private List<ClassGroup> collectInheritanceGroups() { // Considering classes are the nodes of a graph which edges are the inheritance relation between // classes. We just want to isolate every connected sub-graphs.
diff --git a/src/main/java/com/android/tools/r8/dex/JumboStringRewriter.java b/src/main/java/com/android/tools/r8/dex/JumboStringRewriter.java index 785158d..a68f99f 100644 --- a/src/main/java/com/android/tools/r8/dex/JumboStringRewriter.java +++ b/src/main/java/com/android/tools/r8/dex/JumboStringRewriter.java
@@ -252,6 +252,8 @@ return code.getDebugInfo(); } + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") private List<DexInstruction> expandCode() { LinkedList<DexInstruction> instructions = new LinkedList<>(); Collections.addAll(instructions, method.getCode().asDexCode().instructions);
diff --git a/src/main/java/com/android/tools/r8/dump/DumpOptions.java b/src/main/java/com/android/tools/r8/dump/DumpOptions.java index 0c538fa..9779fcf 100644 --- a/src/main/java/com/android/tools/r8/dump/DumpOptions.java +++ b/src/main/java/com/android/tools/r8/dump/DumpOptions.java
@@ -14,6 +14,7 @@ import com.android.tools.r8.shaking.ProguardConfigurationRule; import com.android.tools.r8.startup.StartupProfileProvider; import com.android.tools.r8.utils.InternalOptions.DesugarState; +import com.android.tools.r8.utils.StringUtils; import com.android.tools.r8.utils.ThreadUtils; import java.util.ArrayList; import java.util.Collection; @@ -179,17 +180,22 @@ } public static void parse(String content, DumpOptions.Builder builder) { - String[] lines = content.split("\n"); - for (String line : lines) { - String trimmed = line.trim(); - int i = trimmed.indexOf('='); - if (i < 0) { - throw new RuntimeException("Invalid dump line. Expected = in line: '" + trimmed + "'"); - } - String key = trimmed.substring(0, i).trim(); - String value = trimmed.substring(i + 1).trim(); - parseKeyValue(builder, key, value); - } + StringUtils.splitForEach( + content, + '\n', + line -> { + String trimmed = line.trim(); + if (trimmed.isEmpty()) { + return; + } + int i = trimmed.indexOf('='); + if (i < 0) { + throw new RuntimeException("Invalid dump line. Expected = in line: '" + trimmed + "'"); + } + String key = trimmed.substring(0, i).trim(); + String value = trimmed.substring(i + 1).trim(); + parseKeyValue(builder, key, value); + }); } private static void parseKeyValue(Builder builder, String key, String value) {
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassInstanceFieldsMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassInstanceFieldsMerger.java index 195a8fc..f43d5ec 100644 --- a/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassInstanceFieldsMerger.java +++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassInstanceFieldsMerger.java
@@ -103,6 +103,8 @@ } } + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") static Map<InstanceFieldInfo, LinkedList<DexEncodedField>> getAvailableFieldsByExactInfo( DexProgramClass target) { Map<InstanceFieldInfo, LinkedList<DexEncodedField>> availableFieldsByInfo = @@ -115,6 +117,8 @@ return availableFieldsByInfo; } + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") static Map<InstanceFieldInfo, LinkedList<DexEncodedField>> getAvailableFieldsByRelaxedInfo( AppView<? extends AppInfoWithClassHierarchy> appView, Map<InstanceFieldInfo, LinkedList<DexEncodedField>> availableFieldsByExactInfo) {
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java index 299c516..8fc788b 100644 --- a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java +++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
@@ -332,6 +332,8 @@ } } + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") private List<MergeGroup> getInitialGroups() { MergeGroup initialClassGroup = new MergeGroup(); MergeGroup initialInterfaceGroup = new MergeGroup();
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/MergeGroup.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/MergeGroup.java index fe08b37..e0f2b3b 100644 --- a/src/main/java/com/android/tools/r8/horizontalclassmerging/MergeGroup.java +++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/MergeGroup.java
@@ -31,6 +31,8 @@ public static class Metadata {} + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") private final LinkedList<DexProgramClass> classes; private DexField classIdField; @@ -39,6 +41,8 @@ private BidirectionalManyToOneMap<DexEncodedField, DexEncodedField> instanceFieldMap; + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") public MergeGroup() { this.classes = new LinkedList<>(); }
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/PolicyExecutor.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/PolicyExecutor.java index c206e75..28ec89d 100644 --- a/src/main/java/com/android/tools/r8/horizontalclassmerging/PolicyExecutor.java +++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/PolicyExecutor.java
@@ -34,6 +34,8 @@ } } + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") private LinkedList<MergeGroup> applyMultiClassPolicy( MultiClassPolicy policy, LinkedList<MergeGroup> groups) { // For each group apply the multi class policy and add all the new groups together. @@ -51,6 +53,8 @@ return newGroups; } + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") private <T> LinkedList<MergeGroup> applyMultiClassPolicyWithPreprocessing( MultiClassPolicyWithPreprocessing<T> policy, LinkedList<MergeGroup> groups, @@ -77,6 +81,8 @@ * policies registered to this policy executor on the class groups yielding a new collection of * class groups. */ + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") public Collection<MergeGroup> run( Collection<MergeGroup> inputGroups, Collection<Policy> policies,
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/AtMostOneClassThatMatchesPolicy.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/AtMostOneClassThatMatchesPolicy.java index c73675f..17bb034 100644 --- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/AtMostOneClassThatMatchesPolicy.java +++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/AtMostOneClassThatMatchesPolicy.java
@@ -17,6 +17,8 @@ public abstract class AtMostOneClassThatMatchesPolicy extends MultiClassPolicy { + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") @Override public Collection<MergeGroup> apply(MergeGroup group) { // Create a new merge group for each class that we want at most one of.
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/LimitClassGroups.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/LimitClassGroups.java index 55d0472..15070c2 100644 --- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/LimitClassGroups.java +++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/LimitClassGroups.java
@@ -24,6 +24,8 @@ assert maxGroupSize >= 2; } + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") @Override public Collection<MergeGroup> apply(MergeGroup group) { if (group.size() <= maxGroupSize || group.isInterfaceGroup()) {
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoClassInitializerCycles.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoClassInitializerCycles.java index 744154c..b1ad665 100644 --- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoClassInitializerCycles.java +++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoClassInitializerCycles.java
@@ -106,6 +106,8 @@ this.appView = appView; } + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") @Override public Collection<MergeGroup> apply(MergeGroup group, Void nothing) { // Partition the merge group into smaller groups that may be merged. If the class initialization
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoDeadLocks.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoDeadLocks.java index 576e0ef..f120117 100644 --- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoDeadLocks.java +++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoDeadLocks.java
@@ -25,6 +25,8 @@ return appView.appInfo().isLockCandidate(clazz.type) || clazz.hasStaticSynchronizedMethods(); } + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") @Override public Collection<MergeGroup> apply(MergeGroup group) { // Gather all synchronized classes.
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoWeakerAccessPrivileges.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoWeakerAccessPrivileges.java index 600b5a8..2305438 100644 --- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoWeakerAccessPrivileges.java +++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoWeakerAccessPrivileges.java
@@ -43,6 +43,8 @@ this.immediateSubtypingInfo = immediateSubtypingInfo; } + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") @Override public Collection<MergeGroup> apply(MergeGroup group) { List<MergeGroup> newMergeGroups = new LinkedList<>();
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/OnlyDirectlyConnectedOrUnrelatedInterfaces.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/OnlyDirectlyConnectedOrUnrelatedInterfaces.java index 6d54364..fd24d1f 100644 --- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/OnlyDirectlyConnectedOrUnrelatedInterfaces.java +++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/OnlyDirectlyConnectedOrUnrelatedInterfaces.java
@@ -70,6 +70,8 @@ this.mode = mode; } + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") @Override public Collection<MergeGroup> apply(MergeGroup group, SubtypingInfo subtypingInfo) { if (!group.isInterfaceGroup()) {
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/PreserveMethodCharacteristics.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/PreserveMethodCharacteristics.java index a6e27f5..60f57e4 100644 --- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/PreserveMethodCharacteristics.java +++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/PreserveMethodCharacteristics.java
@@ -135,6 +135,8 @@ } } + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") @Override public Collection<MergeGroup> apply(MergeGroup group) { List<TargetGroup> groups = new ArrayList<>();
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/constant/SparseConditionalConstantPropagation.java b/src/main/java/com/android/tools/r8/ir/analysis/constant/SparseConditionalConstantPropagation.java index 0ac3c7e..69ef71c 100644 --- a/src/main/java/com/android/tools/r8/ir/analysis/constant/SparseConditionalConstantPropagation.java +++ b/src/main/java/com/android/tools/r8/ir/analysis/constant/SparseConditionalConstantPropagation.java
@@ -36,8 +36,13 @@ private final AppView<?> appView; private final IRCode code; private final Map<Value, LatticeElement> mapping = new HashMap<>(); + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") private final Deque<Value> ssaEdges = new LinkedList<>(); + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") private final Deque<BasicBlock> flowEdges = new LinkedList<>(); + private final int maxBlockNumber; private final BitSet[] executableFlowEdges; private final BitSet visitedBlocks;
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoMessageInfo.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoMessageInfo.java index 69d0ae9..631502d 100644 --- a/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoMessageInfo.java +++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoMessageInfo.java
@@ -26,8 +26,14 @@ private int flags; + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") private LinkedList<ProtoFieldInfo> fields; + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") private LinkedList<ProtoFieldObject> hasBitsObjects; + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") private LinkedList<ProtoOneOfObjectPair> oneOfObjects; private Builder(ProgramMethod dynamicMethod) { @@ -38,6 +44,8 @@ this.flags = value; } + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") public void addField(ProtoFieldInfo field) { if (fields == null) { fields = new LinkedList<>(); @@ -45,6 +53,8 @@ fields.add(field); } + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") public void addHasBitsObject(ProtoFieldObject hasBitsObject) { if (hasBitsObjects == null) { hasBitsObjects = new LinkedList<>(); @@ -52,6 +62,8 @@ hasBitsObjects.add(hasBitsObject); } + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") public void addOneOfObject(ProtoFieldObject oneOfObject, ProtoFieldObject oneOfCaseObject) { if (oneOfObjects == null) { oneOfObjects = new LinkedList<>();
diff --git a/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java b/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java index 3827b37..276150a 100644 --- a/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java +++ b/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java
@@ -169,7 +169,10 @@ // Catch handler information about which successors are catch handlers and what their guards are. private CatchHandlers<Integer> catchHandlers = CatchHandlers.EMPTY_INDICES; + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") private LinkedList<Instruction> instructions = new LinkedList<>(); + private int number = -1; private List<Phi> phis = new ArrayList<>(); @@ -1413,6 +1416,8 @@ * Remove a number of instructions. The instructions to remove are given as indexes in the * instruction stream. */ + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") public void removeInstructions(List<Integer> toRemove) { if (!toRemove.isEmpty()) { LinkedList<Instruction> newInstructions = new LinkedList<>();
diff --git a/src/main/java/com/android/tools/r8/ir/code/IRCode.java b/src/main/java/com/android/tools/r8/ir/code/IRCode.java index 56f1150..a46b0a2 100644 --- a/src/main/java/com/android/tools/r8/ir/code/IRCode.java +++ b/src/main/java/com/android/tools/r8/ir/code/IRCode.java
@@ -447,10 +447,11 @@ } /** - * Trace blocks and attempt to put fallthrough blocks immediately after the block that - * falls through. When we fail to do that we create a new fallthrough block with an explicit - * goto to the actual fallthrough block. + * Trace blocks and attempt to put fallthrough blocks immediately after the block that falls + * through. When we fail to do that we create a new fallthrough block with an explicit goto to the + * actual fallthrough block. */ + @SuppressWarnings("JdkObsolete") // Consider replacing the use of LinkedList. public void traceBlocks() { // Get the blocks first, as calling topologicallySortedBlocks also sets marks. ImmutableList<BasicBlock> sorted = topologicallySortedBlocks();
diff --git a/src/main/java/com/android/tools/r8/ir/code/Value.java b/src/main/java/com/android/tools/r8/ir/code/Value.java index f4c211f..d7b86fe 100644 --- a/src/main/java/com/android/tools/r8/ir/code/Value.java +++ b/src/main/java/com/android/tools/r8/ir/code/Value.java
@@ -167,9 +167,17 @@ protected final int number; public Instruction definition = null; + + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") private LinkedList<Instruction> users = new LinkedList<>(); + private Set<Instruction> uniqueUsers = null; + + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") private LinkedList<Phi> phiUsers = new LinkedList<>(); + private Set<Phi> uniquePhiUsers = null; private Value nextConsecutive = null; private Value previousConsecutive = null;
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java index 35c6667..c9bc10c 100644 --- a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java +++ b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
@@ -375,6 +375,8 @@ private final Reference2IntMap<BasicBlock> offsets = new Reference2IntOpenHashMap<>(); // Worklist of reachable blocks. + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") private final Queue<Integer> traceBlocksWorklist = new LinkedList<>(); // Bitmap to ensure we don't process an instruction more than once. @@ -384,9 +386,13 @@ private Set<Integer> processedSubroutineInstructions = null; // Worklist for SSA construction. + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") private final Queue<WorklistItem> ssaWorklist = new LinkedList<>(); // Basic blocks. Added after processing from the worklist. + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") private final LinkedList<BasicBlock> blocks = new LinkedList<>(); private BasicBlock entryBlock = null;
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java index c21f00e..0050541 100644 --- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java +++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -65,7 +65,8 @@ import com.android.tools.r8.lightir.Lir2IRConverter; import com.android.tools.r8.lightir.LirCode; import com.android.tools.r8.lightir.LirStrategy; -import com.android.tools.r8.lightir.LirStrategy.PhiInInstructionsStrategy; +import com.android.tools.r8.lightir.LirStrategy.ExternalPhisStrategy; +import com.android.tools.r8.lightir.PhiInInstructionsStrategy; import com.android.tools.r8.naming.IdentifierNameStringMarker; import com.android.tools.r8.optimize.argumentpropagation.ArgumentPropagatorIROptimizer; import com.android.tools.r8.position.MethodPosition; @@ -1055,12 +1056,18 @@ OptimizationFeedback feedback, BytecodeMetadataProvider bytecodeMetadataProvider, Timing timing) { - LirStrategy<Value, Integer> strategy = new PhiInInstructionsStrategy(); - timing.begin("IR->LIR"); - LirCode<Integer> lirCode = + IRCode round1 = doRoundtripWithStrategy(code, new ExternalPhisStrategy(), "indirect phis"); + IRCode round2 = doRoundtripWithStrategy(round1, new PhiInInstructionsStrategy(), "inline phis"); + return round2; + } + + private <EV, S extends LirStrategy<Value, EV>> IRCode doRoundtripWithStrategy( + IRCode code, S strategy, String name) { + timing.begin("IR->LIR (" + name + ")"); + LirCode<EV> lirCode = IR2LirConverter.translate(code, strategy.getEncodingStrategy(), appView.dexItemFactory()); timing.end(); - timing.begin("LIR->IR"); + timing.begin("LIR->IR (" + name + ")"); IRCode irCode = Lir2IRConverter.translate( code.context(), lirCode, strategy.getDecodingStrategy(lirCode), appView);
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java b/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java index 80abf84..362d883 100644 --- a/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java +++ b/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
@@ -867,6 +867,8 @@ // argument instruction // - Removes unused arguments // - Updates the type of arguments whose type has been strengthened + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") private void rewriteArguments( IRCode code, DexMethod originalMethodReference,
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/PrimaryD8L8IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/PrimaryD8L8IRConverter.java index 39fc23a..cf7a083 100644 --- a/src/main/java/com/android/tools/r8/ir/conversion/PrimaryD8L8IRConverter.java +++ b/src/main/java/com/android/tools/r8/ir/conversion/PrimaryD8L8IRConverter.java
@@ -229,12 +229,7 @@ int limit = 11; for (DexProgramClass clazz : appView.appInfo().classesWithDeterministicOrder()) { if (!clazz.type.descriptor.startsWith(neverMergePrefix)) { - boolean hasExceptionPrefix = false; - for (DexString exceptionPrefix : neverMerge.getExceptionPrefixes()) { - hasExceptionPrefix = - hasExceptionPrefix | clazz.type.descriptor.startsWith(exceptionPrefix); - } - if (hasExceptionPrefix) { + if (hasExceptionPrefix(clazz)) { continue; } if (limit-- < 0) { @@ -255,6 +250,15 @@ } } + private boolean hasExceptionPrefix(DexProgramClass clazz) { + for (DexString exceptionPrefix : neverMerge.getExceptionPrefixes()) { + if (clazz.type.descriptor.startsWith(exceptionPrefix)) { + return true; + } + } + return false; + } + void classSynthesisDesugaring( ExecutorService executorService, CfClassSynthesizerDesugaringEventConsumer classSynthesizerEventConsumer)
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/callgraph/CycleEliminator.java b/src/main/java/com/android/tools/r8/ir/conversion/callgraph/CycleEliminator.java index dbae4a9..52dd9bc 100644 --- a/src/main/java/com/android/tools/r8/ir/conversion/callgraph/CycleEliminator.java +++ b/src/main/java/com/android/tools/r8/ir/conversion/callgraph/CycleEliminator.java
@@ -393,6 +393,8 @@ return false; } + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") private LinkedList<Node> extractCycle(Node entry) { LinkedList<Node> cycle = new LinkedList<>(); do {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/CovariantReturnTypeAnnotationTransformer.java b/src/main/java/com/android/tools/r8/ir/desugar/CovariantReturnTypeAnnotationTransformer.java index 788afd1..8ac1b02 100644 --- a/src/main/java/com/android/tools/r8/ir/desugar/CovariantReturnTypeAnnotationTransformer.java +++ b/src/main/java/com/android/tools/r8/ir/desugar/CovariantReturnTypeAnnotationTransformer.java
@@ -54,18 +54,18 @@ // the contained CovariantReturnType annotations. public final class CovariantReturnTypeAnnotationTransformer { - private final AppView<?> appView; private final IRConverter converter; private final MethodProcessorEventConsumer methodProcessorEventConsumer = MethodProcessorEventConsumer.empty(); private final DexItemFactory factory; public CovariantReturnTypeAnnotationTransformer(AppView<?> appView, IRConverter converter) { - this.appView = appView; this.converter = converter; this.factory = appView.dexItemFactory(); } + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") public void process( DexApplication.Builder<?> builder, CovariantReturnTypeAnnotationTransformerEventConsumer eventConsumer) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/lint/GenerateHtmlDoc.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/lint/GenerateHtmlDoc.java index d502339..45aa53f 100644 --- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/lint/GenerateHtmlDoc.java +++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/lint/GenerateHtmlDoc.java
@@ -17,6 +17,8 @@ import com.android.tools.r8.ir.desugar.desugaredlibrary.lint.SupportedClasses.MethodAnnotation; import com.android.tools.r8.ir.desugar.desugaredlibrary.lint.SupportedClasses.SupportedClass; import com.android.tools.r8.utils.AndroidApiLevel; +import com.android.tools.r8.utils.ListUtils; +import com.android.tools.r8.utils.StringUtils; import java.io.PrintStream; import java.nio.file.Files; import java.util.ArrayList; @@ -124,10 +126,10 @@ if (rewritten != null) { return rewritten; } - String[] split = packageName.split("\\."); - if (split.length > 2) { - String prevPackage = - packageName.substring(0, packageName.length() - split[split.length - 1].length() - 1); + List<String> split = StringUtils.split(packageName, '.'); + if (split.size() > 2) { + String last = ListUtils.last(split); + String prevPackage = packageName.substring(0, packageName.length() - last.length() - 1); return typeInPackage(typeName, prevPackage); } return null; @@ -303,14 +305,14 @@ } private String format(String s, int i) { - String[] regexpSplit = s.split("\\."); - if (regexpSplit.length < i) { + List<String> split = StringUtils.split(s, '.'); + if (split.size() < i) { return s; } int splitIndex = 0; int mid = i / 2; for (int j = 0; j < mid; j++) { - splitIndex += regexpSplit[j].length(); + splitIndex += split.get(j).length(); } splitIndex += mid; return s.substring(0, splitIndex) + HTML_SPLIT + s.substring(splitIndex); @@ -340,17 +342,17 @@ return appendLiCode(s); } StringBuilder sb = new StringBuilder(); - String[] split = s.split("\\("); - sb.append(split[0]).append('(').append(HTML_SPLIT); - if (split[1].length() < MAX_LINE_CHARACTERS - 2) { - sb.append(split[1]); + List<String> split = StringUtils.split(s, '('); + sb.append(split.get(0)).append('(').append(HTML_SPLIT); + if (split.get(1).length() < MAX_LINE_CHARACTERS - 2) { + sb.append(split.get(1)); return appendLiCode(sb.toString()); } - String[] secondSplit = split[1].split(","); + List<String> secondSplit = StringUtils.split(split.get(1), ','); sb.append(" "); - for (int i = 0; i < secondSplit.length; i++) { - sb.append(secondSplit[i]); - if (i != secondSplit.length - 1) { + for (int i = 0; i < secondSplit.size(); i++) { + sb.append(secondSplit.get(i)); + if (i != secondSplit.size() - 1) { sb.append(','); sb.append(HTML_SPLIT); }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineDesugaredLibrarySpecification.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineDesugaredLibrarySpecification.java index c357c2a..31baed9 100644 --- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineDesugaredLibrarySpecification.java +++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineDesugaredLibrarySpecification.java
@@ -14,7 +14,9 @@ import com.android.tools.r8.ir.desugar.desugaredlibrary.DesugaredLibrarySpecification; import com.android.tools.r8.ir.desugar.desugaredlibrary.specificationconversion.LibraryValidator; import com.android.tools.r8.utils.AndroidApiLevel; +import com.android.tools.r8.utils.ListUtils; import com.android.tools.r8.utils.SemanticVersion; +import com.android.tools.r8.utils.StringUtils; import com.android.tools.r8.utils.Timing; import java.util.List; import java.util.Map; @@ -251,8 +253,9 @@ if (leadingVersionNumberCache != -1) { return leadingVersionNumberCache; } - String[] split = topLevelFlags.getIdentifier().split(":"); - return leadingVersionNumberCache = SemanticVersion.parse(split[split.length - 1]).getMajor(); + List<String> split = StringUtils.split(topLevelFlags.getIdentifier(), ':'); + String last = ListUtils.last(split); + return leadingVersionNumberCache = SemanticVersion.parse(last).getMajor(); } public boolean includesJDK11Methods() {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineWrapperConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineWrapperConverter.java index e471367..e8c8073 100644 --- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineWrapperConverter.java +++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineWrapperConverter.java
@@ -136,6 +136,8 @@ }); } + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") private LinkedHashMap<DexType, WrapperDescriptorBuilder> orderDescriptors( Map<DexType, WrapperDescriptorBuilder> descriptors) { LinkedHashMap<DexType, WrapperDescriptorBuilder> orderedDescriptors = new LinkedHashMap<>(); @@ -155,6 +157,8 @@ return orderedDescriptors; } + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") private void finalizeWrapperDescriptors( LinkedHashMap<DexType, WrapperDescriptorBuilder> descriptors, MachineRewritingFlags.Builder builder) { @@ -171,6 +175,8 @@ }); } + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") private void fillDescriptors( DexClass wrapperClass, Set<DexMethod> excludedMethods,
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java index cd2c596..9f985e9 100644 --- a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java +++ b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
@@ -636,6 +636,8 @@ * Covert the switch instruction to a sequence of if instructions checking for a specified set of * keys, followed by a new switch with the remaining keys. */ + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") void convertSwitchToSwitchAndIfs( IRCode code, ListIterator<BasicBlock> blocksIterator,
diff --git a/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java b/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java index 8d146ad..90c6c2b 100644 --- a/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java +++ b/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
@@ -151,8 +151,12 @@ // List of all top-level live intervals for all SSA values. private List<LiveIntervals> liveIntervals = new ArrayList<>(); // List of active intervals. + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") private List<LiveIntervals> active = new LinkedList<>(); // List of intervals where the current instruction falls into one of their live range holes. + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") protected List<LiveIntervals> inactive = new LinkedList<>(); // List of intervals that no register has been allocated to sorted by first live range. protected PriorityQueue<LiveIntervals> unhandled = new PriorityQueue<>(); @@ -243,6 +247,8 @@ clearState(); } + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") public static void computeDebugInfo( IRCode code, ImmutableList<BasicBlock> blocks, @@ -1112,6 +1118,8 @@ * allocated and have been moved from unhandled to inactive. The move sources have their hints * updated. The rest of the register allocation state is unchanged. */ + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") private void allocateArgumentIntervalsWithSrc(LiveIntervals srcInterval, ArgumentReuseMode mode) { Value value = srcInterval.getValue(); for (Instruction instruction : value.uniqueUsers()) {
diff --git a/src/main/java/com/android/tools/r8/ir/regalloc/RegisterMoveScheduler.java b/src/main/java/com/android/tools/r8/ir/regalloc/RegisterMoveScheduler.java index f7e377d..5251d17 100644 --- a/src/main/java/com/android/tools/r8/ir/regalloc/RegisterMoveScheduler.java +++ b/src/main/java/com/android/tools/r8/ir/regalloc/RegisterMoveScheduler.java
@@ -60,6 +60,8 @@ valueMap.put(move.dst, move.dst); } + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") public void schedule() { assert everyDestinationOnlyWrittenOnce();
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 49f2fbb..cc88ca9 100644 --- a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java +++ b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
@@ -47,7 +47,6 @@ import com.android.tools.r8.synthesis.SyntheticNaming; import com.android.tools.r8.utils.AndroidApp; import com.android.tools.r8.utils.AsmUtils; -import com.android.tools.r8.utils.ClassFileConsumerDataImpl; import com.android.tools.r8.utils.ComparatorUtils; import com.android.tools.r8.utils.ExceptionUtils; import com.android.tools.r8.utils.InternalGlobalSyntheticsProgramConsumer.InternalGlobalSyntheticsCfConsumer; @@ -335,10 +334,7 @@ verifyCf(result); } ExceptionUtils.withConsumeResourceHandler( - options.reporter, - handler -> - consumer.acceptClassFile( - new ClassFileConsumerDataImpl(ByteDataView.of(result), desc, handler))); + options.reporter, handler -> consumer.accept(ByteDataView.of(result), desc, handler)); } private int compareTypesThroughLens(DexType a, DexType b) {
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinSourceDebugExtensionParser.java b/src/main/java/com/android/tools/r8/kotlin/KotlinSourceDebugExtensionParser.java index 065ff92..6cf38cb 100644 --- a/src/main/java/com/android/tools/r8/kotlin/KotlinSourceDebugExtensionParser.java +++ b/src/main/java/com/android/tools/r8/kotlin/KotlinSourceDebugExtensionParser.java
@@ -6,6 +6,7 @@ import com.android.tools.r8.naming.Range; import com.android.tools.r8.utils.SegmentTree; +import com.android.tools.r8.utils.StringUtils; import com.android.tools.r8.utils.ThrowingConsumer; import java.io.BufferedReader; import java.io.Closeable; @@ -216,8 +217,8 @@ throws KotlinSourceDebugExtensionParserException { // + <file_number_i> <file_name_i> // <file_path_i> - String[] entries = entryLine.trim().split(" "); - if (entries.length != 3 || !entries[0].equals("+")) { + String[] entries = StringUtils.splitKnownSize(entryLine.trim(), ' ', 3); + if (entries == null || !entries[0].equals("+")) { throw new KotlinSourceDebugExtensionParserException( "Wrong number of entries on line " + entryLine); }
diff --git a/src/main/java/com/android/tools/r8/lightir/ByteUtils.java b/src/main/java/com/android/tools/r8/lightir/ByteUtils.java index f719f11..5d34483 100644 --- a/src/main/java/com/android/tools/r8/lightir/ByteUtils.java +++ b/src/main/java/com/android/tools/r8/lightir/ByteUtils.java
@@ -51,6 +51,15 @@ return (value >= 0) && (value <= 0xFFFF); } + private static int truncateToU2(int value) { + return value & 0xFFFF; + } + + public static int ensureU2(int value) { + assert isU2(value); + return truncateToU2(value); + } + public static int unsetBitAtIndex(int value, int index) { return value & ~(1 << (index - 1)); }
diff --git a/src/main/java/com/android/tools/r8/lightir/IR2LirConverter.java b/src/main/java/com/android/tools/r8/lightir/IR2LirConverter.java index 21af715..ee53ceb 100644 --- a/src/main/java/com/android/tools/r8/lightir/IR2LirConverter.java +++ b/src/main/java/com/android/tools/r8/lightir/IR2LirConverter.java
@@ -48,6 +48,11 @@ strategy.defineBlock(block, blockIndex); } + private boolean recordPhi(Phi phi, int valueIndex) { + recordValue(phi, valueIndex); + return strategy.isPhiInlineInstruction(); + } + private void recordValue(Value value, int valueIndex) { EV encodedValue = strategy.defineValue(value, valueIndex); if (value.hasLocalInfo()) { @@ -69,16 +74,8 @@ BasicBlockIterator blockIt = irCode.listIterator(); while (blockIt.hasNext()) { BasicBlock block = blockIt.next(); - if (block.hasPhis()) { - // The block order of the predecessors may change, since the LIR does not encode the - // direct links, the block order is used to determine predecessor order. - int[] permutation = computePermutation(block.getPredecessors(), strategy::getBlockIndex); - Value[] operands = new Value[block.getPredecessors().size()]; - for (Phi phi : block.getPhis()) { - permuteOperands(phi.getOperands(), permutation, operands); - builder.addPhi(phi.getType(), Arrays.asList(operands)); - currentValueIndex++; - } + if (strategy.isPhiInlineInstruction()) { + currentValueIndex += computePhis(block); } if (block.hasCatchHandlers()) { CatchHandlers<BasicBlock> handlers = block.getCatchHandlers(); @@ -112,6 +109,25 @@ } assert builder.verifyCurrentValueIndex(currentValueIndex); } + if (!strategy.isPhiInlineInstruction()) { + irCode.listIterator().forEachRemaining(this::computePhis); + } + } + + private int computePhis(BasicBlock block) { + int valuesOffset = 0; + if (block.hasPhis()) { + // The block order of the predecessors may change, since the LIR does not encode the + // direct links, the block order is used to determine predecessor order. + int[] permutation = computePermutation(block.getPredecessors(), strategy::getBlockIndex); + Value[] operands = new Value[block.getPredecessors().size()]; + for (Phi phi : block.getPhis()) { + permuteOperands(phi.getOperands(), permutation, operands); + builder.addPhi(phi.getType(), Arrays.asList(operands)); + valuesOffset++; + } + } + return valuesOffset; } private void computeBlockAndValueTables() { @@ -120,9 +136,10 @@ for (BasicBlock block : irCode.blocks) { recordBlock(block, instructionIndex); for (Phi phi : block.getPhis()) { - recordValue(phi, valueIndex); - valueIndex++; - instructionIndex++; + if (recordPhi(phi, valueIndex)) { + valueIndex++; + instructionIndex++; + } } for (Instruction instruction : block.getInstructions()) { if (instruction.hasOutValue()) {
diff --git a/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java b/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java index cc64c4e..e09e9f5 100644 --- a/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java +++ b/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java
@@ -4,7 +4,6 @@ package com.android.tools.r8.lightir; import com.android.tools.r8.graph.AppView; -import com.android.tools.r8.graph.DebugLocalInfo; import com.android.tools.r8.graph.DexField; import com.android.tools.r8.graph.DexMethod; import com.android.tools.r8.graph.DexString; @@ -58,6 +57,7 @@ AppView<?> appView) { Parser<EV> parser = new Parser<>(lirCode, method.getReference(), appView, strategy); parser.parseArguments(method); + parser.ensureDebugInfo(); lirCode.forEach(view -> view.accept(parser)); return parser.getIRCode(method); } @@ -157,6 +157,23 @@ advanceNextPositionEntry(); } + public void ensureDebugInfo() { + if (code.getDebugLocalInfoTable() == null) { + return; + } + code.getDebugLocalInfoTable() + .forEachLocalDefinition( + (encodedValue, localInfo) -> { + Value value = getValue(encodedValue); + if (!value.hasLocalInfo()) { + value.setLocalInfo(localInfo); + } + assert value.getLocalInfo() == localInfo; + }); + } + + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") public IRCode getIRCode(ProgramMethod method) { LinkedList<BasicBlock> blockList = new LinkedList<>(); IntList blockIndices = new IntArrayList(blocks.keySet()); @@ -192,7 +209,7 @@ } public Value getValue(EV encodedValue) { - return strategy.getValue(encodedValue); + return strategy.getValue(encodedValue, code.getStrategyInfo()); } public List<Value> getValues(List<EV> indices) { @@ -213,20 +230,34 @@ public Value getOutValueForNextInstruction(TypeElement type) { int valueIndex = toInstructionIndexInIR(peekNextInstructionIndex()); - DebugLocalInfo localInfo = code.getDebugLocalInfo(valueIndex); - return strategy.getValueDefinitionForInstructionIndex(valueIndex, type, localInfo); + return strategy.getValueDefinitionForInstructionIndex( + valueIndex, type, code::getDebugLocalInfo); } public Phi getPhiForNextInstructionAndAdvanceState(TypeElement type) { - int valueIndex = toInstructionIndexInIR(peekNextInstructionIndex()); - DebugLocalInfo localInfo = code.getDebugLocalInfo(valueIndex); - // TODO(b/225838009): The phi constructor implicitly adds to the block, so we need to ensure - // the block. However, we must grab the index above. Find a way to clean this up so it is - // uniform with instructions. - advanceInstructionState(); - // Creating the phi implicitly adds it to currentBlock. - return strategy.getPhiDefinitionForInstructionIndex( - valueIndex, currentBlock, type, localInfo); + int instructionIndex = peekNextInstructionIndex(); + int valueIndex = toInstructionIndexInIR(instructionIndex); + Phi phi = + strategy.getPhiDefinitionForInstructionIndex( + valueIndex, + blockIndex -> getBasicBlockOrEnsureCurrentBlock(blockIndex, instructionIndex), + type, + code::getDebugLocalInfo, + code.getStrategyInfo()); + ensureCurrentPosition(); + ++nextInstructionIndex; + return phi; + } + + private BasicBlock getBasicBlockOrEnsureCurrentBlock(int index, int currentInstructionIndex) { + // If the index is at current or past it ensure the block. + if (index >= currentInstructionIndex) { + ensureCurrentBlock(); + return currentBlock; + } + // Otherwise we assume the index is an exact block index for an existing block. + assert blocks.containsKey(index); + return getBasicBlock(index); } private void advanceInstructionState() { @@ -260,8 +291,9 @@ // Arguments are not included in the "instructions" so this does not call "addInstruction" // which would otherwise advance the state. TypeElement typeElement = type.toTypeElement(appView); - DebugLocalInfo localInfo = code.getDebugLocalInfo(index); - Value dest = strategy.getValueDefinitionForInstructionIndex(index, typeElement, localInfo); + Value dest = + strategy.getValueDefinitionForInstructionIndex( + index, typeElement, code::getDebugLocalInfo); Argument argument = new Argument(dest, index, type.isBooleanType()); assert currentBlock != null; assert currentPosition.isSyntheticPosition();
diff --git a/src/main/java/com/android/tools/r8/lightir/LirBuilder.java b/src/main/java/com/android/tools/r8/lightir/LirBuilder.java index b2fe3ba..fd4113a 100644 --- a/src/main/java/com/android/tools/r8/lightir/LirBuilder.java +++ b/src/main/java/com/android/tools/r8/lightir/LirBuilder.java
@@ -433,6 +433,6 @@ instructionCount, new TryCatchTable(tryCatchRanges), debugTable, - strategy.getSsaValueStrategy()); + strategy.getStrategyInfo()); } }
diff --git a/src/main/java/com/android/tools/r8/lightir/LirCode.java b/src/main/java/com/android/tools/r8/lightir/LirCode.java index f62d9f6..3f84cdf 100644 --- a/src/main/java/com/android/tools/r8/lightir/LirCode.java +++ b/src/main/java/com/android/tools/r8/lightir/LirCode.java
@@ -12,6 +12,7 @@ import com.android.tools.r8.ir.code.Position; import it.unimi.dsi.fastutil.ints.Int2ReferenceMap; import java.util.Map; +import java.util.function.BiConsumer; public class LirCode<EV> implements Iterable<LirInstructionView> { @@ -48,9 +49,13 @@ this.valueToLocalMap = valueToLocalMap; this.instructionToEndUseMap = instructionToEndUseMap; } + + public void forEachLocalDefinition(BiConsumer<EV, DebugLocalInfo> fn) { + valueToLocalMap.forEach(fn); + } } - private final LirSsaValueStrategy<EV> ssaValueStrategy; + private final LirStrategyInfo<EV> strategyInfo; private final IRMetadata metadata; @@ -89,7 +94,7 @@ int instructionCount, TryCatchTable tryCatchTable, DebugLocalInfoTable<EV> debugLocalInfoTable, - LirSsaValueStrategy<EV> ssaValueStrategy) { + LirStrategyInfo<EV> strategyInfo) { this.metadata = metadata; this.constants = constants; this.positionTable = positions; @@ -98,11 +103,17 @@ this.instructionCount = instructionCount; this.tryCatchTable = tryCatchTable; this.debugLocalInfoTable = debugLocalInfoTable; - this.ssaValueStrategy = ssaValueStrategy; + this.strategyInfo = strategyInfo; } public EV decodeValueIndex(int encodedValueIndex, int currentValueIndex) { - return ssaValueStrategy.decodeValueIndex(encodedValueIndex, currentValueIndex); + return strategyInfo + .getReferenceStrategy() + .decodeValueIndex(encodedValueIndex, currentValueIndex); + } + + public LirStrategyInfo<EV> getStrategyInfo() { + return strategyInfo; } public int getArgumentCount() { @@ -137,7 +148,7 @@ return debugLocalInfoTable; } - public DebugLocalInfo getDebugLocalInfo(int valueIndex) { + public DebugLocalInfo getDebugLocalInfo(EV valueIndex) { return debugLocalInfoTable == null ? null : debugLocalInfoTable.valueToLocalMap.get(valueIndex); }
diff --git a/src/main/java/com/android/tools/r8/lightir/LirDecodingStrategy.java b/src/main/java/com/android/tools/r8/lightir/LirDecodingStrategy.java index 1e25e3c..0b0a51d 100644 --- a/src/main/java/com/android/tools/r8/lightir/LirDecodingStrategy.java +++ b/src/main/java/com/android/tools/r8/lightir/LirDecodingStrategy.java
@@ -7,15 +7,21 @@ import com.android.tools.r8.ir.analysis.type.TypeElement; import com.android.tools.r8.ir.code.BasicBlock; import com.android.tools.r8.ir.code.Phi; +import java.util.function.Function; +import java.util.function.IntFunction; /** Abstraction for how to decode SSA values (and basic blocks) when reading LIR. */ public abstract class LirDecodingStrategy<V, EV> { - public abstract V getValue(EV encodedValue); + public abstract V getValue(EV encodedValue, LirStrategyInfo<EV> strategyInfo); public abstract V getValueDefinitionForInstructionIndex( - int instructionIndex, TypeElement type, DebugLocalInfo localInfo); + int instructionIndex, TypeElement type, Function<EV, DebugLocalInfo> getLocalInfo); public abstract Phi getPhiDefinitionForInstructionIndex( - int instructionIndex, BasicBlock block, TypeElement type, DebugLocalInfo localInfo); + int valueIndex, + IntFunction<BasicBlock> getBlock, + TypeElement type, + Function<EV, DebugLocalInfo> getLocalInfo, + LirStrategyInfo<EV> strategyInfo); }
diff --git a/src/main/java/com/android/tools/r8/lightir/LirEncodingStrategy.java b/src/main/java/com/android/tools/r8/lightir/LirEncodingStrategy.java index 8bbba90..eb814d1 100644 --- a/src/main/java/com/android/tools/r8/lightir/LirEncodingStrategy.java +++ b/src/main/java/com/android/tools/r8/lightir/LirEncodingStrategy.java
@@ -14,13 +14,17 @@ public abstract EV defineValue(V value, int index); + public abstract boolean isPhiInlineInstruction(); + public abstract boolean verifyValueIndex(V value, int expectedIndex); public abstract EV getEncodedValue(V value); public int getEncodedValueIndexForReference(EV encodedValue, int referencingValueIndex) { - return getSsaValueStrategy().encodeValueIndex(encodedValue, referencingValueIndex); + return getStrategyInfo() + .getReferenceStrategy() + .encodeValueIndex(encodedValue, referencingValueIndex); } - public abstract LirSsaValueStrategy<EV> getSsaValueStrategy(); + public abstract LirStrategyInfo<EV> getStrategyInfo(); }
diff --git a/src/main/java/com/android/tools/r8/lightir/LirPrinter.java b/src/main/java/com/android/tools/r8/lightir/LirPrinter.java index 20dfc30..f4a840b 100644 --- a/src/main/java/com/android/tools/r8/lightir/LirPrinter.java +++ b/src/main/java/com/android/tools/r8/lightir/LirPrinter.java
@@ -53,7 +53,7 @@ } private String fmtValueIndex(EV valueIndex) { - return "v" + valueIndex; + return valueIndex.toString(); } private String fmtInsnIndex(int instructionIndex) {
diff --git a/src/main/java/com/android/tools/r8/lightir/LirStrategy.java b/src/main/java/com/android/tools/r8/lightir/LirStrategy.java index 70cda39..108586f 100644 --- a/src/main/java/com/android/tools/r8/lightir/LirStrategy.java +++ b/src/main/java/com/android/tools/r8/lightir/LirStrategy.java
@@ -3,6 +3,8 @@ // BSD-style license that can be found in the LICENSE file. package com.android.tools.r8.lightir; +import com.android.tools.r8.errors.Unimplemented; +import com.android.tools.r8.errors.Unreachable; import com.android.tools.r8.graph.DebugLocalInfo; import com.android.tools.r8.ir.analysis.type.TypeElement; import com.android.tools.r8.ir.code.BasicBlock; @@ -11,6 +13,11 @@ import com.android.tools.r8.ir.code.Value; import it.unimi.dsi.fastutil.objects.Reference2IntMap; import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; +import java.util.ArrayList; +import java.util.IdentityHashMap; +import java.util.Map; +import java.util.function.Function; +import java.util.function.IntFunction; /** * Abstraction for encoding and decoding LIR values. @@ -26,114 +33,326 @@ public abstract LirDecodingStrategy<V, EV> getDecodingStrategy(LirCode<EV> code); - // Strategy that implements the encoding of phi values as instructions in the LIR instruction - // stream. - public static class PhiInInstructionsStrategy extends LirStrategy<Value, Integer> { + /** + * Encoding of a value with a phi-bit. + * + * <p>Due to the generic signature the encoding is boxed so this just adds some convenient + * predicates and formatting since it is boxed anyway. + * + * <p>JVM code attribute has length u2 (16-bit / max 65536). Thus, the number of basic blocks and + * phi count is also bounded by the same value. The encoding here is taken to be + * + * <ul> + * <li>1-bit for value/phi bit (sign bit / most significant bit), + * <li>15-bit phi index (the following most significant bits). + * <li>16-bit block index (the least significant bits). + * </ul> + * + * <p>TODO(b/225838009): Fix this encoding to support pathological block counts above 32k. + */ + public static class PhiOrValue { + private final int value; + + public static PhiOrValue forPhi(int blockIndex, int phiIndex) { + int sign = Integer.MIN_VALUE; + int block = ensure15bit(blockIndex) << 16; + int phi = ByteUtils.ensureU2(phiIndex); + int raw = sign | block | phi; + assert raw < 0; + return new PhiOrValue(raw); + } + + private static int ensure15bit(int value) { + if (value >= (1 << 15)) { + // TODO(b/225838009): Support 16-bit values and inline this helper. + throw new Unimplemented("No support for more than 15-bit block index."); + } + return ByteUtils.ensureU2(value); + } + + public static PhiOrValue forNonPhi(int index) { + assert index >= 0; + return new PhiOrValue(index); + } + + private PhiOrValue(int value) { + this.value = value; + } + + public boolean isPhi() { + return value < 0; + } + + public boolean isNonPhi() { + return !isPhi(); + } + + public int getRawValue() { + return value; + } + + public int getDecodedValue() { + assert isNonPhi(); + return value; + } + + public int getBlockIndex() { + assert isPhi(); + return (value & ~Integer.MIN_VALUE) >> 16; + } + + public int getPhiIndex() { + assert isPhi(); + return value & 0xFFFF; + } @Override - public LirEncodingStrategy<Value, Integer> getEncodingStrategy() { + public String toString() { + if (isPhi()) { + return "phi(" + getBlockIndex() + "," + getPhiIndex() + ")"; + } + return "v" + getDecodedValue(); + } + + @Override + public int hashCode() { + return value; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (obj == this) { + return true; + } + return obj instanceof PhiOrValue && (value == ((PhiOrValue) obj).value); + } + } + + public static class ExternalPhisStrategy extends LirStrategy<Value, PhiOrValue> { + + @Override + public LirEncodingStrategy<Value, PhiOrValue> getEncodingStrategy() { return new EncodingStrategy(); } @Override - public LirDecodingStrategy<Value, Integer> getDecodingStrategy(LirCode<Integer> code) { + public LirDecodingStrategy<Value, PhiOrValue> getDecodingStrategy(LirCode<PhiOrValue> code) { return new DecodingStrategy(code); } - } - private static class EncodingStrategy extends LirEncodingStrategy<Value, Integer> { + private static class StrategyInfo extends LirStrategyInfo<PhiOrValue> { + private static final StrategyInfo EMPTY = new StrategyInfo(new int[0]); - // EV == Integer and its definition is equal to its shifted instruction index. - // The conversion for EV to its int-valued reference is determined by the 'valueStrategy'. + private final int[] phiTable; - private final LirSsaValueStrategy<Integer> valueStrategy = LirSsaValueStrategy.get(); - private final Reference2IntMap<Value> values = new Reference2IntOpenHashMap<>(); - private final Reference2IntMap<BasicBlock> blocks = new Reference2IntOpenHashMap<>(); - - @Override - public void defineBlock(BasicBlock block, int index) { - assert !blocks.containsKey(block); - blocks.put(block, index); - } - - @Override - public Integer defineValue(Value value, int index) { - values.put(value, index); - return index; - } - - @Override - public boolean verifyValueIndex(Value value, int expectedIndex) { - assert expectedIndex == values.getInt(value); - return true; - } - - @Override - public Integer getEncodedValue(Value value) { - return values.getInt(value); - } - - @Override - public int getBlockIndex(BasicBlock block) { - assert blocks.containsKey(block); - return blocks.getInt(block); - } - - @Override - public LirSsaValueStrategy<Integer> getSsaValueStrategy() { - return valueStrategy; - } - } - - private static class DecodingStrategy extends LirDecodingStrategy<Value, Integer> { - - private final Value[] values; - - DecodingStrategy(LirCode<Integer> code) { - values = new Value[code.getArgumentCount() + code.getInstructionCount()]; - } - - @Override - public Value getValue(Integer encodedValue) { - int index = encodedValue; - Value value = values[index]; - if (value == null) { - value = new Value(index, TypeElement.getBottom(), null); - values[index] = value; + public StrategyInfo(int[] phiTable) { + this.phiTable = phiTable; } - return value; + + @Override + public LirSsaValueStrategy<PhiOrValue> getReferenceStrategy() { + return ReferenceStrategy.INSTANCE; + } } - @Override - public Value getValueDefinitionForInstructionIndex( - int index, TypeElement type, DebugLocalInfo localInfo) { - Value value = values[index]; - if (value == null) { - value = new Value(index, type, localInfo); - values[index] = value; - } else { - value.setType(type); - if (localInfo != null) { - value.setLocalInfo(localInfo); + private static class EncodingStrategy extends LirEncodingStrategy<Value, PhiOrValue> { + private final Map<Value, PhiOrValue> values = new IdentityHashMap<>(); + private final Reference2IntMap<BasicBlock> blocks = new Reference2IntOpenHashMap<>(); + private final ArrayList<Integer> phiTable = new ArrayList<>(); + + @Override + public boolean isPhiInlineInstruction() { + return false; + } + + @Override + public void defineBlock(BasicBlock block, int index) { + assert !blocks.containsKey(block); + blocks.put(block, index); + if (block.getPhis().isEmpty()) { + return; } + int i = 0; + for (Phi phi : block.getPhis()) { + values.put(phi, PhiOrValue.forPhi(index, i++)); + } + // Amend the phi table with the index of the basic block and the number of its phis. + phiTable.add(index); + phiTable.add(i); } - return value; + + @Override + public PhiOrValue defineValue(Value value, int index) { + if (value.isPhi()) { + // Phis are defined as part of blocks. + PhiOrValue encodedValue = values.get(value); + assert encodedValue != null; + return encodedValue; + } + PhiOrValue encodedValue = PhiOrValue.forNonPhi(index); + values.put(value, encodedValue); + return encodedValue; + } + + @Override + public boolean verifyValueIndex(Value value, int expectedIndex) { + PhiOrValue encodedValue = values.get(value); + assert encodedValue.isNonPhi(); + assert expectedIndex == encodedValue.getDecodedValue(); + return true; + } + + @Override + public PhiOrValue getEncodedValue(Value value) { + return values.get(value); + } + + @Override + public int getBlockIndex(BasicBlock block) { + assert blocks.containsKey(block); + return blocks.getInt(block); + } + + @Override + public LirStrategyInfo<PhiOrValue> getStrategyInfo() { + if (phiTable.isEmpty()) { + return StrategyInfo.EMPTY; + } + int[] array = new int[phiTable.size()]; + for (int i = 0; i < phiTable.size(); i++) { + array[i] = phiTable.get(i); + } + return new StrategyInfo(array); + } } - @Override - public Phi getPhiDefinitionForInstructionIndex( - int index, BasicBlock block, TypeElement type, DebugLocalInfo localInfo) { - Phi phi = new Phi(index, block, type, localInfo, RegisterReadType.NORMAL); - Value value = values[index]; - if (value != null) { - // A fake ssa value has already been created, replace the users by the actual phi. - // TODO(b/225838009): We could consider encoding the value type as a bit in the value index - // and avoid the overhead of replacing users at phi-definition time. - assert !value.isPhi(); - value.replaceUsers(phi); + private static class DecodingStrategy extends LirDecodingStrategy<Value, PhiOrValue> { + + private final Value[] values; + private final int firstPhiValueIndex; + + DecodingStrategy(LirCode<PhiOrValue> code) { + values = new Value[code.getArgumentCount() + code.getInstructionCount()]; + int phiValueIndex = -1; + for (LirInstructionView view : code) { + if (view.getOpcode() == LirOpcodes.PHI) { + phiValueIndex = code.getArgumentCount() + view.getInstructionIndex(); + break; + } + } + this.firstPhiValueIndex = phiValueIndex; } - values[index] = phi; - return phi; + + private int decode(PhiOrValue encodedValue, LirStrategyInfo<PhiOrValue> strategyInfo) { + if (encodedValue.isNonPhi()) { + return encodedValue.getDecodedValue(); + } + StrategyInfo info = (StrategyInfo) strategyInfo; + int phiBlock = encodedValue.getBlockIndex(); + int phiIndex = encodedValue.getPhiIndex(); + assert firstPhiValueIndex != -1; + int index = firstPhiValueIndex; + for (int i = 0; i < info.phiTable.length; i++) { + int blockIndex = info.phiTable[i]; + if (blockIndex == phiBlock) { + return index + phiIndex; + } + index += info.phiTable[++i]; + } + throw new Unreachable("Unexpectedly fell off the end of the phi table"); + } + + @Override + public Value getValue(PhiOrValue encodedValue, LirStrategyInfo<PhiOrValue> strategyInfo) { + int index = decode(encodedValue, strategyInfo); + Value value = values[index]; + if (value == null) { + value = new Value(index, TypeElement.getBottom(), null); + values[index] = value; + } + return value; + } + + @Override + public Value getValueDefinitionForInstructionIndex( + int index, TypeElement type, Function<PhiOrValue, DebugLocalInfo> getLocalInfo) { + PhiOrValue encodedValue = new PhiOrValue(index); + assert encodedValue.isNonPhi(); + DebugLocalInfo localInfo = getLocalInfo.apply(encodedValue); + Value value = values[index]; + if (value == null) { + value = new Value(index, type, localInfo); + values[index] = value; + } else { + value.setType(type); + if (localInfo != null && !value.hasLocalInfo()) { + value.setLocalInfo(localInfo); + } + assert localInfo == value.getLocalInfo(); + } + return value; + } + + @Override + public Phi getPhiDefinitionForInstructionIndex( + int valueIndex, + IntFunction<BasicBlock> getBlock, + TypeElement type, + Function<PhiOrValue, DebugLocalInfo> getLocalInfo, + LirStrategyInfo<PhiOrValue> strategyInfo) { + PhiOrValue encodedValue = getEncodedPhiForAbsoluteValueIndex(valueIndex, strategyInfo); + BasicBlock block = getBlock.apply(encodedValue.getBlockIndex()); + DebugLocalInfo localInfo = getLocalInfo.apply(encodedValue); + Phi phi = new Phi(valueIndex, block, type, localInfo, RegisterReadType.NORMAL); + Value value = values[valueIndex]; + if (value != null) { + // A fake ssa value has already been created, replace the users by the actual phi. + // TODO(b/225838009): We could consider encoding the value phi-bit in the value index + // and avoid the overhead of replacing users at phi-definition time. + assert !value.isPhi(); + value.replaceUsers(phi); + } + values[valueIndex] = phi; + return phi; + } + + private PhiOrValue getEncodedPhiForAbsoluteValueIndex( + int phiValueIndex, LirStrategyInfo<PhiOrValue> strategyInfo) { + StrategyInfo info = (StrategyInfo) strategyInfo; + int currentPhiValueIndex = firstPhiValueIndex; + for (int i = 0; i < info.phiTable.length; i += 2) { + assert currentPhiValueIndex <= phiValueIndex; + int blockIndex = info.phiTable[i]; + int phiCount = info.phiTable[i + 1]; + assert phiCount > 0; + if (phiValueIndex < currentPhiValueIndex + phiCount) { + int phiOffsetInBlock = phiValueIndex - currentPhiValueIndex; + return PhiOrValue.forPhi(blockIndex, phiOffsetInBlock); + } + currentPhiValueIndex += phiCount; + } + throw new Unreachable("Unexpected fall off the end of the phi table"); + } + } + + // TODO(b/225838009): Consider still encoding the local value refs as small relative indexes. + private static class ReferenceStrategy extends LirSsaValueStrategy<PhiOrValue> { + + private static final ReferenceStrategy INSTANCE = new ReferenceStrategy(); + + @Override + public int encodeValueIndex(PhiOrValue value, int currentValueIndex) { + return value.getRawValue(); + } + + @Override + public PhiOrValue decodeValueIndex(int encodedValueIndex, int currentValueIndex) { + return new PhiOrValue(encodedValueIndex); + } } } + }
diff --git a/src/main/java/com/android/tools/r8/lightir/LirStrategyInfo.java b/src/main/java/com/android/tools/r8/lightir/LirStrategyInfo.java new file mode 100644 index 0000000..088786c --- /dev/null +++ b/src/main/java/com/android/tools/r8/lightir/LirStrategyInfo.java
@@ -0,0 +1,9 @@ +// Copyright (c) 2023, 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.lightir; + +public abstract class LirStrategyInfo<EV> { + + public abstract LirSsaValueStrategy<EV> getReferenceStrategy(); +}
diff --git a/src/main/java/com/android/tools/r8/lightir/PhiInInstructionsStrategy.java b/src/main/java/com/android/tools/r8/lightir/PhiInInstructionsStrategy.java new file mode 100644 index 0000000..0b0d537 --- /dev/null +++ b/src/main/java/com/android/tools/r8/lightir/PhiInInstructionsStrategy.java
@@ -0,0 +1,145 @@ +// Copyright (c) 2023, 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.lightir; + +import com.android.tools.r8.graph.DebugLocalInfo; +import com.android.tools.r8.ir.analysis.type.TypeElement; +import com.android.tools.r8.ir.code.BasicBlock; +import com.android.tools.r8.ir.code.Phi; +import com.android.tools.r8.ir.code.Phi.RegisterReadType; +import com.android.tools.r8.ir.code.Value; +import it.unimi.dsi.fastutil.objects.Reference2IntMap; +import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; +import java.util.function.Function; +import java.util.function.IntFunction; + +/** Strategy encoding phi values as instructions in the LIR instruction stream. */ +public class PhiInInstructionsStrategy extends LirStrategy<Value, Integer> { + + @Override + public LirEncodingStrategy<Value, Integer> getEncodingStrategy() { + return new EncodingStrategy(); + } + + @Override + public LirDecodingStrategy<Value, Integer> getDecodingStrategy(LirCode<Integer> code) { + return new DecodingStrategy(code); + } + + private static class EncodingStrategy extends LirEncodingStrategy<Value, Integer> { + + // EV == Integer and its definition is equal to its shifted instruction index. + // The conversion for EV to its int-valued reference is determined by the 'valueStrategy'. + + private final LirSsaValueStrategy<Integer> referenceStrategy = LirSsaValueStrategy.get(); + private final Reference2IntMap<Value> values = new Reference2IntOpenHashMap<>(); + private final Reference2IntMap<BasicBlock> blocks = new Reference2IntOpenHashMap<>(); + + @Override + public boolean isPhiInlineInstruction() { + return true; + } + + @Override + public void defineBlock(BasicBlock block, int index) { + assert !blocks.containsKey(block); + blocks.put(block, index); + } + + @Override + public Integer defineValue(Value value, int index) { + values.put(value, index); + return index; + } + + @Override + public boolean verifyValueIndex(Value value, int expectedIndex) { + assert expectedIndex == values.getInt(value); + return true; + } + + @Override + public Integer getEncodedValue(Value value) { + return values.getInt(value); + } + + @Override + public int getBlockIndex(BasicBlock block) { + assert blocks.containsKey(block); + return blocks.getInt(block); + } + + @Override + public LirStrategyInfo<Integer> getStrategyInfo() { + return new LirStrategyInfo<Integer>() { + @Override + public LirSsaValueStrategy<Integer> getReferenceStrategy() { + return referenceStrategy; + } + }; + } + } + + private static class DecodingStrategy extends LirDecodingStrategy<Value, Integer> { + + private final Value[] values; + + DecodingStrategy(LirCode<Integer> code) { + values = new Value[code.getArgumentCount() + code.getInstructionCount()]; + } + + @Override + public Value getValue(Integer encodedValue, LirStrategyInfo<Integer> strategyInfo) { + int index = encodedValue; + Value value = values[index]; + if (value == null) { + value = new Value(index, TypeElement.getBottom(), null); + values[index] = value; + } + return value; + } + + @Override + public Value getValueDefinitionForInstructionIndex( + int index, TypeElement type, Function<Integer, DebugLocalInfo> getLocalInfo) { + DebugLocalInfo localInfo = getLocalInfo.apply(index); + Value value = values[index]; + if (value == null) { + value = new Value(index, type, localInfo); + values[index] = value; + } else { + value.setType(type); + if (localInfo != null) { + if (!value.hasLocalInfo()) { + value.setLocalInfo(localInfo); + } + assert localInfo == value.getLocalInfo(); + } + } + return value; + } + + @Override + public Phi getPhiDefinitionForInstructionIndex( + int valueIndex, + IntFunction<BasicBlock> getBlock, + TypeElement type, + Function<Integer, DebugLocalInfo> getLocalInfo, + LirStrategyInfo<Integer> strategyInfo) { + BasicBlock block = getBlock.apply(valueIndex); + DebugLocalInfo localInfo = getLocalInfo.apply(valueIndex); + Phi phi = new Phi(valueIndex, block, type, localInfo, RegisterReadType.NORMAL); + Value value = values[valueIndex]; + if (value != null) { + // A fake ssa value has already been created, replace the users by the actual phi. + // TODO(b/225838009): We could consider encoding the value type as a bit in the value index + // and avoid the overhead of replacing users at phi-definition time. + assert !value.isPhi(); + value.replaceUsers(phi); + } + values[valueIndex] = phi; + return phi; + } + } +}
diff --git a/src/main/java/com/android/tools/r8/naming/ClassNamingForNameMapper.java b/src/main/java/com/android/tools/r8/naming/ClassNamingForNameMapper.java index 15efe36..2a1408a 100644 --- a/src/main/java/com/android/tools/r8/naming/ClassNamingForNameMapper.java +++ b/src/main/java/com/android/tools/r8/naming/ClassNamingForNameMapper.java
@@ -139,6 +139,10 @@ /** List of MappedRanges that belong to the same renamed name. */ public static class MappedRangesOfName { + + private static final MappedRangesOfName EMPTY_INSTANCE = + new MappedRangesOfName(Collections.emptyList()); + private final List<MappedRange> mappedRanges; public MappedRangesOfName(List<MappedRange> mappedRanges) { @@ -211,6 +215,10 @@ return mappedRanges; } + public static MappedRangesOfName empty() { + return EMPTY_INSTANCE; + } + @Override public boolean equals(Object o) { if (this == o) { @@ -562,7 +570,7 @@ */ private List<MappingInformation> additionalMappingInformation = EMPTY_MAPPING_INFORMATION; - MappedRange( + public MappedRange( Range minifiedRange, MethodSignature signature, Range originalRange, String renamedName) { this.minifiedRange = minifiedRange; this.signature = signature;
diff --git a/src/main/java/com/android/tools/r8/naming/IdentifierNameStringUtils.java b/src/main/java/com/android/tools/r8/naming/IdentifierNameStringUtils.java index 6e14907..3b022c7 100644 --- a/src/main/java/com/android/tools/r8/naming/IdentifierNameStringUtils.java +++ b/src/main/java/com/android/tools/r8/naming/IdentifierNameStringUtils.java
@@ -34,6 +34,7 @@ import com.android.tools.r8.ir.code.Value; import com.android.tools.r8.naming.identifiernamestring.IdentifierNameStringLookupResult; import com.android.tools.r8.shaking.AppInfoWithLiveness; +import com.android.tools.r8.utils.StringUtils; import com.google.common.collect.Sets; import java.util.ArrayList; import java.util.List; @@ -340,15 +341,15 @@ String identifier = dexString.toString(); String typeIdentifier = null; String memberIdentifier = null; - String[] items = identifier.split("#"); + List<String> items = StringUtils.split(identifier, '#'); // "x#y#z" - if (items.length > 2) { + if (items.size() > 2) { return null; } // "fully.qualified.ClassName#fieldOrMethodName" - if (items.length == 2) { - typeIdentifier = items[0]; - memberIdentifier = items[1]; + if (items.size() == 2) { + typeIdentifier = items.get(0); + memberIdentifier = items.get(1); } else { int lastDot = identifier.lastIndexOf("."); // "fully.qualified.ClassName.fieldOrMethodName"
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorIROptimizer.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorIROptimizer.java index f92af83..c76e842 100644 --- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorIROptimizer.java +++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorIROptimizer.java
@@ -33,6 +33,8 @@ * {@link Assume} instructions when non-trivial information is known about non-constant arguments * such as their nullability, dynamic type, interval, etc. */ + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") public static void optimize( AppView<AppInfoWithLiveness> appView, IRCode code,
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/MemberNamingWithMappedRangesOfName.java b/src/main/java/com/android/tools/r8/retrace/internal/MemberNamingWithMappedRangesOfName.java index 26d5a16..d60e6bf 100644 --- a/src/main/java/com/android/tools/r8/retrace/internal/MemberNamingWithMappedRangesOfName.java +++ b/src/main/java/com/android/tools/r8/retrace/internal/MemberNamingWithMappedRangesOfName.java
@@ -34,7 +34,20 @@ return mappedRangesOfName.getMappedRanges(); } + List<MappedRange> getMappedRangesWithNoMinifiedRangeAndPositionZero() { + return mappedRangesOfName.allRangesForLine(0, true); + } + public MemberNaming getMemberNaming() { return methodMemberNaming; } + + public boolean isSingleCatchAllRange() { + if (getMappedRanges().size() == 1) { + MappedRange singleMappedRange = ListUtils.first(getMappedRanges()); + return singleMappedRange.minifiedRange != null + && singleMappedRange.minifiedRange.isCatchAll(); + } + return false; + } }
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/RetraceFrameResultImpl.java b/src/main/java/com/android/tools/r8/retrace/internal/RetraceFrameResultImpl.java index b48e8c2..f82327a 100644 --- a/src/main/java/com/android/tools/r8/retrace/internal/RetraceFrameResultImpl.java +++ b/src/main/java/com/android/tools/r8/retrace/internal/RetraceFrameResultImpl.java
@@ -90,6 +90,7 @@ RetraceClassElementImpl classElement = mappedRangeData.getRetraceClassElement(); List<MemberNamingWithMappedRangesOfName> memberNamingWithMappedRangesOfNames = mappedRangeData.getMemberNamingWithMappedRanges(); + OptionalInt position = mappedRangeData.getPosition(); if (memberNamingWithMappedRangesOfNames == null || memberNamingWithMappedRangesOfNames.isEmpty()) { return Stream.of( @@ -101,7 +102,7 @@ classElement.getRetracedClass().getClassReference())), ImmutableList.of(), Optional.empty(), - mappedRangeData.getPosition(), + position, retracer)); } // Iterate over mapped ranges that may have different positions than specified. @@ -110,6 +111,23 @@ memberNamingWithMappedRangesOfNames) { List<MappedRange> mappedRangesForMemberNaming = memberNamingWithMappedRangesOfName.getMappedRanges(); + MemberNaming memberNaming = memberNamingWithMappedRangesOfName.getMemberNaming(); + if (mappedRangesForMemberNaming.isEmpty()) { + assert memberNaming != null; + MappedRange mappedRange = + new MappedRange( + null, + memberNaming.getOriginalSignature().asMethodSignature(), + null, + memberNaming.getRenamedName()); + ambiguousFrames.add( + elementFromMappedRanges( + Collections.singletonList(MappedRangeForFrame.create(mappedRange)), + Optional.of(memberNaming), + classElement, + position)); + continue; + } MappedRange firstMappedRange = mappedRangesForMemberNaming.get(0); Range minifiedRange = firstMappedRange.minifiedRange; List<MappedRange> mappedRangesForElement = Lists.newArrayList(firstMappedRange); @@ -119,10 +137,10 @@ // This is a new frame separateAmbiguousOriginalPositions( classElement, - Optional.ofNullable(memberNamingWithMappedRangesOfName.getMemberNaming()), + Optional.ofNullable(memberNaming), mappedRangesForElement, ambiguousFrames, - mappedRangeData.getPosition()); + position); mappedRangesForElement = new ArrayList<>(); minifiedRange = mappedRange.minifiedRange; } @@ -130,10 +148,10 @@ } separateAmbiguousOriginalPositions( classElement, - Optional.ofNullable(memberNamingWithMappedRangesOfName.getMemberNaming()), + Optional.ofNullable(memberNaming), mappedRangesForElement, ambiguousFrames, - mappedRangeData.getPosition()); + position); } return ambiguousFrames.stream(); });
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/RetraceMethodResultImpl.java b/src/main/java/com/android/tools/r8/retrace/internal/RetraceMethodResultImpl.java index 86af9c0..3a95c5f 100644 --- a/src/main/java/com/android/tools/r8/retrace/internal/RetraceMethodResultImpl.java +++ b/src/main/java/com/android/tools/r8/retrace/internal/RetraceMethodResultImpl.java
@@ -94,7 +94,7 @@ if (context instanceof RetraceStackTraceContextImpl) { stackTraceContext = (RetraceStackTraceContextImpl) context; } - boolean hasPosition = position.isPresent() && position.getAsInt() >= 0; + boolean hasPosition = position.isPresent() && position.getAsInt() > 0; Function<MemberNamingWithMappedRangesOfName, List<MappedRange>> selector = hasPosition ? filterOnExistingPosition(position.getAsInt()) : filterOnNoPosition(); for (Pair<RetraceClassElementImpl, List<MemberNamingWithMappedRangesOfName>> mappedRange : @@ -114,9 +114,27 @@ } } if (narrowedRanges.isEmpty()) { + boolean preamblePosition = position.isEmpty() || position.getAsInt() <= 0; for (Pair<RetraceClassElementImpl, List<MemberNamingWithMappedRangesOfName>> mappedRange : mappedRanges) { - narrowedRanges.add(new RetraceFrameResultData(mappedRange.getFirst(), null, position)); + List<MemberNamingWithMappedRangesOfName> memberNamingWithMappedRanges = new ArrayList<>(); + // If we could find a result, and we have observed a reported preamble position, we create a + // mapping containing only the member-naming. + if (mappedRange.getSecond() != null && preamblePosition) { + memberNamingWithMappedRanges = + ListUtils.map( + mappedRange.getSecond(), + m -> + // Check if we have a catch-all range since that could map 0 to a non-zero + // original line. + m.isSingleCatchAllRange() + ? m + : new MemberNamingWithMappedRangesOfName( + m.getMemberNaming(), MappedRangesOfName.empty())); + } + narrowedRanges.add( + new RetraceFrameResultData( + mappedRange.getFirst(), memberNamingWithMappedRanges, position)); } } return new RetraceFrameResultImpl( @@ -186,7 +204,7 @@ } private Function<MemberNamingWithMappedRangesOfName, List<MappedRange>> filterOnNoPosition() { - return MemberNamingWithMappedRangesOfName::getMappedRanges; + return MemberNamingWithMappedRangesOfName::getMappedRangesWithNoMinifiedRangeAndPositionZero; } @Override
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java index b46adc0..a30bcf4 100644 --- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java +++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -3833,6 +3833,8 @@ private Map<DexMethod, MethodProcessingContext> methodProcessingContexts = new ConcurrentHashMap<>(); + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") private final List<ProgramMethod> desugaredMethods = new LinkedList<>(); private final Map<DexMethod, ProgramMethod> liveMethods = new ConcurrentHashMap<>();
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardClassSpecification.java b/src/main/java/com/android/tools/r8/shaking/ProguardClassSpecification.java index e13dc82..1ce8f04 100644 --- a/src/main/java/com/android/tools/r8/shaking/ProguardClassSpecification.java +++ b/src/main/java/com/android/tools/r8/shaking/ProguardClassSpecification.java
@@ -34,6 +34,8 @@ ImmutableList.builder(); protected ProguardTypeMatcher inheritanceClassName; protected boolean inheritanceIsExtends = false; + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") protected List<ProguardMemberRule> memberRules = new LinkedList<>(); protected Builder() { @@ -348,10 +350,11 @@ protected StringBuilder append(StringBuilder builder) { appendAnnotations(classAnnotations, builder); - boolean needsSpaceBeforeClassType = - StringUtils.appendNonEmpty(builder, null, classAccessFlags, null) - | StringUtils.appendNonEmpty( - builder, "!", negatedClassAccessFlags.toString().replace(" ", " !"), null); + boolean hasAccessFlags = StringUtils.appendNonEmpty(builder, null, classAccessFlags, null); + boolean hasNegatedAccessFlags = + StringUtils.appendNonEmpty( + builder, "!", negatedClassAccessFlags.toString().replace(" ", " !"), null); + boolean needsSpaceBeforeClassType = hasAccessFlags || hasNegatedAccessFlags; if (needsSpaceBeforeClassType) { builder.append(' '); }
diff --git a/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java b/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java index 907ed11..352facd 100644 --- a/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java +++ b/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
@@ -95,7 +95,6 @@ import java.util.Map.Entry; import java.util.Queue; import java.util.Set; -import java.util.Stack; import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; @@ -512,7 +511,7 @@ ProguardIfRule ifRule) { Set<Wrapper<DexMethod>> methodsMarked = options.forceProguardCompatibility ? null : new HashSet<>(); - Stack<DexClass> worklist = new Stack<>(); + Deque<DexClass> worklist = new ArrayDeque<>(); worklist.add(clazz); while (!worklist.isEmpty()) { DexClass currentClass = worklist.pop();
diff --git a/src/main/java/com/android/tools/r8/shaking/WhyAreYouKeepingConsumer.java b/src/main/java/com/android/tools/r8/shaking/WhyAreYouKeepingConsumer.java index d4f127a..483db26 100644 --- a/src/main/java/com/android/tools/r8/shaking/WhyAreYouKeepingConsumer.java +++ b/src/main/java/com/android/tools/r8/shaking/WhyAreYouKeepingConsumer.java
@@ -25,10 +25,10 @@ import com.android.tools.r8.utils.StringUtils; import com.android.tools.r8.utils.StringUtils.BraceType; import java.io.PrintStream; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Deque; import java.util.IdentityHashMap; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Objects; @@ -125,7 +125,7 @@ return null; } Map<GraphNode, GraphNode> seen = new IdentityHashMap<>(); - Deque<GraphPath> queue = new LinkedList<>(); + Deque<GraphPath> queue = new ArrayDeque<>(); GraphPath path = null; GraphNode current = node; while (true) {
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java index 44f53b1..efe5d62 100644 --- a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java +++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
@@ -66,9 +66,6 @@ public class SyntheticFinalization { - // TODO(b/237413146): Implement a non-quadratic grouping algorithm. - private static final int GROUP_COUNT_THRESHOLD = 10; - public static class Result { public final CommittedItems commit; public final NonIdentityGraphLens lens;
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java index 49746f4..3bbb9ae 100644 --- a/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java +++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
@@ -6,6 +6,8 @@ import static com.android.tools.r8.utils.ConsumerUtils.emptyConsumer; import com.android.tools.r8.FeatureSplit; +import com.android.tools.r8.SyntheticInfoConsumer; +import com.android.tools.r8.SyntheticInfoConsumerData; import com.android.tools.r8.contexts.CompilationContext.UniqueContext; import com.android.tools.r8.errors.MissingGlobalSyntheticsConsumerDiagnostic; import com.android.tools.r8.errors.Unreachable; @@ -38,6 +40,8 @@ import com.android.tools.r8.horizontalclassmerging.HorizontalClassMerger; import com.android.tools.r8.naming.NamingLens; import com.android.tools.r8.origin.Origin; +import com.android.tools.r8.references.ClassReference; +import com.android.tools.r8.references.Reference; import com.android.tools.r8.synthesis.SyntheticFinalization.Result; import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind; import com.android.tools.r8.utils.Box; @@ -1169,4 +1173,40 @@ return new SyntheticFinalization(appView.options(), this, committed) .computeFinalSynthetics(appView, timing); } + + public void reportSyntheticsInformation(SyntheticInfoConsumer consumer) { + assert isFinalized(); + Map<DexType, DexType> seen = new IdentityHashMap<>(); + committed.forEachItem( + ref -> { + DexType holder = ref.getHolder(); + DexType context = ref.getContext().getSynthesizingContextType(); + DexType old = seen.put(holder, context); + assert old == null || old == context; + if (old == null) { + consumer.acceptSyntheticInfo(new SyntheticInfoConsumerDataImpl(holder, context)); + } + }); + } + + private static class SyntheticInfoConsumerDataImpl implements SyntheticInfoConsumerData { + + private final DexType holder; + private final DexType context; + + public SyntheticInfoConsumerDataImpl(DexType holder, DexType context) { + this.holder = holder; + this.context = context; + } + + @Override + public ClassReference getSyntheticClass() { + return Reference.classFromDescriptor(holder.toDescriptorString()); + } + + @Override + public ClassReference getSynthesizingContextClass() { + return Reference.classFromDescriptor(context.toDescriptorString()); + } + } }
diff --git a/src/main/java/com/android/tools/r8/utils/AndroidAppConsumers.java b/src/main/java/com/android/tools/r8/utils/AndroidAppConsumers.java index 1c01a7b..7a77e25 100644 --- a/src/main/java/com/android/tools/r8/utils/AndroidAppConsumers.java +++ b/src/main/java/com/android/tools/r8/utils/AndroidAppConsumers.java
@@ -4,16 +4,14 @@ package com.android.tools.r8.utils; import com.android.tools.r8.BaseCompilerCommand; +import com.android.tools.r8.ByteDataView; import com.android.tools.r8.ClassFileConsumer; -import com.android.tools.r8.ClassFileConsumerData; import com.android.tools.r8.DataDirectoryResource; import com.android.tools.r8.DataEntryResource; import com.android.tools.r8.DataResourceConsumer; import com.android.tools.r8.DexFilePerClassFileConsumer; -import com.android.tools.r8.DexFilePerClassFileConsumerData; import com.android.tools.r8.DexIndexedConsumer; import com.android.tools.r8.DexIndexedConsumer.ForwardingConsumer; -import com.android.tools.r8.DexIndexedConsumerData; import com.android.tools.r8.DiagnosticsHandler; import com.android.tools.r8.ProgramConsumer; import com.android.tools.r8.ResourceException; @@ -105,9 +103,13 @@ new Int2ReferenceAVLTreeMap<>(); @Override - public void acceptDexIndexedFile(DexIndexedConsumerData data) { - super.acceptDexIndexedFile(data); - addDexFile(data.getFileIndex(), data.getByteDataCopy(), data.getClassDescriptors()); + public void accept( + int fileIndex, + ByteDataView data, + Set<String> descriptors, + DiagnosticsHandler handler) { + super.accept(fileIndex, data, descriptors, handler); + addDexFile(fileIndex, data.copyByteData(), descriptors); } @Override @@ -180,12 +182,13 @@ private TreeMap<String, DescriptorsWithContents> files = new TreeMap<>(); @Override - public void acceptDexFile(DexFilePerClassFileConsumerData data) { - super.acceptDexFile(data); - addDexFile( - data.getPrimaryClassDescriptor(), - data.getByteDataCopy(), - data.getClassDescriptors()); + public void accept( + String primaryClassDescriptor, + ByteDataView data, + Set<String> descriptors, + DiagnosticsHandler handler) { + super.accept(primaryClassDescriptor, data, descriptors, handler); + addDexFile(primaryClassDescriptor, data.copyByteData(), descriptors); } synchronized void addDexFile( @@ -255,9 +258,9 @@ private List<DescriptorsWithContents> files = new ArrayList<>(); @Override - public void acceptClassFile(ClassFileConsumerData data) { - super.acceptClassFile(data); - addClassFile(data.getByteDataCopy(), data.getClassDescriptor()); + public void accept(ByteDataView data, String descriptor, DiagnosticsHandler handler) { + super.accept(data, descriptor, handler); + addClassFile(data.copyByteData(), descriptor); } synchronized void addClassFile(byte[] data, String descriptor) {
diff --git a/src/main/java/com/android/tools/r8/utils/ClassFileConsumerDataImpl.java b/src/main/java/com/android/tools/r8/utils/ClassFileConsumerDataImpl.java deleted file mode 100644 index b375086..0000000 --- a/src/main/java/com/android/tools/r8/utils/ClassFileConsumerDataImpl.java +++ /dev/null
@@ -1,43 +0,0 @@ -// Copyright (c) 2023, 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.utils; - -import com.android.tools.r8.ByteDataView; -import com.android.tools.r8.ClassFileConsumerData; -import com.android.tools.r8.DiagnosticsHandler; - -/** Internal implementation of the consumer data. */ -public class ClassFileConsumerDataImpl implements ClassFileConsumerData { - - private final ByteDataView data; - private final String descriptor; - private final DiagnosticsHandler handler; - - public ClassFileConsumerDataImpl( - ByteDataView data, String descriptor, DiagnosticsHandler handler) { - this.data = data; - this.descriptor = descriptor; - this.handler = handler; - } - - @Override - public ByteDataView getByteDataView() { - return data; - } - - @Override - public byte[] getByteDataCopy() { - return data.copyByteData(); - } - - @Override - public String getClassDescriptor() { - return descriptor; - } - - @Override - public DiagnosticsHandler getDiagnosticsHandler() { - return handler; - } -}
diff --git a/src/main/java/com/android/tools/r8/utils/DeterminismChecker.java b/src/main/java/com/android/tools/r8/utils/DeterminismChecker.java index 2f95428..c1817a7 100644 --- a/src/main/java/com/android/tools/r8/utils/DeterminismChecker.java +++ b/src/main/java/com/android/tools/r8/utils/DeterminismChecker.java
@@ -121,7 +121,7 @@ return; } if (method.hasCode()) { - String[] lines = method.getCode().toString().split("\n"); + List<String> lines = StringUtils.splitLines(method.getCode().toString()); for (String line : lines) { if (!callback.onLine(line)) { return;
diff --git a/src/main/java/com/android/tools/r8/utils/DexFilePerClassFileConsumerDataImpl.java b/src/main/java/com/android/tools/r8/utils/DexFilePerClassFileConsumerDataImpl.java index 9dc9e8b..e69de29 100644 --- a/src/main/java/com/android/tools/r8/utils/DexFilePerClassFileConsumerDataImpl.java +++ b/src/main/java/com/android/tools/r8/utils/DexFilePerClassFileConsumerDataImpl.java
@@ -1,61 +0,0 @@ -// Copyright (c) 2023, 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.utils; - -import com.android.tools.r8.ByteDataView; -import com.android.tools.r8.DexFilePerClassFileConsumerData; -import com.android.tools.r8.DiagnosticsHandler; -import java.util.Set; - -public class DexFilePerClassFileConsumerDataImpl implements DexFilePerClassFileConsumerData { - - private final String primaryClassDescriptor; - private final String synthesizingContextDescriptor; - private final ByteDataView data; - private final Set<String> classDescriptors; - private final DiagnosticsHandler handler; - - public DexFilePerClassFileConsumerDataImpl( - String primaryClassDescriptor, - String synthesizingContextDescriptor, - ByteDataView data, - Set<String> classDescriptors, - DiagnosticsHandler handler) { - this.primaryClassDescriptor = primaryClassDescriptor; - this.synthesizingContextDescriptor = synthesizingContextDescriptor; - this.data = data; - this.classDescriptors = classDescriptors; - this.handler = handler; - } - - @Override - public String getPrimaryClassDescriptor() { - return primaryClassDescriptor; - } - - @Override - public String getSynthesizingContextForPrimaryClass() { - return synthesizingContextDescriptor; - } - - @Override - public ByteDataView getByteDataView() { - return data; - } - - @Override - public byte[] getByteDataCopy() { - return data.copyByteData(); - } - - @Override - public Set<String> getClassDescriptors() { - return classDescriptors; - } - - @Override - public DiagnosticsHandler getDiagnosticsHandler() { - return handler; - } -}
diff --git a/src/main/java/com/android/tools/r8/utils/DexIndexedConsumerDataImpl.java b/src/main/java/com/android/tools/r8/utils/DexIndexedConsumerDataImpl.java deleted file mode 100644 index 2de21e4..0000000 --- a/src/main/java/com/android/tools/r8/utils/DexIndexedConsumerDataImpl.java +++ /dev/null
@@ -1,50 +0,0 @@ -// Copyright (c) 2023, 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.utils; - -import com.android.tools.r8.ByteDataView; -import com.android.tools.r8.DexIndexedConsumerData; -import com.android.tools.r8.DiagnosticsHandler; -import java.util.Set; - -public class DexIndexedConsumerDataImpl implements DexIndexedConsumerData { - - private final int fileIndex; - private final ByteDataView data; - private final Set<String> classDescriptors; - private final DiagnosticsHandler handler; - - public DexIndexedConsumerDataImpl( - int fileIndex, ByteDataView data, Set<String> classDescriptors, DiagnosticsHandler handler) { - this.fileIndex = fileIndex; - this.data = data; - this.classDescriptors = classDescriptors; - this.handler = handler; - } - - @Override - public int getFileIndex() { - return fileIndex; - } - - @Override - public ByteDataView getByteDataView() { - return data; - } - - @Override - public byte[] getByteDataCopy() { - return data.copyByteData(); - } - - @Override - public Set<String> getClassDescriptors() { - return classDescriptors; - } - - @Override - public DiagnosticsHandler getDiagnosticsHandler() { - return handler; - } -}
diff --git a/src/main/java/com/android/tools/r8/utils/InternalGlobalSyntheticsProgramConsumer.java b/src/main/java/com/android/tools/r8/utils/InternalGlobalSyntheticsProgramConsumer.java index 6fcc519..1428459 100644 --- a/src/main/java/com/android/tools/r8/utils/InternalGlobalSyntheticsProgramConsumer.java +++ b/src/main/java/com/android/tools/r8/utils/InternalGlobalSyntheticsProgramConsumer.java
@@ -9,7 +9,6 @@ import com.android.tools.r8.ByteDataView; import com.android.tools.r8.ClassFileConsumer; import com.android.tools.r8.DexFilePerClassFileConsumer; -import com.android.tools.r8.DexFilePerClassFileConsumerData; import com.android.tools.r8.DiagnosticsHandler; import com.android.tools.r8.GlobalSyntheticsConsumer; import com.android.tools.r8.ProgramConsumer; @@ -103,8 +102,12 @@ } @Override - public synchronized void acceptDexFile(DexFilePerClassFileConsumerData data) { - builder.addGlobalSynthetic(data.getPrimaryClassDescriptor(), data.getByteDataCopy()); + public synchronized void accept( + String primaryClassDescriptor, + ByteDataView data, + Set<String> descriptors, + DiagnosticsHandler handler) { + builder.addGlobalSynthetic(primaryClassDescriptor, data.copyByteData()); } @Override @@ -146,8 +149,12 @@ } @Override - public void acceptDexFile(DexFilePerClassFileConsumerData data) { - addGlobal(data.getPrimaryClassDescriptor(), data.getByteDataView()); + public void accept( + String primaryClassDescriptor, + ByteDataView data, + Set<String> descriptors, + DiagnosticsHandler handler) { + addGlobal(primaryClassDescriptor, data); } @Override
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 b26527a..0d7a71c 100644 --- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java +++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -18,6 +18,7 @@ import com.android.tools.r8.ProgramConsumer; import com.android.tools.r8.SourceFileProvider; import com.android.tools.r8.StringConsumer; +import com.android.tools.r8.SyntheticInfoConsumer; import com.android.tools.r8.Version; import com.android.tools.r8.androidapi.ComputedApiLevel; import com.android.tools.r8.cf.CfVersion; @@ -181,6 +182,7 @@ public ProgramClassConflictResolver programClassConflictResolver = null; private GlobalSyntheticsConsumer globalSyntheticsConsumer = null; + private SyntheticInfoConsumer syntheticInfoConsumer = null; public DataResourceConsumer dataResourceConsumer; public FeatureSplitConfiguration featureSplitConfiguration; @@ -517,6 +519,14 @@ this.globalSyntheticsConsumer = globalSyntheticsConsumer; } + public void setSyntheticInfoConsumer(SyntheticInfoConsumer syntheticInfoConsumer) { + this.syntheticInfoConsumer = syntheticInfoConsumer; + } + + public SyntheticInfoConsumer getSyntheticInfoConsumer() { + return syntheticInfoConsumer; + } + public boolean isDesugaredLibraryCompilation() { return machineDesugaredLibrarySpecification.isLibraryCompilation(); } @@ -938,9 +948,7 @@ String property = System.getProperty("com.android.tools.r8.extensiveLoggingFilter"); if (property != null) { ImmutableSet.Builder<String> builder = ImmutableSet.builder(); - for (String method : property.split(";")) { - builder.add(method); - } + StringUtils.splitForEach(property, ';', builder::add); return builder.build(); } return ImmutableSet.of(); @@ -951,9 +959,7 @@ System.getProperty("com.android.tools.r8.extensiveInterfaceMethodMinifierLoggingFilter"); if (property != null) { ImmutableSet.Builder<String> builder = ImmutableSet.builder(); - for (String method : property.split(";")) { - builder.add(method); - } + StringUtils.splitForEach(property, ';', builder::add); return builder.build(); } return ImmutableSet.of();
diff --git a/src/main/java/com/android/tools/r8/utils/ListUtils.java b/src/main/java/com/android/tools/r8/utils/ListUtils.java index 55fe509..47549a6 100644 --- a/src/main/java/com/android/tools/r8/utils/ListUtils.java +++ b/src/main/java/com/android/tools/r8/utils/ListUtils.java
@@ -218,12 +218,16 @@ return builder.build(); } + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") public static <T> LinkedList<T> newLinkedList(T element) { LinkedList<T> list = new LinkedList<>(); list.add(element); return list; } + // TODO(b/270398965): Replace LinkedList. + @SuppressWarnings("JdkObsolete") public static <T> LinkedList<T> newLinkedList(ForEachable<T> forEachable) { LinkedList<T> list = new LinkedList<>(); forEachable.forEach(list::add);
diff --git a/src/main/java/com/android/tools/r8/utils/StringUtils.java b/src/main/java/com/android/tools/r8/utils/StringUtils.java index efe43d3..a561718 100644 --- a/src/main/java/com/android/tools/r8/utils/StringUtils.java +++ b/src/main/java/com/android/tools/r8/utils/StringUtils.java
@@ -14,6 +14,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.function.Consumer; import java.util.function.Function; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -55,7 +56,8 @@ public static String toASCIIString(String s) { StringBuilder builder = new StringBuilder(); - for (char ch : s.toCharArray()) { + for (int i = 0; i < s.length(); i++) { + char ch = s.charAt(i); if (0x1f < ch && ch < 0x7f) { // 0 - 0x1f and 0x7f are control characters. builder.append(ch); } else { @@ -65,6 +67,68 @@ return builder.toString(); } + // Utilities for splitting (and avoiding errorprone String.split). + + /** + * Iterate over the substrings of a string split by a single char separator. + * + * <p>No special treatment of whitespace. No occurrence of the separator will appear in any + * split-off substring. Given N occurrences of the separator, the resulting callback will be + * called N+1 times. + */ + public static void splitForEach(String string, char separator, Consumer<String> fn) { + int length = string.length(); + int start = 0; + for (int i = 0; i < length; i++) { + char c = string.charAt(i); + if (c == separator) { + fn.accept(string.substring(start, i)); + start = i + 1; + } + } + fn.accept(string.substring(start)); + } + + /** + * Split a string by a single char separator. + * + * <p>No special treatment of whitespace. No occurrence of the separator will appear in any + * split-off substring. Given N occurrences of the separator, the resulting split list will have + * size N+1. + */ + public static List<String> split(String string, char separator) { + List<String> result = new ArrayList<>(); + splitForEach(string, separator, result::add); + return result; + } + + /** + * Split a string by a single char separator with the requirement on the split size. + * + * <p>No special treatment of whitespace. No occurrence of the separator will appear in any + * split-off substring. Given N occurrences of the separator, the resulting split list will have + * size N+1. + * + * <p>Thus for a valid split with size=N, the result will be an array of length N if and only if + * the input string has exactly N-1 occurrences of the separator. In any other case the return + * value is null. + */ + public static String[] splitKnownSize(String string, char separator, int size) { + assert size > 1; + String[] result = new String[size]; + IntBox box = new IntBox(0); + splitForEach( + string, + separator, + part -> { + int i = box.getAndIncrement(); + if (i < size) { + result[i] = part; + } + }); + return size == box.get() ? result : null; + } + public static boolean appendNonEmpty( StringBuilder builder, String pre, Object item, String post) { if (item == null) {
diff --git a/src/main/java/com/android/tools/r8/utils/Timing.java b/src/main/java/com/android/tools/r8/utils/Timing.java index b4519a9..3947cae 100644 --- a/src/main/java/com/android/tools/r8/utils/Timing.java +++ b/src/main/java/com/android/tools/r8/utils/Timing.java
@@ -20,7 +20,6 @@ import java.util.LinkedHashMap; import java.util.Map; import java.util.Map.Entry; -import java.util.Stack; public class Timing { @@ -75,7 +74,7 @@ } private final Node top; - private final Stack<Node> stack; + private final Deque<Node> stack; private final boolean trackMemory; @Deprecated @@ -85,7 +84,7 @@ private Timing(String title, boolean trackMemory) { this.trackMemory = trackMemory; - stack = new Stack<>(); + stack = new ArrayDeque<>(); top = new Node(title, trackMemory); stack.push(top); }
diff --git a/src/test/java/com/android/tools/r8/D8CommandTest.java b/src/test/java/com/android/tools/r8/D8CommandTest.java index ff10302..11cebfd 100644 --- a/src/test/java/com/android/tools/r8/D8CommandTest.java +++ b/src/test/java/com/android/tools/r8/D8CommandTest.java
@@ -44,6 +44,7 @@ import java.nio.file.Paths; import java.util.Collection; import java.util.List; +import java.util.Set; import java.util.function.Predicate; import java.util.zip.ZipFile; import org.junit.Test; @@ -465,10 +466,15 @@ class MultiTypeConsumer implements DexIndexedConsumer, DexFilePerClassFileConsumer { @Override - public void acceptDexFile(DexFilePerClassFileConsumerData data) {} + public void accept( + String primaryClassDescriptor, + ByteDataView data, + Set<String> descriptors, + DiagnosticsHandler handler) {} @Override - public void acceptDexIndexedFile(DexIndexedConsumerData data) {} + public void accept( + int fileIndex, ByteDataView data, Set<String> descriptors, DiagnosticsHandler handler) {} @Override public void finished(DiagnosticsHandler handler) {
diff --git a/src/test/java/com/android/tools/r8/ExtractMarkerTest.java b/src/test/java/com/android/tools/r8/ExtractMarkerTest.java index e8a4d1d..6ed73d8 100644 --- a/src/test/java/com/android/tools/r8/ExtractMarkerTest.java +++ b/src/test/java/com/android/tools/r8/ExtractMarkerTest.java
@@ -14,6 +14,7 @@ import com.android.tools.r8.utils.BooleanUtils; import java.nio.file.Paths; import java.util.Collection; +import java.util.Set; import org.junit.Assume; import org.junit.Test; import org.junit.runner.RunWith; @@ -59,11 +60,15 @@ .setProgramConsumer( new DexIndexedConsumer.ForwardingConsumer(null) { @Override - public void acceptDexIndexedFile(DexIndexedConsumerData data) { + public void accept( + int fileIndex, + ByteDataView data, + Set<String> descriptors, + DiagnosticsHandler handler) { Marker marker; try { Collection<Marker> markers = - ExtractMarker.extractMarkerFromDexProgramData(data.getByteDataCopy()); + ExtractMarker.extractMarkerFromDexProgramData(data.copyByteData()); assertEquals(1, markers.size()); marker = markers.iterator().next(); } catch (Exception e) { @@ -99,11 +104,12 @@ .setProgramConsumer( new ClassFileConsumer.ForwardingConsumer(null) { @Override - public void acceptClassFile(ClassFileConsumerData data) { + public void accept( + ByteDataView data, String descriptor, DiagnosticsHandler handler) { Marker marker; try { Collection<Marker> markers = - ExtractMarker.extractMarkerFromClassProgramData(data.getByteDataCopy()); + ExtractMarker.extractMarkerFromClassProgramData(data.copyByteData()); assertEquals(1, markers.size()); marker = markers.iterator().next(); } catch (Exception e) {
diff --git a/src/test/java/com/android/tools/r8/KotlinCompilerTool.java b/src/test/java/com/android/tools/r8/KotlinCompilerTool.java index 259f1a0..642e319 100644 --- a/src/test/java/com/android/tools/r8/KotlinCompilerTool.java +++ b/src/test/java/com/android/tools/r8/KotlinCompilerTool.java
@@ -17,6 +17,7 @@ import com.android.tools.r8.utils.ArrayUtils; import com.android.tools.r8.utils.FileUtils; import com.android.tools.r8.utils.structural.Ordered; +import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -367,6 +368,9 @@ } cmdline.addAll(additionalArguments); ProcessBuilder builder = new ProcessBuilder(cmdline); + if (ToolHelper.isNewGradleSetup()) { + builder.directory(new File(ToolHelper.getProjectRoot())); + } return ToolHelper.runProcess(builder); } }
diff --git a/src/test/java/com/android/tools/r8/ProguardMapMarkerTest.java b/src/test/java/com/android/tools/r8/ProguardMapMarkerTest.java index 5be0095..f0b68de 100644 --- a/src/test/java/com/android/tools/r8/ProguardMapMarkerTest.java +++ b/src/test/java/com/android/tools/r8/ProguardMapMarkerTest.java
@@ -63,11 +63,15 @@ .setProgramConsumer( new DexIndexedConsumer.ForwardingConsumer(null) { @Override - public void acceptDexIndexedFile(DexIndexedConsumerData data) { + public void accept( + int fileIndex, + ByteDataView data, + Set<String> descriptors, + DiagnosticsHandler handler) { Marker marker; try { Collection<Marker> markers = - ExtractMarker.extractMarkerFromDexProgramData(data.getByteDataCopy()); + ExtractMarker.extractMarkerFromDexProgramData(data.copyByteData()); assertEquals(1, markers.size()); marker = markers.iterator().next(); } catch (Exception e) { @@ -107,11 +111,12 @@ .setProgramConsumer( new ClassFileConsumer.ForwardingConsumer(null) { @Override - public void acceptClassFile(ClassFileConsumerData data) { + public void accept( + ByteDataView data, String descriptor, DiagnosticsHandler handler) { Marker marker; try { Collection<Marker> markers = - ExtractMarker.extractMarkerFromClassProgramData(data.getByteDataCopy()); + ExtractMarker.extractMarkerFromClassProgramData(data.copyByteData()); assertEquals(1, markers.size()); marker = markers.iterator().next(); } catch (Exception e) {
diff --git a/src/test/java/com/android/tools/r8/R8ModeMarkerTest.java b/src/test/java/com/android/tools/r8/R8ModeMarkerTest.java index d4ab329..32f0871 100644 --- a/src/test/java/com/android/tools/r8/R8ModeMarkerTest.java +++ b/src/test/java/com/android/tools/r8/R8ModeMarkerTest.java
@@ -8,6 +8,7 @@ import com.android.tools.r8.dex.Marker; import java.util.Collection; +import java.util.Set; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -39,10 +40,11 @@ } @Override - public void acceptDexIndexedFile(DexIndexedConsumerData data) { + public void accept( + int fileIndex, ByteDataView data, Set<String> descriptors, DiagnosticsHandler handler) { try { Collection<Marker> markers = - ExtractMarker.extractMarkerFromDexProgramData(data.getByteDataCopy()); + ExtractMarker.extractMarkerFromDexProgramData(data.copyByteData()); assertEquals(1, markers.size()); marker = markers.iterator().next(); } catch (Exception e) { @@ -65,10 +67,10 @@ } @Override - public void acceptClassFile(ClassFileConsumerData data) { + public void accept(ByteDataView data, String descriptors, DiagnosticsHandler handler) { try { Collection<Marker> markers = - ExtractMarker.extractMarkerFromClassProgramData(data.getByteDataCopy()); + ExtractMarker.extractMarkerFromClassProgramData(data.copyByteData()); assertEquals(1, markers.size()); marker = markers.iterator().next(); } catch (Exception e) {
diff --git a/src/test/java/com/android/tools/r8/R8RunSmaliTestsTest.java b/src/test/java/com/android/tools/r8/R8RunSmaliTestsTest.java index a89ee46..384043c 100644 --- a/src/test/java/com/android/tools/r8/R8RunSmaliTestsTest.java +++ b/src/test/java/com/android/tools/r8/R8RunSmaliTestsTest.java
@@ -216,7 +216,6 @@ @Test public void SmaliTest() throws Exception { Path originalDexFile = Paths.get(SMALI_DIR, directoryName, dexFileName); - // Path outputPath = temp.getRoot().toPath().resolve("classes.dex"); if (failingOnX8.contains(directoryName)) { thrown.expect(CompilationFailedException.class); @@ -229,9 +228,21 @@ boolean originalFailing = (originalFailingOnArtVersions.containsKey(version) && originalFailingOnArtVersions.get(version).contains(directoryName)); + Path testJar = Paths.get(SMALI_DIR, directoryName, "Test.jar"); + boolean testJarExists = testJar.toFile().exists(); + Path testJarDex = null; + if (testJarExists) { + testJarDex = + testForD8(Backend.DEX) + .setMinApi(parameters) + .addProgramFiles(testJar) + .compile() + .writeToZip(); + } testForR8(parameters.getBackend()) .addKeepAllClassesRule() .addProgramDexFileData(Files.readAllBytes(originalDexFile)) + .applyIf(testJarExists, p -> p.addProgramFiles(testJar)) .addDontWarn(missingClasses.getOrDefault(directoryName, Collections.emptySet())) .setMinApi(parameters) .compile() @@ -243,12 +254,14 @@ // Also run the original DEX if possible. if (!dalvikVerificationError && !originalFailing) { + ImmutableList.Builder<String> dexListBuilder = ImmutableList.builder(); + dexListBuilder.add(originalDexFile.toString()); + if (testJarExists) { + dexListBuilder.add(testJarDex.toString()); + } String originalOutput = ToolHelper.runArtNoVerificationErrors( - ImmutableList.of(originalDexFile.toString()), - "Test", - null, - parameters.getRuntime().asDex().getVm()); + dexListBuilder.build(), "Test", null, parameters.getRuntime().asDex().getVm()); assertEquals(expectedOutput, originalOutput); } }
diff --git a/src/test/java/com/android/tools/r8/ToolHelper.java b/src/test/java/com/android/tools/r8/ToolHelper.java index 51ed733..592892a 100644 --- a/src/test/java/com/android/tools/r8/ToolHelper.java +++ b/src/test/java/com/android/tools/r8/ToolHelper.java
@@ -97,9 +97,9 @@ } public static String getProjectRoot() { - String property = System.getProperty("user.dir"); - if (property.endsWith("d8_r8/test")) { - return "../../"; + String userDirProperty = System.getProperty("user.dir"); + if (userDirProperty.endsWith("d8_r8/test")) { + return Paths.get(userDirProperty).getParent().getParent().toString() + "/"; } return ""; } @@ -2273,7 +2273,7 @@ throws IOException { boolean printCwd = builder.directory() != null; if (printCwd) { - out.println("(cd " + builder.directory().toString() + "; "); + out.println("(cd " + builder.directory() + "; "); } String command = String.join(" ", builder.command()); out.println(command);
diff --git a/src/test/java/com/android/tools/r8/compilerapi/CompilerApiTest.java b/src/test/java/com/android/tools/r8/compilerapi/CompilerApiTest.java index 7a10578..60ca0c6 100644 --- a/src/test/java/com/android/tools/r8/compilerapi/CompilerApiTest.java +++ b/src/test/java/com/android/tools/r8/compilerapi/CompilerApiTest.java
@@ -80,8 +80,17 @@ return PostStartupMockClass.class; } + public static Path getProjectRoot() { + String userDirProperty = System.getProperty("user.dir"); + if (userDirProperty.endsWith("d8_r8/test")) { + return Paths.get(userDirProperty).getParent().getParent(); + } + return Paths.get(""); + } + public Path getJava8RuntimeJar() { - return Paths.get("third_party", "openjdk", "openjdk-rt-1.8", "rt.jar"); + return getProjectRoot() + .resolve(Paths.get("third_party", "openjdk", "openjdk-rt-1.8", "rt.jar")); } public List<String> getKeepMainRules(Class<?> clazz) {
diff --git a/src/test/java/com/android/tools/r8/compilerapi/CompilerApiTestCollection.java b/src/test/java/com/android/tools/r8/compilerapi/CompilerApiTestCollection.java index f4ef14b..c2d4a30 100644 --- a/src/test/java/com/android/tools/r8/compilerapi/CompilerApiTestCollection.java +++ b/src/test/java/com/android/tools/r8/compilerapi/CompilerApiTestCollection.java
@@ -13,7 +13,6 @@ import com.android.tools.r8.compilerapi.assertionconfiguration.AssertionConfigurationTest; import com.android.tools.r8.compilerapi.classconflictresolver.ClassConflictResolverTest; import com.android.tools.r8.compilerapi.desugardependencies.DesugarDependenciesTest; -import com.android.tools.r8.compilerapi.dexconsumers.PerClassSyntheticContextsTest; import com.android.tools.r8.compilerapi.diagnostics.ProguardKeepRuleDiagnosticsApiTest; import com.android.tools.r8.compilerapi.diagnostics.UnsupportedFeaturesDiagnosticApiTest; import com.android.tools.r8.compilerapi.globalsynthetics.GlobalSyntheticsTest; @@ -24,6 +23,7 @@ import com.android.tools.r8.compilerapi.mockdata.PostStartupMockClass; import com.android.tools.r8.compilerapi.sourcefile.CustomSourceFileTest; import com.android.tools.r8.compilerapi.startupprofile.StartupProfileApiTest; +import com.android.tools.r8.compilerapi.syntheticscontexts.SyntheticContextsConsumerTest; import com.android.tools.r8.compilerapi.testsetup.ApiTestingSetUpTest; import com.android.tools.r8.compilerapi.wrappers.CommandLineParserTest; import com.android.tools.r8.compilerapi.wrappers.EnableMissingLibraryApiModelingTest; @@ -60,7 +60,7 @@ StartupProfileApiTest.ApiTest.class, ClassConflictResolverTest.ApiTest.class, ProguardKeepRuleDiagnosticsApiTest.ApiTest.class, - PerClassSyntheticContextsTest.ApiTest.class); + SyntheticContextsConsumerTest.ApiTest.class); private final TemporaryFolder temp;
diff --git a/src/test/java/com/android/tools/r8/compilerapi/dexconsumers/PerClassSyntheticContextsTest.java b/src/test/java/com/android/tools/r8/compilerapi/syntheticscontexts/SyntheticContextsConsumerTest.java similarity index 66% rename from src/test/java/com/android/tools/r8/compilerapi/dexconsumers/PerClassSyntheticContextsTest.java rename to src/test/java/com/android/tools/r8/compilerapi/syntheticscontexts/SyntheticContextsConsumerTest.java index 69f7b9b..f596594 100644 --- a/src/test/java/com/android/tools/r8/compilerapi/dexconsumers/PerClassSyntheticContextsTest.java +++ b/src/test/java/com/android/tools/r8/compilerapi/syntheticscontexts/SyntheticContextsConsumerTest.java
@@ -1,17 +1,18 @@ // Copyright (c) 2023, 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.compilerapi.dexconsumers; +package com.android.tools.r8.compilerapi.syntheticscontexts; import static org.junit.Assert.assertEquals; +import com.android.tools.r8.ByteDataView; import com.android.tools.r8.ClassFileConsumer; -import com.android.tools.r8.ClassFileConsumerData; import com.android.tools.r8.D8; import com.android.tools.r8.D8Command; import com.android.tools.r8.DexFilePerClassFileConsumer; -import com.android.tools.r8.DexFilePerClassFileConsumerData; import com.android.tools.r8.DiagnosticsHandler; +import com.android.tools.r8.SyntheticInfoConsumer; +import com.android.tools.r8.SyntheticInfoConsumerData; import com.android.tools.r8.TestParameters; import com.android.tools.r8.compilerapi.CompilerApiTest; import com.android.tools.r8.compilerapi.CompilerApiTestRunner; @@ -20,12 +21,14 @@ import com.android.tools.r8.synthesis.SyntheticItemsTestUtils; import java.util.HashMap; import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; import org.junit.Test; -public class PerClassSyntheticContextsTest extends CompilerApiTestRunner { +public class SyntheticContextsConsumerTest extends CompilerApiTestRunner { - public PerClassSyntheticContextsTest(TestParameters parameters) { + public SyntheticContextsConsumerTest(TestParameters parameters) { super(parameters); } @@ -47,8 +50,8 @@ new ClassFileConsumer() { @Override - public void acceptClassFile(ClassFileConsumerData data) { - outputs.put(data.getClassDescriptor(), data.getByteDataCopy()); + public void accept(ByteDataView data, String descriptor, DiagnosticsHandler handler) { + outputs.put(descriptor, data.copyByteData()); } @Override @@ -76,16 +79,36 @@ } public void run(byte[] input, Consumer<String> syntheticContext) throws Exception { + Map<String, String> synthetic2context = new ConcurrentHashMap<>(); D8.run( D8Command.builder() .addClassProgramData(input, Origin.unknown()) .addLibraryFiles(getJava8RuntimeJar()) .setMinApiLevel(1) + .setSyntheticInfoConsumer( + new SyntheticInfoConsumer() { + @Override + public void acceptSyntheticInfo(SyntheticInfoConsumerData data) { + synthetic2context.put( + data.getSyntheticClass().getDescriptor(), + data.getSynthesizingContextClass().getDescriptor()); + } + + @Override + public void finished() { + // nothing to finish up. + } + }) .setProgramConsumer( new DexFilePerClassFileConsumer() { + @Override - public void acceptDexFile(DexFilePerClassFileConsumerData data) { - syntheticContext.accept(data.getSynthesizingContextForPrimaryClass()); + public void accept( + String primaryClassDescriptor, + ByteDataView data, + Set<String> descriptors, + DiagnosticsHandler handler) { + syntheticContext.accept(synthetic2context.get(primaryClassDescriptor)); } @Override
diff --git a/src/test/java/com/android/tools/r8/d8/DexVersionTests.java b/src/test/java/com/android/tools/r8/d8/DexVersionTests.java index 7c82964..f413f98 100644 --- a/src/test/java/com/android/tools/r8/d8/DexVersionTests.java +++ b/src/test/java/com/android/tools/r8/d8/DexVersionTests.java
@@ -5,17 +5,18 @@ import static org.junit.Assert.assertTrue; +import com.android.tools.r8.ByteDataView; import com.android.tools.r8.CompilationFailedException; import com.android.tools.r8.D8; import com.android.tools.r8.D8Command; import com.android.tools.r8.DexIndexedConsumer; -import com.android.tools.r8.DexIndexedConsumerData; import com.android.tools.r8.DiagnosticsHandler; import com.android.tools.r8.OutputMode; import com.android.tools.r8.ToolHelper; import com.android.tools.r8.utils.AndroidApiLevel; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Set; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -76,7 +77,8 @@ boolean hasOutput = false; @Override - public void acceptDexIndexedFile(DexIndexedConsumerData data) { + public void accept( + int fileIndex, ByteDataView data, Set<String> descriptors, DiagnosticsHandler handler) { hasOutput = true; }
diff --git a/src/test/java/com/android/tools/r8/debuginfo/NoLineInfoTest.java b/src/test/java/com/android/tools/r8/debuginfo/NoLineInfoTest.java index 87820f1..f0d4c89 100644 --- a/src/test/java/com/android/tools/r8/debuginfo/NoLineInfoTest.java +++ b/src/test/java/com/android/tools/r8/debuginfo/NoLineInfoTest.java
@@ -5,6 +5,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assume.assumeFalse; import com.android.tools.r8.TestBase; @@ -126,7 +127,10 @@ assertThat( "Unexpected input-source stacktrace", stacktrace, - StackTrace.isSame(getUnexpectedRetracedStacktrace()))); + StackTrace.isSame( + parameters.isCfRuntime() + ? getExpectedInputStacktrace() + : getUnexpectedRetracedStacktrace()))); } private StackTraceLine line(String file, String method, int line) { @@ -201,10 +205,9 @@ // TODO(b/232212653): The retraced stack trace should be the same as `getExpectedInputStacktrace`. private StackTrace getUnexpectedRetracedStacktrace() { + assertFalse(parameters.isCfRuntime()); StackTraceLine fooLine; - if (parameters.isCfRuntime()) { - fooLine = inputLine("foo", -1); - } else if (customSourceFile) { + if (customSourceFile) { // TODO(b/232212653): Should retrace convert out of "0" and represent it as <noline>/-1? fooLine = inputLine("foo", 0); } else if (isRuntimeWithPcAsLineNumberSupport()) { @@ -213,17 +216,8 @@ } else { fooLine = inputLine("foo", -1); } - - // TODO(b/232212653): Normal line-opt will cause a single-line mapping. Retrace should not - // optimize that to mean it represents a single possible line. (<noline> should not match 1:x). - StackTraceLine barLine = - parameters.isCfRuntime() ? inputLine("bar", 100) : inputLine("bar", getPcEncoding(0)); - - // TODO(b/232212653): The retracing in CF where the line table is preserved is incorrect. - // same issue as for bar. - StackTraceLine bazLine = - parameters.isCfRuntime() ? inputLine("baz", 100) : inputLine("baz", getPcEncoding(0)); - + StackTraceLine barLine = inputLine("bar", getPcEncoding(0)); + StackTraceLine bazLine = inputLine("baz", getPcEncoding(0)); return StackTrace.builder() .add(fooLine) .add(barLine)
diff --git a/src/test/java/com/android/tools/r8/desugar/DesugarToClassFileDeprecatedAttribute.java b/src/test/java/com/android/tools/r8/desugar/DesugarToClassFileDeprecatedAttribute.java index 2bc0090..efcc639 100644 --- a/src/test/java/com/android/tools/r8/desugar/DesugarToClassFileDeprecatedAttribute.java +++ b/src/test/java/com/android/tools/r8/desugar/DesugarToClassFileDeprecatedAttribute.java
@@ -6,10 +6,11 @@ import static org.junit.Assert.assertTrue; +import com.android.tools.r8.ByteDataView; import com.android.tools.r8.ClassFileConsumer; import com.android.tools.r8.ClassFileConsumer.ForwardingConsumer; -import com.android.tools.r8.ClassFileConsumerData; import com.android.tools.r8.D8TestCompileResult; +import com.android.tools.r8.DiagnosticsHandler; import com.android.tools.r8.R8FullTestBuilder; import com.android.tools.r8.TestBase; import com.android.tools.r8.TestParameters; @@ -90,8 +91,9 @@ .setProgramConsumer( new ClassFileConsumer.ForwardingConsumer(null) { @Override - public void acceptClassFile(ClassFileConsumerData data) { - checkDeprecatedAttributes(data.getByteDataView().getBuffer()); + public void accept( + ByteDataView data, String descriptor, DiagnosticsHandler handler) { + checkDeprecatedAttributes(data.getBuffer()); } }) .compile(); @@ -126,8 +128,8 @@ builder.setProgramConsumer( new ForwardingConsumer(null) { @Override - public void acceptClassFile(ClassFileConsumerData data) { - checkDeprecatedAttributes(data.getByteDataView().getBuffer()); + public void accept(ByteDataView data, String descriptor, DiagnosticsHandler handler) { + checkDeprecatedAttributes(data.getBuffer()); } }); }
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/BackportDuplicationTest.java b/src/test/java/com/android/tools/r8/desugar/backports/BackportDuplicationTest.java index 9be08a2..ed2dd4e 100644 --- a/src/test/java/com/android/tools/r8/desugar/backports/BackportDuplicationTest.java +++ b/src/test/java/com/android/tools/r8/desugar/backports/BackportDuplicationTest.java
@@ -10,11 +10,11 @@ import static org.junit.Assert.fail; import static org.junit.Assume.assumeTrue; +import com.android.tools.r8.ByteDataView; import com.android.tools.r8.ClassFileConsumer; -import com.android.tools.r8.ClassFileConsumerData; import com.android.tools.r8.CompilationFailedException; import com.android.tools.r8.DexFilePerClassFileConsumer; -import com.android.tools.r8.DexFilePerClassFileConsumerData; +import com.android.tools.r8.DiagnosticsHandler; import com.android.tools.r8.OutputMode; import com.android.tools.r8.TestBase; import com.android.tools.r8.TestParameters; @@ -247,16 +247,21 @@ firstRoundOutput.isCf() ? new ClassFileConsumer.ForwardingConsumer(null) { @Override - public void acceptClassFile(ClassFileConsumerData data) { - byte[] bytes = data.getByteDataCopy(); + public void accept( + ByteDataView data, String descriptor, DiagnosticsHandler handler) { + byte[] bytes = data.copyByteData(); assert bytes != null; outputsRoundOne.add(bytes); } } : new DexFilePerClassFileConsumer.ForwardingConsumer(null) { @Override - public void acceptDexFile(DexFilePerClassFileConsumerData data) { - byte[] bytes = data.getByteDataCopy(); + public void accept( + String primaryClassDescriptor, + ByteDataView data, + Set<String> descriptors, + DiagnosticsHandler handler) { + byte[] bytes = data.copyByteData(); assert bytes != null; outputsRoundOne.add(bytes); }
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/BackportMainDexTest.java b/src/test/java/com/android/tools/r8/desugar/backports/BackportMainDexTest.java index 4a55fc2..5369238 100644 --- a/src/test/java/com/android/tools/r8/desugar/backports/BackportMainDexTest.java +++ b/src/test/java/com/android/tools/r8/desugar/backports/BackportMainDexTest.java
@@ -9,8 +9,8 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import com.android.tools.r8.ByteDataView; import com.android.tools.r8.DexIndexedConsumer; -import com.android.tools.r8.DexIndexedConsumerData; import com.android.tools.r8.DiagnosticsHandler; import com.android.tools.r8.GenerateMainDexListRunResult; import com.android.tools.r8.OutputMode; @@ -361,12 +361,13 @@ Set<String> mainDexDescriptors; @Override - public void acceptDexIndexedFile(DexIndexedConsumerData data) { - if (data.getFileIndex() == 0) { + public void accept( + int fileIndex, ByteDataView data, Set<String> descriptors, DiagnosticsHandler handler) { + if (fileIndex == 0) { assertNull(mainDexBytes); assertNull(mainDexDescriptors); - mainDexBytes = data.getByteDataCopy(); - mainDexDescriptors = data.getClassDescriptors(); + mainDexBytes = data.copyByteData(); + mainDexDescriptors = descriptors; } }
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/EmptyDesugaredLibrary.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/EmptyDesugaredLibrary.java index 2f65784..3fd5104 100644 --- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/EmptyDesugaredLibrary.java +++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/EmptyDesugaredLibrary.java
@@ -9,8 +9,9 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import com.android.tools.r8.ByteDataView; import com.android.tools.r8.DexIndexedConsumer; -import com.android.tools.r8.DexIndexedConsumerData; +import com.android.tools.r8.DiagnosticsHandler; import com.android.tools.r8.L8TestBuilder; import com.android.tools.r8.TestParameters; import com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification; @@ -21,6 +22,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.List; +import java.util.Set; import java.util.zip.ZipFile; import org.junit.Test; import org.junit.runner.RunWith; @@ -65,7 +67,8 @@ } @Override - public void acceptDexIndexedFile(DexIndexedConsumerData data) { + public void accept( + int fileIndex, ByteDataView data, Set<String> descriptors, DiagnosticsHandler handler) { count++; } }
diff --git a/src/test/java/com/android/tools/r8/dexsplitter/SplitterTestBase.java b/src/test/java/com/android/tools/r8/dexsplitter/SplitterTestBase.java index 3988efd..1d8821e 100644 --- a/src/test/java/com/android/tools/r8/dexsplitter/SplitterTestBase.java +++ b/src/test/java/com/android/tools/r8/dexsplitter/SplitterTestBase.java
@@ -3,8 +3,10 @@ import static junit.framework.TestCase.fail; import static org.junit.Assume.assumeTrue; +import com.android.tools.r8.ByteDataView; import com.android.tools.r8.CompilationFailedException; import com.android.tools.r8.DexIndexedConsumer.ArchiveConsumer; +import com.android.tools.r8.DiagnosticsHandler; import com.android.tools.r8.FeatureSplit; import com.android.tools.r8.R8FullTestBuilder; import com.android.tools.r8.R8TestCompileResult; @@ -90,7 +92,17 @@ builder .addProgramResourceProvider(ArchiveResourceProvider.fromArchive(featureJar, true)) - .setProgramConsumer(new ArchiveConsumer(outputPath, true)); + .setProgramConsumer( + new ArchiveConsumer(outputPath, true) { + @Override + public void accept( + int fileIndex, + ByteDataView data, + Set<String> descriptors, + DiagnosticsHandler handler) { + super.accept(fileIndex, data, descriptors, handler); + } + }); } public static FeatureSplit splitWithNonJavaFile(
diff --git a/src/test/java/com/android/tools/r8/kotlin/reflection/ReflectiveConstructionWithInlineClassTest.java b/src/test/java/com/android/tools/r8/kotlin/reflection/ReflectiveConstructionWithInlineClassTest.java index 32568f9..a3e00b4 100644 --- a/src/test/java/com/android/tools/r8/kotlin/reflection/ReflectiveConstructionWithInlineClassTest.java +++ b/src/test/java/com/android/tools/r8/kotlin/reflection/ReflectiveConstructionWithInlineClassTest.java
@@ -10,6 +10,7 @@ import com.android.tools.r8.KotlinTestParameters; import com.android.tools.r8.R8FullTestBuilder; import com.android.tools.r8.TestParameters; +import com.android.tools.r8.TestShrinkerBuilder; import com.android.tools.r8.ToolHelper; import com.android.tools.r8.kotlin.metadata.KotlinMetadataTestBase; import com.android.tools.r8.shaking.ProguardKeepAttributes; @@ -96,6 +97,10 @@ .addProgramFiles(kotlinc.getKotlinReflectJar()) .addProgramFiles(kotlinc.getKotlinAnnotationJar()) .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.LATEST)) + .applyIf( + parameters.isCfRuntime() + && kotlinParameters.isNewerThan(KotlinCompilerVersion.KOTLINC_1_8_0), + TestShrinkerBuilder::addDontWarnJavaLangInvokeLambdaMetadataFactory) .setMinApi(parameters) .addKeepMainRule(MAIN_CLASS) .addKeepClassAndMembersRules(PKG + ".Data") @@ -119,11 +124,7 @@ .assertNoErrorMessages() .apply(KotlinMetadataTestBase::verifyExpectedWarningsFromKotlinReflectAndStdLib) .run(parameters.getRuntime(), MAIN_CLASS) - // TODO(b/269792580): Figure out why this is throwing an abstract method error. - .assertFailureWithErrorThatThrows( - kotlinParameters.isKotlinDev() && parameters.isCfRuntime() - ? AbstractMethodError.class - : IllegalArgumentException.class); + .assertFailureWithErrorThatThrows(IllegalArgumentException.class); } @Test @@ -134,9 +135,6 @@ .assertNoErrorMessages() .apply(KotlinMetadataTestBase::verifyExpectedWarningsFromKotlinReflectAndStdLib) .run(parameters.getRuntime(), MAIN_CLASS) - // TODO(b/269792580): Figure out why this is throwing an abstract method error. - .assertFailureWithErrorThatThrowsIf( - kotlinParameters.isKotlinDev() && parameters.isCfRuntime(), AbstractMethodError.class) - .assertSuccessWithOutputLinesIf(!kotlinParameters.isKotlinDev(), EXPECTED_OUTPUT); + .assertSuccessWithOutputLines(EXPECTED_OUTPUT); } }
diff --git a/src/test/java/com/android/tools/r8/lightir/LirBasicCallbackTest.java b/src/test/java/com/android/tools/r8/lightir/LirBasicCallbackTest.java index 062470c..abd980d 100644 --- a/src/test/java/com/android/tools/r8/lightir/LirBasicCallbackTest.java +++ b/src/test/java/com/android/tools/r8/lightir/LirBasicCallbackTest.java
@@ -37,6 +37,11 @@ private static class ThrowingStrategy extends LirEncodingStrategy<Value, Integer> { @Override + public boolean isPhiInlineInstruction() { + return false; + } + + @Override public void defineBlock(BasicBlock block, int index) { throw new Unreachable(); } @@ -62,7 +67,7 @@ } @Override - public LirSsaValueStrategy<Integer> getSsaValueStrategy() { + public LirStrategyInfo<Integer> getStrategyInfo() { return null; } }
diff --git a/src/test/java/com/android/tools/r8/naming/retraceproguard/CatchAllRangeWithNoLineNumberTest.java b/src/test/java/com/android/tools/r8/naming/retraceproguard/CatchAllRangeWithNoLineNumberTest.java index 4372134..aac289a 100644 --- a/src/test/java/com/android/tools/r8/naming/retraceproguard/CatchAllRangeWithNoLineNumberTest.java +++ b/src/test/java/com/android/tools/r8/naming/retraceproguard/CatchAllRangeWithNoLineNumberTest.java
@@ -26,7 +26,6 @@ @RunWith(Parameterized.class) public class CatchAllRangeWithNoLineNumberTest extends TestBase { - private final TestParameters parameters; private final ProguardVersion proguardVersion; @Parameters(name = "{0}, {1}") @@ -36,8 +35,8 @@ public CatchAllRangeWithNoLineNumberTest( TestParameters parameters, ProguardVersion proguardVersion) { - this.parameters = parameters; this.proguardVersion = proguardVersion; + parameters.assertNoneRuntime(); } private final String[] stackTrace = @@ -85,7 +84,7 @@ private final String retracedR8 = StringUtils.lines( "\tat foo.bar.Baz.foo(Baz.java:33)", - "\tat foo.bar.Qux.foo(Qux.java:33)", + "\tat foo.bar.Qux.foo(Qux.java)", "\tat foo.bar.Quux.foo(Quux.java:33)", "\tat foo.bar.Baz.foo(Baz.java:33)", "\tat foo.bar.Baz.foo(Baz.java:33)");
diff --git a/src/test/java/com/android/tools/r8/regress/Regress37740372.java b/src/test/java/com/android/tools/r8/regress/Regress37740372.java index b46866c..8047716 100644 --- a/src/test/java/com/android/tools/r8/regress/Regress37740372.java +++ b/src/test/java/com/android/tools/r8/regress/Regress37740372.java
@@ -8,11 +8,12 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import com.android.tools.r8.ByteDataView; import com.android.tools.r8.D8; import com.android.tools.r8.D8Command; import com.android.tools.r8.D8Command.Builder; import com.android.tools.r8.DexIndexedConsumer; -import com.android.tools.r8.DexIndexedConsumerData; +import com.android.tools.r8.DiagnosticsHandler; import com.android.tools.r8.origin.EmbeddedOrigin; import com.android.tools.r8.origin.Origin; import com.android.tools.r8.smali.SmaliTestBase; @@ -21,6 +22,7 @@ import com.android.tools.r8.utils.codeinspector.ClassSubject; import com.android.tools.r8.utils.codeinspector.CodeInspector; import java.util.Base64; +import java.util.Set; import org.junit.Test; public class Regress37740372 extends SmaliTestBase { @@ -140,9 +142,10 @@ } @Override - public void acceptDexIndexedFile(DexIndexedConsumerData data) { - assertEquals(0, data.getFileIndex()); - this.data = data.getByteDataCopy(); + public void accept( + int fileIndex, ByteDataView data, Set<String> descriptors, DiagnosticsHandler handler) { + assertEquals(0, fileIndex); + this.data = data.copyByteData(); } }
diff --git a/src/test/java/com/android/tools/r8/retrace/RetraceTests.java b/src/test/java/com/android/tools/r8/retrace/RetraceTests.java index 36a00f1..c8ce59b 100644 --- a/src/test/java/com/android/tools/r8/retrace/RetraceTests.java +++ b/src/test/java/com/android/tools/r8/retrace/RetraceTests.java
@@ -43,7 +43,6 @@ import com.android.tools.r8.retrace.stacktraces.InlineNoLineNumberStackTrace; import com.android.tools.r8.retrace.stacktraces.InlineNoLineWithBaseEntryNumberAssumeNoInlineStackTrace; import com.android.tools.r8.retrace.stacktraces.InlinePreambleNoOriginalStackTrace; -import com.android.tools.r8.retrace.stacktraces.InlinePreambleWithOriginalStackTrace; import com.android.tools.r8.retrace.stacktraces.InlineSourceFileContextStackTrace; import com.android.tools.r8.retrace.stacktraces.InlineSourceFileStackTrace; import com.android.tools.r8.retrace.stacktraces.InlineWithLineNumbersStackTrace; @@ -248,11 +247,6 @@ } @Test - public void testInlinePreambleWithOriginalStackTrace() throws Exception { - runRetraceTest(new InlinePreambleWithOriginalStackTrace()); - } - - @Test public void testInlinePreambleNoOriginalStackTrace() throws Exception { runRetraceTest(new InlinePreambleNoOriginalStackTrace()); }
diff --git a/src/test/java/com/android/tools/r8/retrace/StackTraceRegularExpressionParserTests.java b/src/test/java/com/android/tools/r8/retrace/StackTraceRegularExpressionParserTests.java index 80d580b..480f8bf 100644 --- a/src/test/java/com/android/tools/r8/retrace/StackTraceRegularExpressionParserTests.java +++ b/src/test/java/com/android/tools/r8/retrace/StackTraceRegularExpressionParserTests.java
@@ -485,12 +485,12 @@ @Override public List<String> retracedStackTrace() { - return ImmutableList.of("com.android.tools.r8.R8.foo(7)"); + return ImmutableList.of("com.android.tools.r8.R8.foo()"); } @Override public List<String> retraceVerboseStackTrace() { - return ImmutableList.of("com.android.tools.r8.R8.boolean foo()(7)"); + return ImmutableList.of("com.android.tools.r8.R8.boolean foo()()"); } @Override
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousWithMultipleLineMappingsStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousWithMultipleLineMappingsStackTrace.java index 51a9249..1041ace 100644 --- a/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousWithMultipleLineMappingsStackTrace.java +++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousWithMultipleLineMappingsStackTrace.java
@@ -40,9 +40,7 @@ return Arrays.asList( "java.lang.IndexOutOfBoundsException", "\tat java.util.ArrayList.get(ArrayList.java:411)", - "\tat com.android.tools.r8.Internal.void foo(int)(Internal.java:10)", - "\t<OR> at com.android.tools.r8.Internal.void foo(int)(Internal.java:11)", - "\t<OR> at com.android.tools.r8.Internal.void foo(int)(Internal.java:12)"); + "\tat com.android.tools.r8.Internal.void foo(int)(Internal.java)"); } @Override
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousWithSignatureStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousWithSignatureStackTrace.java index c9ed69c..1f0cd0c 100644 --- a/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousWithSignatureStackTrace.java +++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/AmbiguousWithSignatureStackTrace.java
@@ -41,10 +41,10 @@ return Arrays.asList( "java.lang.IndexOutOfBoundsException", "\tat java.util.ArrayList.get(ArrayList.java:411)", - "\tat com.android.tools.r8.Internal.boolean foo(int,int)(Internal.java:13)", - "\t<OR> at com.android.tools.r8.Internal.void foo(int)(Internal.java:10)", - "\t<OR> at com.android.tools.r8.Internal.void foo(int,boolean)(Internal.java:12)", - "\t<OR> at com.android.tools.r8.Internal.void foo(int,int)(Internal.java:11)"); + "\tat com.android.tools.r8.Internal.boolean foo(int,int)(Internal.java)", + "\t<OR> at com.android.tools.r8.Internal.void foo(int)(Internal.java)", + "\t<OR> at com.android.tools.r8.Internal.void foo(int,boolean)(Internal.java)", + "\t<OR> at com.android.tools.r8.Internal.void foo(int,int)(Internal.java)"); } @Override
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/InlineNoLineAssumeNoInlineAmbiguousStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/InlineNoLineAssumeNoInlineAmbiguousStackTrace.java index 515d6b0..7c63a27 100644 --- a/src/test/java/com/android/tools/r8/retrace/stacktraces/InlineNoLineAssumeNoInlineAmbiguousStackTrace.java +++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/InlineNoLineAssumeNoInlineAmbiguousStackTrace.java
@@ -21,20 +21,14 @@ public List<String> retracedStackTrace() { return Arrays.asList( "Exception in thread \"main\" java.lang.NullPointerException", - // TODO(b/231622686): Should not emit inline frame. - "\tat retrace.Main.method1(Main.java)", - "\tat retrace.Main.main(Main.java)", - "\t<OR> at retrace.Main.otherMain(Main.java)"); + "\tat retrace.Main.otherMain(Main.java)"); } @Override public List<String> retraceVerboseStackTrace() { return Arrays.asList( "Exception in thread \"main\" java.lang.NullPointerException", - // TODO(b/231622686): Should not emit inline frame. - "\tat retrace.Main.void method1(java.lang.String)(Main.java:0)", - "\tat retrace.Main.void main(java.lang.String[])(Main.java:0)", - "\t<OR> at retrace.Main.void otherMain(java.lang.String[])(Main.java)"); + "\tat retrace.Main.void otherMain(java.lang.String[])(Main.java)"); } @Override
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/InlineNoLineNumberAssumeNoInlineStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/InlineNoLineNumberAssumeNoInlineStackTrace.java index ffc5da2..9382f6e 100644 --- a/src/test/java/com/android/tools/r8/retrace/stacktraces/InlineNoLineNumberAssumeNoInlineStackTrace.java +++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/InlineNoLineNumberAssumeNoInlineStackTrace.java
@@ -19,12 +19,8 @@ @Override public List<String> retracedStackTrace() { - // TODO(b/231622686): Should assume that no lines means no inline frames. return Arrays.asList( "Exception in thread \"main\" java.lang.NullPointerException", - "\tat retrace.Main.method1(Main.java)", - "\tat retrace.Main.main(Main.java)", - "\t<OR> at retrace.Main.method2(Main.java)", "\tat retrace.Main.main(Main.java)"); } @@ -33,10 +29,7 @@ // TODO(b/231622686): Should assume that no lines means no inline frames. return Arrays.asList( "Exception in thread \"main\" java.lang.NullPointerException", - "\tat retrace.Main.void method1(java.lang.String)(Main.java:0)", - "\tat retrace.Main.void main(java.lang.String[])(Main.java:0)", - "\t<OR> at retrace.Main.void method2(int)(Main.java:0)", - "\tat retrace.Main.void main(java.lang.String[])(Main.java:0)"); + "\tat retrace.Main.void main(java.lang.String[])(Main.java)"); } @Override
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/InlineNoLineWithBaseEntryNumberAssumeNoInlineStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/InlineNoLineWithBaseEntryNumberAssumeNoInlineStackTrace.java index 3e52ebd..3e6de74 100644 --- a/src/test/java/com/android/tools/r8/retrace/stacktraces/InlineNoLineWithBaseEntryNumberAssumeNoInlineStackTrace.java +++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/InlineNoLineWithBaseEntryNumberAssumeNoInlineStackTrace.java
@@ -19,22 +19,16 @@ @Override public List<String> retracedStackTrace() { - // TODO(b/231622686): Should assume that no lines means no inline frames. return Arrays.asList( "Exception in thread \"main\" java.lang.NullPointerException", - "\tat retrace.Main.main(Main.java)", - "\t<OR> at retrace.Main.method1(Main.java)", "\tat retrace.Main.main(Main.java)"); } @Override public List<String> retraceVerboseStackTrace() { - // TODO(b/231622686): Should assume that no lines means no inline frames. return Arrays.asList( "Exception in thread \"main\" java.lang.NullPointerException", - "\tat retrace.Main.void main(java.lang.String[])(Main.java)", - "\t<OR> at retrace.Main.void method1(java.lang.String)(Main.java:0)", - "\tat retrace.Main.void main(java.lang.String[])(Main.java:0)"); + "\tat retrace.Main.void main(java.lang.String[])(Main.java)"); } @Override
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/InlinePreambleNoOriginalStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/InlinePreambleNoOriginalStackTrace.java index 47732b8..79a9172 100644 --- a/src/test/java/com/android/tools/r8/retrace/stacktraces/InlinePreambleNoOriginalStackTrace.java +++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/InlinePreambleNoOriginalStackTrace.java
@@ -20,21 +20,15 @@ @Override public List<String> retracedStackTrace() { return Arrays.asList( - // TODO(b/231622686): Should only include preamble "Exception in thread \"main\" java.lang.NullPointerException", - "\tat retrace.Main.main(Main.java)", - "\t<OR> at retrace.Main.method1(Main.java)", "\tat retrace.Main.main(Main.java)"); } @Override public List<String> retraceVerboseStackTrace() { return Arrays.asList( - // TODO(b/231622686): Should only include preamble "Exception in thread \"main\" java.lang.NullPointerException", - "\tat retrace.Main.void main(java.lang.String[])(Main.java)", - "\t<OR> at retrace.Main.void method1(java.lang.String)(Main.java:0)", - "\tat retrace.Main.void main(java.lang.String[])(Main.java:0)"); + "\tat retrace.Main.void main(java.lang.String[])(Main.java)"); } @Override
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/InlinePreambleWithOriginalStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/InlinePreambleWithOriginalStackTrace.java deleted file mode 100644 index 72c2076..0000000 --- a/src/test/java/com/android/tools/r8/retrace/stacktraces/InlinePreambleWithOriginalStackTrace.java +++ /dev/null
@@ -1,53 +0,0 @@ -// Copyright (c) 2022, 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.retrace.stacktraces; - -import com.android.tools.r8.utils.StringUtils; -import java.util.Arrays; -import java.util.List; - -public class InlinePreambleWithOriginalStackTrace implements StackTraceForTest { - - @Override - public List<String> obfuscatedStackTrace() { - return Arrays.asList( - "Exception in thread \"main\" java.lang.NullPointerException", - "\tat a.foo(Unknown Source)"); - } - - @Override - public List<String> retracedStackTrace() { - return Arrays.asList( - // TODO(b/231622686): Should only include preamble - "Exception in thread \"main\" java.lang.NullPointerException", - "\tat retrace.Main.main(Main.java)", - "\t<OR> at retrace.Main.method1(Main.java)", - "\tat retrace.Main.main(Main.java)"); - } - - @Override - public List<String> retraceVerboseStackTrace() { - return Arrays.asList( - // TODO(b/231622686): Should only include preamble - "Exception in thread \"main\" java.lang.NullPointerException", - "\tat retrace.Main.void main(java.lang.String[])(Main.java:0)", - "\t<OR> at retrace.Main.void method1(java.lang.String)(Main.java:0)", - "\tat retrace.Main.void main(java.lang.String[])(Main.java:0)"); - } - - @Override - public String mapping() { - return StringUtils.lines( - "retrace.Main -> a:", - " 0:1:void main(java.lang.String[]):0:0 -> foo", - " 2:2:void method1(java.lang.String):0:0 -> foo", - " 2:2:void main(java.lang.String[]):0 -> foo"); - } - - @Override - public int expectedWarnings() { - return 0; - } -}
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/MultipleLinesNoLineNumberStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/MultipleLinesNoLineNumberStackTrace.java index b1a31db..3f5746d 100644 --- a/src/test/java/com/android/tools/r8/retrace/stacktraces/MultipleLinesNoLineNumberStackTrace.java +++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/MultipleLinesNoLineNumberStackTrace.java
@@ -30,9 +30,8 @@ public List<String> retracedStackTrace() { return Arrays.asList( "Exception in thread \"main\" java.lang.NullPointerException", - "\tat com.android.tools.r8.naming.retrace.Main.main(Main.java)", - "\t<OR> at com.android.tools.r8.naming.retrace.Main.method1(Main.java)", - "\tat com.android.tools.r8.naming.retrace.Main.main(Main.java)"); + "\tat com.android.tools.r8.naming.retrace.Main.method1(Main.java:42)", + "\tat com.android.tools.r8.naming.retrace.Main.main(Main.java:28)"); } @Override @@ -40,8 +39,6 @@ return Arrays.asList( "Exception in thread \"main\" java.lang.NullPointerException", "\tat com.android.tools.r8.naming.retrace.Main.void" - + " main(java.lang.String[])(Main.java:153)", - "\t<OR> at com.android.tools.r8.naming.retrace.Main.void" + " method1(java.lang.String)(Main.java:42)", "\tat com.android.tools.r8.naming.retrace.Main.void" + " main(java.lang.String[])(Main.java:28)");
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/OutsideLineRangeStackTraceTest.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/OutsideLineRangeStackTraceTest.java index ea9ada4..2ebf79a 100644 --- a/src/test/java/com/android/tools/r8/retrace/stacktraces/OutsideLineRangeStackTraceTest.java +++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/OutsideLineRangeStackTraceTest.java
@@ -47,8 +47,7 @@ "\tat some.other.Class.void method1()(Class.java:42)", "\tat some.other.Class.void method1()(Class.java:42)", "\tat some.Class.a(Class.java:27)", - "\tat some.Class.void method2()(Class.java)", - "\t<OR> at some.Class.void method2()(Class.java:10)"); + "\tat some.Class.void method2()(Class.java)"); } @Override
diff --git a/src/test/java/com/android/tools/r8/retrace/stacktraces/PreambleLineNumberStackTrace.java b/src/test/java/com/android/tools/r8/retrace/stacktraces/PreambleLineNumberStackTrace.java index 316fdfc..98a6ed6 100644 --- a/src/test/java/com/android/tools/r8/retrace/stacktraces/PreambleLineNumberStackTrace.java +++ b/src/test/java/com/android/tools/r8/retrace/stacktraces/PreambleLineNumberStackTrace.java
@@ -33,8 +33,7 @@ return Arrays.asList( "Exception in thread \"main\" java.lang.NullPointerException", " at kotlin.ResultKt.createFailure(Result.kt)", - // TODO(b/270593835): We should report kotlin.ResultKt.createFailure(Result.kt). - " at kotlin.ResultKt.a(Result.kt:0)", + " at kotlin.ResultKt.createFailure(Result.kt:0)", " at kotlin.ResultKt.createFailure(Result.kt:122)", " at kotlin.ResultKt.createFailure(Result.kt:124)"); } @@ -43,11 +42,8 @@ public List<String> retraceVerboseStackTrace() { return Arrays.asList( "Exception in thread \"main\" java.lang.NullPointerException", - // TODO(b/270593835): We should not have an ambiguous frame reporting here. - " at kotlin.ResultKt.void createFailure(java.lang.Throwable)(Result.kt:122)", - " <OR> at kotlin.ResultKt.void createFailure(java.lang.Throwable)(Result.kt:124)", - // TODO(b/270593835): We should report kotlin.ResultKt.createFailure(Result.kt). - " at kotlin.ResultKt.a(Result.kt:0)", + " at kotlin.ResultKt.void createFailure(java.lang.Throwable)(Result.kt)", + " at kotlin.ResultKt.void createFailure(java.lang.Throwable)(Result.kt:0)", " at kotlin.ResultKt.void createFailure(java.lang.Throwable)(Result.kt:122)", " at kotlin.ResultKt.void createFailure(java.lang.Throwable)(Result.kt:124)"); }
diff --git a/src/test/java/com/android/tools/r8/synthesis/RepeatedCompilationNestedSyntheticsTest.java b/src/test/java/com/android/tools/r8/synthesis/RepeatedCompilationNestedSyntheticsTest.java index e273552..b18935b 100644 --- a/src/test/java/com/android/tools/r8/synthesis/RepeatedCompilationNestedSyntheticsTest.java +++ b/src/test/java/com/android/tools/r8/synthesis/RepeatedCompilationNestedSyntheticsTest.java
@@ -10,11 +10,10 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import com.android.tools.r8.ByteDataView; import com.android.tools.r8.ClassFileConsumer; -import com.android.tools.r8.ClassFileConsumerData; import com.android.tools.r8.DesugarGraphConsumer; import com.android.tools.r8.DexFilePerClassFileConsumer; -import com.android.tools.r8.DexFilePerClassFileConsumerData; import com.android.tools.r8.DiagnosticsHandler; import com.android.tools.r8.TestBase; import com.android.tools.r8.TestParameters; @@ -70,8 +69,8 @@ .setProgramConsumer( new ClassFileConsumer() { @Override - public void acceptClassFile(ClassFileConsumerData data) { - firstCompilation.put(data.getClassDescriptor(), data.getByteDataCopy()); + public void accept(ByteDataView data, String descriptor, DiagnosticsHandler handler) { + firstCompilation.put(descriptor, data.copyByteData()); } @Override @@ -122,9 +121,10 @@ b.setProgramConsumer( new ClassFileConsumer() { @Override - public void acceptClassFile(ClassFileConsumerData data) { - secondCompilation.put(data.getClassDescriptor(), data.getByteDataCopy()); - allDescriptors.add(data.getClassDescriptor()); + public void accept( + ByteDataView data, String descriptor, DiagnosticsHandler handler) { + secondCompilation.put(descriptor, data.copyByteData()); + allDescriptors.add(descriptor); } @Override @@ -133,12 +133,15 @@ b -> b.setProgramConsumer( new DexFilePerClassFileConsumer() { + @Override - public synchronized void acceptDexFile( - DexFilePerClassFileConsumerData data) { - secondCompilation.put( - data.getPrimaryClassDescriptor(), data.getByteDataCopy()); - allDescriptors.addAll(data.getClassDescriptors()); + public void accept( + String primaryClassDescriptor, + ByteDataView data, + Set<String> descriptors, + DiagnosticsHandler handler) { + secondCompilation.put(primaryClassDescriptor, data.copyByteData()); + allDescriptors.addAll(descriptors); } @Override
diff --git a/src/test/java/com/android/tools/r8/synthesis/RepeatedCompilationSyntheticsTest.java b/src/test/java/com/android/tools/r8/synthesis/RepeatedCompilationSyntheticsTest.java index 842c56e..e7e5c3c 100644 --- a/src/test/java/com/android/tools/r8/synthesis/RepeatedCompilationSyntheticsTest.java +++ b/src/test/java/com/android/tools/r8/synthesis/RepeatedCompilationSyntheticsTest.java
@@ -10,7 +10,6 @@ import com.android.tools.r8.ByteDataView; import com.android.tools.r8.ClassFileConsumer; import com.android.tools.r8.DexFilePerClassFileConsumer; -import com.android.tools.r8.DexFilePerClassFileConsumerData; import com.android.tools.r8.DiagnosticsHandler; import com.android.tools.r8.TestBase; import com.android.tools.r8.TestParameters; @@ -23,6 +22,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -113,9 +113,12 @@ b.setProgramConsumer( new DexFilePerClassFileConsumer() { @Override - public synchronized void acceptDexFile( - DexFilePerClassFileConsumerData data) { - secondCompilation.addAll(data.getClassDescriptors()); + public void accept( + String primaryClassDescriptor, + ByteDataView data, + Set<String> descriptors, + DiagnosticsHandler handler) { + secondCompilation.addAll(descriptors); } @Override
diff --git a/src/test/java/com/android/tools/r8/utils/Smali.java b/src/test/java/com/android/tools/r8/utils/Smali.java index 4190da5..4321812 100644 --- a/src/test/java/com/android/tools/r8/utils/Smali.java +++ b/src/test/java/com/android/tools/r8/utils/Smali.java
@@ -3,8 +3,8 @@ // BSD-style license that can be found in the LICENSE file. package com.android.tools.r8.utils; +import com.android.tools.r8.ByteDataView; import com.android.tools.r8.DexIndexedConsumer; -import com.android.tools.r8.DexIndexedConsumerData; import com.android.tools.r8.DiagnosticsHandler; import com.android.tools.r8.dex.ApplicationReader; import com.android.tools.r8.dex.ApplicationWriter; @@ -19,6 +19,7 @@ import java.io.StringReader; import java.util.Arrays; import java.util.List; +import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import org.antlr.runtime.CommonTokenStream; @@ -128,8 +129,9 @@ byte[] contents; @Override - public void acceptDexIndexedFile(DexIndexedConsumerData data) { - contents = data.getByteDataCopy(); + public void accept( + int fileIndex, ByteDataView data, Set<String> descriptors, DiagnosticsHandler handler) { + contents = data.copyByteData(); } @Override
diff --git a/src/test/java/com/android/tools/r8/utils/StringUtilsTest.java b/src/test/java/com/android/tools/r8/utils/StringUtilsTest.java index acadcc6..2237b07 100644 --- a/src/test/java/com/android/tools/r8/utils/StringUtilsTest.java +++ b/src/test/java/com/android/tools/r8/utils/StringUtilsTest.java
@@ -3,7 +3,9 @@ // BSD-style license that can be found in the LICENSE file. package com.android.tools.r8.utils; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import com.android.tools.r8.TestBase; @@ -47,6 +49,18 @@ assertListEquals(ImmutableList.of("\ra\r\rb\r"), StringUtils.splitLines("\ra\r\rb\r")); } + @Test + public void testSplit() { + assertListEquals(ImmutableList.of(" "), StringUtils.split(" ", '.')); + assertListEquals(ImmutableList.of("", ""), StringUtils.split(".", '.')); + assertListEquals(ImmutableList.of("", "", "", ""), StringUtils.split("...", '.')); + assertListEquals(ImmutableList.of("a", "b", "c", "d"), StringUtils.split("a.b.c.d", '.')); + + assertArrayEquals(new String[] {"a", "b", "c"}, StringUtils.splitKnownSize("a.b.c", '.', 3)); + assertNull(StringUtils.splitKnownSize("a.b.c", '.', 2)); + assertNull(StringUtils.splitKnownSize("a.b.c", '.', 4)); + } + private void assertListEquals(List<String> xs, List<String> ys) { assertEquals( StringUtils.join(", ", xs, s -> '"' + StringUtils.toASCIIString(s) + '"', BraceType.SQUARE),
diff --git a/third_party/binary_compatibility_tests/compiler_api_tests.tar.gz.sha1 b/third_party/binary_compatibility_tests/compiler_api_tests.tar.gz.sha1 index e2f9b98..8a2887d 100644 --- a/third_party/binary_compatibility_tests/compiler_api_tests.tar.gz.sha1 +++ b/third_party/binary_compatibility_tests/compiler_api_tests.tar.gz.sha1
@@ -1 +1 @@ -0f355ce5bfc00d39fc533575bb119053b0d8cfc4 \ No newline at end of file +42f88c3f809026d506e15c14804dd584bc0b9474 \ No newline at end of file