Move vertical class merging classes to verticalclassmerging package
Change-Id: Id71b8a2a6870da4452df298d6d8670232dd9fcc6
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 1af471f..53f1446 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -34,7 +34,6 @@
import com.android.tools.r8.graph.SubtypingInfo;
import com.android.tools.r8.graph.analysis.ClassInitializerAssertionEnablingAnalysis;
import com.android.tools.r8.graph.analysis.InitializedClassesInInstanceMethodsAnalysis;
-import com.android.tools.r8.graph.classmerging.VerticallyMergedClasses;
import com.android.tools.r8.graph.lens.AppliedGraphLens;
import com.android.tools.r8.horizontalclassmerging.HorizontalClassMerger;
import com.android.tools.r8.inspector.internal.InspectorImpl;
@@ -105,8 +104,6 @@
import com.android.tools.r8.shaking.RuntimeTypeCheckInfo;
import com.android.tools.r8.shaking.TreePruner;
import com.android.tools.r8.shaking.TreePrunerConfiguration;
-import com.android.tools.r8.shaking.VerticalClassMerger;
-import com.android.tools.r8.shaking.VerticalClassMergerGraphLens;
import com.android.tools.r8.shaking.WhyAreYouKeepingConsumer;
import com.android.tools.r8.synthesis.SyntheticFinalization;
import com.android.tools.r8.synthesis.SyntheticItems;
@@ -120,6 +117,9 @@
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.ThreadUtils;
import com.android.tools.r8.utils.Timing;
+import com.android.tools.r8.verticalclassmerging.VerticalClassMerger;
+import com.android.tools.r8.verticalclassmerging.VerticalClassMergerGraphLens;
+import com.android.tools.r8.verticalclassmerging.VerticallyMergedClasses;
import com.google.common.collect.Iterables;
import com.google.common.io.ByteStreams;
import java.io.ByteArrayOutputStream;
diff --git a/src/main/java/com/android/tools/r8/graph/AppView.java b/src/main/java/com/android/tools/r8/graph/AppView.java
index 5093100..4536685 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -14,7 +14,6 @@
import com.android.tools.r8.graph.DexValue.DexValueString;
import com.android.tools.r8.graph.analysis.InitializedClassesInInstanceMethodsAnalysis.InitializedClassesInInstanceMethods;
import com.android.tools.r8.graph.classmerging.MergedClassesCollection;
-import com.android.tools.r8.graph.classmerging.VerticallyMergedClasses;
import com.android.tools.r8.graph.lens.GraphLens;
import com.android.tools.r8.graph.lens.InitClassLens;
import com.android.tools.r8.graph.lens.NonIdentityGraphLens;
@@ -65,6 +64,7 @@
import com.android.tools.r8.utils.Timing;
import com.android.tools.r8.utils.threads.ThreadTask;
import com.android.tools.r8.utils.threads.ThreadTaskUtils;
+import com.android.tools.r8.verticalclassmerging.VerticallyMergedClasses;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableSet;
import java.io.IOException;
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/RespectPackageBoundaries.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/RespectPackageBoundaries.java
index ded7e1d..12ef6dc 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/RespectPackageBoundaries.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/RespectPackageBoundaries.java
@@ -16,8 +16,8 @@
import com.android.tools.r8.horizontalclassmerging.HorizontalClassMerger.Mode;
import com.android.tools.r8.horizontalclassmerging.MergeGroup;
import com.android.tools.r8.horizontalclassmerging.MultiClassPolicy;
-import com.android.tools.r8.shaking.VerticalClassMerger.IllegalAccessDetector;
import com.android.tools.r8.utils.TraversalContinuation;
+import com.android.tools.r8.verticalclassmerging.IllegalAccessDetector;
import com.google.common.collect.Iterables;
import java.util.ArrayList;
import java.util.Collection;
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 07ea7c8..e46d250 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
@@ -50,7 +50,6 @@
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramMethod;
-import com.android.tools.r8.graph.classmerging.VerticallyMergedClasses;
import com.android.tools.r8.graph.lens.FieldLookupResult;
import com.android.tools.r8.graph.lens.GraphLens;
import com.android.tools.r8.graph.lens.MethodLookupResult;
@@ -115,6 +114,7 @@
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.LazyBox;
import com.android.tools.r8.verticalclassmerging.InterfaceTypeToClassTypeLensCodeRewriterHelper;
+import com.android.tools.r8.verticalclassmerging.VerticallyMergedClasses;
import com.google.common.collect.Sets;
import java.util.ArrayDeque;
import java.util.ArrayList;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java b/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java
index 46dd4a0..f9c5e5f 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java
@@ -24,8 +24,8 @@
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import com.android.tools.r8.shaking.VerticalClassMerger.SingleTypeMapperGraphLens;
import com.android.tools.r8.utils.TriFunction;
+import com.android.tools.r8.verticalclassmerging.VerticalClassMerger.SingleTypeMapperGraphLens;
// Computes the inlining constraint for a given instruction.
public class InliningConstraints {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadAndStoreElimination.java b/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadAndStoreElimination.java
index bd85948..1cd2253 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadAndStoreElimination.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadAndStoreElimination.java
@@ -17,7 +17,6 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.FieldResolutionResult.SingleFieldResolutionResult;
import com.android.tools.r8.graph.ProgramMethod;
-import com.android.tools.r8.graph.classmerging.VerticallyMergedClasses;
import com.android.tools.r8.ir.analysis.type.Nullability;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.SingleFieldValue;
@@ -48,6 +47,7 @@
import com.android.tools.r8.ir.optimize.info.initializer.InstanceInitializerInfo;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.ArrayUtils;
+import com.android.tools.r8.verticalclassmerging.VerticallyMergedClasses;
import com.google.common.collect.Sets;
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
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 4bda905..2bf05d0 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -62,7 +62,6 @@
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.analysis.ResourceAccessAnalysis;
import com.android.tools.r8.graph.bytecodemetadata.BytecodeMetadataProvider;
-import com.android.tools.r8.graph.classmerging.VerticallyMergedClasses;
import com.android.tools.r8.horizontalclassmerging.HorizontalClassMerger;
import com.android.tools.r8.horizontalclassmerging.HorizontallyMergedClasses;
import com.android.tools.r8.horizontalclassmerging.Policy;
@@ -111,6 +110,7 @@
import com.android.tools.r8.utils.IROrdering.NondeterministicIROrdering;
import com.android.tools.r8.utils.collections.ProgramMethodSet;
import com.android.tools.r8.utils.structural.Ordered;
+import com.android.tools.r8.verticalclassmerging.VerticallyMergedClasses;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Equivalence.Wrapper;
import com.google.common.base.Predicates;
diff --git a/src/main/java/com/android/tools/r8/verticalclassmerging/IllegalAccessDetector.java b/src/main/java/com/android/tools/r8/verticalclassmerging/IllegalAccessDetector.java
new file mode 100644
index 0000000..c71a51d
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/verticalclassmerging/IllegalAccessDetector.java
@@ -0,0 +1,207 @@
+package com.android.tools.r8.verticalclassmerging;
+
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexClassAndField;
+import com.android.tools.r8.graph.DexClassAndMethod;
+import com.android.tools.r8.graph.DexField;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.MethodResolutionResult;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.graph.UseRegistryWithResult;
+import com.android.tools.r8.graph.lens.GraphLens;
+import com.android.tools.r8.graph.lens.MethodLookupResult;
+import com.android.tools.r8.utils.OptionalBool;
+
+// Searches for a reference to a non-private, non-public class, field or method declared in the
+// same package as [source].
+public class IllegalAccessDetector extends UseRegistryWithResult<Boolean, ProgramMethod> {
+
+ private final AppView<? extends AppInfoWithClassHierarchy> appViewWithClassHierarchy;
+
+ public IllegalAccessDetector(
+ AppView<? extends AppInfoWithClassHierarchy> appViewWithClassHierarchy,
+ ProgramMethod context) {
+ super(appViewWithClassHierarchy, context, false);
+ this.appViewWithClassHierarchy = appViewWithClassHierarchy;
+ }
+
+ protected boolean checkFoundPackagePrivateAccess() {
+ assert getResult();
+ return true;
+ }
+
+ protected boolean setFoundPackagePrivateAccess() {
+ setResult(true);
+ return true;
+ }
+
+ protected static boolean continueSearchForPackagePrivateAccess() {
+ return false;
+ }
+
+ private boolean checkFieldReference(DexField field) {
+ return checkRewrittenFieldReference(appViewWithClassHierarchy.graphLens().lookupField(field));
+ }
+
+ private boolean checkRewrittenFieldReference(DexField field) {
+ assert field.getHolderType().isClassType();
+ DexType fieldHolder = field.getHolderType();
+ if (fieldHolder.isSamePackage(getContext().getHolderType())) {
+ if (checkRewrittenTypeReference(fieldHolder)) {
+ return checkFoundPackagePrivateAccess();
+ }
+ DexClassAndField resolvedField =
+ appViewWithClassHierarchy.appInfo().resolveField(field).getResolutionPair();
+ if (resolvedField == null) {
+ return setFoundPackagePrivateAccess();
+ }
+ if (resolvedField.getHolder() != getContext().getHolder()
+ && !resolvedField.getAccessFlags().isPublic()) {
+ return setFoundPackagePrivateAccess();
+ }
+ if (checkRewrittenFieldType(resolvedField)) {
+ return checkFoundPackagePrivateAccess();
+ }
+ }
+ return continueSearchForPackagePrivateAccess();
+ }
+
+ protected boolean checkRewrittenFieldType(DexClassAndField field) {
+ return continueSearchForPackagePrivateAccess();
+ }
+
+ private boolean checkRewrittenMethodReference(
+ DexMethod rewrittenMethod, OptionalBool isInterface) {
+ DexType baseType =
+ rewrittenMethod.getHolderType().toBaseType(appViewWithClassHierarchy.dexItemFactory());
+ if (baseType.isClassType() && baseType.isSamePackage(getContext().getHolderType())) {
+ if (checkTypeReference(rewrittenMethod.getHolderType())) {
+ return checkFoundPackagePrivateAccess();
+ }
+ MethodResolutionResult resolutionResult =
+ isInterface.isUnknown()
+ ? appViewWithClassHierarchy
+ .appInfo()
+ .unsafeResolveMethodDueToDexFormat(rewrittenMethod)
+ : appViewWithClassHierarchy
+ .appInfo()
+ .resolveMethod(rewrittenMethod, isInterface.isTrue());
+ if (!resolutionResult.isSingleResolution()) {
+ return setFoundPackagePrivateAccess();
+ }
+ DexClassAndMethod resolvedMethod = resolutionResult.asSingleResolution().getResolutionPair();
+ if (resolvedMethod.getHolder() != getContext().getHolder()
+ && !resolvedMethod.getAccessFlags().isPublic()) {
+ return setFoundPackagePrivateAccess();
+ }
+ }
+ return continueSearchForPackagePrivateAccess();
+ }
+
+ private boolean checkTypeReference(DexType type) {
+ return internalCheckTypeReference(type, appViewWithClassHierarchy.graphLens());
+ }
+
+ private boolean checkRewrittenTypeReference(DexType type) {
+ return internalCheckTypeReference(type, GraphLens.getIdentityLens());
+ }
+
+ private boolean internalCheckTypeReference(DexType type, GraphLens graphLens) {
+ DexType baseType =
+ graphLens.lookupType(type.toBaseType(appViewWithClassHierarchy.dexItemFactory()));
+ if (baseType.isClassType() && baseType.isSamePackage(getContext().getHolderType())) {
+ DexClass clazz = appViewWithClassHierarchy.definitionFor(baseType);
+ if (clazz == null || !clazz.isPublic()) {
+ return setFoundPackagePrivateAccess();
+ }
+ }
+ return continueSearchForPackagePrivateAccess();
+ }
+
+ @Override
+ public void registerInitClass(DexType clazz) {
+ if (appViewWithClassHierarchy.initClassLens().isFinal()) {
+ // The InitClass lens is always rewritten up until the most recent graph lens, so first map
+ // the class type to the most recent graph lens.
+ DexType rewrittenType = appViewWithClassHierarchy.graphLens().lookupType(clazz);
+ DexField initClassField =
+ appViewWithClassHierarchy.initClassLens().getInitClassField(rewrittenType);
+ checkRewrittenFieldReference(initClassField);
+ } else {
+ checkTypeReference(clazz);
+ }
+ }
+
+ @Override
+ public void registerInvokeVirtual(DexMethod method) {
+ MethodLookupResult lookup =
+ appViewWithClassHierarchy.graphLens().lookupInvokeVirtual(method, getContext());
+ checkRewrittenMethodReference(lookup.getReference(), OptionalBool.FALSE);
+ }
+
+ @Override
+ public void registerInvokeDirect(DexMethod method) {
+ MethodLookupResult lookup =
+ appViewWithClassHierarchy.graphLens().lookupInvokeDirect(method, getContext());
+ checkRewrittenMethodReference(lookup.getReference(), OptionalBool.UNKNOWN);
+ }
+
+ @Override
+ public void registerInvokeStatic(DexMethod method) {
+ MethodLookupResult lookup =
+ appViewWithClassHierarchy.graphLens().lookupInvokeStatic(method, getContext());
+ checkRewrittenMethodReference(lookup.getReference(), OptionalBool.UNKNOWN);
+ }
+
+ @Override
+ public void registerInvokeInterface(DexMethod method) {
+ MethodLookupResult lookup =
+ appViewWithClassHierarchy.graphLens().lookupInvokeInterface(method, getContext());
+ checkRewrittenMethodReference(lookup.getReference(), OptionalBool.TRUE);
+ }
+
+ @Override
+ public void registerInvokeSuper(DexMethod method) {
+ MethodLookupResult lookup =
+ appViewWithClassHierarchy.graphLens().lookupInvokeSuper(method, getContext());
+ checkRewrittenMethodReference(lookup.getReference(), OptionalBool.UNKNOWN);
+ }
+
+ @Override
+ public void registerInstanceFieldWrite(DexField field) {
+ checkFieldReference(field);
+ }
+
+ @Override
+ public void registerInstanceFieldRead(DexField field) {
+ checkFieldReference(field);
+ }
+
+ @Override
+ public void registerNewInstance(DexType type) {
+ checkTypeReference(type);
+ }
+
+ @Override
+ public void registerStaticFieldRead(DexField field) {
+ checkFieldReference(field);
+ }
+
+ @Override
+ public void registerStaticFieldWrite(DexField field) {
+ checkFieldReference(field);
+ }
+
+ @Override
+ public void registerTypeReference(DexType type) {
+ checkTypeReference(type);
+ }
+
+ @Override
+ public void registerInstanceOf(DexType type) {
+ checkTypeReference(type);
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/verticalclassmerging/InvokeSpecialToDefaultLibraryMethodUseRegistry.java b/src/main/java/com/android/tools/r8/verticalclassmerging/InvokeSpecialToDefaultLibraryMethodUseRegistry.java
new file mode 100644
index 0000000..2451630
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/verticalclassmerging/InvokeSpecialToDefaultLibraryMethodUseRegistry.java
@@ -0,0 +1,67 @@
+package com.android.tools.r8.verticalclassmerging;
+
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexField;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.graph.UseRegistryWithResult;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+
+public class InvokeSpecialToDefaultLibraryMethodUseRegistry
+ extends UseRegistryWithResult<Boolean, ProgramMethod> {
+
+ InvokeSpecialToDefaultLibraryMethodUseRegistry(
+ AppView<AppInfoWithLiveness> appView, ProgramMethod context) {
+ super(appView, context, false);
+ assert context.getHolder().isInterface();
+ }
+
+ @Override
+ @SuppressWarnings("ReferenceEquality")
+ public void registerInvokeSpecial(DexMethod method) {
+ ProgramMethod context = getContext();
+ if (method.getHolderType() != context.getHolderType()) {
+ return;
+ }
+
+ DexEncodedMethod definition = context.getHolder().lookupMethod(method);
+ if (definition != null && definition.belongsToVirtualPool()) {
+ setResult(true);
+ }
+ }
+
+ @Override
+ public void registerInitClass(DexType type) {}
+
+ @Override
+ public void registerInvokeDirect(DexMethod method) {}
+
+ @Override
+ public void registerInvokeInterface(DexMethod method) {}
+
+ @Override
+ public void registerInvokeStatic(DexMethod method) {}
+
+ @Override
+ public void registerInvokeSuper(DexMethod method) {}
+
+ @Override
+ public void registerInvokeVirtual(DexMethod method) {}
+
+ @Override
+ public void registerInstanceFieldRead(DexField field) {}
+
+ @Override
+ public void registerInstanceFieldWrite(DexField field) {}
+
+ @Override
+ public void registerStaticFieldRead(DexField field) {}
+
+ @Override
+ public void registerStaticFieldWrite(DexField field) {}
+
+ @Override
+ public void registerTypeReference(DexType type) {}
+}
diff --git a/src/main/java/com/android/tools/r8/verticalclassmerging/SynthesizedBridgeCode.java b/src/main/java/com/android/tools/r8/verticalclassmerging/SynthesizedBridgeCode.java
new file mode 100644
index 0000000..4471ff5
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/verticalclassmerging/SynthesizedBridgeCode.java
@@ -0,0 +1,84 @@
+package com.android.tools.r8.verticalclassmerging;
+
+import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.graph.DexClassAndMethod;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.UseRegistry;
+import com.android.tools.r8.ir.code.InvokeType;
+import com.android.tools.r8.ir.synthetic.AbstractSynthesizedCode;
+import com.android.tools.r8.ir.synthetic.ForwardMethodSourceCode;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+public class SynthesizedBridgeCode extends AbstractSynthesizedCode {
+
+ private DexMethod method;
+ private DexMethod invocationTarget;
+ private InvokeType type;
+ private final boolean isInterface;
+
+ public SynthesizedBridgeCode(
+ DexMethod method, DexMethod invocationTarget, InvokeType type, boolean isInterface) {
+ this.method = method;
+ this.invocationTarget = invocationTarget;
+ this.type = type;
+ this.isInterface = isInterface;
+ }
+
+ public DexMethod getMethod() {
+ return method;
+ }
+
+ public DexMethod getTarget() {
+ return invocationTarget;
+ }
+
+ // By the time the synthesized code object is created, vertical class merging still has not
+ // finished. Therefore it is possible that the method signatures `method` and `invocationTarget`
+ // will change as a result of additional class merging operations. To deal with this, the
+ // vertical class merger explicitly invokes this method to update `method` and `invocation-
+ // Target` when vertical class merging has finished.
+ //
+ // Note that, without this step, these method signatures might refer to intermediate signatures
+ // that are only present in the middle of vertical class merging, which means that the graph
+ // lens will not work properly (since the graph lens generated by vertical class merging only
+ // expects to be applied to method signatures from *before* vertical class merging or *after*
+ // vertical class merging).
+ public void updateMethodSignatures(Function<DexMethod, DexMethod> transformer) {
+ method = transformer.apply(method);
+ invocationTarget = transformer.apply(invocationTarget);
+ }
+
+ @Override
+ public SourceCodeProvider getSourceCodeProvider() {
+ ForwardMethodSourceCode.Builder forwardSourceCodeBuilder =
+ ForwardMethodSourceCode.builder(method);
+ forwardSourceCodeBuilder
+ .setReceiver(method.holder)
+ .setTargetReceiver(type.isStatic() ? null : method.holder)
+ .setTarget(invocationTarget)
+ .setInvokeType(type)
+ .setIsInterface(isInterface);
+ return forwardSourceCodeBuilder::build;
+ }
+
+ @Override
+ public Consumer<UseRegistry> getRegistryCallback(DexClassAndMethod method) {
+ return registry -> {
+ assert registry.getTraversalContinuation().shouldContinue();
+ switch (type) {
+ case DIRECT:
+ registry.registerInvokeDirect(invocationTarget);
+ break;
+ case STATIC:
+ registry.registerInvokeStatic(invocationTarget);
+ break;
+ case VIRTUAL:
+ registry.registerInvokeVirtual(invocationTarget);
+ break;
+ default:
+ throw new Unreachable("Unexpected invocation type: " + type);
+ }
+ };
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java b/src/main/java/com/android/tools/r8/verticalclassmerging/VerticalClassMerger.java
similarity index 87%
rename from src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
rename to src/main/java/com/android/tools/r8/verticalclassmerging/VerticalClassMerger.java
index 2211f75..36982c6 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/verticalclassmerging/VerticalClassMerger.java
@@ -1,7 +1,7 @@
// Copyright (c) 2017, 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.shaking;
+package com.android.tools.r8.verticalclassmerging;
import static com.android.tools.r8.dex.Constants.TEMPORARY_INSTANCE_INITIALIZER_PREFIX;
import static com.android.tools.r8.graph.DexClassAndMethod.asProgramMethodOrNull;
@@ -17,15 +17,12 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.features.FeatureSplitBoundaryOptimizationUtils;
import com.android.tools.r8.graph.AccessControl;
-import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.Code;
import com.android.tools.r8.graph.DefaultInstanceInitializerCode;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexClass;
-import com.android.tools.r8.graph.DexClassAndField;
-import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMember;
import com.android.tools.r8.graph.DexEncodedMethod;
@@ -57,9 +54,6 @@
import com.android.tools.r8.graph.PrunedItems;
import com.android.tools.r8.graph.SubtypingInfo;
import com.android.tools.r8.graph.TopDownClassHierarchyTraversal;
-import com.android.tools.r8.graph.UseRegistry;
-import com.android.tools.r8.graph.UseRegistryWithResult;
-import com.android.tools.r8.graph.classmerging.VerticallyMergedClasses;
import com.android.tools.r8.graph.fixup.TreeFixerBase;
import com.android.tools.r8.graph.lens.FieldLookupResult;
import com.android.tools.r8.graph.lens.GraphLens;
@@ -70,9 +64,11 @@
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedback;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackSimple;
-import com.android.tools.r8.ir.synthetic.AbstractSynthesizedCode;
-import com.android.tools.r8.ir.synthetic.ForwardMethodSourceCode;
import com.android.tools.r8.profile.rewriting.ProfileCollectionAdditions;
+import com.android.tools.r8.shaking.AnnotationFixer;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.shaking.KeepInfoCollection;
+import com.android.tools.r8.shaking.MainDexInfo;
import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.CollectionUtils;
import com.android.tools.r8.utils.FieldSignatureEquivalence;
@@ -108,8 +104,6 @@
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
-import java.util.function.Consumer;
-import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;
@@ -638,8 +632,8 @@
if (!profileCollectionAdditions.isNop()) {
for (SynthesizedBridgeCode synthesizedBridge : synthesizedBridges) {
profileCollectionAdditions.applyIfContextIsInProfile(
- lens.getPreviousMethodSignature(synthesizedBridge.method),
- additionsBuilder -> additionsBuilder.addRule(synthesizedBridge.method));
+ lens.getPreviousMethodSignature(synthesizedBridge.getMethod()),
+ additionsBuilder -> additionsBuilder.addRule(synthesizedBridge.getMethod()));
}
}
profileCollectionAdditions.commit(appView);
@@ -652,9 +646,9 @@
mutator -> {
for (SynthesizedBridgeCode synthesizedBridge : synthesizedBridges) {
ProgramMethod bridge =
- asProgramMethodOrNull(appView.definitionFor(synthesizedBridge.method));
+ asProgramMethodOrNull(appView.definitionFor(synthesizedBridge.getMethod()));
ProgramMethod target =
- asProgramMethodOrNull(appView.definitionFor(synthesizedBridge.invocationTarget));
+ asProgramMethodOrNull(appView.definitionFor(synthesizedBridge.getTarget()));
if (bridge != null && target != null) {
mutator.joinMethod(bridge, info -> info.merge(appView.getKeepInfo(target).joiner()));
continue;
@@ -711,7 +705,7 @@
// the two methods map back to the same original method, and that the original method
// can be mapped to the implementation method.
DexMethod implementationMethod =
- ((SynthesizedBridgeCode) encodedMethod.getCode()).invocationTarget;
+ ((SynthesizedBridgeCode) encodedMethod.getCode()).getTarget();
DexMethod originalImplementationMethod =
graphLens.getOriginalMethodSignature(implementationMethod);
assert originalMethod == originalImplementationMethod;
@@ -1999,325 +1993,4 @@
return true;
}
}
-
- // Searches for a reference to a non-private, non-public class, field or method declared in the
- // same package as [source].
- public static class IllegalAccessDetector extends UseRegistryWithResult<Boolean, ProgramMethod> {
-
- private final AppView<? extends AppInfoWithClassHierarchy> appViewWithClassHierarchy;
-
- public IllegalAccessDetector(
- AppView<? extends AppInfoWithClassHierarchy> appViewWithClassHierarchy,
- ProgramMethod context) {
- super(appViewWithClassHierarchy, context, false);
- this.appViewWithClassHierarchy = appViewWithClassHierarchy;
- }
-
- protected boolean checkFoundPackagePrivateAccess() {
- assert getResult();
- return true;
- }
-
- protected boolean setFoundPackagePrivateAccess() {
- setResult(true);
- return true;
- }
-
- protected static boolean continueSearchForPackagePrivateAccess() {
- return false;
- }
-
- private boolean checkFieldReference(DexField field) {
- return checkRewrittenFieldReference(appViewWithClassHierarchy.graphLens().lookupField(field));
- }
-
- private boolean checkRewrittenFieldReference(DexField field) {
- assert field.getHolderType().isClassType();
- DexType fieldHolder = field.getHolderType();
- if (fieldHolder.isSamePackage(getContext().getHolderType())) {
- if (checkRewrittenTypeReference(fieldHolder)) {
- return checkFoundPackagePrivateAccess();
- }
- DexClassAndField resolvedField =
- appViewWithClassHierarchy.appInfo().resolveField(field).getResolutionPair();
- if (resolvedField == null) {
- return setFoundPackagePrivateAccess();
- }
- if (resolvedField.getHolder() != getContext().getHolder()
- && !resolvedField.getAccessFlags().isPublic()) {
- return setFoundPackagePrivateAccess();
- }
- if (checkRewrittenFieldType(resolvedField)) {
- return checkFoundPackagePrivateAccess();
- }
- }
- return continueSearchForPackagePrivateAccess();
- }
-
- protected boolean checkRewrittenFieldType(DexClassAndField field) {
- return continueSearchForPackagePrivateAccess();
- }
-
- private boolean checkRewrittenMethodReference(
- DexMethod rewrittenMethod, OptionalBool isInterface) {
- DexType baseType =
- rewrittenMethod.getHolderType().toBaseType(appViewWithClassHierarchy.dexItemFactory());
- if (baseType.isClassType() && baseType.isSamePackage(getContext().getHolderType())) {
- if (checkTypeReference(rewrittenMethod.getHolderType())) {
- return checkFoundPackagePrivateAccess();
- }
- MethodResolutionResult resolutionResult =
- isInterface.isUnknown()
- ? appViewWithClassHierarchy
- .appInfo()
- .unsafeResolveMethodDueToDexFormat(rewrittenMethod)
- : appViewWithClassHierarchy
- .appInfo()
- .resolveMethod(rewrittenMethod, isInterface.isTrue());
- if (!resolutionResult.isSingleResolution()) {
- return setFoundPackagePrivateAccess();
- }
- DexClassAndMethod resolvedMethod =
- resolutionResult.asSingleResolution().getResolutionPair();
- if (resolvedMethod.getHolder() != getContext().getHolder()
- && !resolvedMethod.getAccessFlags().isPublic()) {
- return setFoundPackagePrivateAccess();
- }
- }
- return continueSearchForPackagePrivateAccess();
- }
-
- private boolean checkTypeReference(DexType type) {
- return internalCheckTypeReference(type, appViewWithClassHierarchy.graphLens());
- }
-
- private boolean checkRewrittenTypeReference(DexType type) {
- return internalCheckTypeReference(type, GraphLens.getIdentityLens());
- }
-
- private boolean internalCheckTypeReference(DexType type, GraphLens graphLens) {
- DexType baseType =
- graphLens.lookupType(type.toBaseType(appViewWithClassHierarchy.dexItemFactory()));
- if (baseType.isClassType() && baseType.isSamePackage(getContext().getHolderType())) {
- DexClass clazz = appViewWithClassHierarchy.definitionFor(baseType);
- if (clazz == null || !clazz.isPublic()) {
- return setFoundPackagePrivateAccess();
- }
- }
- return continueSearchForPackagePrivateAccess();
- }
-
- @Override
- public void registerInitClass(DexType clazz) {
- if (appViewWithClassHierarchy.initClassLens().isFinal()) {
- // The InitClass lens is always rewritten up until the most recent graph lens, so first map
- // the class type to the most recent graph lens.
- DexType rewrittenType = appViewWithClassHierarchy.graphLens().lookupType(clazz);
- DexField initClassField =
- appViewWithClassHierarchy.initClassLens().getInitClassField(rewrittenType);
- checkRewrittenFieldReference(initClassField);
- } else {
- checkTypeReference(clazz);
- }
- }
-
- @Override
- public void registerInvokeVirtual(DexMethod method) {
- MethodLookupResult lookup =
- appViewWithClassHierarchy.graphLens().lookupInvokeVirtual(method, getContext());
- checkRewrittenMethodReference(lookup.getReference(), OptionalBool.FALSE);
- }
-
- @Override
- public void registerInvokeDirect(DexMethod method) {
- MethodLookupResult lookup =
- appViewWithClassHierarchy.graphLens().lookupInvokeDirect(method, getContext());
- checkRewrittenMethodReference(lookup.getReference(), OptionalBool.UNKNOWN);
- }
-
- @Override
- public void registerInvokeStatic(DexMethod method) {
- MethodLookupResult lookup =
- appViewWithClassHierarchy.graphLens().lookupInvokeStatic(method, getContext());
- checkRewrittenMethodReference(lookup.getReference(), OptionalBool.UNKNOWN);
- }
-
- @Override
- public void registerInvokeInterface(DexMethod method) {
- MethodLookupResult lookup =
- appViewWithClassHierarchy.graphLens().lookupInvokeInterface(method, getContext());
- checkRewrittenMethodReference(lookup.getReference(), OptionalBool.TRUE);
- }
-
- @Override
- public void registerInvokeSuper(DexMethod method) {
- MethodLookupResult lookup =
- appViewWithClassHierarchy.graphLens().lookupInvokeSuper(method, getContext());
- checkRewrittenMethodReference(lookup.getReference(), OptionalBool.UNKNOWN);
- }
-
- @Override
- public void registerInstanceFieldWrite(DexField field) {
- checkFieldReference(field);
- }
-
- @Override
- public void registerInstanceFieldRead(DexField field) {
- checkFieldReference(field);
- }
-
- @Override
- public void registerNewInstance(DexType type) {
- checkTypeReference(type);
- }
-
- @Override
- public void registerStaticFieldRead(DexField field) {
- checkFieldReference(field);
- }
-
- @Override
- public void registerStaticFieldWrite(DexField field) {
- checkFieldReference(field);
- }
-
- @Override
- public void registerTypeReference(DexType type) {
- checkTypeReference(type);
- }
-
- @Override
- public void registerInstanceOf(DexType type) {
- checkTypeReference(type);
- }
- }
-
- public static class InvokeSpecialToDefaultLibraryMethodUseRegistry
- extends UseRegistryWithResult<Boolean, ProgramMethod> {
-
- InvokeSpecialToDefaultLibraryMethodUseRegistry(
- AppView<AppInfoWithLiveness> appView, ProgramMethod context) {
- super(appView, context, false);
- assert context.getHolder().isInterface();
- }
-
- @Override
- @SuppressWarnings("ReferenceEquality")
- public void registerInvokeSpecial(DexMethod method) {
- ProgramMethod context = getContext();
- if (method.getHolderType() != context.getHolderType()) {
- return;
- }
-
- DexEncodedMethod definition = context.getHolder().lookupMethod(method);
- if (definition != null && definition.belongsToVirtualPool()) {
- setResult(true);
- }
- }
-
- @Override
- public void registerInitClass(DexType type) {}
-
- @Override
- public void registerInvokeDirect(DexMethod method) {}
-
- @Override
- public void registerInvokeInterface(DexMethod method) {}
-
- @Override
- public void registerInvokeStatic(DexMethod method) {}
-
- @Override
- public void registerInvokeSuper(DexMethod method) {}
-
- @Override
- public void registerInvokeVirtual(DexMethod method) {}
-
- @Override
- public void registerInstanceFieldRead(DexField field) {}
-
- @Override
- public void registerInstanceFieldWrite(DexField field) {}
-
- @Override
- public void registerStaticFieldRead(DexField field) {}
-
- @Override
- public void registerStaticFieldWrite(DexField field) {}
-
- @Override
- public void registerTypeReference(DexType type) {}
- }
-
- public static class SynthesizedBridgeCode extends AbstractSynthesizedCode {
-
- private DexMethod method;
- private DexMethod invocationTarget;
- private InvokeType type;
- private final boolean isInterface;
-
- public SynthesizedBridgeCode(
- DexMethod method,
- DexMethod invocationTarget,
- InvokeType type,
- boolean isInterface) {
- this.method = method;
- this.invocationTarget = invocationTarget;
- this.type = type;
- this.isInterface = isInterface;
- }
-
- // By the time the synthesized code object is created, vertical class merging still has not
- // finished. Therefore it is possible that the method signatures `method` and `invocationTarget`
- // will change as a result of additional class merging operations. To deal with this, the
- // vertical class merger explicitly invokes this method to update `method` and `invocation-
- // Target` when vertical class merging has finished.
- //
- // Note that, without this step, these method signatures might refer to intermediate signatures
- // that are only present in the middle of vertical class merging, which means that the graph
- // lens will not work properly (since the graph lens generated by vertical class merging only
- // expects to be applied to method signatures from *before* vertical class merging or *after*
- // vertical class merging).
- public void updateMethodSignatures(Function<DexMethod, DexMethod> transformer) {
- method = transformer.apply(method);
- invocationTarget = transformer.apply(invocationTarget);
- }
-
- @Override
- public SourceCodeProvider getSourceCodeProvider() {
- ForwardMethodSourceCode.Builder forwardSourceCodeBuilder =
- ForwardMethodSourceCode.builder(method);
- forwardSourceCodeBuilder
- .setReceiver(method.holder)
- .setTargetReceiver(type.isStatic() ? null : method.holder)
- .setTarget(invocationTarget)
- .setInvokeType(type)
- .setIsInterface(isInterface);
- return forwardSourceCodeBuilder::build;
- }
-
- @Override
- public Consumer<UseRegistry> getRegistryCallback(DexClassAndMethod method) {
- return registry -> {
- assert registry.getTraversalContinuation().shouldContinue();
- switch (type) {
- case DIRECT:
- registry.registerInvokeDirect(invocationTarget);
- break;
- case STATIC:
- registry.registerInvokeStatic(invocationTarget);
- break;
- case VIRTUAL:
- registry.registerInvokeVirtual(invocationTarget);
- break;
- default:
- throw new Unreachable("Unexpected invocation type: " + type);
- }
- };
- }
- }
-
- public Collection<DexType> getRemovedClasses() {
- return Collections.unmodifiableCollection(mergedClasses.keySet());
- }
}
diff --git a/src/main/java/com/android/tools/r8/shaking/VerticalClassMergerGraphLens.java b/src/main/java/com/android/tools/r8/verticalclassmerging/VerticalClassMergerGraphLens.java
similarity index 99%
rename from src/main/java/com/android/tools/r8/shaking/VerticalClassMergerGraphLens.java
rename to src/main/java/com/android/tools/r8/verticalclassmerging/VerticalClassMergerGraphLens.java
index d4525f0..1a08e65 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMergerGraphLens.java
+++ b/src/main/java/com/android/tools/r8/verticalclassmerging/VerticalClassMergerGraphLens.java
@@ -2,7 +2,7 @@
// 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.shaking;
+package com.android.tools.r8.verticalclassmerging;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexField;
@@ -11,7 +11,6 @@
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.classmerging.VerticallyMergedClasses;
import com.android.tools.r8.graph.lens.GraphLens;
import com.android.tools.r8.graph.lens.MethodLookupResult;
import com.android.tools.r8.graph.lens.NestedGraphLens;
diff --git a/src/main/java/com/android/tools/r8/graph/classmerging/VerticallyMergedClasses.java b/src/main/java/com/android/tools/r8/verticalclassmerging/VerticallyMergedClasses.java
similarity index 96%
rename from src/main/java/com/android/tools/r8/graph/classmerging/VerticallyMergedClasses.java
rename to src/main/java/com/android/tools/r8/verticalclassmerging/VerticallyMergedClasses.java
index 78c6259..d6f3e64 100644
--- a/src/main/java/com/android/tools/r8/graph/classmerging/VerticallyMergedClasses.java
+++ b/src/main/java/com/android/tools/r8/verticalclassmerging/VerticallyMergedClasses.java
@@ -2,10 +2,11 @@
// 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.graph.classmerging;
+package com.android.tools.r8.verticalclassmerging;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.classmerging.MergedClasses;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.collections.BidirectionalManyToOneMap;
import com.android.tools.r8.utils.collections.BidirectionalManyToOneRepresentativeMap;
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/VerticallyMergedClassesInspector.java b/src/test/java/com/android/tools/r8/utils/codeinspector/VerticallyMergedClassesInspector.java
index d1f04cb..5b8f002 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/VerticallyMergedClassesInspector.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/VerticallyMergedClassesInspector.java
@@ -8,9 +8,9 @@
import static org.junit.Assert.assertTrue;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.classmerging.VerticallyMergedClasses;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.references.Reference;
+import com.android.tools.r8.verticalclassmerging.VerticallyMergedClasses;
public class VerticallyMergedClassesInspector {