diff options
author | Ian Zerny <zerny@google.com> | 2021-03-18 09:13:05 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2021-03-18 09:13:05 +0000 |
commit | 9b0e8ba143aa6d1cc2ff04ade59156a2a2b2f0b3 (patch) | |
tree | a514fba63a38dad79ec63f81f58c6edba4fcfe54 | |
parent | 22e2b2c473aff864309be995b715608dd83c0034 (diff) | |
parent | c4e4ae59b83f3d913c34c55e90000a4756cfe65f (diff) | |
download | r8-9b0e8ba143aa6d1cc2ff04ade59156a2a2b2f0b3.tar.gz |
Add mapping information for compiler synthesized classes. am: c4e4ae59b8
Original change: undetermined
Change-Id: I4afea1da07795abcf753dfe63b39d5f629174ebd
8 files changed, 169 insertions, 17 deletions
diff --git a/src/main/java/com/android/tools/r8/naming/MemberNaming.java b/src/main/java/com/android/tools/r8/naming/MemberNaming.java index 51c3272ef..4a50244a2 100644 --- a/src/main/java/com/android/tools/r8/naming/MemberNaming.java +++ b/src/main/java/com/android/tools/r8/naming/MemberNaming.java @@ -172,7 +172,7 @@ public class MemberNaming { public static final NoSignature NO_SIGNATURE = new NoSignature(); - public NoSignature() { + private NoSignature() { super("NO SIGNATURE"); } diff --git a/src/main/java/com/android/tools/r8/naming/mappinginformation/CompilerSynthesizedMappingInformation.java b/src/main/java/com/android/tools/r8/naming/mappinginformation/CompilerSynthesizedMappingInformation.java new file mode 100644 index 000000000..b0a13baee --- /dev/null +++ b/src/main/java/com/android/tools/r8/naming/mappinginformation/CompilerSynthesizedMappingInformation.java @@ -0,0 +1,45 @@ +// Copyright (c) 2020, 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.naming.mappinginformation; + +import com.android.tools.r8.DiagnosticsHandler; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; + +public class CompilerSynthesizedMappingInformation extends MappingInformation { + + public static final String ID = "com.android.tools.r8.synthesized"; + + public CompilerSynthesizedMappingInformation() { + super(NO_LINE_NUMBER); + } + + @Override + public boolean isCompilerSynthesizedMappingInformation() { + return true; + } + + @Override + public CompilerSynthesizedMappingInformation asCompilerSynthesizedMappingInformation() { + return this; + } + + @Override + public boolean allowOther(MappingInformation information) { + return !information.isCompilerSynthesizedMappingInformation(); + } + + @Override + public String serialize() { + JsonObject result = new JsonObject(); + result.add(MAPPING_ID_KEY, new JsonPrimitive(ID)); + return result.toString(); + } + + public static CompilerSynthesizedMappingInformation deserialize( + JsonObject object, DiagnosticsHandler diagnosticsHandler, int lineNumber) { + return new CompilerSynthesizedMappingInformation(); + } +} diff --git a/src/main/java/com/android/tools/r8/naming/mappinginformation/MappingInformation.java b/src/main/java/com/android/tools/r8/naming/mappinginformation/MappingInformation.java index c1c5105db..cb0708fdc 100644 --- a/src/main/java/com/android/tools/r8/naming/mappinginformation/MappingInformation.java +++ b/src/main/java/com/android/tools/r8/naming/mappinginformation/MappingInformation.java @@ -50,6 +50,14 @@ public abstract class MappingInformation { return null; } + public boolean isCompilerSynthesizedMappingInformation() { + return false; + } + + public CompilerSynthesizedMappingInformation asCompilerSynthesizedMappingInformation() { + return null; + } + public abstract boolean allowOther(MappingInformation information); public static MappingInformation fromJsonObject( @@ -75,6 +83,9 @@ public abstract class MappingInformation { return MethodSignatureChangedInformation.build(object, diagnosticsHandler, lineNumber); case FileNameInformation.ID: return FileNameInformation.build(object, diagnosticsHandler, lineNumber); + case CompilerSynthesizedMappingInformation.ID: + return CompilerSynthesizedMappingInformation.deserialize( + object, diagnosticsHandler, lineNumber); default: diagnosticsHandler.info(MappingInformationDiagnostics.noHandlerFor(lineNumber, idString)); return null; diff --git a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java index 47ccd9159..f8ad5bbba 100644 --- a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java +++ b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java @@ -47,6 +47,7 @@ import com.android.tools.r8.naming.MemberNaming.FieldSignature; import com.android.tools.r8.naming.MemberNaming.MethodSignature; import com.android.tools.r8.naming.NamingLens; import com.android.tools.r8.naming.Range; +import com.android.tools.r8.naming.mappinginformation.CompilerSynthesizedMappingInformation; import com.android.tools.r8.naming.mappinginformation.FileNameInformation; import com.android.tools.r8.retrace.internal.RetraceUtils; import com.android.tools.r8.shaking.KeepInfoCollection; @@ -274,6 +275,8 @@ public class LineNumberOptimizer { ClassNameMapper.Builder classNameMapperBuilder = ClassNameMapper.builder(); // Collect which files contain which classes that need to have their line numbers optimized. for (DexProgramClass clazz : application.classes()) { + boolean isSyntheticClass = appView.getSyntheticItems().isSyntheticClass(clazz); + IdentityHashMap<DexString, List<DexEncodedMethod>> methodsByRenamedName = groupMethodsByRenamedName(appView.graphLens(), namingLens, clazz); @@ -299,6 +302,12 @@ public class LineNumberOptimizer { } } + if (isSyntheticClass) { + onDemandClassNamingBuilder + .get() + .addMappingInformation(new CompilerSynthesizedMappingInformation()); + } + // If the class is renamed add it to the classNamingBuilder. addClassToClassNaming(originalType, renamedClassName, onDemandClassNamingBuilder); diff --git a/src/test/java/com/android/tools/r8/retrace/RetraceLambdaTest.java b/src/test/java/com/android/tools/r8/retrace/RetraceLambdaTest.java index aa543c88f..41d1c3f02 100644 --- a/src/test/java/com/android/tools/r8/retrace/RetraceLambdaTest.java +++ b/src/test/java/com/android/tools/r8/retrace/RetraceLambdaTest.java @@ -5,15 +5,23 @@ package com.android.tools.r8.retrace; import static com.android.tools.r8.naming.retrace.StackTrace.isSameExceptForFileNameAndLineNumber; +import static com.android.tools.r8.references.Reference.classFromClass; +import static com.android.tools.r8.utils.codeinspector.Matchers.isCompilerSynthesized; import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; +import static org.junit.Assume.assumeTrue; import com.android.tools.r8.TestBase; import com.android.tools.r8.TestParameters; import com.android.tools.r8.TestParametersCollection; import com.android.tools.r8.naming.retrace.StackTrace; +import com.android.tools.r8.references.ClassReference; import com.android.tools.r8.synthesis.SyntheticItemsTestUtils; +import com.android.tools.r8.utils.codeinspector.FoundClassSubject; +import com.google.common.collect.ImmutableList; +import java.util.Collection; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -48,22 +56,48 @@ public class RetraceLambdaTest extends TestBase { .run(parameters.getRuntime(), Main.class) .assertFailureWithErrorThatMatches(containsString("Hello World!")) .inspectStackTrace( - stackTrace -> { - assertThat( - stackTrace, - isSameExceptForFileNameAndLineNumber( - StackTrace.builder() - .addWithoutFileNameAndLineNumber(Main.class, JAVAC_LAMBDA_METHOD) - // TODO(b/172014416): Support a D8 mapping and prune the synthetic. - .applyIf( - parameters.isDexRuntime(), - b -> - b.addWithoutFileNameAndLineNumber( - SyntheticItemsTestUtils.syntheticLambdaClass(Main.class, 0), - "run")) - .addWithoutFileNameAndLineNumber(Main.class, "runIt") - .addWithoutFileNameAndLineNumber(Main.class, "main") - .build())); + stackTrace -> + assertThat( + stackTrace, + isSameExceptForFileNameAndLineNumber( + StackTrace.builder() + .addWithoutFileNameAndLineNumber(Main.class, JAVAC_LAMBDA_METHOD) + // TODO(b/172014416): Support a D8 mapping and prune the synthetic. + .applyIf( + parameters.isDexRuntime(), + b -> + b.addWithoutFileNameAndLineNumber( + SyntheticItemsTestUtils.syntheticLambdaClass(Main.class, 0), + "run")) + .addWithoutFileNameAndLineNumber(Main.class, "runIt") + .addWithoutFileNameAndLineNumber(Main.class, "main") + .build()))); + } + + @Test + public void testMappingInformation() throws Exception { + assumeTrue("R8/CF does not desugar", parameters.isDexRuntime()); + testForR8(parameters.getBackend()) + .addInnerClasses(getClass()) + .addKeepAttributeSourceFile() + .addKeepAttributeLineNumberTable() + .noTreeShaking() + .noMinification() + .setMinApi(parameters.getApiLevel()) + .run(parameters.getRuntime(), Main.class) + .assertFailureWithErrorThatMatches(containsString("Hello World!")) + .inspectFailure( + inspector -> { + Collection<ClassReference> inputs = + ImmutableList.of(classFromClass(MyRunner.class), classFromClass(Main.class)); + for (FoundClassSubject clazz : inspector.allClasses()) { + if (inputs.contains(clazz.getFinalReference())) { + assertThat(clazz, not(isCompilerSynthesized())); + } else { + assertThat(clazz, isCompilerSynthesized()); + } + } + assertEquals(inputs.size() + 1, inspector.allClasses().size()); }); } diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java index be358de26..176310868 100644 --- a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java +++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java @@ -26,7 +26,9 @@ import com.android.tools.r8.naming.ClassNamingForNameMapper; import com.android.tools.r8.naming.MemberNaming; import com.android.tools.r8.naming.MemberNaming.FieldSignature; import com.android.tools.r8.naming.MemberNaming.MethodSignature; +import com.android.tools.r8.naming.MemberNaming.NoSignature; import com.android.tools.r8.naming.MemberNaming.Signature; +import com.android.tools.r8.naming.mappinginformation.MappingInformation; import com.android.tools.r8.naming.signature.GenericSignatureParser; import com.android.tools.r8.references.ClassReference; import com.android.tools.r8.references.FieldReference; @@ -44,6 +46,7 @@ import java.io.File; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.function.Consumer; import java.util.function.Predicate; @@ -412,6 +415,27 @@ public class FoundClassSubject extends ClassSubject { } @Override + public boolean isCompilerSynthesized() { + if (naming == null) { + return false; + } + Map<Signature, List<MappingInformation>> additionalMappings = naming.getAdditionalMappings(); + if (additionalMappings == null) { + return false; + } + List<MappingInformation> infos = additionalMappings.get(NoSignature.NO_SIGNATURE); + if (infos == null) { + return false; + } + for (MappingInformation info : infos) { + if (info.isCompilerSynthesizedMappingInformation()) { + return true; + } + } + return false; + } + + @Override public boolean isLocalClass() { return dexClass.isLocalClass(); } diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/Matchers.java b/src/test/java/com/android/tools/r8/utils/codeinspector/Matchers.java index 28f0b9c0e..e7db18c9b 100644 --- a/src/test/java/com/android/tools/r8/utils/codeinspector/Matchers.java +++ b/src/test/java/com/android/tools/r8/utils/codeinspector/Matchers.java @@ -218,6 +218,28 @@ public class Matchers { }; } + public static Matcher<Subject> isCompilerSynthesized() { + return new TypeSafeMatcher<Subject>() { + @Override + protected boolean matchesSafely(Subject subject) { + return subject.isPresent() && subject.isCompilerSynthesized(); + } + + @Override + public void describeTo(Description description) { + description.appendText(" compiler synthesized"); + } + + @Override + public void describeMismatchSafely(final Subject subject, Description description) { + description + .appendText(type(subject) + " ") + .appendValue(name(subject)) + .appendText(" was not"); + } + }; + } + public static Matcher<ClassSubject> hasDefaultConstructor() { return new TypeSafeMatcher<ClassSubject>() { @Override diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/Subject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/Subject.java index 05d83b78e..29bc90bdf 100644 --- a/src/test/java/com/android/tools/r8/utils/codeinspector/Subject.java +++ b/src/test/java/com/android/tools/r8/utils/codeinspector/Subject.java @@ -4,6 +4,8 @@ package com.android.tools.r8.utils.codeinspector; +import com.android.tools.r8.errors.Unimplemented; + public abstract class Subject { public abstract boolean isPresent(); @@ -11,4 +13,9 @@ public abstract class Subject { public abstract boolean isRenamed(); public abstract boolean isSynthetic(); + + public boolean isCompilerSynthesized() { + throw new Unimplemented( + "Predicate not yet supported on Subject: " + getClass().getSimpleName()); + } } |