Merge commit '003f5b447a7d850ac3bae1f499920fb5b63a476d' into dev-release
diff --git a/src/main/java/com/android/tools/r8/D8Command.java b/src/main/java/com/android/tools/r8/D8Command.java
index 92f194a..9673bc2 100644
--- a/src/main/java/com/android/tools/r8/D8Command.java
+++ b/src/main/java/com/android/tools/r8/D8Command.java
@@ -68,6 +68,7 @@
private boolean intermediate = false;
private DesugarGraphConsumer desugarGraphConsumer = null;
private StringConsumer desugaredLibraryKeepRuleConsumer = null;
+ private String synthesizedClassPrefix = "";
private Builder() {
this(new DefaultD8DiagnosticsHandler());
@@ -168,6 +169,11 @@
return CompilationMode.DEBUG;
}
+ Builder setSynthesizedClassesPrefix(String prefix) {
+ synthesizedClassPrefix = prefix;
+ return self();
+ }
+
@Override
void validate() {
Reporter reporter = getReporter();
@@ -227,6 +233,7 @@
libraryConfiguration,
getAssertionsConfiguration(),
getOutputInspections(),
+ synthesizedClassPrefix,
getThreadCount(),
factory);
}
@@ -238,6 +245,7 @@
private final DesugarGraphConsumer desugarGraphConsumer;
private final StringConsumer desugaredLibraryKeepRuleConsumer;
private final DesugaredLibraryConfiguration libraryConfiguration;
+ private final String synthesizedClassPrefix;
private final DexItemFactory factory;
public static Builder builder() {
@@ -297,6 +305,7 @@
DesugaredLibraryConfiguration libraryConfiguration,
List<AssertionsConfiguration> assertionsConfiguration,
List<Consumer<Inspector>> outputInspections,
+ String synthesizedClassPrefix,
int threadCount,
DexItemFactory factory) {
super(
@@ -317,6 +326,7 @@
this.desugarGraphConsumer = desugarGraphConsumer;
this.desugaredLibraryKeepRuleConsumer = desugaredLibraryKeepRuleConsumer;
this.libraryConfiguration = libraryConfiguration;
+ this.synthesizedClassPrefix = synthesizedClassPrefix;
this.factory = factory;
}
@@ -326,6 +336,7 @@
desugarGraphConsumer = null;
desugaredLibraryKeepRuleConsumer = null;
libraryConfiguration = null;
+ synthesizedClassPrefix = null;
factory = null;
}
@@ -372,8 +383,8 @@
internal.dexClassChecksumFilter = getDexClassChecksumFilter();
internal.enableInheritanceClassInDexDistributor = isOptimizeMultidexForLinearAlloc();
- // TODO(134732760): This is still work in progress.
internal.desugaredLibraryConfiguration = libraryConfiguration;
+ internal.synthesizedClassPrefix = synthesizedClassPrefix;
internal.desugaredLibraryKeepRuleConsumer = desugaredLibraryKeepRuleConsumer;
// Default is to remove all javac generated assertion code when generating dex.
diff --git a/src/main/java/com/android/tools/r8/GenerateLintFiles.java b/src/main/java/com/android/tools/r8/GenerateLintFiles.java
index 830f6b6..a6d704b 100644
--- a/src/main/java/com/android/tools/r8/GenerateLintFiles.java
+++ b/src/main/java/com/android/tools/r8/GenerateLintFiles.java
@@ -145,7 +145,7 @@
ParameterAnnotationsList.empty(),
code,
50);
- if (method.accessFlags.isStatic()) {
+ if (method.isStatic() || method.isDirectMethod()) {
directMethods.add(throwingMethod);
} else {
virtualMethods.add(throwingMethod);
diff --git a/src/main/java/com/android/tools/r8/L8Command.java b/src/main/java/com/android/tools/r8/L8Command.java
index c32fbb7..7741651 100644
--- a/src/main/java/com/android/tools/r8/L8Command.java
+++ b/src/main/java/com/android/tools/r8/L8Command.java
@@ -178,8 +178,10 @@
assert internal.enableInheritanceClassInDexDistributor;
internal.enableInheritanceClassInDexDistributor = false;
- // TODO(134732760): This is still work in progress.
+ assert libraryConfiguration != null;
internal.desugaredLibraryConfiguration = libraryConfiguration;
+ internal.synthesizedClassPrefix =
+ libraryConfiguration.getSynthesizedLibraryClassesPackagePrefix();
// Default is to remove all javac generated assertion code when generating dex.
assert internal.assertionsConfiguration == null;
@@ -289,6 +291,8 @@
R8Command.Builder r8Builder =
R8Command.builder(getReporter())
.addProgramResourceProvider(desugaredLibrary)
+ .setSynthesizedClassesPrefix(
+ libraryConfiguration.getSynthesizedLibraryClassesPackagePrefix())
.setMinApiLevel(getMinApiLevel())
.setMode(getMode())
.setProgramConsumer(getProgramConsumer());
@@ -307,6 +311,8 @@
D8Command.Builder d8Builder =
D8Command.builder(getReporter())
.addProgramResourceProvider(desugaredLibrary)
+ .setSynthesizedClassesPrefix(
+ libraryConfiguration.getSynthesizedLibraryClassesPackagePrefix())
.setMinApiLevel(getMinApiLevel())
.setMode(getMode())
.setProgramConsumer(getProgramConsumer());
diff --git a/src/main/java/com/android/tools/r8/PrintUses.java b/src/main/java/com/android/tools/r8/PrintUses.java
index 57f8395..4b310aa 100644
--- a/src/main/java/com/android/tools/r8/PrintUses.java
+++ b/src/main/java/com/android/tools/r8/PrintUses.java
@@ -18,7 +18,6 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DexValue;
import com.android.tools.r8.graph.DexValue.DexValueArray;
-import com.android.tools.r8.graph.DexValue.DexValueType;
import com.android.tools.r8.graph.DirectMappedDexApplication;
import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.graph.UseRegistry;
@@ -258,9 +257,9 @@
}
for (DexAnnotation annotation : method.annotations().annotations) {
if (annotation.annotation.type == appInfo.dexItemFactory().annotationThrows) {
- DexValueArray dexValues = (DexValueArray) annotation.annotation.elements[0].value;
+ DexValueArray dexValues = annotation.annotation.elements[0].value.asDexValueArray();
for (DexValue dexValType : dexValues.getValues()) {
- registerTypeReference(((DexValueType) dexValType).value);
+ registerTypeReference(dexValType.asDexValueType().value);
}
}
}
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 5223520..5bca79b1 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -34,7 +34,7 @@
import com.android.tools.r8.inspector.internal.InspectorImpl;
import com.android.tools.r8.ir.analysis.proto.GeneratedExtensionRegistryShrinker;
import com.android.tools.r8.ir.conversion.IRConverter;
-import com.android.tools.r8.ir.desugar.BackportedMethodRewriter;
+import com.android.tools.r8.ir.desugar.DesugaredLibraryRetargeter;
import com.android.tools.r8.ir.desugar.NestedPrivateMethodLense;
import com.android.tools.r8.ir.desugar.R8NestBasedAccessDesugaring;
import com.android.tools.r8.ir.optimize.AssertionsRewriter;
@@ -278,7 +278,7 @@
MainDexListBuilder.checkForAssumedLibraryTypes(appView.appInfo());
}
if (!options.desugaredLibraryConfiguration.getRetargetCoreLibMember().isEmpty()) {
- BackportedMethodRewriter.checkForAssumedLibraryTypes(appView);
+ DesugaredLibraryRetargeter.checkForAssumedLibraryTypes(appView);
}
List<ProguardConfigurationRule> synthesizedProguardRules = new ArrayList<>();
@@ -411,7 +411,7 @@
// The class type lattice elements include information about the interfaces that a class
// implements. This information can change as a result of vertical class merging, so we need
// to clear the cache, so that we will recompute the type lattice elements.
- appView.dexItemFactory().clearTypeLatticeElementsCache();
+ appView.dexItemFactory().clearTypeElementsCache();
if (options.getProguardConfiguration().isAccessModificationAllowed()) {
GraphLense publicizedLense =
@@ -514,7 +514,7 @@
}
// None of the optimizations above should lead to the creation of type lattice elements.
- assert appView.dexItemFactory().verifyNoCachedTypeLatticeElements();
+ assert appView.dexItemFactory().verifyNoCachedTypeElements();
// Collect switch maps and ordinals maps.
if (options.enableEnumSwitchMapRemoval) {
@@ -536,7 +536,7 @@
}
// Clear the reference type lattice element cache to reduce memory pressure.
- appView.dexItemFactory().clearTypeLatticeElementsCache();
+ appView.dexItemFactory().clearTypeElementsCache();
// At this point all code has been mapped according to the graph lens. We cannot remove the
// graph lens entirely, though, since it is needed for mapping all field and method signatures
@@ -717,7 +717,7 @@
// TODO(b/112437944): Avoid iterating the entire application to post-process every
// dynamicMethod() method.
appView.withGeneratedMessageLiteShrinker(
- shrinker -> shrinker.postOptimizeDynamicMethods(converter));
+ shrinker -> shrinker.postOptimizeDynamicMethods(converter, timing));
// If proto shrinking is enabled, we need to post-process every
// findLiteExtensionByNumber() method. This ensures that there are no references to dead
@@ -725,7 +725,7 @@
// TODO(b/112437944): Avoid iterating the entire application to post-process every
// findLiteExtensionByNumber() method.
appView.withGeneratedExtensionRegistryShrinker(
- shrinker -> shrinker.postOptimizeGeneratedExtensionRegistry(converter));
+ shrinker -> shrinker.postOptimizeGeneratedExtensionRegistry(converter, timing));
}
}
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index 611bc7a..fea04c7 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -104,6 +104,7 @@
private GraphConsumer mainDexKeptGraphConsumer = null;
private BiFunction<String, Long, Boolean> dexClassChecksumFilter = (name, checksum) -> true;
private final List<FeatureSplit> featureSplits = new ArrayList<>();
+ private String synthesizedClassPrefix = "";
private boolean allowPartiallyImplementedProguardOptions = false;
private boolean allowTestProguardOptions =
@@ -146,6 +147,11 @@
return CompilationMode.RELEASE;
}
+ Builder setSynthesizedClassesPrefix(String prefix) {
+ synthesizedClassPrefix = prefix;
+ return self();
+ }
+
/**
* Disable tree shaking.
*
@@ -572,6 +578,7 @@
featureSplitConfiguration,
getAssertionsConfiguration(),
getOutputInspections(),
+ synthesizedClassPrefix,
getThreadCount());
return command;
@@ -654,6 +661,7 @@
private final StringConsumer desugaredLibraryKeepRuleConsumer;
private final DesugaredLibraryConfiguration libraryConfiguration;
private final FeatureSplitConfiguration featureSplitConfiguration;
+ private final String synthesizedClassPrefix;
/** Get a new {@link R8Command.Builder}. */
public static Builder builder() {
@@ -731,6 +739,7 @@
FeatureSplitConfiguration featureSplitConfiguration,
List<AssertionsConfiguration> assertionsConfiguration,
List<Consumer<Inspector>> outputInspections,
+ String synthesizedClassPrefix,
int threadCount) {
super(
inputApp,
@@ -764,6 +773,7 @@
this.desugaredLibraryKeepRuleConsumer = desugaredLibraryKeepRuleConsumer;
this.libraryConfiguration = libraryConfiguration;
this.featureSplitConfiguration = featureSplitConfiguration;
+ this.synthesizedClassPrefix = synthesizedClassPrefix;
}
private R8Command(boolean printHelp, boolean printVersion) {
@@ -784,6 +794,7 @@
desugaredLibraryKeepRuleConsumer = null;
libraryConfiguration = null;
featureSplitConfiguration = null;
+ synthesizedClassPrefix = null;
}
/** Get the enable-tree-shaking state. */
@@ -910,8 +921,8 @@
internal.enableInheritanceClassInDexDistributor = isOptimizeMultidexForLinearAlloc();
- // TODO(134732760): This is still work in progress.
internal.desugaredLibraryConfiguration = libraryConfiguration;
+ internal.synthesizedClassPrefix = synthesizedClassPrefix;
internal.desugaredLibraryKeepRuleConsumer = desugaredLibraryKeepRuleConsumer;
assert internal.threadCount == ThreadUtils.NOT_SPECIFIED;
diff --git a/src/main/java/com/android/tools/r8/ResourceShrinker.java b/src/main/java/com/android/tools/r8/ResourceShrinker.java
index efeccec..0affffd 100644
--- a/src/main/java/com/android/tools/r8/ResourceShrinker.java
+++ b/src/main/java/com/android/tools/r8/ResourceShrinker.java
@@ -174,19 +174,25 @@
}
private void processFieldValue(DexValue value) {
- if (value instanceof DexValue.DexValueString) {
- callback.referencedString(((DexValue.DexValueString) value).value.toString());
- } else if (value instanceof DexValue.DexValueInt) {
- int constantValue = ((DexValue.DexValueInt) value).getValue();
- callback.referencedInt(constantValue);
- } else if (value instanceof DexValue.DexValueArray) {
- DexValue.DexValueArray arrayEncodedValue = (DexValue.DexValueArray) value;
- for (DexValue encodedValue : arrayEncodedValue.getValues()) {
- if (encodedValue instanceof DexValue.DexValueInt) {
- int constantValue = ((DexValue.DexValueInt) encodedValue).getValue();
- callback.referencedInt(constantValue);
+ switch (value.getValueKind()) {
+ case ARRAY:
+ for (DexValue elementValue : value.asDexValueArray().getValues()) {
+ if (elementValue.isDexValueInt()) {
+ callback.referencedInt(elementValue.asDexValueInt().getValue());
+ }
}
- }
+ break;
+
+ case INT:
+ callback.referencedInt(value.asDexValueInt().getValue());
+ break;
+
+ case STRING:
+ callback.referencedString(value.asDexValueString().value.toString());
+ break;
+
+ default:
+ // Intentionally empty.
}
}
@@ -286,22 +292,29 @@
}
private void processAnnotationValue(DexValue value) {
- if (value instanceof DexValue.DexValueInt) {
- DexValue.DexValueInt dexValueInt = (DexValue.DexValueInt) value;
- callback.referencedInt(dexValueInt.value);
- } else if (value instanceof DexValue.DexValueString) {
- DexValue.DexValueString dexValueString = (DexValue.DexValueString) value;
- callback.referencedString(dexValueString.value.toString());
- } else if (value instanceof DexValue.DexValueArray) {
- DexValue.DexValueArray dexValueArray = (DexValue.DexValueArray) value;
- for (DexValue dexValue : dexValueArray.getValues()) {
- processAnnotationValue(dexValue);
- }
- } else if (value instanceof DexValue.DexValueAnnotation) {
- DexValue.DexValueAnnotation dexValueAnnotation = (DexValue.DexValueAnnotation) value;
- for (DexAnnotationElement element : dexValueAnnotation.value.elements) {
- processAnnotationValue(element.value);
- }
+ switch (value.getValueKind()) {
+ case ANNOTATION:
+ for (DexAnnotationElement element : value.asDexValueAnnotation().value.elements) {
+ processAnnotationValue(element.value);
+ }
+ break;
+
+ case ARRAY:
+ for (DexValue elementValue : value.asDexValueArray().getValues()) {
+ processAnnotationValue(elementValue);
+ }
+ break;
+
+ case INT:
+ callback.referencedInt(value.asDexValueInt().value);
+ break;
+
+ case STRING:
+ callback.referencedString(value.asDexValueString().value.toString());
+ break;
+
+ default:
+ // Intentionally empty.
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/FixedLocalValue.java b/src/main/java/com/android/tools/r8/cf/FixedLocalValue.java
index 1b68ef6..cc78305 100644
--- a/src/main/java/com/android/tools/r8/cf/FixedLocalValue.java
+++ b/src/main/java/com/android/tools/r8/cf/FixedLocalValue.java
@@ -18,7 +18,7 @@
private final Phi phi;
public FixedLocalValue(Phi phi) {
- super(phi.getNumber(), phi.getTypeLattice(), phi.getLocalInfo());
+ super(phi.getNumber(), phi.getType(), phi.getLocalInfo());
this.phi = phi;
}
diff --git a/src/main/java/com/android/tools/r8/cf/TypeVerificationHelper.java b/src/main/java/com/android/tools/r8/cf/TypeVerificationHelper.java
index e77cba3..5b4d9f2 100644
--- a/src/main/java/com/android/tools/r8/cf/TypeVerificationHelper.java
+++ b/src/main/java/com/android/tools/r8/cf/TypeVerificationHelper.java
@@ -9,7 +9,7 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.Argument;
import com.android.tools.r8.ir.code.ConstNumber;
import com.android.tools.r8.ir.code.IRCode;
@@ -182,15 +182,15 @@
return types.iterator().next();
}
Iterator<DexType> iterator = types.iterator();
- TypeLatticeElement result = getLatticeElement(iterator.next());
+ TypeElement result = toTypeElement(iterator.next());
while (iterator.hasNext()) {
- result = result.join(getLatticeElement(iterator.next()), appView);
+ result = result.join(toTypeElement(iterator.next()), appView);
}
// All types are reference types so the join is either a class or an array.
if (result.isClassType()) {
- return result.asClassTypeLatticeElement().getClassType();
+ return result.asClassType().getClassType();
} else if (result.isArrayType()) {
- return result.asArrayTypeLatticeElement().getArrayType(appView.dexItemFactory());
+ return result.asArrayType().toDexType(appView.dexItemFactory());
}
throw new CompilationError("Unexpected join " + result + " of types: " +
String.join(", ",
@@ -215,8 +215,8 @@
return createInitializedType(join(ImmutableSet.of(type1, type2)));
}
- private TypeLatticeElement getLatticeElement(DexType type) {
- return TypeLatticeElement.fromDexType(type, Nullability.maybeNull(), appView);
+ private TypeElement toTypeElement(DexType type) {
+ return TypeElement.fromDexType(type, Nullability.maybeNull(), appView);
}
public Map<Value, TypeInfo> computeVerificationTypes() {
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstNumber.java b/src/main/java/com/android/tools/r8/cf/code/CfConstNumber.java
index 8977303..da5d12a 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstNumber.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstNumber.java
@@ -128,7 +128,7 @@
@Override
public void buildIR(IRBuilder builder, CfState state, CfSourceCode code) {
- builder.addConst(type.toPrimitiveTypeLattice(), state.push(type).register, value);
+ builder.addConst(type.toPrimitiveType(), state.push(type).register, value);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java b/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java
index ef0ec1b..8f01356 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java
@@ -10,14 +10,6 @@
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DexValue;
-import com.android.tools.r8.graph.DexValue.DexValueDouble;
-import com.android.tools.r8.graph.DexValue.DexValueFloat;
-import com.android.tools.r8.graph.DexValue.DexValueInt;
-import com.android.tools.r8.graph.DexValue.DexValueLong;
-import com.android.tools.r8.graph.DexValue.DexValueMethodHandle;
-import com.android.tools.r8.graph.DexValue.DexValueMethodType;
-import com.android.tools.r8.graph.DexValue.DexValueString;
-import com.android.tools.r8.graph.DexValue.DexValueType;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.code.ValueType;
@@ -55,26 +47,27 @@
methodName.toString(), callSite.methodProto.toDescriptorString(lens), bsmHandle, bsmArgs);
}
- private Object decodeBootstrapArgument(DexValue dexValue, NamingLens lens) {
- if (dexValue instanceof DexValueInt) {
- return ((DexValueInt) dexValue).getValue();
- } else if (dexValue instanceof DexValueLong) {
- return ((DexValueLong) dexValue).getValue();
- } else if (dexValue instanceof DexValueFloat) {
- return ((DexValueFloat) dexValue).getValue();
- } else if (dexValue instanceof DexValueDouble) {
- return ((DexValueDouble) dexValue).getValue();
- } else if (dexValue instanceof DexValueString) {
- return ((DexValueString) dexValue).getValue();
- } else if (dexValue instanceof DexValueType) {
- return Type.getType(lens.lookupDescriptor(((DexValueType) dexValue).value).toString());
- } else if (dexValue instanceof DexValueMethodType) {
- return Type.getMethodType(((DexValueMethodType) dexValue).value.toDescriptorString(lens));
- } else if (dexValue instanceof DexValueMethodHandle) {
- return ((DexValueMethodHandle) dexValue).value.toAsmHandle(lens);
- } else {
- throw new Unreachable(
- "Unsupported bootstrap argument of type " + dexValue.getClass().getSimpleName());
+ private Object decodeBootstrapArgument(DexValue value, NamingLens lens) {
+ switch (value.getValueKind()) {
+ case DOUBLE:
+ return value.asDexValueDouble().getValue();
+ case FLOAT:
+ return value.asDexValueFloat().getValue();
+ case INT:
+ return value.asDexValueInt().getValue();
+ case LONG:
+ return value.asDexValueLong().getValue();
+ case METHOD_HANDLE:
+ return value.asDexValueMethodHandle().getValue().toAsmHandle(lens);
+ case METHOD_TYPE:
+ return Type.getMethodType(value.asDexValueMethodType().getValue().toDescriptorString(lens));
+ case STRING:
+ return value.asDexValueString().getValue();
+ case TYPE:
+ return Type.getType(lens.lookupDescriptor(value.asDexValueType().value).toString());
+ default:
+ throw new Unreachable(
+ "Unsupported bootstrap argument of type " + value.getClass().getSimpleName());
}
}
diff --git a/src/main/java/com/android/tools/r8/code/Const.java b/src/main/java/com/android/tools/r8/code/Const.java
index 9026684..498f747 100644
--- a/src/main/java/com/android/tools/r8/code/Const.java
+++ b/src/main/java/com/android/tools/r8/code/Const.java
@@ -3,7 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.code;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.SingleConstant;
import com.android.tools.r8.ir.conversion.IRBuilder;
import com.android.tools.r8.naming.ClassNameMapper;
@@ -58,8 +58,7 @@
@Override
public void buildIR(IRBuilder builder) {
int value = decodedValue();
- TypeLatticeElement typeLattice =
- value == 0 ? TypeLatticeElement.getTop() : TypeLatticeElement.getSingle();
- builder.addConst(typeLattice, AA, value);
+ TypeElement type = value == 0 ? TypeElement.getTop() : TypeElement.getSingle();
+ builder.addConst(type, AA, value);
}
}
diff --git a/src/main/java/com/android/tools/r8/code/Const16.java b/src/main/java/com/android/tools/r8/code/Const16.java
index f859228..9d69f25 100644
--- a/src/main/java/com/android/tools/r8/code/Const16.java
+++ b/src/main/java/com/android/tools/r8/code/Const16.java
@@ -3,7 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.code;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.SingleConstant;
import com.android.tools.r8.ir.conversion.IRBuilder;
import com.android.tools.r8.naming.ClassNameMapper;
@@ -52,8 +52,7 @@
@Override
public void buildIR(IRBuilder builder) {
int value = decodedValue();
- TypeLatticeElement typeLattice =
- value == 0 ? TypeLatticeElement.getTop() : TypeLatticeElement.getSingle();
- builder.addConst(typeLattice, AA, value);
+ TypeElement type = value == 0 ? TypeElement.getTop() : TypeElement.getSingle();
+ builder.addConst(type, AA, value);
}
}
diff --git a/src/main/java/com/android/tools/r8/code/Const4.java b/src/main/java/com/android/tools/r8/code/Const4.java
index a036d57..b9fd59c 100644
--- a/src/main/java/com/android/tools/r8/code/Const4.java
+++ b/src/main/java/com/android/tools/r8/code/Const4.java
@@ -3,7 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.code;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.SingleConstant;
import com.android.tools.r8.ir.conversion.IRBuilder;
import com.android.tools.r8.naming.ClassNameMapper;
@@ -58,8 +58,7 @@
@Override
public void buildIR(IRBuilder builder) {
int value = decodedValue();
- TypeLatticeElement typeLattice =
- value == 0 ? TypeLatticeElement.getTop() : TypeLatticeElement.getSingle();
- builder.addConst(typeLattice, A, value);
+ TypeElement type = value == 0 ? TypeElement.getTop() : TypeElement.getSingle();
+ builder.addConst(type, A, value);
}
}
diff --git a/src/main/java/com/android/tools/r8/code/ConstHigh16.java b/src/main/java/com/android/tools/r8/code/ConstHigh16.java
index f3821a6..b16e45d 100644
--- a/src/main/java/com/android/tools/r8/code/ConstHigh16.java
+++ b/src/main/java/com/android/tools/r8/code/ConstHigh16.java
@@ -3,7 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.code;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.SingleConstant;
import com.android.tools.r8.ir.conversion.IRBuilder;
import com.android.tools.r8.naming.ClassNameMapper;
@@ -58,8 +58,7 @@
@Override
public void buildIR(IRBuilder builder) {
int value = decodedValue();
- TypeLatticeElement typeLattice =
- value == 0 ? TypeLatticeElement.getTop() : TypeLatticeElement.getSingle();
- builder.addConst(typeLattice, AA, value);
+ TypeElement type = value == 0 ? TypeElement.getTop() : TypeElement.getSingle();
+ builder.addConst(type, AA, value);
}
}
diff --git a/src/main/java/com/android/tools/r8/code/ConstWide.java b/src/main/java/com/android/tools/r8/code/ConstWide.java
index 31c1089..dd2e6e6 100644
--- a/src/main/java/com/android/tools/r8/code/ConstWide.java
+++ b/src/main/java/com/android/tools/r8/code/ConstWide.java
@@ -3,7 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.code;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.WideConstant;
import com.android.tools.r8.ir.conversion.IRBuilder;
import com.android.tools.r8.naming.ClassNameMapper;
@@ -57,6 +57,6 @@
@Override
public void buildIR(IRBuilder builder) {
- builder.addConst(TypeLatticeElement.getWide(), AA, decodedValue());
+ builder.addConst(TypeElement.getWide(), AA, decodedValue());
}
}
diff --git a/src/main/java/com/android/tools/r8/code/ConstWide16.java b/src/main/java/com/android/tools/r8/code/ConstWide16.java
index 2f7634d..99c1810 100644
--- a/src/main/java/com/android/tools/r8/code/ConstWide16.java
+++ b/src/main/java/com/android/tools/r8/code/ConstWide16.java
@@ -3,7 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.code;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.WideConstant;
import com.android.tools.r8.ir.conversion.IRBuilder;
import com.android.tools.r8.naming.ClassNameMapper;
@@ -57,6 +57,6 @@
@Override
public void buildIR(IRBuilder builder) {
- builder.addConst(TypeLatticeElement.getWide(), AA, decodedValue());
+ builder.addConst(TypeElement.getWide(), AA, decodedValue());
}
}
diff --git a/src/main/java/com/android/tools/r8/code/ConstWide32.java b/src/main/java/com/android/tools/r8/code/ConstWide32.java
index 51ef097..1e2c274 100644
--- a/src/main/java/com/android/tools/r8/code/ConstWide32.java
+++ b/src/main/java/com/android/tools/r8/code/ConstWide32.java
@@ -3,7 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.code;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.WideConstant;
import com.android.tools.r8.ir.conversion.IRBuilder;
import com.android.tools.r8.naming.ClassNameMapper;
@@ -57,6 +57,6 @@
@Override
public void buildIR(IRBuilder builder) {
- builder.addConst(TypeLatticeElement.getWide(), AA, decodedValue());
+ builder.addConst(TypeElement.getWide(), AA, decodedValue());
}
}
diff --git a/src/main/java/com/android/tools/r8/code/ConstWideHigh16.java b/src/main/java/com/android/tools/r8/code/ConstWideHigh16.java
index 8437a35..26d5ea0 100644
--- a/src/main/java/com/android/tools/r8/code/ConstWideHigh16.java
+++ b/src/main/java/com/android/tools/r8/code/ConstWideHigh16.java
@@ -3,7 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.code;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.WideConstant;
import com.android.tools.r8.ir.conversion.IRBuilder;
import com.android.tools.r8.naming.ClassNameMapper;
@@ -57,6 +57,6 @@
@Override
public void buildIR(IRBuilder builder) {
- builder.addConst(TypeLatticeElement.getWide(), AA, decodedValue());
+ builder.addConst(TypeElement.getWide(), AA, decodedValue());
}
}
diff --git a/src/main/java/com/android/tools/r8/dex/DexParser.java b/src/main/java/com/android/tools/r8/dex/DexParser.java
index f15e96e..a6eb1c3 100644
--- a/src/main/java/com/android/tools/r8/dex/DexParser.java
+++ b/src/main/java/com/android/tools/r8/dex/DexParser.java
@@ -48,10 +48,7 @@
import com.android.tools.r8.graph.DexTypeList;
import com.android.tools.r8.graph.DexValue;
import com.android.tools.r8.graph.DexValue.DexValueKind;
-import com.android.tools.r8.graph.DexValue.DexValueMethodHandle;
-import com.android.tools.r8.graph.DexValue.DexValueMethodType;
import com.android.tools.r8.graph.DexValue.DexValueNull;
-import com.android.tools.r8.graph.DexValue.DexValueString;
import com.android.tools.r8.graph.EnclosingMethodAttribute;
import com.android.tools.r8.graph.FieldAccessFlags;
import com.android.tools.r8.graph.InnerClassAttribute;
@@ -1244,14 +1241,14 @@
dexReader.getUint(dexSection.offset + (Constants.TYPE_CALL_SITE_ID_ITEM_SIZE * index));
DexEncodedArray callSiteEncodedArray = encodedArrayAt(callSiteOffset);
DexValue[] values = callSiteEncodedArray.values;
- assert values[0] instanceof DexValueMethodHandle;
- assert values[1] instanceof DexValueString;
- assert values[2] instanceof DexValueMethodType;
+ assert values[0].isDexValueMethodHandle();
+ assert values[1].isDexValueString();
+ assert values[2].isDexValueMethodType();
return dexItemFactory.createCallSite(
- ((DexValueString) values[1]).value,
- ((DexValueMethodType) values[2]).value,
- ((DexValueMethodHandle) values[0]).value,
+ values[1].asDexValueString().value,
+ values[2].asDexValueMethodType().value,
+ values[0].asDexValueMethodHandle().value,
// 3 means first extra args
Arrays.asList(Arrays.copyOfRange(values, 3, values.length)));
}
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfo.java b/src/main/java/com/android/tools/r8/graph/AppInfo.java
index 2ddba3f..a41e119 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfo.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfo.java
@@ -31,11 +31,15 @@
private final DexApplication app;
private final DexItemFactory dexItemFactory;
- private final ConcurrentHashMap<DexType, Map<DexMember<?, ?>, DexEncodedMember<?, ?>>>
- definitions = new ConcurrentHashMap<>();
+
+ // TODO(b/151804585): Remove this cache.
+ private final ConcurrentHashMap<DexType, Map<DexField, DexEncodedField>> fieldDefinitionsCache =
+ new ConcurrentHashMap<>();
+
// For some optimizations, e.g. optimizing synthetic classes, we may need to resolve the current
// class being optimized.
- final ConcurrentHashMap<DexType, DexProgramClass> synthesizedClasses = new ConcurrentHashMap<>();
+ private final ConcurrentHashMap<DexType, DexProgramClass> synthesizedClasses =
+ new ConcurrentHashMap<>();
// Set when a new AppInfo replaces a previous one. All public methods should verify that the
// current instance is not obsolete, to ensure that we almost use the most recent AppInfo.
@@ -50,7 +54,7 @@
assert !previous.isObsolete();
this.app = previous.app;
this.dexItemFactory = app.dexItemFactory;
- this.definitions.putAll(previous.definitions);
+ this.fieldDefinitionsCache.putAll(previous.fieldDefinitionsCache);
copyMetadataFromPrevious(previous);
}
@@ -94,7 +98,7 @@
assert checkIfObsolete();
assert clazz.type.isD8R8SynthesizedClassType();
DexProgramClass previous = synthesizedClasses.put(clazz.type, clazz);
- invalidateTypeCacheFor(clazz.type);
+ invalidateFieldCacheFor(clazz.type);
assert previous == null || previous == clazz;
}
@@ -103,12 +107,11 @@
return Collections.unmodifiableCollection(synthesizedClasses.values());
}
- private Map<DexMember<?, ?>, DexEncodedMember<?, ?>> computeDefinitions(DexType type) {
- Builder<DexMember<?, ?>, DexEncodedMember<?, ?>> builder = ImmutableMap.builder();
+ private Map<DexField, DexEncodedField> computeFieldDefinitions(DexType type) {
+ Builder<DexField, DexEncodedField> builder = ImmutableMap.builder();
DexClass clazz = definitionFor(type);
if (clazz != null) {
- clazz.forEachMethod(method -> builder.put(method.toReference(), method));
- clazz.forEachField(field -> builder.put(field.toReference(), field));
+ clazz.forEachField(field -> builder.put(field.field, field));
}
return builder.build();
}
@@ -173,35 +176,29 @@
@Override
public DexEncodedMethod definitionFor(DexMethod method) {
assert checkIfObsolete();
- DexType holderType = method.holder;
- DexEncodedMethod cached = (DexEncodedMethod) getDefinitions(holderType).get(method);
- if (cached != null && cached.isObsolete()) {
- definitions.remove(holderType);
- cached = (DexEncodedMethod) getDefinitions(holderType).get(method);
+ assert method.holder.isClassType();
+ if (!method.holder.isClassType()) {
+ return null;
}
- return cached;
+ DexClass clazz = definitionFor(method.holder);
+ if (clazz == null) {
+ return null;
+ }
+ return clazz.getMethodCollection().getMethod(method);
}
@Override
public DexEncodedField definitionFor(DexField field) {
assert checkIfObsolete();
- return (DexEncodedField) getDefinitions(field.holder).get(field);
+ return getFieldDefinitions(field.holder).get(field);
}
- private Map<DexMember<?, ?>, DexEncodedMember<?, ?>> getDefinitions(DexType type) {
- Map<DexMember<?, ?>, DexEncodedMember<?, ?>> typeDefinitions = definitions.get(type);
- if (typeDefinitions != null) {
- return typeDefinitions;
- }
-
- typeDefinitions = computeDefinitions(type);
- Map<DexMember<?, ?>, DexEncodedMember<?, ?>> existing =
- definitions.putIfAbsent(type, typeDefinitions);
- return existing != null ? existing : typeDefinitions;
+ private Map<DexField, DexEncodedField> getFieldDefinitions(DexType type) {
+ return fieldDefinitionsCache.computeIfAbsent(type, this::computeFieldDefinitions);
}
- public void invalidateTypeCacheFor(DexType type) {
- definitions.remove(type);
+ public void invalidateFieldCacheFor(DexType type) {
+ fieldDefinitionsCache.remove(type);
}
// TODO(b/147578480): Temporary API since most of the code base use a type instead
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfoWithSubtyping.java b/src/main/java/com/android/tools/r8/graph/AppInfoWithSubtyping.java
index 5f2b826..58611d4 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfoWithSubtyping.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfoWithSubtyping.java
@@ -5,7 +5,7 @@
import static com.android.tools.r8.ir.desugar.LambdaRewriter.LAMBDA_GROUP_CLASS_NAME_PREFIX;
-import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
import com.android.tools.r8.ir.desugar.LambdaDescriptor;
import com.android.tools.r8.utils.SetUtils;
import com.android.tools.r8.utils.WorkList;
@@ -480,7 +480,7 @@
return !isSubtype(type1, type2) && !isSubtype(type2, type1);
}
- public boolean mayHaveFinalizeMethodDirectlyOrIndirectly(ClassTypeLatticeElement type) {
+ public boolean mayHaveFinalizeMethodDirectlyOrIndirectly(ClassTypeElement type) {
if (type.getClassType() == dexItemFactory().objectType && !type.getInterfaces().isEmpty()) {
for (DexType interfaceType : type.getInterfaces()) {
if (computeMayHaveFinalizeMethodDirectlyOrIndirectlyIfAbsent(interfaceType, false)) {
diff --git a/src/main/java/com/android/tools/r8/graph/AssemblyWriter.java b/src/main/java/com/android/tools/r8/graph/AssemblyWriter.java
index 74735f4..4eb9a85 100644
--- a/src/main/java/com/android/tools/r8/graph/AssemblyWriter.java
+++ b/src/main/java/com/android/tools/r8/graph/AssemblyWriter.java
@@ -7,6 +7,9 @@
import com.android.tools.r8.ir.conversion.IRConverter;
import com.android.tools.r8.ir.conversion.OneTimeMethodProcessor;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackIgnore;
+import com.android.tools.r8.kotlin.Kotlin;
+import com.android.tools.r8.kotlin.KotlinClassMetadataReader;
+import com.android.tools.r8.kotlin.KotlinInfo;
import com.android.tools.r8.naming.ClassNameMapper;
import com.android.tools.r8.naming.MemberNaming.FieldSignature;
import com.android.tools.r8.utils.CfgPrinter;
@@ -21,6 +24,7 @@
private final boolean writeAnnotations;
private final boolean writeIR;
private final AppInfoWithSubtyping appInfo;
+ private final Kotlin kotlin;
private final Timing timing = new Timing("AssemblyWriter");
public AssemblyWriter(
@@ -41,6 +45,7 @@
} else {
this.appInfo = null;
}
+ kotlin = new Kotlin(application.dexItemFactory);
}
@Override
@@ -59,7 +64,7 @@
ps.println("# Bytecode for");
ps.println("# Class: '" + clazzName + "'");
if (writeAllClassInfo) {
- writeAnnotations(clazz.annotations(), ps);
+ writeAnnotations(clazz, clazz.annotations(), ps);
ps.println("# Flags: '" + clazz.accessFlags + "'");
if (clazz.superType != application.dexItemFactory.objectType) {
ps.println("# Extends: '" + clazz.superType.toSourceString() + "'");
@@ -87,7 +92,7 @@
FieldSignature fieldSignature = naming != null
? naming.originalSignatureOf(field.field)
: FieldSignature.fromDexField(field.field);
- writeAnnotations(field.annotations(), ps);
+ writeAnnotations(null, field.annotations(), ps);
ps.print(field.accessFlags + " ");
ps.print(fieldSignature);
if (field.isStatic() && field.hasExplicitStaticValue()) {
@@ -110,7 +115,7 @@
: method.method.name.toString();
ps.println("#");
ps.println("# Method: '" + methodName + "':");
- writeAnnotations(method.annotations(), ps);
+ writeAnnotations(null, method.annotations(), ps);
ps.println("# " + method.accessFlags);
ps.println("#");
ps.println();
@@ -134,16 +139,17 @@
ps.println(printer.toString());
}
- private void writeAnnotations(DexAnnotationSet annotations, PrintStream ps) {
+ private void writeAnnotations(
+ DexProgramClass clazz, DexAnnotationSet annotations, PrintStream ps) {
if (writeAnnotations) {
if (!annotations.isEmpty()) {
ps.println("# Annotations:");
for (DexAnnotation annotation : annotations.annotations) {
- ps.print("# ");
- if (annotation.annotation.type
- == application.dexItemFactory.createType("Lkotlin/Metadata;")) {
- ps.println("<kotlin metadata>");
+ if (annotation.annotation.type == kotlin.metadata.kotlinMetadataType) {
+ assert clazz != null : "Kotlin metadata is a class annotation";
+ writeKotlinMetadata(clazz, annotation, ps);
} else {
+ ps.print("# ");
ps.println(annotation);
}
}
@@ -151,6 +157,14 @@
}
}
+ private void writeKotlinMetadata(
+ DexProgramClass clazz, DexAnnotation annotation, PrintStream ps) {
+ assert annotation.annotation.type == kotlin.metadata.kotlinMetadataType;
+ KotlinInfo kotlinInfo =
+ KotlinClassMetadataReader.createKotlinInfo(kotlin, clazz, annotation.annotation);
+ ps.println(kotlinInfo.toString("# "));
+ }
+
@Override
void writeClassFooter(DexProgramClass clazz, PrintStream ps) {
diff --git a/src/main/java/com/android/tools/r8/graph/DexAnnotation.java b/src/main/java/com/android/tools/r8/graph/DexAnnotation.java
index 50b4b2f..a409737 100644
--- a/src/main/java/com/android/tools/r8/graph/DexAnnotation.java
+++ b/src/main/java/com/android/tools/r8/graph/DexAnnotation.java
@@ -99,9 +99,11 @@
public static DexType getEnclosingClassFromAnnotation(
DexAnnotation annotation, DexItemFactory factory) {
- DexValueType typeValue =
- (DexValueType) getSystemValueAnnotationValue(factory.annotationEnclosingClass, annotation);
- return typeValue == null ? null : typeValue.value;
+ DexValue value = getSystemValueAnnotationValue(factory.annotationEnclosingClass, annotation);
+ if (value == null) {
+ return null;
+ }
+ return value.asDexValueType().value;
}
public static DexAnnotation createEnclosingMethodAnnotation(DexMethod enclosingMethod,
@@ -112,10 +114,11 @@
public static DexMethod getEnclosingMethodFromAnnotation(
DexAnnotation annotation, DexItemFactory factory) {
- DexValueMethod methodValue =
- (DexValueMethod)
- getSystemValueAnnotationValue(factory.annotationEnclosingMethod, annotation);
- return methodValue == null ? null : methodValue.value;
+ DexValue value = getSystemValueAnnotationValue(factory.annotationEnclosingMethod, annotation);
+ if (value == null) {
+ return null;
+ }
+ return value.asDexValueMethod().value;
}
public static boolean isEnclosingClassAnnotation(DexAnnotation annotation,
@@ -159,12 +162,12 @@
Pair<DexString, Integer> result = new Pair<>();
for (DexAnnotationElement element : elements) {
if (element.name == factory.createString("name")) {
- if (element.value instanceof DexValueString) {
- result.setFirst(((DexValueString) element.value).getValue());
+ if (element.value.isDexValueString()) {
+ result.setFirst(element.value.asDexValueString().getValue());
}
} else {
assert element.name == factory.createString("accessFlags");
- result.setSecond(((DexValueInt) element.value).getValue());
+ result.setSecond(element.value.asDexValueInt().getValue());
}
}
return result;
@@ -182,14 +185,14 @@
public static List<DexType> getMemberClassesFromAnnotation(
DexAnnotation annotation, DexItemFactory factory) {
- DexValueArray membersArray =
- (DexValueArray) getSystemValueAnnotationValue(factory.annotationMemberClasses, annotation);
- if (membersArray == null) {
+ DexValue value = getSystemValueAnnotationValue(factory.annotationMemberClasses, annotation);
+ if (value == null) {
return null;
}
+ DexValueArray membersArray = value.asDexValueArray();
List<DexType> types = new ArrayList<>(membersArray.getValues().length);
- for (DexValue value : membersArray.getValues()) {
- types.add(((DexValueType) value).value);
+ for (DexValue elementValue : membersArray.getValues()) {
+ types.add(elementValue.asDexValueType().value);
}
return types;
}
@@ -233,10 +236,10 @@
}
public static String getSignature(DexAnnotation signatureAnnotation) {
- DexValueArray elements = (DexValueArray) signatureAnnotation.annotation.elements[0].value;
+ DexValueArray elements = signatureAnnotation.annotation.elements[0].value.asDexValueArray();
StringBuilder signature = new StringBuilder();
for (DexValue element : elements.getValues()) {
- signature.append(((DexValueString) element).value.toString());
+ signature.append(element.asDexValueString().value.toString());
}
return signature.toString();
}
@@ -349,16 +352,16 @@
if (!value.name.toSourceString().equals("value")) {
throw new CompilationError(getInvalidSynthesizedClassMapMessage(clazz, foundAnnotation));
}
- if (!(value.value instanceof DexValueArray)) {
+ DexValueArray existingList = value.value.asDexValueArray();
+ if (existingList == null) {
throw new CompilationError(getInvalidSynthesizedClassMapMessage(clazz, foundAnnotation));
}
- DexValueArray existingList = (DexValueArray) value.value;
Collection<DexType> synthesized = new ArrayList<>(existingList.values.length);
for (DexValue element : existingList.getValues()) {
- if (!(element instanceof DexValueType)) {
+ if (!element.isDexValueType()) {
throw new CompilationError(getInvalidSynthesizedClassMapMessage(clazz, foundAnnotation));
}
- synthesized.add(((DexValueType) element).value);
+ synthesized.add(element.asDexValueType().value);
}
return synthesized;
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexCallSite.java b/src/main/java/com/android/tools/r8/graph/DexCallSite.java
index 382f4bb..3249abf 100644
--- a/src/main/java/com/android/tools/r8/graph/DexCallSite.java
+++ b/src/main/java/com/android/tools/r8/graph/DexCallSite.java
@@ -213,52 +213,35 @@
private void write(List<DexValue> args) throws IOException {
out.writeInt(args.size());
for (DexValue arg : args) {
- // String, Class, Integer, Long, Float, Double, MethodHandle, MethodType
- if (arg instanceof DexValue.DexValueString) {
- out.writeByte(0);
- write(((DexValue.DexValueString) arg).value);
- continue;
+ out.writeByte(arg.getValueKind().toByte());
+ switch (arg.getValueKind()) {
+ case DOUBLE:
+ out.writeDouble(arg.asDexValueDouble().value);
+ break;
+ case FLOAT:
+ out.writeFloat(arg.asDexValueFloat().value);
+ break;
+ case INT:
+ out.writeInt(arg.asDexValueInt().value);
+ break;
+ case LONG:
+ out.writeLong(arg.asDexValueLong().value);
+ break;
+ case METHOD_HANDLE:
+ write(arg.asDexValueMethodHandle().value);
+ break;
+ case METHOD_TYPE:
+ write(arg.asDexValueMethodType().value);
+ break;
+ case STRING:
+ write(arg.asDexValueString().value);
+ break;
+ case TYPE:
+ write(arg.asDexValueType().value);
+ break;
+ default:
+ assert false;
}
-
- if (arg instanceof DexValue.DexValueType) {
- out.writeByte(1);
- write(((DexValue.DexValueType) arg).value);
- continue;
- }
-
- if (arg instanceof DexValue.DexValueInt) {
- out.writeByte(2);
- out.writeInt(((DexValue.DexValueInt) arg).value);
- continue;
- }
-
- if (arg instanceof DexValue.DexValueLong) {
- out.writeByte(3);
- out.writeLong(((DexValue.DexValueLong) arg).value);
- continue;
- }
-
- if (arg instanceof DexValue.DexValueFloat) {
- out.writeByte(4);
- out.writeFloat(((DexValue.DexValueFloat) arg).value);
- continue;
- }
-
- if (arg instanceof DexValue.DexValueDouble) {
- out.writeByte(5);
- out.writeDouble(((DexValue.DexValueDouble) arg).value);
- continue;
- }
-
- if (arg instanceof DexValue.DexValueMethodHandle) {
- out.writeByte(6);
- write(((DexValue.DexValueMethodHandle) arg).value);
- continue;
- }
-
- assert arg instanceof DexValue.DexValueMethodType;
- out.writeByte(7);
- write(((DexValue.DexValueMethodType) arg).value);
}
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexClass.java b/src/main/java/com/android/tools/r8/graph/DexClass.java
index 773a71a..85810ed 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClass.java
@@ -85,9 +85,7 @@
this.type = type;
setStaticFields(staticFields);
setInstanceFields(instanceFields);
- this.methodCollection = new MethodCollection(this);
- setDirectMethods(directMethods);
- setVirtualMethods(virtualMethods);
+ this.methodCollection = new MethodCollection(this, directMethods, virtualMethods);
this.nestHost = nestHost;
this.nestMembers = nestMembers;
assert nestMembers != null;
@@ -148,12 +146,8 @@
return Iterables.filter(directMethods(), predicate::test);
}
- public void appendDirectMethod(DexEncodedMethod method) {
- methodCollection.appendDirectMethod(method);
- }
-
- public void appendDirectMethods(Collection<DexEncodedMethod> methods) {
- methodCollection.appendDirectMethods(methods);
+ public void addDirectMethods(Collection<DexEncodedMethod> methods) {
+ methodCollection.addDirectMethods(methods);
}
public void removeDirectMethod(DexMethod method) {
@@ -172,12 +166,8 @@
return Iterables.filter(virtualMethods(), predicate::test);
}
- public void appendVirtualMethod(DexEncodedMethod method) {
- methodCollection.appendVirtualMethod(method);
- }
-
- public void appendVirtualMethods(Collection<DexEncodedMethod> methods) {
- methodCollection.appendVirtualMethods(methods);
+ public void addVirtualMethods(Collection<DexEncodedMethod> methods) {
+ methodCollection.addVirtualMethods(methods);
}
public void setVirtualMethods(DexEncodedMethod[] methods) {
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedField.java b/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
index 8a21e7b..10427a3 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
@@ -7,7 +7,7 @@
import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.dex.MixedSectionCollection;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.analysis.value.SingleValue;
import com.android.tools.r8.ir.code.IRCode;
@@ -207,7 +207,7 @@
return null;
}
if (singleValue.isMaterializableInContext(appView, code.method.method.holder)) {
- TypeLatticeElement type = TypeLatticeElement.fromDexType(field.type, maybeNull(), appView);
+ TypeElement type = TypeElement.fromDexType(field.type, maybeNull(), appView);
return singleValue.createMaterializingInstruction(
appView, code, TypeAndLocalInfoSupplier.create(type, local));
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index 342a3ed..01b0e84 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -1108,6 +1108,7 @@
MethodAccessFlags newFlags = target.accessFlags.copy();
// Some debuggers (like IntelliJ) automatically skip synthetic methods on single step.
newFlags.setSynthetic();
+ newFlags.unsetAbstract();
ForwardMethodSourceCode.Builder forwardSourceCodeBuilder =
ForwardMethodSourceCode.builder(newMethod);
forwardSourceCodeBuilder
diff --git a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
index bfaf19c..30d9369 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
@@ -3,7 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.graph;
-import static com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement.computeLeastUpperBoundOfInterfaces;
+import static com.android.tools.r8.ir.analysis.type.ClassTypeElement.computeLeastUpperBoundOfInterfaces;
import static com.google.common.base.Predicates.alwaysTrue;
import com.android.tools.r8.dex.Constants;
@@ -18,11 +18,11 @@
import com.android.tools.r8.graph.DexDebugEvent.SetInlineFrame;
import com.android.tools.r8.graph.DexDebugEvent.SetPrologueEnd;
import com.android.tools.r8.graph.DexMethodHandle.MethodHandleType;
-import com.android.tools.r8.ir.analysis.type.ArrayTypeLatticeElement;
-import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ArrayTypeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.ReferenceTypeLatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ReferenceTypeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.InvokeMethod;
import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.ir.code.Value;
@@ -82,11 +82,11 @@
private final Map<DexString, SetFile> setFiles = new HashMap<>();
private final Map<SetInlineFrame, SetInlineFrame> setInlineFrames = new HashMap<>();
- // ReferenceTypeLattice canonicalization.
- private final ConcurrentHashMap<DexType, ReferenceTypeLatticeElement>
- referenceTypeLatticeElements = new ConcurrentHashMap<>();
- private final ConcurrentHashMap<DexType, Set<DexType>>
- classTypeLatticeInterfaces = new ConcurrentHashMap<>();
+ // ReferenceTypeElement canonicalization.
+ private final ConcurrentHashMap<DexType, ReferenceTypeElement> referenceTypes =
+ new ConcurrentHashMap<>();
+ private final ConcurrentHashMap<DexType, Set<DexType>> classTypeInterfaces =
+ new ConcurrentHashMap<>();
public final LRUCacheTable<Set<DexType>, Set<DexType>, Set<DexType>>
leastUpperBoundOfInterfacesTable = LRUCacheTable.create(8, 8);
@@ -1201,7 +1201,7 @@
if (invokedMethod == charSequenceConstructor) {
// NullPointerException - if seq is null.
Value seqValue = invoke.inValues().get(1);
- return !seqValue.getTypeLattice().isNullable();
+ return !seqValue.getType().isNullable();
}
if (invokedMethod == defaultConstructor) {
@@ -1220,7 +1220,7 @@
if (invokedMethod == stringConstructor) {
// NullPointerException - if str is null.
Value strValue = invoke.inValues().get(1);
- return !strValue.getTypeLattice().isNullable();
+ return !strValue.getType().isNullable();
}
assert false : "Unexpected invoke targeting `" + invokedMethod.toSourceString() + "`";
@@ -1644,20 +1644,20 @@
return method.name == classConstructorMethodName;
}
- public void clearTypeLatticeElementsCache() {
- referenceTypeLatticeElements.clear();
- classTypeLatticeInterfaces.clear();
+ public void clearTypeElementsCache() {
+ referenceTypes.clear();
+ classTypeInterfaces.clear();
leastUpperBoundOfInterfacesTable.clear();
}
- public boolean verifyNoCachedTypeLatticeElements() {
- assert referenceTypeLatticeElements.isEmpty();
- assert classTypeLatticeInterfaces.isEmpty();
+ public boolean verifyNoCachedTypeElements() {
+ assert referenceTypes.isEmpty();
+ assert classTypeInterfaces.isEmpty();
assert leastUpperBoundOfInterfacesTable.isEmpty();
return true;
}
- public ReferenceTypeLatticeElement createReferenceTypeLatticeElement(
+ public ReferenceTypeElement createReferenceTypeElement(
DexType type, Nullability nullability, AppView<?> appView) {
// Class case:
// If two concurrent threads will try to create the same class-type the concurrent hash map will
@@ -1671,56 +1671,54 @@
// (ii) If base is ArrayLattice case we can use our induction hypothesis to get that only one
// element is created for us up to this case. Threads will now race to return from the
// latest recursive call and fight to get access to .computeIfAbsent to add the
- // ArrayTypeLatticeElement but only one will enter. The property that only one
- // ArrayTypeLatticeElement is created per level therefore holds inductively.
- TypeLatticeElement memberType = null;
+ // ArrayTypeElement but only one will enter. The property that only one
+ // ArrayTypeElement is created per level therefore holds inductively.
+ TypeElement memberType = null;
if (type.isArrayType()) {
- ReferenceTypeLatticeElement existing = referenceTypeLatticeElements.get(type);
+ ReferenceTypeElement existing = referenceTypes.get(type);
if (existing != null) {
return existing.getOrCreateVariant(nullability);
}
memberType =
- TypeLatticeElement.fromDexType(
+ TypeElement.fromDexType(
type.toArrayElementType(this), Nullability.maybeNull(), appView, true);
}
- TypeLatticeElement finalMemberType = memberType;
- return referenceTypeLatticeElements
+ TypeElement finalMemberType = memberType;
+ return referenceTypes
.computeIfAbsent(
type,
t -> {
if (type.isClassType()) {
if (!appView.enableWholeProgramOptimizations()) {
// Don't reason at the level of interfaces in D8.
- return ClassTypeLatticeElement.create(type, nullability, Collections.emptySet());
+ return ClassTypeElement.create(type, nullability, Collections.emptySet());
}
assert appView.appInfo().hasSubtyping();
if (appView.isInterface(type).isTrue()) {
- return ClassTypeLatticeElement.create(
+ return ClassTypeElement.create(
objectType, nullability, Collections.singleton(type));
}
// In theory, `interfaces` is the least upper bound of implemented interfaces.
// It is expensive to walk through type hierarchy; collect implemented interfaces;
// and compute the least upper bound of two interface sets. Hence, lazy
// computations. Most likely during lattice join. See {@link
- // ClassTypeLatticeElement#getInterfaces}.
- return ClassTypeLatticeElement.create(type, nullability, appView.withSubtyping());
+ // ClassTypeElement#getInterfaces}.
+ return ClassTypeElement.create(type, nullability, appView.withSubtyping());
}
assert type.isArrayType();
- return ArrayTypeLatticeElement.create(finalMemberType, nullability);
+ return ArrayTypeElement.create(finalMemberType, nullability);
})
.getOrCreateVariant(nullability);
}
public Set<DexType> getOrComputeLeastUpperBoundOfImplementedInterfaces(
DexType type, AppView<? extends AppInfoWithSubtyping> appView) {
- return classTypeLatticeInterfaces
- .computeIfAbsent(
- type,
- t -> {
- Set<DexType> itfs = appView.appInfo().implementedInterfaces(t);
- return computeLeastUpperBoundOfInterfaces(appView, itfs, itfs);
- }
- );
+ return classTypeInterfaces.computeIfAbsent(
+ type,
+ t -> {
+ Set<DexType> itfs = appView.appInfo().implementedInterfaces(t);
+ return computeLeastUpperBoundOfInterfaces(appView, itfs, itfs);
+ });
}
synchronized public void forAllTypes(Consumer<DexType> f) {
diff --git a/src/main/java/com/android/tools/r8/graph/DexType.java b/src/main/java/com/android/tools/r8/graph/DexType.java
index 4b8c6d4..01c5298 100644
--- a/src/main/java/com/android/tools/r8/graph/DexType.java
+++ b/src/main/java/com/android/tools/r8/graph/DexType.java
@@ -16,6 +16,7 @@
import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.ir.desugar.BackportedMethodRewriter;
+import com.android.tools.r8.ir.desugar.DesugaredLibraryRetargeter;
import com.android.tools.r8.ir.desugar.NestBasedAccessDesugaring;
import com.android.tools.r8.ir.desugar.TwrCloseResourceRewriter;
import com.android.tools.r8.ir.optimize.ServiceLoaderRewriter;
@@ -44,8 +45,7 @@
private String toStringCache = null;
DexType(DexString descriptor) {
- assert !descriptor.toString().contains(".")
- : "Malformed descriptor: " + descriptor.toString();
+ assert !descriptor.toString().contains(".") : "Malformed descriptor: " + descriptor.toString();
this.descriptor = descriptor;
}
@@ -145,11 +145,12 @@
}
@Override
- public void collectIndexedItems(IndexedItemCollection collection,
- DexMethod method, int instructionOffset) {
+ public void collectIndexedItems(
+ IndexedItemCollection collection, DexMethod method, int instructionOffset) {
if (collection.addType(this)) {
- collection.getRenamedDescriptor(this).collectIndexedItems(collection, method,
- instructionOffset);
+ collection
+ .getRenamedDescriptor(this)
+ .collectIndexedItems(collection, method, instructionOffset);
}
}
@@ -272,6 +273,7 @@
|| name.contains(TwrCloseResourceRewriter.UTILITY_CLASS_NAME)
|| name.contains(NestBasedAccessDesugaring.NEST_CONSTRUCTOR_NAME)
|| name.contains(BackportedMethodRewriter.UTILITY_CLASS_NAME_PREFIX)
+ || name.contains(DesugaredLibraryRetargeter.DESUGAR_LIB_RETARGET_CLASS_NAME_PREFIX)
|| name.contains(ServiceLoaderRewriter.SERVICE_LOADER_CLASS_NAME)
|| oldSynthesizedName(name);
}
@@ -298,17 +300,17 @@
public int elementSizeForPrimitiveArrayType() {
assert isPrimitiveArrayType();
switch (descriptor.content[1]) {
- case 'Z': // boolean
- case 'B': // byte
+ case 'Z': // boolean
+ case 'B': // byte
return 1;
- case 'S': // short
- case 'C': // char
+ case 'S': // short
+ case 'C': // char
return 2;
- case 'I': // int
- case 'F': // float
+ case 'I': // int
+ case 'F': // float
return 4;
- case 'J': // long
- case 'D': // double
+ case 'J': // long
+ case 'D': // double
return 8;
default:
throw new Unreachable("Not array of primitives '" + descriptor + "'");
@@ -328,8 +330,11 @@
if (leadingSquareBrackets == 0) {
return this;
}
- DexString newDesc = dexItemFactory.createString(descriptor.size - leadingSquareBrackets,
- Arrays.copyOfRange(descriptor.content, leadingSquareBrackets, descriptor.content.length));
+ DexString newDesc =
+ dexItemFactory.createString(
+ descriptor.size - leadingSquareBrackets,
+ Arrays.copyOfRange(
+ descriptor.content, leadingSquareBrackets, descriptor.content.length));
return dexItemFactory.createType(newDesc);
}
@@ -364,8 +369,10 @@
public DexType toArrayElementType(DexItemFactory dexItemFactory) {
assert this.isArrayType();
- DexString newDesc = dexItemFactory.createString(descriptor.size - 1,
- Arrays.copyOfRange(descriptor.content, 1, descriptor.content.length));
+ DexString newDesc =
+ dexItemFactory.createString(
+ descriptor.size - 1,
+ Arrays.copyOfRange(descriptor.content, 1, descriptor.content.length));
return dexItemFactory.createType(newDesc);
}
@@ -376,7 +383,8 @@
if (lastSeparator == -1) {
return packagePart ? "" : descriptor.substring(1, descriptor.length() - 1);
} else {
- return packagePart ? descriptor.substring(1, lastSeparator)
+ return packagePart
+ ? descriptor.substring(1, lastSeparator)
: descriptor.substring(lastSeparator + 1, descriptor.length() - 1);
}
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexValue.java b/src/main/java/com/android/tools/r8/graph/DexValue.java
index be0cf37..bab3c75 100644
--- a/src/main/java/com/android/tools/r8/graph/DexValue.java
+++ b/src/main/java/com/android/tools/r8/graph/DexValue.java
@@ -10,7 +10,7 @@
import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.dex.MixedSectionCollection;
import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.BasicBlock.ThrowingInfo;
import com.android.tools.r8.ir.code.ConstInstruction;
import com.android.tools.r8.ir.code.ConstString;
@@ -102,6 +102,8 @@
public static final DexValue[] EMPTY_ARRAY = {};
+ public abstract DexValueKind getValueKind();
+
public boolean isDexItemBasedValueString() {
return false;
}
@@ -110,14 +112,30 @@
return null;
}
+ public boolean isDexValueMethodHandle() {
+ return false;
+ }
+
public DexValueMethodHandle asDexValueMethodHandle() {
return null;
}
+ public boolean isDexValueMethodType() {
+ return false;
+ }
+
public DexValueMethodType asDexValueMethodType() {
return null;
}
+ public boolean isDexValueAnnotation() {
+ return false;
+ }
+
+ public DexValueAnnotation asDexValueAnnotation() {
+ return null;
+ }
+
public boolean isDexValueArray() {
return false;
}
@@ -158,6 +176,22 @@
return null;
}
+ public boolean isDexValueEnum() {
+ return false;
+ }
+
+ public DexValueEnum asDexValueEnum() {
+ return null;
+ }
+
+ public boolean isDexValueField() {
+ return false;
+ }
+
+ public DexValueField asDexValueField() {
+ return null;
+ }
+
public boolean isDexValueFloat() {
return false;
}
@@ -182,6 +216,14 @@
return null;
}
+ public boolean isDexValueMethod() {
+ return false;
+ }
+
+ public DexValueMethod asDexValueMethod() {
+ return null;
+ }
+
public boolean isDexValueNull() {
return false;
}
@@ -392,6 +434,11 @@
}
@Override
+ public DexValueKind getValueKind() {
+ return DexValueKind.BYTE;
+ }
+
+ @Override
public DexType getType(DexItemFactory factory) {
return factory.byteType;
}
@@ -470,6 +517,11 @@
}
@Override
+ public DexValueKind getValueKind() {
+ return DexValueKind.SHORT;
+ }
+
+ @Override
public DexType getType(DexItemFactory factory) {
return factory.shortType;
}
@@ -547,6 +599,11 @@
}
@Override
+ public DexValueKind getValueKind() {
+ return DexValueKind.CHAR;
+ }
+
+ @Override
public DexType getType(DexItemFactory factory) {
return factory.charType;
}
@@ -628,6 +685,11 @@
}
@Override
+ public DexValueKind getValueKind() {
+ return DexValueKind.INT;
+ }
+
+ @Override
public DexType getType(DexItemFactory factory) {
return factory.intType;
}
@@ -705,6 +767,11 @@
}
@Override
+ public DexValueKind getValueKind() {
+ return DexValueKind.LONG;
+ }
+
+ @Override
public DexType getType(DexItemFactory factory) {
return factory.longType;
}
@@ -782,6 +849,11 @@
}
@Override
+ public DexValueKind getValueKind() {
+ return DexValueKind.FLOAT;
+ }
+
+ @Override
public DexType getType(DexItemFactory factory) {
return factory.floatType;
}
@@ -836,8 +908,8 @@
if (other == this) {
return true;
}
- return (other instanceof DexValueFloat) &&
- (Float.compare(value, ((DexValueFloat) other).value) == 0);
+ return other instanceof DexValueFloat
+ && Float.compare(value, ((DexValueFloat) other).value) == 0;
}
@Override
@@ -865,6 +937,11 @@
}
@Override
+ public DexValueKind getValueKind() {
+ return DexValueKind.DOUBLE;
+ }
+
+ @Override
public DexType getType(DexItemFactory factory) {
return factory.doubleType;
}
@@ -937,8 +1014,6 @@
this.value = value;
}
- protected abstract DexValueKind getValueKind();
-
@Override
public DexType getType(DexItemFactory factory) {
throw new Unreachable();
@@ -1024,7 +1099,7 @@
}
@Override
- protected DexValueKind getValueKind() {
+ public DexValueKind getValueKind() {
return DexValueKind.STRING;
}
@@ -1036,7 +1111,7 @@
@Override
public ConstInstruction asConstInstruction(
AppView<? extends AppInfoWithSubtyping> appView, IRCode code, DebugLocalInfo local) {
- TypeLatticeElement type = TypeLatticeElement.stringClassType(appView, definitelyNotNull());
+ TypeElement type = TypeElement.stringClassType(appView, definitelyNotNull());
Value outValue = code.createValue(type, local);
ConstString instruction =
new ConstString(outValue, value, ThrowingInfo.defaultForConstString(appView.options()));
@@ -1082,7 +1157,7 @@
}
@Override
- protected DexValueKind getValueKind() {
+ public DexValueKind getValueKind() {
return DexValueKind.STRING;
}
@@ -1094,7 +1169,7 @@
@Override
public ConstInstruction asConstInstruction(
AppView<? extends AppInfoWithSubtyping> appView, IRCode code, DebugLocalInfo local) {
- TypeLatticeElement type = TypeLatticeElement.stringClassType(appView, definitelyNotNull());
+ TypeElement type = TypeElement.stringClassType(appView, definitelyNotNull());
Value outValue = code.createValue(type, local);
DexItemBasedConstString instruction =
new DexItemBasedConstString(
@@ -1121,7 +1196,7 @@
}
@Override
- protected DexValueKind getValueKind() {
+ public DexValueKind getValueKind() {
return DexValueKind.TYPE;
}
@@ -1149,7 +1224,7 @@
}
@Override
- protected DexValueKind getValueKind() {
+ public DexValueKind getValueKind() {
return DexValueKind.FIELD;
}
@@ -1158,6 +1233,16 @@
IndexedItemCollection indexedItems, DexMethod method, int instructionOffset) {
value.collectIndexedItems(indexedItems, method, instructionOffset);
}
+
+ @Override
+ public boolean isDexValueField() {
+ return true;
+ }
+
+ @Override
+ public DexValueField asDexValueField() {
+ return this;
+ }
}
static public class DexValueMethod extends NestedDexValue<DexMethod> {
@@ -1167,7 +1252,7 @@
}
@Override
- protected DexValueKind getValueKind() {
+ public DexValueKind getValueKind() {
return DexValueKind.METHOD;
}
@@ -1176,6 +1261,16 @@
IndexedItemCollection indexedItems, DexMethod method, int instructionOffset) {
value.collectIndexedItems(indexedItems, method, instructionOffset);
}
+
+ @Override
+ public boolean isDexValueMethod() {
+ return true;
+ }
+
+ @Override
+ public DexValueMethod asDexValueMethod() {
+ return this;
+ }
}
static public class DexValueEnum extends NestedDexValue<DexField> {
@@ -1185,7 +1280,7 @@
}
@Override
- protected DexValueKind getValueKind() {
+ public DexValueKind getValueKind() {
return DexValueKind.ENUM;
}
@@ -1194,6 +1289,16 @@
IndexedItemCollection indexedItems, DexMethod method, int instructionOffset) {
value.collectIndexedItems(indexedItems, method, instructionOffset);
}
+
+ @Override
+ public boolean isDexValueEnum() {
+ return true;
+ }
+
+ @Override
+ public DexValueEnum asDexValueEnum() {
+ return this;
+ }
}
static public class DexValueMethodType extends NestedDexValue<DexProto> {
@@ -1203,12 +1308,17 @@
}
@Override
+ public boolean isDexValueMethodType() {
+ return true;
+ }
+
+ @Override
public DexValueMethodType asDexValueMethodType() {
return this;
}
@Override
- protected DexValueKind getValueKind() {
+ public DexValueKind getValueKind() {
return DexValueKind.METHOD_TYPE;
}
@@ -1232,6 +1342,11 @@
}
@Override
+ public DexValueKind getValueKind() {
+ return DexValueKind.ARRAY;
+ }
+
+ @Override
public void collectIndexedItems(IndexedItemCollection indexedItems,
DexMethod method, int instructionOffset) {
collectAll(indexedItems, values);
@@ -1310,6 +1425,21 @@
}
@Override
+ public DexValueKind getValueKind() {
+ return DexValueKind.ANNOTATION;
+ }
+
+ @Override
+ public boolean isDexValueAnnotation() {
+ return true;
+ }
+
+ @Override
+ public DexValueAnnotation asDexValueAnnotation() {
+ return this;
+ }
+
+ @Override
public void collectIndexedItems(IndexedItemCollection indexedItems,
DexMethod method, int instructionOffset) {
value.collectIndexedItems(indexedItems, method, instructionOffset);
@@ -1377,6 +1507,11 @@
}
@Override
+ public DexValueKind getValueKind() {
+ return DexValueKind.NULL;
+ }
+
+ @Override
public DexType getType(DexItemFactory factory) {
throw new Unreachable();
}
@@ -1421,7 +1556,7 @@
if (other == this) {
return true;
}
- return (other instanceof DexValueNull);
+ return other instanceof DexValueNull;
}
@Override
@@ -1458,6 +1593,11 @@
}
@Override
+ public DexValueKind getValueKind() {
+ return DexValueKind.BOOLEAN;
+ }
+
+ @Override
public DexType getType(DexItemFactory factory) {
return factory.booleanType;
}
@@ -1502,7 +1642,7 @@
if (other == this) {
return true;
}
- return (other instanceof DexValueBoolean) && ((DexValueBoolean) other).value == value;
+ return other instanceof DexValueBoolean && ((DexValueBoolean) other).value == value;
}
@Override
@@ -1524,12 +1664,17 @@
}
@Override
+ public boolean isDexValueMethodHandle() {
+ return true;
+ }
+
+ @Override
public DexValueMethodHandle asDexValueMethodHandle() {
return this;
}
@Override
- protected DexValueKind getValueKind() {
+ public DexValueKind getValueKind() {
return DexValueKind.METHOD_HANDLE;
}
diff --git a/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java b/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java
index b8210c8..03c329c 100644
--- a/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java
+++ b/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java
@@ -243,7 +243,7 @@
return self();
}
- public Builder addClasspathClasses(List<DexClasspathClass> classes) {
+ public Builder addClasspathClasses(Collection<DexClasspathClass> classes) {
classpathClasses =
ImmutableList.<DexClasspathClass>builder()
.addAll(classpathClasses)
diff --git a/src/main/java/com/android/tools/r8/graph/MethodArrayBacking.java b/src/main/java/com/android/tools/r8/graph/MethodArrayBacking.java
index 7800d81a..4eda679 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodArrayBacking.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodArrayBacking.java
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.graph;
-import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.PredicateUtils;
import com.android.tools.r8.utils.TraversalContinuation;
import com.google.common.base.MoreObjects;
@@ -11,7 +10,6 @@
import com.google.common.collect.Sets;
import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
@@ -22,16 +20,23 @@
private DexEncodedMethod[] directMethods = DexEncodedMethod.EMPTY_ARRAY;
private DexEncodedMethod[] virtualMethods = DexEncodedMethod.EMPTY_ARRAY;
- private boolean belongsToDirectPool(DexEncodedMethod method) {
- return method.accessFlags.isStatic()
- || method.accessFlags.isPrivate()
- || method.accessFlags.isConstructor();
+ private boolean verifyNoDuplicateMethods() {
+ Set<DexMethod> unique = Sets.newIdentityHashSet();
+ forEachMethod(
+ method -> {
+ boolean changed = unique.add(method.method);
+ assert changed : "Duplicate method `" + method.method.toSourceString() + "`";
+ });
+ return true;
}
- private boolean belongsToVirtualPool(DexEncodedMethod method) {
- return !belongsToDirectPool(method);
+ @Override
+ boolean verify() {
+ assert verifyNoDuplicateMethods();
+ return true;
}
+ @Override
int size() {
return directMethods.length + virtualMethods.length;
}
@@ -53,27 +58,19 @@
return TraversalContinuation.CONTINUE;
}
+ @Override
public Iterable<DexEncodedMethod> methods() {
return Iterables.concat(Arrays.asList(directMethods), Arrays.asList(virtualMethods));
}
+ @Override
List<DexEncodedMethod> directMethods() {
assert directMethods != null;
- if (InternalOptions.assertionsEnabled()) {
- return Collections.unmodifiableList(Arrays.asList(directMethods));
- }
return Arrays.asList(directMethods);
}
- void appendDirectMethod(DexEncodedMethod method) {
- DexEncodedMethod[] newMethods = new DexEncodedMethod[directMethods.length + 1];
- System.arraycopy(directMethods, 0, newMethods, 0, directMethods.length);
- newMethods[directMethods.length] = method;
- directMethods = newMethods;
- assert verifyNoDuplicateMethods();
- }
-
- void appendDirectMethods(Collection<DexEncodedMethod> methods) {
+ @Override
+ void addDirectMethods(Collection<DexEncodedMethod> methods) {
DexEncodedMethod[] newMethods = new DexEncodedMethod[directMethods.length + methods.size()];
System.arraycopy(directMethods, 0, newMethods, 0, directMethods.length);
int i = directMethods.length;
@@ -92,6 +89,7 @@
directMethods = newMethods;
}
+ @Override
void removeDirectMethod(DexMethod method) {
int index = -1;
for (int i = 0; i < directMethods.length; i++) {
@@ -105,33 +103,20 @@
}
}
- void setDirectMethod(int index, DexEncodedMethod method) {
- directMethods[index] = method;
- assert verifyNoDuplicateMethods();
- }
-
+ @Override
void setDirectMethods(DexEncodedMethod[] methods) {
directMethods = MoreObjects.firstNonNull(methods, DexEncodedMethod.EMPTY_ARRAY);
assert verifyNoDuplicateMethods();
}
+ @Override
List<DexEncodedMethod> virtualMethods() {
assert virtualMethods != null;
- if (InternalOptions.assertionsEnabled()) {
- return Collections.unmodifiableList(Arrays.asList(virtualMethods));
- }
return Arrays.asList(virtualMethods);
}
- void appendVirtualMethod(DexEncodedMethod method) {
- DexEncodedMethod[] newMethods = new DexEncodedMethod[virtualMethods.length + 1];
- System.arraycopy(virtualMethods, 0, newMethods, 0, virtualMethods.length);
- newMethods[virtualMethods.length] = method;
- virtualMethods = newMethods;
- assert verifyNoDuplicateMethods();
- }
-
- void appendVirtualMethods(Collection<DexEncodedMethod> methods) {
+ @Override
+ void addVirtualMethods(Collection<DexEncodedMethod> methods) {
DexEncodedMethod[] newMethods = new DexEncodedMethod[virtualMethods.length + methods.size()];
System.arraycopy(virtualMethods, 0, newMethods, 0, virtualMethods.length);
int i = virtualMethods.length;
@@ -143,11 +128,13 @@
assert verifyNoDuplicateMethods();
}
+ @Override
void setVirtualMethods(DexEncodedMethod[] methods) {
virtualMethods = MoreObjects.firstNonNull(methods, DexEncodedMethod.EMPTY_ARRAY);
assert verifyNoDuplicateMethods();
}
+ @Override
void virtualizeMethods(Set<DexEncodedMethod> privateInstanceMethods) {
int vLen = virtualMethods.length;
int dLen = directMethods.length;
@@ -174,6 +161,7 @@
setVirtualMethods(newVirtualMethods);
}
+ @Override
DexEncodedMethod getDirectMethod(DexMethod method) {
for (DexEncodedMethod directMethod : directMethods) {
if (method.match(directMethod)) {
@@ -183,10 +171,12 @@
return null;
}
+ @Override
DexEncodedMethod getDirectMethod(Predicate<DexEncodedMethod> predicate) {
return PredicateUtils.findFirst(directMethods, predicate);
}
+ @Override
DexEncodedMethod getVirtualMethod(DexMethod method) {
for (DexEncodedMethod virtualMethod : virtualMethods) {
if (method.match(virtualMethod)) {
@@ -196,51 +186,41 @@
return null;
}
+ @Override
DexEncodedMethod getVirtualMethod(Predicate<DexEncodedMethod> predicate) {
return PredicateUtils.findFirst(virtualMethods, predicate);
}
+ @Override
DexEncodedMethod getMethod(DexMethod method) {
DexEncodedMethod result = getDirectMethod(method);
return result == null ? getVirtualMethod(method) : result;
}
+ @Override
void addMethod(DexEncodedMethod method) {
- if (method.accessFlags.isStatic()
- || method.accessFlags.isPrivate()
- || method.accessFlags.isConstructor()) {
+ if (belongsToDirectPool(method)) {
addDirectMethod(method);
} else {
addVirtualMethod(method);
}
}
+ @Override
void addVirtualMethod(DexEncodedMethod virtualMethod) {
- assert !virtualMethod.accessFlags.isStatic();
- assert !virtualMethod.accessFlags.isPrivate();
- assert !virtualMethod.accessFlags.isConstructor();
+ assert belongsToVirtualPool(virtualMethod);
virtualMethods = Arrays.copyOf(virtualMethods, virtualMethods.length + 1);
virtualMethods[virtualMethods.length - 1] = virtualMethod;
}
- void addDirectMethod(DexEncodedMethod staticMethod) {
- assert staticMethod.accessFlags.isStatic()
- || staticMethod.accessFlags.isPrivate()
- || staticMethod.accessFlags.isConstructor();
+ @Override
+ void addDirectMethod(DexEncodedMethod directMethod) {
+ assert belongsToDirectPool(directMethod);
directMethods = Arrays.copyOf(directMethods, directMethods.length + 1);
- directMethods[directMethods.length - 1] = staticMethod;
+ directMethods[directMethods.length - 1] = directMethod;
}
- boolean verifyNoDuplicateMethods() {
- Set<DexMethod> unique = Sets.newIdentityHashSet();
- forEachMethod(
- method -> {
- boolean changed = unique.add(method.method);
- assert changed : "Duplicate method `" + method.method.toSourceString() + "`";
- });
- return true;
- }
-
+ @Override
public DexEncodedMethod replaceDirectMethod(
DexMethod method, Function<DexEncodedMethod, DexEncodedMethod> replacement) {
for (int i = 0; i < directMethods.length; i++) {
@@ -255,6 +235,7 @@
return null;
}
+ @Override
public DexEncodedMethod replaceDirectMethodWithVirtualMethod(
DexMethod method, Function<DexEncodedMethod, DexEncodedMethod> replacement) {
for (int i = 0; i < directMethods.length; i++) {
@@ -263,18 +244,20 @@
DexEncodedMethod newMethod = replacement.apply(directMethod);
assert belongsToVirtualPool(newMethod);
removeDirectMethod(i);
- appendVirtualMethod(newMethod);
+ addVirtualMethod(newMethod);
return newMethod;
}
}
return null;
}
+ @Override
public void replaceMethods(Function<DexEncodedMethod, DexEncodedMethod> replacement) {
replaceDirectMethods(replacement);
replaceVirtualMethods(replacement);
}
+ @Override
public void replaceDirectMethods(Function<DexEncodedMethod, DexEncodedMethod> replacement) {
for (int i = 0; i < directMethods.length; i++) {
DexEncodedMethod method = directMethods[i];
@@ -287,6 +270,7 @@
}
}
+ @Override
public void replaceVirtualMethods(Function<DexEncodedMethod, DexEncodedMethod> replacement) {
for (int i = 0; i < virtualMethods.length; i++) {
DexEncodedMethod method = virtualMethods[i];
diff --git a/src/main/java/com/android/tools/r8/graph/MethodCollection.java b/src/main/java/com/android/tools/r8/graph/MethodCollection.java
index a4f3d5a..269b36b 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodCollection.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodCollection.java
@@ -1,12 +1,13 @@
package com.android.tools.r8.graph;
+import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.IterableUtils;
import com.android.tools.r8.utils.TraversalContinuation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
-import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
@@ -14,12 +15,37 @@
public class MethodCollection {
- private final DexClass holder;
- private final MethodArrayBacking backing = new MethodArrayBacking();
- private Optional<DexEncodedMethod> cachedClassInitializer = null;
+ // Threshold between using an array and a map for the backing store.
+ // Compiling R8 plus library shows classes with up to 30 methods account for about 95% of classes.
+ private static final int ARRAY_BACKING_THRESHOLD = 30;
- public MethodCollection(DexClass holder) {
+ private final DexClass holder;
+ private final MethodCollectionBacking backing;
+ private DexEncodedMethod cachedClassInitializer = DexEncodedMethod.SENTINEL;
+
+ public MethodCollection(
+ DexClass holder, DexEncodedMethod[] directMethods, DexEncodedMethod[] virtualMethods) {
this.holder = holder;
+ if (directMethods.length + virtualMethods.length > ARRAY_BACKING_THRESHOLD) {
+ backing = new MethodMapBacking();
+ } else {
+ backing = new MethodArrayBacking();
+ }
+ backing.setDirectMethods(directMethods);
+ backing.setVirtualMethods(virtualMethods);
+ }
+
+ private void resetCaches() {
+ resetDirectMethodCaches();
+ resetVirtualMethodCaches();
+ }
+
+ private void resetDirectMethodCaches() {
+ resetClassInitializerCache();
+ }
+
+ private void resetVirtualMethodCaches() {
+ // Nothing to do.
}
public int size() {
@@ -50,10 +76,16 @@
}
public List<DexEncodedMethod> directMethods() {
+ if (InternalOptions.assertionsEnabled()) {
+ return Collections.unmodifiableList(backing.directMethods());
+ }
return backing.directMethods();
}
public List<DexEncodedMethod> virtualMethods() {
+ if (InternalOptions.assertionsEnabled()) {
+ return Collections.unmodifiableList(backing.virtualMethods());
+ }
return backing.virtualMethods();
}
@@ -77,48 +109,56 @@
return backing.getVirtualMethod(predicate);
}
+ private void resetClassInitializerCache() {
+ cachedClassInitializer = DexEncodedMethod.SENTINEL;
+ }
+
public DexEncodedMethod getClassInitializer() {
- if (cachedClassInitializer == null) {
- cachedClassInitializer = Optional.empty();
+ if (cachedClassInitializer == DexEncodedMethod.SENTINEL) {
+ cachedClassInitializer = null;
for (DexEncodedMethod directMethod : directMethods()) {
if (directMethod.isClassInitializer()) {
- cachedClassInitializer = Optional.of(directMethod);
+ cachedClassInitializer = directMethod;
break;
}
}
}
- return cachedClassInitializer.orElse(null);
+ return cachedClassInitializer;
}
public void addMethod(DexEncodedMethod method) {
+ resetCaches();
backing.addMethod(method);
}
public void addVirtualMethod(DexEncodedMethod virtualMethod) {
+ resetVirtualMethodCaches();
backing.addVirtualMethod(virtualMethod);
}
public void addDirectMethod(DexEncodedMethod directMethod) {
- cachedClassInitializer = null;
+ resetDirectMethodCaches();
backing.addDirectMethod(directMethod);
}
public DexEncodedMethod replaceDirectMethod(
DexMethod method, Function<DexEncodedMethod, DexEncodedMethod> replacement) {
- cachedClassInitializer = null;
+ resetDirectMethodCaches();
return backing.replaceDirectMethod(method, replacement);
}
public void replaceMethods(Function<DexEncodedMethod, DexEncodedMethod> replacement) {
+ resetCaches();
backing.replaceMethods(replacement);
}
public void replaceVirtualMethods(Function<DexEncodedMethod, DexEncodedMethod> replacement) {
+ resetVirtualMethodCaches();
backing.replaceVirtualMethods(replacement);
}
public void replaceDirectMethods(Function<DexEncodedMethod, DexEncodedMethod> replacement) {
- cachedClassInitializer = null;
+ resetDirectMethodCaches();
backing.replaceDirectMethods(replacement);
}
@@ -131,49 +171,41 @@
*/
public DexEncodedMethod replaceDirectMethodWithVirtualMethod(
DexMethod method, Function<DexEncodedMethod, DexEncodedMethod> replacement) {
- // The class initializer can never by converted to a virtual.
+ resetCaches();
return backing.replaceDirectMethodWithVirtualMethod(method, replacement);
}
- public void appendDirectMethod(DexEncodedMethod method) {
- assert verifyCorrectnessOfMethodHolder(method);
- cachedClassInitializer = null;
- backing.appendDirectMethod(method);
- }
-
- public void appendDirectMethods(Collection<DexEncodedMethod> methods) {
+ public void addDirectMethods(Collection<DexEncodedMethod> methods) {
assert verifyCorrectnessOfMethodHolders(methods);
- cachedClassInitializer = null;
- backing.appendDirectMethods(methods);
+ resetDirectMethodCaches();
+ backing.addDirectMethods(methods);
}
public void removeDirectMethod(DexMethod method) {
- cachedClassInitializer = null;
+ resetDirectMethodCaches();
backing.removeDirectMethod(method);
}
public void setDirectMethods(DexEncodedMethod[] methods) {
assert verifyCorrectnessOfMethodHolders(methods);
- cachedClassInitializer = null;
+ resetDirectMethodCaches();
backing.setDirectMethods(methods);
}
- public void appendVirtualMethod(DexEncodedMethod method) {
- assert verifyCorrectnessOfMethodHolder(method);
- backing.appendVirtualMethod(method);
- }
-
- public void appendVirtualMethods(Collection<DexEncodedMethod> methods) {
+ public void addVirtualMethods(Collection<DexEncodedMethod> methods) {
assert verifyCorrectnessOfMethodHolders(methods);
- backing.appendVirtualMethods(methods);
+ resetVirtualMethodCaches();
+ backing.addVirtualMethods(methods);
}
public void setVirtualMethods(DexEncodedMethod[] methods) {
assert verifyCorrectnessOfMethodHolders(methods);
+ resetVirtualMethodCaches();
backing.setVirtualMethods(methods);
}
public void virtualizeMethods(Set<DexEncodedMethod> privateInstanceMethods) {
+ resetVirtualMethodCaches();
backing.virtualizeMethods(privateInstanceMethods);
}
@@ -191,7 +223,7 @@
method -> {
assert verifyCorrectnessOfMethodHolder(method);
});
- assert backing.verifyNoDuplicateMethods();
+ assert backing.verify();
return true;
}
diff --git a/src/main/java/com/android/tools/r8/graph/MethodCollectionBacking.java b/src/main/java/com/android/tools/r8/graph/MethodCollectionBacking.java
index b50adf6..427f022 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodCollectionBacking.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodCollectionBacking.java
@@ -4,11 +4,35 @@
package com.android.tools.r8.graph;
import com.android.tools.r8.utils.TraversalContinuation;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
+import java.util.function.Predicate;
public abstract class MethodCollectionBacking {
+ // Internal consistency.
+
+ abstract boolean verify();
+
+ boolean belongsToDirectPool(DexEncodedMethod method) {
+ return method.accessFlags.isStatic()
+ || method.accessFlags.isPrivate()
+ || method.accessFlags.isConstructor();
+ }
+
+ boolean belongsToVirtualPool(DexEncodedMethod method) {
+ return !belongsToDirectPool(method);
+ }
+
+ // Collection methods.
+
+ abstract int size();
+
+ // Traversal methods.
+
abstract TraversalContinuation traverse(Function<DexEncodedMethod, TraversalContinuation> fn);
void forEachMethod(Consumer<DexEncodedMethod> fn) {
@@ -18,4 +42,58 @@
return TraversalContinuation.CONTINUE;
});
}
+
+ abstract Iterable<DexEncodedMethod> methods();
+
+ abstract List<DexEncodedMethod> directMethods();
+
+ abstract List<DexEncodedMethod> virtualMethods();
+
+ // Lookup methods.
+
+ abstract DexEncodedMethod getMethod(DexMethod method);
+
+ abstract DexEncodedMethod getDirectMethod(DexMethod method);
+
+ abstract DexEncodedMethod getDirectMethod(Predicate<DexEncodedMethod> predicate);
+
+ abstract DexEncodedMethod getVirtualMethod(DexMethod method);
+
+ abstract DexEncodedMethod getVirtualMethod(Predicate<DexEncodedMethod> predicate);
+
+ // Amendment methods.
+
+ abstract void addMethod(DexEncodedMethod method);
+
+ abstract void addDirectMethod(DexEncodedMethod method);
+
+ abstract void addVirtualMethod(DexEncodedMethod method);
+
+ abstract void addDirectMethods(Collection<DexEncodedMethod> methods);
+
+ abstract void addVirtualMethods(Collection<DexEncodedMethod> methods);
+
+ // Removal methods.
+
+ abstract void removeDirectMethod(DexMethod method);
+
+ // Replacement/mutation methods.
+
+ abstract void setDirectMethods(DexEncodedMethod[] methods);
+
+ abstract void setVirtualMethods(DexEncodedMethod[] methods);
+
+ abstract void replaceMethods(Function<DexEncodedMethod, DexEncodedMethod> replacement);
+
+ abstract void replaceDirectMethods(Function<DexEncodedMethod, DexEncodedMethod> replacement);
+
+ abstract void replaceVirtualMethods(Function<DexEncodedMethod, DexEncodedMethod> replacement);
+
+ abstract DexEncodedMethod replaceDirectMethod(
+ DexMethod method, Function<DexEncodedMethod, DexEncodedMethod> replacement);
+
+ abstract DexEncodedMethod replaceDirectMethodWithVirtualMethod(
+ DexMethod method, Function<DexEncodedMethod, DexEncodedMethod> replacement);
+
+ abstract void virtualizeMethods(Set<DexEncodedMethod> privateInstanceMethods);
}
diff --git a/src/main/java/com/android/tools/r8/graph/MethodMapBacking.java b/src/main/java/com/android/tools/r8/graph/MethodMapBacking.java
new file mode 100644
index 0000000..8afffc6
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/MethodMapBacking.java
@@ -0,0 +1,306 @@
+// 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.graph;
+
+import com.android.tools.r8.utils.Box;
+import com.android.tools.r8.utils.MethodSignatureEquivalence;
+import com.android.tools.r8.utils.TraversalContinuation;
+import com.google.common.base.Equivalence.Wrapper;
+import it.unimi.dsi.fastutil.objects.Object2ReferenceLinkedOpenHashMap;
+import it.unimi.dsi.fastutil.objects.Object2ReferenceMap;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+public class MethodMapBacking extends MethodCollectionBacking {
+
+ private Object2ReferenceMap<Wrapper<DexMethod>, DexEncodedMethod> methodMap;
+
+ public MethodMapBacking() {
+ this.methodMap = createMap();
+ }
+
+ private static Object2ReferenceMap<Wrapper<DexMethod>, DexEncodedMethod> createMap() {
+ // Maintain a linked map so the output order remains a deterministic function of the input.
+ return new Object2ReferenceLinkedOpenHashMap<>();
+ }
+
+ private static Object2ReferenceMap<Wrapper<DexMethod>, DexEncodedMethod> createMap(int capacity) {
+ // Maintain a linked map so the output order remains a deterministic function of the input.
+ return new Object2ReferenceLinkedOpenHashMap<>(capacity);
+ }
+
+ private Wrapper<DexMethod> wrap(DexMethod method) {
+ return MethodSignatureEquivalence.get().wrap(method);
+ }
+
+ private void replace(Wrapper<DexMethod> existingKey, DexEncodedMethod method) {
+ if (existingKey.get().match(method)) {
+ methodMap.put(existingKey, method);
+ } else {
+ methodMap.remove(existingKey);
+ methodMap.put(wrap(method.method), method);
+ }
+ }
+
+ private void rehash() {
+ Object2ReferenceMap<Wrapper<DexMethod>, DexEncodedMethod> newMap = createMap(methodMap.size());
+ for (DexEncodedMethod method : methodMap.values()) {
+ newMap.put(wrap(method.method), method);
+ }
+ methodMap = newMap;
+ }
+
+ @Override
+ boolean verify() {
+ methodMap.forEach(
+ (key, method) -> {
+ assert key.get().match(method);
+ });
+ return true;
+ }
+
+ @Override
+ int size() {
+ return methodMap.size();
+ }
+
+ @Override
+ TraversalContinuation traverse(Function<DexEncodedMethod, TraversalContinuation> fn) {
+ for (Entry<Wrapper<DexMethod>, DexEncodedMethod> entry : methodMap.object2ReferenceEntrySet()) {
+ TraversalContinuation result = fn.apply(entry.getValue());
+ if (result.shouldBreak()) {
+ return result;
+ }
+ }
+ return TraversalContinuation.CONTINUE;
+ }
+
+ @Override
+ Iterable<DexEncodedMethod> methods() {
+ return methodMap.values();
+ }
+
+ @Override
+ List<DexEncodedMethod> directMethods() {
+ List<DexEncodedMethod> methods = new ArrayList<>(size());
+ forEachMethod(
+ method -> {
+ if (belongsToDirectPool(method)) {
+ methods.add(method);
+ }
+ });
+ return methods;
+ }
+
+ @Override
+ List<DexEncodedMethod> virtualMethods() {
+ List<DexEncodedMethod> methods = new ArrayList<>(size());
+ forEachMethod(
+ method -> {
+ if (belongsToVirtualPool(method)) {
+ methods.add(method);
+ }
+ });
+ return methods;
+ }
+
+ @Override
+ DexEncodedMethod getMethod(DexMethod method) {
+ return methodMap.get(wrap(method));
+ }
+
+ private DexEncodedMethod getMethod(Predicate<DexEncodedMethod> predicate) {
+ Box<DexEncodedMethod> found = new Box<>();
+ traverse(
+ method -> {
+ if (predicate.test(method)) {
+ found.set(method);
+ return TraversalContinuation.BREAK;
+ }
+ return TraversalContinuation.CONTINUE;
+ });
+ return found.get();
+ }
+
+ @Override
+ DexEncodedMethod getDirectMethod(DexMethod method) {
+ DexEncodedMethod definition = getMethod(method);
+ return definition != null && belongsToDirectPool(definition) ? definition : null;
+ }
+
+ @Override
+ DexEncodedMethod getDirectMethod(Predicate<DexEncodedMethod> predicate) {
+ Predicate<DexEncodedMethod> isDirect = this::belongsToDirectPool;
+ return getMethod(isDirect.and(predicate));
+ }
+
+ @Override
+ DexEncodedMethod getVirtualMethod(DexMethod method) {
+ DexEncodedMethod definition = getMethod(method);
+ return definition != null && belongsToVirtualPool(definition) ? definition : null;
+ }
+
+ @Override
+ DexEncodedMethod getVirtualMethod(Predicate<DexEncodedMethod> predicate) {
+ Predicate<DexEncodedMethod> isVirtual = this::belongsToVirtualPool;
+ return getMethod(isVirtual.and(predicate));
+ }
+
+ @Override
+ void addMethod(DexEncodedMethod method) {
+ Wrapper<DexMethod> key = wrap(method.method);
+ DexEncodedMethod old = methodMap.put(key, method);
+ assert old == null;
+ }
+
+ @Override
+ void addDirectMethod(DexEncodedMethod method) {
+ assert belongsToDirectPool(method);
+ addMethod(method);
+ }
+
+ @Override
+ void addVirtualMethod(DexEncodedMethod method) {
+ assert belongsToVirtualPool(method);
+ addMethod(method);
+ }
+
+ @Override
+ void addDirectMethods(Collection<DexEncodedMethod> methods) {
+ for (DexEncodedMethod method : methods) {
+ addDirectMethod(method);
+ }
+ }
+
+ @Override
+ void addVirtualMethods(Collection<DexEncodedMethod> methods) {
+ for (DexEncodedMethod method : methods) {
+ addVirtualMethod(method);
+ }
+ }
+
+ @Override
+ void removeDirectMethod(DexMethod method) {
+ methodMap.remove(wrap(method));
+ }
+
+ @Override
+ void setDirectMethods(DexEncodedMethod[] methods) {
+ if ((methods == null || methods.length == 0) && methodMap.isEmpty()) {
+ return;
+ }
+ if (methods == null) {
+ methods = DexEncodedMethod.EMPTY_ARRAY;
+ }
+ Object2ReferenceMap<Wrapper<DexMethod>, DexEncodedMethod> newMap =
+ createMap(size() + methods.length);
+ forEachMethod(
+ method -> {
+ if (belongsToVirtualPool(method)) {
+ newMap.put(wrap(method.method), method);
+ }
+ });
+ for (DexEncodedMethod method : methods) {
+ assert belongsToDirectPool(method);
+ newMap.put(wrap(method.method), method);
+ }
+ methodMap = newMap;
+ }
+
+ @Override
+ void setVirtualMethods(DexEncodedMethod[] methods) {
+ if ((methods == null || methods.length == 0) && methodMap.isEmpty()) {
+ return;
+ }
+ if (methods == null) {
+ methods = DexEncodedMethod.EMPTY_ARRAY;
+ }
+ Object2ReferenceMap<Wrapper<DexMethod>, DexEncodedMethod> newMap =
+ createMap(size() + methods.length);
+ forEachMethod(
+ method -> {
+ if (belongsToDirectPool(method)) {
+ newMap.put(wrap(method.method), method);
+ }
+ });
+ for (DexEncodedMethod method : methods) {
+ assert belongsToVirtualPool(method);
+ newMap.put(wrap(method.method), method);
+ }
+ methodMap = newMap;
+ }
+
+ @Override
+ void replaceMethods(Function<DexEncodedMethod, DexEncodedMethod> replacement) {
+ boolean rehash = false;
+ for (Object2ReferenceMap.Entry<Wrapper<DexMethod>, DexEncodedMethod> entry :
+ methodMap.object2ReferenceEntrySet()) {
+ DexEncodedMethod newMethod = replacement.apply(entry.getValue());
+ if (newMethod != entry.getValue()) {
+ rehash = rehash || newMethod.method != entry.getKey().get();
+ entry.setValue(newMethod);
+ }
+ }
+ if (rehash) {
+ rehash();
+ }
+ }
+
+ @Override
+ void replaceDirectMethods(Function<DexEncodedMethod, DexEncodedMethod> replacement) {
+ replaceMethods(method -> belongsToDirectPool(method) ? replacement.apply(method) : method);
+ }
+
+ @Override
+ void replaceVirtualMethods(Function<DexEncodedMethod, DexEncodedMethod> replacement) {
+ replaceMethods(method -> belongsToVirtualPool(method) ? replacement.apply(method) : method);
+ }
+
+ @Override
+ DexEncodedMethod replaceDirectMethod(
+ DexMethod method, Function<DexEncodedMethod, DexEncodedMethod> replacement) {
+ Wrapper<DexMethod> key = wrap(method);
+ DexEncodedMethod existing = methodMap.get(key);
+ if (existing == null || belongsToVirtualPool(existing)) {
+ return null;
+ }
+ DexEncodedMethod newMethod = replacement.apply(existing);
+ assert belongsToDirectPool(newMethod);
+ replace(key, newMethod);
+ return newMethod;
+ }
+
+ @Override
+ DexEncodedMethod replaceDirectMethodWithVirtualMethod(
+ DexMethod method, Function<DexEncodedMethod, DexEncodedMethod> replacement) {
+ Wrapper<DexMethod> key = wrap(method);
+ DexEncodedMethod existing = methodMap.get(key);
+ if (existing == null || belongsToVirtualPool(existing)) {
+ return null;
+ }
+ DexEncodedMethod newMethod = replacement.apply(existing);
+ assert belongsToVirtualPool(newMethod);
+ replace(key, newMethod);
+ return newMethod;
+ }
+
+ @Override
+ void virtualizeMethods(Set<DexEncodedMethod> privateInstanceMethods) {
+ // This is a no-op as the virtualizer has modified the encoded method bits.
+ assert verifyVirtualizedMethods(privateInstanceMethods);
+ }
+
+ private boolean verifyVirtualizedMethods(Set<DexEncodedMethod> methods) {
+ for (DexEncodedMethod method : methods) {
+ assert belongsToVirtualPool(method);
+ assert methodMap.get(wrap(method.method)) == method;
+ }
+ return true;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/graph/ResolutionResult.java b/src/main/java/com/android/tools/r8/graph/ResolutionResult.java
index 5c1611d..e8cae8d 100644
--- a/src/main/java/com/android/tools/r8/graph/ResolutionResult.java
+++ b/src/main/java/com/android/tools/r8/graph/ResolutionResult.java
@@ -135,6 +135,10 @@
return resolvedMethod;
}
+ public DexClassAndMethod getResolutionPair() {
+ return DexClassAndMethod.create(resolvedHolder, resolvedMethod);
+ }
+
@Override
public boolean isSingleResolution() {
return true;
diff --git a/src/main/java/com/android/tools/r8/graph/UseRegistry.java b/src/main/java/com/android/tools/r8/graph/UseRegistry.java
index 2c27763..1e89e13 100644
--- a/src/main/java/com/android/tools/r8/graph/UseRegistry.java
+++ b/src/main/java/com/android/tools/r8/graph/UseRegistry.java
@@ -3,14 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.graph;
-import com.android.tools.r8.graph.DexValue.DexValueDouble;
-import com.android.tools.r8.graph.DexValue.DexValueFloat;
-import com.android.tools.r8.graph.DexValue.DexValueInt;
-import com.android.tools.r8.graph.DexValue.DexValueLong;
-import com.android.tools.r8.graph.DexValue.DexValueMethodHandle;
-import com.android.tools.r8.graph.DexValue.DexValueMethodType;
-import com.android.tools.r8.graph.DexValue.DexValueString;
-import com.android.tools.r8.graph.DexValue.DexValueType;
public abstract class UseRegistry {
@@ -128,22 +120,27 @@
// Register bootstrap method arguments.
// Only Type, MethodHandle, and MethodType need to be registered.
for (DexValue arg : callSite.bootstrapArgs) {
- if (arg instanceof DexValueType) {
- registerTypeReference(((DexValueType) arg).value);
- } else if (arg instanceof DexValueMethodHandle) {
- DexMethodHandle handle = ((DexValueMethodHandle) arg).value;
- MethodHandleUse use = isLambdaMetaFactory
- ? MethodHandleUse.ARGUMENT_TO_LAMBDA_METAFACTORY
- : MethodHandleUse.NOT_ARGUMENT_TO_LAMBDA_METAFACTORY;
- registerMethodHandle(handle, use);
- } else if (arg instanceof DexValueMethodType) {
- registerProto(((DexValueMethodType) arg).value);
- } else {
- assert (arg instanceof DexValueInt)
- || (arg instanceof DexValueLong)
- || (arg instanceof DexValueFloat)
- || (arg instanceof DexValueDouble)
- || (arg instanceof DexValueString);
+ switch (arg.getValueKind()) {
+ case METHOD_HANDLE:
+ DexMethodHandle handle = arg.asDexValueMethodHandle().value;
+ MethodHandleUse use =
+ isLambdaMetaFactory
+ ? MethodHandleUse.ARGUMENT_TO_LAMBDA_METAFACTORY
+ : MethodHandleUse.NOT_ARGUMENT_TO_LAMBDA_METAFACTORY;
+ registerMethodHandle(handle, use);
+ break;
+ case METHOD_TYPE:
+ registerProto(arg.asDexValueMethodType().value);
+ break;
+ case TYPE:
+ registerTypeReference(arg.asDexValueType().value);
+ break;
+ default:
+ assert arg.isDexValueInt()
+ || arg.isDexValueLong()
+ || arg.isDexValueFloat()
+ || arg.isDexValueDouble()
+ || arg.isDexValueString();
}
}
}
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/DesugaredLibraryConversionWrapperAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/DesugaredLibraryConversionWrapperAnalysis.java
index d8d48a2..8d61294 100644
--- a/src/main/java/com/android/tools/r8/graph/analysis/DesugaredLibraryConversionWrapperAnalysis.java
+++ b/src/main/java/com/android/tools/r8/graph/analysis/DesugaredLibraryConversionWrapperAnalysis.java
@@ -15,18 +15,16 @@
import com.android.tools.r8.ir.desugar.DesugaredLibraryAPIConverter.Mode;
import com.android.tools.r8.utils.OptionalBool;
import java.util.ArrayList;
+import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
-import java.util.Set;
-import java.util.function.Consumer;
public class DesugaredLibraryConversionWrapperAnalysis extends EnqueuerAnalysis
implements EnqueuerInvokeAnalysis {
private final AppView<?> appView;
private final DesugaredLibraryAPIConverter converter;
- private boolean callbackGenerated = false;
- private Map<DexProgramClass, DexProgramClass> wrappersToReverseMap = null;
+ private Map<DexType, DexProgramClass> synthesizedWrappers = new IdentityHashMap<>();
public DesugaredLibraryConversionWrapperAnalysis(AppView<?> appView) {
this.appView = appView;
@@ -69,22 +67,18 @@
}
public List<DexEncodedMethod> generateCallbackMethods() {
- assert !callbackGenerated;
- callbackGenerated = true;
return converter.generateCallbackMethods();
}
- public Set<DexProgramClass> generateWrappers() {
- assert wrappersToReverseMap == null;
- wrappersToReverseMap = converter.synthesizeWrappersAndMapToReverse();
- return wrappersToReverseMap.keySet();
+ public List<DexProgramClass> generateWrappers() {
+ return converter.synthesizeWrappers(synthesizedWrappers);
}
// Generate a mock classpath class for all vivified types.
// Types will be available at runtime in the desugared library dex file.
- public List<DexClasspathClass> generateWrappersSuperTypeMock() {
+ public List<DexClasspathClass> generateWrappersSuperTypeMock(List<DexProgramClass> wrappers) {
List<DexClasspathClass> classpathClasses = new ArrayList<>();
- for (DexProgramClass wrapper : wrappersToReverseMap.keySet()) {
+ for (DexProgramClass wrapper : wrappers) {
boolean mockIsInterface = wrapper.interfaces.size() == 1;
DexType mockType = mockIsInterface ? wrapper.interfaces.values[0] : wrapper.superType;
if (appView.definitionFor(mockType) == null) {
@@ -106,37 +100,4 @@
}
return classpathClasses;
}
-
- public DesugaredLibraryConversionWrapperAnalysis registerWrite(
- DexProgramClass wrapper, Consumer<DexEncodedMethod> registration) {
- registration.accept(getInitializer(wrapper));
- return this;
- }
-
- public DesugaredLibraryConversionWrapperAnalysis registerReads(
- DexProgramClass wrapper, Consumer<DexEncodedMethod> registration) {
- // The field of each wrapper is read exclusively in all virtual methods and the reverse wrapper
- // convert method.
- for (DexEncodedMethod virtualMethod : wrapper.virtualMethods()) {
- registration.accept(virtualMethod);
- }
- DexProgramClass reverseWrapper = wrappersToReverseMap.get(wrapper);
- assert reverseWrapper != null;
- registration.accept(getConvertMethod(reverseWrapper));
- return this;
- }
-
- private DexEncodedMethod getInitializer(DexProgramClass wrapper) {
- DexEncodedMethod initializer =
- wrapper.lookupDirectMethod(DexEncodedMethod::isInstanceInitializer);
- assert initializer != null;
- return initializer;
- }
-
- private DexEncodedMethod getConvertMethod(DexProgramClass wrapper) {
- DexEncodedMethod convertMethod = wrapper.lookupDirectMethod(DexEncodedMethod::isStatic);
- assert convertMethod != null;
- assert convertMethod.method.name == appView.dexItemFactory().convertMethodName;
- return convertMethod;
- }
}
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerAnalysis.java
index 8374410..29d7dcc 100644
--- a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerAnalysis.java
+++ b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerAnalysis.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.shaking.Enqueuer;
import com.android.tools.r8.shaking.EnqueuerWorklist;
+import com.android.tools.r8.utils.Timing;
public abstract class EnqueuerAnalysis {
@@ -28,7 +29,7 @@
* Called when the Enqueuer reaches a fixpoint. This may happen multiple times, since each
* analysis may enqueue items into the worklist upon the fixpoint using {@param worklist}.
*/
- public void notifyFixpoint(Enqueuer enqueuer, EnqueuerWorklist worklist) {}
+ public void notifyFixpoint(Enqueuer enqueuer, EnqueuerWorklist worklist, Timing timing) {}
/**
* Called when the Enqueuer has reached the final fixpoint. Each analysis may use this callback to
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/InitializedClassesInInstanceMethodsAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/InitializedClassesInInstanceMethodsAnalysis.java
index 7df903b..f32143d 100644
--- a/src/main/java/com/android/tools/r8/graph/analysis/InitializedClassesInInstanceMethodsAnalysis.java
+++ b/src/main/java/com/android/tools/r8/graph/analysis/InitializedClassesInInstanceMethodsAnalysis.java
@@ -10,7 +10,7 @@
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
import java.util.IdentityHashMap;
import java.util.Map;
@@ -79,7 +79,7 @@
mapping.getOrDefault(key, guaranteedToBeInitialized);
mapping.put(
key,
- ClassTypeLatticeElement.computeLeastUpperBoundOfClasses(
+ ClassTypeElement.computeLeastUpperBoundOfClasses(
appInfo, guaranteedToBeInitialized, existingGuaranteedToBeInitialized));
}
diff --git a/src/main/java/com/android/tools/r8/inspector/BooleanValueInspector.java b/src/main/java/com/android/tools/r8/inspector/BooleanValueInspector.java
index 1fba365..105f577 100644
--- a/src/main/java/com/android/tools/r8/inspector/BooleanValueInspector.java
+++ b/src/main/java/com/android/tools/r8/inspector/BooleanValueInspector.java
@@ -3,6 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.inspector;
+import com.android.tools.r8.Keep;
+
+@Keep
public interface BooleanValueInspector extends ValueInspector {
boolean getBooleanValue();
}
diff --git a/src/main/java/com/android/tools/r8/inspector/ByteValueInspector.java b/src/main/java/com/android/tools/r8/inspector/ByteValueInspector.java
index 718183e..045476d 100644
--- a/src/main/java/com/android/tools/r8/inspector/ByteValueInspector.java
+++ b/src/main/java/com/android/tools/r8/inspector/ByteValueInspector.java
@@ -3,6 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.inspector;
+import com.android.tools.r8.Keep;
+
+@Keep
public interface ByteValueInspector extends ValueInspector {
byte getByteValue();
}
diff --git a/src/main/java/com/android/tools/r8/inspector/CharValueInspector.java b/src/main/java/com/android/tools/r8/inspector/CharValueInspector.java
index d79ee9c..05d5c2b 100644
--- a/src/main/java/com/android/tools/r8/inspector/CharValueInspector.java
+++ b/src/main/java/com/android/tools/r8/inspector/CharValueInspector.java
@@ -3,6 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.inspector;
+import com.android.tools.r8.Keep;
+
+@Keep
public interface CharValueInspector extends ValueInspector {
char getCharValue();
}
diff --git a/src/main/java/com/android/tools/r8/inspector/DoubleValueInspector.java b/src/main/java/com/android/tools/r8/inspector/DoubleValueInspector.java
index 334f7ac..e9ac7e1 100644
--- a/src/main/java/com/android/tools/r8/inspector/DoubleValueInspector.java
+++ b/src/main/java/com/android/tools/r8/inspector/DoubleValueInspector.java
@@ -3,6 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.inspector;
+import com.android.tools.r8.Keep;
+
+@Keep
public interface DoubleValueInspector extends ValueInspector {
double getDoubleValue();
}
diff --git a/src/main/java/com/android/tools/r8/inspector/FloatValueInspector.java b/src/main/java/com/android/tools/r8/inspector/FloatValueInspector.java
index cb4c12d..a7be463 100644
--- a/src/main/java/com/android/tools/r8/inspector/FloatValueInspector.java
+++ b/src/main/java/com/android/tools/r8/inspector/FloatValueInspector.java
@@ -3,6 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.inspector;
+import com.android.tools.r8.Keep;
+
+@Keep
public interface FloatValueInspector extends ValueInspector {
float getFloatValue();
}
diff --git a/src/main/java/com/android/tools/r8/inspector/IntValueInspector.java b/src/main/java/com/android/tools/r8/inspector/IntValueInspector.java
index 38376c2..6b43ac8 100644
--- a/src/main/java/com/android/tools/r8/inspector/IntValueInspector.java
+++ b/src/main/java/com/android/tools/r8/inspector/IntValueInspector.java
@@ -3,6 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.inspector;
+import com.android.tools.r8.Keep;
+
+@Keep
public interface IntValueInspector extends ValueInspector {
int getIntValue();
}
diff --git a/src/main/java/com/android/tools/r8/inspector/LongValueInspector.java b/src/main/java/com/android/tools/r8/inspector/LongValueInspector.java
index 177a885..987721e 100644
--- a/src/main/java/com/android/tools/r8/inspector/LongValueInspector.java
+++ b/src/main/java/com/android/tools/r8/inspector/LongValueInspector.java
@@ -3,6 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.inspector;
+import com.android.tools.r8.Keep;
+
+@Keep
public interface LongValueInspector extends ValueInspector {
long getLongValue();
}
diff --git a/src/main/java/com/android/tools/r8/inspector/ShortValueInspector.java b/src/main/java/com/android/tools/r8/inspector/ShortValueInspector.java
index fb1d823..6b01df3 100644
--- a/src/main/java/com/android/tools/r8/inspector/ShortValueInspector.java
+++ b/src/main/java/com/android/tools/r8/inspector/ShortValueInspector.java
@@ -3,6 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.inspector;
+import com.android.tools.r8.Keep;
+
+@Keep
public interface ShortValueInspector extends ValueInspector {
short getShortValue();
}
diff --git a/src/main/java/com/android/tools/r8/inspector/StringValueInspector.java b/src/main/java/com/android/tools/r8/inspector/StringValueInspector.java
index c0b78c4..5336948 100644
--- a/src/main/java/com/android/tools/r8/inspector/StringValueInspector.java
+++ b/src/main/java/com/android/tools/r8/inspector/StringValueInspector.java
@@ -3,6 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.inspector;
+import com.android.tools.r8.Keep;
+
+@Keep
public interface StringValueInspector extends ValueInspector {
String getStringValue();
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/ClassInitializationAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/ClassInitializationAnalysis.java
index 7270d42..7167e72 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/ClassInitializationAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/ClassInitializationAnalysis.java
@@ -14,7 +14,7 @@
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ResolutionResult;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.CatchHandlers.CatchHandler;
import com.android.tools.r8.ir.code.DominatorTree;
@@ -278,7 +278,7 @@
instruction.isInstanceGet()
? instruction.asInstanceGet().object()
: instruction.asInstancePut().object();
- if (object.getTypeLattice().isNullable()) {
+ if (object.getType().isNullable()) {
// If the receiver is null we cannot be sure that the holder has been initialized.
return false;
}
@@ -294,7 +294,7 @@
Query mode,
AnalysisAssumption assumption) {
if (assumption == AnalysisAssumption.NONE) {
- if (instruction.getReceiver().getTypeLattice().isNullable()) {
+ if (instruction.getReceiver().getType().isNullable()) {
// If the receiver is null we cannot be sure that the holder has been initialized.
return false;
}
@@ -311,7 +311,7 @@
Query mode,
AnalysisAssumption assumption) {
if (assumption == AnalysisAssumption.NONE) {
- if (instruction.getReceiver().getTypeLattice().isNullable()) {
+ if (instruction.getReceiver().getType().isNullable()) {
// If the receiver is null we cannot be sure that the holder has been initialized.
return false;
}
@@ -362,7 +362,7 @@
Query mode,
AnalysisAssumption assumption) {
if (assumption == AnalysisAssumption.NONE) {
- if (instruction.getReceiver().getTypeLattice().isNullable()) {
+ if (instruction.getReceiver().getType().isNullable()) {
// If the receiver is null we cannot be sure that the holder has been initialized.
return false;
}
@@ -406,7 +406,7 @@
Query mode,
AnalysisAssumption assumption) {
if (assumption == AnalysisAssumption.NONE) {
- if (instruction.getReceiver().getTypeLattice().isNullable()) {
+ if (instruction.getReceiver().getType().isNullable()) {
// If the receiver is null we cannot be sure that the holder has been initialized.
return false;
}
@@ -554,9 +554,9 @@
// implies that the type of the receiver must be initialized.
if (!method.isStatic()) {
assert arguments.size() > 0;
- TypeLatticeElement type = arguments.get(0).getTypeLattice();
+ TypeElement type = arguments.get(0).getType();
if (type.isClassType()) {
- enqueue(type.asClassTypeLatticeElement().getClassType(), visited, worklist);
+ enqueue(type.asClassType().getClassType(), visited, worklist);
}
}
// If an invoke to a method succeeds, and the method would have thrown and exception if the
@@ -566,9 +566,9 @@
if (nonNullParamOrThrowFacts != null) {
for (int i = 0; i < arguments.size(); i++) {
if (nonNullParamOrThrowFacts.get(i)) {
- TypeLatticeElement type = arguments.get(i).getTypeLattice();
+ TypeElement type = arguments.get(i).getType();
if (type.isClassType()) {
- enqueue(type.asClassTypeLatticeElement().getClassType(), visited, worklist);
+ enqueue(type.asClassType().getClassType(), visited, worklist);
}
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/TypeChecker.java b/src/main/java/com/android/tools/r8/ir/analysis/TypeChecker.java
index 01a7e3d..f8a621d 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/TypeChecker.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/TypeChecker.java
@@ -9,7 +9,7 @@
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.FieldInstruction;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.InstancePut;
@@ -67,15 +67,14 @@
if (instruction.isReturnVoid()) {
return true;
}
- TypeLatticeElement valueType = instruction.returnValue().getTypeLattice();
- TypeLatticeElement returnType =
- TypeLatticeElement.fromDexType(
- method.method.proto.returnType, Nullability.maybeNull(), appView);
+ TypeElement valueType = instruction.returnValue().getType();
+ TypeElement returnType =
+ TypeElement.fromDexType(method.method.proto.returnType, Nullability.maybeNull(), appView);
if (isSubtypeOf(valueType, returnType)) {
return true;
}
- if (returnType.isClassType() && valueType.isReference()) {
+ if (returnType.isClassType() && valueType.isReferenceType()) {
// Interface types are treated like Object according to the JVM spec.
// https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.10.1.2-100
DexClass clazz = appView.definitionFor(method.method.proto.returnType);
@@ -91,15 +90,14 @@
public boolean checkFieldPut(FieldInstruction instruction) {
assert instruction.isFieldPut();
- TypeLatticeElement valueType = instruction.value().getTypeLattice();
- TypeLatticeElement fieldType =
- TypeLatticeElement.fromDexType(
- instruction.getField().type, valueType.nullability(), appView);
+ TypeElement valueType = instruction.value().getType();
+ TypeElement fieldType =
+ TypeElement.fromDexType(instruction.getField().type, valueType.nullability(), appView);
if (isSubtypeOf(valueType, fieldType)) {
return true;
}
- if (fieldType.isClassType() && valueType.isReference()) {
+ if (fieldType.isClassType() && valueType.isReferenceType()) {
// Interface types are treated like Object according to the JVM spec.
// https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.10.1.2-100
DexClass clazz = appView.definitionFor(instruction.getField().type);
@@ -110,16 +108,15 @@
}
public boolean check(Throw instruction) {
- TypeLatticeElement valueType = instruction.exception().getTypeLattice();
- TypeLatticeElement throwableType =
- TypeLatticeElement.fromDexType(
+ TypeElement valueType = instruction.exception().getType();
+ TypeElement throwableType =
+ TypeElement.fromDexType(
appView.dexItemFactory().throwableType, valueType.nullability(), appView);
return isSubtypeOf(valueType, throwableType);
}
- private boolean isSubtypeOf(
- TypeLatticeElement expectedSubtype, TypeLatticeElement expectedSupertype) {
- return (expectedSubtype.isNullType() && expectedSupertype.isReference())
+ private boolean isSubtypeOf(TypeElement expectedSubtype, TypeElement expectedSupertype) {
+ return (expectedSubtype.isNullType() && expectedSupertype.isReferenceType())
|| expectedSubtype.lessThanOrEqual(expectedSupertype, appView)
|| expectedSubtype.isBasedOnMissingClass(appView);
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/equivalence/BasicBlockBehavioralSubsumption.java b/src/main/java/com/android/tools/r8/ir/analysis/equivalence/BasicBlockBehavioralSubsumption.java
index 7422417..27c4e19 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/equivalence/BasicBlockBehavioralSubsumption.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/equivalence/BasicBlockBehavioralSubsumption.java
@@ -192,7 +192,7 @@
Value outValue = instruction.outValue();
Value otherOutValue = other.outValue();
- if (!outValue.getTypeLattice().equals(otherOutValue.getTypeLattice())) {
+ if (!outValue.getType().equals(otherOutValue.getType())) {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/escape/EscapeAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/escape/EscapeAnalysis.java
index 466edeb..43e484d 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/escape/EscapeAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/escape/EscapeAnalysis.java
@@ -83,7 +83,7 @@
// Returns the set of instructions where the value of interest can escape from the code.
private void run(IRCode code, Value valueOfInterest, Predicate<Instruction> stoppingCriterion) {
- assert valueOfInterest.getTypeLattice().isReference();
+ assert valueOfInterest.getType().isReferenceType();
assert trackedValues.isEmpty();
assert valuesToTrack.isEmpty();
@@ -153,13 +153,13 @@
}
if (couldIntroduceTrackedValueAlias) {
Value outValue = user.outValue();
- assert outValue != null && outValue.getTypeLattice().isReference();
+ assert outValue != null && outValue.getType().isReferenceType();
addToWorklist(outValue);
}
// Track propagated values through which the value of interest can escape indirectly.
Value propagatedValue = getPropagatedSubject(alias, user);
if (propagatedValue != null && propagatedValue != alias) {
- assert propagatedValue.getTypeLattice().isReference();
+ assert propagatedValue.getType().isReferenceType();
addToWorklist(propagatedValue);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/InstanceFieldValueAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/InstanceFieldValueAnalysis.java
index e540a06..3aec803 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/InstanceFieldValueAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/InstanceFieldValueAnalysis.java
@@ -12,8 +12,8 @@
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.code.Argument;
import com.android.tools.r8.ir.code.BasicBlock;
@@ -30,6 +30,7 @@
import com.android.tools.r8.ir.optimize.info.field.InstanceFieldInitializationInfoCollection;
import com.android.tools.r8.ir.optimize.info.field.InstanceFieldInitializationInfoFactory;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.Timing;
public class InstanceFieldValueAnalysis extends FieldValueAnalysis {
@@ -66,6 +67,20 @@
IRCode code,
ClassInitializerDefaultsResult classInitializerDefaultsResult,
OptimizationFeedback feedback,
+ DexEncodedMethod method,
+ Timing timing) {
+ timing.begin("Analyze instance initializer");
+ InstanceFieldInitializationInfoCollection result =
+ run(appView, code, classInitializerDefaultsResult, feedback, method);
+ timing.end();
+ return result;
+ }
+
+ private static InstanceFieldInitializationInfoCollection run(
+ AppView<?> appView,
+ IRCode code,
+ ClassInitializerDefaultsResult classInitializerDefaultsResult,
+ OptimizationFeedback feedback,
DexEncodedMethod method) {
assert appView.appInfo().hasLiveness();
assert appView.enableWholeProgramOptimizations();
@@ -153,10 +168,9 @@
DexType fieldType = field.field.type;
if (fieldType.isClassType()) {
- ClassTypeLatticeElement dynamicLowerBoundType = value.getDynamicLowerBoundType(appView);
- TypeLatticeElement dynamicUpperBoundType = value.getDynamicUpperBoundType(appView);
- TypeLatticeElement staticFieldType =
- TypeLatticeElement.fromDexType(fieldType, maybeNull(), appView);
+ ClassTypeElement dynamicLowerBoundType = value.getDynamicLowerBoundType(appView);
+ TypeElement dynamicUpperBoundType = value.getDynamicUpperBoundType(appView);
+ TypeElement staticFieldType = TypeElement.fromDexType(fieldType, maybeNull(), appView);
if (dynamicLowerBoundType != null || !dynamicUpperBoundType.equals(staticFieldType)) {
builder.recordInitializationInfo(
field,
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java
index 10dd287..4d57a5e 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java
@@ -12,9 +12,9 @@
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexProgramClass;
-import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.analysis.value.AbstractValueFactory;
import com.android.tools.r8.ir.analysis.value.SingleEnumValue;
@@ -29,6 +29,7 @@
import com.android.tools.r8.ir.optimize.ClassInitializerDefaultsOptimization.ClassInitializerDefaultsResult;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedback;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.Timing;
public class StaticFieldValueAnalysis extends FieldValueAnalysis {
@@ -46,13 +47,16 @@
IRCode code,
ClassInitializerDefaultsResult classInitializerDefaultsResult,
OptimizationFeedback feedback,
- DexEncodedMethod method) {
+ DexEncodedMethod method,
+ Timing timing) {
assert appView.appInfo().hasLiveness();
assert appView.enableWholeProgramOptimizations();
assert method.isClassInitializer();
+ timing.begin("Analyze class initializer");
DexProgramClass clazz = appView.definitionFor(method.method.holder).asProgramClass();
new StaticFieldValueAnalysis(appView.withLiveness(), code, feedback, clazz, method)
.computeFieldOptimizationInfo(classInitializerDefaultsResult);
+ timing.end();
}
@Override
@@ -105,15 +109,15 @@
}
// Dynamic upper bound type.
- TypeLatticeElement fieldType =
- TypeLatticeElement.fromDexType(field.field.type, Nullability.maybeNull(), appView);
- TypeLatticeElement dynamicUpperBoundType = value.getDynamicUpperBoundType(appView);
+ TypeElement fieldType =
+ TypeElement.fromDexType(field.field.type, Nullability.maybeNull(), appView);
+ TypeElement dynamicUpperBoundType = value.getDynamicUpperBoundType(appView);
if (dynamicUpperBoundType.strictlyLessThan(fieldType, appView)) {
feedback.markFieldHasDynamicUpperBoundType(field, dynamicUpperBoundType);
}
// Dynamic lower bound type.
- ClassTypeLatticeElement dynamicLowerBoundType = value.getDynamicLowerBoundType(appView);
+ ClassTypeElement dynamicLowerBoundType = value.getDynamicLowerBoundType(appView);
if (dynamicLowerBoundType != null) {
assert dynamicLowerBoundType.lessThanOrEqual(dynamicUpperBoundType, appView);
feedback.markFieldHasDynamicLowerBoundType(field, dynamicLowerBoundType);
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedExtensionRegistryShrinker.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedExtensionRegistryShrinker.java
index 4de5c39..2a70440 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedExtensionRegistryShrinker.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedExtensionRegistryShrinker.java
@@ -32,6 +32,7 @@
import com.android.tools.r8.shaking.TreePrunerConfiguration;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.FileUtils;
+import com.android.tools.r8.utils.Timing;
import com.google.common.base.Predicates;
import com.google.common.collect.Sets;
import java.io.IOException;
@@ -155,13 +156,15 @@
return removedExtensionFields.contains(field);
}
- public void postOptimizeGeneratedExtensionRegistry(IRConverter converter) {
+ public void postOptimizeGeneratedExtensionRegistry(IRConverter converter, Timing timing) {
+ timing.begin("[Proto] Post optimize generated extension registry");
forEachFindLiteExtensionByNumberMethod(
method ->
converter.processMethod(
method,
OptimizationFeedbackIgnore.getInstance(),
OneTimeMethodProcessor.getInstance()));
+ timing.end(); // [Proto] Post optimize generated extension registry
}
private void forEachFindLiteExtensionByNumberMethod(Consumer<DexEncodedMethod> consumer) {
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteBuilderShrinker.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteBuilderShrinker.java
index 8da13ed..feca06c 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteBuilderShrinker.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteBuilderShrinker.java
@@ -13,9 +13,9 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.EnumValueInfoMapCollection.EnumValueInfo;
import com.android.tools.r8.graph.EnumValueInfoMapCollection.EnumValueInfoMap;
-import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.CheckCast;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
@@ -217,8 +217,8 @@
if (!references.methodToInvokeMembers.isNewMutableInstanceEnum(methodToInvokeValue)) {
continue;
}
- ClassTypeLatticeElement receiverType =
- invoke.getReceiver().getDynamicUpperBoundType(appView).asClassTypeLatticeElement();
+ ClassTypeElement receiverType =
+ invoke.getReceiver().getDynamicUpperBoundType(appView).asClassType();
if (receiverType != null) {
AppInfoWithClassHierarchy appInfo = appView.appInfo();
DexType rawReceiverType = receiverType.getClassType();
@@ -269,9 +269,9 @@
if (definition.getInvokedMethod() != appView.dexItemFactory().enumMethods.ordinal) {
return false;
}
- TypeLatticeElement enumType = definition.getReceiver().getTypeLattice();
+ TypeElement enumType = definition.getReceiver().getType();
return enumType.isClassType()
- && enumType.asClassTypeLatticeElement().getClassType() == references.methodToInvokeType;
+ && enumType.asClassType().getClassType() == references.methodToInvokeType;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteShrinker.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteShrinker.java
index cc7307f..390f2b2 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteShrinker.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteShrinker.java
@@ -15,7 +15,7 @@
import com.android.tools.r8.ir.analysis.proto.schema.ProtoMessageInfo;
import com.android.tools.r8.ir.analysis.proto.schema.ProtoObject;
import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.ArrayPut;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.BasicBlock.ThrowingInfo;
@@ -32,6 +32,7 @@
import com.android.tools.r8.ir.conversion.OneTimeMethodProcessor;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackIgnore;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.Timing;
import java.util.List;
import java.util.function.Consumer;
@@ -43,8 +44,8 @@
private final ProtoReferences references;
private final ThrowingInfo throwingInfo;
- private final TypeLatticeElement objectArrayType;
- private final TypeLatticeElement stringType;
+ private final TypeElement objectArrayType;
+ private final TypeElement stringType;
public GeneratedMessageLiteShrinker(
AppView<AppInfoWithLiveness> appView,
@@ -58,9 +59,9 @@
// Types.
this.objectArrayType =
- TypeLatticeElement.fromDexType(
+ TypeElement.fromDexType(
appView.dexItemFactory().objectArrayType, Nullability.definitelyNotNull(), appView);
- this.stringType = TypeLatticeElement.stringClassType(appView, Nullability.definitelyNotNull());
+ this.stringType = TypeElement.stringClassType(appView, Nullability.definitelyNotNull());
}
public void run(DexEncodedMethod method, IRCode code) {
@@ -69,13 +70,15 @@
}
}
- public void postOptimizeDynamicMethods(IRConverter converter) {
+ public void postOptimizeDynamicMethods(IRConverter converter, Timing timing) {
+ timing.begin("[Proto] Post optimize dynamic methods");
forEachDynamicMethod(
method ->
converter.processMethod(
method,
OptimizationFeedbackIgnore.getInstance(),
OneTimeMethodProcessor.getInstance()));
+ timing.end();
}
private void forEachDynamicMethod(Consumer<DexEncodedMethod> consumer) {
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/LiveProtoFieldObject.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/LiveProtoFieldObject.java
index 568b822..308ea07 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/LiveProtoFieldObject.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/LiveProtoFieldObject.java
@@ -7,7 +7,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.BasicBlock.ThrowingInfo;
import com.android.tools.r8.ir.code.ConstString;
import com.android.tools.r8.ir.code.DexItemBasedConstString;
@@ -31,8 +31,7 @@
@Override
public Instruction buildIR(AppView<?> appView, IRCode code) {
Value value =
- code.createValue(
- TypeLatticeElement.stringClassType(appView, Nullability.definitelyNotNull()));
+ code.createValue(TypeElement.stringClassType(appView, Nullability.definitelyNotNull()));
ThrowingInfo throwingInfo = ThrowingInfo.defaultForConstString(appView.options());
if (appView.options().isMinifying()) {
return new DexItemBasedConstString(
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoEnqueuerExtension.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoEnqueuerExtension.java
index bf6c8b1..e414f23 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoEnqueuerExtension.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoEnqueuerExtension.java
@@ -21,7 +21,7 @@
import com.android.tools.r8.ir.analysis.proto.ProtoReferences;
import com.android.tools.r8.ir.analysis.proto.ProtoShrinker;
import com.android.tools.r8.ir.analysis.proto.RawMessageInfoDecoder;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.IRCodeUtils;
@@ -37,6 +37,7 @@
import com.android.tools.r8.shaking.KeepReason;
import com.android.tools.r8.utils.BitUtils;
import com.android.tools.r8.utils.OptionalBool;
+import com.android.tools.r8.utils.Timing;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import java.util.IdentityHashMap;
@@ -171,7 +172,8 @@
}
@Override
- public void notifyFixpoint(Enqueuer enqueuer, EnqueuerWorklist worklist) {
+ public void notifyFixpoint(Enqueuer enqueuer, EnqueuerWorklist worklist, Timing timing) {
+ timing.begin("[Proto] Extend fixpoint");
populateExtensionGraph(enqueuer);
markMapOrRequiredFieldsAsReachable(enqueuer, worklist);
@@ -187,6 +189,7 @@
tracePendingInstructionsInDynamicMethods(enqueuer, worklist);
}
}
+ timing.end();
}
/**
@@ -317,17 +320,17 @@
InvokeMethod invoke = extensionFactory.asInvokeMethod();
DexMethod invokedMethod = invoke.getInvokedMethod();
- TypeLatticeElement containerType, extensionType;
+ TypeElement containerType, extensionType;
if (invokedMethod == references.generatedMessageLiteMethods.newRepeatedGeneratedExtension) {
- containerType = invoke.arguments().get(0).getTypeLattice();
- extensionType = invoke.arguments().get(1).getTypeLattice();
+ containerType = invoke.arguments().get(0).getType();
+ extensionType = invoke.arguments().get(1).getType();
} else if (invokedMethod
== references.generatedMessageLiteMethods.newSingularGeneratedExtension) {
- containerType = invoke.arguments().get(0).getTypeLattice();
- extensionType = invoke.arguments().get(2).getTypeLattice();
+ containerType = invoke.arguments().get(0).getType();
+ extensionType = invoke.arguments().get(2).getType();
} else if (references.generatedExtensionMethods.isConstructor(invokedMethod)) {
- containerType = invoke.arguments().get(1).getTypeLattice();
- extensionType = invoke.arguments().get(3).getTypeLattice();
+ containerType = invoke.arguments().get(1).getType();
+ extensionType = invoke.arguments().get(3).getType();
} else {
return;
}
@@ -343,9 +346,8 @@
extensionGraph
.computeIfAbsent(
- containerType.asClassTypeLatticeElement().getClassType(),
- ignore -> Sets.newIdentityHashSet())
- .add(extensionType.asClassTypeLatticeElement().getClassType());
+ containerType.asClassType().getClassType(), ignore -> Sets.newIdentityHashSet())
+ .add(extensionType.asClassType().getClassType());
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoObjectFromInvokeStatic.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoObjectFromInvokeStatic.java
index 0812098..8c9bc00 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoObjectFromInvokeStatic.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoObjectFromInvokeStatic.java
@@ -7,7 +7,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.InvokeStatic;
@@ -26,8 +26,7 @@
public Instruction buildIR(AppView<?> appView, IRCode code) {
Value value =
code.createValue(
- TypeLatticeElement.fromDexType(
- method.proto.returnType, Nullability.maybeNull(), appView));
+ TypeElement.fromDexType(method.proto.returnType, Nullability.maybeNull(), appView));
return new InvokeStatic(method, value, ImmutableList.of());
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoObjectFromStaticGet.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoObjectFromStaticGet.java
index 551466f..874ab9d 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoObjectFromStaticGet.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoObjectFromStaticGet.java
@@ -7,7 +7,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.StaticGet;
@@ -28,8 +28,7 @@
@Override
public Instruction buildIR(AppView<?> appView, IRCode code) {
Value value =
- code.createValue(
- TypeLatticeElement.fromDexType(field.type, Nullability.maybeNull(), appView));
+ code.createValue(TypeElement.fromDexType(field.type, Nullability.maybeNull(), appView));
return new StaticGet(value, field);
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/ArrayTypeElement.java b/src/main/java/com/android/tools/r8/ir/analysis/type/ArrayTypeElement.java
new file mode 100644
index 0000000..4af45c6
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/ArrayTypeElement.java
@@ -0,0 +1,184 @@
+// 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.ir.analysis.type;
+
+import static com.android.tools.r8.ir.analysis.type.Nullability.maybeNull;
+
+import com.android.tools.r8.graph.AppInfoWithSubtyping;
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexType;
+import java.util.Objects;
+import java.util.function.Function;
+
+public class ArrayTypeElement extends ReferenceTypeElement {
+
+ private final TypeElement memberTypeLattice;
+
+ // On-demand link between other nullability-variants.
+ private final NullabilityVariants<ArrayTypeElement> variants;
+
+ public static ArrayTypeElement create(TypeElement memberTypeLattice, Nullability nullability) {
+ return NullabilityVariants.create(
+ nullability, (variants) -> new ArrayTypeElement(memberTypeLattice, nullability, variants));
+ }
+
+ private ArrayTypeElement(
+ TypeElement memberTypeLattice,
+ Nullability nullability,
+ NullabilityVariants<ArrayTypeElement> variants) {
+ super(nullability);
+ assert memberTypeLattice.isPrimitiveType() || memberTypeLattice.nullability().isMaybeNull();
+ this.memberTypeLattice = memberTypeLattice;
+ this.variants = variants;
+ }
+
+ public DexType toDexType(DexItemFactory factory) {
+ TypeElement baseTypeLattice = getBaseType();
+ DexType baseType;
+ if (baseTypeLattice.isPrimitiveType()) {
+ baseType = baseTypeLattice.asPrimitiveType().toDexType(factory);
+ } else {
+ assert baseTypeLattice.isClassType();
+ baseType = baseTypeLattice.asClassType().getClassType();
+ }
+ return factory.createArrayType(getNesting(), baseType);
+ }
+
+ public int getNesting() {
+ int nesting = 1;
+ TypeElement member = getMemberType();
+ while (member.isArrayType()) {
+ ++nesting;
+ member = member.asArrayType().getMemberType();
+ }
+ return nesting;
+ }
+
+ public TypeElement getMemberType() {
+ return memberTypeLattice;
+ }
+
+ public TypeElement getMemberTypeAsValueType() {
+ return memberTypeLattice.isFineGrainedType() ? getInt() : memberTypeLattice;
+ }
+
+ public TypeElement getBaseType() {
+ TypeElement base = getMemberType();
+ while (base.isArrayType()) {
+ base = base.asArrayType().getMemberType();
+ }
+ return base;
+ }
+
+ private ArrayTypeElement createVariant(
+ Nullability nullability, NullabilityVariants<ArrayTypeElement> variants) {
+ assert this.nullability != nullability;
+ return new ArrayTypeElement(memberTypeLattice, nullability, variants);
+ }
+
+ @Override
+ public ReferenceTypeElement getOrCreateVariant(Nullability nullability) {
+ ArrayTypeElement variant = variants.get(nullability);
+ if (variant != null) {
+ return variant;
+ }
+ return variants.getOrCreateElement(nullability, this::createVariant);
+ }
+
+ @Override
+ public boolean isBasedOnMissingClass(AppView<? extends AppInfoWithSubtyping> appView) {
+ return memberTypeLattice.isBasedOnMissingClass(appView);
+ }
+
+ @Override
+ public boolean isArrayType() {
+ return true;
+ }
+
+ @Override
+ public ArrayTypeElement asArrayType() {
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return nullability.toString() + " (" + memberTypeLattice.toString() + "[])";
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof ArrayTypeElement)) {
+ return false;
+ }
+ ArrayTypeElement other = (ArrayTypeElement) o;
+ if (nullability() != other.nullability()) {
+ return false;
+ }
+ return memberTypeLattice.equals(other.memberTypeLattice);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(nullability, memberTypeLattice);
+ }
+
+ @Override
+ public ArrayTypeElement fixupClassTypeReferences(
+ Function<DexType, DexType> mapping, AppView<? extends AppInfoWithSubtyping> appView) {
+ if (memberTypeLattice.isReferenceType()) {
+ TypeElement substitutedMemberType =
+ memberTypeLattice.fixupClassTypeReferences(mapping, appView);
+ if (substitutedMemberType != memberTypeLattice) {
+ return ArrayTypeElement.create(substitutedMemberType, nullability);
+ }
+ }
+ return this;
+ }
+
+ ReferenceTypeElement join(ArrayTypeElement other, AppView<?> appView) {
+ Nullability nullability = nullability().join(other.nullability());
+ ReferenceTypeElement join =
+ joinMember(this.memberTypeLattice, other.memberTypeLattice, appView, nullability);
+ if (join == null) {
+ // Check if other has the right nullability before creating it.
+ if (other.nullability == nullability) {
+ return other;
+ } else {
+ return getOrCreateVariant(nullability);
+ }
+ } else {
+ assert join.nullability == nullability;
+ return join;
+ }
+ }
+
+ private static ReferenceTypeElement joinMember(
+ TypeElement aMember, TypeElement bMember, AppView<?> appView, Nullability nullability) {
+ if (aMember.equals(bMember)) {
+ // Return null indicating the join is the same as the member to avoid object allocation.
+ return null;
+ }
+ if (aMember.isArrayType() && bMember.isArrayType()) {
+ TypeElement join =
+ joinMember(
+ aMember.asArrayType().memberTypeLattice,
+ bMember.asArrayType().memberTypeLattice,
+ appView,
+ maybeNull());
+ return join == null ? null : ArrayTypeElement.create(join, nullability);
+ }
+ if (aMember.isClassType() && bMember.isClassType()) {
+ ReferenceTypeElement join = aMember.asClassType().join(bMember.asClassType(), appView);
+ return ArrayTypeElement.create(join, nullability);
+ }
+ if (aMember.isPrimitiveType() || bMember.isPrimitiveType()) {
+ return objectClassType(appView, nullability);
+ }
+ return objectArrayType(appView, nullability);
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/ArrayTypeLatticeElement.java b/src/main/java/com/android/tools/r8/ir/analysis/type/ArrayTypeLatticeElement.java
deleted file mode 100644
index 39ebff8..0000000
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/ArrayTypeLatticeElement.java
+++ /dev/null
@@ -1,190 +0,0 @@
-// 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.ir.analysis.type;
-
-import static com.android.tools.r8.ir.analysis.type.Nullability.maybeNull;
-
-import com.android.tools.r8.graph.AppInfoWithSubtyping;
-import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexType;
-import java.util.Objects;
-import java.util.function.Function;
-
-public class ArrayTypeLatticeElement extends ReferenceTypeLatticeElement {
-
- private final TypeLatticeElement memberTypeLattice;
-
- // On-demand link between other nullability-variants.
- private final NullabilityVariants<ArrayTypeLatticeElement> variants;
-
- public static ArrayTypeLatticeElement create(
- TypeLatticeElement memberTypeLattice, Nullability nullability) {
- return NullabilityVariants.create(
- nullability,
- (variants) -> new ArrayTypeLatticeElement(memberTypeLattice, nullability, variants));
- }
-
- private ArrayTypeLatticeElement(
- TypeLatticeElement memberTypeLattice,
- Nullability nullability,
- NullabilityVariants<ArrayTypeLatticeElement> variants) {
- super(nullability);
- assert memberTypeLattice.isPrimitive() || memberTypeLattice.nullability().isMaybeNull();
- this.memberTypeLattice = memberTypeLattice;
- this.variants = variants;
- }
-
- public DexType getArrayType(DexItemFactory factory) {
- TypeLatticeElement baseTypeLattice = getArrayBaseTypeLattice();
- DexType baseType;
- if (baseTypeLattice.isPrimitive()) {
- baseType = baseTypeLattice.asPrimitiveTypeLatticeElement().toDexType(factory);
- } else {
- assert baseTypeLattice.isClassType();
- baseType = baseTypeLattice.asClassTypeLatticeElement().getClassType();
- }
- return factory.createArrayType(getNesting(), baseType);
- }
-
- int getNesting() {
- int nesting = 1;
- TypeLatticeElement member = getArrayMemberTypeAsMemberType();
- while (member.isArrayType()) {
- ++nesting;
- member = member.asArrayTypeLatticeElement().getArrayMemberTypeAsMemberType();
- }
- return nesting;
- }
-
- public TypeLatticeElement getArrayMemberTypeAsMemberType() {
- return memberTypeLattice;
- }
-
- public TypeLatticeElement getArrayMemberTypeAsValueType() {
- return memberTypeLattice.isFineGrainedType() ? getInt() : memberTypeLattice;
- }
-
- public TypeLatticeElement getArrayBaseTypeLattice() {
- TypeLatticeElement base = getArrayMemberTypeAsMemberType();
- while (base.isArrayType()) {
- base = base.asArrayTypeLatticeElement().getArrayMemberTypeAsMemberType();
- }
- return base;
- }
-
- private ArrayTypeLatticeElement createVariant(
- Nullability nullability, NullabilityVariants<ArrayTypeLatticeElement> variants) {
- assert this.nullability != nullability;
- return new ArrayTypeLatticeElement(memberTypeLattice, nullability, variants);
- }
-
- @Override
- public ReferenceTypeLatticeElement getOrCreateVariant(Nullability nullability) {
- ArrayTypeLatticeElement variant = variants.get(nullability);
- if (variant != null) {
- return variant;
- }
- return variants.getOrCreateElement(nullability, this::createVariant);
- }
-
- @Override
- public boolean isBasedOnMissingClass(AppView<? extends AppInfoWithSubtyping> appView) {
- return memberTypeLattice.isBasedOnMissingClass(appView);
- }
-
- @Override
- public boolean isArrayType() {
- return true;
- }
-
- @Override
- public ArrayTypeLatticeElement asArrayTypeLatticeElement() {
- return this;
- }
-
- @Override
- public String toString() {
- return nullability.toString() + " (" + memberTypeLattice.toString() + "[])";
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof ArrayTypeLatticeElement)) {
- return false;
- }
- ArrayTypeLatticeElement other = (ArrayTypeLatticeElement) o;
- if (nullability() != other.nullability()) {
- return false;
- }
- return memberTypeLattice.equals(other.memberTypeLattice);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(nullability, memberTypeLattice);
- }
-
- @Override
- public ArrayTypeLatticeElement fixupClassTypeReferences(
- Function<DexType, DexType> mapping, AppView<? extends AppInfoWithSubtyping> appView) {
- if (memberTypeLattice.isReference()) {
- TypeLatticeElement substitutedMemberType =
- memberTypeLattice.fixupClassTypeReferences(mapping, appView);
- if (substitutedMemberType != memberTypeLattice) {
- return ArrayTypeLatticeElement.create(substitutedMemberType, nullability);
- }
- }
- return this;
- }
-
- ReferenceTypeLatticeElement join(ArrayTypeLatticeElement other, AppView<?> appView) {
- Nullability nullability = nullability().join(other.nullability());
- ReferenceTypeLatticeElement join =
- joinMember(this.memberTypeLattice, other.memberTypeLattice, appView, nullability);
- if (join == null) {
- // Check if other has the right nullability before creating it.
- if (other.nullability == nullability) {
- return other;
- } else {
- return getOrCreateVariant(nullability);
- }
- } else {
- assert join.nullability == nullability;
- return join;
- }
- }
-
- private static ReferenceTypeLatticeElement joinMember(
- TypeLatticeElement aMember,
- TypeLatticeElement bMember,
- AppView<?> appView,
- Nullability nullability) {
- if (aMember.equals(bMember)) {
- // Return null indicating the join is the same as the member to avoid object allocation.
- return null;
- }
- if (aMember.isArrayType() && bMember.isArrayType()) {
- TypeLatticeElement join =
- joinMember(
- aMember.asArrayTypeLatticeElement().memberTypeLattice,
- bMember.asArrayTypeLatticeElement().memberTypeLattice,
- appView,
- maybeNull());
- return join == null ? null : ArrayTypeLatticeElement.create(join, nullability);
- }
- if (aMember.isClassType() && bMember.isClassType()) {
- ReferenceTypeLatticeElement join =
- aMember.asClassTypeLatticeElement().join(bMember.asClassTypeLatticeElement(), appView);
- return ArrayTypeLatticeElement.create(join, nullability);
- }
- if (aMember.isPrimitive() || bMember.isPrimitive()) {
- return objectClassType(appView, nullability);
- }
- return objectArrayType(appView, nullability);
- }
-}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/BooleanTypeLatticeElement.java b/src/main/java/com/android/tools/r8/ir/analysis/type/BooleanTypeElement.java
similarity index 71%
rename from src/main/java/com/android/tools/r8/ir/analysis/type/BooleanTypeLatticeElement.java
rename to src/main/java/com/android/tools/r8/ir/analysis/type/BooleanTypeElement.java
index 07e3503..eea19ef 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/BooleanTypeLatticeElement.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/BooleanTypeElement.java
@@ -3,11 +3,11 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.analysis.type;
-public class BooleanTypeLatticeElement extends SinglePrimitiveTypeLatticeElement {
+public class BooleanTypeElement extends SinglePrimitiveTypeElement {
- private static final BooleanTypeLatticeElement INSTANCE = new BooleanTypeLatticeElement();
+ private static final BooleanTypeElement INSTANCE = new BooleanTypeElement();
- static BooleanTypeLatticeElement getInstance() {
+ static BooleanTypeElement getInstance() {
return INSTANCE;
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/BottomTypeLatticeElement.java b/src/main/java/com/android/tools/r8/ir/analysis/type/BottomTypeElement.java
similarity index 76%
rename from src/main/java/com/android/tools/r8/ir/analysis/type/BottomTypeLatticeElement.java
rename to src/main/java/com/android/tools/r8/ir/analysis/type/BottomTypeElement.java
index 1583714..5ded712 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/BottomTypeLatticeElement.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/BottomTypeElement.java
@@ -3,15 +3,15 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.analysis.type;
-public class BottomTypeLatticeElement extends TypeLatticeElement {
- private static final BottomTypeLatticeElement INSTANCE = new BottomTypeLatticeElement();
+public class BottomTypeElement extends TypeElement {
+ private static final BottomTypeElement INSTANCE = new BottomTypeElement();
@Override
public Nullability nullability() {
return Nullability.bottom();
}
- static BottomTypeLatticeElement getInstance() {
+ static BottomTypeElement getInstance() {
return INSTANCE;
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/ByteTypeLatticeElement.java b/src/main/java/com/android/tools/r8/ir/analysis/type/ByteTypeElement.java
similarity index 72%
rename from src/main/java/com/android/tools/r8/ir/analysis/type/ByteTypeLatticeElement.java
rename to src/main/java/com/android/tools/r8/ir/analysis/type/ByteTypeElement.java
index b2df89c..c9e5e9f 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/ByteTypeLatticeElement.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/ByteTypeElement.java
@@ -3,11 +3,11 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.analysis.type;
-public class ByteTypeLatticeElement extends SinglePrimitiveTypeLatticeElement {
+public class ByteTypeElement extends SinglePrimitiveTypeElement {
- private static final ByteTypeLatticeElement INSTANCE = new ByteTypeLatticeElement();
+ private static final ByteTypeElement INSTANCE = new ByteTypeElement();
- static ByteTypeLatticeElement getInstance() {
+ static ByteTypeElement getInstance() {
return INSTANCE;
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/CharTypeLatticeElement.java b/src/main/java/com/android/tools/r8/ir/analysis/type/CharTypeElement.java
similarity index 72%
rename from src/main/java/com/android/tools/r8/ir/analysis/type/CharTypeLatticeElement.java
rename to src/main/java/com/android/tools/r8/ir/analysis/type/CharTypeElement.java
index 3ff532f..0d33bfd 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/CharTypeLatticeElement.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/CharTypeElement.java
@@ -3,11 +3,11 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.analysis.type;
-public class CharTypeLatticeElement extends SinglePrimitiveTypeLatticeElement {
+public class CharTypeElement extends SinglePrimitiveTypeElement {
- private static final CharTypeLatticeElement INSTANCE = new CharTypeLatticeElement();
+ private static final CharTypeElement INSTANCE = new CharTypeElement();
- static CharTypeLatticeElement getInstance() {
+ static CharTypeElement getInstance() {
return INSTANCE;
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/ClassTypeLatticeElement.java b/src/main/java/com/android/tools/r8/ir/analysis/type/ClassTypeElement.java
similarity index 88%
rename from src/main/java/com/android/tools/r8/ir/analysis/type/ClassTypeLatticeElement.java
rename to src/main/java/com/android/tools/r8/ir/analysis/type/ClassTypeElement.java
index 0499222..8a47047 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/ClassTypeLatticeElement.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/ClassTypeElement.java
@@ -23,38 +23,37 @@
import java.util.function.Function;
import java.util.stream.Collectors;
-public class ClassTypeLatticeElement extends ReferenceTypeLatticeElement {
+public class ClassTypeElement extends ReferenceTypeElement {
// Least upper bound of interfaces that this class type is implementing.
// Lazily computed on demand via DexItemFactory, where the canonicalized set will be maintained.
private Set<DexType> lazyInterfaces;
private AppView<? extends AppInfoWithSubtyping> appView;
// On-demand link between other nullability-variants.
- private final NullabilityVariants<ClassTypeLatticeElement> variants;
+ private final NullabilityVariants<ClassTypeElement> variants;
private final DexType type;
- public static ClassTypeLatticeElement create(
+ public static ClassTypeElement create(
DexType classType, Nullability nullability, Set<DexType> interfaces) {
assert interfaces != null;
return NullabilityVariants.create(
nullability,
- (variants) ->
- new ClassTypeLatticeElement(classType, nullability, interfaces, variants, null));
+ (variants) -> new ClassTypeElement(classType, nullability, interfaces, variants, null));
}
- public static ClassTypeLatticeElement create(
+ public static ClassTypeElement create(
DexType classType, Nullability nullability, AppView<? extends AppInfoWithSubtyping> appView) {
assert appView != null;
return NullabilityVariants.create(
nullability,
- (variants) -> new ClassTypeLatticeElement(classType, nullability, null, variants, appView));
+ (variants) -> new ClassTypeElement(classType, nullability, null, variants, appView));
}
- private ClassTypeLatticeElement(
+ private ClassTypeElement(
DexType classType,
Nullability nullability,
Set<DexType> interfaces,
- NullabilityVariants<ClassTypeLatticeElement> variants,
+ NullabilityVariants<ClassTypeElement> variants,
AppView<? extends AppInfoWithSubtyping> appView) {
super(nullability);
assert classType.isClassType();
@@ -80,20 +79,20 @@
return lazyInterfaces;
}
- private ClassTypeLatticeElement createVariant(
- Nullability nullability, NullabilityVariants<ClassTypeLatticeElement> variants) {
+ private ClassTypeElement createVariant(
+ Nullability nullability, NullabilityVariants<ClassTypeElement> variants) {
assert this.nullability != nullability;
- return new ClassTypeLatticeElement(type, nullability, lazyInterfaces, variants, appView);
+ return new ClassTypeElement(type, nullability, lazyInterfaces, variants, appView);
}
- public boolean isRelatedTo(ClassTypeLatticeElement other, AppView<?> appView) {
+ public boolean isRelatedTo(ClassTypeElement other, AppView<?> appView) {
return lessThanOrEqualUpToNullability(other, appView)
|| other.lessThanOrEqualUpToNullability(this, appView);
}
@Override
- public ClassTypeLatticeElement getOrCreateVariant(Nullability nullability) {
- ClassTypeLatticeElement variant = variants.get(nullability);
+ public ClassTypeElement getOrCreateVariant(Nullability nullability) {
+ ClassTypeElement variant = variants.get(nullability);
if (variant != null) {
return variant;
}
@@ -114,12 +113,12 @@
}
@Override
- public ClassTypeLatticeElement asClassTypeLatticeElement() {
+ public ClassTypeElement asClassType() {
return this;
}
@Override
- public ClassTypeLatticeElement asMeetWithNotNull() {
+ public ClassTypeElement asMeetWithNotNull() {
return getOrCreateVariant(nullability.meet(Nullability.definitelyNotNull()));
}
@@ -145,11 +144,11 @@
}
@Override
- public TypeLatticeElement fixupClassTypeReferences(
+ public TypeElement fixupClassTypeReferences(
Function<DexType, DexType> mapping, AppView<? extends AppInfoWithSubtyping> appView) {
DexType mappedType = mapping.apply(type);
if (mappedType.isPrimitiveType()) {
- return PrimitiveTypeLatticeElement.fromDexType(mappedType, false);
+ return PrimitiveTypeElement.fromDexType(mappedType, false);
}
if (mappedType != type) {
return create(mappedType, nullability, appView);
@@ -196,12 +195,12 @@
return this;
}
- ClassTypeLatticeElement join(ClassTypeLatticeElement other, AppView<?> appView) {
+ ClassTypeElement join(ClassTypeElement other, AppView<?> appView) {
Nullability nullability = nullability().join(other.nullability());
if (!appView.appInfo().hasSubtyping()) {
assert lazyInterfaces != null && lazyInterfaces.isEmpty();
assert other.lazyInterfaces != null && other.lazyInterfaces.isEmpty();
- return ClassTypeLatticeElement.create(
+ return ClassTypeElement.create(
getClassType() == other.getClassType()
? getClassType()
: appView.dexItemFactory().objectType,
@@ -220,7 +219,7 @@
if (lubItfs == null) {
lubItfs = computeLeastUpperBoundOfInterfaces(appView.withSubtyping(), c1lubItfs, c2lubItfs);
}
- return ClassTypeLatticeElement.create(lubType, nullability, lubItfs);
+ return ClassTypeElement.create(lubType, nullability, lubItfs);
}
private enum InterfaceMarker {
@@ -371,10 +370,10 @@
if (this == o) {
return true;
}
- if (!(o instanceof ClassTypeLatticeElement)) {
+ if (!(o instanceof ClassTypeElement)) {
return false;
}
- ClassTypeLatticeElement other = (ClassTypeLatticeElement) o;
+ ClassTypeElement other = (ClassTypeElement) o;
if (nullability() != other.nullability()) {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/DestructivePhiTypeUpdater.java b/src/main/java/com/android/tools/r8/ir/analysis/type/DestructivePhiTypeUpdater.java
index 6449294..3e34256 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/DestructivePhiTypeUpdater.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/DestructivePhiTypeUpdater.java
@@ -40,7 +40,7 @@
Deque<Phi> worklist = new ArrayDeque<>(affectedPhis);
while (!worklist.isEmpty()) {
Phi phi = worklist.poll();
- phi.setTypeLattice(TypeLatticeElement.getBottom());
+ phi.setType(TypeElement.getBottom());
for (Phi affectedPhi : phi.uniquePhiUsers()) {
if (affectedPhis.add(affectedPhi)) {
worklist.add(affectedPhi);
@@ -56,10 +56,10 @@
worklist.addAll(affectedPhis);
while (!worklist.isEmpty()) {
Phi phi = worklist.poll();
- TypeLatticeElement newType = phi.computePhiType(appView);
- if (!phi.getTypeLattice().equals(newType)) {
+ TypeElement newType = phi.computePhiType(appView);
+ if (!phi.getType().equals(newType)) {
assert !newType.isBottom();
- phi.setTypeLattice(newType);
+ phi.setType(newType);
worklist.addAll(phi.uniquePhiUsers());
affectedValues.addAll(phi.affectedValues());
}
@@ -80,12 +80,12 @@
for (Value operand : phi.getOperands()) {
if (operand.isPhi()) {
Phi operandPhi = operand.asPhi();
- TypeLatticeElement operandType = operandPhi.getTypeLattice();
+ TypeElement operandType = operandPhi.getType();
assert !affectedPhis.contains(operandPhi) || operandType.isBottom();
assert affectedPhis.contains(operandPhi)
- || operandType.isPrimitive()
+ || operandType.isPrimitiveType()
|| operandType.isNullType()
- || (operandType.isReference()
+ || (operandType.isReferenceType()
&& operandType.fixupClassTypeReferences(mapping, appView) == operandType);
}
}
@@ -98,9 +98,9 @@
while (blocks.hasNext()) {
BasicBlock block = blocks.next();
for (Phi phi : block.getPhis()) {
- TypeLatticeElement phiTypeLattice = phi.getTypeLattice();
- TypeLatticeElement substituted = phiTypeLattice.fixupClassTypeReferences(mapping, appView);
- assert substituted == phiTypeLattice || affectedPhis.contains(phi);
+ TypeElement phiType = phi.getType();
+ TypeElement substituted = phiType.fixupClassTypeReferences(mapping, appView);
+ assert substituted == phiType || affectedPhis.contains(phi);
}
}
return true;
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/DoubleTypeLatticeElement.java b/src/main/java/com/android/tools/r8/ir/analysis/type/DoubleTypeElement.java
similarity index 69%
rename from src/main/java/com/android/tools/r8/ir/analysis/type/DoubleTypeLatticeElement.java
rename to src/main/java/com/android/tools/r8/ir/analysis/type/DoubleTypeElement.java
index 3f521c2..e9632a8 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/DoubleTypeLatticeElement.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/DoubleTypeElement.java
@@ -3,11 +3,11 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.analysis.type;
-public class DoubleTypeLatticeElement extends WidePrimitiveTypeLatticeElement {
+public class DoubleTypeElement extends WidePrimitiveTypeElement {
- private static final DoubleTypeLatticeElement INSTANCE = new DoubleTypeLatticeElement();
+ private static final DoubleTypeElement INSTANCE = new DoubleTypeElement();
- static DoubleTypeLatticeElement getInstance() {
+ static DoubleTypeElement getInstance() {
return INSTANCE;
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/FloatTypeLatticeElement.java b/src/main/java/com/android/tools/r8/ir/analysis/type/FloatTypeElement.java
similarity index 69%
rename from src/main/java/com/android/tools/r8/ir/analysis/type/FloatTypeLatticeElement.java
rename to src/main/java/com/android/tools/r8/ir/analysis/type/FloatTypeElement.java
index 69933a0..386981d 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/FloatTypeLatticeElement.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/FloatTypeElement.java
@@ -3,10 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.analysis.type;
-public class FloatTypeLatticeElement extends SinglePrimitiveTypeLatticeElement {
- private static final FloatTypeLatticeElement INSTANCE = new FloatTypeLatticeElement();
+public class FloatTypeElement extends SinglePrimitiveTypeElement {
+ private static final FloatTypeElement INSTANCE = new FloatTypeElement();
- static FloatTypeLatticeElement getInstance() {
+ static FloatTypeElement getInstance() {
return INSTANCE;
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/IntTypeLatticeElement.java b/src/main/java/com/android/tools/r8/ir/analysis/type/IntTypeElement.java
similarity index 70%
rename from src/main/java/com/android/tools/r8/ir/analysis/type/IntTypeLatticeElement.java
rename to src/main/java/com/android/tools/r8/ir/analysis/type/IntTypeElement.java
index 2d7e5b3..5ecb417 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/IntTypeLatticeElement.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/IntTypeElement.java
@@ -3,10 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.analysis.type;
-public class IntTypeLatticeElement extends SinglePrimitiveTypeLatticeElement {
- private static final IntTypeLatticeElement INSTANCE = new IntTypeLatticeElement();
+public class IntTypeElement extends SinglePrimitiveTypeElement {
+ private static final IntTypeElement INSTANCE = new IntTypeElement();
- static IntTypeLatticeElement getInstance() {
+ static IntTypeElement getInstance() {
return INSTANCE;
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/LongTypeLatticeElement.java b/src/main/java/com/android/tools/r8/ir/analysis/type/LongTypeElement.java
similarity index 70%
rename from src/main/java/com/android/tools/r8/ir/analysis/type/LongTypeLatticeElement.java
rename to src/main/java/com/android/tools/r8/ir/analysis/type/LongTypeElement.java
index db3ef45..caf2ed3 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/LongTypeLatticeElement.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/LongTypeElement.java
@@ -3,11 +3,11 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.analysis.type;
-public class LongTypeLatticeElement extends WidePrimitiveTypeLatticeElement {
+public class LongTypeElement extends WidePrimitiveTypeElement {
- private static final LongTypeLatticeElement INSTANCE = new LongTypeLatticeElement();
+ private static final LongTypeElement INSTANCE = new LongTypeElement();
- static LongTypeLatticeElement getInstance() {
+ static LongTypeElement getInstance() {
return INSTANCE;
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/NullabilityVariants.java b/src/main/java/com/android/tools/r8/ir/analysis/type/NullabilityVariants.java
index 9a0f95a..2c76787 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/NullabilityVariants.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/NullabilityVariants.java
@@ -7,14 +7,14 @@
import java.util.function.BiFunction;
import java.util.function.Function;
-public class NullabilityVariants<T extends ReferenceTypeLatticeElement> {
+public class NullabilityVariants<T extends ReferenceTypeElement> {
private T maybeNullVariant;
private T definitelyNullVariant;
private T definitelyNotNullVariant;
private T bottomVariant;
- public static <T extends ReferenceTypeLatticeElement> T create(
+ public static <T extends ReferenceTypeElement> T create(
Nullability nullability, Function<NullabilityVariants<T>, T> callback) {
NullabilityVariants<T> variants = new NullabilityVariants<>();
T newElement = callback.apply(variants);
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/PrimitiveTypeLatticeElement.java b/src/main/java/com/android/tools/r8/ir/analysis/type/PrimitiveTypeElement.java
similarity index 68%
rename from src/main/java/com/android/tools/r8/ir/analysis/type/PrimitiveTypeLatticeElement.java
rename to src/main/java/com/android/tools/r8/ir/analysis/type/PrimitiveTypeElement.java
index 6a16fdc..4e9b5f1a 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/PrimitiveTypeLatticeElement.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/PrimitiveTypeElement.java
@@ -9,10 +9,8 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.code.NumericType;
-/**
- * A {@link TypeLatticeElement} that abstracts primitive types.
- */
-public abstract class PrimitiveTypeLatticeElement extends TypeLatticeElement {
+/** A {@link TypeElement} that abstracts primitive types. */
+public abstract class PrimitiveTypeElement extends TypeElement {
@Override
public Nullability nullability() {
@@ -20,16 +18,16 @@
}
@Override
- public boolean isPrimitive() {
+ public boolean isPrimitiveType() {
return true;
}
@Override
- public PrimitiveTypeLatticeElement asPrimitiveTypeLatticeElement() {
+ public PrimitiveTypeElement asPrimitiveType() {
return this;
}
- static PrimitiveTypeLatticeElement fromDexType(DexType type, boolean asArrayElementType) {
+ static PrimitiveTypeElement fromDexType(DexType type, boolean asArrayElementType) {
assert type.isPrimitiveType();
return fromTypeDescriptorChar((char) type.descriptor.content[0], asArrayElementType);
}
@@ -73,37 +71,37 @@
|| isDouble();
}
- private static PrimitiveTypeLatticeElement fromTypeDescriptorChar(
+ private static PrimitiveTypeElement fromTypeDescriptorChar(
char descriptor, boolean asArrayElementType) {
switch (descriptor) {
case 'Z':
if (asArrayElementType) {
- return TypeLatticeElement.getBoolean();
+ return TypeElement.getBoolean();
}
// fall through
case 'B':
if (asArrayElementType) {
- return TypeLatticeElement.getByte();
+ return TypeElement.getByte();
}
// fall through
case 'S':
if (asArrayElementType) {
- return TypeLatticeElement.getShort();
+ return TypeElement.getShort();
}
// fall through
case 'C':
if (asArrayElementType) {
- return TypeLatticeElement.getChar();
+ return TypeElement.getChar();
}
// fall through
case 'I':
- return TypeLatticeElement.getInt();
+ return TypeElement.getInt();
case 'F':
- return TypeLatticeElement.getFloat();
+ return TypeElement.getFloat();
case 'J':
- return TypeLatticeElement.getLong();
+ return TypeElement.getLong();
case 'D':
- return TypeLatticeElement.getDouble();
+ return TypeElement.getDouble();
case 'V':
throw new InternalCompilerError("No value type for void type.");
default:
@@ -111,40 +109,40 @@
}
}
- public static PrimitiveTypeLatticeElement fromNumericType(NumericType numericType) {
+ public static PrimitiveTypeElement fromNumericType(NumericType numericType) {
switch(numericType) {
case BYTE:
case CHAR:
case SHORT:
case INT:
- return TypeLatticeElement.getInt();
+ return TypeElement.getInt();
case FLOAT:
- return TypeLatticeElement.getFloat();
+ return TypeElement.getFloat();
case LONG:
- return TypeLatticeElement.getLong();
+ return TypeElement.getLong();
case DOUBLE:
- return TypeLatticeElement.getDouble();
+ return TypeElement.getDouble();
default:
throw new Unreachable("Invalid numeric type '" + numericType + "'");
}
}
- TypeLatticeElement join(PrimitiveTypeLatticeElement other) {
+ TypeElement join(PrimitiveTypeElement other) {
if (this == other) {
return this;
}
if (isSinglePrimitive()) {
if (other.isSinglePrimitive()) {
- return TypeLatticeElement.getSingle();
+ return TypeElement.getSingle();
}
assert other.isWidePrimitive();
- return TypeLatticeElement.getTop();
+ return TypeElement.getTop();
}
assert isWidePrimitive();
if (other.isWidePrimitive()) {
- return TypeLatticeElement.getWide();
+ return TypeElement.getWide();
}
assert other.isSinglePrimitive();
- return TypeLatticeElement.getTop();
+ return TypeElement.getTop();
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/ReferenceTypeElement.java b/src/main/java/com/android/tools/r8/ir/analysis/type/ReferenceTypeElement.java
new file mode 100644
index 0000000..c150cfd
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/ReferenceTypeElement.java
@@ -0,0 +1,108 @@
+// Copyright (c) 2018, 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.ir.analysis.type;
+
+import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.graph.DexItemFactory;
+
+public abstract class ReferenceTypeElement extends TypeElement {
+
+ private static class NullElement extends ReferenceTypeElement {
+
+ NullElement(Nullability nullability) {
+ super(nullability);
+ }
+
+ @Override
+ public ReferenceTypeElement getOrCreateVariant(Nullability nullability) {
+ return nullability.isNullable() ? NULL_INSTANCE : NULL_BOTTOM_INSTANCE;
+ }
+
+ private static NullElement create() {
+ return new NullElement(Nullability.definitelyNull());
+ }
+
+ private static NullElement createBottom() {
+ return new NullElement(Nullability.bottom());
+ }
+
+ @Override
+ public boolean isNullType() {
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return nullability.toString() + " " + DexItemFactory.nullValueType.toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return System.identityHashCode(this);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof NullElement)) {
+ return false;
+ }
+ return true;
+ }
+ }
+
+ private static final ReferenceTypeElement NULL_INSTANCE = NullElement.create();
+ private static final ReferenceTypeElement NULL_BOTTOM_INSTANCE = NullElement.createBottom();
+
+ final Nullability nullability;
+
+ ReferenceTypeElement(Nullability nullability) {
+ this.nullability = nullability;
+ }
+
+ @Override
+ public Nullability nullability() {
+ return nullability;
+ }
+
+ static ReferenceTypeElement getNullType() {
+ return NULL_INSTANCE;
+ }
+
+ public abstract ReferenceTypeElement getOrCreateVariant(Nullability nullability);
+
+ public TypeElement asMeetWithNotNull() {
+ return getOrCreateVariant(nullability.meet(Nullability.definitelyNotNull()));
+ }
+
+ public TypeElement asDefinitelyNotNull() {
+ return getOrCreateVariant(Nullability.definitelyNotNull());
+ }
+
+ public TypeElement asMaybeNull() {
+ return getOrCreateVariant(Nullability.maybeNull());
+ }
+
+ @Override
+ public boolean isReferenceType() {
+ return true;
+ }
+
+ @Override
+ public ReferenceTypeElement asReferenceType() {
+ return this;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ throw new Unreachable("Should be implemented on each sub type");
+ }
+
+ @Override
+ public int hashCode() {
+ throw new Unreachable("Should be implemented on each sub type");
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/ReferenceTypeLatticeElement.java b/src/main/java/com/android/tools/r8/ir/analysis/type/ReferenceTypeLatticeElement.java
deleted file mode 100644
index b888ae5..0000000
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/ReferenceTypeLatticeElement.java
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright (c) 2018, 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.ir.analysis.type;
-
-import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.DexItemFactory;
-
-public abstract class ReferenceTypeLatticeElement extends TypeLatticeElement {
-
- private static class NullLatticeElement extends ReferenceTypeLatticeElement {
-
- NullLatticeElement(Nullability nullability) {
- super(nullability);
- }
-
- @Override
- public ReferenceTypeLatticeElement getOrCreateVariant(Nullability nullability) {
- return nullability.isNullable() ? NULL_INSTANCE : NULL_BOTTOM_INSTANCE;
- }
-
- private static NullLatticeElement create() {
- return new NullLatticeElement(Nullability.definitelyNull());
- }
-
- private static NullLatticeElement createBottom() {
- return new NullLatticeElement(Nullability.bottom());
- }
-
- @Override
- public boolean isNullType() {
- return true;
- }
-
- @Override
- public String toString() {
- return nullability.toString() + " " + DexItemFactory.nullValueType.toString();
- }
-
- @Override
- public int hashCode() {
- return System.identityHashCode(this);
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof NullLatticeElement)) {
- return false;
- }
- return true;
- }
- }
-
- private static final ReferenceTypeLatticeElement NULL_INSTANCE = NullLatticeElement.create();
- private static final ReferenceTypeLatticeElement NULL_BOTTOM_INSTANCE =
- NullLatticeElement.createBottom();
-
- final Nullability nullability;
-
- ReferenceTypeLatticeElement(Nullability nullability) {
- this.nullability = nullability;
- }
-
- @Override
- public Nullability nullability() {
- return nullability;
- }
-
- static ReferenceTypeLatticeElement getNullTypeLatticeElement() {
- return NULL_INSTANCE;
- }
-
- public abstract ReferenceTypeLatticeElement getOrCreateVariant(Nullability nullability);
-
- public TypeLatticeElement asMeetWithNotNull() {
- return getOrCreateVariant(nullability.meet(Nullability.definitelyNotNull()));
- }
-
- public TypeLatticeElement asDefinitelyNotNull() {
- return getOrCreateVariant(Nullability.definitelyNotNull());
- }
-
- public TypeLatticeElement asMaybeNull() {
- return getOrCreateVariant(Nullability.maybeNull());
- }
-
- @Override
- public boolean isReference() {
- return true;
- }
-
- @Override
- public ReferenceTypeLatticeElement asReferenceTypeLatticeElement() {
- return this;
- }
-
- @Override
- public boolean equals(Object o) {
- throw new Unreachable("Should be implemented on each sub type");
- }
-
- @Override
- public int hashCode() {
- throw new Unreachable("Should be implemented on each sub type");
- }
-}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/ShortTypeLatticeElement.java b/src/main/java/com/android/tools/r8/ir/analysis/type/ShortTypeElement.java
similarity index 72%
rename from src/main/java/com/android/tools/r8/ir/analysis/type/ShortTypeLatticeElement.java
rename to src/main/java/com/android/tools/r8/ir/analysis/type/ShortTypeElement.java
index 85bd6fc..61b8514 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/ShortTypeLatticeElement.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/ShortTypeElement.java
@@ -3,11 +3,11 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.analysis.type;
-public class ShortTypeLatticeElement extends SinglePrimitiveTypeLatticeElement {
+public class ShortTypeElement extends SinglePrimitiveTypeElement {
- private static final ShortTypeLatticeElement INSTANCE = new ShortTypeLatticeElement();
+ private static final ShortTypeElement INSTANCE = new ShortTypeElement();
- static ShortTypeLatticeElement getInstance() {
+ static ShortTypeElement getInstance() {
return INSTANCE;
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/SinglePrimitiveTypeLatticeElement.java b/src/main/java/com/android/tools/r8/ir/analysis/type/SinglePrimitiveTypeElement.java
similarity index 61%
rename from src/main/java/com/android/tools/r8/ir/analysis/type/SinglePrimitiveTypeLatticeElement.java
rename to src/main/java/com/android/tools/r8/ir/analysis/type/SinglePrimitiveTypeElement.java
index 2a94fb5..40436d1 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/SinglePrimitiveTypeLatticeElement.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/SinglePrimitiveTypeElement.java
@@ -3,17 +3,16 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.analysis.type;
-/** A {@link TypeLatticeElement} that abstracts primitive types, which fit in 32 bits. */
-public class SinglePrimitiveTypeLatticeElement extends PrimitiveTypeLatticeElement {
+/** A {@link TypeElement} that abstracts primitive types, which fit in 32 bits. */
+public class SinglePrimitiveTypeElement extends PrimitiveTypeElement {
- private static final SinglePrimitiveTypeLatticeElement INSTANCE =
- new SinglePrimitiveTypeLatticeElement();
+ private static final SinglePrimitiveTypeElement INSTANCE = new SinglePrimitiveTypeElement();
- SinglePrimitiveTypeLatticeElement() {
+ SinglePrimitiveTypeElement() {
super();
}
- static SinglePrimitiveTypeLatticeElement getInstance() {
+ static SinglePrimitiveTypeElement getInstance() {
return INSTANCE;
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/TopTypeLatticeElement.java b/src/main/java/com/android/tools/r8/ir/analysis/type/TopTypeElement.java
similarity index 77%
rename from src/main/java/com/android/tools/r8/ir/analysis/type/TopTypeLatticeElement.java
rename to src/main/java/com/android/tools/r8/ir/analysis/type/TopTypeElement.java
index 1d483e8..6c7fec2 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/TopTypeLatticeElement.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/TopTypeElement.java
@@ -3,15 +3,15 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.analysis.type;
-public class TopTypeLatticeElement extends TypeLatticeElement {
- private static final TopTypeLatticeElement INSTANCE = new TopTypeLatticeElement();
+public class TopTypeElement extends TypeElement {
+ private static final TopTypeElement INSTANCE = new TopTypeElement();
@Override
public Nullability nullability() {
return Nullability.maybeNull();
}
- static TopTypeLatticeElement getInstance() {
+ static TopTypeElement getInstance() {
return INSTANCE;
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/TypeAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/type/TypeAnalysis.java
index 0596d7b..3d1c2b5 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/TypeAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/TypeAnalysis.java
@@ -101,7 +101,7 @@
// The type for Argument, a quasi instruction is already set correctly during IR building.
// Note that we don't need to enqueue the out value of arguments here because it's constant.
} else if (instruction.hasInvariantOutType()) {
- TypeLatticeElement derived = instruction.evaluate(appView);
+ TypeElement derived = instruction.evaluate(appView);
updateTypeOfValue(outValue, derived);
} else {
enqueue(outValue);
@@ -113,18 +113,18 @@
}
private void analyzeValue(Value value) {
- TypeLatticeElement previous = value.getTypeLattice();
- TypeLatticeElement derived =
+ TypeElement previous = value.getType();
+ TypeElement derived =
value.isPhi() ? value.asPhi().computePhiType(appView) : value.definition.evaluate(appView);
assert mayHaveImpreciseTypes || derived.isPreciseType();
assert !previous.isPreciseType() || derived.isPreciseType();
updateTypeOfValue(value, derived);
}
- private void updateTypeOfValue(Value value, TypeLatticeElement type) {
+ private void updateTypeOfValue(Value value, TypeElement type) {
assert mode != Mode.UNSET;
- TypeLatticeElement current = value.getTypeLattice();
+ TypeElement current = value.getType();
if (current.equals(type)) {
return;
}
@@ -158,10 +158,10 @@
public static DexType getRefinedReceiverType(
AppView<? extends AppInfoWithSubtyping> appView, InvokeMethodWithReceiver invoke) {
Value receiver = invoke.getReceiver();
- TypeLatticeElement lattice = receiver.getDynamicUpperBoundType(appView);
+ TypeElement lattice = receiver.getDynamicUpperBoundType(appView);
DexType staticReceiverType = invoke.getInvokedMethod().holder;
if (lattice.isClassType()) {
- ClassTypeLatticeElement classType = lattice.asClassTypeLatticeElement();
+ ClassTypeElement classType = lattice.asClassType();
DexType refinedType = classType.getClassType();
if (refinedType == appView.dexItemFactory().objectType) {
Set<DexType> interfaces = classType.getInterfaces();
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/TypeElement.java b/src/main/java/com/android/tools/r8/ir/analysis/type/TypeElement.java
new file mode 100644
index 0000000..ecc7340
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/TypeElement.java
@@ -0,0 +1,422 @@
+// 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.ir.analysis.type;
+
+import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.graph.AppInfoWithSubtyping;
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexDefinitionSupplier;
+import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.ir.code.Value;
+import java.util.function.Function;
+
+/** The base abstraction of lattice elements for local type analysis. */
+public abstract class TypeElement {
+
+ public static BottomTypeElement getBottom() {
+ return BottomTypeElement.getInstance();
+ }
+
+ public static TopTypeElement getTop() {
+ return TopTypeElement.getInstance();
+ }
+
+ public static BooleanTypeElement getBoolean() {
+ return BooleanTypeElement.getInstance();
+ }
+
+ public static ByteTypeElement getByte() {
+ return ByteTypeElement.getInstance();
+ }
+
+ public static ShortTypeElement getShort() {
+ return ShortTypeElement.getInstance();
+ }
+
+ public static CharTypeElement getChar() {
+ return CharTypeElement.getInstance();
+ }
+
+ public static IntTypeElement getInt() {
+ return IntTypeElement.getInstance();
+ }
+
+ public static FloatTypeElement getFloat() {
+ return FloatTypeElement.getInstance();
+ }
+
+ public static SinglePrimitiveTypeElement getSingle() {
+ return SinglePrimitiveTypeElement.getInstance();
+ }
+
+ public static LongTypeElement getLong() {
+ return LongTypeElement.getInstance();
+ }
+
+ public static DoubleTypeElement getDouble() {
+ return DoubleTypeElement.getInstance();
+ }
+
+ public static WidePrimitiveTypeElement getWide() {
+ return WidePrimitiveTypeElement.getInstance();
+ }
+
+ public static ReferenceTypeElement getNull() {
+ return ReferenceTypeElement.getNullType();
+ }
+
+ public TypeElement fixupClassTypeReferences(
+ Function<DexType, DexType> mapping, AppView<? extends AppInfoWithSubtyping> appView) {
+ return this;
+ }
+
+ public boolean isNullable() {
+ return nullability().isNullable();
+ }
+
+ public abstract Nullability nullability();
+
+ /**
+ * Computes the least upper bound of the current and the other elements.
+ *
+ * @param other {@link TypeElement} to join.
+ * @param appView {@link DexDefinitionSupplier}.
+ * @return {@link TypeElement}, a least upper bound of {@param this} and {@param other}.
+ */
+ public TypeElement join(TypeElement other, AppView<?> appView) {
+ if (this == other) {
+ return this;
+ }
+ if (isBottom()) {
+ return other;
+ }
+ if (other.isBottom()) {
+ return this;
+ }
+ if (isTop() || other.isTop()) {
+ return getTop();
+ }
+ if (isPrimitiveType()) {
+ return other.isPrimitiveType() ? asPrimitiveType().join(other.asPrimitiveType()) : getTop();
+ }
+ if (other.isPrimitiveType()) {
+ // By the above case, !(isPrimitive())
+ return getTop();
+ }
+ // From now on, this and other are precise reference types, i.e., either ArrayType or ClassType.
+ assert isReferenceType() && other.isReferenceType();
+ assert isPreciseType() && other.isPreciseType();
+ Nullability nullabilityJoin = nullability().join(other.nullability());
+ if (isNullType()) {
+ return other.asReferenceType().getOrCreateVariant(nullabilityJoin);
+ }
+ if (other.isNullType()) {
+ return this.asReferenceType().getOrCreateVariant(nullabilityJoin);
+ }
+ if (getClass() != other.getClass()) {
+ return objectClassType(appView, nullabilityJoin);
+ }
+ // From now on, getClass() == other.getClass()
+ if (isArrayType()) {
+ assert other.isArrayType();
+ return asArrayType().join(other.asArrayType(), appView);
+ }
+ if (isClassType()) {
+ assert other.isClassType();
+ return asClassType().join(other.asClassType(), appView);
+ }
+ throw new Unreachable("unless a new type lattice is introduced.");
+ }
+
+ public static TypeElement join(Iterable<TypeElement> typeLattices, AppView<?> appView) {
+ TypeElement result = getBottom();
+ for (TypeElement other : typeLattices) {
+ result = result.join(other, appView);
+ }
+ return result;
+ }
+
+ /**
+ * Determines the strict partial order of the given {@link TypeElement}s.
+ *
+ * @param other expected to be *strictly* bigger than {@param this}
+ * @param appView {@link DexDefinitionSupplier} to compute the least upper bound of {@link
+ * TypeElement}
+ * @return {@code true} if {@param this} is strictly less than {@param other}.
+ */
+ public boolean strictlyLessThan(TypeElement other, AppView<?> appView) {
+ if (equals(other)) {
+ return false;
+ }
+ TypeElement lub = join(other, appView);
+ return !equals(lub) && other.equals(lub);
+ }
+
+ /**
+ * Determines the partial order of the given {@link TypeElement}s.
+ *
+ * @param other expected to be bigger than or equal to {@param this}
+ * @param appView {@link DexDefinitionSupplier} to compute the least upper bound of {@link
+ * TypeElement}
+ * @return {@code true} if {@param this} is less than or equal to {@param other}.
+ */
+ public boolean lessThanOrEqual(TypeElement other, AppView<?> appView) {
+ return equals(other) || strictlyLessThan(other, appView);
+ }
+
+ /**
+ * Determines if this {@link TypeElement} is less than or equal to the given {@link TypeElement}
+ * up to nullability.
+ *
+ * @param other to check for equality with this
+ * @return {@code true} if {@param this} is equal up to nullability with {@param other}.
+ */
+ public boolean lessThanOrEqualUpToNullability(TypeElement other, AppView<?> appView) {
+ if (this == other) {
+ return true;
+ }
+ if (this.isTop()) {
+ return other.isTop();
+ }
+ if (other.isTop()) {
+ return true;
+ }
+ if (this.isBottom()) {
+ return true;
+ }
+ if (other.isBottom()) {
+ return false;
+ }
+ if (isPrimitiveType()) {
+ // Primitives cannot be nullable.
+ return lessThanOrEqual(other, appView);
+ }
+ assert isReferenceType() && other.isReferenceType();
+ ReferenceTypeElement otherAsNullable =
+ other.isNullable()
+ ? other.asReferenceType()
+ : other.asReferenceType().getOrCreateVariant(Nullability.maybeNull());
+ return lessThanOrEqual(otherAsNullable, appView);
+ }
+
+ /**
+ * Determines if the {@link TypeElement}s are equal up to nullability.
+ *
+ * @param other to check for equality with this
+ * @return {@code true} if {@param this} is equal up to nullability with {@param other}.
+ */
+ public boolean equalUpToNullability(TypeElement other) {
+ if (this == other) {
+ return true;
+ }
+ if (isPrimitiveType() || other.isPrimitiveType()) {
+ return false;
+ }
+ assert isReferenceType() && other.isReferenceType();
+ ReferenceTypeElement thisAsMaybeNull =
+ this.asReferenceType().getOrCreateVariant(Nullability.maybeNull());
+ ReferenceTypeElement otherAsMaybeNull =
+ other.asReferenceType().getOrCreateVariant(Nullability.maybeNull());
+ return thisAsMaybeNull.equals(otherAsMaybeNull);
+ }
+
+ /**
+ * Determines if this type is based on a missing class, directly or indirectly.
+ *
+ * @return {@code} true if this type is based on a missing class.
+ * @param appView
+ */
+ public boolean isBasedOnMissingClass(AppView<? extends AppInfoWithSubtyping> appView) {
+ return false;
+ }
+
+ /**
+ * Represents a type that can be everything.
+ *
+ * @return {@code true} if the corresponding {@link Value} could be any kinds.
+ */
+ public boolean isTop() {
+ return false;
+ }
+
+ /**
+ * Represents an empty type.
+ *
+ * @return {@code true} if the type of corresponding {@link Value} is not determined yet.
+ */
+ public boolean isBottom() {
+ return false;
+ }
+
+ public boolean isReferenceType() {
+ return false;
+ }
+
+ public ReferenceTypeElement asReferenceType() {
+ return null;
+ }
+
+ public boolean isArrayType() {
+ return false;
+ }
+
+ public ArrayTypeElement asArrayType() {
+ return null;
+ }
+
+ public boolean isClassType() {
+ return false;
+ }
+
+ public ClassTypeElement asClassType() {
+ return null;
+ }
+
+ public boolean isPrimitiveType() {
+ return false;
+ }
+
+ public PrimitiveTypeElement asPrimitiveType() {
+ return null;
+ }
+
+ public boolean isSinglePrimitive() {
+ return false;
+ }
+
+ public boolean isWidePrimitive() {
+ return false;
+ }
+
+ boolean isBoolean() {
+ return false;
+ }
+
+ boolean isByte() {
+ return false;
+ }
+
+ boolean isShort() {
+ return false;
+ }
+
+ boolean isChar() {
+ return false;
+ }
+
+ public boolean isInt() {
+ return false;
+ }
+
+ public boolean isFloat() {
+ return false;
+ }
+
+ public boolean isLong() {
+ return false;
+ }
+
+ public boolean isDouble() {
+ return false;
+ }
+
+ public boolean isPreciseType() {
+ return isArrayType()
+ || isClassType()
+ || isNullType()
+ || isInt()
+ || isFloat()
+ || isLong()
+ || isDouble()
+ || isBottom();
+ }
+
+ public boolean isFineGrainedType() {
+ return isBoolean()
+ || isByte()
+ || isShort()
+ || isChar();
+ }
+
+ /**
+ * Determines if this type only includes null values that are defined by a const-number
+ * instruction in the same enclosing method.
+ *
+ * These null values can be assigned to any type.
+ */
+ public boolean isNullType() {
+ return false;
+ }
+
+ /**
+ * Determines if this type only includes null values.
+ *
+ * These null values cannot be assigned to any type. For example, it is a type error to "throw v"
+ * where the value `v` satisfies isDefinitelyNull(), because the static type of `v` may not be a
+ * subtype of Throwable.
+ */
+ public boolean isDefinitelyNull() {
+ return nullability().isDefinitelyNull();
+ }
+
+ public boolean isDefinitelyNotNull() {
+ return nullability().isDefinitelyNotNull();
+ }
+
+ public int requiredRegisters() {
+ assert !isBottom() && !isTop();
+ return 1;
+ }
+
+ public static ClassTypeElement objectClassType(AppView<?> appView, Nullability nullability) {
+ return fromDexType(appView.dexItemFactory().objectType, nullability, appView).asClassType();
+ }
+
+ static ArrayTypeElement objectArrayType(AppView<?> appView, Nullability nullability) {
+ DexItemFactory dexItemFactory = appView.dexItemFactory();
+ return fromDexType(
+ dexItemFactory.createArrayType(1, dexItemFactory.objectType), nullability, appView)
+ .asArrayType();
+ }
+
+ public static ClassTypeElement classClassType(AppView<?> appView, Nullability nullability) {
+ return fromDexType(appView.dexItemFactory().classType, nullability, appView).asClassType();
+ }
+
+ public static ClassTypeElement stringClassType(AppView<?> appView, Nullability nullability) {
+ return fromDexType(appView.dexItemFactory().stringType, nullability, appView).asClassType();
+ }
+
+ public static TypeElement fromDexType(DexType type, Nullability nullability, AppView<?> appView) {
+ return fromDexType(type, nullability, appView, false);
+ }
+
+ public static TypeElement fromDexType(
+ DexType type, Nullability nullability, AppView<?> appView, boolean asArrayElementType) {
+ if (type == DexItemFactory.nullValueType) {
+ assert !nullability.isDefinitelyNotNull();
+ return getNull();
+ }
+ if (type.isPrimitiveType()) {
+ return PrimitiveTypeElement.fromDexType(type, asArrayElementType);
+ }
+ return appView.dexItemFactory().createReferenceTypeElement(type, nullability, appView);
+ }
+
+ public boolean isValueTypeCompatible(TypeElement other) {
+ return (isReferenceType() && other.isReferenceType())
+ || (isSinglePrimitive() && other.isSinglePrimitive())
+ || (isWidePrimitive() && other.isWidePrimitive());
+ }
+
+ @Override
+ public abstract String toString();
+
+ @Override
+ public abstract boolean equals(Object o);
+
+ @Override
+ public abstract int hashCode();
+}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/TypeLatticeElement.java b/src/main/java/com/android/tools/r8/ir/analysis/type/TypeLatticeElement.java
deleted file mode 100644
index de7b894..0000000
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/TypeLatticeElement.java
+++ /dev/null
@@ -1,434 +0,0 @@
-// 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.ir.analysis.type;
-
-import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.AppInfoWithSubtyping;
-import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexDefinitionSupplier;
-import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.code.Value;
-import java.util.function.Function;
-
-/**
- * The base abstraction of lattice elements for local type analysis.
- */
-public abstract class TypeLatticeElement {
-
- public static BottomTypeLatticeElement getBottom() {
- return BottomTypeLatticeElement.getInstance();
- }
-
- public static TopTypeLatticeElement getTop() {
- return TopTypeLatticeElement.getInstance();
- }
-
- public static BooleanTypeLatticeElement getBoolean() {
- return BooleanTypeLatticeElement.getInstance();
- }
-
- public static ByteTypeLatticeElement getByte() {
- return ByteTypeLatticeElement.getInstance();
- }
-
- public static ShortTypeLatticeElement getShort() {
- return ShortTypeLatticeElement.getInstance();
- }
-
- public static CharTypeLatticeElement getChar() {
- return CharTypeLatticeElement.getInstance();
- }
-
- public static IntTypeLatticeElement getInt() {
- return IntTypeLatticeElement.getInstance();
- }
-
- public static FloatTypeLatticeElement getFloat() {
- return FloatTypeLatticeElement.getInstance();
- }
-
- public static SinglePrimitiveTypeLatticeElement getSingle() {
- return SinglePrimitiveTypeLatticeElement.getInstance();
- }
-
- public static LongTypeLatticeElement getLong() {
- return LongTypeLatticeElement.getInstance();
- }
-
- public static DoubleTypeLatticeElement getDouble() {
- return DoubleTypeLatticeElement.getInstance();
- }
-
- public static WidePrimitiveTypeLatticeElement getWide() {
- return WidePrimitiveTypeLatticeElement.getInstance();
- }
-
- public static ReferenceTypeLatticeElement getNull() {
- return ReferenceTypeLatticeElement.getNullTypeLatticeElement();
- }
-
- public TypeLatticeElement fixupClassTypeReferences(
- Function<DexType, DexType> mapping, AppView<? extends AppInfoWithSubtyping> appView) {
- return this;
- }
-
- public boolean isNullable() {
- return nullability().isNullable();
- }
-
- public abstract Nullability nullability();
-
- /**
- * Computes the least upper bound of the current and the other elements.
- *
- * @param other {@link TypeLatticeElement} to join.
- * @param appView {@link DexDefinitionSupplier}.
- * @return {@link TypeLatticeElement}, a least upper bound of {@param this} and {@param other}.
- */
- public TypeLatticeElement join(TypeLatticeElement other, AppView<?> appView) {
- if (this == other) {
- return this;
- }
- if (isBottom()) {
- return other;
- }
- if (other.isBottom()) {
- return this;
- }
- if (isTop() || other.isTop()) {
- return getTop();
- }
- if (isPrimitive()) {
- return other.isPrimitive()
- ? asPrimitiveTypeLatticeElement().join(other.asPrimitiveTypeLatticeElement())
- : getTop();
- }
- if (other.isPrimitive()) {
- // By the above case, !(isPrimitive())
- return getTop();
- }
- // From now on, this and other are precise reference types, i.e., either ArrayType or ClassType.
- assert isReference() && other.isReference();
- assert isPreciseType() && other.isPreciseType();
- Nullability nullabilityJoin = nullability().join(other.nullability());
- if (isNullType()) {
- return other.asReferenceTypeLatticeElement().getOrCreateVariant(nullabilityJoin);
- }
- if (other.isNullType()) {
- return this.asReferenceTypeLatticeElement().getOrCreateVariant(nullabilityJoin);
- }
- if (getClass() != other.getClass()) {
- return objectClassType(appView, nullabilityJoin);
- }
- // From now on, getClass() == other.getClass()
- if (isArrayType()) {
- assert other.isArrayType();
- return asArrayTypeLatticeElement().join(other.asArrayTypeLatticeElement(), appView);
- }
- if (isClassType()) {
- assert other.isClassType();
- return asClassTypeLatticeElement().join(other.asClassTypeLatticeElement(), appView);
- }
- throw new Unreachable("unless a new type lattice is introduced.");
- }
-
- public static TypeLatticeElement join(
- Iterable<TypeLatticeElement> typeLattices, AppView<?> appView) {
- TypeLatticeElement result = getBottom();
- for (TypeLatticeElement other : typeLattices) {
- result = result.join(other, appView);
- }
- return result;
- }
-
- /**
- * Determines the strict partial order of the given {@link TypeLatticeElement}s.
- *
- * @param other expected to be *strictly* bigger than {@param this}
- * @param appView {@link DexDefinitionSupplier} to compute the least upper bound of {@link
- * TypeLatticeElement}
- * @return {@code true} if {@param this} is strictly less than {@param other}.
- */
- public boolean strictlyLessThan(TypeLatticeElement other, AppView<?> appView) {
- if (equals(other)) {
- return false;
- }
- TypeLatticeElement lub = join(other, appView);
- return !equals(lub) && other.equals(lub);
- }
-
- /**
- * Determines the partial order of the given {@link TypeLatticeElement}s.
- *
- * @param other expected to be bigger than or equal to {@param this}
- * @param appView {@link DexDefinitionSupplier} to compute the least upper bound of {@link
- * TypeLatticeElement}
- * @return {@code true} if {@param this} is less than or equal to {@param other}.
- */
- public boolean lessThanOrEqual(TypeLatticeElement other, AppView<?> appView) {
- return equals(other) || strictlyLessThan(other, appView);
- }
-
- /**
- * Determines if this {@link TypeLatticeElement} is less than or equal to the given {@link
- * TypeLatticeElement} up to nullability.
- *
- * @param other to check for equality with this
- * @return {@code true} if {@param this} is equal up to nullability with {@param other}.
- */
- public boolean lessThanOrEqualUpToNullability(TypeLatticeElement other, AppView<?> appView) {
- if (this == other) {
- return true;
- }
- if (this.isTop()) {
- return other.isTop();
- }
- if (other.isTop()) {
- return true;
- }
- if (this.isBottom()) {
- return true;
- }
- if (other.isBottom()) {
- return false;
- }
- if (isPrimitive()) {
- // Primitives cannot be nullable.
- return lessThanOrEqual(other, appView);
- }
- assert isReference() && other.isReference();
- ReferenceTypeLatticeElement otherAsNullable =
- other.isNullable()
- ? other.asReferenceTypeLatticeElement()
- : other.asReferenceTypeLatticeElement().getOrCreateVariant(Nullability.maybeNull());
- return lessThanOrEqual(otherAsNullable, appView);
- }
-
- /**
- * Determines if the {@link TypeLatticeElement}s are equal up to nullability.
- *
- * @param other to check for equality with this
- * @return {@code true} if {@param this} is equal up to nullability with {@param other}.
- */
- public boolean equalUpToNullability(TypeLatticeElement other) {
- if (this == other) {
- return true;
- }
- if (isPrimitive() || other.isPrimitive()) {
- return false;
- }
- assert isReference() && other.isReference();
- ReferenceTypeLatticeElement thisAsMaybeNull =
- this.asReferenceTypeLatticeElement().getOrCreateVariant(Nullability.maybeNull());
- ReferenceTypeLatticeElement otherAsMaybeNull =
- other.asReferenceTypeLatticeElement().getOrCreateVariant(Nullability.maybeNull());
- return thisAsMaybeNull.equals(otherAsMaybeNull);
- }
-
- /**
- * Determines if this type is based on a missing class, directly or indirectly.
- *
- * @return {@code} true if this type is based on a missing class.
- * @param appView
- */
- public boolean isBasedOnMissingClass(AppView<? extends AppInfoWithSubtyping> appView) {
- return false;
- }
-
- /**
- * Represents a type that can be everything.
- *
- * @return {@code true} if the corresponding {@link Value} could be any kinds.
- */
- public boolean isTop() {
- return false;
- }
-
- /**
- * Represents an empty type.
- *
- * @return {@code true} if the type of corresponding {@link Value} is not determined yet.
- */
- public boolean isBottom() {
- return false;
- }
-
- public boolean isReference() {
- return false;
- }
-
- public ReferenceTypeLatticeElement asReferenceTypeLatticeElement() {
- return null;
- }
-
- public boolean isArrayType() {
- return false;
- }
-
- public ArrayTypeLatticeElement asArrayTypeLatticeElement() {
- return null;
- }
-
- public boolean isClassType() {
- return false;
- }
-
- public ClassTypeLatticeElement asClassTypeLatticeElement() {
- return null;
- }
-
- public boolean isPrimitive() {
- return false;
- }
-
- public PrimitiveTypeLatticeElement asPrimitiveTypeLatticeElement() {
- return null;
- }
-
- public boolean isSinglePrimitive() {
- return false;
- }
-
- public boolean isWidePrimitive() {
- return false;
- }
-
- boolean isBoolean() {
- return false;
- }
-
- boolean isByte() {
- return false;
- }
-
- boolean isShort() {
- return false;
- }
-
- boolean isChar() {
- return false;
- }
-
- public boolean isInt() {
- return false;
- }
-
- public boolean isFloat() {
- return false;
- }
-
- public boolean isLong() {
- return false;
- }
-
- public boolean isDouble() {
- return false;
- }
-
- public boolean isPreciseType() {
- return isArrayType()
- || isClassType()
- || isNullType()
- || isInt()
- || isFloat()
- || isLong()
- || isDouble()
- || isBottom();
- }
-
- public boolean isFineGrainedType() {
- return isBoolean()
- || isByte()
- || isShort()
- || isChar();
- }
-
- /**
- * Determines if this type only includes null values that are defined by a const-number
- * instruction in the same enclosing method.
- *
- * These null values can be assigned to any type.
- */
- public boolean isNullType() {
- return false;
- }
-
- /**
- * Determines if this type only includes null values.
- *
- * These null values cannot be assigned to any type. For example, it is a type error to "throw v"
- * where the value `v` satisfies isDefinitelyNull(), because the static type of `v` may not be a
- * subtype of Throwable.
- */
- public boolean isDefinitelyNull() {
- return nullability().isDefinitelyNull();
- }
-
- public boolean isDefinitelyNotNull() {
- return nullability().isDefinitelyNotNull();
- }
-
- public int requiredRegisters() {
- assert !isBottom() && !isTop();
- return 1;
- }
-
- public static ClassTypeLatticeElement objectClassType(
- AppView<?> appView, Nullability nullability) {
- return fromDexType(appView.dexItemFactory().objectType, nullability, appView)
- .asClassTypeLatticeElement();
- }
-
- static ArrayTypeLatticeElement objectArrayType(AppView<?> appView, Nullability nullability) {
- DexItemFactory dexItemFactory = appView.dexItemFactory();
- return fromDexType(
- dexItemFactory.createArrayType(1, dexItemFactory.objectType), nullability, appView)
- .asArrayTypeLatticeElement();
- }
-
- public static ClassTypeLatticeElement classClassType(
- AppView<?> appView, Nullability nullability) {
- return fromDexType(appView.dexItemFactory().classType, nullability, appView)
- .asClassTypeLatticeElement();
- }
-
- public static ClassTypeLatticeElement stringClassType(
- AppView<?> appView, Nullability nullability) {
- return fromDexType(appView.dexItemFactory().stringType, nullability, appView)
- .asClassTypeLatticeElement();
- }
-
- public static TypeLatticeElement fromDexType(
- DexType type, Nullability nullability, AppView<?> appView) {
- return fromDexType(type, nullability, appView, false);
- }
-
- public static TypeLatticeElement fromDexType(
- DexType type, Nullability nullability, AppView<?> appView, boolean asArrayElementType) {
- if (type == DexItemFactory.nullValueType) {
- assert !nullability.isDefinitelyNotNull();
- return getNull();
- }
- if (type.isPrimitiveType()) {
- return PrimitiveTypeLatticeElement.fromDexType(type, asArrayElementType);
- }
- return appView.dexItemFactory().createReferenceTypeLatticeElement(type, nullability, appView);
- }
-
- public boolean isValueTypeCompatible(TypeLatticeElement other) {
- return (isReference() && other.isReference())
- || (isSinglePrimitive() && other.isSinglePrimitive())
- || (isWidePrimitive() && other.isWidePrimitive());
- }
-
- @Override
- public abstract String toString();
-
- @Override
- public abstract boolean equals(Object o);
-
- @Override
- public abstract int hashCode();
-}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/TypeUtils.java b/src/main/java/com/android/tools/r8/ir/analysis/type/TypeUtils.java
index 912b379..02459a7 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/TypeUtils.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/TypeUtils.java
@@ -8,8 +8,8 @@
public class TypeUtils {
- public static boolean isNullPointerException(TypeLatticeElement type, AppView<?> appView) {
+ public static boolean isNullPointerException(TypeElement type, AppView<?> appView) {
return type.isClassType()
- && type.asClassTypeLatticeElement().getClassType() == appView.dexItemFactory().npeType;
+ && type.asClassType().getClassType() == appView.dexItemFactory().npeType;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/WidePrimitiveTypeLatticeElement.java b/src/main/java/com/android/tools/r8/ir/analysis/type/WidePrimitiveTypeElement.java
similarity index 64%
rename from src/main/java/com/android/tools/r8/ir/analysis/type/WidePrimitiveTypeLatticeElement.java
rename to src/main/java/com/android/tools/r8/ir/analysis/type/WidePrimitiveTypeElement.java
index 3e07e54..0ae7426 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/WidePrimitiveTypeLatticeElement.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/WidePrimitiveTypeElement.java
@@ -3,17 +3,16 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.analysis.type;
-/** A {@link TypeLatticeElement} that abstracts primitive types, which fit in 64 bits. */
-public class WidePrimitiveTypeLatticeElement extends PrimitiveTypeLatticeElement {
+/** A {@link TypeElement} that abstracts primitive types, which fit in 64 bits. */
+public class WidePrimitiveTypeElement extends PrimitiveTypeElement {
- private static final WidePrimitiveTypeLatticeElement INSTANCE =
- new WidePrimitiveTypeLatticeElement();
+ private static final WidePrimitiveTypeElement INSTANCE = new WidePrimitiveTypeElement();
- WidePrimitiveTypeLatticeElement() {
+ WidePrimitiveTypeElement() {
super();
}
- static WidePrimitiveTypeLatticeElement getInstance() {
+ static WidePrimitiveTypeElement getInstance() {
return INSTANCE;
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleConstClassValue.java b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleConstClassValue.java
index 897b31e..34a83d1 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleConstClassValue.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleConstClassValue.java
@@ -5,7 +5,7 @@
package com.android.tools.r8.ir.analysis.value;
import static com.android.tools.r8.ir.analysis.type.Nullability.definitelyNotNull;
-import static com.android.tools.r8.ir.analysis.type.TypeLatticeElement.classClassType;
+import static com.android.tools.r8.ir.analysis.type.TypeElement.classClassType;
import static com.android.tools.r8.optimize.MemberRebindingAnalysis.isClassTypeVisibleFromContext;
import com.android.tools.r8.graph.AppInfoWithSubtyping;
@@ -14,7 +14,7 @@
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLense;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.ConstClass;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
@@ -63,13 +63,11 @@
@Override
public Instruction createMaterializingInstruction(
AppView<? extends AppInfoWithSubtyping> appView, IRCode code, TypeAndLocalInfoSupplier info) {
- TypeLatticeElement typeLattice = info.getTypeLattice();
+ TypeElement typeLattice = info.getOutType();
DebugLocalInfo debugLocalInfo = info.getLocalInfo();
assert typeLattice.isClassType();
assert appView
- .isSubtype(
- appView.dexItemFactory().classType,
- typeLattice.asClassTypeLatticeElement().getClassType())
+ .isSubtype(appView.dexItemFactory().classType, typeLattice.asClassType().getClassType())
.isTrue();
Value returnedValue =
code.createValue(classClassType(appView, definitelyNotNull()), debugLocalInfo);
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleFieldValue.java b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleFieldValue.java
index 5479737..ef38879 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleFieldValue.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleFieldValue.java
@@ -14,8 +14,8 @@
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLense;
-import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.StaticGet;
@@ -39,9 +39,8 @@
public boolean mayHaveFinalizeMethodDirectlyOrIndirectly(AppView<AppInfoWithLiveness> appView) {
DexType fieldType = field.type;
if (fieldType.isClassType()) {
- ClassTypeLatticeElement fieldClassType =
- TypeLatticeElement.fromDexType(fieldType, maybeNull(), appView)
- .asClassTypeLatticeElement();
+ ClassTypeElement fieldClassType =
+ TypeElement.fromDexType(fieldType, maybeNull(), appView).asClassType();
return appView.appInfo().mayHaveFinalizeMethodDirectlyOrIndirectly(fieldClassType);
}
assert fieldType.isArrayType() || fieldType.isPrimitiveType();
@@ -76,8 +75,8 @@
@Override
public Instruction createMaterializingInstruction(
AppView<? extends AppInfoWithSubtyping> appView, IRCode code, TypeAndLocalInfoSupplier info) {
- TypeLatticeElement type = TypeLatticeElement.fromDexType(field.type, maybeNull(), appView);
- assert type.lessThanOrEqual(info.getTypeLattice(), appView);
+ TypeElement type = TypeElement.fromDexType(field.type, maybeNull(), appView);
+ assert type.lessThanOrEqual(info.getOutType(), appView);
Value outValue = code.createValue(type, info.getLocalInfo());
return new StaticGet(outValue, field);
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleNumberValue.java b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleNumberValue.java
index b408c90..e2f12fe 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleNumberValue.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleNumberValue.java
@@ -9,7 +9,7 @@
import com.android.tools.r8.graph.DebugLocalInfo;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLense;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.ConstNumber;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
@@ -68,12 +68,12 @@
@Override
public Instruction createMaterializingInstruction(
AppView<? extends AppInfoWithSubtyping> appView, IRCode code, TypeAndLocalInfoSupplier info) {
- TypeLatticeElement typeLattice = info.getTypeLattice();
+ TypeElement typeLattice = info.getOutType();
DebugLocalInfo debugLocalInfo = info.getLocalInfo();
- assert !typeLattice.isReference() || value == 0;
+ assert !typeLattice.isReferenceType() || value == 0;
Value returnedValue =
code.createValue(
- typeLattice.isReference() ? TypeLatticeElement.getNull() : typeLattice, debugLocalInfo);
+ typeLattice.isReferenceType() ? TypeElement.getNull() : typeLattice, debugLocalInfo);
return new ConstNumber(returnedValue, value);
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleStringValue.java b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleStringValue.java
index a7439c0..1280264 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleStringValue.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleStringValue.java
@@ -5,7 +5,7 @@
package com.android.tools.r8.ir.analysis.value;
import static com.android.tools.r8.ir.analysis.type.Nullability.definitelyNotNull;
-import static com.android.tools.r8.ir.analysis.type.TypeLatticeElement.stringClassType;
+import static com.android.tools.r8.ir.analysis.type.TypeElement.stringClassType;
import com.android.tools.r8.graph.AppInfoWithSubtyping;
import com.android.tools.r8.graph.AppView;
@@ -13,7 +13,7 @@
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLense;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.BasicBlock.ThrowingInfo;
import com.android.tools.r8.ir.code.ConstString;
import com.android.tools.r8.ir.code.IRCode;
@@ -65,13 +65,11 @@
AppView<? extends AppInfoWithSubtyping> appView,
IRCode code,
TypeAndLocalInfoSupplier info) {
- TypeLatticeElement typeLattice = info.getTypeLattice();
+ TypeElement typeLattice = info.getOutType();
DebugLocalInfo debugLocalInfo = info.getLocalInfo();
assert typeLattice.isClassType();
assert appView
- .isSubtype(
- appView.dexItemFactory().stringType,
- typeLattice.asClassTypeLatticeElement().getClassType())
+ .isSubtype(appView.dexItemFactory().stringType, typeLattice.asClassType().getClassType())
.isTrue();
Value returnedValue =
code.createValue(stringClassType(appView, definitelyNotNull()), debugLocalInfo);
diff --git a/src/main/java/com/android/tools/r8/ir/code/Argument.java b/src/main/java/com/android/tools/r8/ir/code/Argument.java
index 1db2ba6..2ace686 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Argument.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Argument.java
@@ -9,7 +9,7 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
@@ -121,8 +121,8 @@
}
@Override
- public TypeLatticeElement evaluate(AppView<?> appView) {
- return outValue.getTypeLattice();
+ public TypeElement evaluate(AppView<?> appView) {
+ return outValue.getType();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/ArithmeticBinop.java b/src/main/java/com/android/tools/r8/ir/code/ArithmeticBinop.java
index 5d97e99..bf545a0 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ArithmeticBinop.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ArithmeticBinop.java
@@ -9,7 +9,7 @@
import com.android.tools.r8.ir.analysis.constant.Bottom;
import com.android.tools.r8.ir.analysis.constant.ConstLatticeElement;
import com.android.tools.r8.ir.analysis.constant.LatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import java.util.function.Function;
@@ -140,20 +140,20 @@
ConstNumber newConst;
if (type == NumericType.INT) {
int result = foldIntegers(leftConst.getIntValue(), rightConst.getIntValue());
- Value value = code.createValue(TypeLatticeElement.getInt(), getLocalInfo());
+ Value value = code.createValue(TypeElement.getInt(), getLocalInfo());
newConst = new ConstNumber(value, result);
} else if (type == NumericType.LONG) {
long result = foldLongs(leftConst.getLongValue(), rightConst.getLongValue());
- Value value = code.createValue(TypeLatticeElement.getLong(), getLocalInfo());
+ Value value = code.createValue(TypeElement.getLong(), getLocalInfo());
newConst = new ConstNumber(value, result);
} else if (type == NumericType.FLOAT) {
float result = foldFloat(leftConst.getFloatValue(), rightConst.getFloatValue());
- Value value = code.createValue(TypeLatticeElement.getFloat(), getLocalInfo());
+ Value value = code.createValue(TypeElement.getFloat(), getLocalInfo());
newConst = new ConstNumber(value, Float.floatToIntBits(result));
} else {
assert type == NumericType.DOUBLE;
double result = foldDouble(leftConst.getDoubleValue(), rightConst.getDoubleValue());
- Value value = code.createValue(TypeLatticeElement.getDouble(), getLocalInfo());
+ Value value = code.createValue(TypeElement.getDouble(), getLocalInfo());
newConst = new ConstNumber(value, Double.doubleToLongBits(result));
}
return new ConstLatticeElement(newConst);
diff --git a/src/main/java/com/android/tools/r8/ir/code/ArrayAccess.java b/src/main/java/com/android/tools/r8/ir/code/ArrayAccess.java
new file mode 100644
index 0000000..14ac116
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/code/ArrayAccess.java
@@ -0,0 +1,38 @@
+// 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.ir.code;
+
+import java.util.List;
+
+public abstract class ArrayAccess extends Instruction implements ImpreciseMemberTypeInstruction {
+
+ // Input values are ordered according to the stack order of the Java bytecodes.
+ private static final int ARRAY_INDEX = 0;
+ private static final int INDEX_INDEX = 1;
+
+ ArrayAccess(Value outValue, List<? extends Value> inValues) {
+ super(outValue, inValues);
+ }
+
+ public Value array() {
+ return inValues.get(ARRAY_INDEX);
+ }
+
+ public Value index() {
+ return inValues.get(INDEX_INDEX);
+ }
+
+ @Override
+ public boolean isArrayAccess() {
+ return true;
+ }
+
+ @Override
+ public ArrayAccess asArrayAccess() {
+ return this;
+ }
+
+ public abstract ArrayAccess withMemberType(MemberType newMemberType);
+}
diff --git a/src/main/java/com/android/tools/r8/ir/code/ArrayGet.java b/src/main/java/com/android/tools/r8/ir/code/ArrayGet.java
index 17dcc5e..432cf11 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ArrayGet.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ArrayGet.java
@@ -19,8 +19,8 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.analysis.type.ArrayTypeLatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ArrayTypeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.conversion.TypeConstraintResolver;
@@ -30,7 +30,7 @@
import java.util.Arrays;
import java.util.Set;
-public class ArrayGet extends Instruction implements ImpreciseMemberTypeInstruction {
+public class ArrayGet extends ArrayAccess {
private MemberType type;
@@ -53,14 +53,6 @@
return outValue;
}
- public Value array() {
- return inValues.get(0);
- }
-
- public Value index() {
- return inValues.get(1);
- }
-
@Override
public MemberType getMemberType() {
return type;
@@ -68,9 +60,9 @@
@Override
public boolean couldIntroduceAnAlias(AppView<?> appView, Value root) {
- assert root != null && root.getTypeLattice().isReference();
+ assert root != null && root.getType().isReferenceType();
assert outValue != null;
- return outValue.getTypeLattice().isReference();
+ return outValue.getType().isReferenceType();
}
@Override
@@ -94,13 +86,12 @@
instruction = new AgetObject(dest, array, index);
break;
case BOOLEAN_OR_BYTE:
- ArrayTypeLatticeElement arrayType = array().getTypeLattice().asArrayTypeLatticeElement();
- if (arrayType != null
- && arrayType.getArrayMemberTypeAsMemberType() == TypeLatticeElement.getBoolean()) {
+ ArrayTypeElement arrayType = array().getType().asArrayType();
+ if (arrayType != null && arrayType.getMemberType() == TypeElement.getBoolean()) {
instruction = new AgetBoolean(dest, array, index);
} else {
- assert array().getTypeLattice().isDefinitelyNull()
- || arrayType.getArrayMemberTypeAsMemberType() == TypeLatticeElement.getByte();
+ assert array().getType().isDefinitelyNull()
+ || arrayType.getMemberType() == TypeElement.getByte();
instruction = new AgetByte(dest, array, index);
}
break;
@@ -172,7 +163,7 @@
@Override
public DexType computeVerificationType(AppView<?> appView, TypeVerificationHelper helper) {
// This method is not called for ArrayGet on primitive array.
- assert this.outValue.getTypeLattice().isReference();
+ assert this.outValue.getType().isReferenceType();
DexType arrayType = helper.getDexType(array());
if (arrayType == DexItemFactory.nullValueType) {
// JVM 8 §4.10.1.9.aaload: Array component type of null is null.
@@ -193,56 +184,51 @@
}
@Override
- public TypeLatticeElement evaluate(AppView<?> appView) {
- ArrayTypeLatticeElement arrayTypeLattice = array().getTypeLattice().isArrayType()
- ? array().getTypeLattice().asArrayTypeLatticeElement()
- : null;
+ public TypeElement evaluate(AppView<?> appView) {
+ ArrayTypeElement arrayTypeLattice =
+ array().getType().isArrayType() ? array().getType().asArrayType() : null;
switch (getMemberType()) {
case OBJECT:
// If the out-type of the array is bottom (the input array must be definitely null), then
// the instruction cannot return. For now we return NULL as the type to ensure we have a
// type consistent witness for the out-value type. We could consider returning bottom in
// this case as the value is indeed empty, i.e., the instruction will always fail.
- TypeLatticeElement valueType =
+ TypeElement valueType =
arrayTypeLattice == null
- ? TypeLatticeElement.getNull()
- : arrayTypeLattice.getArrayMemberTypeAsValueType();
- assert valueType.isReference();
+ ? TypeElement.getNull()
+ : arrayTypeLattice.getMemberTypeAsValueType();
+ assert valueType.isReferenceType();
return valueType;
case BOOLEAN_OR_BYTE:
case CHAR:
case SHORT:
case INT:
- assert arrayTypeLattice == null
- || arrayTypeLattice.getArrayMemberTypeAsValueType().isInt();
- return TypeLatticeElement.getInt();
+ assert arrayTypeLattice == null || arrayTypeLattice.getMemberTypeAsValueType().isInt();
+ return TypeElement.getInt();
case FLOAT:
- assert arrayTypeLattice == null
- || arrayTypeLattice.getArrayMemberTypeAsValueType().isFloat();
- return TypeLatticeElement.getFloat();
+ assert arrayTypeLattice == null || arrayTypeLattice.getMemberTypeAsValueType().isFloat();
+ return TypeElement.getFloat();
case LONG:
- assert arrayTypeLattice == null
- || arrayTypeLattice.getArrayMemberTypeAsValueType().isLong();
- return TypeLatticeElement.getLong();
+ assert arrayTypeLattice == null || arrayTypeLattice.getMemberTypeAsValueType().isLong();
+ return TypeElement.getLong();
case DOUBLE:
- assert arrayTypeLattice == null
- || arrayTypeLattice.getArrayMemberTypeAsValueType().isDouble();
- return TypeLatticeElement.getDouble();
+ assert arrayTypeLattice == null || arrayTypeLattice.getMemberTypeAsValueType().isDouble();
+ return TypeElement.getDouble();
case INT_OR_FLOAT:
assert arrayTypeLattice == null
- || arrayTypeLattice.getArrayMemberTypeAsValueType().isSinglePrimitive();
+ || arrayTypeLattice.getMemberTypeAsValueType().isSinglePrimitive();
return checkConstraint(dest(), ValueTypeConstraint.INT_OR_FLOAT);
case LONG_OR_DOUBLE:
assert arrayTypeLattice == null
- || arrayTypeLattice.getArrayMemberTypeAsValueType().isWidePrimitive();
+ || arrayTypeLattice.getMemberTypeAsValueType().isWidePrimitive();
return checkConstraint(dest(), ValueTypeConstraint.LONG_OR_DOUBLE);
default:
throw new Unreachable("Unexpected member type: " + getMemberType());
}
}
- private static TypeLatticeElement checkConstraint(Value value, ValueTypeConstraint constraint) {
- TypeLatticeElement latticeElement = value.constrainedType(constraint);
+ private static TypeElement checkConstraint(Value value, ValueTypeConstraint constraint) {
+ TypeElement latticeElement = value.constrainedType(constraint);
if (latticeElement != null) {
return latticeElement;
}
@@ -267,9 +253,8 @@
@Override
public boolean outTypeKnownToBeBoolean(Set<Phi> seen) {
- return array().getTypeLattice().isArrayType()
- && array().getTypeLattice().asArrayTypeLatticeElement().getArrayMemberTypeAsMemberType()
- == TypeLatticeElement.getBoolean();
+ return array().getType().isArrayType()
+ && array().getType().asArrayType().getMemberType() == TypeElement.getBoolean();
}
@Override
@@ -281,4 +266,9 @@
public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
return false;
}
+
+ @Override
+ public ArrayAccess withMemberType(MemberType newMemberType) {
+ return new ArrayGet(newMemberType, outValue(), array(), index());
+ }
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/ArrayLength.java b/src/main/java/com/android/tools/r8/ir/code/ArrayLength.java
index da92bf3..dc0b133 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ArrayLength.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ArrayLength.java
@@ -10,7 +10,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.AbstractError;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
@@ -75,7 +75,7 @@
@Override
public AbstractError instructionInstanceCanThrow(AppView<?> appView, DexType context) {
- if (array().typeLattice.isNullable()) {
+ if (array().type.isNullable()) {
return AbstractError.specific(appView.dexItemFactory().npeType);
}
@@ -130,8 +130,8 @@
}
@Override
- public TypeLatticeElement evaluate(AppView<?> appView) {
- return TypeLatticeElement.getInt();
+ public TypeElement evaluate(AppView<?> appView) {
+ return TypeElement.getInt();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/ArrayPut.java b/src/main/java/com/android/tools/r8/ir/code/ArrayPut.java
index 589710f..f4a8a14 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ArrayPut.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ArrayPut.java
@@ -16,8 +16,8 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.analysis.type.ArrayTypeLatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ArrayTypeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.conversion.TypeConstraintResolver;
@@ -26,11 +26,9 @@
import com.android.tools.r8.ir.regalloc.RegisterAllocator;
import java.util.Arrays;
-public class ArrayPut extends Instruction implements ImpreciseMemberTypeInstruction {
+public class ArrayPut extends ArrayAccess {
// Input values are ordered according to the stack order of the Java bytecode astore.
- private static final int ARRAY_INDEX = 0;
- private static final int INDEX_INDEX = 1;
private static final int VALUE_INDEX = 2;
private MemberType type;
@@ -53,14 +51,6 @@
return visitor.visit(this);
}
- public Value array() {
- return inValues.get(ARRAY_INDEX);
- }
-
- public Value index() {
- return inValues.get(INDEX_INDEX);
- }
-
public Value value() {
return inValues.get(VALUE_INDEX);
}
@@ -89,13 +79,12 @@
instruction = new AputObject(value, array, index);
break;
case BOOLEAN_OR_BYTE:
- ArrayTypeLatticeElement arrayType = array().getTypeLattice().asArrayTypeLatticeElement();
- if (arrayType != null
- && arrayType.getArrayMemberTypeAsMemberType() == TypeLatticeElement.getBoolean()) {
+ ArrayTypeElement arrayType = array().getType().asArrayType();
+ if (arrayType != null && arrayType.getMemberType() == TypeElement.getBoolean()) {
instruction = new AputBoolean(value, array, index);
} else {
- assert array().getTypeLattice().isDefinitelyNull()
- || arrayType.getArrayMemberTypeAsMemberType() == TypeLatticeElement.getByte();
+ assert array().getType().isDefinitelyNull()
+ || arrayType.getMemberType() == TypeElement.getByte();
instruction = new AputByte(value, array, index);
}
break;
@@ -176,13 +165,12 @@
}
// Check for type errors.
- TypeLatticeElement arrayType = array.getTypeLattice();
- TypeLatticeElement valueType = value().getTypeLattice();
+ TypeElement arrayType = array.getType();
+ TypeElement valueType = value().getType();
if (!arrayType.isArrayType()) {
return true;
}
- TypeLatticeElement memberType =
- arrayType.asArrayTypeLatticeElement().getArrayMemberTypeAsValueType();
+ TypeElement memberType = arrayType.asArrayType().getMemberTypeAsValueType();
if (!valueType.lessThanOrEqualUpToNullability(memberType, appView)) {
return true;
}
@@ -275,4 +263,9 @@
public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, DexType context) {
return false;
}
+
+ @Override
+ public ArrayAccess withMemberType(MemberType newMemberType) {
+ return new ArrayPut(newMemberType, array(), index(), value());
+ }
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Assume.java b/src/main/java/com/android/tools/r8/ir/code/Assume.java
index 37de422..6611bc7 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Assume.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Assume.java
@@ -9,8 +9,8 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.Assume.Assumption;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
@@ -47,8 +47,8 @@
}
public static Assume<DynamicTypeAssumption> createAssumeDynamicTypeInstruction(
- TypeLatticeElement dynamicUpperBoundType,
- ClassTypeLatticeElement dynamicLowerBoundType,
+ TypeElement dynamicUpperBoundType,
+ ClassTypeElement dynamicLowerBoundType,
Value dest,
Value src,
Instruction origin,
@@ -164,10 +164,10 @@
@Override
public boolean couldIntroduceAnAlias(AppView<?> appView, Value root) {
- assert root != null && root.getTypeLattice().isReference();
+ assert root != null && root.getType().isReferenceType();
assert outValue != null;
- TypeLatticeElement outType = outValue.getTypeLattice();
- if (outType.isPrimitive()) {
+ TypeElement outType = outValue.getType();
+ if (outType.isPrimitiveType()) {
return false;
}
if (assumption.isAssumeNone()) {
@@ -179,14 +179,17 @@
}
if (appView.appInfo().hasSubtyping()) {
if (outType.isClassType()
- && root.getTypeLattice().isClassType()
- && appView.appInfo().withSubtyping().inDifferentHierarchy(
- outType.asClassTypeLatticeElement().getClassType(),
- root.getTypeLattice().asClassTypeLatticeElement().getClassType())) {
+ && root.getType().isClassType()
+ && appView
+ .appInfo()
+ .withSubtyping()
+ .inDifferentHierarchy(
+ outType.asClassType().getClassType(),
+ root.getType().asClassType().getClassType())) {
return false;
}
}
- return outType.isReference();
+ return outType.isReferenceType();
}
@Override
@@ -240,13 +243,13 @@
}
@Override
- public TypeLatticeElement evaluate(AppView<?> appView) {
+ public TypeElement evaluate(AppView<?> appView) {
if (assumption.isAssumeNone() || assumption.isAssumeDynamicType()) {
- return src().getTypeLattice();
+ return src().getType();
}
if (assumption.isAssumeNonNull()) {
- assert src().getTypeLattice().isReference();
- return src().getTypeLattice().asReferenceTypeLatticeElement().asMeetWithNotNull();
+ assert src().getType().isReferenceType();
+ return src().getType().asReferenceType().asMeetWithNotNull();
}
throw new Unimplemented();
}
@@ -275,18 +278,17 @@
public boolean verifyTypes(AppView<?> appView) {
assert super.verifyTypes(appView);
- TypeLatticeElement inType = src().getTypeLattice();
- TypeLatticeElement outType = outValue().getTypeLattice();
+ TypeElement inType = src().getType();
+ TypeElement outType = outValue().getType();
if (isAssumeNone() || isAssumeDynamicType()) {
- assert inType.isReference() : inType;
+ assert inType.isReferenceType() : inType;
assert outType.equals(inType)
: "At " + this + System.lineSeparator() + outType + " != " + inType;
} else {
assert isAssumeNonNull() : this;
- assert inType.isReference() : inType;
- assert inType.isNullType()
- || outType.equals(inType.asReferenceTypeLatticeElement().asMeetWithNotNull())
- : "At " + this + System.lineSeparator() + outType + " != " + inType;
+ assert inType.isReferenceType() : inType;
+ assert inType.isNullType() || outType.equals(inType.asReferenceType().asMeetWithNotNull())
+ : "At " + this + System.lineSeparator() + outType + " != " + inType;
}
return true;
}
@@ -351,27 +353,27 @@
@Override
public boolean verifyCorrectnessOfValues(Value dest, Value src, AppView<?> appView) {
- assert dest.getTypeLattice() == src.getTypeLattice();
+ assert dest.getType() == src.getType();
return true;
}
}
public static class DynamicTypeAssumption extends Assumption {
- private final TypeLatticeElement dynamicUpperBoundType;
- private final ClassTypeLatticeElement dynamicLowerBoundType;
+ private final TypeElement dynamicUpperBoundType;
+ private final ClassTypeElement dynamicLowerBoundType;
private DynamicTypeAssumption(
- TypeLatticeElement dynamicUpperBoundType, ClassTypeLatticeElement dynamicLowerBoundType) {
+ TypeElement dynamicUpperBoundType, ClassTypeElement dynamicLowerBoundType) {
this.dynamicUpperBoundType = dynamicUpperBoundType;
this.dynamicLowerBoundType = dynamicLowerBoundType;
}
- public TypeLatticeElement getDynamicUpperBoundType() {
+ public TypeElement getDynamicUpperBoundType() {
return dynamicUpperBoundType;
}
- public ClassTypeLatticeElement getDynamicLowerBoundType() {
+ public ClassTypeElement getDynamicLowerBoundType() {
return dynamicLowerBoundType;
}
@@ -382,7 +384,7 @@
@Override
public boolean verifyCorrectnessOfValues(Value dest, Value src, AppView<?> appView) {
- assert dynamicUpperBoundType.lessThanOrEqualUpToNullability(src.getTypeLattice(), appView);
+ assert dynamicUpperBoundType.lessThanOrEqualUpToNullability(src.getType(), appView);
return true;
}
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 584ea2c..37d9b9e 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
@@ -13,7 +13,7 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLense;
import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.Phi.RegisterReadType;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.conversion.IRBuilder;
@@ -1445,8 +1445,8 @@
public static BasicBlock createRethrowBlock(
IRCode code, Position position, DexType guard, AppView<?> appView) {
- TypeLatticeElement guardTypeLattice =
- TypeLatticeElement.fromDexType(guard, Nullability.definitelyNotNull(), appView);
+ TypeElement guardTypeLattice =
+ TypeElement.fromDexType(guard, Nullability.definitelyNotNull(), appView);
BasicBlock block = new BasicBlock();
MoveException moveException =
new MoveException(
@@ -1743,14 +1743,14 @@
int nextBlockNumber = code.getHighestBlockNumber() + 1;
List<BasicBlock> predecessors = getMutablePredecessors();
boolean hasMoveException = entry().isMoveException();
- TypeLatticeElement exceptionTypeLattice = null;
+ TypeElement exceptionTypeLattice = null;
DexType exceptionType = null;
MoveException move = null;
Position position = entry().getPosition();
if (hasMoveException) {
// Remove the move-exception instruction.
move = entry().asMoveException();
- exceptionTypeLattice = move.outValue().getTypeLattice();
+ exceptionTypeLattice = move.outValue().getType();
exceptionType = move.getExceptionType();
assert move.getDebugValues().isEmpty();
getInstructions().remove(0);
diff --git a/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionListIterator.java b/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionListIterator.java
index 98f4c97..4e5c923 100644
--- a/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionListIterator.java
+++ b/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionListIterator.java
@@ -12,7 +12,7 @@
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.Phi.RegisterReadType;
import com.android.tools.r8.ir.optimize.NestUtils;
import com.android.tools.r8.utils.InternalOptions;
@@ -228,7 +228,7 @@
throw new IllegalStateException();
}
- assert !current.hasOutValue() || current.outValue().getTypeLattice().isInt();
+ assert !current.hasOutValue() || current.outValue().getType().isInt();
// Replace the instruction by const-number.
ConstNumber constNumber = code.createIntConstant(value, current.getLocalInfo());
@@ -249,8 +249,8 @@
}
// Replace the instruction by static-get.
- TypeLatticeElement newType = TypeLatticeElement.fromDexType(field.type, maybeNull(), appView);
- TypeLatticeElement oldType = current.hasOutValue() ? current.outValue().getTypeLattice() : null;
+ TypeElement newType = TypeElement.fromDexType(field.type, maybeNull(), appView);
+ TypeElement oldType = current.hasOutValue() ? current.outValue().getType() : null;
Value value = code.createValue(newType, current.getLocalInfo());
StaticGet staticGet = new StaticGet(value, field);
for (Value inValue : current.inValues()) {
@@ -534,9 +534,8 @@
// TODO(b/120257211): Even if the receiver is used, we can avoid inserting a check-cast
// instruction if the program still type checks without the cast.
Value receiver = invoke.inValues().get(0);
- TypeLatticeElement castTypeLattice =
- TypeLatticeElement.fromDexType(
- downcast, receiver.getTypeLattice().nullability(), appView);
+ TypeElement castTypeLattice =
+ TypeElement.fromDexType(downcast, receiver.getType().nullability(), appView);
CheckCast castInstruction =
new CheckCast(code.createValue(castTypeLattice), receiver, downcast);
castInstruction.setPosition(invoke.getPosition());
@@ -715,7 +714,7 @@
new Phi(
code.valueNumberGenerator.next(),
newExitBlock,
- TypeLatticeElement.getBottom(),
+ TypeElement.getBottom(),
null,
RegisterReadType.NORMAL);
phi.addOperands(operands);
diff --git a/src/main/java/com/android/tools/r8/ir/code/Binop.java b/src/main/java/com/android/tools/r8/ir/code/Binop.java
index 70187db..f0d4eff 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Binop.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Binop.java
@@ -10,8 +10,8 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.analysis.type.PrimitiveTypeLatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.PrimitiveTypeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.InliningConstraints;
import com.android.tools.r8.ir.regalloc.RegisterAllocator;
@@ -134,8 +134,8 @@
}
@Override
- public TypeLatticeElement evaluate(AppView<?> appView) {
- return PrimitiveTypeLatticeElement.fromNumericType(type);
+ public TypeElement evaluate(AppView<?> appView) {
+ return PrimitiveTypeElement.fromNumericType(type);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/CheckCast.java b/src/main/java/com/android/tools/r8/ir/code/CheckCast.java
index a084a0f..2d7e409 100644
--- a/src/main/java/com/android/tools/r8/ir/code/CheckCast.java
+++ b/src/main/java/com/android/tools/r8/ir/code/CheckCast.java
@@ -17,7 +17,7 @@
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.AbstractError;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
@@ -121,8 +121,7 @@
}
}
AppView<? extends AppInfoWithLiveness> appViewWithLiveness = appView.withLiveness();
- TypeLatticeElement castType =
- TypeLatticeElement.fromDexType(type, definitelyNotNull(), appView);
+ TypeElement castType = TypeElement.fromDexType(type, definitelyNotNull(), appView);
if (object()
.getDynamicUpperBoundType(appViewWithLiveness)
.lessThanOrEqualUpToNullability(castType, appView)) {
@@ -160,21 +159,20 @@
}
@Override
- public TypeLatticeElement evaluate(AppView<?> appView) {
- return TypeLatticeElement.fromDexType(type, object().getTypeLattice().nullability(), appView);
+ public TypeElement evaluate(AppView<?> appView) {
+ return TypeElement.fromDexType(type, object().getType().nullability(), appView);
}
@Override
public boolean verifyTypes(AppView<?> appView) {
assert super.verifyTypes(appView);
- TypeLatticeElement inType = object().getTypeLattice();
+ TypeElement inType = object().getType();
assert inType.isPreciseType();
- TypeLatticeElement outType = outValue().getTypeLattice();
- TypeLatticeElement castType =
- TypeLatticeElement.fromDexType(getType(), inType.nullability(), appView);
+ TypeElement outType = outValue().getType();
+ TypeElement castType = TypeElement.fromDexType(getType(), inType.nullability(), appView);
if (inType.lessThanOrEqual(castType, appView)) {
// Cast can be removed. Check that it is sound to replace all users of the out-value by the
diff --git a/src/main/java/com/android/tools/r8/ir/code/Cmp.java b/src/main/java/com/android/tools/r8/ir/code/Cmp.java
index acccf31..2b44f93 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Cmp.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Cmp.java
@@ -15,7 +15,7 @@
import com.android.tools.r8.ir.analysis.constant.Bottom;
import com.android.tools.r8.ir.analysis.constant.ConstLatticeElement;
import com.android.tools.r8.ir.analysis.constant.LatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.utils.LongInterval;
@@ -186,7 +186,7 @@
result = (int) Math.signum(left - right);
}
}
- Value value = code.createValue(TypeLatticeElement.getInt(), getLocalInfo());
+ Value value = code.createValue(TypeElement.getInt(), getLocalInfo());
ConstNumber newConst = new ConstNumber(value, result);
return new ConstLatticeElement(newConst);
} else if (leftLattice.isValueRange() && rightLattice.isConst()) {
@@ -214,7 +214,7 @@
return Bottom.getInstance();
}
int result = Integer.signum(Long.compare(leftRange.getMin(), rightRange.getMin()));
- Value value = code.createValue(TypeLatticeElement.getInt(), getLocalInfo());
+ Value value = code.createValue(TypeElement.getInt(), getLocalInfo());
ConstNumber newConst = new ConstNumber(value, result);
return new ConstLatticeElement(newConst);
}
@@ -235,8 +235,8 @@
}
@Override
- public TypeLatticeElement evaluate(AppView<?> appView) {
- return TypeLatticeElement.getInt();
+ public TypeElement evaluate(AppView<?> appView) {
+ return TypeElement.getInt();
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstClass.java b/src/main/java/com/android/tools/r8/ir/code/ConstClass.java
index a9089f8..e77f315 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstClass.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstClass.java
@@ -15,7 +15,7 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.AbstractError;
import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.analysis.value.UnknownValue;
import com.android.tools.r8.ir.conversion.CfBuilder;
@@ -46,7 +46,7 @@
Value newValue =
new Value(
code.valueNumberGenerator.next(),
- original.outValue().getTypeLattice(),
+ original.outValue().getType(),
original.getLocalInfo());
return copyOf(newValue, original);
}
@@ -172,8 +172,8 @@
}
@Override
- public TypeLatticeElement evaluate(AppView<?> appView) {
- return TypeLatticeElement.classClassType(appView, Nullability.definitelyNotNull());
+ public TypeElement evaluate(AppView<?> appView) {
+ return TypeElement.classClassType(appView, Nullability.definitelyNotNull());
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstMethodHandle.java b/src/main/java/com/android/tools/r8/ir/code/ConstMethodHandle.java
index 446601c..996bf38 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstMethodHandle.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstMethodHandle.java
@@ -11,7 +11,7 @@
import com.android.tools.r8.graph.DexMethodHandle;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
@@ -40,7 +40,7 @@
Value newValue =
new Value(
code.valueNumberGenerator.next(),
- original.outValue().getTypeLattice(),
+ original.outValue().getType(),
original.getLocalInfo());
return copyOf(newValue, original);
}
@@ -116,8 +116,8 @@
}
@Override
- public TypeLatticeElement evaluate(AppView<?> appView) {
- return TypeLatticeElement.fromDexType(
+ public TypeElement evaluate(AppView<?> appView) {
+ return TypeElement.fromDexType(
appView.dexItemFactory().methodHandleType, Nullability.definitelyNotNull(), appView);
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstMethodType.java b/src/main/java/com/android/tools/r8/ir/code/ConstMethodType.java
index bb3f574..6cd4d0b 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstMethodType.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstMethodType.java
@@ -11,7 +11,7 @@
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
@@ -40,7 +40,7 @@
Value newValue =
new Value(
code.valueNumberGenerator.next(),
- original.outValue().getTypeLattice(),
+ original.outValue().getType(),
original.getLocalInfo());
return copyOf(newValue, original);
}
@@ -110,8 +110,8 @@
}
@Override
- public TypeLatticeElement evaluate(AppView<?> appView) {
- return TypeLatticeElement.fromDexType(
+ public TypeElement evaluate(AppView<?> appView) {
+ return TypeElement.fromDexType(
appView.dexItemFactory().methodTypeType, Nullability.definitelyNotNull(), appView);
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstNumber.java b/src/main/java/com/android/tools/r8/ir/code/ConstNumber.java
index 84f33f3..2683b66 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstNumber.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstNumber.java
@@ -21,7 +21,7 @@
import com.android.tools.r8.ir.analysis.constant.Bottom;
import com.android.tools.r8.ir.analysis.constant.ConstLatticeElement;
import com.android.tools.r8.ir.analysis.constant.LatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
@@ -54,10 +54,11 @@
}
public static ConstNumber copyOf(IRCode code, ConstNumber original) {
- Value newValue = new Value(
- code.valueNumberGenerator.next(),
- original.outValue().getTypeLattice(),
- original.getLocalInfo());
+ Value newValue =
+ new Value(
+ code.valueNumberGenerator.next(),
+ original.outValue().getType(),
+ original.getLocalInfo());
return copyOf(newValue, original);
}
@@ -250,7 +251,7 @@
@Override
public String toString() {
if (outValue != null) {
- return super.toString() + " " + value + " (" + outValue().getTypeLattice() + ")";
+ return super.toString() + " " + value + " (" + outValue().getType() + ")";
} else {
return super.toString() + " " + value + " (dead)";
}
@@ -314,16 +315,14 @@
}
@Override
- public TypeLatticeElement evaluate(AppView<?> appView) {
- return outValue().getTypeLattice();
+ public TypeElement evaluate(AppView<?> appView) {
+ return outValue().getType();
}
@Override
public boolean verifyTypes(AppView<?> appView) {
assert super.verifyTypes(appView);
- assert !isZero()
- || outValue().getTypeLattice().isPrimitive()
- || outValue().getTypeLattice().isNullType();
+ assert !isZero() || outValue().getType().isPrimitiveType() || outValue().getType().isNullType();
return true;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstString.java b/src/main/java/com/android/tools/r8/ir/code/ConstString.java
index a80bc66..c98d8b7 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstString.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstString.java
@@ -11,7 +11,7 @@
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.analysis.value.UnknownValue;
import com.android.tools.r8.ir.code.BasicBlock.ThrowingInfo;
@@ -42,8 +42,9 @@
public static ConstString copyOf(IRCode code, ConstString original) {
Value newValue =
- new Value(code.valueNumberGenerator.next(),
- original.outValue().getTypeLattice(),
+ new Value(
+ code.valueNumberGenerator.next(),
+ original.outValue().getType(),
original.getLocalInfo());
return copyOf(newValue, original);
}
@@ -153,8 +154,8 @@
}
@Override
- public TypeLatticeElement evaluate(AppView<?> appView) {
- return TypeLatticeElement.stringClassType(appView, Nullability.definitelyNotNull());
+ public TypeElement evaluate(AppView<?> appView) {
+ return TypeElement.stringClassType(appView, Nullability.definitelyNotNull());
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/DebugLocalWrite.java b/src/main/java/com/android/tools/r8/ir/code/DebugLocalWrite.java
index 453a564..5884660 100644
--- a/src/main/java/com/android/tools/r8/ir/code/DebugLocalWrite.java
+++ b/src/main/java/com/android/tools/r8/ir/code/DebugLocalWrite.java
@@ -79,7 +79,7 @@
@Override
public boolean verifyTypes(AppView<?> appView) {
super.verifyTypes(appView);
- assert src().getTypeLattice().lessThanOrEqual(outValue().getTypeLattice(), appView);
+ assert src().getType().lessThanOrEqual(outValue().getType(), appView);
return true;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/DexItemBasedConstString.java b/src/main/java/com/android/tools/r8/ir/code/DexItemBasedConstString.java
index 979f172..70ebd80 100644
--- a/src/main/java/com/android/tools/r8/ir/code/DexItemBasedConstString.java
+++ b/src/main/java/com/android/tools/r8/ir/code/DexItemBasedConstString.java
@@ -11,7 +11,7 @@
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.BasicBlock.ThrowingInfo;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
@@ -48,8 +48,9 @@
public static DexItemBasedConstString copyOf(IRCode code, DexItemBasedConstString original) {
Value newValue =
- new Value(code.valueNumberGenerator.next(),
- original.outValue().getTypeLattice(),
+ new Value(
+ code.valueNumberGenerator.next(),
+ original.outValue().getType(),
original.getLocalInfo());
return copyOf(newValue, original);
}
@@ -153,8 +154,8 @@
}
@Override
- public TypeLatticeElement evaluate(AppView<?> appView) {
- return TypeLatticeElement.stringClassType(appView, Nullability.definitelyNotNull());
+ public TypeElement evaluate(AppView<?> appView) {
+ return TypeElement.stringClassType(appView, Nullability.definitelyNotNull());
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/Dup.java b/src/main/java/com/android/tools/r8/ir/code/Dup.java
index 79fe507..cddc41e 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Dup.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Dup.java
@@ -70,7 +70,7 @@
@Override
public void buildCf(CfBuilder builder) {
- if (this.inValues.get(0).getTypeLattice().isWidePrimitive()) {
+ if (this.inValues.get(0).getType().isWidePrimitive()) {
builder.add(new CfStackInstruction(Opcode.Dup2));
} else {
builder.add(new CfStackInstruction(Opcode.Dup));
diff --git a/src/main/java/com/android/tools/r8/ir/code/Dup2.java b/src/main/java/com/android/tools/r8/ir/code/Dup2.java
index 2c24e04..465c408 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Dup2.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Dup2.java
@@ -33,8 +33,8 @@
private Dup2(StackValues dest, Value srcBottom, Value srcTop) {
super(dest, ImmutableList.of(srcBottom, srcTop));
- assert !srcBottom.getTypeLattice().isWidePrimitive();
- assert !srcTop.getTypeLattice().isWidePrimitive();
+ assert !srcBottom.getType().isWidePrimitive();
+ assert !srcTop.getType().isWidePrimitive();
assert dest.getStackValues().length == 4;
assert srcBottom.isValueOnStack() && !(srcBottom instanceof StackValues);
assert srcTop.isValueOnStack() && !(srcTop instanceof StackValues);
diff --git a/src/main/java/com/android/tools/r8/ir/code/FieldInstruction.java b/src/main/java/com/android/tools/r8/ir/code/FieldInstruction.java
index 507ae25..d7e0067 100644
--- a/src/main/java/com/android/tools/r8/ir/code/FieldInstruction.java
+++ b/src/main/java/com/android/tools/r8/ir/code/FieldInstruction.java
@@ -17,7 +17,7 @@
import com.android.tools.r8.ir.analysis.fieldvalueanalysis.ConcreteMutableFieldSet;
import com.android.tools.r8.ir.analysis.fieldvalueanalysis.EmptyFieldSet;
import com.android.tools.r8.ir.analysis.fieldvalueanalysis.UnknownFieldSet;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.analysis.value.SingleFieldValue;
import com.android.tools.r8.ir.analysis.value.UnknownValue;
@@ -114,7 +114,7 @@
if (isInstanceGet() || isInstancePut()) {
if (!assumption.canAssumeReceiverIsNotNull()) {
Value receiver = inValues.get(0);
- if (receiver.isAlwaysNull(appView) || receiver.typeLattice.isNullable()) {
+ if (receiver.isAlwaysNull(appView) || receiver.type.isNullable()) {
return AbstractError.specific(appView.dexItemFactory().npeType);
}
}
@@ -189,9 +189,8 @@
AppView<AppInfoWithLiveness> appView, DexEncodedField field) {
assert isFieldPut();
- TypeLatticeElement type = value().getTypeLattice();
- TypeLatticeElement baseType =
- type.isArrayType() ? type.asArrayTypeLatticeElement().getArrayBaseTypeLattice() : type;
+ TypeElement type = value().getType();
+ TypeElement baseType = type.isArrayType() ? type.asArrayType().getBaseType() : type;
if (!baseType.isClassType()) {
return false;
}
@@ -225,7 +224,7 @@
return resolutionResult != null && resolutionResult.isProgramMethod(appView);
}
- return appInfo.mayHaveFinalizeMethodDirectlyOrIndirectly(baseType.asClassTypeLatticeElement());
+ return appInfo.mayHaveFinalizeMethodDirectlyOrIndirectly(baseType.asClassType());
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/FixedRegisterValue.java b/src/main/java/com/android/tools/r8/ir/code/FixedRegisterValue.java
index b074e44..c1424b7 100644
--- a/src/main/java/com/android/tools/r8/ir/code/FixedRegisterValue.java
+++ b/src/main/java/com/android/tools/r8/ir/code/FixedRegisterValue.java
@@ -4,7 +4,7 @@
package com.android.tools.r8.ir.code;
import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import java.util.function.Predicate;
// Value that has a fixed register allocated. These are used for inserting spill, restore, and phi
@@ -12,7 +12,7 @@
public class FixedRegisterValue extends Value {
private final int register;
- public FixedRegisterValue(TypeLatticeElement moveType, int register) {
+ public FixedRegisterValue(TypeElement moveType, int register) {
// Set local info to null since these values are never representatives of live-ranges.
super(-1, moveType, null);
setNeedsRegister(true);
@@ -21,8 +21,8 @@
@Override
public ValueType outType() {
- TypeLatticeElement type = getTypeLattice();
- if (type.isPrimitive()) {
+ TypeElement type = getType();
+ if (type.isPrimitiveType()) {
if (type.isSinglePrimitive()) {
if (type.isInt()) {
return ValueType.INT;
@@ -40,7 +40,7 @@
}
}
} else {
- assert type.isReference();
+ assert type.isReferenceType();
return ValueType.OBJECT;
}
throw new Unreachable("Unexpected imprecise type: " + type);
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 883d49f..53573ac 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
@@ -12,9 +12,9 @@
import com.android.tools.r8.graph.classmerging.VerticallyMergedClasses;
import com.android.tools.r8.ir.analysis.TypeChecker;
import com.android.tools.r8.ir.analysis.ValueMayDependOnEnvironmentAnalysis;
-import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.Phi.RegisterReadType;
import com.android.tools.r8.ir.conversion.IRBuilder;
import com.android.tools.r8.origin.Origin;
@@ -565,9 +565,8 @@
return true;
}
for (Instruction instruction : instructions()) {
- if (instruction.outValue != null && instruction.outValue.getTypeLattice().isClassType()) {
- ClassTypeLatticeElement classTypeLattice =
- instruction.outValue.getTypeLattice().asClassTypeLatticeElement();
+ if (instruction.outValue != null && instruction.outValue.getType().isClassType()) {
+ ClassTypeElement classTypeLattice = instruction.outValue.getType().asClassType();
assert !verticallyMergedClasses.hasBeenMergedIntoSubtype(classTypeLattice.getClassType());
for (DexType itf : classTypeLattice.getInterfaces()) {
assert !verticallyMergedClasses.hasBeenMergedIntoSubtype(itf);
@@ -893,11 +892,11 @@
public boolean verifyNoImpreciseOrBottomTypes() {
Predicate<Value> verifyValue =
v -> {
- assert v.getTypeLattice().isPreciseType();
- assert !v.getTypeLattice().isFineGrainedType();
+ assert v.getType().isPreciseType();
+ assert !v.getType().isFineGrainedType();
// For now we assume no bottom types on IR values. We may want to reconsider this for
// representing unreachable code.
- assert !v.getTypeLattice().isBottom();
+ assert !v.getType().isBottom();
assert !(v.definition instanceof ImpreciseMemberTypeInstruction)
|| ((ImpreciseMemberTypeInstruction) v.definition).getMemberType().isPrecise();
return true;
@@ -908,9 +907,8 @@
public boolean verifyNoNullabilityBottomTypes() {
Predicate<Value> verifyValue =
v -> {
- assert v.getTypeLattice().isPrimitive()
- || v.getTypeLattice().asReferenceTypeLatticeElement().nullability()
- != Nullability.bottom();
+ assert v.getType().isPrimitiveType()
+ || v.getType().asReferenceType().nullability() != Nullability.bottom();
return true;
};
return verifySSATypeLattice(wrapSSAVerifierWithStackValueHandling(verifyValue));
@@ -1049,21 +1047,21 @@
return thisValue;
}
- public Value createValue(TypeLatticeElement typeLattice, DebugLocalInfo local) {
+ public Value createValue(TypeElement typeLattice, DebugLocalInfo local) {
return new Value(valueNumberGenerator.next(), typeLattice, local);
}
- public Value createValue(TypeLatticeElement typeLattice) {
+ public Value createValue(TypeElement typeLattice) {
return createValue(typeLattice, null);
}
public ConstNumber createDoubleConstant(double value, DebugLocalInfo local) {
- Value out = createValue(TypeLatticeElement.getDouble(), local);
+ Value out = createValue(TypeElement.getDouble(), local);
return new ConstNumber(out, Double.doubleToLongBits(value));
}
public ConstNumber createFloatConstant(float value, DebugLocalInfo local) {
- Value out = createValue(TypeLatticeElement.getFloat(), local);
+ Value out = createValue(TypeElement.getFloat(), local);
return new ConstNumber(out, Float.floatToIntBits(value));
}
@@ -1072,16 +1070,16 @@
}
public ConstNumber createIntConstant(int value, DebugLocalInfo local) {
- Value out = createValue(TypeLatticeElement.getInt(), local);
+ Value out = createValue(TypeElement.getInt(), local);
return new ConstNumber(out, value);
}
public ConstNumber createLongConstant(long value, DebugLocalInfo local) {
- Value out = createValue(TypeLatticeElement.getLong(), local);
+ Value out = createValue(TypeElement.getLong(), local);
return new ConstNumber(out, value);
}
- public Phi createPhi(BasicBlock block, TypeLatticeElement type) {
+ public Phi createPhi(BasicBlock block, TypeElement type) {
return new Phi(valueNumberGenerator.next(), block, type, null, RegisterReadType.NORMAL);
}
@@ -1091,17 +1089,17 @@
public ConstClass createConstClass(AppView<?> appView, DexType type) {
Value out =
- createValue(TypeLatticeElement.fromDexType(type, Nullability.definitelyNotNull(), appView));
+ createValue(TypeElement.fromDexType(type, Nullability.definitelyNotNull(), appView));
return new ConstClass(out, type);
}
public ConstNumber createConstNull() {
- Value out = createValue(TypeLatticeElement.getNull());
+ Value out = createValue(TypeElement.getNull());
return new ConstNumber(out, 0);
}
public ConstNumber createConstNull(DebugLocalInfo local) {
- Value out = createValue(TypeLatticeElement.getNull(), local);
+ Value out = createValue(TypeElement.getNull(), local);
return new ConstNumber(out, 0);
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/If.java b/src/main/java/com/android/tools/r8/ir/code/If.java
index 611ebcc..da0592d 100644
--- a/src/main/java/com/android/tools/r8/ir/code/If.java
+++ b/src/main/java/com/android/tools/r8/ir/code/If.java
@@ -10,7 +10,7 @@
import com.android.tools.r8.cf.code.CfIf;
import com.android.tools.r8.cf.code.CfIfCmp;
import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.utils.CfgPrinter;
@@ -61,10 +61,10 @@
}
}
- private static boolean verifyTypeCompatible(TypeLatticeElement valueType, If.Type ifType) {
+ private static boolean verifyTypeCompatible(TypeElement valueType, If.Type ifType) {
return valueType.isInt()
|| (valueType.isFloat() && (ifType == Type.EQ || ifType == Type.NE))
- || (valueType.isReference() && (ifType == Type.EQ || ifType == Type.NE));
+ || (valueType.isReferenceType() && (ifType == Type.EQ || ifType == Type.NE));
}
private Type type;
@@ -199,14 +199,14 @@
public BasicBlock targetFromCondition(ConstNumber value) {
assert isZeroTest();
- assert verifyTypeCompatible(value.outValue().getTypeLattice(), type);
+ assert verifyTypeCompatible(value.outValue().getType(), type);
return targetFromCondition(Long.signum(value.getRawValue()));
}
public BasicBlock targetFromCondition(ConstNumber left, ConstNumber right) {
assert !isZeroTest();
assert left.outType() == right.outType();
- assert verifyTypeCompatible(left.outValue().getTypeLattice(), type);
+ assert verifyTypeCompatible(left.outValue().getType(), type);
return targetFromCondition(Long.signum(left.getRawValue() - right.getRawValue()));
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/ImpreciseMemberTypeInstruction.java b/src/main/java/com/android/tools/r8/ir/code/ImpreciseMemberTypeInstruction.java
index 2b5bc02..ff21fbd 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ImpreciseMemberTypeInstruction.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ImpreciseMemberTypeInstruction.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.ir.conversion.TypeConstraintResolver;
public interface ImpreciseMemberTypeInstruction {
+
MemberType getMemberType();
void constrainType(TypeConstraintResolver constraintResolver);
diff --git a/src/main/java/com/android/tools/r8/ir/code/InitClass.java b/src/main/java/com/android/tools/r8/ir/code/InitClass.java
index 8dd260c..02ee0eb 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InitClass.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InitClass.java
@@ -16,7 +16,7 @@
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis.AnalysisAssumption;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis.Query;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
@@ -30,7 +30,7 @@
public InitClass(Value outValue, DexType clazz) {
super(outValue);
assert hasOutValue();
- assert outValue.getTypeLattice().isInt();
+ assert outValue.getType().isInt();
assert clazz.isClassType();
this.clazz = clazz;
}
@@ -50,8 +50,8 @@
}
@Override
- public TypeLatticeElement evaluate(AppView<?> appView) {
- return TypeLatticeElement.getInt();
+ public TypeElement evaluate(AppView<?> appView) {
+ return TypeElement.getInt();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/InstanceGet.java b/src/main/java/com/android/tools/r8/ir/code/InstanceGet.java
index 6d9b8e9..6edc6da 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InstanceGet.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InstanceGet.java
@@ -23,7 +23,7 @@
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis.AnalysisAssumption;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis.Query;
import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
@@ -68,9 +68,9 @@
@Override
public boolean couldIntroduceAnAlias(AppView<?> appView, Value root) {
- assert root != null && root.getTypeLattice().isReference();
+ assert root != null && root.getType().isReferenceType();
assert outValue != null;
- return outValue.getTypeLattice().isReference();
+ return outValue.getType().isReferenceType();
}
@Override
@@ -181,8 +181,8 @@
}
@Override
- public TypeLatticeElement evaluate(AppView<?> appView) {
- return TypeLatticeElement.fromDexType(getField().type, Nullability.maybeNull(), appView);
+ public TypeElement evaluate(AppView<?> appView) {
+ return TypeElement.fromDexType(getField().type, Nullability.maybeNull(), appView);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/InstanceOf.java b/src/main/java/com/android/tools/r8/ir/code/InstanceOf.java
index de4fa66..c18e3c5 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InstanceOf.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InstanceOf.java
@@ -9,7 +9,7 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
@@ -91,8 +91,8 @@
}
@Override
- public TypeLatticeElement evaluate(AppView<?> appView) {
- return TypeLatticeElement.getInt();
+ public TypeElement evaluate(AppView<?> appView) {
+ return TypeElement.getInt();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/InstancePut.java b/src/main/java/com/android/tools/r8/ir/code/InstancePut.java
index 5680260..116a3e6 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InstancePut.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InstancePut.java
@@ -160,7 +160,7 @@
// If the value being written by this instruction is an array, then make sure that the value
// being written by the other instruction is the exact same value. Otherwise, the verifier
// may incorrectly join the types of these arrays to Object[].
- if (value().getTypeLattice().isArrayType() && value() != instancePut.value()) {
+ if (value().getType().isArrayType() && value() != instancePut.value()) {
return false;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Instruction.java b/src/main/java/com/android/tools/r8/ir/code/Instruction.java
index a56f0a2..654c2e8 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Instruction.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Instruction.java
@@ -19,7 +19,7 @@
import com.android.tools.r8.ir.analysis.fieldvalueanalysis.AbstractFieldSet;
import com.android.tools.r8.ir.analysis.fieldvalueanalysis.EmptyFieldSet;
import com.android.tools.r8.ir.analysis.fieldvalueanalysis.UnknownFieldSet;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.analysis.value.UnknownValue;
import com.android.tools.r8.ir.code.Assume.DynamicTypeAssumption;
@@ -145,9 +145,9 @@
}
@Override
- public TypeLatticeElement getTypeLattice() {
+ public TypeElement getOutType() {
if (hasOutValue()) {
- return outValue().getTypeLattice();
+ return outValue().getType();
}
return null;
}
@@ -661,6 +661,14 @@
return this;
}
+ public boolean isArrayAccess() {
+ return false;
+ }
+
+ public ArrayAccess asArrayAccess() {
+ return null;
+ }
+
public boolean isArrayGet() {
return false;
}
@@ -1375,7 +1383,7 @@
public abstract void insertLoadAndStores(InstructionListIterator it, LoadStoreHelper helper);
public DexType computeVerificationType(AppView<?> appView, TypeVerificationHelper helper) {
- assert outValue == null || !outValue.getTypeLattice().isReference();
+ assert outValue == null || !outValue.getType().isReferenceType();
throw new Unreachable("Instruction without object outValue cannot compute verification type");
}
@@ -1389,7 +1397,7 @@
}
// TODO(b/72693244): maybe rename to computeOutType once TypeVerificationHelper is gone?
- public TypeLatticeElement evaluate(AppView<?> appView) {
+ public TypeElement evaluate(AppView<?> appView) {
assert outValue == null;
throw new Unimplemented(
"Implement type lattice evaluation for: " + getInstructionName());
@@ -1398,16 +1406,16 @@
public boolean verifyTypes(AppView<?> appView) {
// TODO(b/72693244): for instructions with invariant out type, we can verify type directly here.
if (outValue != null) {
- TypeLatticeElement outTypeLatticeElement = outValue.getTypeLattice();
- if (outTypeLatticeElement.isArrayType()) {
+ TypeElement outTypeElement = outValue.getType();
+ if (outTypeElement.isArrayType()) {
DexType outBaseType =
- outTypeLatticeElement
- .asArrayTypeLatticeElement()
- .getArrayType(appView.dexItemFactory())
+ outTypeElement
+ .asArrayType()
+ .toDexType(appView.dexItemFactory())
.toBaseType(appView.dexItemFactory());
assert appView.graphLense().lookupType(outBaseType) == outBaseType;
- } else if (outTypeLatticeElement.isClassType()) {
- DexType outType = outTypeLatticeElement.asClassTypeLatticeElement().getClassType();
+ } else if (outTypeElement.isClassType()) {
+ DexType outType = outTypeElement.asClassType().getClassType();
assert appView.graphLense().lookupType(outType) == outType;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Invoke.java b/src/main/java/com/android/tools/r8/ir/code/Invoke.java
index 15834d9..05e80d1 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Invoke.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Invoke.java
@@ -16,7 +16,7 @@
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.DexBuilder;
import java.util.List;
import java.util.Set;
@@ -167,14 +167,14 @@
protected void addInvokeAndMoveResult(
com.android.tools.r8.code.Instruction instruction, DexBuilder builder) {
if (outValue != null && outValue.needsRegister()) {
- TypeLatticeElement moveType = outValue.getTypeLattice();
+ TypeElement moveType = outValue.getType();
int register = builder.allocatedRegister(outValue, getNumber());
com.android.tools.r8.code.Instruction moveResult;
if (moveType.isSinglePrimitive()) {
moveResult = new MoveResult(register);
} else if (moveType.isWidePrimitive()) {
moveResult = new MoveResultWide(register);
- } else if (moveType.isReference()) {
+ } else if (moveType.isReferenceType()) {
moveResult = new MoveResultObject(register);
} else {
throw new Unreachable("Unexpected result type " + outType());
@@ -187,24 +187,27 @@
@Override
public boolean couldIntroduceAnAlias(AppView<?> appView, Value root) {
- assert root != null && root.getTypeLattice().isReference();
+ assert root != null && root.getType().isReferenceType();
if (outValue == null) {
return false;
}
- TypeLatticeElement outType = outValue.getTypeLattice();
- if (outType.isPrimitive()) {
+ TypeElement outType = outValue.getType();
+ if (outType.isPrimitiveType()) {
return false;
}
if (appView.appInfo().hasSubtyping()) {
if (outType.isClassType()
- && root.getTypeLattice().isClassType()
- && appView.appInfo().withSubtyping().inDifferentHierarchy(
- outType.asClassTypeLatticeElement().getClassType(),
- root.getTypeLattice().asClassTypeLatticeElement().getClassType())) {
+ && root.getType().isClassType()
+ && appView
+ .appInfo()
+ .withSubtyping()
+ .inDifferentHierarchy(
+ outType.asClassType().getClassType(),
+ root.getType().asClassType().getClassType())) {
return false;
}
}
- return outType.isReference();
+ return outType.isReferenceType();
}
@Override
@@ -284,12 +287,12 @@
}
@Override
- public TypeLatticeElement evaluate(AppView<?> appView) {
+ public TypeElement evaluate(AppView<?> appView) {
DexType returnType = getReturnType();
if (returnType.isVoidType()) {
throw new Unreachable("void methods have no type.");
}
- return TypeLatticeElement.fromDexType(returnType, Nullability.maybeNull(), appView);
+ return TypeElement.fromDexType(returnType, Nullability.maybeNull(), appView);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeCustom.java b/src/main/java/com/android/tools/r8/ir/code/InvokeCustom.java
index 2c7dcfb..9ee1988 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeCustom.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeCustom.java
@@ -10,9 +10,9 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.desugar.LambdaDescriptor;
@@ -43,9 +43,9 @@
}
private static boolean verifyLambdaInterfaces(
- TypeLatticeElement returnTypeLattice, Set<DexType> lambdaInterfaceSet, DexType objectType) {
- Set<DexType> primaryInterfaces = returnTypeLattice.asClassTypeLatticeElement().getInterfaces();
- if (returnTypeLattice.asClassTypeLatticeElement().getClassType() == objectType) {
+ TypeElement returnType, Set<DexType> lambdaInterfaceSet, DexType objectType) {
+ Set<DexType> primaryInterfaces = returnType.asClassType().getInterfaces();
+ if (returnType.asClassType().getClassType() == objectType) {
assert primaryInterfaces.size() == 1;
// The interfaces returned by the LambdaDescriptor assumed to already contain the primary
// interface. If they're both singleton lists they must be identical and we can return the
@@ -53,47 +53,46 @@
assert lambdaInterfaceSet.contains(primaryInterfaces.iterator().next());
} else {
// We arrive here if the primary interface is a missing class. In that case the
- // returnTypeLattice will be the missing type as the class type.
+ // returnType will be the missing type as the class type.
assert primaryInterfaces.isEmpty();
- assert lambdaInterfaceSet.contains(
- returnTypeLattice.asClassTypeLatticeElement().getClassType());
+ assert lambdaInterfaceSet.contains(returnType.asClassType().getClassType());
}
return true;
}
@Override
- public TypeLatticeElement evaluate(AppView<?> appView) {
- TypeLatticeElement returnTypeLattice = super.evaluate(appView);
+ public TypeElement evaluate(AppView<?> appView) {
+ TypeElement returnType = super.evaluate(appView);
if (!appView.appInfo().hasSubtyping()) {
- return returnTypeLattice;
+ return returnType;
}
List<DexType> lambdaInterfaces =
LambdaDescriptor.getInterfaces(callSite, appView.appInfo().withSubtyping());
if (lambdaInterfaces == null || lambdaInterfaces.isEmpty()) {
- return returnTypeLattice;
+ return returnType;
}
// The primary return type is either an interface or a missing type.
- assert returnTypeLattice instanceof ClassTypeLatticeElement;
+ assert returnType instanceof ClassTypeElement;
- Set<DexType> primaryInterfaces = returnTypeLattice.asClassTypeLatticeElement().getInterfaces();
+ Set<DexType> primaryInterfaces = returnType.asClassType().getInterfaces();
DexType objectType = appView.dexItemFactory().objectType;
- if (returnTypeLattice.asClassTypeLatticeElement().getClassType() == objectType) {
+ if (returnType.asClassType().getClassType() == objectType) {
assert primaryInterfaces.size() == 1;
// Shortcut for the common case: single interface. Save creating a new lattice type.
if (lambdaInterfaces.size() == 1) {
assert lambdaInterfaces.get(0) == primaryInterfaces.iterator().next();
- return returnTypeLattice;
+ return returnType;
}
}
Set<DexType> lambdaInterfaceSet =
ImmutableSet.<DexType>builder().addAll(lambdaInterfaces).build();
- assert verifyLambdaInterfaces(returnTypeLattice, lambdaInterfaceSet, objectType);
+ assert verifyLambdaInterfaces(returnType, lambdaInterfaceSet, objectType);
- return ClassTypeLatticeElement.create(objectType, Nullability.maybeNull(), lambdaInterfaceSet);
+ return ClassTypeElement.create(objectType, Nullability.maybeNull(), lambdaInterfaceSet);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java b/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java
index b4531c3..ddc8952 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java
@@ -166,7 +166,7 @@
// Check if it could throw a NullPointerException as a result of the receiver being null.
Value receiver = getReceiver();
- if (!assumption.canAssumeReceiverIsNotNull() && receiver.getTypeLattice().isNullable()) {
+ if (!assumption.canAssumeReceiverIsNotNull() && receiver.getType().isNullable()) {
return true;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeMethod.java b/src/main/java/com/android/tools/r8/ir/code/InvokeMethod.java
index 401b4df..9b708bc 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeMethod.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeMethod.java
@@ -161,7 +161,7 @@
// incorrectly join the types of these arrays to Object[].
for (int i = 0; i < arguments().size(); ++i) {
Value argument = arguments().get(i);
- if (argument.getTypeLattice().isArrayType() && argument != invoke.arguments().get(i)) {
+ if (argument.getType().isArrayType() && argument != invoke.arguments().get(i)) {
return false;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeMethodWithReceiver.java b/src/main/java/com/android/tools/r8/ir/code/InvokeMethodWithReceiver.java
index e15a387..689bf8f 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeMethodWithReceiver.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeMethodWithReceiver.java
@@ -8,9 +8,9 @@
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis;
-import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.optimize.DefaultInliningOracle;
import com.android.tools.r8.ir.optimize.Inliner.InlineAction;
import com.android.tools.r8.ir.optimize.Inliner.Reason;
@@ -70,12 +70,12 @@
assert super.verifyTypes(appView);
Value receiver = getReceiver();
- TypeLatticeElement receiverType = receiver.getTypeLattice();
+ TypeElement receiverType = receiver.getType();
assert receiverType.isPreciseType();
if (appView.appInfo().hasLiveness()) {
AppView<AppInfoWithLiveness> appViewWithLiveness = appView.withLiveness();
- ClassTypeLatticeElement receiverLowerBoundType =
+ ClassTypeElement receiverLowerBoundType =
receiver.getDynamicLowerBoundType(appViewWithLiveness);
if (receiverLowerBoundType != null) {
DexType refinedReceiverType =
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeMultiNewArray.java b/src/main/java/com/android/tools/r8/ir/code/InvokeMultiNewArray.java
index 02e45ef..a71d185 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeMultiNewArray.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeMultiNewArray.java
@@ -14,7 +14,7 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.AbstractError;
import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
@@ -82,8 +82,8 @@
}
@Override
- public TypeLatticeElement evaluate(AppView<?> appView) {
- return TypeLatticeElement.fromDexType(type, Nullability.definitelyNotNull(), appView);
+ public TypeElement evaluate(AppView<?> appView) {
+ return TypeElement.fromDexType(type, Nullability.definitelyNotNull(), appView);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeNewArray.java b/src/main/java/com/android/tools/r8/ir/code/InvokeNewArray.java
index ce75c7c..7992a1c 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeNewArray.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeNewArray.java
@@ -15,7 +15,7 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.AbstractError;
import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
@@ -111,8 +111,8 @@
}
@Override
- public TypeLatticeElement evaluate(AppView<?> appView) {
- return TypeLatticeElement.fromDexType(type, Nullability.definitelyNotNull(), appView);
+ public TypeElement evaluate(AppView<?> appView) {
+ return TypeElement.fromDexType(type, Nullability.definitelyNotNull(), appView);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java b/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java
index 1218f08..711c911 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java
@@ -154,7 +154,7 @@
// Check if it could throw a NullPointerException as a result of the receiver being null.
Value receiver = getReceiver();
- if (!assumption.canAssumeReceiverIsNotNull() && receiver.getTypeLattice().isNullable()) {
+ if (!assumption.canAssumeReceiverIsNotNull() && receiver.getType().isNullable()) {
return true;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Load.java b/src/main/java/com/android/tools/r8/ir/code/Load.java
index e1885b0..9886690 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Load.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Load.java
@@ -10,7 +10,7 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
@@ -89,8 +89,8 @@
}
@Override
- public TypeLatticeElement evaluate(AppView<?> appView) {
- return src().getTypeLattice();
+ public TypeElement evaluate(AppView<?> appView) {
+ return src().getType();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/LogicalBinop.java b/src/main/java/com/android/tools/r8/ir/code/LogicalBinop.java
index 7f87253..267db9b 100644
--- a/src/main/java/com/android/tools/r8/ir/code/LogicalBinop.java
+++ b/src/main/java/com/android/tools/r8/ir/code/LogicalBinop.java
@@ -9,7 +9,7 @@
import com.android.tools.r8.ir.analysis.constant.Bottom;
import com.android.tools.r8.ir.analysis.constant.ConstLatticeElement;
import com.android.tools.r8.ir.analysis.constant.LatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import java.util.function.Function;
@@ -117,7 +117,7 @@
ConstNumber newConst;
if (type == NumericType.INT) {
int result = foldIntegers(leftConst.getIntValue(), rightConst.getIntValue());
- Value value = code.createValue(TypeLatticeElement.getInt(), getLocalInfo());
+ Value value = code.createValue(TypeElement.getInt(), getLocalInfo());
newConst = new ConstNumber(value, result);
} else {
assert type == NumericType.LONG;
@@ -129,7 +129,7 @@
right = rightConst.getLongValue();
}
long result = foldLongs(leftConst.getLongValue(), right);
- Value value = code.createValue(TypeLatticeElement.getLong(), getLocalInfo());
+ Value value = code.createValue(TypeElement.getLong(), getLocalInfo());
newConst = new ConstNumber(value, result);
}
return new ConstLatticeElement(newConst);
diff --git a/src/main/java/com/android/tools/r8/ir/code/Move.java b/src/main/java/com/android/tools/r8/ir/code/Move.java
index 3478645..adcc848 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Move.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Move.java
@@ -9,7 +9,7 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
@@ -73,7 +73,7 @@
@Override
public String toString() {
- return super.toString() + " (" + outValue().getTypeLattice() + ")";
+ return super.toString() + " (" + outValue().getType() + ")";
}
@Override
@@ -104,8 +104,8 @@
}
@Override
- public TypeLatticeElement evaluate(AppView<?> appView) {
- return src().getTypeLattice();
+ public TypeElement evaluate(AppView<?> appView) {
+ return src().getType();
}
@Override
@@ -128,7 +128,7 @@
super.verifyTypes(appView);
// DebugLocalWrite defines it's own verification of types but should be allowed to call super.
if (!this.isDebugLocalWrite()) {
- assert src().getTypeLattice().equals(outValue().getTypeLattice());
+ assert src().getType().equals(outValue().getType());
}
return true;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/MoveException.java b/src/main/java/com/android/tools/r8/ir/code/MoveException.java
index 143227a..e9cd95f 100644
--- a/src/main/java/com/android/tools/r8/ir/code/MoveException.java
+++ b/src/main/java/com/android/tools/r8/ir/code/MoveException.java
@@ -9,7 +9,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
@@ -111,8 +111,8 @@
}
@Override
- public TypeLatticeElement evaluate(AppView<?> appView) {
- return TypeLatticeElement.fromDexType(exceptionType, Nullability.definitelyNotNull(), appView);
+ public TypeElement evaluate(AppView<?> appView) {
+ return TypeElement.fromDexType(exceptionType, Nullability.definitelyNotNull(), appView);
}
public DexType getExceptionType() {
diff --git a/src/main/java/com/android/tools/r8/ir/code/Neg.java b/src/main/java/com/android/tools/r8/ir/code/Neg.java
index 41ec4f1..ad0886a 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Neg.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Neg.java
@@ -12,8 +12,8 @@
import com.android.tools.r8.ir.analysis.constant.Bottom;
import com.android.tools.r8.ir.analysis.constant.ConstLatticeElement;
import com.android.tools.r8.ir.analysis.constant.LatticeElement;
-import com.android.tools.r8.ir.analysis.type.PrimitiveTypeLatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.PrimitiveTypeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import java.util.function.Function;
@@ -88,7 +88,7 @@
LatticeElement sourceLattice = getLatticeElement.apply(source());
if (sourceLattice.isConst()) {
ConstNumber sourceConst = sourceLattice.asConst().getConstNumber();
- TypeLatticeElement typeLattice = PrimitiveTypeLatticeElement.fromNumericType(type);
+ TypeElement typeLattice = PrimitiveTypeElement.fromNumericType(type);
Value value = code.createValue(typeLattice, getLocalInfo());
ConstNumber newConst;
if (type == NumericType.INT) {
diff --git a/src/main/java/com/android/tools/r8/ir/code/NewArrayEmpty.java b/src/main/java/com/android/tools/r8/ir/code/NewArrayEmpty.java
index 6d2d5df..bd5c34f 100644
--- a/src/main/java/com/android/tools/r8/ir/code/NewArrayEmpty.java
+++ b/src/main/java/com/android/tools/r8/ir/code/NewArrayEmpty.java
@@ -11,7 +11,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
@@ -134,8 +134,8 @@
}
@Override
- public TypeLatticeElement evaluate(AppView<?> appView) {
- return TypeLatticeElement.fromDexType(type, Nullability.definitelyNotNull(), appView);
+ public TypeElement evaluate(AppView<?> appView) {
+ return TypeElement.fromDexType(type, Nullability.definitelyNotNull(), appView);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/NewArrayFilledData.java b/src/main/java/com/android/tools/r8/ir/code/NewArrayFilledData.java
index afd87ff..2211a59 100644
--- a/src/main/java/com/android/tools/r8/ir/code/NewArrayFilledData.java
+++ b/src/main/java/com/android/tools/r8/ir/code/NewArrayFilledData.java
@@ -121,7 +121,7 @@
return AbstractError.top();
}
- if (src().getTypeLattice().isNullable()) {
+ if (src().getType().isNullable()) {
return AbstractError.top();
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/NewInstance.java b/src/main/java/com/android/tools/r8/ir/code/NewInstance.java
index 384a27a..d8acd0b 100644
--- a/src/main/java/com/android/tools/r8/ir/code/NewInstance.java
+++ b/src/main/java/com/android/tools/r8/ir/code/NewInstance.java
@@ -19,7 +19,7 @@
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis.AnalysisAssumption;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis.Query;
import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
@@ -125,8 +125,8 @@
}
@Override
- public TypeLatticeElement evaluate(AppView<?> appView) {
- return TypeLatticeElement.fromDexType(clazz, Nullability.definitelyNotNull(), appView);
+ public TypeElement evaluate(AppView<?> appView) {
+ return TypeElement.fromDexType(clazz, Nullability.definitelyNotNull(), appView);
}
@Override
@@ -226,10 +226,9 @@
@Override
public boolean verifyTypes(AppView<?> appView) {
- TypeLatticeElement type = outValue().getTypeLattice();
+ TypeElement type = outValue().getType();
assert type.isClassType();
- assert type.asClassTypeLatticeElement().getClassType() == clazz
- || appView.options().testing.allowTypeErrors;
+ assert type.asClassType().getClassType() == clazz || appView.options().testing.allowTypeErrors;
assert type.isDefinitelyNotNull();
return true;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Not.java b/src/main/java/com/android/tools/r8/ir/code/Not.java
index 0ab5c78..d000623 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Not.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Not.java
@@ -10,8 +10,8 @@
import com.android.tools.r8.ir.analysis.constant.Bottom;
import com.android.tools.r8.ir.analysis.constant.ConstLatticeElement;
import com.android.tools.r8.ir.analysis.constant.LatticeElement;
-import com.android.tools.r8.ir.analysis.type.PrimitiveTypeLatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.PrimitiveTypeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import java.util.function.Function;
@@ -45,13 +45,13 @@
LatticeElement sourceLattice = getLatticeElement.apply(source());
if (sourceLattice.isConst()) {
ConstNumber sourceConst = sourceLattice.asConst().getConstNumber();
- TypeLatticeElement typeLattice = PrimitiveTypeLatticeElement.fromNumericType(type);
- Value value = code.createValue(typeLattice, getLocalInfo());
+ TypeElement type = PrimitiveTypeElement.fromNumericType(this.type);
+ Value value = code.createValue(type, getLocalInfo());
ConstNumber newConst;
- if (type == NumericType.INT) {
+ if (this.type == NumericType.INT) {
newConst = new ConstNumber(value, ~sourceConst.getIntValue());
} else {
- assert type == NumericType.LONG;
+ assert this.type == NumericType.LONG;
newConst = new ConstNumber(value, ~sourceConst.getLongValue());
}
return new ConstLatticeElement(newConst);
diff --git a/src/main/java/com/android/tools/r8/ir/code/NumberConversion.java b/src/main/java/com/android/tools/r8/ir/code/NumberConversion.java
index 99adf0c..e6b6f8d 100644
--- a/src/main/java/com/android/tools/r8/ir/code/NumberConversion.java
+++ b/src/main/java/com/android/tools/r8/ir/code/NumberConversion.java
@@ -21,8 +21,8 @@
import com.android.tools.r8.code.LongToInt;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.ir.analysis.type.PrimitiveTypeLatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.PrimitiveTypeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import java.util.Set;
@@ -153,8 +153,8 @@
}
@Override
- public TypeLatticeElement evaluate(AppView<?> appView) {
- return PrimitiveTypeLatticeElement.fromNumericType(to);
+ public TypeElement evaluate(AppView<?> appView) {
+ return PrimitiveTypeElement.fromNumericType(to);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/Phi.java b/src/main/java/com/android/tools/r8/ir/code/Phi.java
index 95c2608..49779aa 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Phi.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Phi.java
@@ -11,7 +11,7 @@
import com.android.tools.r8.graph.DebugLocalInfo;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.BasicBlock.EdgeType;
import com.android.tools.r8.ir.conversion.IRBuilder;
import com.android.tools.r8.ir.conversion.TypeConstraintResolver;
@@ -53,10 +53,10 @@
public Phi(
int number,
BasicBlock block,
- TypeLatticeElement typeLattice,
+ TypeElement type,
DebugLocalInfo local,
RegisterReadType readType) {
- super(number, typeLattice, local);
+ super(number, type, local);
this.block = block;
this.readType = readType;
block.addPhi(this);
@@ -97,7 +97,7 @@
throw new InvalidDebugInfoException(
"Type information in locals-table is inconsistent."
+ " Cannot constrain type: "
- + typeLattice
+ + type
+ " for value: "
+ this
+ " by constraint "
@@ -115,7 +115,7 @@
throwUndefinedValueError();
}
- ValueTypeConstraint readConstraint = TypeConstraintResolver.constraintForType(typeLattice);
+ ValueTypeConstraint readConstraint = TypeConstraintResolver.constraintForType(type);
List<Value> operands = new ArrayList<>(block.getPredecessors().size());
for (BasicBlock pred : block.getPredecessors()) {
EdgeType edgeType = pred.getEdgeType(block);
@@ -125,7 +125,7 @@
if (readType != RegisterReadType.NORMAL) {
for (Value operand : operands) {
- TypeLatticeElement type = operand.getTypeLattice();
+ TypeElement type = operand.getType();
ValueTypeConstraint constraint = TypeConstraintResolver.constraintForType(type);
abortOnInvalidDebugInfo(constraint);
}
@@ -261,8 +261,8 @@
return false;
}
// Ensure that the value that replaces this phi is constrained to the type of this phi.
- if (builder != null && typeLattice.isPreciseType() && !typeLattice.isBottom()) {
- builder.constrainType(same, ValueTypeConstraint.fromTypeLattice(typeLattice));
+ if (builder != null && type.isPreciseType() && !type.isBottom()) {
+ builder.constrainType(same, ValueTypeConstraint.fromTypeLattice(type));
}
if (affectedValues != null) {
affectedValues.addAll(this.affectedValues());
@@ -320,7 +320,7 @@
}
builder.append(" <- phi");
StringUtils.append(builder, ListUtils.map(operands, Value::toString));
- builder.append(" : ").append(getTypeLattice());
+ builder.append(" : ").append(getType());
return builder.toString();
}
@@ -398,17 +398,16 @@
}
// Type of phi(v1, v2, ..., vn) is the least upper bound of all those n operands.
- public TypeLatticeElement computePhiType(AppView<?> appView) {
- TypeLatticeElement result = TypeLatticeElement.getBottom();
+ public TypeElement computePhiType(AppView<?> appView) {
+ TypeElement result = TypeElement.getBottom();
for (Value operand : getOperands()) {
- result = result.join(operand.getTypeLattice(), appView);
+ result = result.join(operand.getType(), appView);
}
return result;
}
@Override
- public TypeLatticeElement getDynamicUpperBoundType(
- AppView<? extends AppInfoWithSubtyping> appView) {
+ public TypeElement getDynamicUpperBoundType(AppView<? extends AppInfoWithSubtyping> appView) {
Set<Phi> reachablePhis = SetUtils.newIdentityHashSet(this);
Deque<Phi> worklist = DequeUtils.newArrayDeque(this);
while (!worklist.isEmpty()) {
@@ -422,7 +421,7 @@
}
}
Set<Value> visitedOperands = Sets.newIdentityHashSet();
- TypeLatticeElement result = TypeLatticeElement.getBottom();
+ TypeElement result = TypeElement.getBottom();
for (Phi phi : reachablePhis) {
for (Value operand : phi.getOperands()) {
if (!operand.getAliasedValue().isPhi() && visitedOperands.add(operand)) {
diff --git a/src/main/java/com/android/tools/r8/ir/code/Return.java b/src/main/java/com/android/tools/r8/ir/code/Return.java
index 037f856..0adf292 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Return.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Return.java
@@ -12,7 +12,7 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
@@ -42,9 +42,9 @@
return inValues.size() == 0;
}
- public TypeLatticeElement getReturnType() {
+ public TypeElement getReturnType() {
assert !isReturnVoid();
- return returnValue().getTypeLattice();
+ return returnValue().getType();
}
public Value returnValue() {
@@ -57,8 +57,8 @@
return new ReturnVoid();
}
int register = builder.allocatedRegister(returnValue(), getNumber());
- TypeLatticeElement returnType = getReturnType();
- if (returnType.isReference()) {
+ TypeElement returnType = getReturnType();
+ if (returnType.isReferenceType()) {
return new ReturnObject(register);
}
if (returnType.isSinglePrimitive()) {
@@ -124,8 +124,6 @@
@Override
public void buildCf(CfBuilder builder) {
builder.add(
- isReturnVoid()
- ? new CfReturnVoid()
- : new CfReturn(ValueType.fromTypeLattice(getReturnType())));
+ isReturnVoid() ? new CfReturnVoid() : new CfReturn(ValueType.fromType(getReturnType())));
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/StackValue.java b/src/main/java/com/android/tools/r8/ir/code/StackValue.java
index 430f290..0d13811 100644
--- a/src/main/java/com/android/tools/r8/ir/code/StackValue.java
+++ b/src/main/java/com/android/tools/r8/ir/code/StackValue.java
@@ -6,15 +6,15 @@
import com.android.tools.r8.cf.TypeVerificationHelper.TypeInfo;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
public class StackValue extends Value {
private final int height;
private final TypeInfo typeInfo;
- private StackValue(TypeInfo typeInfo, TypeLatticeElement typeLattice, int height) {
- super(Value.UNDEFINED_NUMBER, typeLattice, null);
+ private StackValue(TypeInfo typeInfo, TypeElement type, int height) {
+ super(Value.UNDEFINED_NUMBER, type, null);
this.height = height;
this.typeInfo = typeInfo;
assert height >= 0;
@@ -23,7 +23,7 @@
public static StackValue create(TypeInfo typeInfo, int height, AppView<?> appView) {
return new StackValue(
typeInfo,
- TypeLatticeElement.fromDexType(typeInfo.getDexType(), Nullability.maybeNull(), appView),
+ TypeElement.fromDexType(typeInfo.getDexType(), Nullability.maybeNull(), appView),
height);
}
@@ -36,7 +36,7 @@
}
public StackValue duplicate(int height) {
- return new StackValue(typeInfo, getTypeLattice(), height);
+ return new StackValue(typeInfo, getType(), height);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/StackValues.java b/src/main/java/com/android/tools/r8/ir/code/StackValues.java
index 528cddd..d0c56eb 100644
--- a/src/main/java/com/android/tools/r8/ir/code/StackValues.java
+++ b/src/main/java/com/android/tools/r8/ir/code/StackValues.java
@@ -5,7 +5,7 @@
package com.android.tools.r8.ir.code;
import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
/**
* {@link StackValues} allow us to represent stack operations that produces two or more elements on
@@ -16,7 +16,7 @@
private final StackValue[] stackValues;
public StackValues(StackValue... stackValues) {
- super(Value.UNDEFINED_NUMBER, TypeLatticeElement.getBottom(), null);
+ super(Value.UNDEFINED_NUMBER, TypeElement.getBottom(), null);
this.stackValues = stackValues;
assert stackValues.length >= 2;
}
@@ -55,7 +55,7 @@
}
@Override
- public TypeLatticeElement getTypeLattice() {
+ public TypeElement getType() {
throw new Unreachable();
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/StaticGet.java b/src/main/java/com/android/tools/r8/ir/code/StaticGet.java
index a3c202b..2c246f92 100644
--- a/src/main/java/com/android/tools/r8/ir/code/StaticGet.java
+++ b/src/main/java/com/android/tools/r8/ir/code/StaticGet.java
@@ -22,7 +22,7 @@
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis.AnalysisAssumption;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis.Query;
import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
@@ -40,7 +40,7 @@
Value newValue =
new Value(
code.valueNumberGenerator.next(),
- original.outValue().getTypeLattice(),
+ original.outValue().getType(),
original.getLocalInfo());
return copyOf(newValue, original);
}
@@ -71,22 +71,25 @@
@Override
public boolean couldIntroduceAnAlias(AppView<?> appView, Value root) {
- assert root != null && root.getTypeLattice().isReference();
+ assert root != null && root.getType().isReferenceType();
assert outValue != null;
- TypeLatticeElement outType = outValue.getTypeLattice();
- if (outType.isPrimitive()) {
+ TypeElement outType = outValue.getType();
+ if (outType.isPrimitiveType()) {
return false;
}
if (appView.appInfo().hasSubtyping()) {
if (outType.isClassType()
- && root.getTypeLattice().isClassType()
- && appView.appInfo().withSubtyping().inDifferentHierarchy(
- outType.asClassTypeLatticeElement().getClassType(),
- root.getTypeLattice().asClassTypeLatticeElement().getClassType())) {
+ && root.getType().isClassType()
+ && appView
+ .appInfo()
+ .withSubtyping()
+ .inDifferentHierarchy(
+ outType.asClassType().getClassType(),
+ root.getType().asClassType().getClassType())) {
return false;
}
}
- return outType.isReference();
+ return outType.isReferenceType();
}
@Override
@@ -219,8 +222,8 @@
}
@Override
- public TypeLatticeElement evaluate(AppView<?> appView) {
- return TypeLatticeElement.fromDexType(getField().type, Nullability.maybeNull(), appView);
+ public TypeElement evaluate(AppView<?> appView) {
+ return TypeElement.fromDexType(getField().type, Nullability.maybeNull(), appView);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/StaticPut.java b/src/main/java/com/android/tools/r8/ir/code/StaticPut.java
index e7d2bdc..16c102b 100644
--- a/src/main/java/com/android/tools/r8/ir/code/StaticPut.java
+++ b/src/main/java/com/android/tools/r8/ir/code/StaticPut.java
@@ -168,7 +168,7 @@
// If the value being written by this instruction is an array, then make sure that the value
// being written by the other instruction is the exact same value. Otherwise, the verifier
// may incorrectly join the types of these arrays to Object[].
- if (value().getTypeLattice().isArrayType() && value() != staticPut.value()) {
+ if (value().getType().isArrayType() && value() != staticPut.value()) {
return false;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Store.java b/src/main/java/com/android/tools/r8/ir/code/Store.java
index 72eb683..4fe63c0 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Store.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Store.java
@@ -11,7 +11,7 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
@@ -89,8 +89,8 @@
}
@Override
- public TypeLatticeElement evaluate(AppView<?> appView) {
- return src().getTypeLattice();
+ public TypeElement evaluate(AppView<?> appView) {
+ return src().getType();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/Swap.java b/src/main/java/com/android/tools/r8/ir/code/Swap.java
index 8cdaa77..2515934 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Swap.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Swap.java
@@ -26,7 +26,7 @@
super(dest, ImmutableList.of(src1, src2));
assert src1.isValueOnStack() && !(src1 instanceof StackValues);
assert src2.isValueOnStack() && !(src2 instanceof StackValues);
- assert !src1.getTypeLattice().isWidePrimitive() && !src2.getTypeLattice().isWidePrimitive();
+ assert !src1.getType().isWidePrimitive() && !src2.getType().isWidePrimitive();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/Throw.java b/src/main/java/com/android/tools/r8/ir/code/Throw.java
index 115e9fd..2b6b80d 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Throw.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Throw.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
@@ -91,7 +91,7 @@
if (exception() == value) {
return true;
}
- TypeLatticeElement exceptionType = exception().getTypeLattice();
+ TypeElement exceptionType = exception().getType();
if (exceptionType.isNullType()) {
// throw null
return true;
diff --git a/src/main/java/com/android/tools/r8/ir/code/TypeAndLocalInfoSupplier.java b/src/main/java/com/android/tools/r8/ir/code/TypeAndLocalInfoSupplier.java
index 0d5cfd6..d28407f 100644
--- a/src/main/java/com/android/tools/r8/ir/code/TypeAndLocalInfoSupplier.java
+++ b/src/main/java/com/android/tools/r8/ir/code/TypeAndLocalInfoSupplier.java
@@ -5,13 +5,14 @@
package com.android.tools.r8.ir.code;
import com.android.tools.r8.graph.DebugLocalInfo;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
public interface TypeAndLocalInfoSupplier {
DebugLocalInfo getLocalInfo();
- TypeLatticeElement getTypeLattice();
- static TypeAndLocalInfoSupplier create(TypeLatticeElement type, DebugLocalInfo local) {
+ TypeElement getOutType();
+
+ static TypeAndLocalInfoSupplier create(TypeElement type, DebugLocalInfo local) {
return new TypeAndLocalInfoSupplier() {
@Override
@@ -20,7 +21,7 @@
}
@Override
- public TypeLatticeElement getTypeLattice() {
+ public TypeElement getOutType() {
return type;
}
};
diff --git a/src/main/java/com/android/tools/r8/ir/code/Unop.java b/src/main/java/com/android/tools/r8/ir/code/Unop.java
index 57fad2d..1765626 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Unop.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Unop.java
@@ -7,7 +7,7 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.InliningConstraints;
@@ -58,8 +58,8 @@
}
@Override
- public TypeLatticeElement evaluate(AppView<?> appView) {
- return source().getTypeLattice();
+ public TypeElement evaluate(AppView<?> appView) {
+ return source().getType();
}
@Override
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 25ed39f..e84f64a 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
@@ -20,8 +20,8 @@
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.analysis.value.UnknownValue;
import com.android.tools.r8.ir.regalloc.LiveIntervals;
@@ -52,81 +52,80 @@
public void constrainType(
ValueTypeConstraint constraint, DexMethod method, Origin origin, Reporter reporter) {
- TypeLatticeElement constrainedType = constrainedType(constraint);
+ TypeElement constrainedType = constrainedType(constraint);
if (constrainedType == null) {
throw reporter.fatalError(
new StringDiagnostic(
"Cannot constrain type: "
- + typeLattice
+ + type
+ " for value: "
+ this
+ " by constraint: "
+ constraint,
origin,
new MethodPosition(method)));
- } else if (constrainedType != typeLattice) {
- setTypeLattice(constrainedType);
+ } else if (constrainedType != type) {
+ setType(constrainedType);
}
}
- public TypeLatticeElement constrainedType(ValueTypeConstraint constraint) {
- if (constraint == ValueTypeConstraint.INT_OR_FLOAT_OR_OBJECT
- && !typeLattice.isWidePrimitive()) {
- return typeLattice;
+ public TypeElement constrainedType(ValueTypeConstraint constraint) {
+ if (constraint == ValueTypeConstraint.INT_OR_FLOAT_OR_OBJECT && !type.isWidePrimitive()) {
+ return type;
}
switch (constraint) {
case OBJECT:
- if (typeLattice.isTop()) {
+ if (type.isTop()) {
if (definition != null && definition.isConstNumber()) {
assert definition.asConstNumber().isZero();
- return TypeLatticeElement.getNull();
+ return TypeElement.getNull();
} else {
- return TypeLatticeElement.getBottom();
+ return TypeElement.getBottom();
}
}
- if (typeLattice.isReference()) {
- return typeLattice;
+ if (type.isReferenceType()) {
+ return type;
}
- if (typeLattice.isBottom()) {
+ if (type.isBottom()) {
// Only a few instructions may propagate a bottom input to a bottom output.
assert isPhi()
|| definition.isDebugLocalWrite()
|| (definition.isArrayGet()
&& definition.asArrayGet().getMemberType() == MemberType.OBJECT);
- return typeLattice;
+ return type;
}
break;
case INT:
- if (typeLattice.isTop() || (typeLattice.isSinglePrimitive() && !typeLattice.isFloat())) {
- return TypeLatticeElement.getInt();
+ if (type.isTop() || (type.isSinglePrimitive() && !type.isFloat())) {
+ return TypeElement.getInt();
}
break;
case FLOAT:
- if (typeLattice.isTop() || (typeLattice.isSinglePrimitive() && !typeLattice.isInt())) {
- return TypeLatticeElement.getFloat();
+ if (type.isTop() || (type.isSinglePrimitive() && !type.isInt())) {
+ return TypeElement.getFloat();
}
break;
case INT_OR_FLOAT:
- if (typeLattice.isTop()) {
- return TypeLatticeElement.getSingle();
+ if (type.isTop()) {
+ return TypeElement.getSingle();
}
- if (typeLattice.isSinglePrimitive()) {
- return typeLattice;
+ if (type.isSinglePrimitive()) {
+ return type;
}
break;
case LONG:
- if (typeLattice.isWidePrimitive() && !typeLattice.isDouble()) {
- return TypeLatticeElement.getLong();
+ if (type.isWidePrimitive() && !type.isDouble()) {
+ return TypeElement.getLong();
}
break;
case DOUBLE:
- if (typeLattice.isWidePrimitive() && !typeLattice.isLong()) {
- return TypeLatticeElement.getDouble();
+ if (type.isWidePrimitive() && !type.isLong()) {
+ return TypeElement.getDouble();
}
break;
case LONG_OR_DOUBLE:
- if (typeLattice.isWidePrimitive()) {
- return typeLattice;
+ if (type.isWidePrimitive()) {
+ return type;
}
break;
default:
@@ -212,8 +211,7 @@
public static final int UNDEFINED_NUMBER = -1;
- public static final Value UNDEFINED =
- new Value(UNDEFINED_NUMBER, TypeLatticeElement.getBottom(), null);
+ public static final Value UNDEFINED = new Value(UNDEFINED_NUMBER, TypeElement.getBottom(), null);
protected final int number;
public Instruction definition = null;
@@ -228,13 +226,13 @@
private boolean isThis = false;
private LongInterval valueRange;
private DebugData debugData;
- protected TypeLatticeElement typeLattice;
+ protected TypeElement type;
- public Value(int number, TypeLatticeElement typeLattice, DebugLocalInfo local) {
- assert typeLattice != null;
+ public Value(int number, TypeElement type, DebugLocalInfo local) {
+ assert type != null;
this.number = number;
this.debugData = local == null ? null : new DebugData(local);
- this.typeLattice = typeLattice;
+ this.type = type;
}
public boolean isFixedRegisterValue() {
@@ -310,7 +308,7 @@
}
public int requiredRegisters() {
- return typeLattice.requiredRegisters();
+ return type.requiredRegisters();
}
public DebugLocalInfo getLocalInfo() {
@@ -553,14 +551,11 @@
// Not always null as the value can be changed via the debugger.
return false;
}
- if (typeLattice.isDefinitelyNull()) {
+ if (type.isDefinitelyNull()) {
return true;
}
- if (typeLattice.isClassType() && appView.appInfo().hasLiveness()) {
- return typeLattice
- .asClassTypeLatticeElement()
- .getClassType()
- .isAlwaysNull(appView.withLiveness());
+ if (type.isClassType() && appView.appInfo().hasLiveness()) {
+ return type.asClassType().getClassType().isAlwaysNull(appView.withLiveness());
}
return false;
}
@@ -831,7 +826,7 @@
builder.append("(");
if (isConstant && definition.asConstNumber().outValue != null) {
ConstNumber constNumber = definition.asConstNumber();
- if (constNumber.outValue().getTypeLattice().isSinglePrimitive()) {
+ if (constNumber.outValue().getType().isSinglePrimitive()) {
builder.append((int) constNumber.getRawValue());
} else {
builder.append(constNumber.getRawValue());
@@ -852,7 +847,7 @@
}
public ValueType outType() {
- return ValueType.fromTypeLattice(typeLattice);
+ return ValueType.fromType(type);
}
public ConstInstruction getConstInstruction() {
@@ -921,9 +916,9 @@
* Returns whether this value is known to never be <code>null</code>.
*/
public boolean isNeverNull() {
- assert typeLattice.isReference();
+ assert type.isReferenceType();
return (definition != null && definition.isAssumeNonNull())
- || typeLattice.nullability().isDefinitelyNotNull();
+ || type.nullability().isDefinitelyNotNull();
}
public boolean isArgument() {
@@ -956,7 +951,7 @@
}
public boolean knownToBeBoolean(Set<Phi> seen) {
- if (!getTypeLattice().isInt()) {
+ if (!getType().isInt()) {
return false;
}
@@ -1014,11 +1009,11 @@
public LongInterval getValueRange() {
if (isConstNumber()) {
- if (typeLattice.isSinglePrimitive()) {
+ if (type.isSinglePrimitive()) {
int value = getConstInstruction().asConstNumber().getIntValue();
return new LongInterval(value, value);
} else {
- assert typeLattice.isWidePrimitive();
+ assert type.isWidePrimitive();
long value = getConstInstruction().asConstNumber().getLongValue();
return new LongInterval(value, value);
}
@@ -1096,45 +1091,44 @@
*
* @param newType The new type lattice element
*/
- public void setTypeLattice(TypeLatticeElement newType) {
+ public void setType(TypeElement newType) {
assert newType != null;
- typeLattice = newType;
+ type = newType;
}
- public void widening(AppView<?> appView, TypeLatticeElement newType) {
+ public void widening(AppView<?> appView, TypeElement newType) {
// During WIDENING (due to fix-point iteration), type update is monotonically upwards,
// i.e., towards something wider.
- assert this.typeLattice.lessThanOrEqual(newType, appView)
+ assert this.type.lessThanOrEqual(newType, appView)
: "During WIDENING, "
+ newType
+ " < "
- + typeLattice
+ + type
+ " at "
+ (isPhi() ? asPhi().printPhi() : definition.toString());
- setTypeLattice(newType);
+ setType(newType);
}
- public void narrowing(AppView<?> appView, TypeLatticeElement newType) {
+ public void narrowing(AppView<?> appView, TypeElement newType) {
// During NARROWING (e.g., after inlining), type update is monotonically downwards,
// i.e., towards something narrower, with more specific type info.
assert (!appView.options().testing.enableNarrowingChecksInD8
&& !appView.enableWholeProgramOptimizations())
- || !this.typeLattice.strictlyLessThan(newType, appView)
+ || !this.type.strictlyLessThan(newType, appView)
: "During NARROWING, "
- + typeLattice
+ + type
+ " < "
+ newType
+ " at "
+ (isPhi() ? asPhi().printPhi() : definition.toString());
- setTypeLattice(newType);
+ setType(newType);
}
- public TypeLatticeElement getTypeLattice() {
- return typeLattice;
+ public TypeElement getType() {
+ return type;
}
- public TypeLatticeElement getDynamicUpperBoundType(
- AppView<? extends AppInfoWithSubtyping> appView) {
+ public TypeElement getDynamicUpperBoundType(AppView<? extends AppInfoWithSubtyping> appView) {
Value root = getAliasedValue();
if (root.isPhi()) {
assert getSpecificAliasedValue(
@@ -1147,7 +1141,7 @@
// Assume<DynamicTypeAssumption>.
Value aliasedValue =
getSpecificAliasedValue(value -> !value.isPhi() && value.definition.isAssumeDynamicType());
- TypeLatticeElement lattice;
+ TypeElement lattice;
if (aliasedValue != null) {
// If there is an alias of the receiver, which is defined by an Assume<DynamicTypeAssumption>
// instruction, then use the dynamic type as the refined receiver type.
@@ -1155,25 +1149,24 @@
aliasedValue.definition.asAssumeDynamicType().getAssumption().getDynamicUpperBoundType();
// For precision, verify that the dynamic type is at least as precise as the static type.
- assert lattice.lessThanOrEqualUpToNullability(typeLattice, appView)
- : typeLattice + " < " + lattice;
+ assert lattice.lessThanOrEqualUpToNullability(type, appView) : type + " < " + lattice;
} else {
// Otherwise, simply use the static type.
- lattice = typeLattice;
+ lattice = type;
}
// Account for nullability, which could be flown from non-null assumption in between dynamic
// type assumption or simply from array/object creation.
- if (typeLattice.isDefinitelyNotNull() && lattice.isNullable()) {
+ if (type.isDefinitelyNotNull() && lattice.isNullable()) {
// Having non-null assumption means it is a reference type.
- assert lattice.isReference();
+ assert lattice.isReferenceType();
// Then, we can return the non-null variant of dynamic type if both assumptions are aliased.
- return lattice.asReferenceTypeLatticeElement().asMeetWithNotNull();
+ return lattice.asReferenceType().asMeetWithNotNull();
}
return lattice;
}
- public ClassTypeLatticeElement getDynamicLowerBoundType(AppView<AppInfoWithLiveness> appView) {
+ public ClassTypeElement getDynamicLowerBoundType(AppView<AppInfoWithLiveness> appView) {
Value root = getAliasedValue();
if (root.isPhi()) {
return null;
@@ -1184,7 +1177,7 @@
DexType type = definition.asNewInstance().clazz;
DexClass clazz = appView.definitionFor(type);
if (clazz != null && !clazz.isInterface()) {
- return ClassTypeLatticeElement.create(type, definitelyNotNull(), appView);
+ return ClassTypeElement.create(type, definitelyNotNull(), appView);
}
return null;
}
@@ -1193,16 +1186,16 @@
// Assume<DynamicTypeAssumption>.
Value aliasedValue = getSpecificAliasedValue(value -> value.definition.isAssumeDynamicType());
if (aliasedValue != null) {
- ClassTypeLatticeElement lattice =
+ ClassTypeElement lattice =
aliasedValue.definition.asAssumeDynamicType().getAssumption().getDynamicLowerBoundType();
- return lattice != null && typeLattice.isDefinitelyNotNull() && lattice.isNullable()
+ return lattice != null && type.isDefinitelyNotNull() && lattice.isNullable()
? lattice.asMeetWithNotNull()
: lattice;
}
// If it is a final or effectively-final class type, then we know the lower bound.
- if (getTypeLattice().isClassType()) {
- ClassTypeLatticeElement classType = getTypeLattice().asClassTypeLatticeElement();
+ if (getType().isClassType()) {
+ ClassTypeElement classType = getType().asClassType();
DexType type = classType.getClassType();
DexClass clazz = appView.definitionFor(type);
if (clazz != null && clazz.isEffectivelyFinal(appView)) {
diff --git a/src/main/java/com/android/tools/r8/ir/code/ValueType.java b/src/main/java/com/android/tools/r8/ir/code/ValueType.java
index 865c7d4..729cdcf 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ValueType.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ValueType.java
@@ -7,8 +7,8 @@
import com.android.tools.r8.errors.InternalCompilerError;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.analysis.type.PrimitiveTypeLatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.PrimitiveTypeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
public enum ValueType {
OBJECT,
@@ -102,35 +102,35 @@
}
}
- public static ValueType fromTypeLattice(TypeLatticeElement typeLatticeElement) {
- if (typeLatticeElement.isReference()) {
+ public static ValueType fromType(TypeElement type) {
+ if (type.isReferenceType()) {
return OBJECT;
}
- if (typeLatticeElement.isInt()) {
+ if (type.isInt()) {
return INT;
}
- if (typeLatticeElement.isFloat()) {
+ if (type.isFloat()) {
return FLOAT;
}
- if (typeLatticeElement.isLong()) {
+ if (type.isLong()) {
return LONG;
}
- if (typeLatticeElement.isDouble()) {
+ if (type.isDouble()) {
return DOUBLE;
}
- throw new Unreachable("Unexpected conversion of imprecise type: " + typeLatticeElement);
+ throw new Unreachable("Unexpected conversion of imprecise type: " + type);
}
- public PrimitiveTypeLatticeElement toPrimitiveTypeLattice() {
+ public PrimitiveTypeElement toPrimitiveType() {
switch (this) {
case INT:
- return TypeLatticeElement.getInt();
+ return TypeElement.getInt();
case FLOAT:
- return TypeLatticeElement.getFloat();
+ return TypeElement.getFloat();
case LONG:
- return TypeLatticeElement.getLong();
+ return TypeElement.getLong();
case DOUBLE:
- return TypeLatticeElement.getDouble();
+ return TypeElement.getDouble();
default:
throw new Unreachable("Unexpected type in conversion to primitive: " + this);
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/ValueTypeConstraint.java b/src/main/java/com/android/tools/r8/ir/code/ValueTypeConstraint.java
index 1f7f97b..13cd1ed 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ValueTypeConstraint.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ValueTypeConstraint.java
@@ -7,8 +7,8 @@
import com.android.tools.r8.errors.InternalCompilerError;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.analysis.type.PrimitiveTypeLatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.PrimitiveTypeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
public enum ValueTypeConstraint {
OBJECT,
@@ -129,44 +129,44 @@
}
}
- public static ValueTypeConstraint fromTypeLattice(TypeLatticeElement typeLatticeElement) {
- if (typeLatticeElement.isReference()) {
+ public static ValueTypeConstraint fromTypeLattice(TypeElement typeElement) {
+ if (typeElement.isReferenceType()) {
return OBJECT;
}
- if (typeLatticeElement.isFineGrainedType() || typeLatticeElement.isInt()) {
+ if (typeElement.isFineGrainedType() || typeElement.isInt()) {
return INT;
}
- if (typeLatticeElement.isFloat()) {
+ if (typeElement.isFloat()) {
return FLOAT;
}
- if (typeLatticeElement.isLong()) {
+ if (typeElement.isLong()) {
return LONG;
}
- if (typeLatticeElement.isDouble()) {
+ if (typeElement.isDouble()) {
return DOUBLE;
}
- if (typeLatticeElement.isSinglePrimitive()) {
+ if (typeElement.isSinglePrimitive()) {
return INT_OR_FLOAT;
}
- if (typeLatticeElement.isWidePrimitive()) {
+ if (typeElement.isWidePrimitive()) {
return LONG_OR_DOUBLE;
}
- if (typeLatticeElement.isTop()) {
+ if (typeElement.isTop()) {
return INT_OR_FLOAT_OR_OBJECT;
}
- throw new Unreachable("Unexpected conversion of type: " + typeLatticeElement);
+ throw new Unreachable("Unexpected conversion of type: " + typeElement);
}
- public PrimitiveTypeLatticeElement toPrimitiveTypeLattice() {
+ public PrimitiveTypeElement toPrimitiveType() {
switch (this) {
case INT:
- return TypeLatticeElement.getInt();
+ return TypeElement.getInt();
case FLOAT:
- return TypeLatticeElement.getFloat();
+ return TypeElement.getFloat();
case LONG:
- return TypeLatticeElement.getLong();
+ return TypeElement.getLong();
case DOUBLE:
- return TypeLatticeElement.getDouble();
+ return TypeElement.getDouble();
default:
throw new Unreachable("Unexpected type in conversion to primitive: " + this);
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
index a16d39d..ae3e7cd 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
@@ -27,7 +27,7 @@
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.Argument;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.CatchHandlers;
@@ -234,7 +234,7 @@
// Insert ConstNumber(v, -1) before Not.
it.previous();
- Value constValue = code.createValue(inValue.getTypeLattice());
+ Value constValue = code.createValue(inValue.getType());
Instruction newInstruction = new ConstNumber(constValue, -1);
newInstruction.setBlock(block);
newInstruction.setPosition(current.getPosition());
@@ -386,7 +386,7 @@
|| constNumber == null
|| add == null
|| store == null
- || constNumber.outValue().getTypeLattice() != TypeLatticeElement.getInt()) {
+ || constNumber.outValue().getType() != TypeElement.getInt()) {
it.next();
continue;
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java
index 8af9977..a4ca85a 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java
@@ -42,7 +42,7 @@
import com.android.tools.r8.graph.DexCode.TryHandler.TypeAddrPair;
import com.android.tools.r8.graph.DexDebugEventBuilder;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.Argument;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.CatchHandlers;
@@ -1404,7 +1404,7 @@
@Override
public void addInstructions(DexBuilder builder, List<Instruction> instructions) {
Move move = getMove();
- TypeLatticeElement moveType = move.outValue().getTypeLattice();
+ TypeElement moveType = move.outValue().getType();
int src = srcRegister(builder);
int dest = destRegister(builder);
Instruction instruction;
@@ -1418,7 +1418,7 @@
instruction = new com.android.tools.r8.code.Move(dest, src);
} else if (moveType.isWidePrimitive()) {
instruction = new MoveWide(dest, src);
- } else if (moveType.isReference()) {
+ } else if (moveType.isReferenceType()) {
instruction = new MoveObject(dest, src);
} else {
throw new Unreachable("Unexpected type: " + move.outType());
@@ -1429,7 +1429,7 @@
instruction = new MoveFrom16(dest, src);
} else if (moveType.isWidePrimitive()) {
instruction = new MoveWideFrom16(dest, src);
- } else if (moveType.isReference()) {
+ } else if (moveType.isReferenceType()) {
instruction = new MoveObjectFrom16(dest, src);
} else {
throw new Unreachable("Unexpected type: " + move.outType());
@@ -1440,7 +1440,7 @@
instruction = new Move16(dest, src);
} else if (moveType.isWidePrimitive()) {
instruction = new MoveWide16(dest, src);
- } else if (moveType.isReference()) {
+ } else if (moveType.isReferenceType()) {
instruction = new MoveObject16(dest, src);
} else {
throw new Unreachable("Unexpected type: " + move.outType());
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/FieldOptimizationFeedback.java b/src/main/java/com/android/tools/r8/ir/conversion/FieldOptimizationFeedback.java
index a6d6267..c6070c5 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/FieldOptimizationFeedback.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/FieldOptimizationFeedback.java
@@ -6,8 +6,8 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedField;
-import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
@@ -19,9 +19,9 @@
void markFieldAsPropagated(DexEncodedField field);
- void markFieldHasDynamicLowerBoundType(DexEncodedField field, ClassTypeLatticeElement type);
+ void markFieldHasDynamicLowerBoundType(DexEncodedField field, ClassTypeElement type);
- void markFieldHasDynamicUpperBoundType(DexEncodedField field, TypeLatticeElement type);
+ void markFieldHasDynamicUpperBoundType(DexEncodedField field, TypeElement type);
void markFieldBitsRead(DexEncodedField field, int bitsRead);
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 e87f619..993a69c 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
@@ -6,14 +6,14 @@
import static com.android.tools.r8.ir.analysis.type.Nullability.definitelyNotNull;
import static com.android.tools.r8.ir.analysis.type.Nullability.maybeNull;
-import static com.android.tools.r8.ir.analysis.type.TypeLatticeElement.getBottom;
-import static com.android.tools.r8.ir.analysis.type.TypeLatticeElement.getDouble;
-import static com.android.tools.r8.ir.analysis.type.TypeLatticeElement.getFloat;
-import static com.android.tools.r8.ir.analysis.type.TypeLatticeElement.getInt;
-import static com.android.tools.r8.ir.analysis.type.TypeLatticeElement.getLong;
-import static com.android.tools.r8.ir.analysis.type.TypeLatticeElement.getNull;
-import static com.android.tools.r8.ir.analysis.type.TypeLatticeElement.getSingle;
-import static com.android.tools.r8.ir.analysis.type.TypeLatticeElement.getWide;
+import static com.android.tools.r8.ir.analysis.type.TypeElement.getBottom;
+import static com.android.tools.r8.ir.analysis.type.TypeElement.getDouble;
+import static com.android.tools.r8.ir.analysis.type.TypeElement.getFloat;
+import static com.android.tools.r8.ir.analysis.type.TypeElement.getInt;
+import static com.android.tools.r8.ir.analysis.type.TypeElement.getLong;
+import static com.android.tools.r8.ir.analysis.type.TypeElement.getNull;
+import static com.android.tools.r8.ir.analysis.type.TypeElement.getSingle;
+import static com.android.tools.r8.ir.analysis.type.TypeElement.getWide;
import com.android.tools.r8.ApiLevelException;
import com.android.tools.r8.errors.CompilationError;
@@ -39,9 +39,9 @@
import com.android.tools.r8.graph.RewrittenPrototypeDescription.RemovedArgumentInfo;
import com.android.tools.r8.graph.RewrittenPrototypeDescription.RewrittenTypeInfo;
import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.PrimitiveTypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.PrimitiveTypeElement;
import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.Add;
import com.android.tools.r8.ir.code.And;
import com.android.tools.r8.ir.code.Argument;
@@ -151,7 +151,7 @@
public static final int INITIAL_BLOCK_OFFSET = -1;
- private static TypeLatticeElement fromMemberType(MemberType type) {
+ private static TypeElement fromMemberType(MemberType type) {
switch (type) {
case BOOLEAN_OR_BYTE:
case CHAR:
@@ -176,8 +176,8 @@
}
}
- public TypeLatticeElement getTypeLattice(DexType type, Nullability nullability) {
- return TypeLatticeElement.fromDexType(type, nullability, appView);
+ public TypeElement getTypeLattice(DexType type, Nullability nullability) {
+ return TypeElement.fromDexType(type, nullability, appView);
}
// SSA construction uses a worklist of basic blocks reachable from the entry and their
@@ -543,13 +543,13 @@
int usedArgumentIndex = 0;
while (argumentIndex < numberOfArguments) {
- TypeLatticeElement type;
+ TypeElement type;
ArgumentInfo argumentInfo = argumentsInfo.getArgumentInfo(argumentIndex);
if (argumentInfo.isRemovedArgumentInfo()) {
RemovedArgumentInfo removedArgumentInfo = argumentInfo.asRemovedArgumentInfo();
writeCallback.accept(register, removedArgumentInfo.getType());
type =
- TypeLatticeElement.fromDexType(
+ TypeElement.fromDexType(
removedArgumentInfo.getType(), Nullability.maybeNull(), appView);
addConstantOrUnusedArgument(register, removedArgumentInfo);
} else {
@@ -567,7 +567,7 @@
}
usedArgumentIndex++;
writeCallback.accept(register, argType);
- type = TypeLatticeElement.fromDexType(argType, Nullability.maybeNull(), appView);
+ type = TypeElement.fromDexType(argType, Nullability.maybeNull(), appView);
if (argType.isBooleanType()) {
addBooleanNonThisArgument(register);
} else {
@@ -882,8 +882,8 @@
int moveExceptionDest = source.getMoveExceptionRegister(targetIndex);
Position position = source.getCanonicalDebugPositionAtOffset(moveExceptionItem.targetOffset);
if (moveExceptionDest >= 0) {
- TypeLatticeElement typeLattice =
- TypeLatticeElement.fromDexType(moveExceptionItem.guard, definitelyNotNull(), appView);
+ TypeElement typeLattice =
+ TypeElement.fromDexType(moveExceptionItem.guard, definitelyNotNull(), appView);
Value out = writeRegister(moveExceptionDest, typeLattice, ThrowingInfo.NO_THROW, null);
MoveException moveException =
new MoveException(out, moveExceptionItem.guard, appView.options());
@@ -932,12 +932,11 @@
void addThisArgument(int register) {
boolean receiverCouldBeNull = context != null && context != method;
Nullability nullability = receiverCouldBeNull ? maybeNull() : definitelyNotNull();
- TypeLatticeElement receiverType =
- TypeLatticeElement.fromDexType(method.method.holder, nullability, appView);
+ TypeElement receiverType = TypeElement.fromDexType(method.method.holder, nullability, appView);
addThisArgument(register, receiverType);
}
- public void addThisArgument(int register, TypeLatticeElement receiverType) {
+ public void addThisArgument(int register, TypeElement receiverType) {
DebugLocalInfo local = getOutgoingLocal(register);
Value value = writeRegister(register, receiverType, ThrowingInfo.NO_THROW, local);
addInstruction(new Argument(value, currentBlock.size(), false));
@@ -945,7 +944,7 @@
value.markAsThis();
}
- public void addNonThisArgument(int register, TypeLatticeElement typeLattice) {
+ public void addNonThisArgument(int register, TypeElement typeLattice) {
DebugLocalInfo local = getOutgoingLocal(register);
Value value = writeRegister(register, typeLattice, ThrowingInfo.NO_THROW, local);
addNonThisArgument(new Argument(value, currentBlock.size(), false));
@@ -1010,8 +1009,7 @@
// Note that the write register must not lookup outgoing local information and the local is
// never considered clobbered by a start (if the in value has local info it must have been
// marked ended elsewhere).
- Value out = writeRegister(
- register, incomingValue.getTypeLattice(), ThrowingInfo.NO_THROW, local);
+ Value out = writeRegister(register, incomingValue.getType(), ThrowingInfo.NO_THROW, local);
DebugLocalWrite write = new DebugLocalWrite(out, incomingValue);
addInstruction(write);
}
@@ -1092,7 +1090,7 @@
public void addArrayGet(MemberType type, int dest, int array, int index) {
Value in1 = readRegister(array, ValueTypeConstraint.OBJECT);
Value in2 = readRegister(index, ValueTypeConstraint.INT);
- TypeLatticeElement typeLattice = fromMemberType(type);
+ TypeElement typeLattice = fromMemberType(type);
Value out = writeRegister(dest, typeLattice, ThrowingInfo.CAN_THROW);
ArrayGet instruction = new ArrayGet(type, out, in1, in2);
assert instruction.instructionTypeCanThrow();
@@ -1123,8 +1121,8 @@
public void addCheckCast(int value, DexType type) {
Value in = readRegister(value, ValueTypeConstraint.OBJECT);
- TypeLatticeElement castTypeLattice =
- TypeLatticeElement.fromDexType(type, in.getTypeLattice().nullability(), appView);
+ TypeElement castTypeLattice =
+ TypeElement.fromDexType(type, in.getType().nullability(), appView);
Value out = writeRegister(value, castTypeLattice, ThrowingInfo.CAN_THROW);
CheckCast instruction = new CheckCast(out, in, type);
assert instruction.instructionTypeCanThrow();
@@ -1140,7 +1138,7 @@
add(instruction);
}
- public void addConst(TypeLatticeElement typeLattice, int dest, long value) {
+ public void addConst(TypeElement typeLattice, int dest, long value) {
Value out = writeRegister(dest, typeLattice, ThrowingInfo.NO_THROW);
ConstNumber instruction = new ConstNumber(out, value);
assert !instruction.instructionTypeCanThrow();
@@ -1168,8 +1166,7 @@
}
public void addConstClass(int dest, DexType type) {
- TypeLatticeElement typeLattice =
- TypeLatticeElement.classClassType(appView, definitelyNotNull());
+ TypeElement typeLattice = TypeElement.classClassType(appView, definitelyNotNull());
Value out = writeRegister(dest, typeLattice, ThrowingInfo.CAN_THROW);
ConstClass instruction = new ConstClass(out, type);
assert instruction.instructionTypeCanThrow();
@@ -1183,8 +1180,8 @@
"Const-method-handle",
null /* sourceString */);
}
- TypeLatticeElement typeLattice =
- TypeLatticeElement.fromDexType(
+ TypeElement typeLattice =
+ TypeElement.fromDexType(
appView.dexItemFactory().methodHandleType, definitelyNotNull(), appView);
Value out = writeRegister(dest, typeLattice, ThrowingInfo.CAN_THROW);
ConstMethodHandle instruction = new ConstMethodHandle(out, methodHandle);
@@ -1198,8 +1195,8 @@
"Const-method-type",
null /* sourceString */);
}
- TypeLatticeElement typeLattice =
- TypeLatticeElement.fromDexType(
+ TypeElement typeLattice =
+ TypeElement.fromDexType(
appView.dexItemFactory().methodTypeType, definitelyNotNull(), appView);
Value out = writeRegister(dest, typeLattice, ThrowingInfo.CAN_THROW);
ConstMethodType instruction = new ConstMethodType(out, methodType);
@@ -1213,16 +1210,14 @@
}
public void addConstString(int dest, DexString string) {
- TypeLatticeElement typeLattice =
- TypeLatticeElement.stringClassType(appView, definitelyNotNull());
+ TypeElement typeLattice = TypeElement.stringClassType(appView, definitelyNotNull());
ThrowingInfo throwingInfo = throwingInfoForConstStrings();
add(new ConstString(writeRegister(dest, typeLattice, throwingInfo), string, throwingInfo));
}
public void addDexItemBasedConstString(
int dest, DexReference item, NameComputationInfo<?> nameComputationInfo) {
- TypeLatticeElement typeLattice =
- TypeLatticeElement.stringClassType(appView, definitelyNotNull());
+ TypeElement typeLattice = TypeElement.stringClassType(appView, definitelyNotNull());
ThrowingInfo throwingInfo = throwingInfoForConstStrings();
Value out = writeRegister(dest, typeLattice, throwingInfo);
add(new DexItemBasedConstString(out, item, nameComputationInfo, throwingInfo));
@@ -1268,7 +1263,7 @@
// If the move is writing to a different local we must construct a new value.
DebugLocalInfo destLocal = getOutgoingLocal(dest);
if (destLocal != null && destLocal != in.getLocalInfo()) {
- Value out = writeRegister(dest, in.getTypeLattice(), ThrowingInfo.NO_THROW);
+ Value out = writeRegister(dest, in.getType(), ThrowingInfo.NO_THROW);
addInstruction(new DebugLocalWrite(out, in));
return;
}
@@ -1423,7 +1418,7 @@
Value out =
writeRegister(
dest,
- TypeLatticeElement.fromDexType(field.type, maybeNull(), appView),
+ TypeElement.fromDexType(field.type, maybeNull(), appView),
ThrowingInfo.CAN_THROW);
InstanceGet instruction = new InstanceGet(out, in, field);
assert instruction.instructionTypeCanThrow();
@@ -1712,11 +1707,11 @@
: maybeNull();
// InvokeCustom.evaluate will look into the metadata of the callsite which will provide more
// information than just looking at the type.
- TypeLatticeElement typeLatticeElement =
+ TypeElement typeElement =
invoke.isInvokeCustom()
? invoke.evaluate(appView)
- : TypeLatticeElement.fromDexType(outType, nullability, appView);
- Value outValue = writeRegister(dest, typeLatticeElement, ThrowingInfo.CAN_THROW);
+ : TypeElement.fromDexType(outType, nullability, appView);
+ Value outValue = writeRegister(dest, typeElement, ThrowingInfo.CAN_THROW);
invoke.setOutValue(outValue);
}
@@ -1745,8 +1740,7 @@
public void addNewArrayEmpty(int dest, int size, DexType type) {
assert type.isArrayType();
Value in = readRegister(size, ValueTypeConstraint.INT);
- TypeLatticeElement arrayTypeLattice =
- TypeLatticeElement.fromDexType(type, definitelyNotNull(), appView);
+ TypeElement arrayTypeLattice = TypeElement.fromDexType(type, definitelyNotNull(), appView);
Value out = writeRegister(dest, arrayTypeLattice, ThrowingInfo.CAN_THROW);
NewArrayEmpty instruction = new NewArrayEmpty(out, in, type);
assert instruction.instructionTypeCanThrow();
@@ -1762,8 +1756,7 @@
}
public void addNewInstance(int dest, DexType type) {
- TypeLatticeElement instanceType =
- TypeLatticeElement.fromDexType(type, definitelyNotNull(), appView);
+ TypeElement instanceType = TypeElement.fromDexType(type, definitelyNotNull(), appView);
Value out = writeRegister(dest, instanceType, ThrowingInfo.CAN_THROW);
NewInstance instruction = new NewInstance(type, out);
assert instruction.instructionTypeCanThrow();
@@ -1797,7 +1790,7 @@
}
public void addInitClass(int dest, DexType clazz) {
- Value out = writeRegister(dest, TypeLatticeElement.getInt(), ThrowingInfo.CAN_THROW);
+ Value out = writeRegister(dest, TypeElement.getInt(), ThrowingInfo.CAN_THROW);
InitClass instruction = new InitClass(out, clazz);
assert instruction.instructionTypeCanThrow();
addInstruction(instruction);
@@ -1807,7 +1800,7 @@
Value out =
writeRegister(
dest,
- TypeLatticeElement.fromDexType(field.type, maybeNull(), appView),
+ TypeElement.fromDexType(field.type, maybeNull(), appView),
ThrowingInfo.CAN_THROW);
StaticGet instruction = new StaticGet(out, field);
assert instruction.instructionTypeCanThrow();
@@ -2142,7 +2135,7 @@
value = getUninitializedDebugLocalValue(register, constraint);
} else {
DebugLocalInfo local = getIncomingLocalAtBlock(register, block);
- TypeLatticeElement phiType = TypeConstraintResolver.typeForConstraint(constraint);
+ TypeElement phiType = TypeConstraintResolver.typeForConstraint(constraint);
hasImpreciseValues |= !phiType.isPreciseType();
Phi phi = new Phi(valueNumberGenerator.next(), block, phiType, local, readType);
if (!block.isSealed()) {
@@ -2181,15 +2174,14 @@
private Value getUninitializedDebugLocalValue(int register, ValueTypeConstraint typeConstraint) {
// A debug initiated value must have a precise type constraint.
assert typeConstraint.isPrecise();
- TypeLatticeElement type =
- typeConstraint.isObject() ? getNull() : typeConstraint.toPrimitiveTypeLattice();
+ TypeElement type = typeConstraint.isObject() ? getNull() : typeConstraint.toPrimitiveType();
if (uninitializedDebugLocalValues == null) {
uninitializedDebugLocalValues = new Int2ReferenceOpenHashMap<>();
}
List<Value> values = uninitializedDebugLocalValues.get(register);
if (values != null) {
for (Value value : values) {
- if (value.getTypeLattice() == type) {
+ if (value.getType() == type) {
return value;
}
}
@@ -2235,14 +2227,14 @@
// This special write register is needed when changing the scoping of a local variable.
// See addDebugLocalStart and addDebugLocalEnd.
private Value writeRegister(
- int register, TypeLatticeElement typeLattice, ThrowingInfo throwing, DebugLocalInfo local) {
+ int register, TypeElement typeLattice, ThrowingInfo throwing, DebugLocalInfo local) {
checkRegister(register);
Value value = new Value(valueNumberGenerator.next(), typeLattice, local);
currentBlock.writeCurrentDefinition(register, value, throwing);
return value;
}
- public Value writeRegister(int register, TypeLatticeElement typeLattice, ThrowingInfo throwing) {
+ public Value writeRegister(int register, TypeElement typeLattice, ThrowingInfo throwing) {
DebugLocalInfo incomingLocal = getIncomingLocal(register);
DebugLocalInfo outgoingLocal = getOutgoingLocal(register);
// If the local info does not change at the current instruction, we need to ensure
@@ -2261,7 +2253,7 @@
}
public Value writeNumericRegister(int register, NumericType type, ThrowingInfo throwing) {
- return writeRegister(register, PrimitiveTypeLatticeElement.fromNumericType(type), throwing);
+ return writeRegister(register, PrimitiveTypeElement.fromNumericType(type), throwing);
}
private DebugLocalInfo getIncomingLocal(int register) {
@@ -2340,7 +2332,7 @@
private void addInstruction(Instruction ir, Position position) {
assert verifyOutValueType(ir);
- hasImpreciseValues |= ir.outValue() != null && !ir.outValue().getTypeLattice().isPreciseType();
+ hasImpreciseValues |= ir.outValue() != null && !ir.outValue().getType().isPreciseType();
ir.setPosition(position);
attachLocalValues(ir);
currentBlock.add(ir, metadata);
@@ -2373,11 +2365,11 @@
private boolean verifyOutValueType(Instruction ir) {
assert ir.outValue() == null
|| ir.isArrayGet()
- || ir.evaluate(appView) == ir.outValue().getTypeLattice();
+ || ir.evaluate(appView) == ir.outValue().getType();
assert ir.outValue() == null
|| !ir.isArrayGet()
- || ir.evaluate(appView) == ir.outValue().getTypeLattice()
- || (ir.outValue().getTypeLattice().isBottom() && ir.evaluate(appView).isReference());
+ || ir.evaluate(appView) == ir.outValue().getType()
+ || (ir.outValue().getType().isBottom() && ir.evaluate(appView).isReferenceType());
return true;
}
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 d968d31..cae0c84 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
@@ -30,7 +30,7 @@
import com.android.tools.r8.ir.analysis.fieldaccess.TrivialFieldAccessReprocessor;
import com.android.tools.r8.ir.analysis.fieldvalueanalysis.InstanceFieldValueAnalysis;
import com.android.tools.r8.ir.analysis.fieldvalueanalysis.StaticFieldValueAnalysis;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.AlwaysMaterializingDefinition;
import com.android.tools.r8.ir.code.AlwaysMaterializingUser;
import com.android.tools.r8.ir.code.BasicBlock;
@@ -45,6 +45,7 @@
import com.android.tools.r8.ir.desugar.D8NestBasedAccessDesugaring;
import com.android.tools.r8.ir.desugar.DesugaredLibraryAPIConverter;
import com.android.tools.r8.ir.desugar.DesugaredLibraryAPIConverter.Mode;
+import com.android.tools.r8.ir.desugar.DesugaredLibraryRetargeter;
import com.android.tools.r8.ir.desugar.InterfaceMethodRewriter;
import com.android.tools.r8.ir.desugar.InterfaceMethodRewriter.Flavor;
import com.android.tools.r8.ir.desugar.LambdaRewriter;
@@ -143,6 +144,7 @@
private final InterfaceMethodRewriter interfaceMethodRewriter;
private final TwrCloseResourceRewriter twrCloseResourceRewriter;
private final BackportedMethodRewriter backportedMethodRewriter;
+ private final DesugaredLibraryRetargeter desugaredLibraryRetargeter;
private final LambdaMerger lambdaMerger;
private final ClassInliner classInliner;
private final ClassStaticizer classStaticizer;
@@ -217,13 +219,16 @@
.collect(Collectors.toList());
if (options.isDesugaredLibraryCompilation()) {
// Specific L8 Settings.
- // BackportedMethodRewriter is needed for retarget core library members and backports.
+ // DesugaredLibraryRetargeter is needed for retarget core library members and backports.
// InterfaceMethodRewriter is needed for emulated interfaces.
// LambdaRewriter is needed because if it is missing there are invoke custom on
// default/static interface methods, and this is not supported by the compiler.
// DesugaredLibraryAPIConverter is here to duplicate APIs.
// The rest is nulled out. In addition the rewriting logic fails without lambda rewriting.
- this.backportedMethodRewriter = new BackportedMethodRewriter(appView, this);
+ this.desugaredLibraryRetargeter =
+ options.desugaredLibraryConfiguration.getRetargetCoreLibMember().isEmpty()
+ ? null
+ : new DesugaredLibraryRetargeter(appView);
this.interfaceMethodRewriter =
options.desugaredLibraryConfiguration.getEmulateLibraryInterface().isEmpty()
? null
@@ -231,6 +236,10 @@
this.lambdaRewriter = new LambdaRewriter(appView);
this.desugaredLibraryAPIConverter =
new DesugaredLibraryAPIConverter(appView, Mode.GENERATE_CALLBACKS_AND_WRAPPERS);
+ this.backportedMethodRewriter =
+ options.testing.forceLibBackportsInL8CfToCf
+ ? new BackportedMethodRewriter(appView, this)
+ : null;
this.twrCloseResourceRewriter = null;
this.lambdaMerger = null;
this.covariantReturnTypeAnnotationTransformer = null;
@@ -268,6 +277,10 @@
? new TwrCloseResourceRewriter(appView, this)
: null;
this.backportedMethodRewriter = new BackportedMethodRewriter(appView, this);
+ this.desugaredLibraryRetargeter =
+ options.desugaredLibraryConfiguration.getRetargetCoreLibMember().isEmpty()
+ ? null
+ : new DesugaredLibraryRetargeter(appView);
this.covariantReturnTypeAnnotationTransformer =
options.processCovariantReturnTypeAnnotations
? new CovariantReturnTypeAnnotationTransformer(this, appView.dexItemFactory())
@@ -450,7 +463,16 @@
private void synthesizeJava8UtilityClass(
Builder<?> builder, ExecutorService executorService) throws ExecutionException {
- backportedMethodRewriter.synthesizeUtilityClasses(builder, executorService);
+ if (backportedMethodRewriter != null) {
+ backportedMethodRewriter.synthesizeUtilityClasses(builder, executorService);
+ }
+ }
+
+ private void synthesizeRetargetClass(Builder<?> builder, ExecutorService executorService)
+ throws ExecutionException {
+ if (desugaredLibraryRetargeter != null) {
+ desugaredLibraryRetargeter.synthesizeRetargetClasses(builder, executorService, this);
+ }
}
private void synthesizeEnumUnboxingUtilityClass(
@@ -482,6 +504,8 @@
desugarInterfaceMethods(builder, ExcludeDexResources, executor);
synthesizeTwrCloseResourceUtilityClass(builder, executor);
synthesizeJava8UtilityClass(builder, executor);
+ synthesizeRetargetClass(builder, executor);
+
processCovariantReturnTypeAnnotations(builder);
generateDesugaredLibraryAPIWrappers(builder, executor);
@@ -747,6 +771,7 @@
printPhase("Utility classes synthesis");
synthesizeTwrCloseResourceUtilityClass(builder, executorService);
synthesizeJava8UtilityClass(builder, executorService);
+ synthesizeRetargetClass(builder, executorService);
handleSynthesizedClassMapping(builder);
synthesizeEnumUnboxingUtilityClass(builder, executorService);
@@ -974,12 +999,7 @@
private DexType computeOutlineClassType() {
DexType result;
int count = 0;
- String tempPrefix =
- appView
- .options()
- .desugaredLibraryConfiguration
- .getSynthesizedLibraryClassesPackagePrefix(appView);
- String prefix = tempPrefix.replace('/', '.');
+ String prefix = appView.options().synthesizedClassPrefix.replace('/', '.');
do {
String name =
prefix + OutlineOptions.CLASS_NAME + (count == 0 ? "" : Integer.toString(count));
@@ -1375,9 +1395,20 @@
codeRewriter.rewriteThrowableAddAndGetSuppressed(code);
timing.end();
}
- timing.begin("Rewrite backport methods");
- backportedMethodRewriter.desugar(code);
- timing.end();
+
+ if (desugaredLibraryRetargeter != null) {
+ // The desugaredLibraryRetargeter should run before backportedMethodRewriter to be able to
+ // perform backport rewriting before the methods can be retargeted.
+ timing.begin("Retarget library methods");
+ desugaredLibraryRetargeter.desugar(code);
+ timing.end();
+ }
+
+ if (backportedMethodRewriter != null) {
+ timing.begin("Rewrite backport methods");
+ backportedMethodRewriter.desugar(code);
+ timing.end();
+ }
timing.begin("Desugar string concat");
stringConcatRewriter.desugarStringConcats(method.method, code);
@@ -1599,15 +1630,20 @@
if (method.isInitializer()) {
if (method.isClassInitializer()) {
StaticFieldValueAnalysis.run(
- appView, code, classInitializerDefaultsResult, feedback, code.method);
+ appView, code, classInitializerDefaultsResult, feedback, code.method, timing);
} else {
instanceFieldInitializationInfos =
InstanceFieldValueAnalysis.run(
- appView, code, classInitializerDefaultsResult, feedback, code.method);
+ appView, code, classInitializerDefaultsResult, feedback, code.method, timing);
}
}
methodOptimizationInfoCollector.collectMethodOptimizationInfo(
- code.method, code, feedback, dynamicTypeOptimization, instanceFieldInitializationInfos);
+ code.method,
+ code,
+ feedback,
+ dynamicTypeOptimization,
+ instanceFieldInitializationInfos,
+ timing);
}
public void removeDeadCodeAndFinalizeIR(
@@ -1884,7 +1920,7 @@
Instruction check = it.previous();
assert addBefore == check;
// Forced definition of const-zero
- Value fixitValue = code.createValue(TypeLatticeElement.getInt());
+ Value fixitValue = code.createValue(TypeElement.getInt());
Instruction fixitDefinition = new AlwaysMaterializingDefinition(fixitValue);
fixitDefinition.setBlock(addBefore.getBlock());
fixitDefinition.setPosition(addBefore.getPosition());
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 06c4bdf..bb541cf 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
@@ -34,7 +34,7 @@
import com.android.tools.r8.graph.UseRegistry.MethodHandleUse;
import com.android.tools.r8.graph.classmerging.VerticallyMergedClasses;
import com.android.tools.r8.ir.analysis.type.DestructivePhiTypeUpdater;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.CatchHandlers;
import com.android.tools.r8.ir.code.CheckCast;
@@ -86,8 +86,8 @@
private Value makeOutValue(Instruction insn, IRCode code) {
if (insn.outValue() != null) {
- TypeLatticeElement oldType = insn.outValue().getTypeLattice();
- TypeLatticeElement newType =
+ TypeElement oldType = insn.outValue().getType();
+ TypeElement newType =
oldType.fixupClassTypeReferences(appView.graphLense()::lookupType, appView);
return code.createValue(newType, insn.getLocalInfo());
}
@@ -123,8 +123,7 @@
InvokeCustom newInvokeCustom =
new InvokeCustom(newCallSite, newOutValue, invokeCustom.inValues());
iterator.replaceCurrentInstruction(newInvokeCustom);
- if (newOutValue != null
- && newOutValue.getTypeLattice() != invokeCustom.outValue().getTypeLattice()) {
+ if (newOutValue != null && newOutValue.getType() != invokeCustom.outValue().getType()) {
affectedPhis.addAll(newOutValue.uniquePhiUsers());
}
}
@@ -135,8 +134,7 @@
if (newHandle != handle) {
Value newOutValue = makeOutValue(current, code);
iterator.replaceCurrentInstruction(new ConstMethodHandle(newOutValue, newHandle));
- if (newOutValue != null
- && newOutValue.getTypeLattice() != current.outValue().getTypeLattice()) {
+ if (newOutValue != null && newOutValue.getType() != current.outValue().getType()) {
affectedPhis.addAll(newOutValue.uniquePhiUsers());
}
}
@@ -250,8 +248,7 @@
Invoke newInvoke =
Invoke.create(actualInvokeType, actualTarget, null, newOutValue, newInValues);
iterator.replaceCurrentInstruction(newInvoke);
- if (newOutValue != null
- && newOutValue.getTypeLattice() != current.outValue().getTypeLattice()) {
+ if (newOutValue != null && newOutValue.getType() != current.outValue().getType()) {
affectedPhis.addAll(newOutValue.uniquePhiUsers());
}
@@ -287,16 +284,14 @@
Value newOutValue = makeOutValue(current, code);
iterator.replaceCurrentInstruction(
new InvokeStatic(replacementMethod, newOutValue, current.inValues()));
- if (newOutValue != null
- && newOutValue.getTypeLattice() != current.outValue().getTypeLattice()) {
+ if (newOutValue != null && newOutValue.getType() != current.outValue().getType()) {
affectedPhis.addAll(current.outValue().uniquePhiUsers());
}
} else if (actualField != field) {
Value newOutValue = makeOutValue(instanceGet, code);
iterator.replaceCurrentInstruction(
new InstanceGet(newOutValue, instanceGet.object(), actualField));
- if (newOutValue != null
- && newOutValue.getTypeLattice() != current.outValue().getTypeLattice()) {
+ if (newOutValue != null && newOutValue.getType() != current.outValue().getType()) {
affectedPhis.addAll(newOutValue.uniquePhiUsers());
}
}
@@ -328,15 +323,13 @@
Value newOutValue = makeOutValue(current, code);
iterator.replaceCurrentInstruction(
new InvokeStatic(replacementMethod, newOutValue, current.inValues()));
- if (newOutValue != null
- && newOutValue.getTypeLattice() != current.outValue().getTypeLattice()) {
+ if (newOutValue != null && newOutValue.getType() != current.outValue().getType()) {
affectedPhis.addAll(newOutValue.uniquePhiUsers());
}
} else if (actualField != field) {
Value newOutValue = makeOutValue(staticGet, code);
iterator.replaceCurrentInstruction(new StaticGet(newOutValue, actualField));
- if (newOutValue != null
- && newOutValue.getTypeLattice() != current.outValue().getTypeLattice()) {
+ if (newOutValue != null && newOutValue.getType() != current.outValue().getType()) {
affectedPhis.addAll(newOutValue.uniquePhiUsers());
}
}
@@ -399,11 +392,11 @@
.replaceInstructionIfTypeChanged(type, NewInstance::new);
} else if (current.outValue() != null) {
// For all other instructions, substitute any changed type.
- TypeLatticeElement typeLattice = current.outValue().getTypeLattice();
- TypeLatticeElement substituted =
+ TypeElement typeLattice = current.outValue().getType();
+ TypeElement substituted =
typeLattice.fixupClassTypeReferences(graphLense::lookupType, appView);
if (substituted != typeLattice) {
- current.outValue().setTypeLattice(substituted);
+ current.outValue().setType(substituted);
affectedPhis.addAll(current.outValue().uniquePhiUsers());
}
}
@@ -434,7 +427,7 @@
// TODO(b/150188380): Add API to insert a const instruction with a type lattice.
Value rewrittenDefaultValue = iterator.insertConstIntInstruction(code, appView.options(), 0);
iterator.next();
- rewrittenDefaultValue.setTypeLattice(defaultValueLatticeElement(newType));
+ rewrittenDefaultValue.setType(defaultValueLatticeElement(newType));
return rewrittenDefaultValue;
}
return initialValue;
@@ -455,11 +448,11 @@
return false;
}
- private TypeLatticeElement defaultValueLatticeElement(DexType type) {
+ private TypeElement defaultValueLatticeElement(DexType type) {
if (type.isPrimitiveType()) {
- return TypeLatticeElement.fromDexType(type, null, appView);
+ return TypeElement.fromDexType(type, null, appView);
}
- return TypeLatticeElement.getNull();
+ return TypeElement.getNull();
}
public DexCallSite rewriteCallSite(DexCallSite callSite, DexEncodedMethod context) {
@@ -568,16 +561,22 @@
for (int i = 0; i < bootstrapArgs.size(); i++) {
DexValue argument = bootstrapArgs.get(i);
DexValue newArgument = null;
- if (argument instanceof DexValueMethodHandle) {
- newArgument = rewriteDexValueMethodHandle(argument.asDexValueMethodHandle(), method, use);
- } else if (argument instanceof DexValueMethodType) {
- newArgument = rewriteDexMethodType(argument.asDexValueMethodType());
- } else if (argument instanceof DexValueType) {
- DexType oldType = ((DexValueType) argument).value;
- DexType newType = appView.graphLense().lookupType(oldType);
- if (newType != oldType) {
- newArgument = new DexValueType(newType);
- }
+ switch (argument.getValueKind()) {
+ case METHOD_HANDLE:
+ newArgument = rewriteDexValueMethodHandle(argument.asDexValueMethodHandle(), method, use);
+ break;
+ case METHOD_TYPE:
+ newArgument = rewriteDexMethodType(argument.asDexValueMethodType());
+ break;
+ case TYPE:
+ DexType oldType = argument.asDexValueType().value;
+ DexType newType = appView.graphLense().lookupType(oldType);
+ if (newType != oldType) {
+ newArgument = new DexValueType(newType);
+ }
+ break;
+ default:
+ // Intentionally empty.
}
if (newArgument != null) {
if (newBootstrapArgs == null) {
@@ -686,7 +685,7 @@
Instruction newInstruction = constructor.apply(newType, newOutValue);
iterator.replaceCurrentInstruction(newInstruction);
if (newOutValue != null) {
- if (newOutValue.getTypeLattice() != current.outValue().getTypeLattice()) {
+ if (newOutValue.getType() != current.outValue().getType()) {
affectedPhis.addAll(newOutValue.uniquePhiUsers());
} else {
assert current.hasInvariantOutType();
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/MethodOptimizationFeedback.java b/src/main/java/com/android/tools/r8/ir/conversion/MethodOptimizationFeedback.java
index ca144f7..8982b5a 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/MethodOptimizationFeedback.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/MethodOptimizationFeedback.java
@@ -7,8 +7,8 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.classinliner.ClassInlinerEligibilityInfo;
@@ -35,9 +35,9 @@
DexEncodedMethod method, AppView<AppInfoWithLiveness> appView, AbstractValue abstractValue);
void methodReturnsObjectWithUpperBoundType(
- DexEncodedMethod method, AppView<?> appView, TypeLatticeElement type);
+ DexEncodedMethod method, AppView<?> appView, TypeElement type);
- void methodReturnsObjectWithLowerBoundType(DexEncodedMethod method, ClassTypeLatticeElement type);
+ void methodReturnsObjectWithLowerBoundType(DexEncodedMethod method, ClassTypeElement type);
void methodMayNotHaveSideEffects(DexEncodedMethod method);
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/StringSwitchRemover.java b/src/main/java/com/android/tools/r8/ir/conversion/StringSwitchRemover.java
index 2e8bf77..b1f53e1 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/StringSwitchRemover.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/StringSwitchRemover.java
@@ -7,10 +7,10 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexString;
-import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.PrimitiveTypeLatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.PrimitiveTypeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.BasicBlock.ThrowingInfo;
import com.android.tools.r8.ir.code.ConstString;
@@ -37,13 +37,13 @@
private final AppView<?> appView;
private final IdentifierNameStringMarker identifierNameStringMarker;
- private final ClassTypeLatticeElement stringType;
+ private final ClassTypeElement stringType;
private final ThrowingInfo throwingInfo;
StringSwitchRemover(AppView<?> appView, IdentifierNameStringMarker identifierNameStringMarker) {
this.appView = appView;
this.identifierNameStringMarker = identifierNameStringMarker;
- this.stringType = TypeLatticeElement.stringClassType(appView, Nullability.definitelyNotNull());
+ this.stringType = TypeElement.stringClassType(appView, Nullability.definitelyNotNull());
this.throwingInfo = ThrowingInfo.defaultForConstString(appView.options());
}
@@ -109,7 +109,7 @@
InvokeVirtual invokeInstruction =
new InvokeVirtual(
appView.dexItemFactory().stringMethods.equals,
- code.createValue(PrimitiveTypeLatticeElement.getInt()),
+ code.createValue(PrimitiveTypeElement.getInt()),
ImmutableList.of(theSwitch.value(), constStringInstruction.outValue()));
invokeInstruction.setPosition(Position.syntheticNone());
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/TypeConstraintResolver.java b/src/main/java/com/android/tools/r8/ir/conversion/TypeConstraintResolver.java
index 7257d49..d7edc8a 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/TypeConstraintResolver.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/TypeConstraintResolver.java
@@ -6,9 +6,9 @@
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.ir.analysis.type.ArrayTypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ArrayTypeElement;
import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.ArrayPut;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.IRCode;
@@ -59,33 +59,33 @@
this.builder = builder;
}
- public static ValueTypeConstraint constraintForType(TypeLatticeElement type) {
+ public static ValueTypeConstraint constraintForType(TypeElement type) {
// During constraint resolution the type bottom denotes references of not-yet-computed types.
return type.isBottom() ? ValueTypeConstraint.OBJECT : ValueTypeConstraint.fromTypeLattice(type);
}
- public static TypeLatticeElement typeForConstraint(ValueTypeConstraint constraint) {
+ public static TypeElement typeForConstraint(ValueTypeConstraint constraint) {
switch (constraint) {
case INT_OR_FLOAT_OR_OBJECT:
- return TypeLatticeElement.getTop();
+ return TypeElement.getTop();
case OBJECT:
// If the constraint is object the concrete lattice type will need to be computed.
// We mark the object type as bottom for now, with the implication that it is of type
// reference but that it should not contribute to the computation of its join
// (in potentially self-referencing phis).
- return TypeLatticeElement.getBottom();
+ return TypeElement.getBottom();
case INT:
- return TypeLatticeElement.getInt();
+ return TypeElement.getInt();
case FLOAT:
- return TypeLatticeElement.getFloat();
+ return TypeElement.getFloat();
case INT_OR_FLOAT:
- return TypeLatticeElement.getSingle();
+ return TypeElement.getSingle();
case LONG:
- return TypeLatticeElement.getLong();
+ return TypeElement.getLong();
case DOUBLE:
- return TypeLatticeElement.getDouble();
+ return TypeElement.getDouble();
case LONG_OR_DOUBLE:
- return TypeLatticeElement.getWide();
+ return TypeElement.getWide();
default:
throw new Unreachable("Unexpected constraint type: " + constraint);
}
@@ -106,7 +106,7 @@
List<Value> impreciseValues = new ArrayList<>();
for (BasicBlock block : code.blocks) {
for (Phi phi : block.getPhis()) {
- if (!phi.getTypeLattice().isPreciseType()) {
+ if (!phi.getType().isPreciseType()) {
impreciseValues.add(phi);
}
for (Value value : phi.getOperands()) {
@@ -114,8 +114,7 @@
}
}
for (Instruction instruction : block.getInstructions()) {
- if (instruction.outValue() != null
- && !instruction.outValue().getTypeLattice().isPreciseType()) {
+ if (instruction.outValue() != null && !instruction.outValue().getType().isPreciseType()) {
impreciseValues.add(instruction.outValue());
}
@@ -151,7 +150,7 @@
"Cannot determine precise type for value: "
+ stillImprecise.get(0)
+ ", its imprecise type is: "
- + stillImprecise.get(0).getTypeLattice(),
+ + stillImprecise.get(0).getType(),
code.origin,
new MethodPosition(code.method.method)));
}
@@ -161,7 +160,7 @@
ArrayList<Value> stillImprecise = new ArrayList<>(impreciseValues.size());
for (Value value : impreciseValues) {
builder.constrainType(value, getCanonicalTypeConstraint(value, finished));
- if (!value.getTypeLattice().isPreciseType()) {
+ if (!value.getType().isPreciseType()) {
stillImprecise.add(value);
}
}
@@ -173,10 +172,10 @@
assert !type.isPrecise();
Value canonical = canonical(value);
ValueTypeConstraint constraint;
- if (array.getTypeLattice().isArrayType()) {
+ if (array.getType().isArrayType()) {
// If the array type is known it uniquely defines the actual member type.
- ArrayTypeLatticeElement arrayType = array.getTypeLattice().asArrayTypeLatticeElement();
- constraint = ValueTypeConstraint.fromTypeLattice(arrayType.getArrayMemberTypeAsValueType());
+ ArrayTypeElement arrayType = array.getType().asArrayType();
+ constraint = ValueTypeConstraint.fromTypeLattice(arrayType.getMemberTypeAsValueType());
} else {
// If not, e.g., the array input is null, the canonical value determines the final type.
constraint = getCanonicalTypeConstraint(canonical, true);
@@ -192,7 +191,7 @@
}
private ValueTypeConstraint getCanonicalTypeConstraint(Value value, boolean finished) {
- ValueTypeConstraint type = constraintForType(canonical(value).getTypeLattice());
+ ValueTypeConstraint type = constraintForType(canonical(value).getType());
switch (type) {
case INT_OR_FLOAT_OR_OBJECT:
// There is never a second round for resolving object vs single.
@@ -231,7 +230,7 @@
ArrayPut put = user.asArrayPut();
assert value == put.value();
assert !put.getMemberType().isPrecise();
- assert put.array().getTypeLattice().isDefinitelyNull();
+ assert put.array().getType().isDefinitelyNull();
} else {
assert false;
}
@@ -244,8 +243,8 @@
if (canonical1 == canonical2) {
return;
}
- TypeLatticeElement type1 = canonical1.getTypeLattice();
- TypeLatticeElement type2 = canonical2.getTypeLattice();
+ TypeElement type1 = canonical1.getType();
+ TypeElement type2 = canonical2.getType();
if (type1.isPreciseType() && type2.isPreciseType()) {
if (type1 != type2 && constraintForType(type1) != constraintForType(type2)) {
throw new CompilationError(
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
index fd0e452..43db91d 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
@@ -21,7 +21,6 @@
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexLibraryClass;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexProgramClass.ChecksumSupplier;
@@ -31,7 +30,6 @@
import com.android.tools.r8.graph.DexTypeList;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.graph.ParameterAnnotationsList;
-import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
@@ -54,13 +52,10 @@
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.InternalOptions.DesugarState;
-import com.android.tools.r8.utils.StringDiagnostic;
import com.android.tools.r8.utils.Timing;
-import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.IdentityHashMap;
@@ -113,15 +108,17 @@
if (androidApp != null) {
DexApplication app =
new ApplicationReader(androidApp, options, Timing.empty()).read(executor);
- appInfo =
- options.desugaredLibraryConfiguration.getRewritePrefix().isEmpty()
- ? new AppInfo(app)
- : new AppInfoWithClassHierarchy(app);
+ appInfo = new AppInfoWithClassHierarchy(app);
}
AppView<?> appView = AppView.createForD8(appInfo, options, rewritePrefix);
BackportedMethodRewriter.RewritableMethods rewritableMethods =
new BackportedMethodRewriter.RewritableMethods(options, appView);
rewritableMethods.visit(methods::add);
+ if (appInfo != null) {
+ DesugaredLibraryRetargeter desugaredLibraryRetargeter =
+ new DesugaredLibraryRetargeter(appView);
+ desugaredLibraryRetargeter.visit(methods::add);
+ }
return methods;
} catch (ExecutionException e) {
throw unwrapExecutionException(e);
@@ -146,49 +143,10 @@
&& !invoke.isInvokeStatic()) {
continue;
}
+
MethodProvider provider = getMethodProviderOrNull(invoke.getInvokedMethod());
if (provider == null) {
- if (!rewritableMethods.matchesVirtualRewrite(invoke.getInvokedMethod())) {
- continue;
- }
- // We need to force resolution, even on d8, to know if the invoke has to be rewritten.
- ResolutionResult resolutionResult =
- appView
- .appInfo()
- .resolveMethod(invoke.getInvokedMethod().holder, invoke.getInvokedMethod());
- if (resolutionResult.isFailedResolution()) {
- continue;
- }
- DexEncodedMethod singleTarget = resolutionResult.getSingleTarget();
- assert singleTarget != null;
- provider = getMethodProviderOrNull(singleTarget.method);
- if (provider == null) {
- continue;
- }
- }
-
- // Due to emulated dispatch, we have to rewrite invoke-super differently or we end up in
- // infinite loops. We do direct resolution. This is a very uncommon case.
- if (invoke.isInvokeSuper()
- && rewritableMethods.matchesVirtualRewrite(invoke.getInvokedMethod())) {
- DexEncodedMethod dexEncodedMethod =
- appView
- .appInfo()
- .withClassHierarchy()
- .lookupSuperTarget(invoke.getInvokedMethod(), code.method.method.holder);
- // Final methods can be rewritten as a normal invoke.
- if (dexEncodedMethod != null && !dexEncodedMethod.isFinal()) {
- DexMethod retargetMethod =
- appView
- .options()
- .desugaredLibraryConfiguration
- .retargetMethod(dexEncodedMethod.method, appView);
- if (retargetMethod != null) {
- iterator.replaceCurrentInstruction(
- new InvokeStatic(retargetMethod, invoke.outValue(), invoke.arguments()));
- }
- continue;
- }
+ continue;
}
provider.rewriteInvoke(invoke, iterator, code, appView, affectedValues);
@@ -222,11 +180,6 @@
if (!enabled) {
return;
}
- if (appView.options().isDesugaredLibraryCompilation()) {
- synthesizeEmulatedDispatchMethods(builder);
- } else {
- addInterfacesAndForwardingMethods(executorService);
- }
if (holders.isEmpty()) {
return;
}
@@ -243,8 +196,9 @@
}
}
- MethodAccessFlags flags = MethodAccessFlags.fromSharedAccessFlags(
- Constants.ACC_PUBLIC | Constants.ACC_STATIC | Constants.ACC_SYNTHETIC, false);
+ MethodAccessFlags flags =
+ MethodAccessFlags.fromSharedAccessFlags(
+ Constants.ACC_PUBLIC | Constants.ACC_STATIC | Constants.ACC_SYNTHETIC, false);
ClassAccessFlags classAccessFlags =
ClassAccessFlags.fromSharedAccessFlags(Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC);
// Generate the utility classes in a loop since utility classes can require the
@@ -262,7 +216,12 @@
Code code = provider.generateTemplateMethod(appView.options(), method);
DexEncodedMethod dexEncodedMethod =
new DexEncodedMethod(
- method, flags, DexAnnotationSet.empty(), ParameterAnnotationsList.empty(), code, true);
+ method,
+ flags,
+ DexAnnotationSet.empty(),
+ ParameterAnnotationsList.empty(),
+ code,
+ true);
boolean addToMainDexList =
referencingClasses.stream()
.anyMatch(clazz -> appView.appInfo().isInMainDexList(clazz.type));
@@ -273,140 +232,27 @@
method.holder,
dexEncodedMethod,
"java8 methods utility class",
- addToMainDexList);
+ addToMainDexList,
+ appView);
// The following may add elements to methodsProviders.
converter.optimizeSynthesizedClass(utilityClass, executorService);
}
}
- private void addInterfacesAndForwardingMethods(ExecutorService executorService)
- throws ExecutionException {
- assert !appView.options().isDesugaredLibraryCompilation();
- Map<DexType, List<DexMethod>> map = Maps.newIdentityHashMap();
- for (DexMethod emulatedDispatchMethod : rewritableMethods.getEmulatedDispatchMethods()) {
- map.putIfAbsent(emulatedDispatchMethod.holder, new ArrayList<>(1));
- map.get(emulatedDispatchMethod.holder).add(emulatedDispatchMethod);
- }
- List<DexEncodedMethod> addedMethods = new ArrayList<>();
- for (DexProgramClass clazz : appView.appInfo().classes()) {
- if (clazz.superType == null) {
- assert clazz.type == appView.dexItemFactory().objectType : clazz.type.toSourceString();
- continue;
- }
- DexClass dexClass = appView.definitionFor(clazz.superType);
- // Only performs computation if superclass is a library class, but not object to filter out
- // the most common case.
- if (dexClass != null
- && dexClass.isLibraryClass()
- && dexClass.type != appView.dexItemFactory().objectType) {
- for (DexType dexType : map.keySet()) {
- if (inherit(dexClass.asLibraryClass(), dexType)) {
- addedMethods.addAll(addInterfacesAndForwardingMethods(clazz, map.get(dexType)));
- }
- }
- }
- }
- if (addedMethods.isEmpty()) {
- return;
- }
- converter.processMethodsConcurrently(addedMethods, executorService);
- }
-
- private boolean inherit(DexLibraryClass clazz, DexType typeToInherit) {
- DexLibraryClass current = clazz;
- while (current.type != appView.dexItemFactory().objectType) {
- if (current.type == typeToInherit) {
- return true;
- }
- current = appView.definitionFor(current.superType).asLibraryClass();
- }
- return false;
- }
-
- private List<DexEncodedMethod> addInterfacesAndForwardingMethods(
- DexProgramClass clazz, List<DexMethod> dexMethods) {
- // BackportedMethodRewriter emulate dispatch: insertion of a marker interface & forwarding
- // methods.
- // We cannot use the ClassProcessor since this applies up to 26, while the ClassProcessor
- // applies up to 24.
- List<DexEncodedMethod> newForwardingMethods = new ArrayList<>();
- for (DexMethod dexMethod : dexMethods) {
- DexType[] newInterfaces = Arrays.copyOf(clazz.interfaces.values, clazz.interfaces.size() + 1);
- newInterfaces[newInterfaces.length - 1] =
- BackportedMethodRewriter.dispatchInterfaceTypeFor(appView, dexMethod);
- clazz.interfaces = new DexTypeList(newInterfaces);
- DexEncodedMethod dexEncodedMethod = clazz.lookupVirtualMethod(dexMethod);
- if (dexEncodedMethod == null) {
- DexEncodedMethod newMethod = createForwardingMethod(dexMethod, clazz);
- clazz.addVirtualMethod(newMethod);
- newForwardingMethods.add(newMethod);
- }
- }
- return newForwardingMethods;
- }
-
- private DexEncodedMethod createForwardingMethod(DexMethod target, DexClass clazz) {
- // NOTE: Never add a forwarding method to methods of classes unknown or coming from android.jar
- // even if this results in invalid code, these classes are never desugared.
- // In desugared library, emulated interface methods can be overridden by retarget lib members.
- DexMethod forwardMethod =
- appView.options().desugaredLibraryConfiguration.retargetMethod(target, appView);
- assert forwardMethod != null && forwardMethod != target;
- return DexEncodedMethod.createDesugaringForwardingMethod(
- appView.definitionFor(target), clazz, forwardMethod, appView.dexItemFactory());
- }
-
- private void synthesizeEmulatedDispatchMethods(Builder<?> builder) {
- assert appView.options().isDesugaredLibraryCompilation();
- if (rewritableMethods.getEmulatedDispatchMethods().isEmpty()) {
- return;
- }
- ClassAccessFlags itfAccessFlags =
- ClassAccessFlags.fromSharedAccessFlags(
- Constants.ACC_PUBLIC
- | Constants.ACC_SYNTHETIC
- | Constants.ACC_ABSTRACT
- | Constants.ACC_INTERFACE);
- ClassAccessFlags holderAccessFlags =
- ClassAccessFlags.fromSharedAccessFlags(Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC);
- for (DexMethod emulatedDispatchMethod : rewritableMethods.getEmulatedDispatchMethods()) {
- // Dispatch interface.
- DexType interfaceType = dispatchInterfaceTypeFor(appView, emulatedDispatchMethod);
- DexEncodedMethod itfMethod =
- generateInterfaceDispatchMethod(emulatedDispatchMethod, interfaceType);
- synthesizeClassWithUniqueMethod(
- builder,
- itfAccessFlags,
- interfaceType,
- itfMethod,
- "desugared library dispatch interface",
- false);
- // Dispatch holder.
- DexType holderType = dispatchHolderTypeFor(appView, emulatedDispatchMethod);
- DexEncodedMethod dispatchMethod =
- generateHolderDispatchMethod(emulatedDispatchMethod, holderType, itfMethod.method);
- synthesizeClassWithUniqueMethod(
- builder,
- holderAccessFlags,
- holderType,
- dispatchMethod,
- "desugared library dispatch class",
- false);
- }
- }
-
- private DexProgramClass synthesizeClassWithUniqueMethod(
+ static DexProgramClass synthesizeClassWithUniqueMethod(
Builder<?> builder,
ClassAccessFlags accessFlags,
DexType type,
DexEncodedMethod uniqueMethod,
String origin,
- boolean addToMainDexList) {
+ boolean addToMainDexList,
+ AppView<?> appView) {
+ DexItemFactory factory = appView.dexItemFactory();
DexProgramClass newClass =
new DexProgramClass(
type,
null,
- new SynthesizedOrigin(origin, getClass()),
+ new SynthesizedOrigin(origin, BackportedMethodRewriter.class),
accessFlags,
factory.objectType,
DexTypeList.empty(),
@@ -425,133 +271,45 @@
? DexEncodedMethod.EMPTY_ARRAY
: new DexEncodedMethod[] {uniqueMethod},
factory.getSkipNameValidationForTesting(),
- getChecksumSupplier(uniqueMethod));
+ getChecksumSupplier(uniqueMethod, appView));
appView.appInfo().addSynthesizedClass(newClass);
builder.addSynthesizedClass(newClass, addToMainDexList);
return newClass;
}
- private DexEncodedMethod generateInterfaceDispatchMethod(
- DexMethod emulatedDispatchMethod, DexType interfaceType) {
- MethodAccessFlags flags =
- MethodAccessFlags.fromSharedAccessFlags(
- Constants.ACC_PUBLIC | Constants.ACC_ABSTRACT | Constants.ACC_SYNTHETIC, false);
- DexMethod newMethod =
- factory.createMethod(
- interfaceType, emulatedDispatchMethod.proto, emulatedDispatchMethod.name);
- return new DexEncodedMethod(
- newMethod, flags, DexAnnotationSet.empty(), ParameterAnnotationsList.empty(), null, true);
- }
-
- private DexEncodedMethod generateHolderDispatchMethod(
- DexMethod emulatedDispatchMethod, DexType dispatchHolder, DexMethod itfMethod) {
- // The method should look like:
- // static foo(rcvr, arg0, arg1) {
- // if (rcvr instanceof interfaceType) {
- // return invoke-interface receiver.foo(arg0, arg1);
- // } else {
- // return DesugarX.foo(rcvr, arg0, arg1)
- // }
- // We do not deal with complex cases (multiple retargeting of the same signature in the
- // same inheritance tree, etc., since they do not happen in the most common desugared library.
- DexMethod desugarMethod =
- appView
- .options()
- .desugaredLibraryConfiguration
- .retargetMethod(emulatedDispatchMethod, appView);
- assert desugarMethod != null; // This method is reached only for retarget core lib members.
- DexMethod newMethod =
- appView
- .dexItemFactory()
- .createMethod(dispatchHolder, desugarMethod.proto, emulatedDispatchMethod.name);
- return DexEncodedMethod.toEmulateDispatchLibraryMethod(
- emulatedDispatchMethod.holder,
- newMethod,
- desugarMethod,
- itfMethod,
- Collections.emptyList(),
- appView);
- }
-
- private ChecksumSupplier getChecksumSupplier(DexEncodedMethod method) {
+ private static ChecksumSupplier getChecksumSupplier(DexEncodedMethod method, AppView<?> appView) {
if (!appView.options().encodeChecksums) {
return DexProgramClass::invalidChecksumRequest;
}
return c -> method.method.hashCode();
}
-
- public static DexType dispatchInterfaceTypeFor(AppView<?> appView, DexMethod method) {
- return dispatchTypeFor(appView, method, "dispatchInterface");
- }
-
- static DexType dispatchHolderTypeFor(AppView<?> appView, DexMethod method) {
- return dispatchTypeFor(appView, method, "dispatchHolder");
- }
-
- private static DexType dispatchTypeFor(AppView<?> appView, DexMethod method, String suffix) {
- String desugaredLibPrefix =
- appView.options().desugaredLibraryConfiguration.getSynthesizedLibraryClassesPackagePrefix();
- String descriptor =
- "L"
- + desugaredLibPrefix
- + UTILITY_CLASS_NAME_PREFIX
- + '$'
- + method.holder.getName()
- + '$'
- + method.name
- + '$'
- + suffix
- + ';';
- return appView.dexItemFactory().createType(descriptor);
- }
-
+
private MethodProvider getMethodProviderOrNull(DexMethod method) {
DexMethod original = appView.graphLense().getOriginalMethodSignature(method);
assert original != null;
- Map<DexType, DexType> backportCoreLibraryMembers =
- appView.options().desugaredLibraryConfiguration.getBackportCoreLibraryMember();
- if (backportCoreLibraryMembers.containsKey(original.holder)) {
- DexType newHolder = backportCoreLibraryMembers.get(original.holder);
- DexMethod newMethod =
- appView.dexItemFactory().createMethod(newHolder, original.proto, original.name);
- MethodProvider provider = rewritableMethods.getProvider(newMethod);
- if (provider != null) {
- return provider;
- }
- RetargetCoreLibraryMethodProvider extraProvider =
- new RetargetCoreLibraryMethodProvider(newHolder, original, true);
- // TODO(b/139788786): cache this entry, but without writing into a lock free structure.
- // rewritableMethods.addProvider(extraProvider);
- return extraProvider;
- }
return rewritableMethods.getProvider(original);
}
- public static void checkForAssumedLibraryTypes(AppView<?> appView) {
- Map<DexString, Map<DexType, DexType>> retargetCoreLibMember =
- appView.options().desugaredLibraryConfiguration.getRetargetCoreLibMember();
- for (DexString methodName : retargetCoreLibMember.keySet()) {
- for (DexType inType : retargetCoreLibMember.get(methodName).keySet()) {
- DexClass typeClass = appView.definitionFor(inType);
- if (typeClass == null) {
- RewritableMethods.warnMissingRetargetCoreLibraryMember(inType, appView);
- }
- }
- }
- }
-
private static final class RewritableMethods {
// Map backported method to a provider for creating the actual target method (with code).
private final Map<DexMethod, MethodProvider> rewritable = new IdentityHashMap<>();
- // Map virtualRewrites hold a methodName->method mapping for virtual methods which are
- // rewritten while the holder is non final but no superclass implement the method. In this case
- // d8 needs to force resolution of given methods to see if the invoke needs to be rewritten.
- private final Map<DexString, List<DexMethod>> virtualRewrites = new IdentityHashMap<>();
- // non final virtual library methods requiring generation of emulated dispatch.
- private final Set<DexMethod> emulatedDispatchMethods = Sets.newHashSet();
RewritableMethods(InternalOptions options, AppView<?> appView) {
+
+ if (options.testing.forceLibBackportsInL8CfToCf) {
+ DexItemFactory factory = options.itemFactory;
+ initializeJava9OptionalMethodProviders(factory);
+ initializeJava10OptionalMethodProviders(factory);
+ initializeJava11OptionalMethodProviders(factory);
+ initializeStreamMethodProviders(factory);
+ return;
+ }
+
+ if (!options.shouldBackportMethods()) {
+ return;
+ }
+
DexItemFactory factory = options.itemFactory;
if (options.minApiLevel < AndroidApiLevel.K.getLevel()) {
@@ -565,9 +323,9 @@
}
// The following providers are currently not implemented at any API level in Android.
- // They however require the Optional/Stream class to be present, either through
- // desugared libraries or natively. If Optional/Stream class is not present,
- // we do not desugar to avoid confusion in error messages.
+ // They however require the Optional/Stream class to be present, either through desugared
+ // libraries or natively. If Optional/Stream class is not present, we do not desugar to
+ // avoid confusion in error messages.
if (appView.rewritePrefix.hasRewrittenType(factory.optionalType, appView)
|| options.minApiLevel >= AndroidApiLevel.N.getLevel()) {
initializeJava9OptionalMethodProviders(factory);
@@ -583,27 +341,6 @@
initializeJava9MethodProviders(factory);
initializeJava10MethodProviders(factory);
initializeJava11MethodProviders(factory);
-
- if (!options.desugaredLibraryConfiguration.getRetargetCoreLibMember().isEmpty()) {
- initializeRetargetCoreLibraryMembers(appView);
- }
- }
-
- boolean matchesVirtualRewrite(DexMethod method) {
- List<DexMethod> dexMethods = virtualRewrites.get(method.name);
- if (dexMethods == null) {
- return false;
- }
- for (DexMethod dexMethod : dexMethods) {
- if (method.match(dexMethod)) {
- return true;
- }
- }
- return false;
- }
-
- public Set<DexMethod> getEmulatedDispatchMethods() {
- return emulatedDispatchMethods;
}
boolean isEmpty() {
@@ -668,8 +405,9 @@
// int Objects.compare(T a, T b, Comparator<? super T> c)
name = factory.createString("compare");
- proto = factory.createProto(factory.intType, factory.objectType, factory.objectType,
- factory.comparatorType);
+ proto =
+ factory.createProto(
+ factory.intType, factory.objectType, factory.objectType, factory.comparatorType);
method = factory.createMethod(type, proto, name);
addProvider(new MethodGenerator(method, BackportedMethods::ObjectsMethods_compare));
@@ -1242,8 +980,9 @@
// String String.join(CharSequence, CharSequence...)
name = factory.createString("join");
- proto = factory.createProto(factory.stringType, factory.charSequenceType,
- factory.charSequenceArrayType);
+ proto =
+ factory.createProto(
+ factory.stringType, factory.charSequenceType, factory.charSequenceArrayType);
method = factory.createMethod(type, proto, name);
addProvider(
new MethodGenerator(method, BackportedMethods::StringMethods_joinArray, "joinArray"));
@@ -1278,19 +1017,13 @@
name = factory.createString("multiplyFull");
proto = factory.createProto(factory.longType, factory.intType, factory.intType);
method = factory.createMethod(type, proto, name);
- addProvider(
- new MethodGenerator(
- method,
- BackportedMethods::MathMethods_multiplyFull));
+ addProvider(new MethodGenerator(method, BackportedMethods::MathMethods_multiplyFull));
// long {Math,StrictMath}.multiplyHigh(long, long)
name = factory.createString("multiplyHigh");
proto = factory.createProto(factory.longType, factory.longType, factory.longType);
method = factory.createMethod(type, proto, name);
- addProvider(
- new MethodGenerator(
- method,
- BackportedMethods::MathMethods_multiplyHigh));
+ addProvider(new MethodGenerator(method, BackportedMethods::MathMethods_multiplyHigh));
// long {Math,StrictMath}.floorDiv(long, int)
name = factory.createString("floorDiv");
@@ -1384,8 +1117,7 @@
proto = factory.createProto(type, factory.objectArrayType);
method = factory.createMethod(type, proto, name);
addProvider(
- new MethodGenerator(
- method, BackportedMethods::CollectionMethods_listOfArray, "ofArray"));
+ new MethodGenerator(method, BackportedMethods::CollectionMethods_listOfArray, "ofArray"));
// Set<E> Set.of(<args>) for 0 to 10 arguments and Set.of(E[])
type = factory.setType;
@@ -1405,8 +1137,7 @@
proto = factory.createProto(type, factory.objectArrayType);
method = factory.createMethod(type, proto, name);
addProvider(
- new MethodGenerator(
- method, BackportedMethods::CollectionMethods_setOfArray, "ofArray"));
+ new MethodGenerator(method, BackportedMethods::CollectionMethods_setOfArray, "ofArray"));
// Map<K, V> Map.of(<K, V args>) for 0 to 10 pairs and Map.ofEntries(Map.Entry<K, V>[])
type = factory.mapType;
@@ -1553,24 +1284,24 @@
// Optional{void,Int,Long,Double}.stream()
DexType[] optionalTypes =
new DexType[] {
- optionalType,
- factory.optionalDoubleType,
- factory.optionalLongType,
- factory.optionalIntType,
+ optionalType,
+ factory.optionalDoubleType,
+ factory.optionalLongType,
+ factory.optionalIntType,
};
DexType[] streamReturnTypes =
new DexType[] {
- factory.streamType,
- factory.createType(factory.createString("Ljava/util/stream/DoubleStream;")),
- factory.createType(factory.createString("Ljava/util/stream/LongStream;")),
- factory.createType(factory.createString("Ljava/util/stream/IntStream;")),
+ factory.streamType,
+ factory.createType(factory.createString("Ljava/util/stream/DoubleStream;")),
+ factory.createType(factory.createString("Ljava/util/stream/LongStream;")),
+ factory.createType(factory.createString("Ljava/util/stream/IntStream;")),
};
TemplateMethodFactory[] streamMethodFactories =
new TemplateMethodFactory[] {
- BackportedMethods::OptionalMethods_stream,
- BackportedMethods::OptionalMethods_streamDouble,
- BackportedMethods::OptionalMethods_streamLong,
- BackportedMethods::OptionalMethods_streamInt,
+ BackportedMethods::OptionalMethods_stream,
+ BackportedMethods::OptionalMethods_streamDouble,
+ BackportedMethods::OptionalMethods_streamLong,
+ BackportedMethods::OptionalMethods_streamInt,
};
name = factory.createString("stream");
for (int i = 0; i < optionalTypes.length; i++) {
@@ -1579,24 +1310,20 @@
proto = factory.createProto(streamReturnType);
method = factory.createMethod(optional, proto, name);
addProvider(
- new StatifyingMethodGenerator(
- method, streamMethodFactories[i], "stream", optional));
+ new StatifyingMethodGenerator(method, streamMethodFactories[i], "stream", optional));
}
// Optional{void,Int,Long,Double}.ifPresentOrElse(consumer,runnable)
DexType[] consumerTypes =
- new DexType[]{
- factory.consumerType,
- factory.doubleConsumer,
- factory.longConsumer,
- factory.intConsumer
+ new DexType[] {
+ factory.consumerType, factory.doubleConsumer, factory.longConsumer, factory.intConsumer
};
TemplateMethodFactory[] methodFactories =
- new TemplateMethodFactory[]{
- BackportedMethods::OptionalMethods_ifPresentOrElse,
- BackportedMethods::OptionalMethods_ifPresentOrElseDouble,
- BackportedMethods::OptionalMethods_ifPresentOrElseLong,
- BackportedMethods::OptionalMethods_ifPresentOrElseInt
+ new TemplateMethodFactory[] {
+ BackportedMethods::OptionalMethods_ifPresentOrElse,
+ BackportedMethods::OptionalMethods_ifPresentOrElseDouble,
+ BackportedMethods::OptionalMethods_ifPresentOrElseLong,
+ BackportedMethods::OptionalMethods_ifPresentOrElseInt
};
for (int i = 0; i < optionalTypes.length; i++) {
DexType optional = optionalTypes[i];
@@ -1613,17 +1340,14 @@
// Optional{void,Int,Long,Double}.orElseThrow()
DexType[] optionalTypes =
new DexType[] {
- factory.optionalType,
- factory.optionalDoubleType,
- factory.optionalLongType,
- factory.optionalIntType,
+ factory.optionalType,
+ factory.optionalDoubleType,
+ factory.optionalLongType,
+ factory.optionalIntType,
};
DexType[] returnTypes =
new DexType[] {
- factory.objectType,
- factory.doubleType,
- factory.longType,
- factory.intType,
+ factory.objectType, factory.doubleType, factory.longType, factory.intType,
};
MethodInvokeRewriter[] rewriters =
new MethodInvokeRewriter[] {
@@ -1644,17 +1368,17 @@
// Optional{void,Int,Long,Double}.isEmpty()
DexType[] optionalTypes =
new DexType[] {
- factory.optionalType,
- factory.optionalDoubleType,
- factory.optionalLongType,
- factory.optionalIntType,
+ factory.optionalType,
+ factory.optionalDoubleType,
+ factory.optionalLongType,
+ factory.optionalIntType,
};
TemplateMethodFactory[] methodFactories =
- new TemplateMethodFactory[]{
- BackportedMethods::OptionalMethods_isEmpty,
- BackportedMethods::OptionalMethods_isEmptyDouble,
- BackportedMethods::OptionalMethods_isEmptyLong,
- BackportedMethods::OptionalMethods_isEmptyInt
+ new TemplateMethodFactory[] {
+ BackportedMethods::OptionalMethods_isEmpty,
+ BackportedMethods::OptionalMethods_isEmptyDouble,
+ BackportedMethods::OptionalMethods_isEmptyLong,
+ BackportedMethods::OptionalMethods_isEmptyInt
};
DexString name = factory.createString("isEmpty");
for (int i = 0; i < optionalTypes.length; i++) {
@@ -1675,76 +1399,7 @@
DexProto proto = factory.createProto(factory.streamType, factory.objectType);
DexMethod method = factory.createMethod(streamType, proto, name);
addProvider(
- new MethodGenerator(
- method, BackportedMethods::StreamMethods_ofNullable, "ofNullable"));
- }
-
- private static void warnMissingRetargetCoreLibraryMember(DexType type, AppView<?> appView) {
- StringDiagnostic warning =
- new StringDiagnostic(
- "Cannot retarget core library member "
- + type.getName()
- + " because the class is missing.");
- appView.options().reporter.warning(warning);
- }
-
- private void initializeRetargetCoreLibraryMembers(AppView<?> appView) {
- assert appView.appInfo().hasClassHierarchy()
- : "Class hierarchy required for desugared library.";
- Map<DexString, Map<DexType, DexType>> retargetCoreLibMember =
- appView.options().desugaredLibraryConfiguration.getRetargetCoreLibMember();
- for (DexString methodName : retargetCoreLibMember.keySet()) {
- for (DexType inType : retargetCoreLibMember.get(methodName).keySet()) {
- DexClass typeClass = appView.definitionFor(inType);
- if (typeClass != null) {
- DexType newHolder = retargetCoreLibMember.get(methodName).get(inType);
- List<DexEncodedMethod> found = findDexEncodedMethodsWithName(methodName, typeClass);
- for (DexEncodedMethod encodedMethod : found) {
- if (!encodedMethod.isStatic()) {
- virtualRewrites.putIfAbsent(encodedMethod.method.name, new ArrayList<>());
- virtualRewrites.get(encodedMethod.method.name).add(encodedMethod.method);
- if (InterfaceMethodRewriter.isEmulatedInterfaceDispatch(appView, encodedMethod)) {
- // In this case interface method rewriter takes care of it.
- continue;
- } else if (!encodedMethod.isFinal()) {
- // Virtual rewrites require emulated dispatch for inheritance.
- // The call is rewritten to the dispatch holder class instead.
- handleEmulateDispatch(appView, encodedMethod.method);
- newHolder = dispatchHolderTypeFor(appView, encodedMethod.method);
- }
- }
- DexProto proto = encodedMethod.method.proto;
- DexMethod method = appView.dexItemFactory().createMethod(inType, proto, methodName);
- addProvider(
- new RetargetCoreLibraryMethodProvider(
- newHolder, method, encodedMethod.isStatic()));
- }
- }
- }
- }
- }
-
- private List<DexEncodedMethod> findDexEncodedMethodsWithName(
- DexString methodName, DexClass clazz) {
- List<DexEncodedMethod> found = new ArrayList<>();
- for (DexEncodedMethod encodedMethod : clazz.methods()) {
- if (encodedMethod.method.name == methodName) {
- found.add(encodedMethod);
- }
- }
- assert found.size() > 0 : "Should have found a method (library specifications).";
- return found;
- }
-
- private void handleEmulateDispatch(AppView<?> appView, DexMethod method) {
- emulatedDispatchMethods.add(method);
- if (!appView.options().isDesugaredLibraryCompilation()) {
- // Add rewrite rules so keeps rules are correctly generated in the program.
- DexType dispatchInterfaceType = dispatchInterfaceTypeFor(appView, method);
- appView.rewritePrefix.rewriteType(dispatchInterfaceType, dispatchInterfaceType);
- DexType dispatchHolderType = dispatchHolderTypeFor(appView, method);
- appView.rewritePrefix.rewriteType(dispatchHolderType, dispatchHolderType);
- }
+ new MethodGenerator(method, BackportedMethods::StreamMethods_ofNullable, "ofNullable"));
}
private void addProvider(MethodProvider generator) {
@@ -1779,52 +1434,6 @@
public abstract boolean requiresGenerationOfCode();
}
- private static class RetargetCoreLibraryMethodProvider extends MethodProvider {
-
- private final DexType newHolder;
- private DexMethod targetMethod;
- private boolean isStatic;
-
- RetargetCoreLibraryMethodProvider(DexType newHolder, DexMethod method, boolean isStatic) {
- super(method);
- this.newHolder = newHolder;
- this.isStatic = isStatic;
- }
-
- @Override
- public void rewriteInvoke(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- IRCode code,
- AppView<?> appView,
- Set<Value> affectedValues) {
- iterator.replaceCurrentInstruction(
- new InvokeStatic(provideMethod(appView), invoke.outValue(), invoke.inValues()));
- }
-
- @Override
- public DexMethod provideMethod(AppView<?> appView) {
- if (targetMethod != null) {
- return targetMethod;
- }
- DexItemFactory factory = appView.dexItemFactory();
- DexProto newProto =
- isStatic ? method.proto : factory.prependTypeToProto(method.holder, method.proto);
- targetMethod = factory.createMethod(newHolder, newProto, method.name);
- return targetMethod;
- }
-
- @Override
- public Code generateTemplateMethod(InternalOptions options, DexMethod method) {
- throw new Unreachable("Does not generate any method.");
- }
-
- @Override
- public boolean requiresGenerationOfCode() {
- return false;
- }
- }
-
private static final class InvokeRewriter extends MethodProvider {
private final MethodInvokeRewriter rewriter;
@@ -1896,14 +1505,9 @@
DexItemFactory factory = appView.dexItemFactory();
String unqualifiedName = method.holder.getName();
// Avoid duplicate class names between core lib dex file and program dex files.
- String desugaredLibPrefix =
- appView
- .options()
- .desugaredLibraryConfiguration
- .getSynthesizedLibraryClassesPackagePrefix(appView);
String descriptor =
"L"
- + desugaredLibPrefix
+ + appView.options().synthesizedClassPrefix
+ UTILITY_CLASS_NAME_PREFIX
+ '$'
+ unqualifiedName
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
index 76e97df..3d16d19 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
@@ -229,7 +229,7 @@
for (DexProgramClass clazz : newSyntheticMethods.keySet()) {
List<DexEncodedMethod> newForwardingMethods = newSyntheticMethods.get(clazz);
if (newForwardingMethods != null) {
- clazz.appendVirtualMethods(newForwardingMethods);
+ clazz.addVirtualMethods(newForwardingMethods);
newForwardingMethods.forEach(newSynthesizedMethodConsumer);
}
}
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 3cadabf..2be1832 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
@@ -16,6 +16,9 @@
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DexValue;
+import com.android.tools.r8.graph.DexValue.DexValueAnnotation;
+import com.android.tools.r8.graph.DexValue.DexValueArray;
+import com.android.tools.r8.graph.DexValue.DexValueType;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.ir.code.Invoke;
import com.android.tools.r8.ir.conversion.IRConverter;
@@ -96,7 +99,7 @@
method.annotations().keepIf(x -> !isCovariantReturnTypeAnnotation(x.annotation)));
}
// Add the newly constructed methods to the class.
- clazz.appendVirtualMethods(covariantReturnTypeMethods);
+ clazz.addVirtualMethods(covariantReturnTypeMethods);
}
// Processes all the dalvik.annotation.codegen.CovariantReturnType and dalvik.annotation.codegen.
@@ -201,22 +204,22 @@
String name = element.name.toString();
if (annotation.type == factory.annotationCovariantReturnType) {
if (name.equals("returnType")) {
- if (!(element.value instanceof DexValue.DexValueType)) {
+ DexValueType dexValueType = element.value.asDexValueType();
+ if (dexValueType == null) {
throw new CompilationError(
String.format(
"Expected element \"returnType\" of CovariantReturnType annotation to "
+ "reference a type (method: \"%s\", was: %s)",
method.toSourceString(), element.value.getClass().getCanonicalName()));
}
-
- DexValue.DexValueType dexValueType = (DexValue.DexValueType) element.value;
covariantReturnTypes.add(dexValueType.value);
} else if (name.equals("presentAfter")) {
hasPresentAfterElement = true;
}
} else {
if (name.equals("value")) {
- if (!(element.value instanceof DexValue.DexValueArray)) {
+ DexValueArray array = element.value.asDexValueArray();
+ if (array == null) {
throw new CompilationError(
String.format(
"Expected element \"value\" of CovariantReturnTypes annotation to "
@@ -224,11 +227,10 @@
method.toSourceString(), element.value.getClass().getCanonicalName()));
}
- DexValue.DexValueArray array = (DexValue.DexValueArray) element.value;
// Handle the inner dalvik.annotation.codegen.CovariantReturnType annotations recursively.
for (DexValue value : array.getValues()) {
- assert value instanceof DexValue.DexValueAnnotation;
- DexValue.DexValueAnnotation innerAnnotation = (DexValue.DexValueAnnotation) value;
+ assert value.isDexValueAnnotation();
+ DexValueAnnotation innerAnnotation = value.asDexValueAnnotation();
getCovariantReturnTypesFromAnnotation(
clazz, method, innerAnnotation.value, covariantReturnTypes);
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryAPIConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryAPIConverter.java
index ceed9ef..c81eedb 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryAPIConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryAPIConverter.java
@@ -16,7 +16,7 @@
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
@@ -29,14 +29,15 @@
import com.android.tools.r8.ir.synthetic.DesugaredLibraryAPIConversionCfCodeProvider.APIConverterWrapperCfCodeProvider;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.ListUtils;
+import com.android.tools.r8.utils.OptionalBool;
import com.android.tools.r8.utils.StringDiagnostic;
+import com.android.tools.r8.utils.WorkList;
import com.google.common.collect.Sets;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collections;
-import java.util.HashMap;
import java.util.HashSet;
-import java.util.LinkedList;
+import java.util.IdentityHashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
@@ -70,7 +71,9 @@
// Enqueuer and not during IR processing.
private final Mode mode;
private final DesugaredLibraryWrapperSynthesizer wrapperSynthesizor;
- private final Map<DexClass, Set<DexEncodedMethod>> callBackMethods = new HashMap<>();
+ private final Map<DexClass, Set<DexEncodedMethod>> callBackMethods = new IdentityHashMap<>();
+ private final Map<DexClass, List<DexEncodedMethod>> pendingCallBackMethods =
+ new IdentityHashMap<>();
private final Set<DexMethod> trackedCallBackAPIs;
private final Set<DexMethod> trackedAPIs;
@@ -172,7 +175,9 @@
// library type), but the enqueuer cannot see that.
// To avoid too much computation we first look if the method would need to be rewritten if
// it would override a library method, then check if it overrides a library method.
- if (encodedMethod.isPrivateMethod() || encodedMethod.isStatic()) {
+ if (encodedMethod.isPrivateMethod()
+ || encodedMethod.isStatic()
+ || encodedMethod.isLibraryMethodOverride().isFalse()) {
return false;
}
DexMethod method = encodedMethod.method;
@@ -195,22 +200,22 @@
private boolean overridesLibraryMethod(DexClass theClass, DexMethod method) {
// We look up everywhere to see if there is a supertype/interface implementing the method...
- LinkedList<DexType> workList = new LinkedList<>();
- Collections.addAll(workList, theClass.interfaces.values);
+ WorkList<DexType> workList = WorkList.newIdentityWorkList();
+ workList.addIfNotSeen(theClass.interfaces.values);
boolean foundOverrideToRewrite = false;
// There is no methods with desugared types on Object.
if (theClass.superType != factory.objectType) {
- workList.add(theClass.superType);
+ workList.addIfNotSeen(theClass.superType);
}
- while (!workList.isEmpty()) {
- DexType current = workList.removeFirst();
+ while (workList.hasNext()) {
+ DexType current = workList.next();
DexClass dexClass = appView.definitionFor(current);
if (dexClass == null) {
continue;
}
- workList.addAll(Arrays.asList(dexClass.interfaces.values));
+ workList.addIfNotSeen(dexClass.interfaces.values);
if (dexClass.superType != factory.objectType) {
- workList.add(dexClass.superType);
+ workList.addIfNotSeen(dexClass.superType);
}
if (!dexClass.isLibraryClass() && !appView.options().isDesugaredLibraryCompilation()) {
continue;
@@ -249,8 +254,9 @@
private synchronized void addCallBackSignature(DexClass dexClass, DexEncodedMethod method) {
assert dexClass.type == method.method.holder;
- callBackMethods.putIfAbsent(dexClass, new HashSet<>());
- callBackMethods.get(dexClass).add(method);
+ if (callBackMethods.computeIfAbsent(dexClass, key -> new HashSet<>()).add(method)) {
+ pendingCallBackMethods.computeIfAbsent(dexClass, key -> new ArrayList<>()).add(method);
+ }
}
public static DexMethod methodWithVivifiedTypeInSignature(
@@ -289,19 +295,24 @@
if (appView.options().testing.trackDesugaredAPIConversions) {
generateTrackDesugaredAPIWarnings(trackedAPIs, "");
generateTrackDesugaredAPIWarnings(trackedCallBackAPIs, "callback ");
+ trackedAPIs.clear();
+ trackedCallBackAPIs.clear();
}
List<DexEncodedMethod> result = new ArrayList<>();
- for (DexClass dexClass : callBackMethods.keySet()) {
- List<DexEncodedMethod> dexEncodedMethods =
- generateCallbackMethods(callBackMethods.get(dexClass), dexClass);
- dexClass.appendVirtualMethods(dexEncodedMethods);
- result.addAll(dexEncodedMethods);
- }
+ pendingCallBackMethods.forEach(
+ (clazz, callbacks) -> {
+ List<DexEncodedMethod> generated =
+ ListUtils.map(callbacks, callback -> generateCallbackMethod(callback, clazz));
+ clazz.addVirtualMethods(generated);
+ result.addAll(generated);
+ });
+ pendingCallBackMethods.clear();
return result;
}
- public Map<DexProgramClass, DexProgramClass> synthesizeWrappersAndMapToReverse() {
- return wrapperSynthesizor.synthesizeWrappersAndMapToReverse();
+ public List<DexProgramClass> synthesizeWrappers(
+ Map<DexType, DexProgramClass> synthesizedWrappers) {
+ return wrapperSynthesizor.synthesizeWrappers(synthesizedWrappers);
}
public DexClasspathClass synthesizeClasspathMock(
@@ -309,23 +320,21 @@
return wrapperSynthesizor.synthesizeClasspathMock(classToMock, mockType, mockIsInterface);
}
- private List<DexEncodedMethod> generateCallbackMethods(
- Set<DexEncodedMethod> originalMethods, DexClass dexClass) {
- List<DexEncodedMethod> newDexEncodedMethods = new ArrayList<>();
- for (DexEncodedMethod originalMethod : originalMethods) {
- DexMethod methodToInstall =
- methodWithVivifiedTypeInSignature(originalMethod.method, dexClass.type, appView);
- CfCode cfCode =
- new APIConverterWrapperCfCodeProvider(
- appView, originalMethod.method, null, this, dexClass.isInterface())
- .generateCfCode();
- DexEncodedMethod newDexEncodedMethod =
- wrapperSynthesizor.newSynthesizedMethod(methodToInstall, originalMethod, cfCode);
- newDexEncodedMethod.setCode(cfCode, appView);
- newDexEncodedMethods.add(newDexEncodedMethod);
+ private DexEncodedMethod generateCallbackMethod(
+ DexEncodedMethod originalMethod, DexClass dexClass) {
+ DexMethod methodToInstall =
+ methodWithVivifiedTypeInSignature(originalMethod.method, dexClass.type, appView);
+ CfCode cfCode =
+ new APIConverterWrapperCfCodeProvider(
+ appView, originalMethod.method, null, this, dexClass.isInterface())
+ .generateCfCode();
+ DexEncodedMethod newDexEncodedMethod =
+ wrapperSynthesizor.newSynthesizedMethod(methodToInstall, originalMethod, cfCode);
+ newDexEncodedMethod.setCode(cfCode, appView);
+ if (originalMethod.isLibraryMethodOverride().isTrue()) {
+ newDexEncodedMethod.setLibraryMethodOverride(OptionalBool.TRUE);
}
- assert Sets.newHashSet(newDexEncodedMethods).size() == newDexEncodedMethods.size();
- return newDexEncodedMethods;
+ return newDexEncodedMethod;
}
private void generateTrackDesugaredAPIWarnings(Set<DexMethod> tracked, String inner) {
@@ -513,7 +522,7 @@
DexMethod conversionMethod = createConversionMethod(argType, argType, argVivifiedType);
// The value is null only if the input is null.
Value convertedValue =
- createConversionValue(code, inValue.getTypeLattice().nullability(), argVivifiedType);
+ createConversionValue(code, inValue.getType().nullability(), argVivifiedType);
return new InvokeStatic(conversionMethod, convertedValue, Collections.singletonList(inValue));
}
@@ -524,9 +533,8 @@
Value outValue = invokeMethod.outValue();
outValue.replaceUsers(convertedValue);
// The only user of out value is now the new invoke static, so no type propagation is required.
- outValue.setTypeLattice(
- TypeLatticeElement.fromDexType(
- returnVivifiedType, outValue.getTypeLattice().nullability(), appView));
+ outValue.setType(
+ TypeElement.fromDexType(returnVivifiedType, outValue.getType().nullability(), appView));
return new InvokeStatic(conversionMethod, convertedValue, Collections.singletonList(outValue));
}
@@ -557,7 +565,7 @@
}
private Value createConversionValue(IRCode code, Nullability nullability, DexType valueType) {
- return code.createValue(TypeLatticeElement.fromDexType(valueType, nullability, appView));
+ return code.createValue(TypeElement.fromDexType(valueType, nullability, appView));
}
public boolean canConvert(DexType type) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryConfiguration.java b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryConfiguration.java
index bdb4cd9..baa6317 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryConfiguration.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryConfiguration.java
@@ -110,12 +110,6 @@
return libraryCompilation;
}
- public String getSynthesizedLibraryClassesPackagePrefix(AppView<?> appView) {
- return appView.options().isDesugaredLibraryCompilation()
- ? synthesizedLibraryClassesPackagePrefix
- : "";
- }
-
public String getSynthesizedLibraryClassesPackagePrefix() {
return synthesizedLibraryClassesPackagePrefix;
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java
new file mode 100644
index 0000000..3949767
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java
@@ -0,0 +1,441 @@
+// 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.ir.desugar;
+
+import com.android.tools.r8.dex.Constants;
+import com.android.tools.r8.graph.*;
+import com.android.tools.r8.ir.code.IRCode;
+import com.android.tools.r8.ir.code.Instruction;
+import com.android.tools.r8.ir.code.InstructionListIterator;
+import com.android.tools.r8.ir.code.InvokeMethod;
+import com.android.tools.r8.ir.code.InvokeStatic;
+import com.android.tools.r8.ir.conversion.IRConverter;
+import com.android.tools.r8.utils.StringDiagnostic;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.function.Consumer;
+
+public class DesugaredLibraryRetargeter {
+
+ public static final String DESUGAR_LIB_RETARGET_CLASS_NAME_PREFIX =
+ "$r8$retargetLibraryMember$virtualDispatch";
+
+ private final AppView<AppInfoWithClassHierarchy> appView;
+ private final Map<DexMethod, DexMethod> retargetLibraryMember = new IdentityHashMap<>();
+ // Map virtualRewrites hold a methodName->method mapping for virtual methods which are
+ // rewritten while the holder is non final but no superclass implement the method. In this case
+ // d8 needs to force resolution of given methods to see if the invoke needs to be rewritten.
+ private final Map<DexString, List<DexMethod>> virtualRewrites = new IdentityHashMap<>();
+ // Non final virtual library methods requiring generation of emulated dispatch.
+ private final Set<DexMethod> emulatedDispatchMethods = Sets.newHashSet();
+
+ public DesugaredLibraryRetargeter(AppView<?> appView) {
+ assert appView.appInfo().hasClassHierarchy()
+ : "Class hierarchy required for desugared library.";
+ this.appView = appView.withClassHierarchy();
+ if (appView.options().desugaredLibraryConfiguration.getRetargetCoreLibMember().isEmpty()) {
+ return;
+ }
+ new RetargetingSetup().setUpRetargeting();
+ }
+
+ public static void checkForAssumedLibraryTypes(AppView<?> appView) {
+ Map<DexString, Map<DexType, DexType>> retargetCoreLibMember =
+ appView.options().desugaredLibraryConfiguration.getRetargetCoreLibMember();
+ for (DexString methodName : retargetCoreLibMember.keySet()) {
+ for (DexType inType : retargetCoreLibMember.get(methodName).keySet()) {
+ DexClass typeClass = appView.definitionFor(inType);
+ if (typeClass == null) {
+ warnMissingRetargetCoreLibraryMember(inType, appView);
+ }
+ }
+ }
+ }
+
+ private static void warnMissingRetargetCoreLibraryMember(DexType type, AppView<?> appView) {
+ StringDiagnostic warning =
+ new StringDiagnostic(
+ "Cannot retarget core library member "
+ + type.getName()
+ + " because the class is missing.");
+ appView.options().reporter.warning(warning);
+ }
+
+ // Used by the ListOfBackportedMethods utility.
+ void visit(Consumer<DexMethod> consumer) {
+ retargetLibraryMember.keySet().forEach(consumer);
+ }
+
+ public void desugar(IRCode code) {
+ if (retargetLibraryMember.isEmpty()) {
+ return;
+ }
+
+ InstructionListIterator iterator = code.instructionListIterator();
+ while (iterator.hasNext()) {
+ Instruction instruction = iterator.next();
+ if (!instruction.isInvokeMethod()) {
+ continue;
+ }
+
+ InvokeMethod invoke = instruction.asInvokeMethod();
+ DexMethod retarget = getRetargetLibraryMember(invoke.getInvokedMethod());
+ if (retarget == null) {
+ if (!matchesVirtualRewrite(invoke.getInvokedMethod())) {
+ continue;
+ }
+ // We need to force resolution, even on d8, to know if the invoke has to be rewritten.
+ ResolutionResult resolutionResult =
+ appView
+ .appInfo()
+ .resolveMethod(invoke.getInvokedMethod().holder, invoke.getInvokedMethod());
+ if (resolutionResult.isFailedResolution()) {
+ continue;
+ }
+ DexEncodedMethod singleTarget = resolutionResult.getSingleTarget();
+ assert singleTarget != null;
+ retarget = getRetargetLibraryMember(singleTarget.method);
+ if (retarget == null) {
+ continue;
+ }
+ }
+
+ // Due to emulated dispatch, we have to rewrite invoke-super differently or we end up in
+ // infinite loops. We do direct resolution. This is a very uncommon case.
+ if (invoke.isInvokeSuper() && matchesVirtualRewrite(invoke.getInvokedMethod())) {
+ DexEncodedMethod dexEncodedMethod =
+ appView
+ .appInfo()
+ .withClassHierarchy()
+ .lookupSuperTarget(invoke.getInvokedMethod(), code.method.method.holder);
+ // Final methods can be rewritten as a normal invoke.
+ if (dexEncodedMethod != null && !dexEncodedMethod.isFinal()) {
+ DexMethod retargetMethod =
+ appView
+ .options()
+ .desugaredLibraryConfiguration
+ .retargetMethod(dexEncodedMethod.method, appView);
+ if (retargetMethod != null) {
+ iterator.replaceCurrentInstruction(
+ new InvokeStatic(retargetMethod, invoke.outValue(), invoke.arguments()));
+ }
+ continue;
+ }
+ }
+
+ iterator.replaceCurrentInstruction(
+ new InvokeStatic(retarget, invoke.outValue(), invoke.inValues()));
+ }
+ }
+
+ private DexMethod getRetargetLibraryMember(DexMethod method) {
+ Map<DexType, DexType> backportCoreLibraryMembers =
+ appView.options().desugaredLibraryConfiguration.getBackportCoreLibraryMember();
+ if (backportCoreLibraryMembers.containsKey(method.holder)) {
+ DexType newHolder = backportCoreLibraryMembers.get(method.holder);
+ return appView.dexItemFactory().createMethod(newHolder, method.proto, method.name);
+ }
+ return retargetLibraryMember.get(method);
+ }
+
+ private boolean matchesVirtualRewrite(DexMethod method) {
+ List<DexMethod> dexMethods = virtualRewrites.get(method.name);
+ if (dexMethods == null) {
+ return false;
+ }
+ for (DexMethod dexMethod : dexMethods) {
+ if (method.match(dexMethod)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private class RetargetingSetup {
+
+ private void setUpRetargeting() {
+ Map<DexString, Map<DexType, DexType>> retargetCoreLibMember =
+ appView.options().desugaredLibraryConfiguration.getRetargetCoreLibMember();
+ for (DexString methodName : retargetCoreLibMember.keySet()) {
+ for (DexType inType : retargetCoreLibMember.get(methodName).keySet()) {
+ DexClass typeClass = appView.definitionFor(inType);
+ if (typeClass != null) {
+ DexType newHolder = retargetCoreLibMember.get(methodName).get(inType);
+ List<DexEncodedMethod> found = findDexEncodedMethodsWithName(methodName, typeClass);
+ for (DexEncodedMethod encodedMethod : found) {
+ if (!encodedMethod.isStatic()) {
+ virtualRewrites.putIfAbsent(encodedMethod.method.name, new ArrayList<>());
+ virtualRewrites.get(encodedMethod.method.name).add(encodedMethod.method);
+ if (InterfaceMethodRewriter.isEmulatedInterfaceDispatch(appView, encodedMethod)) {
+ // In this case interface method rewriter takes care of it.
+ continue;
+ } else if (!encodedMethod.isFinal()) {
+ // Virtual rewrites require emulated dispatch for inheritance.
+ // The call is rewritten to the dispatch holder class instead.
+ handleEmulateDispatch(appView, encodedMethod.method);
+ newHolder = dispatchHolderTypeFor(encodedMethod.method);
+ }
+ }
+ DexProto proto = encodedMethod.method.proto;
+ DexMethod method = appView.dexItemFactory().createMethod(inType, proto, methodName);
+ retargetLibraryMember.put(
+ method, computeRetargetMethod(method, encodedMethod.isStatic(), newHolder));
+ }
+ }
+ }
+ }
+ }
+
+ private DexMethod computeRetargetMethod(DexMethod method, boolean isStatic, DexType newHolder) {
+ DexItemFactory factory = appView.dexItemFactory();
+ DexProto newProto =
+ isStatic ? method.proto : factory.prependTypeToProto(method.holder, method.proto);
+ return factory.createMethod(newHolder, newProto, method.name);
+ }
+
+ private List<DexEncodedMethod> findDexEncodedMethodsWithName(
+ DexString methodName, DexClass clazz) {
+ List<DexEncodedMethod> found = new ArrayList<>();
+ for (DexEncodedMethod encodedMethod : clazz.methods()) {
+ if (encodedMethod.method.name == methodName) {
+ found.add(encodedMethod);
+ }
+ }
+ assert found.size() > 0 : "Should have found a method (library specifications).";
+ return found;
+ }
+
+ private void handleEmulateDispatch(AppView<?> appView, DexMethod method) {
+ emulatedDispatchMethods.add(method);
+ if (!appView.options().isDesugaredLibraryCompilation()) {
+ // Add rewrite rules so keeps rules are correctly generated in the program.
+ DexType dispatchInterfaceType = dispatchInterfaceTypeFor(method);
+ appView.rewritePrefix.rewriteType(dispatchInterfaceType, dispatchInterfaceType);
+ DexType dispatchHolderType = dispatchHolderTypeFor(method);
+ appView.rewritePrefix.rewriteType(dispatchHolderType, dispatchHolderType);
+ }
+ }
+ }
+
+ public void synthesizeRetargetClasses(
+ DexApplication.Builder<?> builder, ExecutorService executorService, IRConverter converter)
+ throws ExecutionException {
+ new EmulatedDispatchTreeFixer().fixApp(builder, executorService, converter);
+ }
+
+ // The rewrite of virtual calls requires to go through emulate dispatch. This class is responsible
+ // for inserting interfaces on library boundaries and forwarding methods in the program, and to
+ // synthesize the interfaces and emulated dispatch classes in the desugared library.
+ class EmulatedDispatchTreeFixer {
+
+ void fixApp(
+ DexApplication.Builder<?> builder, ExecutorService executorService, IRConverter converter)
+ throws ExecutionException {
+ if (appView.options().isDesugaredLibraryCompilation()) {
+ synthesizeEmulatedDispatchMethods(builder);
+ } else {
+ addInterfacesAndForwardingMethods(executorService, converter);
+ }
+ }
+
+ private void addInterfacesAndForwardingMethods(
+ ExecutorService executorService, IRConverter converter) throws ExecutionException {
+ assert !appView.options().isDesugaredLibraryCompilation();
+ Map<DexType, List<DexMethod>> map = Maps.newIdentityHashMap();
+ for (DexMethod emulatedDispatchMethod : emulatedDispatchMethods) {
+ map.putIfAbsent(emulatedDispatchMethod.holder, new ArrayList<>(1));
+ map.get(emulatedDispatchMethod.holder).add(emulatedDispatchMethod);
+ }
+ List<DexEncodedMethod> addedMethods = new ArrayList<>();
+ for (DexProgramClass clazz : appView.appInfo().classes()) {
+ if (clazz.superType == null) {
+ assert clazz.type == appView.dexItemFactory().objectType : clazz.type.toSourceString();
+ continue;
+ }
+ DexClass dexClass = appView.definitionFor(clazz.superType);
+ // Only performs computation if superclass is a library class, but not object to filter out
+ // the most common case.
+ if (dexClass != null
+ && dexClass.isLibraryClass()
+ && dexClass.type != appView.dexItemFactory().objectType) {
+ for (DexType dexType : map.keySet()) {
+ if (inherit(dexClass.asLibraryClass(), dexType)) {
+ addedMethods.addAll(addInterfacesAndForwardingMethods(clazz, map.get(dexType)));
+ }
+ }
+ }
+ }
+ if (addedMethods.isEmpty()) {
+ return;
+ }
+ converter.processMethodsConcurrently(addedMethods, executorService);
+ }
+
+ private boolean inherit(DexLibraryClass clazz, DexType typeToInherit) {
+ DexLibraryClass current = clazz;
+ while (current.type != appView.dexItemFactory().objectType) {
+ if (current.type == typeToInherit) {
+ return true;
+ }
+ current = appView.definitionFor(current.superType).asLibraryClass();
+ }
+ return false;
+ }
+
+ private List<DexEncodedMethod> addInterfacesAndForwardingMethods(
+ DexProgramClass clazz, List<DexMethod> dexMethods) {
+ // DesugaredLibraryRetargeter emulate dispatch: insertion of a marker interface & forwarding
+ // methods.
+ // We cannot use the ClassProcessor since this applies up to 26, while the ClassProcessor
+ // applies up to 24.
+ List<DexEncodedMethod> newForwardingMethods = new ArrayList<>();
+ for (DexMethod dexMethod : dexMethods) {
+ DexType[] newInterfaces =
+ Arrays.copyOf(clazz.interfaces.values, clazz.interfaces.size() + 1);
+ newInterfaces[newInterfaces.length - 1] = dispatchInterfaceTypeFor(dexMethod);
+ clazz.interfaces = new DexTypeList(newInterfaces);
+ DexEncodedMethod dexEncodedMethod = clazz.lookupVirtualMethod(dexMethod);
+ if (dexEncodedMethod == null) {
+ DexEncodedMethod newMethod = createForwardingMethod(dexMethod, clazz);
+ clazz.addVirtualMethod(newMethod);
+ newForwardingMethods.add(newMethod);
+ }
+ }
+ return newForwardingMethods;
+ }
+
+ private DexEncodedMethod createForwardingMethod(DexMethod target, DexClass clazz) {
+ // NOTE: Never add a forwarding method to methods of classes unknown or coming from
+ // android.jar
+ // even if this results in invalid code, these classes are never desugared.
+ // In desugared library, emulated interface methods can be overridden by retarget lib members.
+ DexMethod forwardMethod =
+ appView.options().desugaredLibraryConfiguration.retargetMethod(target, appView);
+ assert forwardMethod != null && forwardMethod != target;
+ return DexEncodedMethod.createDesugaringForwardingMethod(
+ appView.definitionFor(target), clazz, forwardMethod, appView.dexItemFactory());
+ }
+
+ private void synthesizeEmulatedDispatchMethods(DexApplication.Builder<?> builder) {
+ assert appView.options().isDesugaredLibraryCompilation();
+ if (emulatedDispatchMethods.isEmpty()) {
+ return;
+ }
+ ClassAccessFlags itfAccessFlags =
+ ClassAccessFlags.fromSharedAccessFlags(
+ Constants.ACC_PUBLIC
+ | Constants.ACC_SYNTHETIC
+ | Constants.ACC_ABSTRACT
+ | Constants.ACC_INTERFACE);
+ ClassAccessFlags holderAccessFlags =
+ ClassAccessFlags.fromSharedAccessFlags(Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC);
+ for (DexMethod emulatedDispatchMethod : emulatedDispatchMethods) {
+ // Dispatch interface.
+ DexType interfaceType = dispatchInterfaceTypeFor(emulatedDispatchMethod);
+ DexEncodedMethod itfMethod =
+ generateInterfaceDispatchMethod(emulatedDispatchMethod, interfaceType);
+ BackportedMethodRewriter.synthesizeClassWithUniqueMethod(
+ builder,
+ itfAccessFlags,
+ interfaceType,
+ itfMethod,
+ "desugared library dispatch interface",
+ false,
+ appView);
+ // Dispatch holder.
+ DexType holderType = dispatchHolderTypeFor(emulatedDispatchMethod);
+ DexEncodedMethod dispatchMethod =
+ generateHolderDispatchMethod(emulatedDispatchMethod, holderType, itfMethod.method);
+ BackportedMethodRewriter.synthesizeClassWithUniqueMethod(
+ builder,
+ holderAccessFlags,
+ holderType,
+ dispatchMethod,
+ "desugared library dispatch class",
+ false,
+ appView);
+ }
+ }
+
+ private DexEncodedMethod generateInterfaceDispatchMethod(
+ DexMethod emulatedDispatchMethod, DexType interfaceType) {
+ MethodAccessFlags flags =
+ MethodAccessFlags.fromSharedAccessFlags(
+ Constants.ACC_PUBLIC | Constants.ACC_ABSTRACT | Constants.ACC_SYNTHETIC, false);
+ DexMethod newMethod =
+ appView
+ .dexItemFactory()
+ .createMethod(
+ interfaceType, emulatedDispatchMethod.proto, emulatedDispatchMethod.name);
+ return new DexEncodedMethod(
+ newMethod, flags, DexAnnotationSet.empty(), ParameterAnnotationsList.empty(), null, true);
+ }
+
+ private DexEncodedMethod generateHolderDispatchMethod(
+ DexMethod emulatedDispatchMethod, DexType dispatchHolder, DexMethod itfMethod) {
+ // The method should look like:
+ // static foo(rcvr, arg0, arg1) {
+ // if (rcvr instanceof interfaceType) {
+ // return invoke-interface receiver.foo(arg0, arg1);
+ // } else {
+ // return DesugarX.foo(rcvr, arg0, arg1)
+ // }
+ // We do not deal with complex cases (multiple retargeting of the same signature in the
+ // same inheritance tree, etc., since they do not happen in the most common desugared library.
+ DexMethod desugarMethod =
+ appView
+ .options()
+ .desugaredLibraryConfiguration
+ .retargetMethod(emulatedDispatchMethod, appView);
+ assert desugarMethod != null; // This method is reached only for retarget core lib members.
+ DexMethod newMethod =
+ appView
+ .dexItemFactory()
+ .createMethod(dispatchHolder, desugarMethod.proto, emulatedDispatchMethod.name);
+ return DexEncodedMethod.toEmulateDispatchLibraryMethod(
+ emulatedDispatchMethod.holder,
+ newMethod,
+ desugarMethod,
+ itfMethod,
+ Collections.emptyList(),
+ appView);
+ }
+ }
+
+ private DexType dispatchInterfaceTypeFor(DexMethod method) {
+ return dispatchTypeFor(method, "dispatchInterface");
+ }
+
+ private DexType dispatchHolderTypeFor(DexMethod method) {
+ return dispatchTypeFor(method, "dispatchHolder");
+ }
+
+ private DexType dispatchTypeFor(DexMethod method, String suffix) {
+ String descriptor =
+ "L"
+ + appView
+ .options()
+ .desugaredLibraryConfiguration
+ .getSynthesizedLibraryClassesPackagePrefix()
+ + DESUGAR_LIB_RETARGET_CLASS_NAME_PREFIX
+ + '$'
+ + method.holder.getName()
+ + '$'
+ + method.name
+ + '$'
+ + suffix
+ + ';';
+ return appView.dexItemFactory().createType(descriptor);
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryWrapperSynthesizer.java b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryWrapperSynthesizer.java
index 3527f62..30bc78e 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryWrapperSynthesizer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryWrapperSynthesizer.java
@@ -144,14 +144,9 @@
}
private DexType createWrapperType(DexType type, String suffix) {
- String desugaredLibPrefix =
- appView
- .options()
- .desugaredLibraryConfiguration
- .getSynthesizedLibraryClassesPackagePrefix(appView);
return factory.createType(
"L"
- + desugaredLibPrefix
+ + appView.options().synthesizedClassPrefix
+ WRAPPER_PREFIX
+ type.toString().replace('.', '$')
+ suffix
@@ -511,52 +506,33 @@
void finalizeWrappersForD8(
DexApplication.Builder<?> builder, IRConverter irConverter, ExecutorService executorService)
throws ExecutionException {
- Map<DexType, DexProgramClass> synthesizedWrappers = synthesizeWrappers();
- registerAndProcessWrappers(builder, irConverter, executorService, synthesizedWrappers.values());
+ List<DexProgramClass> synthesizedWrappers = synthesizeWrappers(new IdentityHashMap<>());
+ registerAndProcessWrappers(builder, irConverter, executorService, synthesizedWrappers);
}
- private Map<DexType, DexProgramClass> synthesizeWrappers() {
- Map<DexType, DexProgramClass> synthesizedWrappers = new IdentityHashMap<>();
+ List<DexProgramClass> synthesizeWrappers(Map<DexType, DexProgramClass> synthesizedWrappers) {
+ List<DexProgramClass> additions = new ArrayList<>();
// Generating a wrapper may require other wrappers to be generated, iterate until fix point.
while (synthesizedWrappers.size() != typeWrappers.size() + vivifiedTypeWrappers.size()) {
for (DexType type : typeWrappers.keySet()) {
DexType typeWrapperType = typeWrappers.get(type);
if (!synthesizedWrappers.containsKey(typeWrapperType)) {
- synthesizedWrappers.put(
- typeWrapperType, generateTypeWrapper(getValidClassToWrap(type), typeWrapperType));
+ DexProgramClass wrapper = generateTypeWrapper(getValidClassToWrap(type), typeWrapperType);
+ synthesizedWrappers.put(typeWrapperType, wrapper);
+ additions.add(wrapper);
}
}
for (DexType type : vivifiedTypeWrappers.keySet()) {
DexType vivifiedTypeWrapperType = vivifiedTypeWrappers.get(type);
if (!synthesizedWrappers.containsKey(vivifiedTypeWrapperType)) {
- synthesizedWrappers.put(
- vivifiedTypeWrapperType,
- generateVivifiedTypeWrapper(getValidClassToWrap(type), vivifiedTypeWrapperType));
+ DexProgramClass wrapper =
+ generateVivifiedTypeWrapper(getValidClassToWrap(type), vivifiedTypeWrapperType);
+ synthesizedWrappers.put(vivifiedTypeWrapperType, wrapper);
+ additions.add(wrapper);
}
}
}
- return synthesizedWrappers;
- }
-
- private Map<DexType, DexType> reverseWrapperMap() {
- Map<DexType, DexType> reverseWrapperMap = new IdentityHashMap<>();
- for (DexType type : typeWrappers.keySet()) {
- reverseWrapperMap.put(typeWrappers.get(type), vivifiedTypeWrappers.get(type));
- }
- for (DexType type : vivifiedTypeWrappers.keySet()) {
- reverseWrapperMap.put(vivifiedTypeWrappers.get(type), typeWrappers.get(type));
- }
- return reverseWrapperMap;
- }
-
- Map<DexProgramClass, DexProgramClass> synthesizeWrappersAndMapToReverse() {
- Map<DexType, DexProgramClass> synthesizedWrappers = synthesizeWrappers();
- Map<DexType, DexType> reverseMap = reverseWrapperMap();
- Map<DexProgramClass, DexProgramClass> wrappersAndReverse = new IdentityHashMap<>();
- for (DexProgramClass wrapper : synthesizedWrappers.values()) {
- wrappersAndReverse.put(wrapper, synthesizedWrappers.get(reverseMap.get(wrapper.type)));
- }
- return wrappersAndReverse;
+ return additions;
}
private void registerAndProcessWrappers(
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
index 403f2f0..1a4c416 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
@@ -196,9 +196,9 @@
DexCallSite callSite = instruction.asInvokeCustom().getCallSite();
reportStaticInterfaceMethodHandle(encodedMethod.method, callSite.bootstrapMethod);
for (DexValue arg : callSite.bootstrapArgs) {
- if (arg instanceof DexValue.DexValueMethodHandle) {
- reportStaticInterfaceMethodHandle(encodedMethod.method,
- ((DexValue.DexValueMethodHandle) arg).value);
+ if (arg.isDexValueMethodHandle()) {
+ reportStaticInterfaceMethodHandle(
+ encodedMethod.method, arg.asDexValueMethodHandle().value);
}
}
continue;
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
index ec1b05f..87c3424 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
@@ -667,14 +667,14 @@
// For all instantiation points for which the compiler creates lambda$
// methods, it creates these methods in the same class/interface.
DexMethod implMethod = descriptor.implHandle.asMethod();
- DexClass implMethodHolder = definitionFor(implMethod.holder);
+ DexProgramClass implMethodHolder = definitionFor(implMethod.holder).asProgramClass();
return allowMethodModification
? modifyLambdaImplementationMethod(implMethod, implMethodHolder)
: createSyntheticAccessor(implMethod, implMethodHolder);
}
private DexEncodedMethod modifyLambdaImplementationMethod(
- DexMethod implMethod, DexClass implMethodHolder) {
+ DexMethod implMethod, DexProgramClass implMethodHolder) {
return implMethodHolder
.getMethodCollection()
.replaceDirectMethodWithVirtualMethod(
@@ -701,7 +701,7 @@
}
private DexEncodedMethod createSyntheticAccessor(
- DexMethod implMethod, DexClass implMethodHolder) {
+ DexMethod implMethod, DexProgramClass implMethodHolder) {
MethodAccessFlags accessorFlags =
MethodAccessFlags.fromSharedAccessFlags(
Constants.ACC_SYNTHETIC | Constants.ACC_PUBLIC, false);
@@ -725,7 +725,7 @@
registry -> registry.registerInvokeDirect(implMethod)),
true);
- implMethodHolder.appendVirtualMethod(accessorEncodedMethod);
+ implMethodHolder.addVirtualMethod(accessorEncodedMethod);
return accessorEncodedMethod;
}
}
@@ -761,7 +761,7 @@
// We may arrive here concurrently so we need must update the methods of the class atomically.
synchronized (accessorClass) {
- accessorClass.appendDirectMethod(accessorEncodedMethod);
+ accessorClass.addDirectMethod(accessorEncodedMethod);
}
return accessorEncodedMethod;
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java
index 770f170..4ee35d6 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java
@@ -17,7 +17,7 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.type.Nullability;
import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
@@ -323,8 +323,7 @@
// The out value might be empty in case it was optimized out.
lambdaInstanceValue =
code.createValue(
- TypeLatticeElement.fromDexType(
- lambdaClass.type, Nullability.maybeNull(), getAppView()));
+ TypeElement.fromDexType(lambdaClass.type, Nullability.maybeNull(), getAppView()));
} else {
affectedValues.add(lambdaInstanceValue);
}
@@ -352,8 +351,8 @@
// result:
// NewInstance rResult <- LambdaClass
// Invoke-Direct { rResult, rArg0, rArg1, ... }; method: void LambdaClass.<init>(...)
- lambdaInstanceValue.setTypeLattice(
- lambdaInstanceValue.getTypeLattice().asReferenceTypeLatticeElement().asDefinitelyNotNull());
+ lambdaInstanceValue.setType(
+ lambdaInstanceValue.getType().asReferenceType().asDefinitelyNotNull());
NewInstance newInstance = new NewInstance(lambdaClass.type, lambdaInstanceValue);
instructions.replaceCurrentInstruction(newInstance);
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/StringConcatRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/StringConcatRewriter.java
index 834a492..4b33d2f 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/StringConcatRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/StringConcatRewriter.java
@@ -15,7 +15,8 @@
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DexValue;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.graph.DexValue.DexValueString;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.BasicBlock.ThrowingInfo;
import com.android.tools.r8.ir.code.ConstString;
@@ -212,11 +213,11 @@
}
// Extract recipe.
- DexValue recipeValue = bootstrapArgs.get(0);
- if (!(recipeValue instanceof DexValue.DexValueString)) {
+ DexValueString recipeValue = bootstrapArgs.get(0).asDexValueString();
+ if (recipeValue == null) {
throw error(method, "bootstrap method argument `recipe` must be a string");
}
- String recipe = ((DexValue.DexValueString) recipeValue).getValue().toString();
+ String recipe = recipeValue.getValue().toString();
// Collect chunks and patch the instruction.
ConcatBuilder builder = new ConcatBuilder(appView, code, blocks, instructions);
@@ -273,8 +274,8 @@
}
private static String convertToString(DexMethod method, DexValue value) {
- if (value instanceof DexValue.DexValueString) {
- return ((DexValue.DexValueString) value).getValue().toString();
+ if (value.isDexValueString()) {
+ return value.asDexValueString().getValue().toString();
}
throw error(method,
"const arg referenced from `recipe` is not supported: " + value.getClass().getName());
@@ -338,8 +339,8 @@
instructions.previous();
// new-instance v0, StringBuilder
- TypeLatticeElement stringBuilderTypeLattice =
- TypeLatticeElement.fromDexType(factory.stringBuilderType, definitelyNotNull(), appView);
+ TypeElement stringBuilderTypeLattice =
+ TypeElement.fromDexType(factory.stringBuilderType, definitelyNotNull(), appView);
Value sbInstance = code.createValue(stringBuilderTypeLattice);
appendInstruction(new NewInstance(factory.stringBuilderType, sbInstance));
@@ -361,8 +362,7 @@
Value concatValue = invokeCustom.outValue();
if (concatValue == null) {
// The out value might be empty in case it was optimized out.
- concatValue =
- code.createValue(TypeLatticeElement.stringClassType(appView, definitelyNotNull()));
+ concatValue = code.createValue(TypeElement.stringClassType(appView, definitelyNotNull()));
}
// Replace the instruction.
@@ -440,8 +440,7 @@
@Override
Value getOrCreateValue() {
- Value value =
- code.createValue(TypeLatticeElement.stringClassType(appView, definitelyNotNull()));
+ Value value = code.createValue(TypeElement.stringClassType(appView, definitelyNotNull()));
appendInstruction(
new ConstString(
value,
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/AliasIntroducer.java b/src/main/java/com/android/tools/r8/ir/optimize/AliasIntroducer.java
index cc97597..7219eb0 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/AliasIntroducer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/AliasIntroducer.java
@@ -46,15 +46,14 @@
}
Value outValue = current.outValue();
// TODO(b/129859039): We may need similar concept when adding/testing assume-range
- if (outValue.getTypeLattice().isPrimitive()
- || outValue.getTypeLattice().isNullType()) {
+ if (outValue.getType().isPrimitiveType() || outValue.getType().isNullType()) {
continue;
}
// Split block if needed
BasicBlock insertionBlock =
block.hasCatchHandlers() ? instructionIterator.split(code, blockIterator) : block;
// Replace usages of out-value by the out-value of the AssumeNone instruction.
- Value aliasedValue = code.createValue(outValue.getTypeLattice(), outValue.getLocalInfo());
+ Value aliasedValue = code.createValue(outValue.getType(), outValue.getLocalInfo());
outValue.replaceUsers(aliasedValue);
// Insert AssumeNone instruction.
Assume<NoAssumption> assumeNone =
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/AssumeDynamicTypeRemover.java b/src/main/java/com/android/tools/r8/ir/optimize/AssumeDynamicTypeRemover.java
index 6bb9b03..9102f53 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/AssumeDynamicTypeRemover.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/AssumeDynamicTypeRemover.java
@@ -68,7 +68,7 @@
Value outValue = assumeDynamicTypeInstruction.outValue();
// Check if we need to run the type analysis for the affected values of the out-value.
- if (!outValue.getTypeLattice().equals(inValue.getTypeLattice())) {
+ if (!outValue.getType().equals(inValue.getType())) {
affectedValues.addAll(outValue.affectedValues());
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CallSiteOptimizationInfoPropagator.java b/src/main/java/com/android/tools/r8/ir/optimize/CallSiteOptimizationInfoPropagator.java
index 627aec5..368b58a 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CallSiteOptimizationInfoPropagator.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CallSiteOptimizationInfoPropagator.java
@@ -9,7 +9,7 @@
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.analysis.value.SingleValue;
import com.android.tools.r8.ir.code.Assume;
@@ -223,7 +223,7 @@
}
argumentsSeen++;
Value originalArg = instr.asArgument().outValue();
- if (originalArg.hasLocalInfo() || !originalArg.getTypeLattice().isReference()) {
+ if (originalArg.hasLocalInfo() || !originalArg.getType().isReferenceType()) {
continue;
}
int argIndex = argumentsSeen - 1;
@@ -241,7 +241,7 @@
continue;
}
}
- TypeLatticeElement dynamicUpperBoundType =
+ TypeElement dynamicUpperBoundType =
callSiteOptimizationInfo.getDynamicUpperBoundType(argIndex);
if (dynamicUpperBoundType == null) {
continue;
@@ -255,8 +255,8 @@
continue;
}
Value specializedArg;
- if (dynamicUpperBoundType.strictlyLessThan(originalArg.getTypeLattice(), appView)) {
- specializedArg = code.createValue(originalArg.getTypeLattice());
+ if (dynamicUpperBoundType.strictlyLessThan(originalArg.getType(), appView)) {
+ specializedArg = code.createValue(originalArg.getType());
affectedValues.addAll(originalArg.affectedValues());
originalArg.replaceUsers(specializedArg);
Assume<DynamicTypeAssumption> assumeType =
@@ -267,12 +267,12 @@
} else {
specializedArg = originalArg;
}
- assert specializedArg != null && specializedArg.getTypeLattice().isReference();
+ assert specializedArg != null && specializedArg.getType().isReferenceType();
if (dynamicUpperBoundType.isDefinitelyNotNull()) {
// If we already knew `arg` is never null, e.g., receiver, skip adding non-null.
- if (!specializedArg.getTypeLattice().isDefinitelyNotNull()) {
- Value nonNullArg = code.createValue(
- specializedArg.getTypeLattice().asReferenceTypeLatticeElement().asMeetWithNotNull());
+ if (!specializedArg.getType().isDefinitelyNotNull()) {
+ Value nonNullArg =
+ code.createValue(specializedArg.getType().asReferenceType().asMeetWithNotNull());
affectedValues.addAll(specializedArg.affectedValues());
specializedArg.replaceUsers(nonNullArg);
Assume<NonNullAssumption> assumeNotNull =
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java b/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java
index 1e02c2b..025c178 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java
@@ -30,7 +30,7 @@
import com.android.tools.r8.graph.DexValue.DexValueShort;
import com.android.tools.r8.graph.DexValue.DexValueString;
import com.android.tools.r8.ir.analysis.ValueMayDependOnEnvironmentAnalysis;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.ArrayPut;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.ConstNumber;
@@ -395,7 +395,7 @@
}
DexField field = put.getField();
Value value = put.value();
- TypeLatticeElement valueType = value.getTypeLattice();
+ TypeElement valueType = value.getType();
if (clazz.definesStaticField(field)) {
if (isReadBefore.contains(field)) {
// Promoting this put to a class constant would cause a previous static-get
@@ -439,7 +439,7 @@
isWrittenBefore.remove(field);
}
continue;
- } else if (valueType.isReference() && valueType.isDefinitelyNotNull()) {
+ } else if (valueType.isReferenceType() && valueType.isDefinitelyNotNull()) {
finalFieldPuts.put(field, put);
continue;
}
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 f7755d4..5b78d8a 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
@@ -25,7 +25,7 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.equivalence.BasicBlockBehavioralSubsumption;
import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.code.AlwaysMaterializingNop;
import com.android.tools.r8.ir.code.ArrayLength;
@@ -260,8 +260,8 @@
}
Value value = ifInstruction.lhs();
- if (!value.getTypeLattice().isReference()) {
- assert value.getTypeLattice().isPrimitive();
+ if (!value.getType().isReferenceType()) {
+ assert value.getType().isPrimitiveType();
continue;
}
@@ -1186,12 +1186,10 @@
private boolean checkArgumentType(InvokeMethod invoke, int argumentIndex) {
// TODO(sgjesse): Insert cast if required.
- TypeLatticeElement returnType =
- TypeLatticeElement.fromDexType(
- invoke.getInvokedMethod().proto.returnType, maybeNull(), appView);
- TypeLatticeElement argumentType =
- TypeLatticeElement.fromDexType(
- getArgumentType(invoke, argumentIndex), maybeNull(), appView);
+ TypeElement returnType =
+ TypeElement.fromDexType(invoke.getInvokedMethod().proto.returnType, maybeNull(), appView);
+ TypeElement argumentType =
+ TypeElement.fromDexType(getArgumentType(invoke, argumentIndex), maybeNull(), appView);
return appView.enableWholeProgramOptimizations()
? argumentType.lessThanOrEqual(returnType, appView)
: argumentType.equals(returnType);
@@ -1244,7 +1242,7 @@
// Make sure that we are only narrowing information here. Note, in cases where
// we cannot find the definition of types, computing lessThanOrEqual will
// return false unless it is object.
- if (argument.getTypeLattice().lessThanOrEqual(outValue.getTypeLattice(), appView)) {
+ if (argument.getType().lessThanOrEqual(outValue.getType(), appView)) {
affectedValues.addAll(outValue.affectedValues());
assumeDynamicTypeRemover.markUsersForRemoval(outValue);
mayHaveRemovedTrivialPhi |= outValue.numberOfPhiUsers() > 0;
@@ -1362,17 +1360,17 @@
// If the in-value is `null` and the cast-type is a float-array type, then trivial check-cast
// elimination may lead to verification errors. See b/123269162.
if (options.canHaveArtCheckCastVerifierBug()) {
- if (inValue.getTypeLattice().isNullType()
+ if (inValue.getType().isNullType()
&& castType.isArrayType()
&& castType.toBaseType(dexItemFactory).isFloatType()) {
return RemoveCheckCastInstructionIfTrivialResult.NO_REMOVALS;
}
}
- TypeLatticeElement inTypeLattice = inValue.getTypeLattice();
- TypeLatticeElement outTypeLattice = outValue.getTypeLattice();
- TypeLatticeElement castTypeLattice =
- TypeLatticeElement.fromDexType(castType, inTypeLattice.nullability(), appView);
+ TypeElement inTypeLattice = inValue.getType();
+ TypeElement outTypeLattice = outValue.getType();
+ TypeElement castTypeLattice =
+ TypeElement.fromDexType(castType, inTypeLattice.nullability(), appView);
assert inTypeLattice.nullability().lessThanOrEqual(outTypeLattice.nullability());
@@ -1417,9 +1415,9 @@
}
Value inValue = instanceOf.value();
- TypeLatticeElement inType = inValue.getTypeLattice();
- TypeLatticeElement instanceOfType =
- TypeLatticeElement.fromDexType(instanceOf.type(), inType.nullability(), appView);
+ TypeElement inType = inValue.getType();
+ TypeElement instanceOfType =
+ TypeElement.fromDexType(instanceOf.type(), inType.nullability(), appView);
Value aliasValue = inValue.getAliasedValue();
InstanceOfResult result = InstanceOfResult.UNKNOWN;
@@ -1442,8 +1440,7 @@
if (result == InstanceOfResult.UNKNOWN) {
if (inType.isClassType()
- && isNeverInstantiatedDirectlyOrIndirectly(
- inType.asClassTypeLatticeElement().getClassType())) {
+ && isNeverInstantiatedDirectlyOrIndirectly(inType.asClassType().getClassType())) {
// The type of the in-value is a program class, and is never instantiated directly or
// indirectly. This, the in-value must be null, meaning that the instance-of instruction
// will always evaluate to false.
@@ -1456,7 +1453,7 @@
inValue.getSpecificAliasedValue(
value -> !value.isPhi() && value.definition.isAssumeDynamicType());
if (aliasedValue != null) {
- TypeLatticeElement dynamicType =
+ TypeElement dynamicType =
aliasedValue
.definition
.asAssumeDynamicType()
@@ -1476,7 +1473,7 @@
new ConstNumber(
new Value(
code.valueNumberGenerator.next(),
- TypeLatticeElement.getInt(),
+ TypeElement.getInt(),
instanceOf.outValue().getLocalInfo()),
result == InstanceOfResult.TRUE ? 1 : 0);
it.replaceCurrentInstruction(newInstruction);
@@ -2053,8 +2050,8 @@
for (ConstInstruction value : values) {
stringValues.add(value.outValue());
}
- Value invokeValue = code.createValue(
- newArray.outValue().getTypeLattice(), newArray.getLocalInfo());
+ Value invokeValue =
+ code.createValue(newArray.outValue().getType(), newArray.getLocalInfo());
InvokeNewArray invoke =
new InvokeNewArray(dexItemFactory.stringArrayType, invokeValue, stringValues);
for (Value value : newArray.inValues()) {
@@ -2462,11 +2459,11 @@
} else if (theIf.getType() == Type.EQ || theIf.getType() == Type.NE) {
if (theIf.isZeroTest()) {
if (!lhs.isConstNumber()) {
- TypeLatticeElement l = lhs.getTypeLattice();
- if (l.isReference() && lhs.isNeverNull()) {
+ TypeElement l = lhs.getType();
+ if (l.isReferenceType() && lhs.isNeverNull()) {
simplifyIfWithKnownCondition(code, block, theIf, 1);
} else {
- if (!l.isPrimitive() && !l.isNullable()) {
+ if (!l.isPrimitiveType() && !l.isNullable()) {
simplifyIfWithKnownCondition(code, block, theIf, 1);
}
}
@@ -2721,12 +2718,12 @@
}
if (dominatorTree.get().dominatedBy(block, dominator)) {
- if (newValue.getTypeLattice().lessThanOrEqual(value.getTypeLattice(), appView)) {
+ if (newValue.getType().lessThanOrEqual(value.getType(), appView)) {
value.replaceUsers(newValue);
block.listIterator(code, constNumber).removeOrReplaceByDebugLocalRead();
constantWithValueIterator.remove();
changed = true;
- } else if (value.getTypeLattice().isNullType()) {
+ } else if (value.getType().isNullType()) {
// TODO(b/120257211): Need a mechanism to determine if `newValue` can be used at all of
// the use sites of `value` without introducing a type error.
}
@@ -2875,7 +2872,7 @@
(theIf.getType() == Type.EQ &&
trueNumber.isIntegerOne() &&
falseNumber.isIntegerZero())) {
- Value newOutValue = code.createValue(phi.getTypeLattice(), phi.getLocalInfo());
+ Value newOutValue = code.createValue(phi.getType(), phi.getLocalInfo());
ConstNumber cstToUse = trueNumber.isIntegerOne() ? trueNumber : falseNumber;
BasicBlock phiBlock = phi.getBlock();
Position phiPosition = phiBlock.getPosition();
@@ -3107,7 +3104,7 @@
new InvokeVirtual(
dexItemFactory.throwableMethods.initCause,
code.createValue(
- TypeLatticeElement.fromDexType(
+ TypeElement.fromDexType(
dexItemFactory.throwableType, maybeNull(), appView)),
initCauseArguments);
initCause.setPosition(current.getPosition());
@@ -3316,8 +3313,7 @@
}
private Value addConstString(IRCode code, InstructionListIterator iterator, String s) {
- TypeLatticeElement typeLattice =
- TypeLatticeElement.stringClassType(appView, definitelyNotNull());
+ TypeElement typeLattice = TypeElement.stringClassType(appView, definitelyNotNull());
Value value = code.createValue(typeLattice);
ThrowingInfo throwingInfo =
options.isGeneratingClassFiles() ? ThrowingInfo.NO_THROW : ThrowingInfo.CAN_THROW;
@@ -3351,7 +3347,7 @@
DexType javaIoPrintStreamType = dexItemFactory.javaIoPrintStreamType;
Value out =
code.createValue(
- TypeLatticeElement.fromDexType(javaIoPrintStreamType, definitelyNotNull(), appView));
+ TypeElement.fromDexType(javaIoPrintStreamType, definitelyNotNull(), appView));
DexProto proto = dexItemFactory.createProto(dexItemFactory.voidType, dexItemFactory.objectType);
DexMethod print = dexItemFactory.createMethod(javaIoPrintStreamType, proto, "print");
@@ -3388,7 +3384,7 @@
eol.link(successor);
Value argument = arguments.get(i);
- if (!argument.getTypeLattice().isReference()) {
+ if (!argument.getType().isReferenceType()) {
iterator.add(new InvokeVirtual(print, null, ImmutableList.of(out, primitive)));
} else {
// Insert "if (argument != null) ...".
@@ -3418,7 +3414,7 @@
iterator.add(new InvokeVirtual(print, null, ImmutableList.of(out, nul)));
iterator = isNotNullBlock.listIterator(code);
iterator.setInsertionPosition(position);
- value = code.createValue(TypeLatticeElement.classClassType(appView, definitelyNotNull()));
+ value = code.createValue(TypeElement.classClassType(appView, definitelyNotNull()));
iterator.add(
new InvokeVirtual(
dexItemFactory.objectMembers.getClass, value, ImmutableList.of(arguments.get(i))));
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java b/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java
index 463bfce..d225220 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/DefaultInliningOracle.java
@@ -250,7 +250,7 @@
for (int index = 0; index < arguments.size(); index++) {
Value argument = arguments.get(index);
if ((argument.isArgument()
- || (argument.getTypeLattice().isReference() && argument.isNeverNull()))
+ || (argument.getType().isReferenceType() && argument.isNeverNull()))
&& hints.get(index)) {
// 5-4 instructions per parameter check are expected to be removed.
instructionLimit += 4;
@@ -304,15 +304,15 @@
Reason reason,
WhyAreYouNotInliningReporter whyAreYouNotInliningReporter) {
Value receiver = invoke.getReceiver();
- if (receiver.getTypeLattice().isDefinitelyNull()) {
+ if (receiver.getType().isDefinitelyNull()) {
// A definitely null receiver will throw an error on call site.
whyAreYouNotInliningReporter.reportReceiverDefinitelyNull();
return null;
}
InlineAction action = new InlineAction(singleTarget, invoke, reason);
- if (receiver.getTypeLattice().isNullable()) {
- assert !receiver.getTypeLattice().isDefinitelyNull();
+ if (receiver.getType().isNullable()) {
+ assert !receiver.getType().isDefinitelyNull();
// When inlining an instance method call, we need to preserve the null check for the
// receiver. Therefore, if the receiver may be null and the candidate inlinee does not
// throw if the receiver is null before any other side effect, then we must synthesize a
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java b/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java
index 0c53a4c..82ea8ab 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java
@@ -10,7 +10,7 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.Assume;
import com.android.tools.r8.ir.code.Assume.NonNullAssumption;
import com.android.tools.r8.ir.code.BasicBlock;
@@ -101,8 +101,8 @@
// the out-value of the cast instruction is a more precise type than the in-value,
// otherwise we could introduce type errors.
Value oldReceiver = newCheckCast.object();
- TypeLatticeElement oldReceiverType = oldReceiver.getTypeLattice();
- TypeLatticeElement newReceiverType = newReceiver.getTypeLattice();
+ TypeElement oldReceiverType = oldReceiver.getType();
+ TypeElement newReceiverType = newReceiver.getType();
if (newReceiverType.lessThanOrEqual(oldReceiverType, appView)
&& dominatorTree.dominatedBy(block, devirtualizedInvoke.getBlock())) {
assert nonNull.src() == oldReceiver;
@@ -166,10 +166,9 @@
// (out <-) invoke-virtual a, ... A#foo
if (holderType != invoke.getInvokedMethod().holder) {
Value receiver = invoke.getReceiver();
- TypeLatticeElement receiverTypeLattice = receiver.getTypeLattice();
- TypeLatticeElement castTypeLattice =
- TypeLatticeElement.fromDexType(
- holderType, receiverTypeLattice.nullability(), appView);
+ TypeElement receiverTypeLattice = receiver.getType();
+ TypeElement castTypeLattice =
+ TypeElement.fromDexType(holderType, receiverTypeLattice.nullability(), appView);
// Avoid adding trivial cast and up-cast.
// We should not use strictlyLessThan(castType, receiverType), which detects downcast,
// due to side-casts, e.g., A (unused) < I, B < I, and cast from A to B.
@@ -262,7 +261,7 @@
*/
private DexMethod rebindVirtualInvokeToMostSpecific(
DexMethod target, Value receiver, DexType context) {
- if (!receiver.getTypeLattice().isClassType()) {
+ if (!receiver.getType().isClassType()) {
return target;
}
DexEncodedMethod encodedTarget = appView.definitionFor(target);
@@ -273,9 +272,7 @@
return target;
}
DexType receiverType =
- appView
- .graphLense()
- .lookupType(receiver.getTypeLattice().asClassTypeLatticeElement().getClassType());
+ appView.graphLense().lookupType(receiver.getType().asClassType().getClassType());
if (receiverType == target.holder) {
// Virtual invoke is already as specific as it can get.
return target;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/DynamicTypeOptimization.java b/src/main/java/com/android/tools/r8/ir/optimize/DynamicTypeOptimization.java
index 0a314aa..8048e3a 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/DynamicTypeOptimization.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/DynamicTypeOptimization.java
@@ -11,8 +11,8 @@
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.Assume;
import com.android.tools.r8.ir.code.Assume.DynamicTypeAssumption;
import com.android.tools.r8.ir.code.BasicBlock;
@@ -61,8 +61,8 @@
continue;
}
- TypeLatticeElement dynamicUpperBoundType;
- ClassTypeLatticeElement dynamicLowerBoundType;
+ TypeElement dynamicUpperBoundType;
+ ClassTypeElement dynamicLowerBoundType;
if (current.isInvokeMethod()) {
InvokeMethod invoke = current.asInvokeMethod();
DexMethod invokedMethod = invoke.getInvokedMethod();
@@ -75,7 +75,7 @@
if (invokedMethod.holder.isArrayType()
&& invokedMethod.match(appView.dexItemFactory().objectMembers.clone)) {
dynamicUpperBoundType =
- TypeLatticeElement.fromDexType(invokedMethod.holder, definitelyNotNull(), appView);
+ TypeElement.fromDexType(invokedMethod.holder, definitelyNotNull(), appView);
dynamicLowerBoundType = null;
} else {
DexEncodedMethod singleTarget =
@@ -110,14 +110,14 @@
Value outValue = current.outValue();
boolean isTrivial =
(dynamicUpperBoundType == null
- || !dynamicUpperBoundType.strictlyLessThan(outValue.getTypeLattice(), appView))
+ || !dynamicUpperBoundType.strictlyLessThan(outValue.getType(), appView))
&& dynamicLowerBoundType == null;
if (isTrivial) {
continue;
}
if (dynamicUpperBoundType == null) {
- dynamicUpperBoundType = outValue.getTypeLattice();
+ dynamicUpperBoundType = outValue.getType();
}
// Split block if needed (only debug instructions are allowed after the throwing
@@ -126,8 +126,7 @@
block.hasCatchHandlers() ? instructionIterator.split(code, blockIterator) : block;
// Replace usages of out-value by the out-value of the AssumeDynamicType instruction.
- Value specializedOutValue =
- code.createValue(outValue.getTypeLattice(), outValue.getLocalInfo());
+ Value specializedOutValue = code.createValue(outValue.getType(), outValue.getLocalInfo());
outValue.replaceUsers(specializedOutValue);
// Insert AssumeDynamicType instruction.
@@ -154,9 +153,9 @@
*
* <p>If the method has no normal exits, then null is returned.
*/
- public TypeLatticeElement computeDynamicReturnType(DexEncodedMethod method, IRCode code) {
+ public TypeElement computeDynamicReturnType(DexEncodedMethod method, IRCode code) {
assert method.method.proto.returnType.isReferenceType();
- List<TypeLatticeElement> returnedTypes = new ArrayList<>();
+ List<TypeElement> returnedTypes = new ArrayList<>();
for (BasicBlock block : code.blocks) {
JumpInstruction exitInstruction = block.exit();
if (exitInstruction.isReturn()) {
@@ -164,19 +163,17 @@
returnedTypes.add(returnValue.getDynamicUpperBoundType(appView));
}
}
- return returnedTypes.isEmpty() ? null : TypeLatticeElement.join(returnedTypes, appView);
+ return returnedTypes.isEmpty() ? null : TypeElement.join(returnedTypes, appView);
}
- public ClassTypeLatticeElement computeDynamicLowerBoundType(
- DexEncodedMethod method, IRCode code) {
+ public ClassTypeElement computeDynamicLowerBoundType(DexEncodedMethod method, IRCode code) {
assert method.method.proto.returnType.isReferenceType();
- ClassTypeLatticeElement result = null;
+ ClassTypeElement result = null;
for (BasicBlock block : code.blocks) {
JumpInstruction exitInstruction = block.exit();
if (exitInstruction.isReturn()) {
Value returnValue = exitInstruction.asReturn().returnValue();
- ClassTypeLatticeElement dynamicLowerBoundType =
- returnValue.getDynamicLowerBoundType(appView);
+ ClassTypeElement dynamicLowerBoundType = returnValue.getDynamicLowerBoundType(appView);
if (dynamicLowerBoundType == null) {
return null;
}
@@ -184,7 +181,7 @@
result = dynamicLowerBoundType;
} else if (dynamicLowerBoundType.equalUpToNullability(result)) {
if (dynamicLowerBoundType.nullability() != result.nullability()) {
- result = dynamicLowerBoundType.join(result, appView).asClassTypeLatticeElement();
+ result = dynamicLowerBoundType.join(result, appView).asClassType();
}
} else {
return null;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/IdempotentFunctionCallCanonicalizer.java b/src/main/java/com/android/tools/r8/ir/optimize/IdempotentFunctionCallCanonicalizer.java
index ebf6e57..5dba772 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/IdempotentFunctionCallCanonicalizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/IdempotentFunctionCallCanonicalizer.java
@@ -149,7 +149,7 @@
// Check if the call could throw a NPE as a result of the receiver being null.
if (current.isInvokeMethodWithReceiver()) {
Value receiver = current.asInvokeMethodWithReceiver().getReceiver().getAliasedValue();
- if (receiver.getTypeLattice().isNullable()) {
+ if (receiver.getType().isNullable()) {
continue;
}
}
@@ -195,39 +195,42 @@
.filter(a -> a.getValue().size() > 1)
.sorted((a, b) -> Integer.compare(b.getValue().size(), a.getValue().size()))
.limit(MAX_CANONICALIZED_CALL)
- .forEach((entry) -> {
- InvokeMethod invoke = entry.getKey();
- if (Log.ENABLED) {
- if (factory.libraryMethodsWithReturnValueDependingOnlyOnArguments
- .contains(invoke.getInvokedMethod())) {
- numberOfLibraryCallCanonicalization += entry.getValue().size() - 1;
- } else {
- numberOfProgramCallCanonicalization += entry.getValue().size() - 1;
- }
- }
- Value canonicalizedValue = code.createValue(
- invoke.outValue().getTypeLattice(), invoke.outValue().getLocalInfo());
- Invoke canonicalizedInvoke =
- Invoke.create(
- invoke.getType(),
- invoke.getInvokedMethod(),
- null,
- canonicalizedValue,
- invoke.inValues());
- // Note that it is fine to use any position, since the invoke has no side effects, which
- // is guaranteed not to throw. That is, we will never have a stack trace with this call.
- // Nonetheless, here we pick the position of the very first invocation.
- Position firstInvocationPosition = entry.getValue().get(0).definition.getPosition();
- canonicalizedInvoke.setPosition(firstInvocationPosition);
- if (invoke.inValues().size() > 0) {
- insertCanonicalizedInvokeWithInValues(code, canonicalizedInvoke);
- } else {
- insertCanonicalizedInvokeWithoutInValues(code, canonicalizedInvoke);
- }
- for (Value oldOutValue : entry.getValue()) {
- deadInvocations.put(oldOutValue.definition.asInvokeMethod(), canonicalizedValue);
- }
- });
+ .forEach(
+ (entry) -> {
+ InvokeMethod invoke = entry.getKey();
+ if (Log.ENABLED) {
+ if (factory.libraryMethodsWithReturnValueDependingOnlyOnArguments.contains(
+ invoke.getInvokedMethod())) {
+ numberOfLibraryCallCanonicalization += entry.getValue().size() - 1;
+ } else {
+ numberOfProgramCallCanonicalization += entry.getValue().size() - 1;
+ }
+ }
+ Value canonicalizedValue =
+ code.createValue(invoke.outValue().getType(), invoke.outValue().getLocalInfo());
+ Invoke canonicalizedInvoke =
+ Invoke.create(
+ invoke.getType(),
+ invoke.getInvokedMethod(),
+ null,
+ canonicalizedValue,
+ invoke.inValues());
+ // Note that it is fine to use any position, since the invoke has no side effects,
+ // which
+ // is guaranteed not to throw. That is, we will never have a stack trace with this
+ // call.
+ // Nonetheless, here we pick the position of the very first invocation.
+ Position firstInvocationPosition = entry.getValue().get(0).definition.getPosition();
+ canonicalizedInvoke.setPosition(firstInvocationPosition);
+ if (invoke.inValues().size() > 0) {
+ insertCanonicalizedInvokeWithInValues(code, canonicalizedInvoke);
+ } else {
+ insertCanonicalizedInvokeWithoutInValues(code, canonicalizedInvoke);
+ }
+ for (Value oldOutValue : entry.getValue()) {
+ deadInvocations.put(oldOutValue.definition.asInvokeMethod(), canonicalizedValue);
+ }
+ });
if (!deadInvocations.isEmpty()) {
for (BasicBlock block : code.blocks) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
index d45bbb0..b56dece 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
@@ -21,7 +21,7 @@
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis;
import com.android.tools.r8.ir.analysis.proto.ProtoInliningReasonStrategy;
import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.CatchHandlers.CatchHandler;
import com.android.tools.r8.ir.code.ConstClass;
@@ -631,8 +631,8 @@
// Insert monitor-enter and monitor-exit instructions if the method is synchronized.
if (shouldSynthesizeMonitorEnterExit) {
- TypeLatticeElement throwableType =
- TypeLatticeElement.fromDexType(
+ TypeElement throwableType =
+ TypeElement.fromDexType(
dexItemFactory.throwableType, Nullability.definitelyNotNull(), appView);
code.prepareBlocksForCatchHandlers();
@@ -709,8 +709,7 @@
if (target.isStatic()) {
lockValue =
code.createValue(
- TypeLatticeElement.fromDexType(
- dexItemFactory.objectType, definitelyNotNull(), appView));
+ TypeElement.fromDexType(dexItemFactory.objectType, definitelyNotNull(), appView));
monitorEnterBlockIterator.add(new ConstClass(lockValue, target.method.holder));
} else {
lockValue = entryBlock.getInstructions().getFirst().asArgument().outValue();
@@ -763,7 +762,7 @@
InstructionListIterator iterator = initClassBlock.listIterator(code);
iterator.setInsertionPosition(entryBlock.exit().getPosition());
- iterator.add(new InitClass(code.createValue(TypeLatticeElement.getInt()), target.holder()));
+ iterator.add(new InitClass(code.createValue(TypeElement.getInt()), target.holder()));
}
private void synthesizeNullCheckForReceiver(AppView<?> appView, IRCode code) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java b/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java
index 7e25c8a..4bf7a6d 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java
@@ -16,7 +16,7 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.type.Nullability;
import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.analysis.value.SingleValue;
import com.android.tools.r8.ir.code.BasicBlock;
@@ -139,11 +139,10 @@
.createMaterializingInstruction(appView, code, instruction);
}
- TypeLatticeElement typeLattice = instruction.outValue().getTypeLattice();
+ TypeElement typeLattice = instruction.outValue().getType();
if (returnValueRule.isField()) {
DexField field = returnValueRule.getField();
- assert typeLattice
- == TypeLatticeElement.fromDexType(field.type, Nullability.maybeNull(), appView);
+ assert typeLattice == TypeElement.fromDexType(field.type, Nullability.maybeNull(), appView);
DexEncodedField staticField = appView.appInfo().lookupStaticTarget(field.holder, field);
if (staticField == null) {
@@ -446,7 +445,7 @@
}
DexProgramClass clazz = asProgramClassOrNull(appView.definitionFor(holder));
if (clazz != null) {
- Value dest = code.createValue(TypeLatticeElement.getInt());
+ Value dest = code.createValue(TypeElement.getInt());
iterator.replaceCurrentInstruction(new InitClass(dest, clazz.type));
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/NonNullTracker.java b/src/main/java/com/android/tools/r8/ir/optimize/NonNullTracker.java
index 4fa0312..15904c5 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/NonNullTracker.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/NonNullTracker.java
@@ -12,7 +12,7 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.Assume;
import com.android.tools.r8.ir.code.Assume.NonNullAssumption;
import com.android.tools.r8.ir.code.BasicBlock;
@@ -214,10 +214,10 @@
if (knownToBeNonNullValue.isArgument()
|| !dominatedUsers.isEmpty()
|| !dominatedPhiUsersWithPositions.isEmpty()) {
- TypeLatticeElement typeLattice = knownToBeNonNullValue.getTypeLattice();
+ TypeElement typeLattice = knownToBeNonNullValue.getType();
Value nonNullValue =
code.createValue(
- typeLattice.asReferenceTypeLatticeElement().asMeetWithNotNull(),
+ typeLattice.asReferenceType().asMeetWithNotNull(),
knownToBeNonNullValue.getLocalInfo());
affectedValues.addAll(knownToBeNonNullValue.affectedValues());
Assume<NonNullAssumption> nonNull =
@@ -316,11 +316,11 @@
// ...
// A: non_null_rcv <- non-null(rcv)
// ...y
- TypeLatticeElement typeLattice = knownToBeNonNullValue.getTypeLattice();
- assert typeLattice.isReference();
+ TypeElement typeLattice = knownToBeNonNullValue.getType();
+ assert typeLattice.isReferenceType();
Value nonNullValue =
code.createValue(
- typeLattice.asReferenceTypeLatticeElement().asMeetWithNotNull(),
+ typeLattice.asReferenceType().asMeetWithNotNull(),
knownToBeNonNullValue.getLocalInfo());
affectedValues.addAll(knownToBeNonNullValue.affectedValues());
Assume<NonNullAssumption> nonNull =
@@ -369,9 +369,9 @@
}
private static boolean isNullableReferenceTypeWithUsers(Value value) {
- TypeLatticeElement type = value.getTypeLattice();
- return type.isReference()
- && type.asReferenceTypeLatticeElement().isNullable()
+ TypeElement type = value.getType();
+ return type.isReferenceType()
+ && type.asReferenceType().isNullable()
&& value.numberOfAllUsers() > 0;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
index 4ce7ede..ab9fa71 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
@@ -4,9 +4,9 @@
package com.android.tools.r8.ir.optimize;
+import static com.android.tools.r8.graph.DexProgramClass.asProgramClassOrNull;
import static com.android.tools.r8.ir.analysis.type.Nullability.definitelyNotNull;
import static com.android.tools.r8.ir.analysis.type.Nullability.maybeNull;
-import static com.android.tools.r8.graph.DexProgramClass.asProgramClassOrNull;
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.errors.Unreachable;
@@ -30,10 +30,10 @@
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.graph.ParameterAnnotationsList;
import com.android.tools.r8.graph.UseRegistry;
-import com.android.tools.r8.ir.analysis.type.ArrayTypeLatticeElement;
-import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
-import com.android.tools.r8.ir.analysis.type.PrimitiveTypeLatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ArrayTypeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
+import com.android.tools.r8.ir.analysis.type.PrimitiveTypeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.Add;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.BasicBlock.ThrowingInfo;
@@ -277,7 +277,7 @@
inValues.add(
builder.readRegister(register, ValueTypeConstraint.fromNumericType(numericType)));
}
- TypeLatticeElement latticeElement = PrimitiveTypeLatticeElement.fromNumericType(numericType);
+ TypeElement latticeElement = PrimitiveTypeElement.fromNumericType(numericType);
Value outValue =
builder.writeRegister(outline.argumentCount(), latticeElement, ThrowingInfo.CAN_THROW);
Instruction newInstruction = null;
@@ -359,8 +359,8 @@
@Override
public int createInstruction(IRBuilder builder, Outline outline, int argumentMapIndex) {
- TypeLatticeElement latticeElement =
- TypeLatticeElement.fromDexType(clazz, definitelyNotNull(), builder.appView);
+ TypeElement latticeElement =
+ TypeElement.fromDexType(clazz, definitelyNotNull(), builder.appView);
Value outValue =
builder.writeRegister(outline.argumentCount(), latticeElement, ThrowingInfo.CAN_THROW);
Instruction newInstruction = new NewInstance(clazz, outValue);
@@ -495,8 +495,8 @@
}
Value outValue = null;
if (hasOutValue) {
- TypeLatticeElement latticeElement =
- TypeLatticeElement.fromDexType(method.proto.returnType, maybeNull(), builder.appView);
+ TypeElement latticeElement =
+ TypeElement.fromDexType(method.proto.returnType, maybeNull(), builder.appView);
outValue =
builder.writeRegister(outline.argumentCount(), latticeElement, ThrowingInfo.CAN_THROW);
}
@@ -933,7 +933,7 @@
private boolean supportedArgumentType(Value value) {
// All non array types are supported.
- if (!value.getTypeLattice().isArrayType()) {
+ if (!value.getType().isArrayType()) {
return true;
}
// Avoid array type elements which have interfaces, as Art does not have the same semantics
@@ -942,14 +942,13 @@
&& appView.options().isGeneratingClassFiles()) {
return true;
}
- ArrayTypeLatticeElement arrayTypeLatticeElement =
- value.getTypeLattice().asArrayTypeLatticeElement();
- TypeLatticeElement arrayBaseType = arrayTypeLatticeElement.getArrayBaseTypeLattice();
- if (arrayBaseType.isPrimitive()) {
+ ArrayTypeElement arrayType = value.getType().asArrayType();
+ TypeElement arrayBaseType = arrayType.getBaseType();
+ if (arrayBaseType.isPrimitiveType()) {
return true;
}
if (arrayBaseType.isClassType()) {
- return arrayBaseType.asClassTypeLatticeElement().getInterfaces().size() == 0;
+ return arrayBaseType.asClassType().getInterfaces().size() == 0;
}
return false;
}
@@ -958,30 +957,29 @@
assert supportedArgumentType(value);
DexItemFactory itemFactory = appView.options().itemFactory;
DexType objectType = itemFactory.objectType;
- TypeLatticeElement valueLatticeElement = value.getTypeLattice();
- if (valueLatticeElement.isClassType()) {
- ClassTypeLatticeElement valueClassTypeLatticeElement =
- value.getTypeLattice().asClassTypeLatticeElement();
+ TypeElement valueType = value.getType();
+ if (valueType.isClassType()) {
+ ClassTypeElement valueClassType = value.getType().asClassType();
// For values of lattice type java.lang.Object and only one interface use the interface as
// the type of the outline argument. If there are several interfaces these interfaces don't
// have a common super interface nor are they implemented by a common superclass so the
// argument type of the outline will be java.lang.Object.
- if (valueClassTypeLatticeElement.getClassType() == objectType
- && valueClassTypeLatticeElement.getInterfaces().size() == 1) {
- return valueClassTypeLatticeElement.getInterfaces().iterator().next();
+ if (valueClassType.getClassType() == objectType
+ && valueClassType.getInterfaces().size() == 1) {
+ return valueClassType.getInterfaces().iterator().next();
} else {
- return valueClassTypeLatticeElement.getClassType();
+ return valueClassType.getClassType();
}
- } else if (valueLatticeElement.isArrayType()) {
- return value.getTypeLattice().asArrayTypeLatticeElement().getArrayType(itemFactory);
- } else if (valueLatticeElement.isNullType()) {
+ } else if (valueType.isArrayType()) {
+ return value.getType().asArrayType().toDexType(itemFactory);
+ } else if (valueType.isNullType()) {
// For values which are always null use the actual type at the call site.
return argumentTypeFromInvoke(invoke, argumentIndex);
} else {
- assert valueLatticeElement.isPrimitive();
- assert valueLatticeElement.asPrimitiveTypeLatticeElement().hasDexType();
- DexType type = valueLatticeElement.asPrimitiveTypeLatticeElement().toDexType(itemFactory);
- if (valueLatticeElement.isInt()) {
+ assert valueType.isPrimitiveType();
+ assert valueType.asPrimitiveType().hasDexType();
+ DexType type = valueType.asPrimitiveType().toDexType(itemFactory);
+ if (valueType.isInt()) {
// In the type lattice boolean, byte, short and char are all int. However, as the
// outline argument type use the actual primitive type at the call site.
assert type == itemFactory.intType;
@@ -1488,8 +1486,8 @@
if (outline.argumentTypes.get(i).isBooleanType()) {
builder.addBooleanNonThisArgument(i);
} else {
- TypeLatticeElement typeLattice =
- TypeLatticeElement.fromDexType(outline.argumentTypes.get(i), maybeNull(), appView);
+ TypeElement typeLattice =
+ TypeElement.fromDexType(outline.argumentTypes.get(i), maybeNull(), appView);
builder.addNonThisArgument(i, typeLattice);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/ReflectionOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/ReflectionOptimizer.java
index 055eeca..1b56e8c 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/ReflectionOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/ReflectionOptimizer.java
@@ -14,7 +14,7 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis;
import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.ConstClass;
import com.android.tools.r8.ir.code.IRCode;
@@ -60,8 +60,7 @@
}
if (type != null) {
affectedValues.addAll(current.outValue().affectedValues());
- TypeLatticeElement typeLattice =
- TypeLatticeElement.classClassType(appView, definitelyNotNull());
+ TypeElement typeLattice = TypeElement.classClassType(appView, definitelyNotNull());
Value value = code.createValue(typeLattice, current.getLocalInfo());
ConstClass constClass = new ConstClass(value, type);
it.replaceCurrentInstruction(constClass);
@@ -90,7 +89,7 @@
if (in.hasLocalInfo()) {
return null;
}
- TypeLatticeElement inType = in.getTypeLattice();
+ TypeElement inType = in.getType();
// Check the receiver is either class type or array type. Also make sure it is not
// nullable.
if (!(inType.isClassType() || inType.isArrayType())
@@ -99,8 +98,8 @@
}
DexType type =
inType.isClassType()
- ? inType.asClassTypeLatticeElement().getClassType()
- : inType.asArrayTypeLatticeElement().getArrayType(dexItemFactory);
+ ? inType.asClassType().getClassType()
+ : inType.asArrayType().toDexType(dexItemFactory);
DexType baseType = type.toBaseType(dexItemFactory);
// Make sure base type is a class type.
if (!baseType.isClassType()) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java
index e8799da..d626168 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java
@@ -135,7 +135,7 @@
InvokeVirtual classLoaderInvoke =
serviceLoaderLoad.inValues().get(1).definition.asInvokeVirtual();
boolean isGetClassLoaderOnConstClassOrNull =
- serviceLoaderLoad.inValues().get(1).getTypeLattice().isNullType()
+ serviceLoaderLoad.inValues().get(1).getType().isNullType()
|| (classLoaderInvoke != null
&& classLoaderInvoke.inValues().size() == 1
&& classLoaderInvoke.getReceiver().getAliasedValue().isConstClass()
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/ClassInlinerReceiverAnalysis.java b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/ClassInlinerReceiverAnalysis.java
index f6e6e70..e0f991d 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/ClassInlinerReceiverAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/ClassInlinerReceiverAnalysis.java
@@ -6,7 +6,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
@@ -47,7 +47,7 @@
this.code = code;
this.receiver = code.getThis();
assert !receiver.hasAliasedValue();
- assert receiver.getTypeLattice().isClassType();
+ assert receiver.getType().isClassType();
}
public OptionalBool computeReturnsReceiver() {
@@ -87,12 +87,12 @@
return OptionalBool.TRUE;
}
- ClassTypeLatticeElement valueType = value.getTypeLattice().asClassTypeLatticeElement();
+ ClassTypeElement valueType = value.getType().asClassType();
if (valueType == null) {
return OptionalBool.FALSE;
}
- ClassTypeLatticeElement receiverType = receiver.getTypeLattice().asClassTypeLatticeElement();
+ ClassTypeElement receiverType = receiver.getType().asClassType();
if (!valueType.isRelatedTo(receiverType, appView)) {
// Guaranteed not to return the receiver.
return OptionalBool.FALSE;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/FieldValueHelper.java b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/FieldValueHelper.java
index 832e8b9..833ceaa 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/FieldValueHelper.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/FieldValueHelper.java
@@ -9,7 +9,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexField;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.ConstNumber;
import com.android.tools.r8.ir.code.IRCode;
@@ -98,7 +98,7 @@
new Phi(
code.valueNumberGenerator.next(),
block,
- TypeLatticeElement.fromDexType(field.type, maybeNull(), appView),
+ TypeElement.fromDexType(field.type, maybeNull(), appView),
null,
RegisterReadType.NORMAL);
ins.put(block, phi);
@@ -112,9 +112,9 @@
// phis until we are done with replacing fields reads.
phi.addOperands(operands, false);
- TypeLatticeElement phiType = phi.computePhiType(appView);
- assert phiType.lessThanOrEqual(phi.getTypeLattice(), appView);
- phi.setTypeLattice(phiType);
+ TypeElement phiType = phi.computePhiType(appView);
+ assert phiType.lessThanOrEqual(phi.getType(), appView);
+ phi.setType(phiType);
value = phi;
}
@@ -153,8 +153,8 @@
InstructionListIterator it = block.listIterator(code, root);
// If we met newInstance it means that default value is supposed to be used.
if (field.type.isPrimitiveType()) {
- defaultValue = code.createValue(
- TypeLatticeElement.fromDexType(field.type, definitelyNotNull(), appView));
+ defaultValue =
+ code.createValue(TypeElement.fromDexType(field.type, definitelyNotNull(), appView));
ConstNumber defaultValueInsn = new ConstNumber(defaultValue, 0);
defaultValueInsn.setPosition(root.getPosition());
it.add(defaultValueInsn);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java
index 22344de..81f68de 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java
@@ -19,7 +19,7 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis;
-import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
import com.android.tools.r8.ir.code.AliasedValueConfiguration;
import com.android.tools.r8.ir.code.AssumeAndCheckCastAliasedValueConfiguration;
@@ -175,7 +175,7 @@
}
DexEncodedField field = appView.appInfo().resolveField(staticGet.getField());
FieldOptimizationInfo optimizationInfo = field.getOptimizationInfo();
- ClassTypeLatticeElement dynamicLowerBoundType = optimizationInfo.getDynamicLowerBoundType();
+ ClassTypeElement dynamicLowerBoundType = optimizationInfo.getDynamicLowerBoundType();
if (dynamicLowerBoundType == null
|| !dynamicLowerBoundType.equals(optimizationInfo.getDynamicUpperBoundType())) {
return EligibilityStatus.NOT_A_SINGLETON_FIELD;
@@ -1031,7 +1031,7 @@
}
// A definitely null receiver will throw an error on call site.
- if (receiver.getTypeLattice().nullability().isDefinitelyNull()) {
+ if (receiver.getType().nullability().isDefinitelyNull()) {
return false;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
index 5e8b552..84b952b 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
@@ -18,14 +18,15 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DexValue.DexValueInt;
import com.android.tools.r8.graph.DexValue.DexValueNull;
-import com.android.tools.r8.graph.EnumValueInfoMapCollection.EnumValueInfoMap;
import com.android.tools.r8.graph.GraphLense;
import com.android.tools.r8.graph.GraphLense.NestedGraphLense;
import com.android.tools.r8.graph.RewrittenPrototypeDescription;
import com.android.tools.r8.graph.RewrittenPrototypeDescription.ArgumentInfoCollection;
import com.android.tools.r8.graph.RewrittenPrototypeDescription.RewrittenTypeInfo;
-import com.android.tools.r8.ir.analysis.type.ArrayTypeLatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ArrayTypeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
+import com.android.tools.r8.ir.code.ArrayPut;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.ConstClass;
import com.android.tools.r8.ir.code.FieldInstruction;
@@ -33,6 +34,7 @@
import com.android.tools.r8.ir.code.If;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.InvokeMethod;
+import com.android.tools.r8.ir.code.MemberType;
import com.android.tools.r8.ir.code.Phi;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.ir.conversion.CodeOptimization;
@@ -106,16 +108,15 @@
enumsUnboxingCandidates.remove(enumClass.type);
}
- private DexProgramClass getEnumUnboxingCandidateOrNull(TypeLatticeElement lattice) {
+ private DexProgramClass getEnumUnboxingCandidateOrNull(TypeElement lattice) {
if (lattice.isClassType()) {
- DexType classType = lattice.asClassTypeLatticeElement().getClassType();
+ DexType classType = lattice.asClassType().getClassType();
return getEnumUnboxingCandidateOrNull(classType);
}
if (lattice.isArrayType()) {
- ArrayTypeLatticeElement arrayLattice = lattice.asArrayTypeLatticeElement();
- if (arrayLattice.getArrayBaseTypeLattice().isClassType()) {
- DexType classType =
- arrayLattice.getArrayBaseTypeLattice().asClassTypeLatticeElement().getClassType();
+ ArrayTypeElement arrayLattice = lattice.asArrayType();
+ if (arrayLattice.getBaseType().isClassType()) {
+ DexType classType = arrayLattice.getBaseType().asClassType().getClassType();
return getEnumUnboxingCandidateOrNull(classType);
}
}
@@ -135,7 +136,7 @@
for (Instruction instruction : block.getInstructions()) {
Value outValue = instruction.outValue();
if (outValue != null) {
- DexProgramClass enumClass = getEnumUnboxingCandidateOrNull(outValue.getTypeLattice());
+ DexProgramClass enumClass = getEnumUnboxingCandidateOrNull(outValue.getType());
if (enumClass != null) {
Reason reason = validateEnumUsages(code, outValue, enumClass);
if (reason == Reason.ELIGIBLE) {
@@ -147,7 +148,7 @@
eligibleEnums.add(enumClass.type);
}
}
- if (outValue.getTypeLattice().isNullType()) {
+ if (outValue.getType().isNullType()) {
addNullDependencies(outValue.uniqueUsers(), eligibleEnums);
}
}
@@ -160,17 +161,33 @@
markEnumAsUnboxable(
Reason.CONST_CLASS, appView.definitionForProgramType(constClass.getValue()));
}
+ } else if (instruction.isInvokeStatic()) {
+ // TODO(b/150370354): Since we temporary allow enum unboxing on enums with values and
+ // valueOf static methods only if such methods are unused, such methods cannot be
+ // called. the long term solution is to simply move called methods to a companion class,
+ // as any static helper method, and remove these checks.
+ DexMethod invokedMethod = instruction.asInvokeStatic().getInvokedMethod();
+ DexProgramClass enumClass = getEnumUnboxingCandidateOrNull(invokedMethod.holder);
+ if (enumClass != null) {
+ if (factory.enumMethods.isValueOfMethod(invokedMethod, enumClass)) {
+ markEnumAsUnboxable(Reason.VALUE_OF_INVOKE, enumClass);
+ } else if (factory.enumMethods.isValuesMethod(invokedMethod, enumClass)) {
+ markEnumAsUnboxable(Reason.VALUES_INVOKE, enumClass);
+ } else {
+ assert false; // We do not allow any other static call in unboxing candidates.
+ }
+ }
}
}
for (Phi phi : block.getPhis()) {
- DexProgramClass enumClass = getEnumUnboxingCandidateOrNull(phi.getTypeLattice());
+ DexProgramClass enumClass = getEnumUnboxingCandidateOrNull(phi.getType());
if (enumClass != null) {
Reason reason = validateEnumUsages(code, phi, enumClass);
if (reason == Reason.ELIGIBLE) {
eligibleEnums.add(enumClass.type);
}
}
- if (phi.getTypeLattice().isNullType()) {
+ if (phi.getType().isNullType()) {
addNullDependencies(phi.uniqueUsers(), eligibleEnums);
}
}
@@ -223,7 +240,7 @@
}
for (Phi phi : value.uniquePhiUsers()) {
for (Value operand : phi.getOperands()) {
- if (getEnumUnboxingCandidateOrNull(operand.getTypeLattice()) != enumClass) {
+ if (getEnumUnboxingCandidateOrNull(operand.getType()) != enumClass) {
markEnumAsUnboxable(Reason.INVALID_PHI, enumClass);
return Reason.INVALID_PHI;
}
@@ -263,6 +280,7 @@
if (optimizationInfo.isMutableFieldOptimizationInfo()) {
optimizationInfo
.asMutableFieldOptimizationInfo()
+ .fixupClassTypeReferences(appView.graphLense()::lookupType, appView)
.fixupAbstractValue(appView, appView.graphLense());
} else {
assert optimizationInfo.isDefaultFieldOptimizationInfo();
@@ -275,6 +293,7 @@
if (optimizationInfo.isUpdatableMethodOptimizationInfo()) {
optimizationInfo
.asUpdatableMethodOptimizationInfo()
+ .fixupClassTypeReferences(appView.graphLense()::lookupType, appView)
.fixupAbstractReturnValue(appView, appView.graphLense())
.fixupInstanceInitializerInfo(appView, appView.graphLense());
} else {
@@ -292,6 +311,8 @@
DexProgramClass enumClass = appView.definitionForProgramType(toUnbox);
assert enumClass != null;
+ // Enum candidates have necessarily only one constructor matching enumMethods.constructor
+ // signature.
DexEncodedMethod initializer = enumClass.lookupDirectMethod(factory.enumMethods.constructor);
if (initializer == null) {
// This case typically happens when a programmer uses EnumSet/EnumMap without using the
@@ -307,17 +328,6 @@
if (enumClass.classInitializationMayHaveSideEffects(appView)) {
markEnumAsUnboxable(Reason.INVALID_CLINIT, enumClass);
- continue;
- }
-
- EnumValueInfoMap enumValueInfoMap =
- appView.appInfo().withLiveness().getEnumValueInfoMap(enumClass.type);
- if (enumValueInfoMap == null) {
- markEnumAsUnboxable(Reason.MISSING_INFO_MAP, enumClass);
- continue;
- }
- if (enumValueInfoMap.size() != enumClass.staticFields().size() - 1) {
- markEnumAsUnboxable(Reason.UNEXPECTED_STATIC_FIELD, enumClass);
}
}
if (debugLogEnabled) {
@@ -360,7 +370,7 @@
int offset = BooleanUtils.intValue(!encodedSingleTarget.isStatic());
for (int i = 0; i < singleTarget.proto.parameters.size(); i++) {
if (invokeMethod.inValues().get(offset + i) == enumValue) {
- if (singleTarget.proto.parameters.values[i] != enumClass.type) {
+ if (singleTarget.proto.parameters.values[i].toBaseType(factory) != enumClass.type) {
return Reason.GENERIC_INVOKE;
}
}
@@ -426,16 +436,50 @@
return Reason.ELIGIBLE;
}
// e == MyEnum.X
- TypeLatticeElement leftType = anIf.lhs().getTypeLattice();
- TypeLatticeElement rightType = anIf.rhs().getTypeLattice();
+ TypeElement leftType = anIf.lhs().getType();
+ TypeElement rightType = anIf.rhs().getType();
if (leftType.equalUpToNullability(rightType)) {
assert leftType.isClassType();
- assert leftType.asClassTypeLatticeElement().getClassType() == enumClass.type;
+ assert leftType.asClassType().getClassType() == enumClass.type;
return Reason.ELIGIBLE;
}
return Reason.INVALID_IF_TYPES;
}
+ if (instruction.isArrayLength()) {
+ // MyEnum[] array = ...; array.length; is valid.
+ return Reason.ELIGIBLE;
+ }
+
+ if (instruction.isArrayGet()) {
+ // MyEnum[] array = ...; array[0]; is valid.
+ return Reason.ELIGIBLE;
+ }
+
+ if (instruction.isArrayPut()) {
+ // MyEnum[] array; array[0] = MyEnum.A; is valid.
+ // MyEnum[][] array2d; MyEnum[] array; array2d[0] = array; is valid.
+ // MyEnum[]^N array; MyEnum[]^(N-1) element; array[0] = element; is valid.
+ // We need to prove that the value to put in and the array have correct types.
+ ArrayPut arrayPut = instruction.asArrayPut();
+ assert arrayPut.getMemberType() == MemberType.OBJECT;
+ TypeElement arrayType = arrayPut.array().getType();
+ assert arrayType.isArrayType();
+ assert arrayType.asArrayType().getBaseType().isClassType();
+ ClassTypeElement arrayBaseType = arrayType.asArrayType().getBaseType().asClassType();
+ TypeElement valueBaseType = arrayPut.value().getType();
+ if (valueBaseType.isArrayType()) {
+ assert valueBaseType.asArrayType().getBaseType().isClassType();
+ assert valueBaseType.asArrayType().getNesting() == arrayType.asArrayType().getNesting() - 1;
+ valueBaseType = valueBaseType.asArrayType().getBaseType();
+ }
+ if (arrayBaseType.equalUpToNullability(valueBaseType)
+ && arrayBaseType.getClassType() == enumClass.type) {
+ return Reason.ELIGIBLE;
+ }
+ return Reason.INVALID_ARRAY_PUT;
+ }
+
if (instruction.isAssume()) {
Value outValue = instruction.outValue();
return validateEnumUsages(code, outValue, enumClass);
@@ -537,6 +581,7 @@
UNSUPPORTED_LIBRARY_CALL,
MISSING_INFO_MAP,
INVALID_FIELD_PUT,
+ INVALID_ARRAY_PUT,
FIELD_PUT_ON_ENUM,
TYPE_MISSMATCH_FIELD_PUT,
INVALID_IF_TYPES,
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingCandidateAnalysis.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingCandidateAnalysis.java
index 3d18f6a..0b39506 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingCandidateAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingCandidateAnalysis.java
@@ -15,6 +15,7 @@
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.EnumValueInfoMapCollection.EnumValueInfoMap;
import com.android.tools.r8.ir.optimize.enums.EnumUnboxer.Reason;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.google.common.collect.Sets;
@@ -71,6 +72,12 @@
enumUnboxer.reportFailure(clazz.type, Reason.VIRTUAL_METHOD);
return false;
}
+ EnumValueInfoMap enumValueInfoMap =
+ appView.appInfo().withLiveness().getEnumValueInfoMap(clazz.type);
+ if (enumValueInfoMap == null) {
+ enumUnboxer.reportFailure(clazz.type, Reason.MISSING_INFO_MAP);
+ return false;
+ }
// Methods values, valueOf, init, clinit are present on each enum.
// Methods init and clinit are required if the enum is used.
// Methods valueOf and values are normally kept by the commonly used/recommended enum keep rule
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingRewriter.java
index cbd3824..0d065ff 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingRewriter.java
@@ -22,15 +22,18 @@
import com.android.tools.r8.graph.EnumValueInfoMapCollection.EnumValueInfoMap;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.graph.ParameterAnnotationsList;
+import com.android.tools.r8.ir.analysis.type.ArrayTypeElement;
import com.android.tools.r8.ir.analysis.type.DestructivePhiTypeUpdater;
-import com.android.tools.r8.ir.analysis.type.PrimitiveTypeLatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.PrimitiveTypeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
+import com.android.tools.r8.ir.code.ArrayAccess;
import com.android.tools.r8.ir.code.ConstNumber;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.InstructionListIterator;
import com.android.tools.r8.ir.code.InvokeMethodWithReceiver;
import com.android.tools.r8.ir.code.InvokeStatic;
+import com.android.tools.r8.ir.code.MemberType;
import com.android.tools.r8.ir.code.NumericType;
import com.android.tools.r8.ir.code.Phi;
import com.android.tools.r8.ir.code.StaticGet;
@@ -96,7 +99,7 @@
InvokeMethodWithReceiver invokeMethod = instruction.asInvokeMethodWithReceiver();
DexMethod invokedMethod = invokeMethod.getInvokedMethod();
if (invokedMethod == factory.enumMethods.ordinal
- && invokeMethod.getReceiver().getTypeLattice().isInt()) {
+ && invokeMethod.getReceiver().getType().isInt()) {
instruction =
new InvokeStatic(
ordinalUtilityMethod, invokeMethod.outValue(), invokeMethod.inValues());
@@ -122,13 +125,19 @@
assert enumValueInfo != null
: "Invalid read to " + staticGet.getField().name + ", error during enum analysis";
instruction = new ConstNumber(staticGet.outValue(), enumValueInfo.convertToInt());
- staticGet
- .outValue()
- .setTypeLattice(PrimitiveTypeLatticeElement.fromNumericType(NumericType.INT));
+ staticGet.outValue().setType(PrimitiveTypeElement.fromNumericType(NumericType.INT));
iterator.replaceCurrentInstruction(instruction);
affectedPhis.addAll(staticGet.outValue().uniquePhiUsers());
}
}
+ // Rewrite array accesses from MyEnum[] (OBJECT) to int[] (INT).
+ if (instruction.isArrayAccess()) {
+ ArrayAccess arrayAccess = instruction.asArrayAccess();
+ if (shouldRewriteArrayAccess(arrayAccess)) {
+ instruction = arrayAccess.withMemberType(MemberType.INT);
+ iterator.replaceCurrentInstruction(instruction);
+ }
+ }
assert validateEnumToUnboxRemoved(instruction);
}
if (!affectedPhis.isEmpty()) {
@@ -137,19 +146,31 @@
assert code.isConsistentSSABeforeTypesAreCorrect();
}
+ private boolean shouldRewriteArrayAccess(ArrayAccess arrayAccess) {
+ ArrayTypeElement arrayType = arrayAccess.array().getType().asArrayType();
+ return arrayAccess.getMemberType() == MemberType.OBJECT
+ && arrayType.getNesting() == 1
+ && arrayType.getBaseType().isInt();
+ }
+
private boolean validateEnumToUnboxRemoved(Instruction instruction) {
+ if (instruction.isArrayAccess()) {
+ ArrayAccess arrayAccess = instruction.asArrayAccess();
+ ArrayTypeElement arrayType = arrayAccess.array().getType().asArrayType();
+ assert arrayAccess.getMemberType() != MemberType.OBJECT
+ || arrayType.getNesting() > 1
+ || arrayType.getBaseType().isReferenceType();
+ }
if (instruction.outValue() == null) {
return true;
}
- TypeLatticeElement typeLattice = instruction.outValue().getTypeLattice();
+ TypeElement typeLattice = instruction.outValue().getType();
assert !typeLattice.isClassType()
- || !enumsToUnbox.containsEnum(typeLattice.asClassTypeLatticeElement().getClassType());
+ || !enumsToUnbox.containsEnum(typeLattice.asClassType().getClassType());
if (typeLattice.isArrayType()) {
- TypeLatticeElement arrayBaseTypeLattice =
- typeLattice.asArrayTypeLatticeElement().getArrayBaseTypeLattice();
+ TypeElement arrayBaseTypeLattice = typeLattice.asArrayType().getBaseType();
assert !arrayBaseTypeLattice.isClassType()
- || !enumsToUnbox.containsEnum(
- arrayBaseTypeLattice.asClassTypeLatticeElement().getClassType());
+ || !enumsToUnbox.containsEnum(arrayBaseTypeLattice.asClassType().getClassType());
}
return true;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/CallSiteOptimizationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/CallSiteOptimizationInfo.java
index 18c709c..e85cf9e 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/CallSiteOptimizationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/CallSiteOptimizationInfo.java
@@ -5,7 +5,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.analysis.value.UnknownValue;
import com.android.tools.r8.ir.optimize.CallSiteOptimizationInfoPropagator;
@@ -59,7 +59,7 @@
}
// The index exactly matches with in values of invocation, i.e., even including receiver.
- public TypeLatticeElement getDynamicUpperBoundType(int argIndex) {
+ public TypeElement getDynamicUpperBoundType(int argIndex) {
return null;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/ConcreteCallSiteOptimizationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/ConcreteCallSiteOptimizationInfo.java
index 702074a..ba24e19 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/ConcreteCallSiteOptimizationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/ConcreteCallSiteOptimizationInfo.java
@@ -10,7 +10,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.analysis.value.UnknownValue;
import com.android.tools.r8.ir.code.Value;
@@ -26,7 +26,7 @@
// inValues() size == DexMethod.arity + (isStatic ? 0 : 1) // receiver
// That is, this information takes into account the receiver as well.
private final int size;
- private final Int2ReferenceMap<TypeLatticeElement> dynamicUpperBoundTypes;
+ private final Int2ReferenceMap<TypeElement> dynamicUpperBoundTypes;
private final Int2ReferenceMap<AbstractValue> constants;
private ConcreteCallSiteOptimizationInfo(
@@ -59,15 +59,15 @@
}
}
- TypeLatticeElement thisUpperBoundType = getDynamicUpperBoundType(i);
+ TypeElement thisUpperBoundType = getDynamicUpperBoundType(i);
if (thisUpperBoundType == null) {
// This means the corresponding argument is primitive. The counterpart should be too.
assert other.getDynamicUpperBoundType(i) == null;
continue;
}
- assert thisUpperBoundType.isReference();
- TypeLatticeElement otherUpperBoundType = other.getDynamicUpperBoundType(i);
- assert otherUpperBoundType != null && otherUpperBoundType.isReference();
+ assert thisUpperBoundType.isReferenceType();
+ TypeElement otherUpperBoundType = other.getDynamicUpperBoundType(i);
+ assert otherUpperBoundType != null && otherUpperBoundType.isReferenceType();
result.dynamicUpperBoundTypes.put(
i, thisUpperBoundType.join(otherUpperBoundType, appView));
}
@@ -79,18 +79,17 @@
return TOP;
}
- private TypeLatticeElement[] getStaticTypes(AppView<?> appView, DexEncodedMethod encodedMethod) {
+ private TypeElement[] getStaticTypes(AppView<?> appView, DexEncodedMethod encodedMethod) {
int argOffset = encodedMethod.isStatic() ? 0 : 1;
int size = encodedMethod.method.getArity() + argOffset;
- TypeLatticeElement[] staticTypes = new TypeLatticeElement[size];
+ TypeElement[] staticTypes = new TypeElement[size];
if (!encodedMethod.isStatic()) {
staticTypes[0] =
- TypeLatticeElement.fromDexType(
- encodedMethod.method.holder, definitelyNotNull(), appView);
+ TypeElement.fromDexType(encodedMethod.method.holder, definitelyNotNull(), appView);
}
for (int i = 0; i < encodedMethod.method.getArity(); i++) {
staticTypes[i + argOffset] =
- TypeLatticeElement.fromDexType(
+ TypeElement.fromDexType(
encodedMethod.method.proto.parameters.values[i], maybeNull(), appView);
}
return staticTypes;
@@ -98,7 +97,7 @@
@Override
public boolean hasUsefulOptimizationInfo(AppView<?> appView, DexEncodedMethod encodedMethod) {
- TypeLatticeElement[] staticTypes = getStaticTypes(appView, encodedMethod);
+ TypeElement[] staticTypes = getStaticTypes(appView, encodedMethod);
for (int i = 0; i < size; i++) {
ParameterUsage parameterUsage = encodedMethod.getOptimizationInfo().getParameterUsages(i);
// If the parameter is not used, passing accurate argument info doesn't matter.
@@ -111,10 +110,10 @@
return true;
}
- if (!staticTypes[i].isReference()) {
+ if (!staticTypes[i].isReferenceType()) {
continue;
}
- TypeLatticeElement dynamicUpperBoundType = getDynamicUpperBoundType(i);
+ TypeElement dynamicUpperBoundType = getDynamicUpperBoundType(i);
if (dynamicUpperBoundType == null) {
continue;
}
@@ -137,7 +136,7 @@
}
@Override
- public TypeLatticeElement getDynamicUpperBoundType(int argIndex) {
+ public TypeElement getDynamicUpperBoundType(int argIndex) {
assert 0 <= argIndex && argIndex < size;
assert dynamicUpperBoundTypes != null;
return dynamicUpperBoundTypes.getOrDefault(argIndex, null);
@@ -176,10 +175,10 @@
}
}
- if (arg.getTypeLattice().isPrimitive()) {
+ if (arg.getType().isPrimitiveType()) {
continue;
}
- assert arg.getTypeLattice().isReference();
+ assert arg.getType().isReferenceType();
newCallSiteInfo.dynamicUpperBoundTypes.put(i, arg.getDynamicUpperBoundType(appView));
}
if (newCallSiteInfo.hasUsefulOptimizationInfo(appView, method)) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultFieldOptimizationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultFieldOptimizationInfo.java
index 8248e52..80fbd54 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultFieldOptimizationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultFieldOptimizationInfo.java
@@ -4,8 +4,8 @@
package com.android.tools.r8.ir.optimize.info;
-import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.analysis.value.UnknownValue;
@@ -40,12 +40,12 @@
}
@Override
- public ClassTypeLatticeElement getDynamicLowerBoundType() {
+ public ClassTypeElement getDynamicLowerBoundType() {
return null;
}
@Override
- public TypeLatticeElement getDynamicUpperBoundType() {
+ public TypeElement getDynamicUpperBoundType() {
return null;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultMethodOptimizationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultMethodOptimizationInfo.java
index 29fcf04..414e55f 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultMethodOptimizationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultMethodOptimizationInfo.java
@@ -5,8 +5,8 @@
package com.android.tools.r8.ir.optimize.info;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.analysis.value.UnknownValue;
import com.android.tools.r8.ir.optimize.classinliner.ClassInlinerEligibilityInfo;
@@ -26,8 +26,8 @@
static boolean UNKNOWN_NEVER_RETURNS_NULL = false;
static boolean UNKNOWN_NEVER_RETURNS_NORMALLY = false;
static AbstractValue UNKNOWN_ABSTRACT_RETURN_VALUE = UnknownValue.getInstance();
- static TypeLatticeElement UNKNOWN_TYPE = null;
- static ClassTypeLatticeElement UNKNOWN_CLASS_TYPE = null;
+ static TypeElement UNKNOWN_TYPE = null;
+ static ClassTypeElement UNKNOWN_CLASS_TYPE = null;
static boolean UNKNOWN_CHECKS_NULL_RECEIVER_BEFORE_ANY_SIDE_EFFECT = false;
static boolean UNKNOWN_TRIGGERS_CLASS_INIT_BEFORE_ANY_SIDE_EFFECT = false;
static ClassInlinerEligibilityInfo UNKNOWN_CLASS_INLINER_ELIGIBILITY = null;
@@ -66,12 +66,12 @@
}
@Override
- public TypeLatticeElement getDynamicUpperBoundType() {
+ public TypeElement getDynamicUpperBoundType() {
return UNKNOWN_TYPE;
}
@Override
- public ClassTypeLatticeElement getDynamicLowerBoundType() {
+ public ClassTypeElement getDynamicLowerBoundType() {
return UNKNOWN_CLASS_TYPE;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/FieldOptimizationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/FieldOptimizationInfo.java
index 33a6e75..09ad5e5 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/FieldOptimizationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/FieldOptimizationInfo.java
@@ -4,8 +4,8 @@
package com.android.tools.r8.ir.optimize.info;
-import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
public abstract class FieldOptimizationInfo {
@@ -22,9 +22,9 @@
*/
public abstract int getReadBits();
- public abstract ClassTypeLatticeElement getDynamicLowerBoundType();
+ public abstract ClassTypeElement getDynamicLowerBoundType();
- public abstract TypeLatticeElement getDynamicUpperBoundType();
+ public abstract TypeElement getDynamicUpperBoundType();
public abstract boolean isDead();
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfo.java
index b7b4973..c74bc0a 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfo.java
@@ -5,8 +5,8 @@
package com.android.tools.r8.ir.optimize.info;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.optimize.classinliner.ClassInlinerEligibilityInfo;
import com.android.tools.r8.ir.optimize.info.ParameterUsagesInfo.ParameterUsage;
@@ -32,9 +32,9 @@
boolean classInitializerMayBePostponed();
- TypeLatticeElement getDynamicUpperBoundType();
+ TypeElement getDynamicUpperBoundType();
- ClassTypeLatticeElement getDynamicLowerBoundType();
+ ClassTypeElement getDynamicLowerBoundType();
ParameterUsage getParameterUsages(int parameter);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java b/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java
index bbf2f22..19c897f 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java
@@ -57,9 +57,9 @@
import com.android.tools.r8.ir.analysis.InitializedClassesOnNormalExitAnalysis;
import com.android.tools.r8.ir.analysis.sideeffect.ClassInitializerSideEffectAnalysis;
import com.android.tools.r8.ir.analysis.sideeffect.ClassInitializerSideEffectAnalysis.ClassInitializerSideEffect;
-import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.code.AliasedValueConfiguration;
import com.android.tools.r8.ir.code.AssumeAndCheckCastAliasedValueConfiguration;
@@ -95,6 +95,7 @@
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.MethodSignatureEquivalence;
import com.android.tools.r8.utils.Pair;
+import com.android.tools.r8.utils.Timing;
import com.android.tools.r8.utils.WorkList;
import com.google.common.base.Equivalence.Wrapper;
import com.google.common.collect.Sets;
@@ -123,20 +124,29 @@
IRCode code,
OptimizationFeedback feedback,
DynamicTypeOptimization dynamicTypeOptimization,
- InstanceFieldInitializationInfoCollection instanceFieldInitializationInfos) {
- identifyClassInlinerEligibility(method, code, feedback);
- identifyParameterUsages(method, code, feedback);
- identifyReturnsArgument(method, code, feedback);
+ InstanceFieldInitializationInfoCollection instanceFieldInitializationInfos,
+ Timing timing) {
+ identifyClassInlinerEligibility(method, code, feedback, timing);
+ identifyParameterUsages(method, code, feedback, timing);
+ identifyReturnsArgument(method, code, feedback, timing);
if (options.enableInlining) {
- identifyInvokeSemanticsForInlining(method, code, appView, feedback);
+ identifyInvokeSemanticsForInlining(method, code, feedback, timing);
}
- computeDynamicReturnType(dynamicTypeOptimization, feedback, method, code);
- computeInitializedClassesOnNormalExit(feedback, method, code);
- computeInstanceInitializerInfo(method, code, feedback, instanceFieldInitializationInfos);
- computeMayHaveSideEffects(feedback, method, code);
- computeReturnValueOnlyDependsOnArguments(feedback, method, code);
- computeNonNullParamOrThrow(feedback, method, code);
- computeNonNullParamOnNormalExits(feedback, code);
+ computeDynamicReturnType(dynamicTypeOptimization, feedback, method, code, timing);
+ computeInitializedClassesOnNormalExit(feedback, method, code, timing);
+ computeInstanceInitializerInfo(
+ method, code, feedback, instanceFieldInitializationInfos, timing);
+ computeMayHaveSideEffects(feedback, method, code, timing);
+ computeReturnValueOnlyDependsOnArguments(feedback, method, code, timing);
+ computeNonNullParamOrThrow(feedback, method, code, timing);
+ computeNonNullParamOnNormalExits(feedback, code, timing);
+ }
+
+ private void identifyClassInlinerEligibility(
+ DexEncodedMethod method, IRCode code, OptimizationFeedback feedback, Timing timing) {
+ timing.begin("Identify class inliner eligibility");
+ identifyClassInlinerEligibility(method, code, feedback);
+ timing.end();
}
private void identifyClassInlinerEligibility(
@@ -283,6 +293,13 @@
}
private void identifyParameterUsages(
+ DexEncodedMethod method, IRCode code, OptimizationFeedback feedback, Timing timing) {
+ timing.begin("Identify parameter usages");
+ identifyParameterUsages(method, code, feedback);
+ timing.end();
+ }
+
+ private void identifyParameterUsages(
DexEncodedMethod method, IRCode code, OptimizationFeedback feedback) {
List<ParameterUsage> usages = new ArrayList<>();
List<Value> values = code.collectArguments();
@@ -322,6 +339,13 @@
}
private void identifyReturnsArgument(
+ DexEncodedMethod method, IRCode code, OptimizationFeedback feedback, Timing timing) {
+ timing.begin("Identify returns argument");
+ identifyReturnsArgument(method, code, feedback);
+ timing.end();
+ }
+
+ private void identifyReturnsArgument(
DexEncodedMethod method, IRCode code, OptimizationFeedback feedback) {
List<BasicBlock> normalExits = code.computeNormalExitBlocks();
if (normalExits.isEmpty()) {
@@ -333,14 +357,14 @@
return;
}
Value returnValue = firstExit.returnValue();
- boolean isNeverNull = returnValue.getTypeLattice().isReference() && returnValue.isNeverNull();
+ boolean isNeverNull = returnValue.getType().isReferenceType() && returnValue.isNeverNull();
for (int i = 1; i < normalExits.size(); i++) {
Return exit = normalExits.get(i).exit().asReturn();
Value value = exit.returnValue();
if (value != returnValue) {
returnValue = null;
}
- isNeverNull &= value.getTypeLattice().isReference() && value.isNeverNull();
+ isNeverNull &= value.getType().isReferenceType() && value.isNeverNull();
}
if (returnValue != null) {
Value aliasedValue = returnValue.getAliasedValue();
@@ -365,6 +389,17 @@
DexEncodedMethod method,
IRCode code,
OptimizationFeedback feedback,
+ InstanceFieldInitializationInfoCollection instanceFieldInitializationInfos,
+ Timing timing) {
+ timing.begin("Compute instance initializer info");
+ computeInstanceInitializerInfo(method, code, feedback, instanceFieldInitializationInfos);
+ timing.end();
+ }
+
+ private void computeInstanceInitializerInfo(
+ DexEncodedMethod method,
+ IRCode code,
+ OptimizationFeedback feedback,
InstanceFieldInitializationInfoCollection instanceFieldInitializationInfos) {
assert !appView.appInfo().isPinned(method.method);
@@ -641,7 +676,14 @@
}
private void identifyInvokeSemanticsForInlining(
- DexEncodedMethod method, IRCode code, AppView<?> appView, OptimizationFeedback feedback) {
+ DexEncodedMethod method, IRCode code, OptimizationFeedback feedback, Timing timing) {
+ timing.begin("Identify invoke semantics for inlining");
+ identifyInvokeSemanticsForInlining(method, code, feedback);
+ timing.end();
+ }
+
+ private void identifyInvokeSemanticsForInlining(
+ DexEncodedMethod method, IRCode code, OptimizationFeedback feedback) {
if (method.isStatic()) {
// Identifies if the method preserves class initialization after inlining.
feedback.markTriggerClassInitBeforeAnySideEffect(
@@ -899,24 +941,35 @@
DynamicTypeOptimization dynamicTypeOptimization,
OptimizationFeedback feedback,
DexEncodedMethod method,
+ IRCode code,
+ Timing timing) {
+ timing.begin("Compute dynamic return type");
+ computeDynamicReturnType(dynamicTypeOptimization, feedback, method, code);
+ timing.end();
+ }
+
+ private void computeDynamicReturnType(
+ DynamicTypeOptimization dynamicTypeOptimization,
+ OptimizationFeedback feedback,
+ DexEncodedMethod method,
IRCode code) {
if (dynamicTypeOptimization != null) {
DexType staticReturnTypeRaw = method.method.proto.returnType;
if (!staticReturnTypeRaw.isReferenceType()) {
return;
}
- TypeLatticeElement dynamicReturnType =
+ TypeElement dynamicReturnType =
dynamicTypeOptimization.computeDynamicReturnType(method, code);
if (dynamicReturnType != null) {
- TypeLatticeElement staticReturnType =
- TypeLatticeElement.fromDexType(staticReturnTypeRaw, Nullability.maybeNull(), appView);
+ TypeElement staticReturnType =
+ TypeElement.fromDexType(staticReturnTypeRaw, Nullability.maybeNull(), appView);
// If the dynamic return type is not more precise than the static return type there is no
// need to record it.
if (dynamicReturnType.strictlyLessThan(staticReturnType, appView)) {
feedback.methodReturnsObjectWithUpperBoundType(method, appView, dynamicReturnType);
}
}
- ClassTypeLatticeElement exactReturnType =
+ ClassTypeElement exactReturnType =
dynamicTypeOptimization.computeDynamicLowerBoundType(method, code);
if (exactReturnType != null) {
feedback.methodReturnsObjectWithLowerBoundType(method, exactReturnType);
@@ -925,6 +978,13 @@
}
private void computeInitializedClassesOnNormalExit(
+ OptimizationFeedback feedback, DexEncodedMethod method, IRCode code, Timing timing) {
+ timing.begin("Compute initialized classes on normal exits");
+ computeInitializedClassesOnNormalExit(feedback, method, code);
+ timing.end();
+ }
+
+ private void computeInitializedClassesOnNormalExit(
OptimizationFeedback feedback, DexEncodedMethod method, IRCode code) {
if (options.enableInitializedClassesAnalysis && appView.appInfo().hasLiveness()) {
AppView<AppInfoWithLiveness> appViewWithLiveness = appView.withLiveness();
@@ -938,6 +998,13 @@
}
private void computeMayHaveSideEffects(
+ OptimizationFeedback feedback, DexEncodedMethod method, IRCode code, Timing timing) {
+ timing.begin("Compute may have side effects");
+ computeMayHaveSideEffects(feedback, method, code);
+ timing.end();
+ }
+
+ private void computeMayHaveSideEffects(
OptimizationFeedback feedback, DexEncodedMethod method, IRCode code) {
// If the method is native, we don't know what could happen.
assert !method.accessFlags.isNative();
@@ -1018,6 +1085,13 @@
}
private void computeReturnValueOnlyDependsOnArguments(
+ OptimizationFeedback feedback, DexEncodedMethod method, IRCode code, Timing timing) {
+ timing.begin("Return value only depends on argument");
+ computeReturnValueOnlyDependsOnArguments(feedback, method, code);
+ timing.end();
+ }
+
+ private void computeReturnValueOnlyDependsOnArguments(
OptimizationFeedback feedback, DexEncodedMethod method, IRCode code) {
if (!options.enableDeterminismAnalysis) {
return;
@@ -1029,6 +1103,13 @@
}
}
+ private void computeNonNullParamOrThrow(
+ OptimizationFeedback feedback, DexEncodedMethod method, IRCode code, Timing timing) {
+ timing.begin("Compute non-null-param-or-throw");
+ computeNonNullParamOrThrow(feedback, method, code);
+ timing.end();
+ }
+
// Track usage of parameters and compute their nullability and possibility of NPE.
private void computeNonNullParamOrThrow(
OptimizationFeedback feedback, DexEncodedMethod method, IRCode code) {
@@ -1058,6 +1139,13 @@
}
}
+ private void computeNonNullParamOnNormalExits(
+ OptimizationFeedback feedback, IRCode code, Timing timing) {
+ timing.begin("Compute non-null-param-on-normal-exits");
+ computeNonNullParamOnNormalExits(feedback, code);
+ timing.end();
+ }
+
private void computeNonNullParamOnNormalExits(OptimizationFeedback feedback, IRCode code) {
Set<BasicBlock> normalExits = Sets.newIdentityHashSet();
normalExits.addAll(code.computeNormalExitBlocks());
@@ -1068,7 +1156,7 @@
for (int index = 0; index < arguments.size(); index++) {
Value argument = arguments.get(index);
// Consider reference-type parameter only.
- if (!argument.getTypeLattice().isReference()) {
+ if (!argument.getType().isReferenceType()) {
continue;
}
// The receiver is always non-null on normal exits.
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/MutableFieldOptimizationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/MutableFieldOptimizationInfo.java
index a4917f2..118c285 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/MutableFieldOptimizationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/MutableFieldOptimizationInfo.java
@@ -8,8 +8,8 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLense;
-import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.analysis.value.UnknownValue;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
@@ -31,25 +31,26 @@
private AbstractValue abstractValue = UnknownValue.getInstance();
private int flags;
private int readBits = 0;
- private ClassTypeLatticeElement dynamicLowerBoundType = null;
- private TypeLatticeElement dynamicUpperBoundType = null;
+ private ClassTypeElement dynamicLowerBoundType = null;
+ private TypeElement dynamicUpperBoundType = null;
- public void fixupClassTypeReferences(
+ public MutableFieldOptimizationInfo fixupClassTypeReferences(
Function<DexType, DexType> mapping, AppView<? extends AppInfoWithSubtyping> appView) {
if (dynamicUpperBoundType != null) {
dynamicUpperBoundType = dynamicUpperBoundType.fixupClassTypeReferences(mapping, appView);
}
if (dynamicLowerBoundType != null) {
- TypeLatticeElement dynamicLowerBoundType =
+ TypeElement dynamicLowerBoundType =
this.dynamicLowerBoundType.fixupClassTypeReferences(mapping, appView);
if (dynamicLowerBoundType.isClassType()) {
- this.dynamicLowerBoundType = dynamicLowerBoundType.asClassTypeLatticeElement();
+ this.dynamicLowerBoundType = dynamicLowerBoundType.asClassType();
} else {
- assert dynamicLowerBoundType.isPrimitive();
+ assert dynamicLowerBoundType.isPrimitiveType();
this.dynamicLowerBoundType = null;
this.dynamicUpperBoundType = null;
}
}
+ return this;
}
@Override
@@ -91,20 +92,20 @@
}
@Override
- public ClassTypeLatticeElement getDynamicLowerBoundType() {
+ public ClassTypeElement getDynamicLowerBoundType() {
return dynamicLowerBoundType;
}
- void setDynamicLowerBoundType(ClassTypeLatticeElement type) {
+ void setDynamicLowerBoundType(ClassTypeElement type) {
dynamicLowerBoundType = type;
}
@Override
- public TypeLatticeElement getDynamicUpperBoundType() {
+ public TypeElement getDynamicUpperBoundType() {
return dynamicUpperBoundType;
}
- void setDynamicUpperBoundType(TypeLatticeElement type) {
+ void setDynamicUpperBoundType(TypeElement type) {
dynamicUpperBoundType = type;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackDelayed.java b/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackDelayed.java
index 81d573b..212a044 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackDelayed.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackDelayed.java
@@ -8,8 +8,8 @@
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.classinliner.ClassInlinerEligibilityInfo;
@@ -126,13 +126,12 @@
}
@Override
- public void markFieldHasDynamicLowerBoundType(
- DexEncodedField field, ClassTypeLatticeElement type) {
+ public void markFieldHasDynamicLowerBoundType(DexEncodedField field, ClassTypeElement type) {
getFieldOptimizationInfoForUpdating(field).setDynamicLowerBoundType(type);
}
@Override
- public void markFieldHasDynamicUpperBoundType(DexEncodedField field, TypeLatticeElement type) {
+ public void markFieldHasDynamicUpperBoundType(DexEncodedField field, TypeElement type) {
getFieldOptimizationInfoForUpdating(field).setDynamicUpperBoundType(type);
}
@@ -190,13 +189,13 @@
@Override
public synchronized void methodReturnsObjectWithUpperBoundType(
- DexEncodedMethod method, AppView<?> appView, TypeLatticeElement type) {
+ DexEncodedMethod method, AppView<?> appView, TypeElement type) {
getMethodOptimizationInfoForUpdating(method).markReturnsObjectWithUpperBoundType(appView, type);
}
@Override
public synchronized void methodReturnsObjectWithLowerBoundType(
- DexEncodedMethod method, ClassTypeLatticeElement type) {
+ DexEncodedMethod method, ClassTypeElement type) {
getMethodOptimizationInfoForUpdating(method).markReturnsObjectWithLowerBoundType(type);
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackIgnore.java b/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackIgnore.java
index 66aefb4..2f20a39 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackIgnore.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackIgnore.java
@@ -8,8 +8,8 @@
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.classinliner.ClassInlinerEligibilityInfo;
@@ -40,11 +40,10 @@
public void markFieldAsPropagated(DexEncodedField field) {}
@Override
- public void markFieldHasDynamicLowerBoundType(
- DexEncodedField field, ClassTypeLatticeElement type) {}
+ public void markFieldHasDynamicLowerBoundType(DexEncodedField field, ClassTypeElement type) {}
@Override
- public void markFieldHasDynamicUpperBoundType(DexEncodedField field, TypeLatticeElement type) {}
+ public void markFieldHasDynamicUpperBoundType(DexEncodedField field, TypeElement type) {}
@Override
public void markFieldBitsRead(DexEncodedField field, int bitsRead) {}
@@ -77,11 +76,11 @@
@Override
public void methodReturnsObjectWithUpperBoundType(
- DexEncodedMethod method, AppView<?> appView, TypeLatticeElement type) {}
+ DexEncodedMethod method, AppView<?> appView, TypeElement type) {}
@Override
public void methodReturnsObjectWithLowerBoundType(
- DexEncodedMethod method, ClassTypeLatticeElement type) {}
+ DexEncodedMethod method, ClassTypeElement type) {}
@Override
public void methodMayNotHaveSideEffects(DexEncodedMethod method) {}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackSimple.java b/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackSimple.java
index b258bdf..0bf4d8b 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackSimple.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackSimple.java
@@ -8,8 +8,8 @@
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.classinliner.ClassInlinerEligibilityInfo;
@@ -46,13 +46,12 @@
}
@Override
- public void markFieldHasDynamicLowerBoundType(
- DexEncodedField field, ClassTypeLatticeElement type) {
+ public void markFieldHasDynamicLowerBoundType(DexEncodedField field, ClassTypeElement type) {
// Ignored.
}
@Override
- public void markFieldHasDynamicUpperBoundType(DexEncodedField field, TypeLatticeElement type) {
+ public void markFieldHasDynamicUpperBoundType(DexEncodedField field, TypeElement type) {
// Ignored.
}
@@ -103,13 +102,13 @@
@Override
public void methodReturnsObjectWithUpperBoundType(
- DexEncodedMethod method, AppView<?> appView, TypeLatticeElement type) {
+ DexEncodedMethod method, AppView<?> appView, TypeElement type) {
// Ignored.
}
@Override
public void methodReturnsObjectWithLowerBoundType(
- DexEncodedMethod method, ClassTypeLatticeElement type) {
+ DexEncodedMethod method, ClassTypeElement type) {
// Ignored.
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/UpdatableMethodOptimizationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/UpdatableMethodOptimizationInfo.java
index 366b4d2..ed6233f 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/UpdatableMethodOptimizationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/UpdatableMethodOptimizationInfo.java
@@ -8,8 +8,8 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLense;
-import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.optimize.classinliner.ClassInlinerEligibilityInfo;
import com.android.tools.r8.ir.optimize.info.ParameterUsagesInfo.ParameterUsage;
@@ -28,9 +28,8 @@
private int returnedArgument = DefaultMethodOptimizationInfo.UNKNOWN_RETURNED_ARGUMENT;
private AbstractValue abstractReturnValue =
DefaultMethodOptimizationInfo.UNKNOWN_ABSTRACT_RETURN_VALUE;
- private TypeLatticeElement returnsObjectWithUpperBoundType =
- DefaultMethodOptimizationInfo.UNKNOWN_TYPE;
- private ClassTypeLatticeElement returnsObjectWithLowerBoundType =
+ private TypeElement returnsObjectWithUpperBoundType = DefaultMethodOptimizationInfo.UNKNOWN_TYPE;
+ private ClassTypeElement returnsObjectWithLowerBoundType =
DefaultMethodOptimizationInfo.UNKNOWN_CLASS_TYPE;
private InlinePreference inlining = InlinePreference.Default;
// Stores information about instance methods and constructors for
@@ -142,24 +141,24 @@
nonNullParamOnNormalExits = template.nonNullParamOnNormalExits;
}
- public void fixupClassTypeReferences(
+ public UpdatableMethodOptimizationInfo fixupClassTypeReferences(
Function<DexType, DexType> mapping, AppView<? extends AppInfoWithSubtyping> appView) {
if (returnsObjectWithUpperBoundType != null) {
returnsObjectWithUpperBoundType =
returnsObjectWithUpperBoundType.fixupClassTypeReferences(mapping, appView);
}
if (returnsObjectWithLowerBoundType != null) {
- TypeLatticeElement returnsObjectWithLowerBoundType =
+ TypeElement returnsObjectWithLowerBoundType =
this.returnsObjectWithLowerBoundType.fixupClassTypeReferences(mapping, appView);
if (returnsObjectWithLowerBoundType.isClassType()) {
- this.returnsObjectWithLowerBoundType =
- returnsObjectWithLowerBoundType.asClassTypeLatticeElement();
+ this.returnsObjectWithLowerBoundType = returnsObjectWithLowerBoundType.asClassType();
} else {
- assert returnsObjectWithLowerBoundType.isPrimitive();
+ assert returnsObjectWithLowerBoundType.isPrimitiveType();
this.returnsObjectWithUpperBoundType = DefaultMethodOptimizationInfo.UNKNOWN_TYPE;
this.returnsObjectWithLowerBoundType = DefaultMethodOptimizationInfo.UNKNOWN_CLASS_TYPE;
}
}
+ return this;
}
public UpdatableMethodOptimizationInfo fixupAbstractReturnValue(
@@ -231,12 +230,12 @@
}
@Override
- public TypeLatticeElement getDynamicUpperBoundType() {
+ public TypeElement getDynamicUpperBoundType() {
return returnsObjectWithUpperBoundType;
}
@Override
- public ClassTypeLatticeElement getDynamicLowerBoundType() {
+ public ClassTypeElement getDynamicLowerBoundType() {
return returnsObjectWithLowerBoundType;
}
@@ -405,7 +404,7 @@
abstractReturnValue = value;
}
- void markReturnsObjectWithUpperBoundType(AppView<?> appView, TypeLatticeElement type) {
+ void markReturnsObjectWithUpperBoundType(AppView<?> appView, TypeElement type) {
assert type != null;
// We may get more precise type information if the method is reprocessed (e.g., due to
// optimization info collected from all call sites), and hence the
@@ -420,7 +419,7 @@
returnsObjectWithUpperBoundType = type;
}
- void markReturnsObjectWithLowerBoundType(ClassTypeLatticeElement type) {
+ void markReturnsObjectWithLowerBoundType(ClassTypeElement type) {
assert type != null;
// Currently, we only have a lower bound type when we have _exact_ runtime type information.
// Thus, the type should never become more precise (although the nullability could).
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/field/InstanceFieldInitializationInfoFactory.java b/src/main/java/com/android/tools/r8/ir/optimize/info/field/InstanceFieldInitializationInfoFactory.java
index eb7cdda..87f4c2a 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/field/InstanceFieldInitializationInfoFactory.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/field/InstanceFieldInitializationInfoFactory.java
@@ -4,8 +4,8 @@
package com.android.tools.r8.ir.optimize.info.field;
-import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import java.util.concurrent.ConcurrentHashMap;
public class InstanceFieldInitializationInfoFactory {
@@ -20,7 +20,7 @@
}
public InstanceFieldTypeInitializationInfo createTypeInitializationInfo(
- ClassTypeLatticeElement dynamicLowerBoundType, TypeLatticeElement dynamicUpperBoundType) {
+ ClassTypeElement dynamicLowerBoundType, TypeElement dynamicUpperBoundType) {
return new InstanceFieldTypeInitializationInfo(dynamicLowerBoundType, dynamicUpperBoundType);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/field/InstanceFieldTypeInitializationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/field/InstanceFieldTypeInitializationInfo.java
index 91d1aef..ec77b22 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/field/InstanceFieldTypeInitializationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/field/InstanceFieldTypeInitializationInfo.java
@@ -7,8 +7,8 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.EnumValueInfoMapCollection;
import com.android.tools.r8.graph.GraphLense;
-import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import java.util.Objects;
@@ -18,21 +18,21 @@
*/
public class InstanceFieldTypeInitializationInfo implements InstanceFieldInitializationInfo {
- private final ClassTypeLatticeElement dynamicLowerBoundType;
- private final TypeLatticeElement dynamicUpperBoundType;
+ private final ClassTypeElement dynamicLowerBoundType;
+ private final TypeElement dynamicUpperBoundType;
/** Intentionally package private, use {@link InstanceFieldInitializationInfoFactory} instead. */
InstanceFieldTypeInitializationInfo(
- ClassTypeLatticeElement dynamicLowerBoundType, TypeLatticeElement dynamicUpperBoundType) {
+ ClassTypeElement dynamicLowerBoundType, TypeElement dynamicUpperBoundType) {
this.dynamicLowerBoundType = dynamicLowerBoundType;
this.dynamicUpperBoundType = dynamicUpperBoundType;
}
- public ClassTypeLatticeElement getDynamicLowerBoundType() {
+ public ClassTypeElement getDynamicLowerBoundType() {
return dynamicLowerBoundType;
}
- public TypeLatticeElement getDynamicUpperBoundType() {
+ public TypeElement getDynamicUpperBoundType() {
return dynamicUpperBoundType;
}
@@ -56,8 +56,7 @@
return UnknownInstanceFieldInitializationInfo.getInstance();
}
if (dynamicUpperBoundType.isClassType()
- && unboxedEnums.containsEnum(
- dynamicUpperBoundType.asClassTypeLatticeElement().getClassType())) {
+ && unboxedEnums.containsEnum(dynamicUpperBoundType.asClassType().getClassType())) {
// No point in tracking the type of primitives.
return UnknownInstanceFieldInitializationInfo.getInstance();
}
@@ -65,7 +64,7 @@
dynamicLowerBoundType != null
? dynamicLowerBoundType
.fixupClassTypeReferences(lens::lookupType, appView.withSubtyping())
- .asClassTypeLatticeElement()
+ .asClassType()
: null,
dynamicUpperBoundType.fixupClassTypeReferences(lens::lookupType, appView.withSubtyping()));
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java
index 510c122..ce2394c 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java
@@ -594,8 +594,7 @@
// able to propagate the type information correctly, since lambda merging is neither a
// narrowing nor a widening.
for (Value value : transitivelyTypeAffectedValues) {
- value.setTypeLattice(
- value.getTypeLattice().fixupClassTypeReferences(optimizationInfoFixer, appView));
+ value.setType(value.getType().fixupClassTypeReferences(optimizationInfoFixer, appView));
}
// Filter out the type affected phis and destructively update the type of the phis. This is
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaTypeVisitor.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaTypeVisitor.java
index 7422bc0..9dce489 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaTypeVisitor.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaTypeVisitor.java
@@ -17,12 +17,6 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DexTypeList;
import com.android.tools.r8.graph.DexValue;
-import com.android.tools.r8.graph.DexValue.DexValueArray;
-import com.android.tools.r8.graph.DexValue.DexValueField;
-import com.android.tools.r8.graph.DexValue.DexValueMethod;
-import com.android.tools.r8.graph.DexValue.DexValueMethodHandle;
-import com.android.tools.r8.graph.DexValue.DexValueMethodType;
-import com.android.tools.r8.graph.DexValue.DexValueType;
import com.android.tools.r8.graph.ParameterAnnotationsList;
import java.util.function.Consumer;
import java.util.function.Predicate;
@@ -49,30 +43,29 @@
}
private void accept(DexValue value) {
- if (value instanceof DexValueType) {
- accept(((DexValueType) value).value);
- return;
- }
- if (value instanceof DexValueArray) {
- for (DexValue subValue : ((DexValueArray) value).getValues()) {
- accept(subValue);
- }
- return;
- }
- if (value instanceof DexValueMethod) {
- accept(((DexValueMethod) value).value, null);
- return;
- }
- if (value instanceof DexValueMethodHandle) {
- accept(((DexValueMethodHandle) value).value);
- return;
- }
- if (value instanceof DexValueMethodType) {
- accept(((DexValueMethodType) value).value);
- return;
- }
- if (value instanceof DexValueField) {
- accept(((DexValueField) value).value, null);
+ switch (value.getValueKind()) {
+ case ARRAY:
+ for (DexValue elementValue : value.asDexValueArray().getValues()) {
+ accept(elementValue);
+ }
+ break;
+ case FIELD:
+ accept(value.asDexValueField().value, null);
+ break;
+ case METHOD:
+ accept(value.asDexValueMethod().value, null);
+ break;
+ case METHOD_HANDLE:
+ accept(value.asDexValueMethodHandle().value);
+ break;
+ case METHOD_TYPE:
+ accept(value.asDexValueMethodType().value);
+ break;
+ case TYPE:
+ accept(value.asDexValueType().value);
+ break;
+ default:
+ // Intentionally empty.
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/ClassInitializerSourceCode.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/ClassInitializerSourceCode.java
index b679383..0eec9af 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/ClassInitializerSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/ClassInitializerSourceCode.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DexTypeList;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.Invoke.Type;
import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.ir.code.ValueType;
@@ -47,7 +47,7 @@
if (group.isSingletonLambda(lambda)) {
int id = group.lambdaId(lambda);
add(builder -> builder.addNewInstance(instance, groupClassType));
- add(builder -> builder.addConst(TypeLatticeElement.getInt(), lambdaId, id));
+ add(builder -> builder.addConst(TypeElement.getInt(), lambdaId, id));
add(
builder ->
builder.addInvoke(
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KStyleLambdaGroup.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KStyleLambdaGroup.java
index b510e88..0295106 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KStyleLambdaGroup.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KStyleLambdaGroup.java
@@ -18,7 +18,7 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.EnclosingMethodAttribute;
import com.android.tools.r8.graph.InnerClassAttribute;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.Invoke.Type;
import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.ir.code.ValueType;
@@ -240,7 +240,7 @@
@Override
void prepareSuperConstructorCall(int receiverRegister) {
int arityRegister = nextRegister(ValueType.INT);
- add(builder -> builder.addConst(TypeLatticeElement.getInt(), arityRegister, arity));
+ add(builder -> builder.addConst(TypeElement.getInt(), arityRegister, arity));
add(
builder ->
builder.addInvoke(
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupClassBuilder.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupClassBuilder.java
index 6bc95f2..9f14329 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupClassBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupClassBuilder.java
@@ -25,7 +25,7 @@
import com.android.tools.r8.graph.InnerClassAttribute;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.graph.ParameterAnnotationsList;
-import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedback;
import com.android.tools.r8.ir.optimize.lambda.LambdaGroupClassBuilder;
@@ -240,8 +240,8 @@
// Record that the field is definitely not null. It is guaranteed to be assigned in the
// class initializer of the enclosing class before it is read.
- ClassTypeLatticeElement exactType =
- ClassTypeLatticeElement.create(field.type, definitelyNotNull(), appView);
+ ClassTypeElement exactType =
+ ClassTypeElement.create(field.type, definitelyNotNull(), appView);
feedback.markFieldHasDynamicLowerBoundType(encodedField, exactType);
feedback.markFieldHasDynamicUpperBoundType(encodedField, exactType);
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupCodeStrategy.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupCodeStrategy.java
index 81480d6..3e602b7 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupCodeStrategy.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupCodeStrategy.java
@@ -12,7 +12,7 @@
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.CheckCast;
import com.android.tools.r8.ir.code.ConstNumber;
import com.android.tools.r8.ir.code.InitClass;
@@ -128,7 +128,7 @@
new NewInstance(
newType,
context.code.createValue(
- TypeLatticeElement.fromDexType(newType, definitelyNotNull(), context.appView)));
+ TypeElement.fromDexType(newType, definitelyNotNull(), context.appView)));
context.instructions().replaceCurrentInstruction(patchedNewInstance);
assert newType != oldType;
@@ -178,8 +178,8 @@
// Since all captured values of non-primitive types are stored in fields of type
// java.lang.Object, we need to cast them to appropriate type to satisfy the verifier.
- TypeLatticeElement castTypeLattice =
- TypeLatticeElement.fromDexType(oldFieldType, maybeNull(), context.appView);
+ TypeElement castTypeLattice =
+ TypeElement.fromDexType(oldFieldType, maybeNull(), context.appView);
Value newValue = context.code.createValue(castTypeLattice, newInstanceGet.getLocalInfo());
newInstanceGet.outValue().replaceUsers(newValue);
CheckCast cast = new CheckCast(newValue, newInstanceGet.outValue(), oldFieldType);
@@ -202,7 +202,7 @@
StaticGet patchedStaticGet =
new StaticGet(
context.code.createValue(
- TypeLatticeElement.fromDexType(newField.type, maybeNull(), context.appView)),
+ TypeElement.fromDexType(newField.type, maybeNull(), context.appView)),
newField);
context.instructions().replaceCurrentInstruction(patchedStaticGet);
@@ -213,8 +213,7 @@
@Override
public void patch(ApplyStrategy context, InitClass initClass) {
InitClass pachedInitClass =
- new InitClass(
- context.code.createValue(TypeLatticeElement.getInt()), group.getGroupClassType());
+ new InitClass(context.code.createValue(TypeElement.getInt()), group.getGroupClassType());
context.instructions().replaceCurrentInstruction(pachedInitClass);
}
@@ -229,7 +228,7 @@
DexType lambda = method.holder;
// Create constant with lambda id.
- Value lambdaIdValue = context.code.createValue(TypeLatticeElement.getInt());
+ Value lambdaIdValue = context.code.createValue(TypeElement.getInt());
ConstNumber lambdaId = new ConstNumber(lambdaIdValue, group.lambdaId(lambda));
lambdaId.setPosition(invoke.getPosition());
context.instructions().previous();
@@ -250,7 +249,7 @@
return returnType == context.factory.voidType
? null
: context.code.createValue(
- TypeLatticeElement.fromDexType(returnType, maybeNull(), context.appView));
+ TypeElement.fromDexType(returnType, maybeNull(), context.appView));
}
private List<Value> mapInitializerArgs(
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/library/ObjectsMethodOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/library/ObjectsMethodOptimizer.java
index 975aca8..f76aeae 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/library/ObjectsMethodOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/library/ObjectsMethodOptimizer.java
@@ -42,7 +42,7 @@
private void optimizeRequireNonNull(
InstructionListIterator instructionIterator, InvokeMethod invoke, Set<Value> affectedValues) {
Value inValue = invoke.inValues().get(0);
- if (inValue.getTypeLattice().isDefinitelyNotNull()) {
+ if (inValue.getType().isDefinitelyNotNull()) {
Value outValue = invoke.outValue();
if (outValue != null) {
affectedValues.addAll(outValue.affectedValues());
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/peepholes/DupDupDupPeephole.java b/src/main/java/com/android/tools/r8/ir/optimize/peepholes/DupDupDupPeephole.java
index 8d84870..b1b2eb54 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/peepholes/DupDupDupPeephole.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/peepholes/DupDupDupPeephole.java
@@ -28,11 +28,11 @@
public class DupDupDupPeephole implements BasicBlockPeephole {
private final Point dup1Exp =
- new Point((i) -> i.isDup() && !i.inValues().get(0).getTypeLattice().isWidePrimitive());
+ new Point((i) -> i.isDup() && !i.inValues().get(0).getType().isWidePrimitive());
private final Point dup2Exp =
- new Point((i) -> i.isDup() && !i.inValues().get(0).getTypeLattice().isWidePrimitive());
+ new Point((i) -> i.isDup() && !i.inValues().get(0).getType().isWidePrimitive());
private final Point dup3Exp =
- new Point((i) -> i.isDup() && !i.inValues().get(0).getTypeLattice().isWidePrimitive());
+ new Point((i) -> i.isDup() && !i.inValues().get(0).getType().isWidePrimitive());
private final PeepholeLayout layout = PeepholeLayout.lookBackward(dup1Exp, dup2Exp, dup3Exp);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/peepholes/MoveLoadUpPeephole.java b/src/main/java/com/android/tools/r8/ir/optimize/peepholes/MoveLoadUpPeephole.java
index 49a74d1..127b144 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/peepholes/MoveLoadUpPeephole.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/peepholes/MoveLoadUpPeephole.java
@@ -4,7 +4,7 @@
package com.android.tools.r8.ir.optimize.peepholes;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.InstructionListIterator;
import com.android.tools.r8.ir.code.Load;
@@ -113,7 +113,7 @@
Instruction current = it.next();
if (position != current.getPosition()
|| !current.isConstNumber()
- || current.outValue().getTypeLattice() != TypeLatticeElement.getInt()
+ || current.outValue().getType() != TypeElement.getInt()
|| current.asConstNumber().getIntValue() < -128
|| current.asConstNumber().getIntValue() > 127
|| !it.hasNext()) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/peepholes/StoreSequenceLoadPeephole.java b/src/main/java/com/android/tools/r8/ir/optimize/peepholes/StoreSequenceLoadPeephole.java
index 421bdbf..1ff49d0 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/peepholes/StoreSequenceLoadPeephole.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/peepholes/StoreSequenceLoadPeephole.java
@@ -40,7 +40,7 @@
new Point(
(i) -> {
if (!i.isStore()
- || i.asStore().src().getTypeLattice().isWidePrimitive()
+ || i.asStore().src().getType().isWidePrimitive()
|| i.outValue().hasLocalInfo()
|| i.asStore().outValue().numberOfAllUsers() != 1) {
return false;
@@ -102,7 +102,7 @@
lastOut = stackValues[stackValues.length - 1];
}
- if (lastOut == null || lastOut.getTypeLattice().isWidePrimitive()) {
+ if (lastOut == null || lastOut.getType().isWidePrimitive()) {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
index e0ca9093..f79593b 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
@@ -14,7 +14,7 @@
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.InstructionListIterator;
@@ -536,7 +536,7 @@
Value newValue = null;
Value outValue = invoke.outValue();
if (outValue != null) {
- newValue = code.createValue(outValue.getTypeLattice());
+ newValue = code.createValue(outValue.getType());
DebugLocalInfo localInfo = outValue.getLocalInfo();
if (localInfo != null) {
newValue.setLocalInfo(localInfo);
@@ -563,8 +563,8 @@
it.replaceCurrentInstruction(
new StaticGet(
code.createValue(
- TypeLatticeElement.fromDexType(
- field.type, outValue.getTypeLattice().nullability(), appView),
+ TypeElement.fromDexType(
+ field.type, outValue.getType().nullability(), appView),
outValue.getLocalInfo()),
field));
}
@@ -592,8 +592,8 @@
returnType.isVoidType() || outValue == null
? null
: code.createValue(
- TypeLatticeElement.fromDexType(
- returnType, outValue.getTypeLattice().nullability(), appView),
+ TypeElement.fromDexType(
+ returnType, outValue.getType().nullability(), appView),
outValue.getLocalInfo());
it.replaceCurrentInstruction(new InvokeStatic(newMethod, newOutValue, invoke.inValues()));
}
@@ -724,7 +724,7 @@
methodMapping.put(originalMethod, newMethod.method);
}
}
- hostClass.appendDirectMethods(newMethods);
+ hostClass.addDirectMethods(newMethods);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderOptimizer.java
index 6c714c9..20ea5df 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderOptimizer.java
@@ -14,7 +14,7 @@
import com.android.tools.r8.ir.analysis.escape.EscapeAnalysis;
import com.android.tools.r8.ir.analysis.escape.EscapeAnalysisConfiguration;
import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.Assume;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.BasicBlock.ThrowingInfo;
@@ -294,8 +294,8 @@
}
// Make sure builder is neither phi nor coming from outside of the method.
assert !builder.isPhi() && builder.definition.isNewInstance();
- assert builder.getTypeLattice().isClassType();
- DexType builderType = builder.getTypeLattice().asClassTypeLatticeElement().getClassType();
+ assert builder.getType().isClassType();
+ DexType builderType = builder.getType().asClassType().getClassType();
assert optimizationConfiguration.isBuilderType(builderType);
EscapeAnalysis escapeAnalysis =
new EscapeAnalysis(
@@ -442,7 +442,7 @@
if (number == null) {
return addition;
}
- if (arg.getTypeLattice().isPrimitive()) {
+ if (arg.getType().isPrimitiveType()) {
if (argType == factory.booleanType) {
addition = String.valueOf(number.intValue() != 0);
} else if (argType == factory.byteType) {
@@ -460,7 +460,7 @@
} else if (argType == factory.doubleType) {
addition = String.valueOf(number.doubleValue());
}
- } else if (arg.getTypeLattice().isNullType()) {
+ } else if (arg.getType().isNullType()) {
assert number.intValue() == 0;
addition = "null";
}
@@ -591,7 +591,7 @@
if (outValue != null && outValue.isUsed()) {
Value dummy =
code.createValue(
- TypeLatticeElement.stringClassType(appView, definitelyNotNull()),
+ TypeElement.stringClassType(appView, definitelyNotNull()),
invoke.getLocalInfo());
it.replaceCurrentInstruction(
new ConstString(dummy, factory.createString(DUMMY), throwingInfo));
@@ -612,8 +612,7 @@
assert element != null;
Value stringValue =
code.createValue(
- TypeLatticeElement.stringClassType(appView, definitelyNotNull()),
- invoke.getLocalInfo());
+ TypeElement.stringClassType(appView, definitelyNotNull()), invoke.getLocalInfo());
affectedValues.addAll(outValue.affectedValues());
it.replaceCurrentInstruction(
new ConstString(stringValue, factory.createString(element), throwingInfo));
@@ -815,7 +814,7 @@
public boolean isBuilderInitWithInitialValue(InvokeMethod invoke) {
return isBuilderInit(invoke.getInvokedMethod())
&& invoke.inValues().size() == 2
- && !invoke.inValues().get(1).getTypeLattice().isPrimitive();
+ && !invoke.inValues().get(1).getType().isPrimitiveType();
}
@Override
@@ -838,13 +837,13 @@
return false;
}
assert invoke.inValues().size() == 2;
- TypeLatticeElement argType = invoke.inValues().get(1).getTypeLattice();
- if (!argType.isPrimitive() && !argType.isClassType() && !argType.isNullType()) {
+ TypeElement argType = invoke.inValues().get(1).getType();
+ if (!argType.isPrimitiveType() && !argType.isClassType() && !argType.isNullType()) {
numberOfBuildersWithUnsupportedArg++;
return false;
}
if (argType.isClassType()) {
- DexType argClassType = argType.asClassTypeLatticeElement().getClassType();
+ DexType argClassType = argType.asClassType().getClassType();
return canHandleArgumentType(argClassType);
}
return true;
@@ -868,8 +867,8 @@
private StringBuilderOptimizerEscapeAnalysisConfiguration(Value builder) {
this.builder = builder;
- assert builder.getTypeLattice().isClassType();
- builderType = builder.getTypeLattice().asClassTypeLatticeElement().getClassType();
+ assert builder.getType().isClassType();
+ builderType = builder.getType().asClassType().getClassType();
}
private void logEscapingRoute(boolean legitimate) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/string/StringOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/string/StringOptimizer.java
index 072f762..a2b8eb5 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/string/StringOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/string/StringOptimizer.java
@@ -20,7 +20,7 @@
import com.android.tools.r8.ir.analysis.escape.EscapeAnalysis;
import com.android.tools.r8.ir.analysis.escape.EscapeAnalysisConfiguration;
import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.BasicBlock.ThrowingInfo;
import com.android.tools.r8.ir.code.ConstClass;
import com.android.tools.r8.ir.code.ConstNumber;
@@ -183,8 +183,7 @@
String sub = rcvString.substring(beginIndexValue, endIndexValue);
Value stringValue =
code.createValue(
- TypeLatticeElement.stringClassType(appView, definitelyNotNull()),
- invoke.getLocalInfo());
+ TypeElement.stringClassType(appView, definitelyNotNull()), invoke.getLocalInfo());
affectedValues.addAll(invoke.outValue().affectedValues());
it.replaceCurrentInstruction(
new ConstString(stringValue, factory.createString(sub), throwingInfo));
@@ -201,8 +200,7 @@
factory.createString(receiver.definition.asConstString().getValue().toString().trim());
Value newOutValue =
code.createValue(
- TypeLatticeElement.stringClassType(appView, definitelyNotNull()),
- invoke.getLocalInfo());
+ TypeElement.stringClassType(appView, definitelyNotNull()), invoke.getLocalInfo());
affectedValues.addAll(invoke.outValue().affectedValues());
it.replaceCurrentInstruction(new ConstString(newOutValue, resultString, throwingInfo));
numberOfSimplifiedOperations++;
@@ -443,8 +441,7 @@
affectedValues.addAll(invoke.outValue().affectedValues());
Value stringValue =
code.createValue(
- TypeLatticeElement.stringClassType(appView, definitelyNotNull()),
- invoke.getLocalInfo());
+ TypeElement.stringClassType(appView, definitelyNotNull()), invoke.getLocalInfo());
ConstString constString = new ConstString(stringValue, name, throwingInfo);
it.replaceCurrentInstruction(constString);
logHistogramOfNames(name);
@@ -525,20 +522,19 @@
continue;
}
Value out = invoke.outValue();
- TypeLatticeElement inType = in.getTypeLattice();
+ TypeElement inType = in.getType();
if (out != null && in.isAlwaysNull(appView)) {
affectedValues.addAll(out.affectedValues());
Value nullStringValue =
code.createValue(
- TypeLatticeElement.stringClassType(appView, definitelyNotNull()),
- invoke.getLocalInfo());
+ TypeElement.stringClassType(appView, definitelyNotNull()), invoke.getLocalInfo());
ConstString nullString =
new ConstString(nullStringValue, factory.createString("null"), throwingInfo);
it.replaceCurrentInstruction(nullString);
numberOfSimplifiedConversions++;
} else if (inType.nullability().isDefinitelyNotNull()
&& inType.isClassType()
- && inType.asClassTypeLatticeElement().getClassType().equals(factory.stringType)) {
+ && inType.asClassType().getClassType().equals(factory.stringType)) {
if (out != null) {
affectedValues.addAll(out.affectedValues());
removeOrReplaceByDebugLocalWrite(invoke, it, in, out);
@@ -555,10 +551,10 @@
}
assert invoke.inValues().size() == 1;
Value in = invoke.getReceiver();
- TypeLatticeElement inType = in.getTypeLattice();
+ TypeElement inType = in.getType();
if (inType.nullability().isDefinitelyNotNull()
&& inType.isClassType()
- && inType.asClassTypeLatticeElement().getClassType().equals(factory.stringType)) {
+ && inType.asClassType().getClassType().equals(factory.stringType)) {
Value out = invoke.outValue();
if (out != null) {
affectedValues.addAll(out.affectedValues());
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 5dcdbd8..0f6f6c9 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
@@ -12,7 +12,7 @@
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DebugLocalInfo;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.Add;
import com.android.tools.r8.ir.code.And;
import com.android.tools.r8.ir.code.ArithmeticBinop;
@@ -2747,7 +2747,7 @@
return true;
}
- private Value createValue(TypeLatticeElement typeLattice) {
+ private Value createValue(TypeElement typeLattice) {
Value value = code.createValue(typeLattice, null);
value.setNeedsRegister(true);
return value;
@@ -2800,7 +2800,7 @@
argument.isLinked() ||
argument == previous ||
argument.hasRegisterConstraint()) {
- newArgument = createValue(argument.getTypeLattice());
+ newArgument = createValue(argument.getType());
Move move = new Move(newArgument, argument);
move.setBlock(invoke.getBlock());
replaceArgument(invoke, i, newArgument);
diff --git a/src/main/java/com/android/tools/r8/ir/regalloc/RegisterMove.java b/src/main/java/com/android/tools/r8/ir/regalloc/RegisterMove.java
index dda59e6..60c7c49 100644
--- a/src/main/java/com/android/tools/r8/ir/regalloc/RegisterMove.java
+++ b/src/main/java/com/android/tools/r8/ir/regalloc/RegisterMove.java
@@ -3,7 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.regalloc;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.Instruction;
import java.util.Map;
import java.util.Set;
@@ -12,19 +12,19 @@
// for phi moves and they are moves between actual registers represented by their register number.
public class RegisterMove implements Comparable<RegisterMove> {
- final TypeLatticeElement type;
+ final TypeElement type;
final int dst;
final int src;
final Instruction definition;
- public RegisterMove(int dst, int src, TypeLatticeElement type) {
+ public RegisterMove(int dst, int src, TypeElement type) {
this.dst = dst;
this.src = src;
this.definition = null;
this.type = type;
}
- public RegisterMove(int dst, TypeLatticeElement type, Instruction definition) {
+ public RegisterMove(int dst, TypeElement type, Instruction definition) {
assert definition.isOutConstant();
this.dst = dst;
this.src = LiveIntervals.NO_REGISTER;
@@ -82,14 +82,14 @@
if (dstDiff != 0) {
return dstDiff;
}
- if (type.isPrimitive() != o.type.isPrimitive()) {
- return Boolean.compare(type.isPrimitive(), o.type.isPrimitive());
+ if (type.isPrimitiveType() != o.type.isPrimitiveType()) {
+ return Boolean.compare(type.isPrimitiveType(), o.type.isPrimitiveType());
}
if (type.isWidePrimitive() != o.type.isWidePrimitive()) {
return Boolean.compare(type.isWidePrimitive(), o.type.isWidePrimitive());
}
- if (type.isReference() != o.type.isReference()) {
- return Boolean.compare(type.isReference(), o.type.isReference());
+ if (type.isReferenceType() != o.type.isReferenceType()) {
+ return Boolean.compare(type.isReferenceType(), o.type.isReferenceType());
}
if (definition == null) {
if (o.definition != null) {
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 08afab7..1cb6482 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
@@ -4,7 +4,7 @@
package com.android.tools.r8.ir.regalloc;
import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.Argument;
import com.android.tools.r8.ir.code.ConstInstruction;
import com.android.tools.r8.ir.code.ConstNumber;
@@ -114,7 +114,7 @@
return usedTempRegisters;
}
- private List<RegisterMove> findMovesWithSrc(int src, TypeLatticeElement type) {
+ private List<RegisterMove> findMovesWithSrc(int src, TypeElement type) {
List<RegisterMove> result = new ArrayList<>();
assert src != LiveIntervals.NO_REGISTER;
for (RegisterMove move : moveSet) {
@@ -139,17 +139,14 @@
if (move.definition.isArgument()) {
Argument argument = move.definition.asArgument();
int argumentRegister = argument.outValue().getLiveIntervals().getRegister();
- Value to =
- new FixedRegisterValue(argument.outValue().getTypeLattice(), move.dst);
- Value from =
- new FixedRegisterValue(argument.outValue().getTypeLattice(), argumentRegister);
+ Value to = new FixedRegisterValue(argument.outValue().getType(), move.dst);
+ Value from = new FixedRegisterValue(argument.outValue().getType(), argumentRegister);
instruction = new Move(to, from);
} else {
assert move.definition.isOutConstant();
ConstInstruction definition = move.definition.getOutConstantConstInstruction();
if (definition.isConstNumber()) {
- Value to =
- new FixedRegisterValue(move.definition.outValue().getTypeLattice(), move.dst);
+ Value to = new FixedRegisterValue(move.definition.outValue().getType(), move.dst);
instruction = new ConstNumber(to, definition.asConstNumber().getRawValue());
} else {
throw new Unreachable("Unexpected definition");
diff --git a/src/main/java/com/android/tools/r8/ir/regalloc/SpillMove.java b/src/main/java/com/android/tools/r8/ir/regalloc/SpillMove.java
index 84f51f1..b33743e 100644
--- a/src/main/java/com/android/tools/r8/ir/regalloc/SpillMove.java
+++ b/src/main/java/com/android/tools/r8/ir/regalloc/SpillMove.java
@@ -4,7 +4,7 @@
package com.android.tools.r8.ir.regalloc;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
/**
* A SpillMove represents either a phi move that transfers an SSA value to the SSA phi value or
@@ -12,11 +12,11 @@
* of spilling.
*/
class SpillMove {
- final TypeLatticeElement type;
+ final TypeElement type;
LiveIntervals from;
final LiveIntervals to;
- public SpillMove(TypeLatticeElement type, LiveIntervals to, LiveIntervals from) {
+ public SpillMove(TypeElement type, LiveIntervals to, LiveIntervals from) {
this.type = type;
this.to = to;
this.from = from;
diff --git a/src/main/java/com/android/tools/r8/ir/regalloc/SpillMoveSet.java b/src/main/java/com/android/tools/r8/ir/regalloc/SpillMoveSet.java
index a5506d9..1c13ae6 100644
--- a/src/main/java/com/android/tools/r8/ir/regalloc/SpillMoveSet.java
+++ b/src/main/java/com/android/tools/r8/ir/regalloc/SpillMoveSet.java
@@ -6,7 +6,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
@@ -36,7 +36,7 @@
// The register allocator generating moves.
private final LinearScanRegisterAllocator allocator;
// Reference to the object type.
- private final TypeLatticeElement objectType;
+ private final TypeElement objectType;
// Mapping from instruction numbers to the block that start with that instruction if any.
private final Map<Integer, BasicBlock> blockStartMap = new HashMap<>();
// The number of temporary registers used for parallel moves when scheduling the moves.
@@ -45,7 +45,7 @@
public SpillMoveSet(LinearScanRegisterAllocator allocator, IRCode code, AppView<?> appView) {
this.allocator = allocator;
this.code = code;
- this.objectType = TypeLatticeElement.objectClassType(appView, Nullability.maybeNull());
+ this.objectType = TypeElement.objectClassType(appView, Nullability.maybeNull());
for (BasicBlock block : code.blocks) {
blockStartMap.put(block.entry().getNumber(), block);
}
@@ -197,12 +197,12 @@
return usedTempRegisters;
}
- private TypeLatticeElement moveTypeForIntervals(LiveIntervals to, LiveIntervals from) {
- TypeLatticeElement toType = to.getValue().getTypeLattice();
- TypeLatticeElement fromType = from.getValue().getTypeLattice();
- if (toType.isReference() || fromType.isReference()) {
- assert fromType.isReference() || fromType.isSinglePrimitive();
- assert toType.isReference() || toType.isSinglePrimitive();
+ private TypeElement moveTypeForIntervals(LiveIntervals to, LiveIntervals from) {
+ TypeElement toType = to.getValue().getType();
+ TypeElement fromType = from.getValue().getType();
+ if (toType.isReferenceType() || fromType.isReferenceType()) {
+ assert fromType.isReferenceType() || fromType.isSinglePrimitive();
+ assert toType.isReferenceType() || toType.isSinglePrimitive();
return objectType;
}
assert toType == fromType;
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 7822316..688d59b 100644
--- a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
@@ -26,13 +26,8 @@
import com.android.tools.r8.graph.DexValue.DexValueAnnotation;
import com.android.tools.r8.graph.DexValue.DexValueArray;
import com.android.tools.r8.graph.DexValue.DexValueEnum;
-import com.android.tools.r8.graph.DexValue.DexValueField;
import com.android.tools.r8.graph.DexValue.DexValueInt;
-import com.android.tools.r8.graph.DexValue.DexValueMethod;
-import com.android.tools.r8.graph.DexValue.DexValueMethodHandle;
-import com.android.tools.r8.graph.DexValue.DexValueMethodType;
import com.android.tools.r8.graph.DexValue.DexValueString;
-import com.android.tools.r8.graph.DexValue.DexValueType;
import com.android.tools.r8.graph.GraphLense;
import com.android.tools.r8.graph.InnerClassAttribute;
import com.android.tools.r8.graph.NestMemberClassAttribute;
@@ -234,29 +229,26 @@
}
private String getSignature(DexAnnotationSet annotations) {
- DexValueArray value =
- (DexValueArray)
- getSystemAnnotationValue(annotations, application.dexItemFactory.annotationSignature);
+ DexValue value =
+ getSystemAnnotationValue(annotations, application.dexItemFactory.annotationSignature);
if (value == null) {
return null;
}
// Signature has already been minified by ClassNameMinifier.renameTypesInGenericSignatures().
- DexValue[] parts = value.getValues();
StringBuilder res = new StringBuilder();
- for (DexValue part : parts) {
- res.append(((DexValueString) part).getValue().toString());
+ for (DexValue part : value.asDexValueArray().getValues()) {
+ res.append(part.asDexValueString().getValue().toString());
}
return res.toString();
}
private ImmutableMap<DexString, DexValue> getAnnotationDefaults(DexAnnotationSet annotations) {
- DexValueAnnotation value =
- (DexValueAnnotation)
- getSystemAnnotationValue(annotations, application.dexItemFactory.annotationDefault);
+ DexValue value =
+ getSystemAnnotationValue(annotations, application.dexItemFactory.annotationDefault);
if (value == null) {
return ImmutableMap.of();
}
- DexEncodedAnnotation annotation = value.value;
+ DexEncodedAnnotation annotation = value.asDexValueAnnotation().value;
Builder<DexString, DexValue> builder = ImmutableMap.builder();
for (DexAnnotationElement element : annotation.elements) {
builder.put(element.name, element.value);
@@ -265,16 +257,15 @@
}
private String[] getExceptions(DexAnnotationSet annotations) {
- DexValueArray value =
- (DexValueArray)
- getSystemAnnotationValue(annotations, application.dexItemFactory.annotationThrows);
+ DexValue value =
+ getSystemAnnotationValue(annotations, application.dexItemFactory.annotationThrows);
if (value == null) {
return null;
}
- DexValue[] values = value.getValues();
+ DexValue[] values = value.asDexValueArray().getValues();
String[] res = new String[values.length];
for (int i = 0; i < values.length; i++) {
- res[i] = namingLens.lookupInternalName(((DexValueType) values[i]).value);
+ res[i] = namingLens.lookupInternalName(values[i].asDexValueType().value);
}
return res;
}
@@ -331,13 +322,13 @@
assert annotation.annotation.elements.length == 2;
assert annotation.annotation.elements[0].name.toString().equals("names");
assert annotation.annotation.elements[1].name.toString().equals("accessFlags");
- DexValueArray names = (DexValueArray) annotation.annotation.elements[0].value;
- DexValueArray accessFlags = (DexValueArray) annotation.annotation.elements[1].value;
+ DexValueArray names = annotation.annotation.elements[0].value.asDexValueArray();
+ DexValueArray accessFlags = annotation.annotation.elements[1].value.asDexValueArray();
assert names != null && accessFlags != null;
assert names.getValues().length == accessFlags.getValues().length;
for (int i = 0; i < names.getValues().length; i++) {
- DexValueString name = (DexValueString) names.getValues()[i];
- DexValueInt access = (DexValueInt) accessFlags.getValues()[i];
+ DexValueString name = names.getValues()[i].asDexValueString();
+ DexValueInt access = accessFlags.getValues()[i].asDexValueInt();
visitor.visitParameter(name.value.toString(), access.value);
}
}
@@ -392,44 +383,64 @@
}
private void writeAnnotationElement(AnnotationVisitor visitor, String name, DexValue value) {
- if (value instanceof DexValueAnnotation) {
- DexValueAnnotation valueAnnotation = (DexValueAnnotation) value;
- AnnotationVisitor innerVisitor =
- visitor.visitAnnotation(
- name, namingLens.lookupDescriptor(valueAnnotation.value.type).toString());
- if (innerVisitor != null) {
- writeAnnotation(innerVisitor, valueAnnotation.value);
- innerVisitor.visitEnd();
- }
- } else if (value instanceof DexValueArray) {
- DexValue[] values = ((DexValueArray) value).getValues();
- AnnotationVisitor innerVisitor = visitor.visitArray(name);
- if (innerVisitor != null) {
- for (DexValue arrayValue : values) {
- writeAnnotationElement(innerVisitor, null, arrayValue);
+ switch (value.getValueKind()) {
+ case ANNOTATION:
+ {
+ DexValueAnnotation valueAnnotation = value.asDexValueAnnotation();
+ AnnotationVisitor innerVisitor =
+ visitor.visitAnnotation(
+ name, namingLens.lookupDescriptor(valueAnnotation.value.type).toString());
+ if (innerVisitor != null) {
+ writeAnnotation(innerVisitor, valueAnnotation.value);
+ innerVisitor.visitEnd();
+ }
}
- innerVisitor.visitEnd();
- }
- } else if (value instanceof DexValueEnum) {
- DexValueEnum en = (DexValueEnum) value;
- visitor.visitEnum(
- name, namingLens.lookupDescriptor(en.value.type).toString(), en.value.name.toString());
- } else if (value instanceof DexValueField) {
- throw new Unreachable("writeAnnotationElement of DexValueField");
- } else if (value instanceof DexValueMethod) {
- throw new Unreachable("writeAnnotationElement of DexValueMethod");
- } else if (value instanceof DexValueMethodHandle) {
- throw new Unreachable("writeAnnotationElement of DexValueMethodHandle");
- } else if (value instanceof DexValueMethodType) {
- throw new Unreachable("writeAnnotationElement of DexValueMethodType");
- } else if (value instanceof DexValueString) {
- DexValueString str = (DexValueString) value;
- visitor.visit(name, str.getValue().toString());
- } else if (value instanceof DexValueType) {
- DexValueType ty = (DexValueType) value;
- visitor.visit(name, Type.getType(namingLens.lookupDescriptor(ty.value).toString()));
- } else {
- visitor.visit(name, value.getBoxedValue());
+ break;
+
+ case ARRAY:
+ {
+ DexValue[] values = value.asDexValueArray().getValues();
+ AnnotationVisitor innerVisitor = visitor.visitArray(name);
+ if (innerVisitor != null) {
+ for (DexValue elementValue : values) {
+ writeAnnotationElement(innerVisitor, null, elementValue);
+ }
+ innerVisitor.visitEnd();
+ }
+ }
+ break;
+
+ case ENUM:
+ DexValueEnum en = value.asDexValueEnum();
+ visitor.visitEnum(
+ name, namingLens.lookupDescriptor(en.value.type).toString(), en.value.name.toString());
+ break;
+
+ case FIELD:
+ throw new Unreachable("writeAnnotationElement of DexValueField");
+
+ case METHOD:
+ throw new Unreachable("writeAnnotationElement of DexValueMethod");
+
+ case METHOD_HANDLE:
+ throw new Unreachable("writeAnnotationElement of DexValueMethodHandle");
+
+ case METHOD_TYPE:
+ throw new Unreachable("writeAnnotationElement of DexValueMethodType");
+
+ case STRING:
+ visitor.visit(name, value.asDexValueString().getValue().toString());
+ break;
+
+ case TYPE:
+ visitor.visit(
+ name,
+ Type.getType(namingLens.lookupDescriptor(value.asDexValueType().value).toString()));
+ break;
+
+ default:
+ visitor.visit(name, value.getBoxedValue());
+ break;
}
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinClass.java b/src/main/java/com/android/tools/r8/kotlin/KotlinClass.java
index a37a42b..136947b 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinClass.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinClass.java
@@ -22,6 +22,7 @@
import com.android.tools.r8.graph.InnerClassAttribute;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.StringUtils;
import java.util.List;
import kotlinx.metadata.KmClass;
import kotlinx.metadata.KmConstructor;
@@ -187,7 +188,13 @@
}
@Override
- public String toString() {
- return clazz.toString() + ": " + kmClass.toString();
+ public String toString(String indent) {
+ StringBuilder sb = new StringBuilder(indent);
+ sb.append("Metadata.Class {");
+ sb.append(StringUtils.LINE_SEPARATOR);
+ sb.append(kmDeclarationContainerToString(indent + INDENT));
+ sb.append(indent);
+ sb.append("}");
+ return sb.toString();
}
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinClassFacade.java b/src/main/java/com/android/tools/r8/kotlin/KotlinClassFacade.java
index cc1cd14..627ac9d 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinClassFacade.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinClassFacade.java
@@ -81,8 +81,7 @@
}
@Override
- public String toString() {
- return clazz.toString()
- + ": MultiFileClassFacade(" + StringUtils.join(partClassNames, ", ") + ")";
+ public String toString(String indent) {
+ return indent + "MultiFileClassFacade(" + StringUtils.join(partClassNames, ", ") + ")";
}
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinClassMetadataReader.java b/src/main/java/com/android/tools/r8/kotlin/KotlinClassMetadataReader.java
index fec6a34..e49d99d 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinClassMetadataReader.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinClassMetadataReader.java
@@ -11,7 +11,6 @@
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexValue;
import com.android.tools.r8.graph.DexValue.DexValueArray;
-import com.android.tools.r8.graph.DexValue.DexValueString;
import com.android.tools.r8.utils.StringDiagnostic;
import java.util.IdentityHashMap;
import java.util.Map;
@@ -19,7 +18,7 @@
import kotlinx.metadata.jvm.KotlinClassHeader;
import kotlinx.metadata.jvm.KotlinClassMetadata;
-final class KotlinClassMetadataReader {
+public final class KotlinClassMetadataReader {
static KotlinInfo getKotlinInfo(
Kotlin kotlin,
@@ -73,7 +72,7 @@
return KotlinClassMetadata.read(header);
}
- private static KotlinInfo createKotlinInfo(
+ public static KotlinInfo createKotlinInfo(
Kotlin kotlin, DexClass clazz, DexEncodedAnnotation metadataAnnotation) {
KotlinClassMetadata kMetadata = toKotlinClassMetadata(kotlin, metadataAnnotation);
@@ -96,10 +95,10 @@
}
private static int[] getUnboxedIntArray(DexValue v, String elementName) {
- if (!(v instanceof DexValueArray)) {
+ if (!v.isDexValueArray()) {
throw new MetadataError("invalid '" + elementName + "' value: " + v.toSourceString());
}
- DexValueArray intArrayValue = (DexValueArray) v;
+ DexValueArray intArrayValue = v.asDexValueArray();
DexValue[] values = intArrayValue.getValues();
int[] result = new int [values.length];
for (int i = 0; i < values.length; i++) {
@@ -109,10 +108,10 @@
}
private static String[] getUnboxedStringArray(DexValue v, String elementName) {
- if (!(v instanceof DexValueArray)) {
+ if (!v.isDexValueArray()) {
throw new MetadataError("invalid '" + elementName + "' value: " + v.toSourceString());
}
- DexValueArray stringArrayValue = (DexValueArray) v;
+ DexValueArray stringArrayValue = v.asDexValueArray();
DexValue[] values = stringArrayValue.getValues();
String[] result = new String [values.length];
for (int i = 0; i < values.length; i++) {
@@ -122,10 +121,10 @@
}
private static String getUnboxedString(DexValue v, String elementName) {
- if (!(v instanceof DexValueString)) {
+ if (!v.isDexValueString()) {
throw new MetadataError("invalid '" + elementName + "' value: " + v.toSourceString());
}
- return ((DexValueString) v).getValue().toString();
+ return v.asDexValueString().getValue().toString();
}
private static class MetadataError extends RuntimeException {
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinClassPart.java b/src/main/java/com/android/tools/r8/kotlin/KotlinClassPart.java
index 16223bb..e67cd05 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinClassPart.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinClassPart.java
@@ -12,6 +12,7 @@
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.StringUtils;
import kotlinx.metadata.KmPackage;
import kotlinx.metadata.jvm.KotlinClassHeader;
import kotlinx.metadata.jvm.KotlinClassMetadata;
@@ -82,8 +83,14 @@
}
@Override
- public String toString() {
- return clazz.toString() + ": " + kmPackage.toString()
- + ": MultiFileClassPart(" + facadeClassName + ")";
+ public String toString(String indent) {
+ StringBuilder sb = new StringBuilder(indent);
+ sb.append("Metadata.MultiFileClassPart {");
+ sb.append(StringUtils.LINE_SEPARATOR);
+ sb.append(kmDeclarationContainerToString(indent + INDENT));
+ appendKeyValue(indent + INDENT, "facadeClassName", facadeClassName, sb);
+ sb.append(indent);
+ sb.append("}");
+ return sb.toString();
}
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinFile.java b/src/main/java/com/android/tools/r8/kotlin/KotlinFile.java
index 27c9230..08fc8ef 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinFile.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinFile.java
@@ -64,7 +64,13 @@
}
@Override
- public String toString() {
- return clazz.toString() + ": " + kmPackage.toString();
+ public String toString(String indent) {
+ StringBuilder sb = new StringBuilder(indent);
+ sb.append("Metadata.MultiFileClassPart {\n");
+ sb.append(kmDeclarationContainerToString(indent + INDENT));
+ appendKeyValue(indent + INDENT, "package", kmPackage.toString(), sb);
+ sb.append(indent);
+ sb.append("}");
+ return sb.toString();
}
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinInfo.java
index 7c53cba..967cf05 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinInfo.java
@@ -15,13 +15,20 @@
import com.android.tools.r8.kotlin.KotlinMetadataSynthesizer.KmPropertyGroup;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.StringUtils;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.function.BiFunction;
import java.util.function.Predicate;
+import java.util.stream.Collectors;
import kotlinx.metadata.KmDeclarationContainer;
import kotlinx.metadata.KmFunction;
import kotlinx.metadata.KmProperty;
+import kotlinx.metadata.KmType;
+import kotlinx.metadata.KmTypeAlias;
+import kotlinx.metadata.KmTypeParameter;
import kotlinx.metadata.jvm.KotlinClassHeader;
import kotlinx.metadata.jvm.KotlinClassMetadata;
@@ -202,4 +209,131 @@
}
}
}
+
+ public abstract String toString(String indent);
+
+ String kmDeclarationContainerToString(String indent) {
+ StringBuilder sb = new StringBuilder();
+ KmDeclarationContainer declarations = getDeclarations();
+ appendKmSection(indent, "functions", declarations.getFunctions(), this::kmFunctionToString, sb);
+ appendKmSection(
+ indent, "properties", declarations.getProperties(), this::kmPropertyToString, sb);
+ appendKmSection(
+ indent, "typeAliases", declarations.getTypeAliases(), this::kmTypeAliasToString, sb);
+ return sb.toString();
+ }
+
+ final String INDENT = " ";
+
+ private <T> void appendKmSection(
+ String indent,
+ String header,
+ List<T> items,
+ BiFunction<String, T, String> stringify,
+ StringBuilder sb) {
+ if (items.size() > 0) {
+ sb.append(indent);
+ sb.append(header);
+ sb.append(": [");
+ sb.append(StringUtils.LINE_SEPARATOR);
+ }
+ for (T item : items) {
+ sb.append(stringify.apply(indent + INDENT, item));
+ sb.append(",");
+ sb.append(StringUtils.LINE_SEPARATOR);
+ }
+ if (items.size() > 0) {
+ sb.append(indent);
+ sb.append("]");
+ sb.append(StringUtils.LINE_SEPARATOR);
+ }
+ }
+
+ private String kmFunctionToString(String indent, KmFunction function) {
+ assert function != null;
+ StringBuilder sb = new StringBuilder();
+ sb.append(indent);
+ sb.append("KmFunction {");
+ sb.append(StringUtils.LINE_SEPARATOR);
+ String newIndent = indent + INDENT;
+ KmType receiverParameterType = function.getReceiverParameterType();
+ appendKeyValue(
+ newIndent,
+ "receiverParameterType",
+ receiverParameterType == null ? "null" : kmTypeToString(receiverParameterType),
+ sb);
+ appendKeyValue(newIndent, "returnType", kmTypeToString(function.returnType), sb);
+ appendKeyValue(newIndent, "name", function.getName(), sb);
+ // TODO(b/148581822): Print flags, generic signature etc.
+ sb.append(indent);
+ sb.append("}");
+ return sb.toString();
+ }
+
+ private String kmPropertyToString(String indent, KmProperty property) {
+ // TODO(b/148581822): Add information.
+ return indent + "KmProperty { " + property + "}";
+ }
+
+ private String kmTypeAliasToString(String indent, KmTypeAlias alias) {
+ assert alias != null;
+ StringBuilder sb = new StringBuilder(indent);
+ sb.append("KmTypeAlias {");
+ sb.append(StringUtils.LINE_SEPARATOR);
+ String newIndent = indent + INDENT;
+ appendKeyValue(newIndent, "name", alias.getName(), sb);
+ if (!alias.getTypeParameters().isEmpty()) {
+ appendKeyValue(
+ newIndent,
+ "typeParameters",
+ alias.getTypeParameters().stream()
+ .map(KmTypeParameter::getName)
+ .collect(Collectors.joining(",")),
+ sb);
+ }
+ appendType(newIndent, "underlyingType", alias.underlyingType, sb);
+ appendType(newIndent, "expandedType", alias.expandedType, sb);
+ // TODO(b/151783973): Extend with annotations.
+ sb.append(indent);
+ sb.append("}");
+ return sb.toString();
+ }
+
+ void appendType(String indent, String key, KmType kmType, StringBuilder sb) {
+ sb.append(indent);
+ sb.append(key);
+ sb.append(" {");
+ sb.append(StringUtils.LINE_SEPARATOR);
+ String newIndent = indent + INDENT;
+ appendKeyValue(newIndent, "classifier", kmType.classifier.toString(), sb);
+ if (!kmType.getArguments().isEmpty()) {
+ appendKeyValue(
+ newIndent,
+ "arguments",
+ kmType.getArguments().stream()
+ .map(arg -> arg.getType().classifier.toString())
+ .collect(Collectors.joining(",")),
+ sb);
+ }
+ sb.append(indent);
+ sb.append("}");
+ sb.append(StringUtils.LINE_SEPARATOR);
+ }
+
+ void appendKeyValue(String indent, String key, String value, StringBuilder sb) {
+ sb.append(indent);
+ sb.append(key);
+ sb.append(": ");
+ sb.append(value);
+ sb.append(StringUtils.LINE_SEPARATOR);
+ }
+
+ private String kmTypeToString(KmType type) {
+ return DescriptorUtils.getDescriptorFromKmType(type);
+ }
+
+ @Override
+ public String toString() {
+ return toString("");
+ }
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinSyntheticClass.java b/src/main/java/com/android/tools/r8/kotlin/KotlinSyntheticClass.java
index 1bb17ea..8c4ccaf 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinSyntheticClass.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinSyntheticClass.java
@@ -119,7 +119,7 @@
}
@Override
- public String toString() {
- return clazz.toString() + ": " + metadata.toString();
+ public String toString(String indent) {
+ return indent + "Metadata.SyntheticClass { function: " + metadata.toString() + "}";
}
}
diff --git a/src/main/java/com/android/tools/r8/naming/IdentifierMinifier.java b/src/main/java/com/android/tools/r8/naming/IdentifierMinifier.java
index 72d5558..a0b1328 100644
--- a/src/main/java/com/android/tools/r8/naming/IdentifierMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/IdentifierMinifier.java
@@ -69,8 +69,8 @@
private void adaptClassStringsInStaticField(DexEncodedField encodedField) {
assert encodedField.accessFlags.isStatic();
DexValue staticValue = encodedField.getStaticValue();
- if (staticValue instanceof DexValueString) {
- DexString original = ((DexValueString) staticValue).getValue();
+ if (staticValue.isDexValueString()) {
+ DexString original = staticValue.asDexValueString().getValue();
encodedField.setStaticValue(new DexValueString(getRenamedStringLiteral(original)));
}
}
diff --git a/src/main/java/com/android/tools/r8/naming/IdentifierNameStringMarker.java b/src/main/java/com/android/tools/r8/naming/IdentifierNameStringMarker.java
index 47d6431..d5873a9 100644
--- a/src/main/java/com/android/tools/r8/naming/IdentifierNameStringMarker.java
+++ b/src/main/java/com/android/tools/r8/naming/IdentifierNameStringMarker.java
@@ -18,7 +18,6 @@
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.DexValue;
import com.android.tools.r8.graph.DexValue.DexItemBasedValueString;
import com.android.tools.r8.graph.DexValue.DexValueString;
import com.android.tools.r8.ir.code.BasicBlock;
@@ -81,11 +80,11 @@
if (!identifierNameStrings.containsKey(encodedField.field)) {
return;
}
- DexValue staticValue = encodedField.getStaticValue();
- if (!(staticValue instanceof DexValueString)) {
+ DexValueString staticValue = encodedField.getStaticValue().asDexValueString();
+ if (staticValue == null) {
return;
}
- DexString original = ((DexValueString) staticValue).getValue();
+ DexString original = staticValue.getValue();
DexReference itemBasedString = inferMemberOrTypeFromNameString(appView, original);
if (itemBasedString != null) {
encodedField.setStaticValue(
@@ -162,7 +161,7 @@
assert iterator.peekPrevious() == fieldPut;
iterator.previous();
// Prepare $decoupled just before $fieldPut
- Value newIn = code.createValue(in.getTypeLattice(), in.getLocalInfo());
+ Value newIn = code.createValue(in.getType(), in.getLocalInfo());
DexItemBasedConstString decoupled =
new DexItemBasedConstString(
newIn, itemBasedString, ClassNameComputationInfo.none(), throwingInfo);
@@ -228,7 +227,7 @@
}
// Prepare $decoupled just before $invoke
- Value newIn = code.createValue(in.getTypeLattice(), in.getLocalInfo());
+ Value newIn = code.createValue(in.getType(), in.getLocalInfo());
DexItemBasedConstString decoupled =
new DexItemBasedConstString(
newIn, itemBasedString, ClassNameComputationInfo.none(), throwingInfo);
@@ -295,7 +294,7 @@
assert iterator.peekPrevious() == invoke;
iterator.previous();
// Prepare $decoupled just before $invoke
- Value newIn = code.createValue(in.getTypeLattice(), in.getLocalInfo());
+ Value newIn = code.createValue(in.getType(), in.getLocalInfo());
DexItemBasedConstString decoupled =
new DexItemBasedConstString(
newIn, itemBasedString, ClassNameComputationInfo.none(), throwingInfo);
diff --git a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
index 7df2fbc..fdd1274 100644
--- a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
+++ b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
@@ -37,7 +37,7 @@
import com.android.tools.r8.graph.PresortedComparable;
import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.graph.ResolutionResult.SingleResolutionResult;
-import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
import com.android.tools.r8.ir.code.Invoke.Type;
import com.android.tools.r8.ir.desugar.LambdaDescriptor;
import com.android.tools.r8.utils.CollectionUtils;
@@ -1149,7 +1149,7 @@
boolean isInterface,
LibraryModeledPredicate modeledPredicate,
DexType refinedReceiverType,
- ClassTypeLatticeElement receiverLowerBoundType) {
+ ClassTypeElement receiverLowerBoundType) {
assert checkIfObsolete();
assert refinedReceiverType != null;
@@ -1239,7 +1239,7 @@
private DexEncodedMethod getMethodTargetFromExactRuntimeInformation(
DexType refinedReceiverType,
- ClassTypeLatticeElement receiverLowerBoundType,
+ ClassTypeElement receiverLowerBoundType,
SingleResolutionResult resolution,
DexClass refinedReceiverClass) {
// If the lower-bound on the receiver type is the same as the upper-bound, then we have exact
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 2bc230c..20dde1b 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -23,6 +23,7 @@
import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.experimental.graphinfo.GraphConsumer;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppInfoWithSubtyping;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.CfCode;
@@ -93,7 +94,9 @@
import com.android.tools.r8.utils.DequeUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.InternalOptions.DesugarState;
+import com.android.tools.r8.utils.MethodSignatureEquivalence;
import com.android.tools.r8.utils.OptionalBool;
+import com.android.tools.r8.utils.Pair;
import com.android.tools.r8.utils.SetUtils;
import com.android.tools.r8.utils.StringDiagnostic;
import com.android.tools.r8.utils.Timing;
@@ -169,8 +172,10 @@
private Set<EnqueuerAnalysis> analyses = Sets.newIdentityHashSet();
private Set<EnqueuerInvokeAnalysis> invokeAnalyses = Sets.newIdentityHashSet();
- private final AppInfoWithSubtyping appInfo;
- private final AppView<? extends AppInfoWithSubtyping> appView;
+
+ // Don't hold a direct pointer to app info (use appView).
+ private AppInfoWithSubtyping appInfo;
+ private final AppView<AppInfoWithSubtyping> appView;
private final InternalOptions options;
private RootSet rootSet;
private ProguardClassFilter dontWarnPatterns;
@@ -271,16 +276,8 @@
*/
private final Set<DexEncodedMethod> pendingReflectiveUses = Sets.newLinkedHashSet();
- /**
- * Mapping of types to the reachable method resolutions.
- *
- * <p>Primary map key is the initial/static/symbolic type specified by a live invoke.
- *
- * <p>The keys of the reachable resolutions are again the static reference, thus methodKey.holder
- * will be the same as the classKey.type. The value of the reachable resolution is the resolution
- * target.
- */
- private final Map<DexProgramClass, Map<DexMethod, ProgramMethod>> reachableVirtualResolutions =
+ /** Mapping of types to the methods reachable at that type. */
+ private final Map<DexProgramClass, Set<DexMethod>> reachableVirtualTargets =
new IdentityHashMap<>();
/**
@@ -327,7 +324,8 @@
private final LambdaRewriter lambdaRewriter;
private final DesugaredLibraryConversionWrapperAnalysis desugaredLibraryWrapperAnalysis;
- private final Map<DexType, LambdaClass> lambdaClasses = new IdentityHashMap<>();
+ private final Map<DexType, Pair<LambdaClass, DexEncodedMethod>> lambdaClasses =
+ new IdentityHashMap<>();
private final Map<DexEncodedMethod, Map<DexCallSite, LambdaClass>> lambdaCallSites =
new IdentityHashMap<>();
private final Set<DexProgramClass> classesWithSerializableLambdas = Sets.newIdentityHashSet();
@@ -339,7 +337,7 @@
assert appView.appServices() != null;
InternalOptions options = appView.options();
this.appInfo = appView.appInfo();
- this.appView = appView;
+ this.appView = appView.withSubtyping();
this.forceProguardCompatibility = options.forceProguardCompatibility;
this.graphReporter = new GraphReporter(appView, keptGraphConsumer);
this.mode = mode;
@@ -375,6 +373,10 @@
}
}
+ private AppInfoWithClassHierarchy appInfo() {
+ return appView.appInfo();
+ }
+
public Mode getMode() {
return mode;
}
@@ -656,7 +658,7 @@
if (code != null) {
LambdaClass lambdaClass =
lambdaRewriter.getOrCreateLambdaClass(descriptor, contextMethod.method.holder);
- lambdaClasses.put(lambdaClass.type, lambdaClass);
+ lambdaClasses.put(lambdaClass.type, new Pair<>(lambdaClass, contextMethod));
lambdaCallSites
.computeIfAbsent(contextMethod, k -> new IdentityHashMap<>())
.put(callSite, lambdaClass);
@@ -1855,7 +1857,7 @@
*/
private void transitionMethodsForInstantiatedObject(
InstantiatedObject instantiation, DexClass clazz, List<DexType> interfaces) {
- ScopedDexMethodSet seen = new ScopedDexMethodSet();
+ Set<Wrapper<DexMethod>> seen = new HashSet<>();
WorkList<DexType> worklist = WorkList.newIdentityWorkList();
worklist.addIfNotSeen(interfaces);
// First we lookup and mark all targets on the instantiated class for each reachable method in
@@ -1889,22 +1891,27 @@
}
}
- private Map<DexMethod, ProgramMethod> getReachableVirtualResolutions(DexProgramClass clazz) {
- return reachableVirtualResolutions.getOrDefault(clazz, Collections.emptyMap());
+ private Set<DexMethod> getReachableVirtualTargets(DexProgramClass clazz) {
+ return reachableVirtualTargets.getOrDefault(clazz, Collections.emptySet());
}
private void markProgramMethodOverridesAsLive(
InstantiatedObject instantiation,
DexProgramClass superClass,
- ScopedDexMethodSet seenMethods) {
- Map<DexMethod, ProgramMethod> reachableResolution = getReachableVirtualResolutions(superClass);
- reachableResolution.forEach(
- (method, resolution) -> {
- assert method.holder == superClass.type;
- if (seenMethods.addMethod(resolution.getMethod())) {
- markLiveOverrides(instantiation, superClass, resolution);
- }
- });
+ Set<Wrapper<DexMethod>> seenMethods) {
+ for (DexMethod method : getReachableVirtualTargets(superClass)) {
+ assert method.holder == superClass.type;
+ if (seenMethods.add(MethodSignatureEquivalence.get().wrap(method))) {
+ SingleResolutionResult resolution =
+ appInfo.resolveMethod(superClass, method).asSingleResolution();
+ assert resolution != null;
+ assert resolution.getResolvedHolder().isProgramClass();
+ if (resolution != null && resolution.getResolvedHolder().isProgramClass()) {
+ markLiveOverrides(
+ instantiation, superClass, resolution.getResolutionPair().asProgramMethod());
+ }
+ }
+ }
}
private void markLiveOverrides(
@@ -2281,18 +2288,6 @@
return;
}
- ProgramMethod resolutionMethod = getReachableVirtualResolutions(holder).get(method);
-
- // If the method has already been marked, just report the new reason for the resolved target.
- if (resolutionMethod != null) {
- graphReporter.registerMethod(resolutionMethod.getMethod(), reason);
- return;
- }
-
- if (Log.ENABLED) {
- Log.verbose(getClass(), "Marking virtual method `%s` as reachable.", method);
- }
-
SingleResolutionResult resolution = resolveMethod(method, reason, interfaceInvoke);
if (resolution == null) {
return;
@@ -2306,6 +2301,16 @@
return;
}
+ // If the method has already been marked, just report the new reason for the resolved target.
+ if (getReachableVirtualTargets(holder).contains(method)) {
+ graphReporter.registerMethod(resolution.getResolvedMethod(), reason);
+ return;
+ }
+
+ if (Log.ENABLED) {
+ Log.verbose(getClass(), "Marking virtual method `%s` as reachable.", method);
+ }
+
// We have to mark the resolution targeted, even if it does not become live, we
// need at least an abstract version of it so that it can be targeted.
DexProgramClass resolvedHolder = resolution.getResolvedHolder().asProgramClass();
@@ -2326,9 +2331,7 @@
}
// The method resolved and is accessible, so currently live overrides become live.
- reachableVirtualResolutions
- .computeIfAbsent(holder, k -> new IdentityHashMap<>())
- .put(method, new ProgramMethod(resolvedHolder, resolvedMethod));
+ reachableVirtualTargets.computeIfAbsent(holder, k -> Sets.newIdentityHashSet()).add(method);
resolution
.lookupVirtualDispatchTargets(
@@ -2504,6 +2507,163 @@
return appInfoWithLiveness;
}
+ private static class SyntheticAdditions {
+
+ Map<DexType, Pair<DexProgramClass, DexEncodedMethod>> syntheticInstantiations =
+ new IdentityHashMap<>();
+
+ Map<DexMethod, ProgramMethod> liveMethods = new IdentityHashMap<>();
+
+ Map<DexType, DexClasspathClass> syntheticClasspathClasses = new IdentityHashMap<>();
+
+ // Subset of live methods that need to be pinned.
+ Set<DexMethod> pinnedMethods = Sets.newIdentityHashSet();
+
+ // Subset of synthesized classes that need to be added to the main-dex file.
+ Set<DexType> mainDexTypes = Sets.newIdentityHashSet();
+
+ boolean isEmpty() {
+ boolean empty = syntheticInstantiations.isEmpty() && liveMethods.isEmpty();
+ assert !empty || (pinnedMethods.isEmpty() && mainDexTypes.isEmpty());
+ return empty;
+ }
+
+ void addInstantiatedClass(
+ DexProgramClass clazz, DexEncodedMethod context, boolean isMainDexClass) {
+ assert !syntheticInstantiations.containsKey(clazz.type);
+ syntheticInstantiations.put(clazz.type, new Pair<>(clazz, context));
+ if (isMainDexClass) {
+ mainDexTypes.add(clazz.type);
+ }
+ }
+
+ void addClasspathClass(DexClasspathClass clazz) {
+ DexClasspathClass old = syntheticClasspathClasses.put(clazz.type, clazz);
+ assert old == null;
+ }
+
+ void addLiveMethod(ProgramMethod method) {
+ DexMethod signature = method.getMethod().method;
+ assert !liveMethods.containsKey(signature);
+ liveMethods.put(signature, method);
+ }
+
+ void addLiveAndPinnedMethod(ProgramMethod method) {
+ addLiveMethod(method);
+ pinnedMethods.add(method.getMethod().method);
+ }
+
+ void amendApplication(Builder appBuilder) {
+ assert !isEmpty();
+ for (Pair<DexProgramClass, DexEncodedMethod> clazzAndContext :
+ syntheticInstantiations.values()) {
+ appBuilder.addProgramClass(clazzAndContext.getFirst());
+ }
+ appBuilder.addClasspathClasses(syntheticClasspathClasses.values());
+ appBuilder.addToMainDexList(mainDexTypes);
+ }
+
+ void enqueueWorkItems(Enqueuer enqueuer) {
+ assert !isEmpty();
+ assert enqueuer.mode.isInitialTreeShaking();
+ // All synthetic additions are initial tree shaking only. No need to track keep reasons.
+ KeepReasonWitness fakeReason = enqueuer.graphReporter.fakeReportShouldNotBeUsed();
+
+ enqueuer.pinnedItems.addAll(pinnedMethods);
+ for (Pair<DexProgramClass, DexEncodedMethod> clazzAndContext :
+ syntheticInstantiations.values()) {
+ enqueuer.workList.enqueueMarkInstantiatedAction(
+ clazzAndContext.getFirst(),
+ clazzAndContext.getSecond(),
+ InstantiationReason.SYNTHESIZED_CLASS,
+ fakeReason);
+ }
+ for (ProgramMethod liveMethod : liveMethods.values()) {
+ assert !enqueuer.targetedMethods.contains(liveMethod.getMethod());
+ DexProgramClass holder = liveMethod.getHolder();
+ DexEncodedMethod method = liveMethod.getMethod();
+ enqueuer.markMethodAsTargeted(holder, method, fakeReason);
+ enqueuer.enqueueMarkMethodLiveAction(holder, method, fakeReason);
+ }
+ }
+ }
+
+ private void synthesize() {
+ if (!mode.isInitialTreeShaking()) {
+ return;
+ }
+ // First part of synthesis is to create and register all reachable synthetic additions.
+ // In particular these additions are order independent, i.e., it does not matter which are
+ // registered first and no dependencies may exist among them.
+ SyntheticAdditions additions = new SyntheticAdditions();
+ synthesizeInterfaceMethodBridges(additions);
+ synthesizeLambdas(additions);
+ synthesizeLibraryConversionWrappers(additions);
+ if (additions.isEmpty()) {
+ return;
+ }
+
+ // Now all additions are computed, the application is atomically extended with those additions.
+ Builder appBuilder = appInfo.app().asDirect().builder();
+ additions.amendApplication(appBuilder);
+ appInfo = new AppInfoWithSubtyping(appBuilder.build());
+ appView.setAppInfo(appInfo);
+
+ // Finally once all synthesized items "exist" it is now safe to continue tracing. The new work
+ // items are enqueued and the fixed point will continue once this subroutine returns.
+ additions.enqueueWorkItems(this);
+ }
+
+ private void synthesizeInterfaceMethodBridges(SyntheticAdditions additions) {
+ for (ProgramMethod bridge : syntheticInterfaceMethodBridges.values()) {
+ DexProgramClass holder = bridge.getHolder();
+ DexEncodedMethod method = bridge.getMethod();
+ holder.addVirtualMethod(method);
+ additions.addLiveAndPinnedMethod(bridge);
+ }
+ syntheticInterfaceMethodBridges.clear();
+ }
+
+ private void synthesizeLambdas(SyntheticAdditions additions) {
+ if (lambdaRewriter == null || lambdaClasses.isEmpty()) {
+ assert lambdaCallSites.isEmpty();
+ assert classesWithSerializableLambdas.isEmpty();
+ return;
+ }
+ for (Pair<LambdaClass, DexEncodedMethod> lambdaClassAndContext : lambdaClasses.values()) {
+ // Add all desugared classes to the application, main-dex list, and mark them instantiated.
+ LambdaClass lambdaClass = lambdaClassAndContext.getFirst();
+ DexEncodedMethod context = lambdaClassAndContext.getSecond();
+ DexProgramClass programClass = lambdaClass.getOrCreateLambdaClass();
+ additions.addInstantiatedClass(programClass, context, lambdaClass.addToMainDexList.get());
+
+ // Mark all methods on the desugared lambda classes as live.
+ for (DexEncodedMethod method : programClass.methods()) {
+ additions.addLiveMethod(new ProgramMethod(programClass, method));
+ }
+
+ // Ensure accessors if needed and mark them live too.
+ DexEncodedMethod accessor = lambdaClass.target.ensureAccessibilityIfNeeded(false);
+ if (accessor != null) {
+ DexProgramClass clazz = getProgramClassOrNull(accessor.method.holder);
+ additions.addLiveMethod(new ProgramMethod(clazz, accessor));
+ }
+ }
+
+ // Rewrite all of the invoke-dynamic instructions to lambda class instantiations.
+ lambdaCallSites.forEach(this::rewriteLambdaCallSites);
+
+ // Remove all '$deserializeLambda$' methods which are not supported by desugaring.
+ for (DexProgramClass clazz : classesWithSerializableLambdas) {
+ clazz.removeDirectMethod(appView.dexItemFactory().deserializeLambdaMethod);
+ }
+
+ // Clear state before next fixed point iteration.
+ lambdaClasses.clear();
+ lambdaCallSites.clear();
+ classesWithSerializableLambdas.clear();
+ }
+
private void finalizeLibraryMethodOverrideInformation() {
for (DexProgramClass liveType : liveTypes.getItems()) {
for (DexEncodedMethod method : liveType.virtualMethods()) {
@@ -2530,16 +2690,6 @@
(field, info) -> field != info.getField() || info == MISSING_FIELD_ACCESS_INFO);
assert fieldAccessInfoCollection.verifyMappingIsOneToOne();
- for (ProgramMethod bridge : syntheticInterfaceMethodBridges.values()) {
- DexProgramClass holder = bridge.getHolder();
- DexEncodedMethod method = bridge.getMethod();
- appView.appInfo().invalidateTypeCacheFor(holder.type);
- holder.appendVirtualMethod(method);
- targetedMethods.add(method, graphReporter.fakeReportShouldNotBeUsed());
- liveMethods.add(holder, method, graphReporter.fakeReportShouldNotBeUsed());
- pinnedItems.add(method.method);
- }
-
// Ensure references from various root set collections.
rootSet
.noSideEffects
@@ -2573,8 +2723,6 @@
appBuilder.replaceClasspathClasses(classpathClasses);
// Can't replace the program classes at this point as they are needed in tree pruning.
// Post process the app to add synthetic content.
- postProcessLambdaDesugaring(appBuilder);
- postProcessLibraryConversionWrappers(appBuilder);
DirectMappedDexApplication app = appBuilder.build();
AppInfoWithLiveness appInfoWithLiveness =
@@ -2670,7 +2818,7 @@
}
}
- private void postProcessLibraryConversionWrappers(DirectMappedDexApplication.Builder appBuilder) {
+ private void synthesizeLibraryConversionWrappers(SyntheticAdditions additions) {
if (desugaredLibraryWrapperAnalysis == null) {
return;
}
@@ -2679,95 +2827,24 @@
List<DexEncodedMethod> callbacks = desugaredLibraryWrapperAnalysis.generateCallbackMethods();
for (DexEncodedMethod callback : callbacks) {
DexProgramClass clazz = getProgramClassOrNull(callback.method.holder);
- targetedMethods.add(callback, graphReporter.fakeReportShouldNotBeUsed());
- liveMethods.add(clazz, callback, graphReporter.fakeReportShouldNotBeUsed());
+ additions.addLiveMethod(new ProgramMethod(clazz, callback));
}
// Generate the wrappers.
- Set<DexProgramClass> wrappers = desugaredLibraryWrapperAnalysis.generateWrappers();
+ List<DexProgramClass> wrappers = desugaredLibraryWrapperAnalysis.generateWrappers();
for (DexProgramClass wrapper : wrappers) {
- appBuilder.addProgramClass(wrapper);
- liveTypes.add(wrapper, graphReporter.fakeReportShouldNotBeUsed());
- objectAllocationInfoCollection.recordDirectAllocationSite(
- wrapper,
- null,
- InstantiationReason.SYNTHESIZED_CLASS,
- graphReporter.fakeReportShouldNotBeUsed(),
- appInfo);
+ additions.addInstantiatedClass(wrapper, null, false);
// Mark all methods on the wrapper as live and targeted.
for (DexEncodedMethod method : wrapper.methods()) {
- targetedMethods.add(method, graphReporter.fakeReportShouldNotBeUsed());
- liveMethods.add(wrapper, method, graphReporter.fakeReportShouldNotBeUsed());
+ additions.addLiveMethod(new ProgramMethod(wrapper, method));
}
- // Register wrapper unique field reads and unique write.
- assert wrapper.instanceFields().size() == 1;
- DexField field = wrapper.instanceFields().get(0).field;
- FieldAccessInfoImpl info = new FieldAccessInfoImpl(field);
- fieldAccessInfoCollection.extend(field, info);
- desugaredLibraryWrapperAnalysis
- .registerWrite(wrapper, writeContext -> info.recordWrite(field, writeContext))
- .registerReads(wrapper, readContext -> info.recordRead(field, readContext));
}
// Add all vivified types as classpath classes.
// They will be available at runtime in the desugared library dex file.
- List<DexClasspathClass> mockVivifiedClasses =
- desugaredLibraryWrapperAnalysis.generateWrappersSuperTypeMock();
- appBuilder.addClasspathClasses(mockVivifiedClasses);
- }
-
- private void postProcessLambdaDesugaring(DirectMappedDexApplication.Builder appBuilder) {
- if (lambdaRewriter == null || lambdaClasses.isEmpty()) {
- return;
- }
- for (LambdaClass lambdaClass : lambdaClasses.values()) {
- // Add all desugared classes to the application, main-dex list, and mark them instantiated.
- DexProgramClass programClass = lambdaClass.getOrCreateLambdaClass();
- appBuilder.addProgramClass(programClass);
- if (lambdaClass.addToMainDexList.get()) {
- appBuilder.addToMainDexList(Collections.singletonList(programClass.type));
- }
- liveTypes.add(programClass, graphReporter.fakeReportShouldNotBeUsed());
- objectAllocationInfoCollection.recordDirectAllocationSite(
- programClass,
- null,
- InstantiationReason.SYNTHESIZED_CLASS,
- graphReporter.fakeReportShouldNotBeUsed(),
- appInfo);
-
- // Register all of the field writes in the lambda constructors.
- // This is needed to ensure that the initializers can be optimized.
- Map<DexEncodedField, Set<DexEncodedMethod>> writes =
- lambdaRewriter.getWritesWithContexts(programClass);
- writes.forEach(
- (field, contexts) -> {
- for (DexEncodedMethod context : contexts) {
- registerFieldWrite(field.field, context);
- }
- });
-
- // Mark all methods on the desugared lambda classes as live.
- for (DexEncodedMethod method : programClass.methods()) {
- targetedMethods.add(method, graphReporter.fakeReportShouldNotBeUsed());
- liveMethods.add(programClass, method, graphReporter.fakeReportShouldNotBeUsed());
- }
-
- // Ensure accessors if needed and mark them live too.
- DexEncodedMethod accessor = lambdaClass.target.ensureAccessibilityIfNeeded(false);
- if (accessor != null) {
- DexProgramClass clazz = getProgramClassOrNull(accessor.method.holder);
- targetedMethods.add(accessor, graphReporter.fakeReportShouldNotBeUsed());
- liveMethods.add(clazz, accessor, graphReporter.fakeReportShouldNotBeUsed());
- }
- }
-
- // Rewrite all of the invoke-dynamic instructions to lambda class instantiations.
- lambdaCallSites.forEach(this::rewriteLambdaCallSites);
-
- // Remove all '$deserializeLambda$' methods which are not supported by desugaring.
- for (DexProgramClass clazz : classesWithSerializableLambdas) {
- clazz.removeDirectMethod(appView.dexItemFactory().deserializeLambdaMethod);
- }
+ desugaredLibraryWrapperAnalysis
+ .generateWrappersSuperTypeMock(wrappers)
+ .forEach(additions::addClasspathClass);
}
private void rewriteLambdaCallSites(
@@ -2893,7 +2970,7 @@
// Notify each analysis that a fixpoint has been reached, and give each analysis an
// opportunity to add items to the worklist.
- analyses.forEach(analysis -> analysis.notifyFixpoint(this, workList));
+ analyses.forEach(analysis -> analysis.notifyFixpoint(this, workList, timing));
if (!workList.isEmpty()) {
continue;
}
@@ -2905,6 +2982,11 @@
continue;
}
+ synthesize();
+ if (!workList.isEmpty()) {
+ continue;
+ }
+
// Reached the fixpoint.
break;
}
diff --git a/src/main/java/com/android/tools/r8/shaking/StaticClassMerger.java b/src/main/java/com/android/tools/r8/shaking/StaticClassMerger.java
index b89678e..5031d82 100644
--- a/src/main/java/com/android/tools/r8/shaking/StaticClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/StaticClassMerger.java
@@ -471,9 +471,9 @@
numberOfMergedClasses++;
// Move members from source to target.
- targetClass.appendDirectMethods(
+ targetClass.addDirectMethods(
mergeMethods(sourceClass.directMethods(), targetClass.directMethods(), targetClass));
- targetClass.appendVirtualMethods(
+ targetClass.addVirtualMethods(
mergeMethods(sourceClass.virtualMethods(), targetClass.virtualMethods(), targetClass));
targetClass.setStaticFields(
mergeFields(sourceClass.staticFields(), targetClass.staticFields(), targetClass));
diff --git a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
index ef0ce63..92fa339 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
@@ -50,7 +50,6 @@
import com.android.tools.r8.utils.Timing;
import com.google.common.base.Equivalence;
import com.google.common.base.Equivalence.Wrapper;
-import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.common.collect.Streams;
@@ -238,10 +237,21 @@
}
private void initializeMergeCandidates(Iterable<DexProgramClass> classes) {
- for (DexProgramClass clazz : classes) {
- if (isMergeCandidate(clazz, pinnedTypes) && isStillMergeCandidate(clazz)) {
- mergeCandidates.add(clazz);
+ for (DexProgramClass sourceClass : classes) {
+ DexProgramClass targetClass = appInfo.getSingleDirectSubtype(sourceClass);
+ if (targetClass == null) {
+ continue;
}
+ if (!isMergeCandidate(sourceClass, targetClass, pinnedTypes)) {
+ continue;
+ }
+ if (!isStillMergeCandidate(sourceClass, targetClass)) {
+ continue;
+ }
+ if (mergeMayLeadToIllegalAccesses(sourceClass, targetClass)) {
+ continue;
+ }
+ mergeCandidates.add(sourceClass);
}
}
@@ -313,54 +323,41 @@
DexClass clazz = appInfo.definitionFor(baseType);
if (clazz != null && clazz.isProgramClass()) {
- boolean changed = pinnedTypes.add(baseType);
-
- if (Log.ENABLED) {
- if (changed && isMergeCandidate(clazz.asProgramClass(), ImmutableSet.of())) {
- reason.printLogMessageForClass(clazz);
- }
- }
+ pinnedTypes.add(baseType);
}
}
// Returns true if [clazz] is a merge candidate. Note that the result of the checks in this
// method do not change in response to any class merges.
- private boolean isMergeCandidate(DexProgramClass clazz, Set<DexType> pinnedTypes) {
- if (appInfo.getObjectAllocationInfoCollection().isInstantiatedDirectly(clazz)
- || appInfo.instantiatedLambdas.contains(clazz.type)
- || appInfo.isPinned(clazz.type)
- || pinnedTypes.contains(clazz.type)
- || appInfo.neverMerge.contains(clazz.type)) {
+ private boolean isMergeCandidate(
+ DexProgramClass sourceClass, DexProgramClass targetClass, Set<DexType> pinnedTypes) {
+ assert targetClass != null;
+
+ if (appInfo.getObjectAllocationInfoCollection().isInstantiatedDirectly(sourceClass)
+ || appInfo.instantiatedLambdas.contains(sourceClass.type)
+ || appInfo.isPinned(sourceClass.type)
+ || pinnedTypes.contains(sourceClass.type)
+ || appInfo.neverMerge.contains(sourceClass.type)) {
return false;
}
- assert Streams.stream(Iterables.concat(clazz.fields(), clazz.methods()))
+ assert Streams.stream(Iterables.concat(sourceClass.fields(), sourceClass.methods()))
.map(DexEncodedMember::toReference)
.noneMatch(appInfo::isPinned);
- if (appView.options().featureSplitConfiguration != null &&
- appView.options().featureSplitConfiguration.isInFeature(clazz)) {
+ if (appView.options().featureSplitConfiguration != null
+ && appView.options().featureSplitConfiguration.isInFeature(sourceClass)) {
// TODO(b/141452765): Allow class merging between classes in features.
return false;
}
-
- // Note that the property "singleSubtype == null" cannot change during merging, since we visit
- // classes in a top-down order.
- DexProgramClass singleSubtype = appInfo.getSingleDirectSubtype(clazz);
- if (singleSubtype == null) {
- // TODO(christofferqa): Even if [clazz] has multiple subtypes, we could still merge it into
- // its subclass if [clazz] is not live. This should only be done, though, if it does not
- // lead to members being duplicated.
- return false;
- }
- if (appView.appServices().allServiceTypes().contains(clazz.type)
- && appInfo.isPinned(singleSubtype.type)) {
+ if (appView.appServices().allServiceTypes().contains(sourceClass.type)
+ && appInfo.isPinned(targetClass.type)) {
if (Log.ENABLED) {
- AbortReason.SERVICE_LOADER.printLogMessageForClass(clazz);
+ AbortReason.SERVICE_LOADER.printLogMessageForClass(sourceClass);
}
return false;
}
- if (singleSubtype.isSerializable(appView) && !appInfo.isSerializable(clazz.type)) {
+ if (targetClass.isSerializable(appView) && !appInfo.isSerializable(sourceClass.type)) {
// https://docs.oracle.com/javase/8/docs/platform/serialization/spec/serial-arch.html
// 1.10 The Serializable Interface
// ...
@@ -369,32 +366,32 @@
// * Have access to the no-arg constructor of its first non-serializable superclass
return false;
}
- for (DexEncodedMethod method : clazz.directMethods()) {
+ for (DexEncodedMethod method : sourceClass.directMethods()) {
// We rename constructors to private methods and mark them to be forced-inlined, so we have to
// check if we can force-inline all constructors.
if (method.isInstanceInitializer()) {
- AbortReason reason = disallowInlining(method, singleSubtype.type);
+ AbortReason reason = disallowInlining(method, targetClass.type);
if (reason != null) {
// Cannot guarantee that markForceInline() will work.
if (Log.ENABLED) {
- reason.printLogMessageForClass(clazz);
+ reason.printLogMessageForClass(sourceClass);
}
return false;
}
}
}
- if (clazz.getEnclosingMethod() != null || !clazz.getInnerClasses().isEmpty()) {
+ if (sourceClass.getEnclosingMethod() != null || !sourceClass.getInnerClasses().isEmpty()) {
// TODO(b/147504070): Consider merging of enclosing-method and inner-class attributes.
if (Log.ENABLED) {
- AbortReason.UNSUPPORTED_ATTRIBUTES.printLogMessageForClass(clazz);
+ AbortReason.UNSUPPORTED_ATTRIBUTES.printLogMessageForClass(sourceClass);
}
return false;
}
// We abort class merging when merging across nests or from a nest to non-nest.
// Without nest this checks null == null.
- if (singleSubtype.getNestHost() != clazz.getNestHost()) {
+ if (targetClass.getNestHost() != sourceClass.getNestHost()) {
if (Log.ENABLED) {
- AbortReason.MERGE_ACROSS_NESTS.printLogMessageForClass(clazz);
+ AbortReason.MERGE_ACROSS_NESTS.printLogMessageForClass(sourceClass);
}
return false;
}
@@ -404,66 +401,61 @@
// Returns true if [clazz] is a merge candidate. Note that the result of the checks in this
// method may change in response to class merges. Therefore, this method should always be called
// before merging [clazz] into its subtype.
- private boolean isStillMergeCandidate(DexProgramClass clazz) {
- assert isMergeCandidate(clazz, pinnedTypes);
- if (mergedClassesInverse.containsKey(clazz.type)) {
+ private boolean isStillMergeCandidate(DexProgramClass sourceClass, DexProgramClass targetClass) {
+ assert isMergeCandidate(sourceClass, targetClass, pinnedTypes);
+ if (mergedClassesInverse.containsKey(sourceClass.type)) {
// Do not allow merging the resulting class into its subclass.
// TODO(christofferqa): Get rid of this limitation.
if (Log.ENABLED) {
- AbortReason.ALREADY_MERGED.printLogMessageForClass(clazz);
+ AbortReason.ALREADY_MERGED.printLogMessageForClass(sourceClass);
}
return false;
}
- DexProgramClass targetClass = appInfo.getSingleDirectSubtype(clazz);
// For interface types, this is more complicated, see:
// https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-5.html#jvms-5.5
// We basically can't move the clinit, since it is not called when implementing classes have
// their clinit called - except when the interface has a default method.
- if ((clazz.hasClassInitializer() && targetClass.hasClassInitializer())
+ if ((sourceClass.hasClassInitializer() && targetClass.hasClassInitializer())
|| targetClass.classInitializationMayHaveSideEffects(
- appView, type -> type == clazz.type, Sets.newIdentityHashSet())
- || (clazz.isInterface() && clazz.classInitializationMayHaveSideEffects(appView))) {
+ appView, type -> type == sourceClass.type, Sets.newIdentityHashSet())
+ || (sourceClass.isInterface()
+ && sourceClass.classInitializationMayHaveSideEffects(appView))) {
// TODO(herhut): Handle class initializers.
if (Log.ENABLED) {
- AbortReason.STATIC_INITIALIZERS.printLogMessageForClass(clazz);
+ AbortReason.STATIC_INITIALIZERS.printLogMessageForClass(sourceClass);
}
return false;
}
boolean sourceCanBeSynchronizedOn =
- appView.appInfo().isLockCandidate(clazz.type) || clazz.hasStaticSynchronizedMethods();
+ appView.appInfo().isLockCandidate(sourceClass.type)
+ || sourceClass.hasStaticSynchronizedMethods();
boolean targetCanBeSynchronizedOn =
appView.appInfo().isLockCandidate(targetClass.type)
|| targetClass.hasStaticSynchronizedMethods();
if (sourceCanBeSynchronizedOn && targetCanBeSynchronizedOn) {
if (Log.ENABLED) {
- AbortReason.SOURCE_AND_TARGET_LOCK_CANDIDATES.printLogMessageForClass(clazz);
+ AbortReason.SOURCE_AND_TARGET_LOCK_CANDIDATES.printLogMessageForClass(sourceClass);
}
return false;
}
if (targetClass.getEnclosingMethod() != null || !targetClass.getInnerClasses().isEmpty()) {
// TODO(b/147504070): Consider merging of enclosing-method and inner-class attributes.
if (Log.ENABLED) {
- AbortReason.UNSUPPORTED_ATTRIBUTES.printLogMessageForClass(clazz);
+ AbortReason.UNSUPPORTED_ATTRIBUTES.printLogMessageForClass(sourceClass);
}
return false;
}
- if (mergeMayLeadToIllegalAccesses(clazz, targetClass)) {
+ if (methodResolutionMayChange(sourceClass, targetClass)) {
if (Log.ENABLED) {
- AbortReason.ILLEGAL_ACCESS.printLogMessageForClass(clazz);
- }
- return false;
- }
- if (methodResolutionMayChange(clazz, targetClass)) {
- if (Log.ENABLED) {
- AbortReason.RESOLUTION_FOR_METHODS_MAY_CHANGE.printLogMessageForClass(clazz);
+ AbortReason.RESOLUTION_FOR_METHODS_MAY_CHANGE.printLogMessageForClass(sourceClass);
}
return false;
}
// Field resolution first considers the direct interfaces of [targetClass] before it proceeds
// to the super class.
- if (fieldResolutionMayChange(clazz, targetClass)) {
+ if (fieldResolutionMayChange(sourceClass, targetClass)) {
if (Log.ENABLED) {
- AbortReason.RESOLUTION_FOR_FIELDS_MAY_CHANGE.printLogMessageForClass(clazz);
+ AbortReason.RESOLUTION_FOR_FIELDS_MAY_CHANGE.printLogMessageForClass(sourceClass);
}
return false;
}
@@ -782,20 +774,19 @@
return;
}
- assert isMergeCandidate(clazz, pinnedTypes);
-
DexProgramClass targetClass = appInfo.getSingleDirectSubtype(clazz);
+ assert isMergeCandidate(clazz, targetClass, pinnedTypes);
assert !mergedClasses.containsKey(targetClass.type);
boolean clazzOrTargetClassHasBeenMerged =
mergedClassesInverse.containsKey(clazz.type)
|| mergedClassesInverse.containsKey(targetClass.type);
if (clazzOrTargetClassHasBeenMerged) {
- if (!isStillMergeCandidate(clazz)) {
+ if (!isStillMergeCandidate(clazz, targetClass)) {
return;
}
} else {
- assert isStillMergeCandidate(clazz);
+ assert isStillMergeCandidate(clazz, targetClass);
}
// Guard against the case where we have two methods that may get the same signature
@@ -1085,8 +1076,8 @@
? DexTypeList.empty()
: new DexTypeList(interfaces.toArray(DexType.EMPTY_ARRAY));
// Step 2: replace fields and methods.
- target.appendDirectMethods(directMethods.values());
- target.appendVirtualMethods(virtualMethods.values());
+ target.addDirectMethods(directMethods.values());
+ target.addVirtualMethods(virtualMethods.values());
target.setInstanceFields(mergedInstanceFields);
target.setStaticFields(mergedStaticFields);
target.forEachField(feedback::markFieldCannotBeKept);
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 37b38e9..f9f955c 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -287,6 +287,8 @@
public boolean enablePcDebugInfoOutput = false;
+ public String synthesizedClassPrefix = "";
+
// Number of threads to use while processing the dex files.
public int threadCount = DETERMINISTIC_DEBUGGING ? 1 : ThreadUtils.NOT_SPECIFIED;
// Print smali disassembly.
@@ -360,6 +362,10 @@
return desugaredLibraryConfiguration.isLibraryCompilation();
}
+ public boolean shouldBackportMethods() {
+ return !hasConsumer() || isGeneratingDex();
+ }
+
public boolean shouldKeepStackMapTable() {
return isDesugaredLibraryCompilation()
|| getProguardConfiguration().getKeepAttributes().stackMapTable;
@@ -1091,6 +1097,7 @@
public PrintStream whyAreYouNotInliningConsumer = System.out;
public boolean trackDesugaredAPIConversions =
System.getProperty("com.android.tools.r8.trackDesugaredAPIConversions") != null;
+ public boolean forceLibBackportsInL8CfToCf = false;
// TODO(b/144781417): This is disabled by default as some test apps appear to have such classes.
public boolean allowNonAbstractClassesWithAbstractMethods = true;
@@ -1143,6 +1150,12 @@
enableNameReflectionOptimization = false;
}
+ @VisibleForTesting
+ public void enableEnumUnboxing() {
+ assert !enableEnumUnboxing;
+ enableEnumUnboxing = true;
+ }
+
// TODO(b/69963623): Remove this once enabled.
@VisibleForTesting
public void enablePropagationOfConstantsAtCallSites() {
diff --git a/src/test/java/com/android/tools/r8/R8RunExamplesAndroidOTest.java b/src/test/java/com/android/tools/r8/R8RunExamplesAndroidOTest.java
index a642002..b8256fe 100644
--- a/src/test/java/com/android/tools/r8/R8RunExamplesAndroidOTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunExamplesAndroidOTest.java
@@ -102,7 +102,7 @@
.withOptionConsumer(opts -> opts.enableClassInlining = false)
.withBuilderTransformation(
b -> b.addProguardConfiguration(PROGUARD_OPTIONS, Origin.unknown()))
- .withDexCheck(inspector -> checkLambdaCount(inspector, 115, "lambdadesugaring"))
+ .withDexCheck(inspector -> checkLambdaCount(inspector, 116, "lambdadesugaring"))
.run();
test("lambdadesugaring", "lambdadesugaring", "LambdaDesugaring")
@@ -142,7 +142,7 @@
.withOptionConsumer(opts -> opts.enableClassInlining = false)
.withBuilderTransformation(
b -> b.addProguardConfiguration(PROGUARD_OPTIONS, Origin.unknown()))
- .withDexCheck(inspector -> checkLambdaCount(inspector, 115, "lambdadesugaring"))
+ .withDexCheck(inspector -> checkLambdaCount(inspector, 116, "lambdadesugaring"))
.run();
test("lambdadesugaring", "lambdadesugaring", "LambdaDesugaring")
diff --git a/src/test/java/com/android/tools/r8/TestCompileResult.java b/src/test/java/com/android/tools/r8/TestCompileResult.java
index 87cc650..7f777ed 100644
--- a/src/test/java/com/android/tools/r8/TestCompileResult.java
+++ b/src/test/java/com/android/tools/r8/TestCompileResult.java
@@ -208,10 +208,18 @@
return self();
}
+ public CR disableVerifer() {
+ assert getBackend() == Backend.CF;
+ if (!vmArguments.contains("-noverify")) {
+ vmArguments.add("-noverify");
+ }
+ return self();
+ }
+
public CR enableRuntimeAssertions() {
assert getBackend() == Backend.CF;
- if (!this.vmArguments.contains("-ea")) {
- this.vmArguments.add("-ea");
+ if (!vmArguments.contains("-ea")) {
+ vmArguments.add("-ea");
}
return self();
}
diff --git a/src/test/java/com/android/tools/r8/TestParameters.java b/src/test/java/com/android/tools/r8/TestParameters.java
index d494ea2..d886efb 100644
--- a/src/test/java/com/android/tools/r8/TestParameters.java
+++ b/src/test/java/com/android/tools/r8/TestParameters.java
@@ -23,6 +23,11 @@
this.apiLevel = apiLevel;
}
+ public boolean canUseDefaultAndStaticInterfaceMethods() {
+ assert isCfRuntime() || isDexRuntime();
+ return isCfRuntime() || getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.N);
+ }
+
// Convenience predicates.
public boolean isDexRuntime() {
return runtime.isDex();
diff --git a/src/test/java/com/android/tools/r8/desugar/DesugarInstanceLambdaWithReadsTest.java b/src/test/java/com/android/tools/r8/desugar/DesugarInstanceLambdaWithReadsTest.java
index 07e4f62..bf507de 100644
--- a/src/test/java/com/android/tools/r8/desugar/DesugarInstanceLambdaWithReadsTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/DesugarInstanceLambdaWithReadsTest.java
@@ -87,8 +87,8 @@
}
static class Main {
- // Field that is read from the lambda$ method.
- A filter;
+ // Field that is read from the lambda$ method (private ensures the method can't be inlined).
+ private A filter;
public Main(A filter) {
this.filter = filter;
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ConcurrentHashMapSubclassTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ConcurrentHashMapSubclassTest.java
new file mode 100644
index 0000000..f13eddb
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ConcurrentHashMapSubclassTest.java
@@ -0,0 +1,130 @@
+// 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.desugar.desugaredlibrary;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.utils.BooleanUtils;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class ConcurrentHashMapSubclassTest extends DesugaredLibraryTestBase {
+
+ private final TestParameters parameters;
+ private final boolean shrinkDesugaredLibrary;
+
+ @Parameters(name = "{1}, shrinkDesugaredLibrary: {0}")
+ public static List<Object[]> data() {
+ return buildParameters(
+ BooleanUtils.values(), getTestParameters().withDexRuntimes().withAllApiLevels().build());
+ }
+
+ public ConcurrentHashMapSubclassTest(boolean shrinkDesugaredLibrary, TestParameters parameters) {
+ this.shrinkDesugaredLibrary = shrinkDesugaredLibrary;
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testCustomCollectionD8() throws Exception {
+ KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
+ testForD8()
+ .addInnerClasses(ConcurrentHashMapSubclassTest.class)
+ .setMinApi(parameters.getApiLevel())
+ .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
+ .compile()
+ .addDesugaredCoreLibraryRunClassPath(
+ this::buildDesugaredLibrary,
+ parameters.getApiLevel(),
+ keepRuleConsumer.get(),
+ shrinkDesugaredLibrary)
+ .run(parameters.getRuntime(), Executor.class)
+ .assertSuccessWithOutputLines("1.0", "10.0", "1.0", "10.0", "1.0", "10.0");
+ }
+
+ @Test
+ public void testCustomCollectionR8() throws Exception {
+ KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
+ testForR8(Backend.DEX)
+ .addInnerClasses(ConcurrentHashMapSubclassTest.class)
+ .setMinApi(parameters.getApiLevel())
+ .addKeepClassAndMembersRules(Executor.class)
+ .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
+ .compile()
+ .addDesugaredCoreLibraryRunClassPath(
+ this::buildDesugaredLibrary,
+ parameters.getApiLevel(),
+ keepRuleConsumer.get(),
+ shrinkDesugaredLibrary)
+ .run(parameters.getRuntime(), Executor.class)
+ .assertSuccessWithOutputLines("1.0", "10.0", "1.0", "10.0", "1.0", "10.0");
+ }
+
+ @SuppressWarnings("unchecked")
+ static class Executor {
+ public static void main(String[] args) {
+ directType();
+ classType();
+ itfType();
+ }
+
+ static void itfType() {
+ Map map = new NullableConcurrentHashMap<Integer, Double>();
+ map.put(1, 1.0);
+ map.putAll(example());
+ System.out.println(map.get(1));
+ System.out.println(map.get(10));
+ }
+
+ static void classType() {
+ ConcurrentHashMap map = new NullableConcurrentHashMap<Integer, Double>();
+ map.put(1, 1.0);
+ map.putAll(example());
+ System.out.println(map.get(1));
+ System.out.println(map.get(10));
+ }
+
+ static void directType() {
+ NullableConcurrentHashMap map = new NullableConcurrentHashMap<Integer, Double>();
+ map.put(1, 1.0);
+ map.putAll(example());
+ System.out.println(map.get(1));
+ System.out.println(map.get(10));
+ }
+
+ static Map<Integer, Double> example() {
+ IdentityHashMap<Integer, Double> example = new IdentityHashMap<>();
+ example.put(10, 10.0);
+ return example;
+ }
+ }
+
+ static class NullableConcurrentHashMap<K, V> extends ConcurrentHashMap<K, V> {
+ NullableConcurrentHashMap() {
+ super();
+ }
+
+ @SuppressWarnings("NullableProblems")
+ @Override
+ public V put(K key, V value) {
+ if (key == null || value == null) {
+ return null;
+ }
+ return super.put(key, value);
+ }
+
+ @Override
+ public void putAll(Map<? extends K, ? extends V> m) {
+ for (Entry<? extends K, ? extends V> entry : m.entrySet()) {
+ put(entry.getKey(), entry.getValue());
+ }
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryTestBase.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryTestBase.java
index 628fbfe..b68997a 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryTestBase.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryTestBase.java
@@ -82,7 +82,7 @@
// If we compile extended library here, it means we use TestNG.
// TestNG requires annotations, hence we disable AnnotationRemoval.
// This implies that extra warning are generated if this is set.
- boolean disableL8AnnotationRemovalForTesting = !additionalProgramFiles.isEmpty();
+ boolean extraFiles = !additionalProgramFiles.isEmpty();
ArrayList<Path> extraPaths = new ArrayList<>(additionalProgramFiles);
TestDiagnosticMessagesImpl diagnosticsHandler = new TestDiagnosticMessagesImpl();
Path desugaredLib = temp.newFolder().toPath().resolve("desugar_jdk_libs_dex.zip");
@@ -104,11 +104,12 @@
ToolHelper.runL8(
l8Builder.build(),
options -> {
- if (disableL8AnnotationRemovalForTesting) {
+ if (extraFiles) {
options.testing.disableL8AnnotationRemoval = true;
+ options.testing.forceLibBackportsInL8CfToCf = true;
}
});
- if (!disableL8AnnotationRemovalForTesting) {
+ if (!extraFiles) {
assertTrue(
diagnosticsHandler.getInfos().stream()
.noneMatch(
diff --git a/src/test/java/com/android/tools/r8/desugaring/interfacemethods/DefaultInterfaceMethodDesugaringWithStaticResolutionTest.java b/src/test/java/com/android/tools/r8/desugaring/interfacemethods/DefaultInterfaceMethodDesugaringWithStaticResolutionTest.java
new file mode 100644
index 0000000..bdd7960
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugaring/interfacemethods/DefaultInterfaceMethodDesugaringWithStaticResolutionTest.java
@@ -0,0 +1,97 @@
+package com.android.tools.r8.desugaring.interfacemethods;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assume.assumeTrue;
+
+import com.android.tools.r8.D8TestRunResult;
+import com.android.tools.r8.R8TestRunResult;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class DefaultInterfaceMethodDesugaringWithStaticResolutionTest extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ public DefaultInterfaceMethodDesugaringWithStaticResolutionTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testJVM() throws Exception {
+ assumeTrue(parameters.isCfRuntime());
+ testForJvm()
+ .addTestClasspath()
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutputLines("I.m()");
+ }
+
+ @Test
+ public void testD8() throws Exception {
+ assumeTrue(parameters.isDexRuntime());
+ D8TestRunResult result =
+ testForD8()
+ .addInnerClasses(DefaultInterfaceMethodDesugaringWithStaticResolutionTest.class)
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .run(parameters.getRuntime(), TestClass.class);
+ // TODO(b/152163087): Should always succeed with "I.m()".
+ if (parameters.canUseDefaultAndStaticInterfaceMethods()) {
+ result.assertSuccessWithOutputLines("I.m()");
+ } else {
+ result.assertFailureWithErrorThatMatches(
+ containsString(AbstractMethodError.class.getTypeName()));
+ }
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ R8TestRunResult result =
+ testForR8(parameters.getBackend())
+ .addInnerClasses(DefaultInterfaceMethodDesugaringWithStaticResolutionTest.class)
+ .addKeepAllClassesRule()
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .run(parameters.getRuntime(), TestClass.class);
+ // TODO(b/152163087): Should always succeed with "I.m()".
+ if (parameters.canUseDefaultAndStaticInterfaceMethods()) {
+ result.assertSuccessWithOutputLines("I.m()");
+ } else {
+ result.assertFailureWithErrorThatMatches(
+ containsString(AbstractMethodError.class.getTypeName()));
+ }
+ }
+
+ static class TestClass {
+
+ public static void main(String[] args) {
+ I b = new B();
+ b.m();
+ }
+ }
+
+ interface I {
+
+ default void m() {
+ System.out.println("I.m()");
+ }
+ }
+
+ static class A {
+
+ private static void m() {
+ System.out.println("A.m()");
+ }
+ }
+
+ static class B extends A implements I {}
+}
diff --git a/src/test/java/com/android/tools/r8/enumunboxing/EnumClinitWithSideEffectsUnboxingTest.java b/src/test/java/com/android/tools/r8/enumunboxing/EnumClinitWithSideEffectsUnboxingTest.java
new file mode 100644
index 0000000..2fbd235
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/enumunboxing/EnumClinitWithSideEffectsUnboxingTest.java
@@ -0,0 +1,55 @@
+package com.android.tools.r8.enumunboxing;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.utils.InternalOptions;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class EnumClinitWithSideEffectsUnboxingTest extends EnumUnboxingTestBase {
+
+ private final KeepRule enumKeepRule;
+ private final TestParameters parameters;
+
+ @Parameters(name = "{1}, enum keep rule: {0}")
+ public static List<Object[]> data() {
+ return buildParameters(
+ getAllEnumKeepRules(), getTestParameters().withAllRuntimesAndApiLevels().build());
+ }
+
+ public EnumClinitWithSideEffectsUnboxingTest(KeepRule enumKeepRule, TestParameters parameters) {
+ this.enumKeepRule = enumKeepRule;
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void test() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(EnumClinitWithSideEffectsUnboxingTest.class)
+ .addKeepMainRule(TestClass.class)
+ .addKeepRules(enumKeepRule.getKeepRule())
+ .addOptionsModification(InternalOptions::enableEnumUnboxing)
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutputLines("Hello world!");
+ }
+
+ static class TestClass {
+
+ static MyEnum f = MyEnum.A;
+
+ public static void main(String[] args) {}
+ }
+
+ enum MyEnum {
+ A;
+
+ static {
+ System.out.println("Hello world!");
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/enumunboxing/EnumInitWithSideEffectsUnboxingTest.java b/src/test/java/com/android/tools/r8/enumunboxing/EnumInitWithSideEffectsUnboxingTest.java
new file mode 100644
index 0000000..d353692
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/enumunboxing/EnumInitWithSideEffectsUnboxingTest.java
@@ -0,0 +1,55 @@
+package com.android.tools.r8.enumunboxing;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.utils.InternalOptions;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class EnumInitWithSideEffectsUnboxingTest extends EnumUnboxingTestBase {
+
+ private final KeepRule enumKeepRule;
+ private final TestParameters parameters;
+
+ @Parameters(name = "{1}, enum keep rule: {0}")
+ public static List<Object[]> data() {
+ return buildParameters(
+ getAllEnumKeepRules(), getTestParameters().withAllRuntimesAndApiLevels().build());
+ }
+
+ public EnumInitWithSideEffectsUnboxingTest(KeepRule enumKeepRule, TestParameters parameters) {
+ this.enumKeepRule = enumKeepRule;
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void test() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(EnumInitWithSideEffectsUnboxingTest.class)
+ .addKeepMainRule(TestClass.class)
+ .addKeepRules(enumKeepRule.getKeepRule())
+ .addOptionsModification(InternalOptions::enableEnumUnboxing)
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutputLines("Hello world!");
+ }
+
+ static class TestClass {
+
+ static MyEnum f = MyEnum.A;
+
+ public static void main(String[] args) {}
+ }
+
+ enum MyEnum {
+ A;
+
+ MyEnum() {
+ System.out.println("Hello world!");
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/enumunboxing/EnumUnboxingArrayTest.java b/src/test/java/com/android/tools/r8/enumunboxing/EnumUnboxingArrayTest.java
index 7d6f2ac..c97b7a7 100644
--- a/src/test/java/com/android/tools/r8/enumunboxing/EnumUnboxingArrayTest.java
+++ b/src/test/java/com/android/tools/r8/enumunboxing/EnumUnboxingArrayTest.java
@@ -18,7 +18,7 @@
@RunWith(Parameterized.class)
public class EnumUnboxingArrayTest extends EnumUnboxingTestBase {
- private static final Class<?>[] FAILURES = {
+ private static final Class<?>[] SUCCESSES = {
EnumVarArgs.class,
EnumArrayReadWriteNoEscape.class,
EnumArrayReadWrite.class,
@@ -42,11 +42,11 @@
}
@Test
- public void testEnumUnboxingFailure() throws Exception {
+ public void testEnumUnboxing() throws Exception {
R8TestCompileResult compile =
testForR8(parameters.getBackend())
.addInnerClasses(EnumUnboxingArrayTest.class)
- .addKeepMainRules(FAILURES)
+ .addKeepMainRules(SUCCESSES)
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.addKeepRules(enumKeepRules.getKeepRule())
@@ -54,14 +54,14 @@
.allowDiagnosticInfoMessages()
.setMinApi(parameters.getApiLevel())
.compile();
- for (Class<?> failure : FAILURES) {
+ for (Class<?> success : SUCCESSES) {
R8TestRunResult run =
compile
.inspectDiagnosticMessages(
m ->
- assertEnumIsBoxed(
- failure.getDeclaredClasses()[0], failure.getSimpleName(), m))
- .run(parameters.getRuntime(), failure)
+ assertEnumIsUnboxed(
+ success.getDeclaredClasses()[0], success.getSimpleName(), m))
+ .run(parameters.getRuntime(), success)
.assertSuccess();
assertLines2By2Correct(run.getStdOut());
}
@@ -96,8 +96,8 @@
myEnums[1] = MyEnum.C;
System.out.println(myEnums[1].ordinal());
System.out.println(2);
- System.out.println(myEnums[0]);
- System.out.println("null");
+ System.out.println(myEnums[0] == null);
+ System.out.println("true");
myEnums[0] = MyEnum.B;
System.out.println(myEnums.length);
System.out.println(2);
@@ -117,8 +117,8 @@
MyEnum[] myEnums = getArray();
System.out.println(myEnums[1].ordinal());
System.out.println(2);
- System.out.println(myEnums[0]);
- System.out.println("null");
+ System.out.println(myEnums[0] == null);
+ System.out.println("true");
myEnums[0] = MyEnum.B;
System.out.println(sum(myEnums));
System.out.println(2);
@@ -152,6 +152,8 @@
System.out.println(2);
System.out.println(myEnums[0][0].ordinal());
System.out.println(1);
+ System.out.println(myEnums[0].length);
+ System.out.println(2);
}
@NeverInline
diff --git a/src/test/java/com/android/tools/r8/enumunboxing/EnumUnboxingTestBase.java b/src/test/java/com/android/tools/r8/enumunboxing/EnumUnboxingTestBase.java
index e03d352..e367418 100644
--- a/src/test/java/com/android/tools/r8/enumunboxing/EnumUnboxingTestBase.java
+++ b/src/test/java/com/android/tools/r8/enumunboxing/EnumUnboxingTestBase.java
@@ -96,4 +96,8 @@
BooleanUtils.values(),
KEEP_ENUM);
}
+
+ static List<KeepRule> getAllEnumKeepRules() {
+ return KEEP_ENUM;
+ }
}
diff --git a/src/test/java/com/android/tools/r8/enumunboxing/SwitchEnumUnboxingTest.java b/src/test/java/com/android/tools/r8/enumunboxing/SwitchEnumUnboxingTest.java
index b7c7005..3ccdd37 100644
--- a/src/test/java/com/android/tools/r8/enumunboxing/SwitchEnumUnboxingTest.java
+++ b/src/test/java/com/android/tools/r8/enumunboxing/SwitchEnumUnboxingTest.java
@@ -51,7 +51,9 @@
.compile()
.inspectDiagnosticMessages(
m -> {
- if (enumValueOptimization) {
+ // TODO(b/150370354): We need to allow static helper method to re-enable unboxing
+ // with switches.
+ if (enumValueOptimization && enumKeepRules.getKeepRule().equals("")) {
assertEnumIsUnboxed(ENUM_CLASS, classToTest.getSimpleName(), m);
} else {
assertEnumIsBoxed(ENUM_CLASS, classToTest.getSimpleName(), m);
diff --git a/src/test/java/com/android/tools/r8/inspection/InspectionApiTest.java b/src/test/java/com/android/tools/r8/inspection/InspectionApiTest.java
index 5c5a6e3..9f413d5 100644
--- a/src/test/java/com/android/tools/r8/inspection/InspectionApiTest.java
+++ b/src/test/java/com/android/tools/r8/inspection/InspectionApiTest.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.inspection;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
@@ -14,6 +15,9 @@
import com.android.tools.r8.references.MethodReference;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.utils.StringUtils;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -49,7 +53,7 @@
.apply(b -> b.getBuilder().addOutputInspection(this::inspection))
.run(parameters.getRuntime(), TestClass.class)
.assertSuccessWithOutput(EXPECTED);
- assertFound();
+ assertFound(false);
}
@Test
@@ -61,37 +65,47 @@
.apply(b -> b.getBuilder().addOutputInspection(this::inspection))
.run(parameters.getRuntime(), TestClass.class)
.assertSuccessWithOutput(EXPECTED);
- assertFound();
+ assertFound(true);
}
ClassReference foundClass = null;
FieldReference foundField = null;
- MethodReference foundMethod = null;
+ Set<MethodReference> foundMethods = new HashSet<>();
private void inspection(Inspector inspector) {
inspector.forEachClass(
classInspector -> {
+ assertNull(foundClass);
foundClass = classInspector.getClassReference();
classInspector.forEachField(
fieldInspector -> {
+ assertNull(foundField);
foundField = fieldInspector.getFieldReference();
});
classInspector.forEachMethod(
methodInspector -> {
- // Ignore clinit (which is removed in R8).
- if (!methodInspector.getMethodReference().getMethodName().equals("<clinit>")) {
- foundMethod = methodInspector.getMethodReference();
- }
+ foundMethods.add(methodInspector.getMethodReference());
});
});
}
- private void assertFound() throws Exception {
+ private void assertFound(boolean isR8) throws Exception {
assertEquals(Reference.classFromClass(TestClass.class), foundClass);
assertEquals(Reference.fieldFromField(TestClass.class.getDeclaredField("foo")), foundField);
- assertEquals(
- Reference.methodFromMethod(TestClass.class.getDeclaredMethod("main", String[].class)),
- foundMethod);
+
+ Set<MethodReference> expectedMethods = new HashSet<>();
+ expectedMethods.add(
+ Reference.methodFromMethod(TestClass.class.getDeclaredMethod("main", String[].class)));
+ expectedMethods.add(Reference.methodFromMethod(TestClass.class.getDeclaredConstructor()));
+ if (!isR8) {
+ expectedMethods.add(
+ Reference.method(
+ Reference.classFromClass(TestClass.class),
+ "<clinit>",
+ Collections.emptyList(),
+ null));
+ }
+ assertEquals(expectedMethods, foundMethods);
}
static class TestClass {
diff --git a/src/test/java/com/android/tools/r8/ir/LinearFlowIteratorTest.java b/src/test/java/com/android/tools/r8/ir/LinearFlowIteratorTest.java
index 88785c4..0d31dca 100644
--- a/src/test/java/com/android/tools/r8/ir/LinearFlowIteratorTest.java
+++ b/src/test/java/com/android/tools/r8/ir/LinearFlowIteratorTest.java
@@ -153,7 +153,7 @@
IRCode code = simpleCode();
InstructionListIterator it = new LinearFlowInstructionListIterator(code, code.blocks.get(1));
Instruction current = it.previous();
- assertTrue(current.isConstNumber() && current.outValue().getTypeLattice().isReference());
+ assertTrue(current.isConstNumber() && current.outValue().getType().isReferenceType());
it.next();
current = it.next();
assertTrue(current.isArrayGet());
diff --git a/src/test/java/com/android/tools/r8/ir/SplitBlockTest.java b/src/test/java/com/android/tools/r8/ir/SplitBlockTest.java
index e53db5e..2b3e44d 100644
--- a/src/test/java/com/android/tools/r8/ir/SplitBlockTest.java
+++ b/src/test/java/com/android/tools/r8/ir/SplitBlockTest.java
@@ -11,7 +11,7 @@
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexApplication;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.Add;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.ConstNumber;
@@ -363,10 +363,9 @@
BasicBlock newReturnBlock = iterator.split(code);
// Modify the code to make the inserted block add the constant 10 to the original return
// value.
- Value newConstValue =
- new Value(test.valueNumberGenerator.next(), TypeLatticeElement.getInt(), null);
+ Value newConstValue = new Value(test.valueNumberGenerator.next(), TypeElement.getInt(), null);
Value newReturnValue =
- new Value(test.valueNumberGenerator.next(), TypeLatticeElement.getInt(), null);
+ new Value(test.valueNumberGenerator.next(), TypeElement.getInt(), null);
Value oldReturnValue = newReturnBlock.iterator().next().asReturn().returnValue();
newReturnBlock.iterator().next().asReturn().returnValue().replaceUsers(newReturnValue);
Instruction constInstruction = new ConstNumber(newConstValue, 10);
diff --git a/src/test/java/com/android/tools/r8/ir/analysis/type/ArrayTypeTest.java b/src/test/java/com/android/tools/r8/ir/analysis/type/ArrayTypeTest.java
index 74a49ed..a644df9 100644
--- a/src/test/java/com/android/tools/r8/ir/analysis/type/ArrayTypeTest.java
+++ b/src/test/java/com/android/tools/r8/ir/analysis/type/ArrayTypeTest.java
@@ -4,8 +4,8 @@
package com.android.tools.r8.ir.analysis.type;
-import static com.android.tools.r8.ir.analysis.type.TypeLatticeElement.getFloat;
-import static com.android.tools.r8.ir.analysis.type.TypeLatticeElement.getInt;
+import static com.android.tools.r8.ir.analysis.type.TypeElement.getFloat;
+import static com.android.tools.r8.ir.analysis.type.TypeElement.getInt;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -69,13 +69,13 @@
value = arrayPutInstruction.value();
}
- assertTrue(array.getTypeLattice().isArrayType());
+ assertTrue(array.getType().isArrayType());
- ArrayTypeLatticeElement arrayType = array.getTypeLattice().asArrayTypeLatticeElement();
- TypeLatticeElement elementType = arrayType.getArrayMemberTypeAsMemberType();
+ ArrayTypeElement arrayType = array.getType().asArrayType();
+ TypeElement elementType = arrayType.getMemberType();
assertEquals(getFloat(), elementType);
- assertEquals(getFloat(), value.getTypeLattice());
+ assertEquals(getFloat(), value.getType());
}
}
};
@@ -89,13 +89,13 @@
Value array = arrayPutInstruction.array();
Value value = arrayPutInstruction.value();
- assertTrue(array.getTypeLattice().isArrayType());
+ assertTrue(array.getType().isArrayType());
- ArrayTypeLatticeElement arrayType = array.getTypeLattice().asArrayTypeLatticeElement();
- TypeLatticeElement elementType = arrayType.getArrayMemberTypeAsMemberType();
+ ArrayTypeElement arrayType = array.getType().asArrayType();
+ TypeElement elementType = arrayType.getMemberType();
assertEquals(getFloat(), elementType);
- assertEquals(getFloat(), value.getTypeLattice());
+ assertEquals(getFloat(), value.getType());
}
{
@@ -104,7 +104,7 @@
code,
instruction ->
instruction.isConstNumber() && instruction.asConstNumber().getRawValue() != 0);
- assertEquals(getFloat(), constNumberInstruction.outValue().getTypeLattice());
+ assertEquals(getFloat(), constNumberInstruction.outValue().getType());
}
};
}
@@ -115,7 +115,7 @@
for (BasicBlock block : code.blocks) {
for (Phi phi : block.getPhis()) {
phiCount++;
- assertEquals(getInt(), phi.getTypeLattice());
+ assertEquals(getInt(), phi.getType());
}
}
assertEquals(2, phiCount);
diff --git a/src/test/java/com/android/tools/r8/ir/analysis/type/ConstrainedPrimitiveTypeTest.java b/src/test/java/com/android/tools/r8/ir/analysis/type/ConstrainedPrimitiveTypeTest.java
index 9471d46..e3b40cb 100644
--- a/src/test/java/com/android/tools/r8/ir/analysis/type/ConstrainedPrimitiveTypeTest.java
+++ b/src/test/java/com/android/tools/r8/ir/analysis/type/ConstrainedPrimitiveTypeTest.java
@@ -4,10 +4,10 @@
package com.android.tools.r8.ir.analysis.type;
-import static com.android.tools.r8.ir.analysis.type.TypeLatticeElement.getDouble;
-import static com.android.tools.r8.ir.analysis.type.TypeLatticeElement.getFloat;
-import static com.android.tools.r8.ir.analysis.type.TypeLatticeElement.getInt;
-import static com.android.tools.r8.ir.analysis.type.TypeLatticeElement.getLong;
+import static com.android.tools.r8.ir.analysis.type.TypeElement.getDouble;
+import static com.android.tools.r8.ir.analysis.type.TypeElement.getFloat;
+import static com.android.tools.r8.ir.analysis.type.TypeElement.getInt;
+import static com.android.tools.r8.ir.analysis.type.TypeElement.getLong;
import static org.junit.Assert.assertEquals;
import com.android.tools.r8.NeverInline;
@@ -93,12 +93,12 @@
}
private static Consumer<IRCode> testInspector(
- TypeLatticeElement expectedType, int expectedNumberOfConstNumberInstructions) {
+ TypeElement expectedType, int expectedNumberOfConstNumberInstructions) {
return code -> {
for (Instruction instruction : code.instructions()) {
if (instruction.isConstNumber()) {
ConstNumber constNumberInstruction = instruction.asConstNumber();
- assertEquals(expectedType, constNumberInstruction.outValue().getTypeLattice());
+ assertEquals(expectedType, constNumberInstruction.outValue().getType());
}
}
diff --git a/src/test/java/com/android/tools/r8/ir/analysis/type/NullabilityTest.java b/src/test/java/com/android/tools/r8/ir/analysis/type/NullabilityTest.java
index e4fb7b1..2590f1b 100644
--- a/src/test/java/com/android/tools/r8/ir/analysis/type/NullabilityTest.java
+++ b/src/test/java/com/android/tools/r8/ir/analysis/type/NullabilityTest.java
@@ -5,8 +5,8 @@
import static com.android.tools.r8.ir.analysis.type.Nullability.definitelyNotNull;
import static com.android.tools.r8.ir.analysis.type.Nullability.maybeNull;
-import static com.android.tools.r8.ir.analysis.type.TypeLatticeElement.fromDexType;
-import static com.android.tools.r8.ir.analysis.type.TypeLatticeElement.stringClassType;
+import static com.android.tools.r8.ir.analysis.type.TypeElement.fromDexType;
+import static com.android.tools.r8.ir.analysis.type.TypeElement.stringClassType;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -55,24 +55,24 @@
}
private static void verifyClassTypeLattice(
- Map<Class<? extends Instruction>, TypeLatticeElement> expectedLattices,
+ Map<Class<? extends Instruction>, TypeElement> expectedLattices,
DexType receiverType,
Value v,
- TypeLatticeElement l) {
+ TypeElement l) {
// Due to the last invocation that will check nullability of the argument,
// there is one exceptional mapping to PRIMITIVE.
- if (l.isPrimitive()) {
+ if (l.isPrimitiveType()) {
return;
}
assertTrue(l.isClassType());
- ClassTypeLatticeElement lattice = l.asClassTypeLatticeElement();
+ ClassTypeElement lattice = l.asClassType();
// Receiver
if (lattice.getClassType().equals(receiverType)) {
assertFalse(l.isNullable());
} else {
Instruction definition = v.definition;
if (definition != null) {
- TypeLatticeElement expected = expectedLattices.get(v.definition.getClass());
+ TypeElement expected = expectedLattices.get(v.definition.getClass());
if (expected != null) {
assertEquals(expected, l);
}
@@ -87,7 +87,7 @@
InvokeMethodWithReceiver invoke = instruction.asInvokeMethodWithReceiver();
if (invoke.getInvokedMethod().name.toString().contains("hash")) {
metInvokeVirtual = true;
- TypeLatticeElement l = invoke.getReceiver().getTypeLattice();
+ TypeElement l = invoke.getReceiver().getType();
assertEquals(npeCaught, l.isNullable());
}
}
@@ -95,14 +95,17 @@
assertTrue(metInvokeVirtual);
}
- private void forEachOutValue(IRCode irCode, BiConsumer<Value, TypeLatticeElement> consumer) {
- irCode.instructionIterator().forEachRemaining(instruction -> {
- Value outValue = instruction.outValue();
- if (outValue != null) {
- TypeLatticeElement element = outValue.getTypeLattice();
- consumer.accept(outValue, element);
- }
- });
+ private void forEachOutValue(IRCode irCode, BiConsumer<Value, TypeElement> consumer) {
+ irCode
+ .instructionIterator()
+ .forEachRemaining(
+ instruction -> {
+ Value outValue = instruction.outValue();
+ if (outValue != null) {
+ TypeElement element = outValue.getType();
+ consumer.accept(outValue, element);
+ }
+ });
}
@Test
@@ -122,7 +125,7 @@
.createType(
DescriptorUtils.javaTypeToDescriptor(
NonNullAfterInvoke.class.getCanonicalName()));
- Map<Class<? extends Instruction>, TypeLatticeElement> expectedLattices =
+ Map<Class<? extends Instruction>, TypeElement> expectedLattices =
ImmutableMap.of(
InvokeVirtual.class, stringClassType(appInfo, maybeNull()),
Assume.class, stringClassType(appInfo, definitelyNotNull()),
@@ -149,7 +152,7 @@
.createType(
DescriptorUtils.javaTypeToDescriptor(
NonNullAfterInvoke.class.getCanonicalName()));
- Map<Class<? extends Instruction>, TypeLatticeElement> expectedLattices =
+ Map<Class<? extends Instruction>, TypeElement> expectedLattices =
ImmutableMap.of(
InvokeVirtual.class, stringClassType(appInfo, maybeNull()),
Assume.class, stringClassType(appInfo, definitelyNotNull()),
@@ -176,7 +179,7 @@
.createType(
DescriptorUtils.javaTypeToDescriptor(
NonNullAfterArrayAccess.class.getCanonicalName()));
- Map<Class<? extends Instruction>, TypeLatticeElement> expectedLattices =
+ Map<Class<? extends Instruction>, TypeElement> expectedLattices =
ImmutableMap.of(
// An element inside a non-null array could be null.
ArrayGet.class,
@@ -186,13 +189,13 @@
irCode,
(v, l) -> {
if (l.isArrayType()) {
- ArrayTypeLatticeElement lattice = l.asArrayTypeLatticeElement();
+ ArrayTypeElement lattice = l.asArrayType();
assertEquals(1, lattice.getNesting());
- TypeLatticeElement elementTypeLattice = lattice.getArrayMemberTypeAsMemberType();
- assertTrue(elementTypeLattice.isClassType());
+ TypeElement elementType = lattice.getMemberType();
+ assertTrue(elementType.isClassType());
assertEquals(
appInfo.dexItemFactory().stringType,
- elementTypeLattice.asClassTypeLatticeElement().getClassType());
+ elementType.asClassType().getClassType());
assertEquals(v.definition.isArgument(), l.isNullable());
} else if (l.isClassType()) {
verifyClassTypeLattice(expectedLattices, mainClass, v, l);
@@ -218,7 +221,7 @@
.createType(
DescriptorUtils.javaTypeToDescriptor(
NonNullAfterArrayAccess.class.getCanonicalName()));
- Map<Class<? extends Instruction>, TypeLatticeElement> expectedLattices =
+ Map<Class<? extends Instruction>, TypeElement> expectedLattices =
ImmutableMap.of(
// An element inside a non-null array could be null.
ArrayGet.class,
@@ -228,13 +231,13 @@
irCode,
(v, l) -> {
if (l.isArrayType()) {
- ArrayTypeLatticeElement lattice = l.asArrayTypeLatticeElement();
+ ArrayTypeElement lattice = l.asArrayType();
assertEquals(1, lattice.getNesting());
- TypeLatticeElement elementTypeLattice = lattice.getArrayMemberTypeAsMemberType();
+ TypeElement elementTypeLattice = lattice.getMemberType();
assertTrue(elementTypeLattice.isClassType());
assertEquals(
appInfo.dexItemFactory().stringType,
- elementTypeLattice.asClassTypeLatticeElement().getClassType());
+ elementTypeLattice.asClassType().getClassType());
assertEquals(v.definition.isArgument(), l.isNullable());
} else if (l.isClassType()) {
verifyClassTypeLattice(expectedLattices, mainClass, v, l);
@@ -266,7 +269,7 @@
.createType(
DescriptorUtils.javaTypeToDescriptor(
FieldAccessTest.class.getCanonicalName()));
- Map<Class<? extends Instruction>, TypeLatticeElement> expectedLattices =
+ Map<Class<? extends Instruction>, TypeElement> expectedLattices =
ImmutableMap.of(
Argument.class, fromDexType(testClass, maybeNull(), appInfo),
Assume.class, fromDexType(testClass, definitelyNotNull(), appInfo),
@@ -302,7 +305,7 @@
.createType(
DescriptorUtils.javaTypeToDescriptor(
FieldAccessTest.class.getCanonicalName()));
- Map<Class<? extends Instruction>, TypeLatticeElement> expectedLattices =
+ Map<Class<? extends Instruction>, TypeElement> expectedLattices =
ImmutableMap.of(
Argument.class, fromDexType(testClass, maybeNull(), appInfo),
Assume.class, fromDexType(testClass, definitelyNotNull(), appInfo),
diff --git a/src/test/java/com/android/tools/r8/ir/analysis/type/TypeAnalysisTest.java b/src/test/java/com/android/tools/r8/ir/analysis/type/TypeAnalysisTest.java
index 198ffa3..d0cf699 100644
--- a/src/test/java/com/android/tools/r8/ir/analysis/type/TypeAnalysisTest.java
+++ b/src/test/java/com/android/tools/r8/ir/analysis/type/TypeAnalysisTest.java
@@ -58,10 +58,10 @@
@RunWith(Parameterized.class)
public class TypeAnalysisTest extends SmaliTestBase {
private static final InternalOptions TEST_OPTIONS = new InternalOptions();
- private static final TypeLatticeElement NULL = TypeLatticeElement.getNull();
- private static final TypeLatticeElement SINGLE = TypeLatticeElement.getSingle();
- private static final TypeLatticeElement INT = TypeLatticeElement.getInt();
- private static final TypeLatticeElement LONG = TypeLatticeElement.getLong();
+ private static final TypeElement NULL = TypeElement.getNull();
+ private static final TypeElement SINGLE = TypeElement.getSingle();
+ private static final TypeElement INT = TypeElement.getInt();
+ private static final TypeElement LONG = TypeElement.getLong();
private final String dirName;
private final String smaliFileName;
@@ -119,15 +119,17 @@
new CodeInspector(dexApplication));
}
- private static void forEachOutValue(
- IRCode irCode, BiConsumer<Value, TypeLatticeElement> consumer) {
- irCode.instructionIterator().forEachRemaining(instruction -> {
- Value outValue = instruction.outValue();
- if (outValue != null) {
- TypeLatticeElement element = outValue.getTypeLattice();
- consumer.accept(outValue, element);
- }
- });
+ private static void forEachOutValue(IRCode irCode, BiConsumer<Value, TypeElement> consumer) {
+ irCode
+ .instructionIterator()
+ .forEachRemaining(
+ instruction -> {
+ Value outValue = instruction.outValue();
+ if (outValue != null) {
+ TypeElement element = outValue.getType();
+ consumer.accept(outValue, element);
+ }
+ });
}
// Simple one path with a lot of arithmetic operations.
@@ -173,8 +175,8 @@
(v, l) -> {
if (v == finalArray) {
assertTrue(l.isArrayType());
- ArrayTypeLatticeElement lattice = l.asArrayTypeLatticeElement();
- assertTrue(lattice.getArrayMemberTypeAsMemberType().isPrimitive());
+ ArrayTypeElement lattice = l.asArrayType();
+ assertTrue(lattice.getMemberType().isPrimitiveType());
assertEquals(1, lattice.getNesting());
assertFalse(lattice.isNullable());
}
@@ -200,8 +202,8 @@
(v, l) -> {
if (v == finalArray) {
assertTrue(l.isArrayType());
- ArrayTypeLatticeElement lattice = l.asArrayTypeLatticeElement();
- assertTrue(lattice.getArrayMemberTypeAsMemberType().isPrimitive());
+ ArrayTypeElement lattice = l.asArrayType();
+ assertTrue(lattice.getMemberType().isPrimitiveType());
assertEquals(1, lattice.getNesting());
assertFalse(lattice.isNullable());
}
@@ -213,14 +215,16 @@
MethodSubject loop2Subject =
inspector.clazz("Test").method(new MethodSignature("loop2", "void", ImmutableList.of()));
IRCode irCode = loop2Subject.buildIR();
- forEachOutValue(irCode, (v, l) -> {
- if (l.isClassType()) {
- ClassTypeLatticeElement lattice = l.asClassTypeLatticeElement();
- assertEquals("Ljava/io/PrintStream;", lattice.getClassType().toDescriptorString());
- // TODO(b/70795205): Can be refined by using control-flow info.
- assertTrue(l.isNullable());
- }
- });
+ forEachOutValue(
+ irCode,
+ (v, l) -> {
+ if (l.isClassType()) {
+ ClassTypeElement lattice = l.asClassType();
+ assertEquals("Ljava/io/PrintStream;", lattice.getClassType().toDescriptorString());
+ // TODO(b/70795205): Can be refined by using control-flow info.
+ assertTrue(l.isNullable());
+ }
+ });
}
// move-exception
@@ -230,13 +234,15 @@
.clazz("Test")
.method(new MethodSignature("test2_throw", "int", ImmutableList.of()));
IRCode irCode = test2Subject.buildIR();
- forEachOutValue(irCode, (v, l) -> {
- if (l.isClassType()) {
- ClassTypeLatticeElement lattice = l.asClassTypeLatticeElement();
- assertEquals("Ljava/lang/Throwable;", lattice.getClassType().toDescriptorString());
- assertFalse(l.isNullable());
- }
- });
+ forEachOutValue(
+ irCode,
+ (v, l) -> {
+ if (l.isClassType()) {
+ ClassTypeElement lattice = l.asClassType();
+ assertEquals("Ljava/lang/Throwable;", lattice.getClassType().toDescriptorString());
+ assertFalse(l.isNullable());
+ }
+ });
}
// One very complicated example.
@@ -247,12 +253,12 @@
.method(
new MethodSignature("a", "void", ImmutableList.of("Test", "Test", "Test", "Test")));
DexType test = appView.dexItemFactory().createType("LTest;");
- Map<Class<? extends Instruction>, TypeLatticeElement> expectedLattices =
+ Map<Class<? extends Instruction>, TypeElement> expectedLattices =
ImmutableMap.of(
ArrayLength.class, INT,
- ConstString.class, TypeLatticeElement.stringClassType(appView, definitelyNotNull()),
- CheckCast.class, TypeLatticeElement.fromDexType(test, maybeNull(), appView),
- NewInstance.class, TypeLatticeElement.fromDexType(test, definitelyNotNull(), appView));
+ ConstString.class, TypeElement.stringClassType(appView, definitelyNotNull()),
+ CheckCast.class, TypeElement.fromDexType(test, maybeNull(), appView),
+ NewInstance.class, TypeElement.fromDexType(test, definitelyNotNull(), appView));
IRCode irCode = methodSubject.buildIR();
forEachOutValue(irCode, (v, l) -> {
verifyTypeEnvironment(expectedLattices, v, l);
@@ -275,27 +281,25 @@
.clazz("TestObject")
.method(new MethodSignature("onClick", "void", ImmutableList.of("Test")));
DexType test = appView.dexItemFactory().createType("LTest;");
- Map<Class<? extends Instruction>, TypeLatticeElement> expectedLattices =
+ Map<Class<? extends Instruction>, TypeElement> expectedLattices =
ImmutableMap.of(
- ConstString.class, TypeLatticeElement.stringClassType(appView, definitelyNotNull()),
+ ConstString.class, TypeElement.stringClassType(appView, definitelyNotNull()),
InstanceOf.class, INT,
- StaticGet.class, TypeLatticeElement.fromDexType(test, maybeNull(), appView));
+ StaticGet.class, TypeElement.fromDexType(test, maybeNull(), appView));
IRCode irCode = methodSubject.buildIR();
forEachOutValue(irCode, (v, l) -> verifyTypeEnvironment(expectedLattices, v, l));
}
- private static void assertEither(TypeLatticeElement actual, TypeLatticeElement... expected) {
+ private static void assertEither(TypeElement actual, TypeElement... expected) {
assertTrue(Arrays.stream(expected).anyMatch(e -> e == actual));
}
private static void verifyTypeEnvironment(
- Map<Class<? extends Instruction>, TypeLatticeElement> expectedLattices,
- Value v,
- TypeLatticeElement l) {
+ Map<Class<? extends Instruction>, TypeElement> expectedLattices, Value v, TypeElement l) {
if (v.definition == null) {
return;
}
- TypeLatticeElement expected = expectedLattices.get(v.definition.getClass());
+ TypeElement expected = expectedLattices.get(v.definition.getClass());
if (expected != null) {
assertEquals(expected, l);
}
diff --git a/src/test/java/com/android/tools/r8/ir/analysis/type/TypeConstraintOnTrivialPhiTest.java b/src/test/java/com/android/tools/r8/ir/analysis/type/TypeConstraintOnTrivialPhiTest.java
index 80d752e..0f40b4b 100644
--- a/src/test/java/com/android/tools/r8/ir/analysis/type/TypeConstraintOnTrivialPhiTest.java
+++ b/src/test/java/com/android/tools/r8/ir/analysis/type/TypeConstraintOnTrivialPhiTest.java
@@ -90,30 +90,28 @@
@Test
public void testIntConstraintOnTrivialPhi() throws Exception {
- buildAndCheckIR("intConstraintOnTrivialPhiTest", testInspector(TypeLatticeElement.getInt()));
+ buildAndCheckIR("intConstraintOnTrivialPhiTest", testInspector(TypeElement.getInt()));
}
@Test
public void testFloatConstraintOnTrivialPhi() throws Exception {
- buildAndCheckIR(
- "floatConstraintOnTrivialPhiTest", testInspector(TypeLatticeElement.getFloat()));
+ buildAndCheckIR("floatConstraintOnTrivialPhiTest", testInspector(TypeElement.getFloat()));
}
@Test
public void testLongConstraintOnTrivialPhi() throws Exception {
- buildAndCheckIR("longConstraintOnTrivialPhiTest", testInspector(TypeLatticeElement.getLong()));
+ buildAndCheckIR("longConstraintOnTrivialPhiTest", testInspector(TypeElement.getLong()));
}
@Test
public void testDoubleConstraintOnTrivialPhi() throws Exception {
- buildAndCheckIR(
- "doubleConstraintOnTrivialPhiTest", testInspector(TypeLatticeElement.getDouble()));
+ buildAndCheckIR("doubleConstraintOnTrivialPhiTest", testInspector(TypeElement.getDouble()));
}
- private static Consumer<IRCode> testInspector(TypeLatticeElement expectedType) {
+ private static Consumer<IRCode> testInspector(TypeElement expectedType) {
return code -> {
ConstNumber constNumberInstruction = getMatchingInstruction(code, Instruction::isConstNumber);
- assertEquals(expectedType, constNumberInstruction.outValue().getTypeLattice());
+ assertEquals(expectedType, constNumberInstruction.outValue().getType());
};
}
}
diff --git a/src/test/java/com/android/tools/r8/ir/analysis/type/TypeElementWidthTest.java b/src/test/java/com/android/tools/r8/ir/analysis/type/TypeElementWidthTest.java
new file mode 100644
index 0000000..304d344
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/analysis/type/TypeElementWidthTest.java
@@ -0,0 +1,93 @@
+// 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 com.android.tools.r8.ir.analysis.type;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.graph.DexItemFactory;
+import com.google.common.collect.ImmutableSet;
+import org.junit.Test;
+
+public class TypeElementWidthTest extends TestBase {
+
+ @Test
+ public void testArrayWidth() {
+ ArrayTypeElement arrayType =
+ ArrayTypeElement.create(TypeElement.getInt(), Nullability.maybeNull());
+ assertFalse(arrayType.isSinglePrimitive());
+ assertFalse(arrayType.isWidePrimitive());
+ assertEquals(1, arrayType.requiredRegisters());
+ }
+
+ @Test
+ public void testBooleanWidth() {
+ assertTrue(TypeElement.getBoolean().isSinglePrimitive());
+ assertFalse(TypeElement.getBoolean().isWidePrimitive());
+ assertEquals(1, TypeElement.getBoolean().requiredRegisters());
+ }
+
+ @Test
+ public void testByteWidth() {
+ assertTrue(TypeElement.getByte().isSinglePrimitive());
+ assertFalse(TypeElement.getByte().isWidePrimitive());
+ assertEquals(1, TypeElement.getByte().requiredRegisters());
+ }
+
+ @Test
+ public void testCharWidth() {
+ assertTrue(TypeElement.getChar().isSinglePrimitive());
+ assertFalse(TypeElement.getChar().isWidePrimitive());
+ assertEquals(1, TypeElement.getChar().requiredRegisters());
+ }
+
+ @Test
+ public void testDoubleWidth() {
+ assertTrue(TypeElement.getDouble().isWidePrimitive());
+ assertFalse(TypeElement.getDouble().isSinglePrimitive());
+ assertEquals(2, TypeElement.getDouble().requiredRegisters());
+ }
+
+ @Test
+ public void testFloatWidth() {
+ assertTrue(TypeElement.getFloat().isSinglePrimitive());
+ assertFalse(TypeElement.getFloat().isWidePrimitive());
+ assertEquals(1, TypeElement.getFloat().requiredRegisters());
+ }
+
+ @Test
+ public void testIntWidth() {
+ assertTrue(TypeElement.getInt().isSinglePrimitive());
+ assertFalse(TypeElement.getInt().isWidePrimitive());
+ assertEquals(1, TypeElement.getInt().requiredRegisters());
+ }
+
+ @Test
+ public void testLongWidth() {
+ assertTrue(TypeElement.getLong().isWidePrimitive());
+ assertFalse(TypeElement.getLong().isSinglePrimitive());
+ assertEquals(2, TypeElement.getLong().requiredRegisters());
+ }
+
+ @Test
+ public void testReferenceWidth() {
+ DexItemFactory dexItemFactory = new DexItemFactory();
+ ClassTypeElement referenceType =
+ ClassTypeElement.create(
+ dexItemFactory.objectType, Nullability.maybeNull(), ImmutableSet.of());
+ assertFalse(referenceType.isSinglePrimitive());
+ assertFalse(referenceType.isWidePrimitive());
+ assertEquals(1, referenceType.requiredRegisters());
+ }
+
+ @Test
+ public void testShortWidth() {
+ assertTrue(TypeElement.getShort().isSinglePrimitive());
+ assertFalse(TypeElement.getShort().isWidePrimitive());
+ assertEquals(1, TypeElement.getShort().requiredRegisters());
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/analysis/type/TypeLatticeElementWidthTest.java b/src/test/java/com/android/tools/r8/ir/analysis/type/TypeLatticeElementWidthTest.java
deleted file mode 100644
index f2a20a6..0000000
--- a/src/test/java/com/android/tools/r8/ir/analysis/type/TypeLatticeElementWidthTest.java
+++ /dev/null
@@ -1,93 +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 com.android.tools.r8.ir.analysis.type;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import com.android.tools.r8.TestBase;
-import com.android.tools.r8.graph.DexItemFactory;
-import com.google.common.collect.ImmutableSet;
-import org.junit.Test;
-
-public class TypeLatticeElementWidthTest extends TestBase {
-
- @Test
- public void testArrayWidth() {
- ArrayTypeLatticeElement arrayType =
- ArrayTypeLatticeElement.create(TypeLatticeElement.getInt(), Nullability.maybeNull());
- assertFalse(arrayType.isSinglePrimitive());
- assertFalse(arrayType.isWidePrimitive());
- assertEquals(1, arrayType.requiredRegisters());
- }
-
- @Test
- public void testBooleanWidth() {
- assertTrue(TypeLatticeElement.getBoolean().isSinglePrimitive());
- assertFalse(TypeLatticeElement.getBoolean().isWidePrimitive());
- assertEquals(1, TypeLatticeElement.getBoolean().requiredRegisters());
- }
-
- @Test
- public void testByteWidth() {
- assertTrue(TypeLatticeElement.getByte().isSinglePrimitive());
- assertFalse(TypeLatticeElement.getByte().isWidePrimitive());
- assertEquals(1, TypeLatticeElement.getByte().requiredRegisters());
- }
-
- @Test
- public void testCharWidth() {
- assertTrue(TypeLatticeElement.getChar().isSinglePrimitive());
- assertFalse(TypeLatticeElement.getChar().isWidePrimitive());
- assertEquals(1, TypeLatticeElement.getChar().requiredRegisters());
- }
-
- @Test
- public void testDoubleWidth() {
- assertTrue(TypeLatticeElement.getDouble().isWidePrimitive());
- assertFalse(TypeLatticeElement.getDouble().isSinglePrimitive());
- assertEquals(2, TypeLatticeElement.getDouble().requiredRegisters());
- }
-
- @Test
- public void testFloatWidth() {
- assertTrue(TypeLatticeElement.getFloat().isSinglePrimitive());
- assertFalse(TypeLatticeElement.getFloat().isWidePrimitive());
- assertEquals(1, TypeLatticeElement.getFloat().requiredRegisters());
- }
-
- @Test
- public void testIntWidth() {
- assertTrue(TypeLatticeElement.getInt().isSinglePrimitive());
- assertFalse(TypeLatticeElement.getInt().isWidePrimitive());
- assertEquals(1, TypeLatticeElement.getInt().requiredRegisters());
- }
-
- @Test
- public void testLongWidth() {
- assertTrue(TypeLatticeElement.getLong().isWidePrimitive());
- assertFalse(TypeLatticeElement.getLong().isSinglePrimitive());
- assertEquals(2, TypeLatticeElement.getLong().requiredRegisters());
- }
-
- @Test
- public void testReferenceWidth() {
- DexItemFactory dexItemFactory = new DexItemFactory();
- ClassTypeLatticeElement referenceType =
- ClassTypeLatticeElement.create(
- dexItemFactory.objectType, Nullability.maybeNull(), ImmutableSet.of());
- assertFalse(referenceType.isSinglePrimitive());
- assertFalse(referenceType.isWidePrimitive());
- assertEquals(1, referenceType.requiredRegisters());
- }
-
- @Test
- public void testShortWidth() {
- assertTrue(TypeLatticeElement.getShort().isSinglePrimitive());
- assertFalse(TypeLatticeElement.getShort().isWidePrimitive());
- assertEquals(1, TypeLatticeElement.getShort().requiredRegisters());
- }
-}
diff --git a/src/test/java/com/android/tools/r8/ir/analysis/type/TypeLatticeTest.java b/src/test/java/com/android/tools/r8/ir/analysis/type/TypeLatticeTest.java
index cac6ef5..5a8a80e 100644
--- a/src/test/java/com/android/tools/r8/ir/analysis/type/TypeLatticeTest.java
+++ b/src/test/java/com/android/tools/r8/ir/analysis/type/TypeLatticeTest.java
@@ -3,10 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.analysis.type;
-import static com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement.computeLeastUpperBoundOfInterfaces;
-import static com.android.tools.r8.ir.analysis.type.TypeLatticeElement.fromDexType;
-import static com.android.tools.r8.ir.analysis.type.TypeLatticeElement.getBottom;
-import static com.android.tools.r8.ir.analysis.type.TypeLatticeElement.getTop;
+import static com.android.tools.r8.ir.analysis.type.ClassTypeElement.computeLeastUpperBoundOfInterfaces;
+import static com.android.tools.r8.ir.analysis.type.TypeElement.fromDexType;
+import static com.android.tools.r8.ir.analysis.type.TypeElement.getBottom;
+import static com.android.tools.r8.ir.analysis.type.TypeElement.getTop;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -63,48 +63,48 @@
appView = AppView.createForR8(new AppInfoWithSubtyping(application), options);
}
- private TopTypeLatticeElement top() {
+ private TopTypeElement top() {
return getTop();
}
- private BottomTypeLatticeElement bottom() {
+ private BottomTypeElement bottom() {
return getBottom();
}
- private SinglePrimitiveTypeLatticeElement single() {
- return TypeLatticeElement.getSingle();
+ private SinglePrimitiveTypeElement single() {
+ return TypeElement.getSingle();
}
- private WidePrimitiveTypeLatticeElement wide() {
- return TypeLatticeElement.getWide();
+ private WidePrimitiveTypeElement wide() {
+ return TypeElement.getWide();
}
- private TypeLatticeElement element(DexType type) {
+ private TypeElement element(DexType type) {
return element(type, Nullability.maybeNull());
}
- private TypeLatticeElement element(DexType type, Nullability nullability) {
- return TypeLatticeElement.fromDexType(type, nullability, appView);
+ private TypeElement element(DexType type, Nullability nullability) {
+ return TypeElement.fromDexType(type, nullability, appView);
}
- private ArrayTypeLatticeElement array(int nesting, DexType base) {
- return (ArrayTypeLatticeElement) element(factory.createArrayType(nesting, base));
+ private ArrayTypeElement array(int nesting, DexType base) {
+ return (ArrayTypeElement) element(factory.createArrayType(nesting, base));
}
- private TypeLatticeElement join(TypeLatticeElement... elements) {
+ private TypeElement join(TypeElement... elements) {
assertTrue(elements.length > 1);
- return TypeLatticeElement.join(Arrays.asList(elements), appView);
+ return TypeElement.join(Arrays.asList(elements), appView);
}
- private boolean strictlyLessThan(TypeLatticeElement l1, TypeLatticeElement l2) {
+ private boolean strictlyLessThan(TypeElement l1, TypeElement l2) {
return l1.strictlyLessThan(l2, appView);
}
- private boolean lessThanOrEqual(TypeLatticeElement l1, TypeLatticeElement l2) {
+ private boolean lessThanOrEqual(TypeElement l1, TypeElement l2) {
return l1.lessThanOrEqual(l2, appView);
}
- private boolean lessThanOrEqualUpToNullability(TypeLatticeElement l1, TypeLatticeElement l2) {
+ private boolean lessThanOrEqualUpToNullability(TypeElement l1, TypeElement l2) {
return l1.lessThanOrEqualUpToNullability(l2, appView);
}
@@ -510,7 +510,7 @@
assertTrue(strictlyLessThan(
array(2, factory.objectType),
array(1, factory.objectType)));
- assertTrue(strictlyLessThan(TypeLatticeElement.getNull(), array(1, factory.classType)));
+ assertTrue(strictlyLessThan(TypeElement.getNull(), array(1, factory.classType)));
}
@Test
@@ -535,26 +535,24 @@
public void testSelfOrderWithoutSubtypingInfo() {
DexType type = factory.createType("Lmy/Type;");
appView.withSubtyping().appInfo().registerNewTypeForTesting(type, factory.objectType);
- TypeLatticeElement nonNullType = fromDexType(type, Nullability.definitelyNotNull(), appView);
- ReferenceTypeLatticeElement nullableType =
- nonNullType.asReferenceTypeLatticeElement().getOrCreateVariant(Nullability.maybeNull());
+ TypeElement nonNullType = fromDexType(type, Nullability.definitelyNotNull(), appView);
+ ReferenceTypeElement nullableType =
+ nonNullType.asReferenceType().getOrCreateVariant(Nullability.maybeNull());
assertTrue(strictlyLessThan(nonNullType, nullableType));
assertTrue(lessThanOrEqual(nonNullType, nullableType));
assertFalse(lessThanOrEqual(nullableType, nonNullType));
// Check that the class-type null is also more specific than nullableType.
- assertTrue(strictlyLessThan(TypeLatticeElement.getNull(), nullableType));
+ assertTrue(strictlyLessThan(TypeElement.getNull(), nullableType));
assertTrue(
strictlyLessThan(
- TypeLatticeElement.getNull(),
- nullableType.getOrCreateVariant(Nullability.definitelyNull())));
+ TypeElement.getNull(), nullableType.getOrCreateVariant(Nullability.definitelyNull())));
}
@Test
public void testNotNullOfNullGivesBottom() {
assertEquals(
- Nullability.bottom(),
- ReferenceTypeLatticeElement.getNull().asMeetWithNotNull().nullability());
+ Nullability.bottom(), ReferenceTypeElement.getNull().asMeetWithNotNull().nullability());
}
@Test
diff --git a/src/test/java/com/android/tools/r8/ir/analysis/type/UnconstrainedPrimitiveTypeTest.java b/src/test/java/com/android/tools/r8/ir/analysis/type/UnconstrainedPrimitiveTypeTest.java
index d08b323..f6ad83a 100644
--- a/src/test/java/com/android/tools/r8/ir/analysis/type/UnconstrainedPrimitiveTypeTest.java
+++ b/src/test/java/com/android/tools/r8/ir/analysis/type/UnconstrainedPrimitiveTypeTest.java
@@ -86,41 +86,37 @@
@Test
public void testUnconstrainedSingleWithNoUsers() throws Exception {
- buildAndCheckIR(
- "unconstrainedSingleWithNoUsersTest", testInspector(TypeLatticeElement.getInt(), 1));
+ buildAndCheckIR("unconstrainedSingleWithNoUsersTest", testInspector(TypeElement.getInt(), 1));
}
@Test
public void testUnconstrainedSingleWithIfUser() throws Exception {
- buildAndCheckIR(
- "unconstrainedSingleWithIfUserTest", testInspector(TypeLatticeElement.getInt(), 2));
+ buildAndCheckIR("unconstrainedSingleWithIfUserTest", testInspector(TypeElement.getInt(), 2));
}
@Test
public void testUnconstrainedSingleWithIfZeroUser() throws Exception {
buildAndCheckIR(
- "unconstrainedSingleWithIfZeroUserTest", testInspector(IntTypeLatticeElement.getInt(), 1));
+ "unconstrainedSingleWithIfZeroUserTest", testInspector(IntTypeElement.getInt(), 1));
}
@Test
public void testUnconstrainedWideWithNoUsers() throws Exception {
- buildAndCheckIR(
- "unconstrainedWideWithNoUsersTest", testInspector(TypeLatticeElement.getLong(), 1));
+ buildAndCheckIR("unconstrainedWideWithNoUsersTest", testInspector(TypeElement.getLong(), 1));
}
@Test
public void testUnconstrainedWideWithIfUser() throws Exception {
- buildAndCheckIR(
- "unconstrainedWideWithIfUserTest", testInspector(TypeLatticeElement.getLong(), 2));
+ buildAndCheckIR("unconstrainedWideWithIfUserTest", testInspector(TypeElement.getLong(), 2));
}
private static Consumer<IRCode> testInspector(
- TypeLatticeElement expectedType, int expectedNumberOfConstNumberInstructions) {
+ TypeElement expectedType, int expectedNumberOfConstNumberInstructions) {
return code -> {
for (Instruction instruction : code.instructions()) {
if (instruction.isConstNumber()) {
ConstNumber constNumberInstruction = instruction.asConstNumber();
- assertEquals(expectedType, constNumberInstruction.outValue().getTypeLattice());
+ assertEquals(expectedType, constNumberInstruction.outValue().getType());
}
}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/ConstantRemovalTest.java b/src/test/java/com/android/tools/r8/ir/optimize/ConstantRemovalTest.java
index 607839e..fa6597f 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/ConstantRemovalTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/ConstantRemovalTest.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexApplication;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.ConstNumber;
import com.android.tools.r8.ir.code.Div;
@@ -76,14 +76,14 @@
IRMetadata metadata = IRMetadata.unknown();
Position position = Position.testingPosition();
- Value v3 = new Value(3, TypeLatticeElement.getLong(), null);
+ Value v3 = new Value(3, TypeElement.getLong(), null);
v3.setNeedsRegister(true);
new MockLiveIntervals(v3);
Instruction instruction = new ConstNumber(v3, 0);
instruction.setPosition(position);
block.add(instruction, metadata);
- Value v0 = new Value(0, TypeLatticeElement.getLong(), null);
+ Value v0 = new Value(0, TypeElement.getLong(), null);
v0.setNeedsRegister(true);
new MockLiveIntervals(v0);
instruction = new ConstNumber(v0, 10);
@@ -94,14 +94,14 @@
instruction.setPosition(position);
block.add(instruction, metadata);
- Value v2 = new Value(2, TypeLatticeElement.getInt(), null);
+ Value v2 = new Value(2, TypeElement.getInt(), null);
v2.setNeedsRegister(true);
new MockLiveIntervals(v2);
instruction = new ConstNumber(v2, 10);
instruction.setPosition(position);
block.add(instruction, metadata);
- Value v1 = new Value(1, TypeLatticeElement.getInt(), null);
+ Value v1 = new Value(1, TypeElement.getInt(), null);
v1.setNeedsRegister(true);
new MockLiveIntervals(v1);
instruction = new Move(v1 ,v2);
@@ -112,7 +112,7 @@
instruction.setPosition(position);
block.add(instruction, metadata);
- Value v0_2 = new Value(0, TypeLatticeElement.getLong(), null);
+ Value v0_2 = new Value(0, TypeElement.getLong(), null);
v0_2.setNeedsRegister(true);
new MockLiveIntervals(v0_2);
instruction = new ConstNumber(v0_2, 10);
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/TrivialGotoEliminationTest.java b/src/test/java/com/android/tools/r8/ir/optimize/TrivialGotoEliminationTest.java
index 6104883..95557b6 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/TrivialGotoEliminationTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/TrivialGotoEliminationTest.java
@@ -10,7 +10,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.Argument;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.ConstNumber;
@@ -59,7 +59,7 @@
block2.setFilledForTesting();
BasicBlock block1 = new BasicBlock();
block1.setNumber(1);
- Value value = new Value(0, TypeLatticeElement.getInt(), null);
+ Value value = new Value(0, TypeElement.getInt(), null);
Instruction number = new ConstNumber(value, 0);
number.setPosition(position);
block1.add(number, metadata);
@@ -134,7 +134,7 @@
Value value =
new Value(
0,
- TypeLatticeElement.fromDexType(
+ TypeElement.fromDexType(
app.dexItemFactory.throwableType, Nullability.definitelyNotNull(), appView),
null);
instruction = new Argument(value, 0, false);
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamicupperboundtype/InvokeDirectNegativeTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamicupperboundtype/InvokeDirectNegativeTest.java
index 27db8be..349c613 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamicupperboundtype/InvokeDirectNegativeTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamicupperboundtype/InvokeDirectNegativeTest.java
@@ -13,7 +13,7 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.optimize.info.CallSiteOptimizationInfo;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -59,11 +59,10 @@
assert encodedMethod.method.name.toString().equals("test")
: "Unexpected revisit: " + encodedMethod.toSourceString();
CallSiteOptimizationInfo callSiteOptimizationInfo = encodedMethod.getCallSiteOptimizationInfo();
- TypeLatticeElement upperBoundType = callSiteOptimizationInfo.getDynamicUpperBoundType(1);
+ TypeElement upperBoundType = callSiteOptimizationInfo.getDynamicUpperBoundType(1);
assert upperBoundType.isDefinitelyNotNull();
assert upperBoundType.isClassType()
- && upperBoundType.asClassTypeLatticeElement()
- .getClassType().toSourceString().endsWith("$Base");
+ && upperBoundType.asClassType().getClassType().toSourceString().endsWith("$Base");
}
private void inspect(CodeInspector inspector) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamicupperboundtype/InvokeDirectPositiveTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamicupperboundtype/InvokeDirectPositiveTest.java
index 67bb7db..9119e88 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamicupperboundtype/InvokeDirectPositiveTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamicupperboundtype/InvokeDirectPositiveTest.java
@@ -14,7 +14,7 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.optimize.info.CallSiteOptimizationInfo;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -62,7 +62,7 @@
assert methodName.equals("<init>") || methodName.equals("test")
: "Unexpected revisit: " + encodedMethod.toSourceString();
CallSiteOptimizationInfo callSiteOptimizationInfo = encodedMethod.getCallSiteOptimizationInfo();
- TypeLatticeElement upperBoundType;
+ TypeElement upperBoundType;
if (methodName.equals("test")) {
upperBoundType = callSiteOptimizationInfo.getDynamicUpperBoundType(1);
} else {
@@ -73,8 +73,7 @@
}
assert upperBoundType.isDefinitelyNotNull();
assert upperBoundType.isClassType()
- && upperBoundType.asClassTypeLatticeElement()
- .getClassType().toSourceString().endsWith("$Sub1");
+ && upperBoundType.asClassType().getClassType().toSourceString().endsWith("$Sub1");
}
private void inspect(CodeInspector inspector) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamicupperboundtype/InvokeInterfaceNegativeTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamicupperboundtype/InvokeInterfaceNegativeTest.java
index 1493d73..b341d62 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamicupperboundtype/InvokeInterfaceNegativeTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamicupperboundtype/InvokeInterfaceNegativeTest.java
@@ -14,7 +14,7 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.optimize.info.CallSiteOptimizationInfo;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -64,11 +64,10 @@
assert encodedMethod.method.name.toString().equals("m")
: "Unexpected revisit: " + encodedMethod.toSourceString();
CallSiteOptimizationInfo callSiteOptimizationInfo = encodedMethod.getCallSiteOptimizationInfo();
- TypeLatticeElement upperBoundType = callSiteOptimizationInfo.getDynamicUpperBoundType(1);
+ TypeElement upperBoundType = callSiteOptimizationInfo.getDynamicUpperBoundType(1);
assert upperBoundType.isDefinitelyNotNull();
assert upperBoundType.isClassType()
- && upperBoundType.asClassTypeLatticeElement()
- .getClassType().toSourceString().endsWith("$Base");
+ && upperBoundType.asClassType().getClassType().toSourceString().endsWith("$Base");
}
private void inspect(CodeInspector inspector) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamicupperboundtype/InvokeInterfacePositiveTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamicupperboundtype/InvokeInterfacePositiveTest.java
index 24cad5b..8cc1e12 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamicupperboundtype/InvokeInterfacePositiveTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamicupperboundtype/InvokeInterfacePositiveTest.java
@@ -14,7 +14,7 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.optimize.info.CallSiteOptimizationInfo;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -64,16 +64,14 @@
assert encodedMethod.method.name.toString().equals("m")
: "Unexpected revisit: " + encodedMethod.toSourceString();
CallSiteOptimizationInfo callSiteOptimizationInfo = encodedMethod.getCallSiteOptimizationInfo();
- TypeLatticeElement upperBoundType = callSiteOptimizationInfo.getDynamicUpperBoundType(1);
+ TypeElement upperBoundType = callSiteOptimizationInfo.getDynamicUpperBoundType(1);
assert upperBoundType.isDefinitelyNotNull();
if (encodedMethod.method.holder.toSourceString().endsWith("$A")) {
assert upperBoundType.isClassType()
- && upperBoundType.asClassTypeLatticeElement()
- .getClassType().toSourceString().endsWith("$Sub1");
+ && upperBoundType.asClassType().getClassType().toSourceString().endsWith("$Sub1");
} else {
assert upperBoundType.isClassType()
- && upperBoundType.asClassTypeLatticeElement()
- .getClassType().toSourceString().endsWith("$Base");
+ && upperBoundType.asClassType().getClassType().toSourceString().endsWith("$Base");
}
}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamicupperboundtype/InvokeStaticNegativeTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamicupperboundtype/InvokeStaticNegativeTest.java
index 6291f4d..d98e911 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamicupperboundtype/InvokeStaticNegativeTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamicupperboundtype/InvokeStaticNegativeTest.java
@@ -12,7 +12,7 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.optimize.info.CallSiteOptimizationInfo;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -56,11 +56,10 @@
assert encodedMethod.method.name.toString().equals("test")
: "Unexpected revisit: " + encodedMethod.toSourceString();
CallSiteOptimizationInfo callSiteOptimizationInfo = encodedMethod.getCallSiteOptimizationInfo();
- TypeLatticeElement upperBoundType = callSiteOptimizationInfo.getDynamicUpperBoundType(0);
+ TypeElement upperBoundType = callSiteOptimizationInfo.getDynamicUpperBoundType(0);
assert upperBoundType.isDefinitelyNotNull();
assert upperBoundType.isClassType()
- && upperBoundType.asClassTypeLatticeElement()
- .getClassType().toSourceString().endsWith("$Base");
+ && upperBoundType.asClassType().getClassType().toSourceString().endsWith("$Base");
}
private void inspect(CodeInspector inspector) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamicupperboundtype/InvokeStaticPositiveTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamicupperboundtype/InvokeStaticPositiveTest.java
index f31919a..d014d5a 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamicupperboundtype/InvokeStaticPositiveTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamicupperboundtype/InvokeStaticPositiveTest.java
@@ -13,7 +13,7 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.optimize.info.CallSiteOptimizationInfo;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -63,11 +63,10 @@
// TODO(b/139246447): should avoid visiting <init>, which is trivial, default init!
// For testing purpose, `Base` is not merged and kept. The system correctly caught that, when
// the default initializer is invoked, the receiver had a refined type, `Sub1`.
- TypeLatticeElement upperBoundType = callSiteOptimizationInfo.getDynamicUpperBoundType(0);
+ TypeElement upperBoundType = callSiteOptimizationInfo.getDynamicUpperBoundType(0);
assert upperBoundType.isDefinitelyNotNull();
assert upperBoundType.isClassType()
- && upperBoundType.asClassTypeLatticeElement()
- .getClassType().toSourceString().endsWith("$Sub1");
+ && upperBoundType.asClassType().getClassType().toSourceString().endsWith("$Sub1");
}
private void inspect(CodeInspector inspector) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamicupperboundtype/InvokeVirtualNegativeTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamicupperboundtype/InvokeVirtualNegativeTest.java
index cc0a69f..c2fffc1 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamicupperboundtype/InvokeVirtualNegativeTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamicupperboundtype/InvokeVirtualNegativeTest.java
@@ -14,7 +14,7 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.optimize.info.CallSiteOptimizationInfo;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -63,11 +63,10 @@
: "Unexpected revisit: " + encodedMethod.toSourceString();
CallSiteOptimizationInfo callSiteOptimizationInfo = encodedMethod.getCallSiteOptimizationInfo();
if (methodName.equals("m")) {
- TypeLatticeElement upperBoundType = callSiteOptimizationInfo.getDynamicUpperBoundType(1);
+ TypeElement upperBoundType = callSiteOptimizationInfo.getDynamicUpperBoundType(1);
assert upperBoundType.isDefinitelyNotNull();
assert upperBoundType.isClassType()
- && upperBoundType.asClassTypeLatticeElement()
- .getClassType().toSourceString().endsWith("$Base");
+ && upperBoundType.asClassType().getClassType().toSourceString().endsWith("$Base");
} else {
assert methodName.equals("test");
assert callSiteOptimizationInfo.getDynamicUpperBoundType(0).isDefinitelyNotNull();
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamicupperboundtype/InvokeVirtualPositiveTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamicupperboundtype/InvokeVirtualPositiveTest.java
index f49d16e..22a4faa 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamicupperboundtype/InvokeVirtualPositiveTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/dynamicupperboundtype/InvokeVirtualPositiveTest.java
@@ -14,7 +14,7 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.optimize.info.CallSiteOptimizationInfo;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -62,7 +62,7 @@
assert methodName.equals("<init>") || methodName.equals("m")
: "Unexpected revisit: " + encodedMethod.toSourceString();
CallSiteOptimizationInfo callSiteOptimizationInfo = encodedMethod.getCallSiteOptimizationInfo();
- TypeLatticeElement upperBoundType;
+ TypeElement upperBoundType;
if (methodName.equals("m")) {
upperBoundType = callSiteOptimizationInfo.getDynamicUpperBoundType(1);
} else {
@@ -73,8 +73,7 @@
}
assert upperBoundType.isDefinitelyNotNull();
assert upperBoundType.isClassType()
- && upperBoundType.asClassTypeLatticeElement()
- .getClassType().toSourceString().endsWith("$Sub1");
+ && upperBoundType.asClassType().getClassType().toSourceString().endsWith("$Sub1");
}
private void inspect(CodeInspector inspector) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeInterfaceNegativeTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeInterfaceNegativeTest.java
index 3fde0f1..e7c5597 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeInterfaceNegativeTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeInterfaceNegativeTest.java
@@ -14,7 +14,7 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.optimize.info.CallSiteOptimizationInfo;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -64,11 +64,10 @@
assert encodedMethod.method.name.toString().equals("m")
: "Unexpected revisit: " + encodedMethod.toSourceString();
CallSiteOptimizationInfo callSiteOptimizationInfo = encodedMethod.getCallSiteOptimizationInfo();
- TypeLatticeElement upperBoundType = callSiteOptimizationInfo.getDynamicUpperBoundType(1);
+ TypeElement upperBoundType = callSiteOptimizationInfo.getDynamicUpperBoundType(1);
assert upperBoundType.isNullable();
assert upperBoundType.isClassType()
- && upperBoundType.asClassTypeLatticeElement()
- .getClassType().toSourceString().endsWith("$A");
+ && upperBoundType.asClassType().getClassType().toSourceString().endsWith("$A");
}
private void inspect(CodeInspector inspector) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeVirtualNegativeTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeVirtualNegativeTest.java
index e36d2e9..ad7b3ae 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeVirtualNegativeTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeVirtualNegativeTest.java
@@ -14,7 +14,7 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.optimize.info.CallSiteOptimizationInfo;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -63,11 +63,10 @@
: "Unexpected revisit: " + encodedMethod.toSourceString();
CallSiteOptimizationInfo callSiteOptimizationInfo = encodedMethod.getCallSiteOptimizationInfo();
if (methodName.equals("m")) {
- TypeLatticeElement upperBoundType = callSiteOptimizationInfo.getDynamicUpperBoundType(1);
+ TypeElement upperBoundType = callSiteOptimizationInfo.getDynamicUpperBoundType(1);
assert upperBoundType.isNullable();
assert upperBoundType.isClassType()
- && upperBoundType.asClassTypeLatticeElement()
- .getClassType().equals(encodedMethod.method.holder);
+ && upperBoundType.asClassType().getClassType().equals(encodedMethod.method.holder);
} else {
assert methodName.equals("test");
assert callSiteOptimizationInfo.getDynamicUpperBoundType(0).isDefinitelyNotNull();
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeVirtualPositiveTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeVirtualPositiveTest.java
index e05b279..0551286 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeVirtualPositiveTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/nullability/InvokeVirtualPositiveTest.java
@@ -14,7 +14,7 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.optimize.info.CallSiteOptimizationInfo;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -61,10 +61,9 @@
assert encodedMethod.method.name.toString().equals("m")
: "Unexpected revisit: " + encodedMethod.toSourceString();
CallSiteOptimizationInfo callSiteOptimizationInfo = encodedMethod.getCallSiteOptimizationInfo();
- TypeLatticeElement upperBoundType = callSiteOptimizationInfo.getDynamicUpperBoundType(1);
+ TypeElement upperBoundType = callSiteOptimizationInfo.getDynamicUpperBoundType(1);
assert upperBoundType.isClassType()
- && upperBoundType.asClassTypeLatticeElement()
- .getClassType().toSourceString().endsWith("$A");
+ && upperBoundType.asClassType().getClassType().toSourceString().endsWith("$A");
if (encodedMethod.method.holder.toSourceString().endsWith("$A")) {
assert upperBoundType.isDefinitelyNotNull();
} else {
diff --git a/src/test/java/com/android/tools/r8/ir/regalloc/IdenticalAfterRegisterAllocationTest.java b/src/test/java/com/android/tools/r8/ir/regalloc/IdenticalAfterRegisterAllocationTest.java
index 00ee4e7..9e9b1c4 100644
--- a/src/test/java/com/android/tools/r8/ir/regalloc/IdenticalAfterRegisterAllocationTest.java
+++ b/src/test/java/com/android/tools/r8/ir/regalloc/IdenticalAfterRegisterAllocationTest.java
@@ -6,7 +6,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.Add;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.ConstNumber;
@@ -65,13 +65,13 @@
@Test
public void equalityOfConstantOperands() {
RegisterAllocator allocator = new MockRegisterAllocator();
- Value value0 = new Value(0, TypeLatticeElement.getInt(), null);
+ Value value0 = new Value(0, TypeElement.getInt(), null);
ConstNumber const0 = new ConstNumber(value0, 0);
- Value value1 = new Value(1, TypeLatticeElement.getInt(), null);
+ Value value1 = new Value(1, TypeElement.getInt(), null);
ConstNumber const1 = new ConstNumber(value1, 1);
- Value value2 = new Value(2, TypeLatticeElement.getInt(), null);
+ Value value2 = new Value(2, TypeElement.getInt(), null);
ConstNumber const2 = new ConstNumber(value2, 2);
- Value value3 = new Value(2, TypeLatticeElement.getInt(), null);
+ Value value3 = new Value(2, TypeElement.getInt(), null);
Add add0 = new Add(NumericType.INT, value3, value0, value1);
add0.setPosition(Position.none());
Add add1 = new Add(NumericType.INT, value3, value0, value2);
diff --git a/src/test/java/com/android/tools/r8/ir/regalloc/RegisterMoveSchedulerTest.java b/src/test/java/com/android/tools/r8/ir/regalloc/RegisterMoveSchedulerTest.java
index 911479e..e570b8c 100644
--- a/src/test/java/com/android/tools/r8/ir/regalloc/RegisterMoveSchedulerTest.java
+++ b/src/test/java/com/android/tools/r8/ir/regalloc/RegisterMoveSchedulerTest.java
@@ -13,7 +13,7 @@
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
@@ -157,8 +157,8 @@
CollectMovesIterator moves = new CollectMovesIterator();
int temp = 42;
RegisterMoveScheduler scheduler = new RegisterMoveScheduler(moves, temp);
- scheduler.addMove(new RegisterMove(0, 1, TypeLatticeElement.getInt()));
- scheduler.addMove(new RegisterMove(1, 0, TypeLatticeElement.getInt()));
+ scheduler.addMove(new RegisterMove(0, 1, TypeElement.getInt()));
+ scheduler.addMove(new RegisterMove(1, 0, TypeElement.getInt()));
scheduler.schedule();
assertEquals(3, moves.size());
Move tempMove = moves.get(0);
@@ -182,8 +182,8 @@
CollectMovesIterator moves = new CollectMovesIterator();
int temp = 42;
RegisterMoveScheduler scheduler = new RegisterMoveScheduler(moves, temp);
- scheduler.addMove(new RegisterMove(0, 2, TypeLatticeElement.getLong()));
- scheduler.addMove(new RegisterMove(2, 0, TypeLatticeElement.getLong()));
+ scheduler.addMove(new RegisterMove(0, 2, TypeElement.getLong()));
+ scheduler.addMove(new RegisterMove(2, 0, TypeElement.getLong()));
scheduler.schedule();
assertEquals(3, moves.size());
Move tempMove = moves.get(0);
@@ -207,8 +207,8 @@
CollectMovesIterator moves = new CollectMovesIterator();
int temp = 42;
RegisterMoveScheduler scheduler = new RegisterMoveScheduler(moves, temp);
- scheduler.addMove(new RegisterMove(1, 0, TypeLatticeElement.getLong()));
- scheduler.addMove(new RegisterMove(0, 1, TypeLatticeElement.getInt()));
+ scheduler.addMove(new RegisterMove(1, 0, TypeElement.getLong()));
+ scheduler.addMove(new RegisterMove(0, 1, TypeElement.getInt()));
scheduler.schedule();
assertEquals(3, moves.size());
Move tempMove = moves.get(0).asMove();
@@ -232,8 +232,8 @@
CollectMovesIterator moves = new CollectMovesIterator();
int temp = 42;
RegisterMoveScheduler scheduler = new RegisterMoveScheduler(moves, temp);
- scheduler.addMove(new RegisterMove(0, 1, TypeLatticeElement.getInt()));
- scheduler.addMove(new RegisterMove(1, 0, TypeLatticeElement.getLong()));
+ scheduler.addMove(new RegisterMove(0, 1, TypeElement.getInt()));
+ scheduler.addMove(new RegisterMove(1, 0, TypeElement.getLong()));
scheduler.schedule();
assertEquals(3, moves.size());
Move tempMove = moves.get(0).asMove();
@@ -257,8 +257,8 @@
CollectMovesIterator moves = new CollectMovesIterator();
int temp = 42;
RegisterMoveScheduler scheduler = new RegisterMoveScheduler(moves, temp);
- scheduler.addMove(new RegisterMove(0, 1, TypeLatticeElement.getLong()));
- scheduler.addMove(new RegisterMove(2, 3, TypeLatticeElement.getLong()));
+ scheduler.addMove(new RegisterMove(0, 1, TypeElement.getLong()));
+ scheduler.addMove(new RegisterMove(2, 3, TypeElement.getLong()));
scheduler.schedule();
assertEquals(2, moves.size());
Move firstMove = moves.get(0).asMove();
@@ -276,8 +276,8 @@
CollectMovesIterator moves = new CollectMovesIterator();
int temp = 42;
RegisterMoveScheduler scheduler = new RegisterMoveScheduler(moves, temp);
- scheduler.addMove(new RegisterMove(2, 1, TypeLatticeElement.getLong()));
- scheduler.addMove(new RegisterMove(0, 3, TypeLatticeElement.getLong()));
+ scheduler.addMove(new RegisterMove(2, 1, TypeElement.getLong()));
+ scheduler.addMove(new RegisterMove(0, 3, TypeElement.getLong()));
scheduler.schedule();
assertEquals(3, moves.size());
Move firstMove = moves.get(0).asMove();
@@ -299,9 +299,9 @@
CollectMovesIterator moves = new CollectMovesIterator();
int temp = 42;
RegisterMoveScheduler scheduler = new RegisterMoveScheduler(moves, temp);
- scheduler.addMove(new RegisterMove(2, 0, TypeLatticeElement.getLong()));
- scheduler.addMove(new RegisterMove(0, 2, TypeLatticeElement.getInt()));
- scheduler.addMove(new RegisterMove(1, 3, TypeLatticeElement.getInt()));
+ scheduler.addMove(new RegisterMove(2, 0, TypeElement.getLong()));
+ scheduler.addMove(new RegisterMove(0, 2, TypeElement.getInt()));
+ scheduler.addMove(new RegisterMove(1, 3, TypeElement.getInt()));
scheduler.schedule();
assertEquals(4, moves.size());
Move firstMove = moves.get(0).asMove();
@@ -323,8 +323,8 @@
CollectMovesIterator moves = new CollectMovesIterator();
int temp = 42;
RegisterMoveScheduler scheduler = new RegisterMoveScheduler(moves, temp);
- scheduler.addMove(new RegisterMove(0, 2, TypeLatticeElement.getLong()));
- scheduler.addMove(new RegisterMove(3, 0, TypeLatticeElement.getInt()));
+ scheduler.addMove(new RegisterMove(0, 2, TypeElement.getLong()));
+ scheduler.addMove(new RegisterMove(3, 0, TypeElement.getInt()));
scheduler.schedule();
assertEquals(3, moves.size());
Move firstMove = moves.get(0).asMove();
@@ -346,10 +346,10 @@
CollectMovesIterator moves = new CollectMovesIterator();
int temp = 42;
RegisterMoveScheduler scheduler = new RegisterMoveScheduler(moves, temp);
- scheduler.addMove(new RegisterMove(14, 11, TypeLatticeElement.getLong()));
- scheduler.addMove(new RegisterMove(16, 13, TypeLatticeElement.getLong()));
- scheduler.addMove(new RegisterMove(10, 17, TypeLatticeElement.getLong()));
- scheduler.addMove(new RegisterMove(12, 19, TypeLatticeElement.getLong()));
+ scheduler.addMove(new RegisterMove(14, 11, TypeElement.getLong()));
+ scheduler.addMove(new RegisterMove(16, 13, TypeElement.getLong()));
+ scheduler.addMove(new RegisterMove(10, 17, TypeElement.getLong()));
+ scheduler.addMove(new RegisterMove(12, 19, TypeElement.getLong()));
scheduler.schedule();
// In order to resolve these moves, we need to use two temporary register pairs.
assertEquals(6, moves.size());
@@ -365,16 +365,15 @@
InternalOptions options = new InternalOptions();
AppView<AppInfo> appInfo =
AppView.createForD8(new AppInfo(DexApplication.builder(options, null).build()), options);
- TypeLatticeElement objectType =
- TypeLatticeElement.fromDexType(
- options.itemFactory.objectType, Nullability.maybeNull(), appInfo);
+ TypeElement objectType =
+ TypeElement.fromDexType(options.itemFactory.objectType, Nullability.maybeNull(), appInfo);
CollectMovesIterator moves = new CollectMovesIterator();
int temp = 42;
RegisterMoveScheduler scheduler = new RegisterMoveScheduler(moves, temp);
- scheduler.addMove(new RegisterMove(26, 22, TypeLatticeElement.getInt()));
- scheduler.addMove(new RegisterMove(29, 24, TypeLatticeElement.getLong()));
+ scheduler.addMove(new RegisterMove(26, 22, TypeElement.getInt()));
+ scheduler.addMove(new RegisterMove(29, 24, TypeElement.getLong()));
scheduler.addMove(new RegisterMove(28, 26, objectType));
- scheduler.addMove(new RegisterMove(23, 28, TypeLatticeElement.getLong()));
+ scheduler.addMove(new RegisterMove(23, 28, TypeElement.getLong()));
scheduler.schedule();
// For this example we need recursive unblocking.
assertEquals(6, moves.size());
diff --git a/src/test/java/com/android/tools/r8/ir/regalloc/Regress68656641.java b/src/test/java/com/android/tools/r8/ir/regalloc/Regress68656641.java
index 4700a44..2c1d228 100644
--- a/src/test/java/com/android/tools/r8/ir/regalloc/Regress68656641.java
+++ b/src/test/java/com/android/tools/r8/ir/regalloc/Regress68656641.java
@@ -6,7 +6,7 @@
import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexApplication;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.smali.SmaliBuilder;
@@ -62,20 +62,18 @@
MyRegisterAllocator allocator = new MyRegisterAllocator(appView, code);
// Setup live an inactive live interval with ranges [0, 10[ and [20, 30[ with only
// uses in the first interval and which is linked to another interval.
- LiveIntervals inactiveIntervals =
- new LiveIntervals(new Value(0, TypeLatticeElement.getInt(), null));
+ LiveIntervals inactiveIntervals = new LiveIntervals(new Value(0, TypeElement.getInt(), null));
inactiveIntervals.addRange(new LiveRange(0, 10));
inactiveIntervals.addUse(new LiveIntervalsUse(0, 10));
inactiveIntervals.addUse(new LiveIntervalsUse(4, 10));
inactiveIntervals.addRange(new LiveRange(20, 30));
inactiveIntervals.setRegister(0);
- LiveIntervals linked = new LiveIntervals(new Value(1, TypeLatticeElement.getInt(), null));
+ LiveIntervals linked = new LiveIntervals(new Value(1, TypeElement.getInt(), null));
linked.setRegister(1);
inactiveIntervals.link(linked);
allocator.addInactiveIntervals(inactiveIntervals);
// Setup an unhandled interval that overlaps the inactive interval.
- LiveIntervals unhandledIntervals =
- new LiveIntervals(new Value(2, TypeLatticeElement.getInt(), null));
+ LiveIntervals unhandledIntervals = new LiveIntervals(new Value(2, TypeElement.getInt(), null));
unhandledIntervals.addRange(new LiveRange(12, 24));
// Split the overlapping inactive intervals and check that after the split, the second
// part of the inactive interval is unhandled and will therefore get a new register
diff --git a/src/test/java/com/android/tools/r8/jsr45/JSR45Tests.java b/src/test/java/com/android/tools/r8/jsr45/JSR45Tests.java
index a6fd390..08a4ae9 100644
--- a/src/test/java/com/android/tools/r8/jsr45/JSR45Tests.java
+++ b/src/test/java/com/android/tools/r8/jsr45/JSR45Tests.java
@@ -10,7 +10,6 @@
import com.android.tools.r8.R8Command;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.graph.DexAnnotationElement;
-import com.android.tools.r8.graph.DexValue.DexValueString;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.AndroidAppConsumers;
@@ -30,7 +29,6 @@
import org.junit.rules.TemporaryFolder;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.Opcodes;
public class JSR45Tests {
@@ -158,10 +156,10 @@
Assert.assertNotNull(annotationElement);
Assert.assertTrue(annotationElement.length == 1);
Assert.assertEquals("value", annotationElement[0].name.toString());
- Assert.assertTrue(annotationElement[0].value instanceof DexValueString);
+ Assert.assertTrue(annotationElement[0].value.isDexValueString());
Assert.assertEquals(
sourceDebugExtensionReader.debugSourceExtension,
- ((DexValueString) annotationElement[0].value).value.toSourceString());
+ annotationElement[0].value.asDexValueString().value.toSourceString());
}
private String getGeneratedProguardMap() throws IOException {
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInTypeAliasTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInTypeAliasTest.java
index 094362c..734ce50 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInTypeAliasTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInTypeAliasTest.java
@@ -33,7 +33,24 @@
@RunWith(Parameterized.class)
public class MetadataRewriteInTypeAliasTest extends KotlinMetadataTestBase {
private static final String EXPECTED =
- StringUtils.lines("Impl::foo", "Program::foo", "true", "42");
+ StringUtils.lines(
+ "Impl::foo",
+ "Program::foo",
+ "true",
+ "42",
+ "42",
+ "42",
+ "42",
+ "42",
+ "42",
+ "42",
+ "true",
+ "42",
+ "1",
+ "42",
+ "42",
+ "1",
+ "Hello World!");
private final TestParameters parameters;
@@ -57,7 +74,9 @@
for (KotlinTargetVersion targetVersion : KotlinTargetVersion.values()) {
Path typeAliasLibJar =
kotlinc(KOTLINC, targetVersion)
- .addSourceFiles(getKotlinFileInTest(typeAliasLibFolder, "lib"))
+ .addSourceFiles(
+ getKotlinFileInTest(typeAliasLibFolder, "lib"),
+ getKotlinFileInTest(typeAliasLibFolder, "lib_ext"))
.compile();
typeAliasLibJarMap.put(targetVersion, typeAliasLibJar);
}
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInTypeArgumentsTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInTypeArgumentsTest.java
new file mode 100644
index 0000000..07fbdd9
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInTypeArgumentsTest.java
@@ -0,0 +1,99 @@
+// 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.kotlin.metadata;
+
+import static com.android.tools.r8.KotlinCompilerTool.KOTLINC;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertNotEquals;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.KotlinTargetVersion;
+import com.android.tools.r8.ToolHelper.ProcessResult;
+import com.android.tools.r8.utils.StringUtils;
+import java.nio.file.Path;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class MetadataRewriteInTypeArgumentsTest extends KotlinMetadataTestBase {
+ private static final String EXPECTED =
+ StringUtils.lines("42", "1", "42", "42", "1", "42", "42", "42", "1", "42");
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0} target: {1}")
+ public static Collection<Object[]> data() {
+ return buildParameters(
+ getTestParameters().withCfRuntimes().build(), KotlinTargetVersion.values());
+ }
+
+ public MetadataRewriteInTypeArgumentsTest(
+ TestParameters parameters, KotlinTargetVersion targetVersion) {
+ super(targetVersion);
+ this.parameters = parameters;
+ }
+
+ private static final Map<KotlinTargetVersion, Path> jarMap = new HashMap<>();
+
+ @BeforeClass
+ public static void createLibJar() throws Exception {
+ String typeAliasLibFolder = PKG_PREFIX + "/typeargument_lib";
+ for (KotlinTargetVersion targetVersion : KotlinTargetVersion.values()) {
+ Path typeAliasLibJar =
+ kotlinc(KOTLINC, targetVersion)
+ .addSourceFiles(getKotlinFileInTest(typeAliasLibFolder, "lib"))
+ .compile();
+ jarMap.put(targetVersion, typeAliasLibJar);
+ }
+ }
+
+ @Test
+ public void smokeTest() throws Exception {
+ Path libJar = jarMap.get(targetVersion);
+
+ Path output =
+ kotlinc(parameters.getRuntime().asCf(), KOTLINC, targetVersion)
+ .addClasspathFiles(libJar)
+ .addSourceFiles(getKotlinFileInTest(PKG_PREFIX + "/typeargument_app", "main"))
+ .setOutputPath(temp.newFolder().toPath())
+ .compile();
+
+ testForJvm()
+ .addRunClasspathFiles(ToolHelper.getKotlinStdlibJar(), libJar)
+ .addClasspath(output)
+ .run(parameters.getRuntime(), PKG + ".typeargument_app.MainKt")
+ .assertSuccessWithOutput(EXPECTED);
+ }
+
+ @Test
+ public void testMetadataInTypeAlias_renamed() throws Exception {
+ Path libJar =
+ testForR8(parameters.getBackend())
+ .addProgramFiles(jarMap.get(targetVersion))
+ .addKeepAllClassesRule()
+ .compile()
+ // TODO(b/151925520): Add inspections when program compiles
+ .writeToZip();
+
+ ProcessResult kotlinTestCompileResult =
+ kotlinc(parameters.getRuntime().asCf(), KOTLINC, targetVersion)
+ .addClasspathFiles(libJar)
+ .addSourceFiles(getKotlinFileInTest(PKG_PREFIX + "/typeargument_app", "main"))
+ .setOutputPath(temp.newFolder().toPath())
+ // TODO(b/151925520): update to just .compile() once fixed.
+ .compileRaw();
+ // TODO(b/151925520): should be able to compile!
+ assertNotEquals(0, kotlinTestCompileResult.exitCode);
+ assertThat(
+ kotlinTestCompileResult.stderr,
+ containsString("no type arguments expected for constructor Invariant()"));
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/typealias_app/main.kt b/src/test/java/com/android/tools/r8/kotlin/metadata/typealias_app/main.kt
index f0ddbf7..396c2e4 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/typealias_app/main.kt
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/typealias_app/main.kt
@@ -4,8 +4,29 @@
package com.android.tools.r8.kotlin.metadata.typealias_app
import com.android.tools.r8.kotlin.metadata.typealias_lib.API
+import com.android.tools.r8.kotlin.metadata.typealias_lib.AlphaNaming
+import com.android.tools.r8.kotlin.metadata.typealias_lib.Arr
+import com.android.tools.r8.kotlin.metadata.typealias_lib.Arr2D
+import com.android.tools.r8.kotlin.metadata.typealias_lib.Arr2DTester
+import com.android.tools.r8.kotlin.metadata.typealias_lib.CWithConstructor
+import com.android.tools.r8.kotlin.metadata.typealias_lib.CWithConstructorTester
+import com.android.tools.r8.kotlin.metadata.typealias_lib.ClassWithCompanionC
+import com.android.tools.r8.kotlin.metadata.typealias_lib.FunctionTester
import com.android.tools.r8.kotlin.metadata.typealias_lib.Impl
+import com.android.tools.r8.kotlin.metadata.typealias_lib.InterfaceTester
+import com.android.tools.r8.kotlin.metadata.typealias_lib.MyAdvancedMap
+import com.android.tools.r8.kotlin.metadata.typealias_lib.MyI
+import com.android.tools.r8.kotlin.metadata.typealias_lib.MyMapToSetOfInt
+import com.android.tools.r8.kotlin.metadata.typealias_lib.OuterNested
+import com.android.tools.r8.kotlin.metadata.typealias_lib.OuterNestedInner
+import com.android.tools.r8.kotlin.metadata.typealias_lib.OuterTester
+import com.android.tools.r8.kotlin.metadata.typealias_lib.SimpleClassTester
+import com.android.tools.r8.kotlin.metadata.typealias_lib.StillCWithConstructor
+import com.android.tools.r8.kotlin.metadata.typealias_lib.UnderlyingTypeTest
+import com.android.tools.r8.kotlin.metadata.typealias_lib.UnusedTypeArgument
+import com.android.tools.r8.kotlin.metadata.typealias_lib.VerticalClassMergingTester
import com.android.tools.r8.kotlin.metadata.typealias_lib.seq
+import com.android.tools.r8.kotlin.metadata.typealias_lib.IntSet as IntSet1
class ProgramClass : Impl() {
override fun foo(): API {
@@ -15,6 +36,77 @@
}
}
+fun testUnusedArgument() {
+ val u = UnusedTypeArgument<Int>();
+}
+
+fun testSimpleClass() {
+ val simple = object : AlphaNaming() { }
+ println(SimpleClassTester.f(SimpleClassTester.g(simple)).y)
+}
+
+fun testArr2D() {
+ val arr1d : Arr<Int> = Arr(42);
+ val arr2d : Arr2D<Int> = Arr2D(arr1d);
+ println(Arr2DTester.f(Arr2DTester.g(arr2d)).x.x);
+}
+
+fun testInterface() {
+ val myInstance = object : MyI {
+ override fun f() {
+ println("42");
+ }
+ }
+ InterfaceTester.f(InterfaceTester.g(myInstance)).f()
+
+ val map : MyMapToSetOfInt<Int> = HashMap();
+ val set : IntSet1 = mutableSetOf(42);
+ map.put(1, set);
+ println(InterfaceTester.i(InterfaceTester.h(map))[1]?.iterator()?.next() ?: "");
+}
+
+fun testFunctionTypes() {
+ FunctionTester.f(FunctionTester.g({ i : Int, a : Any ->
+ println(i)
+ println(a)
+ }))(42, "42")
+ FunctionTester.h(FunctionTester.i({ b ->
+ println(b)
+ false
+ }))(true)
+}
+
+fun testNestedClasses() {
+ val nested = OuterNested(42);
+ val myInner : OuterNestedInner = nested.Inner(1)
+ println(OuterTester.g(nested).y)
+ println(OuterTester.f(myInner).x)
+}
+
+fun testCompanion() {
+ ClassWithCompanionC.foo;
+}
+
+fun testConstructor() {
+ println(CWithConstructorTester.f(CWithConstructorTester.g(CWithConstructor(42))).x);
+}
+
+fun testUnderlyingType() {
+ val cWithConstructor = StillCWithConstructor(42)
+ println(UnderlyingTypeTest.f(UnderlyingTypeTest.g(cWithConstructor)).x)
+ val advancedMap : MyAdvancedMap = HashMap();
+ val nested = OuterNested(42);
+ val myInner : OuterNestedInner = nested.Inner(1)
+ advancedMap.put(nested, myInner);
+ val sameMap = UnderlyingTypeTest.h(UnderlyingTypeTest.i(advancedMap))
+ println(sameMap.get(nested)?.x)
+}
+
+fun testVerticalClassMerging() {
+ val apiImpl = VerticalClassMergingTester.produce()
+ VerticalClassMergingTester.passThrough(apiImpl).foo()
+}
+
fun main() {
val instance = ProgramClass()
val l = seq(instance)
@@ -22,4 +114,14 @@
println(api == api.foo())
println(api.hey())
}
+ testUnusedArgument()
+ testSimpleClass()
+ testArr2D()
+ testInterface()
+ testFunctionTypes()
+ testNestedClasses()
+ testCompanion()
+ testConstructor()
+ testUnderlyingType();
+ testVerticalClassMerging();
}
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/typealias_lib/lib.kt b/src/test/java/com/android/tools/r8/kotlin/metadata/typealias_lib/lib.kt
index 82ba761..15771dd 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/typealias_lib/lib.kt
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/typealias_lib/lib.kt
@@ -3,12 +3,15 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.kotlin.metadata.typealias_lib
-// TypeAlias {
-// name: "Jude"
+// KmTypeAlias {
+// name: Jude
// underlyingType {
-// classifier: "kotlin/Long"
+// classifier: Class(name=kotlin/Long)
// }
-// }
+// expandedType {
+// classifier: Class(name=kotlin/Long)
+// }
+// },
typealias Jude = Long
interface Itf {
@@ -16,36 +19,42 @@
fun hey() : Jude
}
-// TypeAlias {
-// name: "API"
+// KmTypeAlias {
+// name: API
// underlyingType {
-// classifier: ".../Itf"
-// }
-// }
-typealias API = Itf
-// TypeAlias {
-// typeParameters { KmTypeParameter { name = "T" ... } }
-// name: "myAliasedList"
-// underlyingType {
-// classifier: "kotlin/Array"
-// }
-// expandedType == underlyingType
-// }
-typealias myAliasedArray<T> = Array<T>
-// TypeAlias {
-// underlyingType {
-// classifier: ".../myAliasedArray"
-// arguments {
-// KmTypeProjection { ... type = ".../API" }
-// }
+// classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Itf)
// }
// expandedType {
-// classifier: "kotlin/Array"
-// arguments {
-// KmTypeProjection { ... type = ".../Itf" }
-// }
+// classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Itf)
// }
-// }
+// },
+typealias API = Itf
+
+// KmTypeAlias {
+// name: myAliasedArray
+// typeParameters: T
+// underlyingType {
+// classifier: Class(name=kotlin/Array)
+// arguments: TypeParameter(id=0)
+// }
+// expandedType {
+// classifier: Class(name=kotlin/Array)
+// arguments: TypeParameter(id=0)
+// }
+// },
+typealias myAliasedArray<T> = Array<T>
+
+// KmTypeAlias {
+// name: APIs
+// underlyingType {
+// classifier: TypeAlias(name=com/android/tools/r8/kotlin/metadata/typealias_lib/myAliasedArray)
+// arguments: TypeAlias(name=com/android/tools/r8/kotlin/metadata/typealias_lib/API)
+// }
+// expandedType {
+// classifier: Class(name=kotlin/Array)
+// arguments: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Itf)
+// }
+// },
typealias APIs = myAliasedArray<API>
open class Impl : API {
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/typealias_lib/lib_ext.kt b/src/test/java/com/android/tools/r8/kotlin/metadata/typealias_lib/lib_ext.kt
new file mode 100644
index 0000000..ba63667
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/typealias_lib/lib_ext.kt
@@ -0,0 +1,415 @@
+// 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.kotlin.metadata.typealias_lib
+
+// Unused type aliases
+
+open class LibraryClass { }
+
+// KmTypeAlias {
+// name: Unused
+// underlyingType {
+// classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/LibraryClass)
+// }
+// expandedType {
+// classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/LibraryClass)
+// }
+// },
+typealias Unused = LibraryClass
+
+// Will give a warning, but is is not an error to have an unused argument.
+// KmTypeAlias {
+// name: UnusedTypeArgument
+// typeParameters: T
+// underlyingType {
+// classifier: TypeAlias(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Unused)
+// }
+// expandedType {
+// classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/LibraryClass)
+// }
+// },
+typealias UnusedTypeArgument<T> = Unused
+
+// Expansion to simple class
+
+open class SimpleClass {
+ val y : Int = 42;
+}
+
+// KmTypeAlias {
+// name: AlphaNaming
+// underlyingType {
+// classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/SimpleClass)
+// }
+// expandedType {
+// classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/SimpleClass)
+// }
+// },
+typealias AlphaNaming = SimpleClass
+
+class SimpleClassTester {
+
+ companion object {
+ fun f(a : SimpleClass) : AlphaNaming {
+ return a;
+ }
+
+ fun g(a : AlphaNaming) : SimpleClass {
+ return a;
+ }
+ }
+}
+
+// Vertical class merging
+
+interface Api {
+
+ fun foo();
+}
+
+class ApiImpl : Api {
+ override fun foo() {
+ println("Hello World!")
+ }
+}
+
+// KmTypeAlias {
+// name: ApiAlias
+// underlyingType {
+// classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Api)
+// }
+// expandedType {
+// classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Api)
+// }
+// },
+typealias ApiAlias = Api
+
+class VerticalClassMergingTester {
+
+ companion object {
+
+ fun produce(): ApiAlias {
+ return ApiImpl()
+ }
+
+ fun passThrough(a : ApiAlias) : ApiAlias {
+ return a;
+ }
+ }
+}
+
+// Multiple expansions
+
+class Arr<K>(val x : K)
+
+// KmTypeAlias {
+// name: Arr1D
+// typeParameters: K
+// underlyingType {
+// classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Arr)
+// arguments: TypeParameter(id=0)
+// }
+// expandedType {
+// classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Arr)
+// arguments: TypeParameter(id=0)
+// }
+// },
+typealias Arr1D<K> = Arr<K>
+
+// KmTypeAlias {
+// name: Arr2D
+// typeParameters: K
+// underlyingType {
+// classifier: TypeAlias(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Arr1D)
+// arguments: TypeAlias(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Arr1D)
+// }
+// expandedType {
+// classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Arr)
+// arguments: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Arr)
+// }
+// },
+typealias Arr2D<K> = Arr1D<Arr1D<K>>
+
+class Arr2DTester {
+
+ companion object {
+
+ fun <K> f(a : Arr1D<Arr1D<K>>) : Arr2D<K> {
+ return a;
+ }
+
+ fun <K> g(a : Arr2D<K>) : Arr1D<Arr1D<K>> {
+ return a;
+ }
+
+ }
+}
+
+// Expansion to interfaces
+
+interface I<T : Any> {
+ fun f()
+}
+
+// KmTypeAlias {
+// name: MyI
+// underlyingType {
+// classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/I)
+// arguments: Class(name=kotlin/Int)
+// }
+// expandedType {
+// classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/I)
+// arguments: Class(name=kotlin/Int)
+// }
+// },
+typealias MyI = I<Int>
+
+// KmTypeAlias {
+// name: IntSet
+// underlyingType {
+// classifier: Class(name=kotlin/collections/Set)
+// arguments: Class(name=kotlin/Int)
+// }
+// expandedType {
+// classifier: Class(name=kotlin/collections/Set)
+// arguments: Class(name=kotlin/Int)
+// }
+// },
+typealias IntSet = Set<Int>
+
+// KmTypeAlias {
+// name: MyMapToSetOfInt
+// typeParameters: K
+// underlyingType {
+// classifier: Class(name=kotlin/collections/MutableMap)
+// arguments: TypeParameter(id=0),TypeAlias(name=com/android/tools/r8/kotlin/metadata/typealias_lib/IntSet)
+// }
+// expandedType {
+// classifier: Class(name=kotlin/collections/MutableMap)
+// arguments: TypeParameter(id=0),Class(name=kotlin/collections/Set)
+// }
+// },
+typealias MyMapToSetOfInt<K> = MutableMap<K, IntSet>
+
+class InterfaceTester {
+
+ companion object {
+
+ fun f(i : I<Int>) : MyI {
+ return i;
+ }
+
+ fun g(myI : MyI) : I<Int> {
+ return myI;
+ }
+
+ fun h(k : MyMapToSetOfInt<Int>) : MutableMap<Int, IntSet> {
+ return k;
+ }
+
+ fun i(myMap : MutableMap<Int, IntSet>) : MyMapToSetOfInt<Int> {
+ return myMap;
+ }
+ }
+}
+
+// Expansion to function types
+
+// KmTypeAlias {
+// name: MyHandler
+// underlyingType {
+// classifier: Class(name=kotlin/Function2)
+// arguments: Class(name=kotlin/Int),Class(name=kotlin/Any),Class(name=kotlin/Unit)
+// }
+// expandedType {
+// classifier: Class(name=kotlin/Function2)
+// arguments: Class(name=kotlin/Int),Class(name=kotlin/Any),Class(name=kotlin/Unit)
+// }
+// },
+typealias MyHandler = (Int, Any) -> Unit
+
+// KmTypeAlias {
+// name: MyGenericPredicate
+// typeParameters: T
+// underlyingType {
+// classifier: Class(name=kotlin/Function1)
+// arguments: TypeParameter(id=0),Class(name=kotlin/Boolean)
+// }
+// expandedType {
+// classifier: Class(name=kotlin/Function1)
+// arguments: TypeParameter(id=0),Class(name=kotlin/Boolean)
+// }
+// },
+typealias MyGenericPredicate<T> = (T) -> Boolean
+
+class FunctionTester {
+
+ companion object {
+
+ fun f(a : (Int, Any) -> Unit) : MyHandler {
+ return a;
+ }
+
+ fun g(a : MyHandler) : (Int, Any) -> Unit {
+ return a;
+ }
+
+ fun h(a : (Boolean) -> Boolean) : MyGenericPredicate<Boolean> {
+ return a;
+ }
+
+ fun i(a : MyGenericPredicate<Boolean>) : (Boolean) -> Boolean {
+ return a;
+ }
+ }
+}
+
+// Expansion to nested classes
+
+class Outer {
+ class Nested(val y : Int) {
+ inner class Inner(val x : Int) {
+
+ }
+ }
+}
+
+// KmTypeAlias {
+// name: OuterNested
+// underlyingType {
+// classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Outer.Nested)
+// }
+// expandedType {
+// classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Outer.Nested)
+// }
+// },
+typealias OuterNested = Outer.Nested
+
+// KmTypeAlias {
+// name: OuterNestedInner
+// underlyingType {
+// classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Outer.Nested.Inner)
+// }
+// expandedType {
+// classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Outer.Nested.Inner)
+// }
+// },
+typealias OuterNestedInner = Outer.Nested.Inner
+
+class OuterTester {
+
+ companion object {
+
+ fun f(a : Outer.Nested.Inner) : OuterNestedInner {
+ return a;
+ }
+
+ fun g(a : OuterNested) : Outer.Nested {
+ return a;
+ }
+
+ }
+}
+
+// Expansion to companion class
+
+class ClassWithCompanion {
+
+ companion object {
+ val foo: String
+ get() = "A.Companion::foo"
+ }
+}
+
+// KmTypeAlias {
+// name: ClassWithCompanionC
+// underlyingType {
+// classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/ClassWithCompanion.Companion)
+// }
+// expandedType {
+// classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/ClassWithCompanion.Companion)
+// }
+// },
+typealias ClassWithCompanionC = ClassWithCompanion.Companion
+
+// Expansion to constructor
+
+class C(val x : Int) {
+
+ private constructor() : this(0)
+}
+
+// KmTypeAlias {
+// name: CWithConstructor
+// underlyingType {
+// classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/C)
+// }
+// expandedType {
+// classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/C)
+// }
+// },
+typealias CWithConstructor = C
+
+class CWithConstructorTester {
+
+ companion object {
+
+ fun f(a : C) : CWithConstructor {
+ return a;
+ }
+
+ fun g(a : CWithConstructor) : C {
+ return a;
+ }
+ }
+}
+
+// Underlying type having type alias
+
+// KmTypeAlias {
+// name: StillCWithConstructor
+// underlyingType {
+// classifier: TypeAlias(name=com/android/tools/r8/kotlin/metadata/typealias_lib/CWithConstructor)
+// }
+// expandedType {
+// classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/C)
+// }
+// },
+typealias StillCWithConstructor = CWithConstructor
+
+// KmTypeAlias {
+// name: MyAdvancedMap
+// underlyingType {
+// classifier: Class(name=kotlin/collections/MutableMap)
+// arguments: TypeAlias(name=com/android/tools/r8/kotlin/metadata/typealias_lib/OuterNested),TypeAlias(name=com/android/tools/r8/kotlin/metadata/typealias_lib/OuterNestedInner)
+// }
+// expandedType {
+// classifier: Class(name=kotlin/collections/MutableMap)
+// arguments: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Outer.Nested),Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Outer.Nested.Inner)
+// }
+// },
+typealias MyAdvancedMap = MutableMap<OuterNested, OuterNestedInner>
+
+class UnderlyingTypeTest {
+
+ companion object {
+
+ fun f(a : StillCWithConstructor) : CWithConstructor {
+ return a;
+ }
+
+ fun g(a : C) : StillCWithConstructor {
+ return a;
+ }
+
+ fun h(a : MutableMap<OuterNested, OuterNestedInner>) : MyAdvancedMap {
+ return a;
+ }
+
+ fun i(a : MyAdvancedMap) : MutableMap<OuterNested, OuterNestedInner> {
+ return a;
+ }
+
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/typeargument_app/main.kt b/src/test/java/com/android/tools/r8/kotlin/metadata/typeargument_app/main.kt
new file mode 100644
index 0000000..7fc2b69
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/typeargument_app/main.kt
@@ -0,0 +1,53 @@
+// 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.kotlin.metadata.typeargument_app
+
+import com.android.tools.r8.kotlin.metadata.typeargument_lib.CoVariant
+import com.android.tools.r8.kotlin.metadata.typeargument_lib.ContraVariant
+import com.android.tools.r8.kotlin.metadata.typeargument_lib.Invariant
+import com.android.tools.r8.kotlin.metadata.typeargument_lib.SomeClass
+import com.android.tools.r8.kotlin.metadata.typeargument_lib.unBoxAndBox
+import com.android.tools.r8.kotlin.metadata.typeargument_lib.update
+
+class SomeSubClass(val x : Int) : SomeClass(), Comparable<SomeClass> {
+
+ override fun compareTo(other: SomeClass): Int {
+ if (other !is SomeSubClass) {
+ return -1;
+ }
+ return x.compareTo(other.x);
+ }
+}
+
+fun testInvariant() {
+ val subtype1 = SomeSubClass(42)
+ val subtype2 = SomeSubClass(1)
+ val inv = Invariant<SomeSubClass>()
+ println(inv.classGenerics(subtype1).x)
+ println(inv.funGenerics(subtype2).x)
+ println(inv.funGenericsWithUpperBound(subtype1).x)
+ println(inv.funGenericsWithUpperBounds(subtype1, subtype2).x)
+ println(inv.mixedGenerics(subtype2).x)
+}
+
+fun testCoVariant() {
+ println(CoVariant(42).classGenerics().t)
+}
+
+fun testContraVariant() {
+ ContraVariant<Number>().classGenerics(42)
+}
+
+fun testExtension() {
+ println(CoVariant(42).unBoxAndBox().t)
+ println(CoVariant(1).update(42).t)
+}
+
+fun main() {
+ testInvariant()
+ testCoVariant()
+ testContraVariant();
+ testExtension()
+}
\ No newline at end of file
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/typeargument_lib/lib.kt b/src/test/java/com/android/tools/r8/kotlin/metadata/typeargument_lib/lib.kt
new file mode 100644
index 0000000..7c8b6cb
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/typeargument_lib/lib.kt
@@ -0,0 +1,63 @@
+// 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.kotlin.metadata.typeargument_lib
+
+open class SomeClass
+
+class Invariant<T> {
+
+ fun classGenerics(t : T) : T {
+ return t
+ }
+
+ fun <R> funGenerics(r : R) : R {
+ return r
+ }
+
+ fun <R : SomeClass> funGenericsWithUpperBound(r : R) : R {
+ return r;
+ }
+
+ fun <R> funGenericsWithUpperBounds(r1 : R, r2 : R) : R
+ where R : SomeClass,
+ R : Comparable<SomeClass> {
+ return when {
+ r1 > r2 -> {
+ r1;
+ }
+ else -> {
+ r2;
+ }
+ }
+ }
+
+ fun <R : T> mixedGenerics(r : R) : T {
+ return r;
+ }
+}
+
+class CoVariant<out T>(val t : T) {
+
+ fun classGenerics() : CoVariant<T> {
+ return CoVariant(t);
+ }
+}
+
+class ContraVariant<in T> {
+
+ fun classGenerics(t : T) {
+ println(t)
+ }
+}
+
+
+fun <T> CoVariant<T>.unBoxAndBox() : CoVariant<T> {
+ return CoVariant(this.t)
+}
+
+fun <T, R> CoVariant<R>.update(t : T) : CoVariant<T> {
+ println(this.t)
+ return CoVariant(t)
+}
diff --git a/src/test/java/com/android/tools/r8/memberrebinding/MemberRebindingConflictTest.java b/src/test/java/com/android/tools/r8/memberrebinding/MemberRebindingConflictTest.java
new file mode 100644
index 0000000..e081a44
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/memberrebinding/MemberRebindingConflictTest.java
@@ -0,0 +1,99 @@
+// 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.memberrebinding;
+
+import static org.hamcrest.core.StringContains.containsString;
+
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.NeverMerge;
+import com.android.tools.r8.R8TestRunResult;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.MethodAccessFlags;
+import com.android.tools.r8.memberrebinding.testclasses.MemberRebindingConflictTestClasses;
+import com.android.tools.r8.memberrebinding.testclasses.MemberRebindingConflictTestClasses.C;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class MemberRebindingConflictTest extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ public MemberRebindingConflictTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void test() throws Exception {
+ R8TestRunResult result =
+ testForR8(parameters.getBackend())
+ .addProgramClasses(A.class, TestClass.class)
+ .addProgramClassFileData(
+ transformer(B.class)
+ .removeMethods(
+ (access, name, descriptor, signature, exceptions) -> {
+ if (name.equals("foo")) {
+ assert MethodAccessFlags.fromCfAccessFlags(access, false).isSynthetic();
+ return true;
+ }
+ return false;
+ })
+ .transform())
+ .addInnerClasses(MemberRebindingConflictTestClasses.class)
+ .addKeepMainRule(TestClass.class)
+ .enableInliningAnnotations()
+ .enableMergeAnnotations()
+ .enableNeverClassInliningAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .run(parameters.getRuntime(), TestClass.class);
+
+ if (parameters.isDexRuntime()
+ && parameters.getRuntime().asDex().getVm().getVersion().isDalvik()) {
+ result.assertSuccessWithOutputLines("foo", "bar", "foo", "baz");
+ } else {
+ result.assertFailureWithErrorThatMatches(
+ containsString(IllegalAccessError.class.getTypeName()));
+ }
+ }
+
+ static class TestClass {
+
+ public static void main(String[] args) {
+ C c = new C();
+ c.bar();
+ c.baz();
+ }
+ }
+
+ @NeverMerge
+ static class A {
+
+ @NeverInline
+ public void foo() {
+ System.out.println("foo");
+ }
+ }
+
+ @NeverMerge
+ public static class B extends A {
+
+ // public synthetic void foo() { super.foo(); }
+
+ @NeverInline
+ public void bar() {
+ foo();
+ System.out.println("bar");
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/memberrebinding/testclasses/MemberRebindingConflictTestClasses.java b/src/test/java/com/android/tools/r8/memberrebinding/testclasses/MemberRebindingConflictTestClasses.java
new file mode 100644
index 0000000..79f7dd6
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/memberrebinding/testclasses/MemberRebindingConflictTestClasses.java
@@ -0,0 +1,22 @@
+// 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.memberrebinding.testclasses;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.memberrebinding.MemberRebindingConflictTest;
+
+public class MemberRebindingConflictTestClasses {
+
+ @NeverClassInline
+ public static class C extends MemberRebindingConflictTest.B {
+
+ @NeverInline
+ public void baz() {
+ super.foo();
+ System.out.println("baz");
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/naming/IdentifierMinifierTest.java b/src/test/java/com/android/tools/r8/naming/IdentifierMinifierTest.java
index 1c7c5bc..627a059 100644
--- a/src/test/java/com/android/tools/r8/naming/IdentifierMinifierTest.java
+++ b/src/test/java/com/android/tools/r8/naming/IdentifierMinifierTest.java
@@ -15,7 +15,6 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.graph.DexEncodedField;
-import com.android.tools.r8.graph.DexValue.DexValueString;
import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
@@ -284,19 +283,22 @@
private static int countRenamedClassIdentifier(
CodeInspector inspector, List<DexEncodedField> fields) {
return fields.stream()
- .filter(encodedField -> encodedField.getStaticValue() instanceof DexValueString)
- .reduce(0, (cnt, encodedField) -> {
- String cnstString =
- ((DexValueString) encodedField.getStaticValue()).getValue().toString();
- if (isValidJavaType(cnstString)) {
- ClassSubject classSubject = inspector.clazz(cnstString);
- if (classSubject.isRenamed()
- && descriptorToJavaType(classSubject.getFinalDescriptor()).equals(cnstString)) {
- return cnt + 1;
- }
- }
- return cnt;
- }, Integer::sum);
+ .filter(encodedField -> encodedField.getStaticValue().isDexValueString())
+ .reduce(
+ 0,
+ (cnt, encodedField) -> {
+ String cnstString =
+ encodedField.getStaticValue().asDexValueString().getValue().toString();
+ if (isValidJavaType(cnstString)) {
+ ClassSubject classSubject = inspector.clazz(cnstString);
+ if (classSubject.isRenamed()
+ && descriptorToJavaType(classSubject.getFinalDescriptor()).equals(cnstString)) {
+ return cnt + 1;
+ }
+ }
+ return cnt;
+ },
+ Integer::sum);
}
private static Set<InstructionSubject> getRenamedMemberIdentifierConstStrings(
diff --git a/src/test/java/com/android/tools/r8/naming/IdentifierNameStringMarkerTest.java b/src/test/java/com/android/tools/r8/naming/IdentifierNameStringMarkerTest.java
index e9ce1d8..116ce4a 100644
--- a/src/test/java/com/android/tools/r8/naming/IdentifierNameStringMarkerTest.java
+++ b/src/test/java/com/android/tools/r8/naming/IdentifierNameStringMarkerTest.java
@@ -26,7 +26,6 @@
import com.android.tools.r8.code.SputObject;
import com.android.tools.r8.graph.DexCode;
import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexValue.DexValueString;
import com.android.tools.r8.smali.SmaliBuilder;
import com.android.tools.r8.smali.SmaliBuilder.MethodSignature;
import com.android.tools.r8.smali.SmaliTestBase;
@@ -278,8 +277,8 @@
assertTrue(clazz.isPresent());
FieldSubject field = clazz.field("java.lang.String", "sClassName");
assertTrue(field.isPresent());
- assertTrue(field.getStaticValue() instanceof DexValueString);
- String defaultValue = ((DexValueString) field.getStaticValue()).getValue().toString();
+ assertTrue(field.getStaticValue().isDexValueString());
+ String defaultValue = field.getStaticValue().asDexValueString().getValue().toString();
assertEquals(BOO, defaultValue);
}
@@ -300,8 +299,8 @@
assertTrue(clazz.isPresent());
FieldSubject field = clazz.field("java.lang.String", "sClassName");
assertTrue(field.isPresent());
- assertTrue(field.getStaticValue() instanceof DexValueString);
- String defaultValue = ((DexValueString) field.getStaticValue()).getValue().toString();
+ assertTrue(field.getStaticValue().isDexValueString());
+ String defaultValue = field.getStaticValue().asDexValueString().getValue().toString();
assertNotEquals(BOO, defaultValue);
}
@@ -324,8 +323,8 @@
assertTrue(clazz.isPresent());
FieldSubject field = clazz.field("java.lang.String", "sFieldName");
assertTrue(field.isPresent());
- assertTrue(field.getStaticValue() instanceof DexValueString);
- String defaultValue = ((DexValueString) field.getStaticValue()).getValue().toString();
+ assertTrue(field.getStaticValue().isDexValueString());
+ String defaultValue = field.getStaticValue().asDexValueString().getValue().toString();
assertNotEquals(fooInBoo, defaultValue);
}
@@ -348,8 +347,8 @@
assertTrue(clazz.isPresent());
FieldSubject field = clazz.field("java.lang.String", "sMethodName");
assertTrue(field.isPresent());
- assertTrue(field.getStaticValue() instanceof DexValueString);
- String defaultValue = ((DexValueString) field.getStaticValue()).getValue().toString();
+ assertTrue(field.getStaticValue().isDexValueString());
+ String defaultValue = field.getStaticValue().asDexValueString().getValue().toString();
assertNotEquals(fooInBoo, defaultValue);
}
diff --git a/src/test/java/com/android/tools/r8/naming/b124357885/B124357885Test.java b/src/test/java/com/android/tools/r8/naming/b124357885/B124357885Test.java
index 1dabc11..e1cd05a 100644
--- a/src/test/java/com/android/tools/r8/naming/b124357885/B124357885Test.java
+++ b/src/test/java/com/android/tools/r8/naming/b124357885/B124357885Test.java
@@ -17,7 +17,6 @@
import com.android.tools.r8.graph.DexAnnotationElement;
import com.android.tools.r8.graph.DexValue;
import com.android.tools.r8.graph.DexValue.DexValueArray;
-import com.android.tools.r8.graph.DexValue.DexValueString;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.StringUtils;
@@ -47,12 +46,12 @@
DexAnnotationElement[] elements = signature.getAnnotation().elements;
assertEquals(1, elements.length);
assertEquals("value", elements[0].name.toString());
- assertTrue(elements[0].value instanceof DexValueArray);
- DexValueArray array = (DexValueArray) elements[0].value;
+ assertTrue(elements[0].value.isDexValueArray());
+ DexValueArray array = elements[0].value.asDexValueArray();
StringBuilder builder = new StringBuilder();
for (DexValue value : array.getValues()) {
- assertTrue(value instanceof DexValueString);
- builder.append(((DexValueString) value).value);
+ assertTrue(value.isDexValueString());
+ builder.append(value.asDexValueString().value);
}
String fooImplFinalDescriptor =
DescriptorUtils.javaTypeToDescriptor(inspector.clazz(FooImpl.class).getFinalName());
diff --git a/src/test/java/com/android/tools/r8/resolution/singletarget/InstantiatedLowerBoundTest.java b/src/test/java/com/android/tools/r8/resolution/singletarget/InstantiatedLowerBoundTest.java
index deec1e3..8a35389 100644
--- a/src/test/java/com/android/tools/r8/resolution/singletarget/InstantiatedLowerBoundTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/singletarget/InstantiatedLowerBoundTest.java
@@ -19,7 +19,7 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.LookupResult;
import com.android.tools.r8.graph.ResolutionResult;
-import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
+import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
import com.android.tools.r8.ir.analysis.type.Nullability;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.google.common.collect.Sets;
@@ -53,8 +53,8 @@
DexType typeB = buildType(B.class, appInfo.dexItemFactory());
DexType typeMain = buildType(Main.class, appInfo.dexItemFactory());
DexMethod fooA = buildNullaryVoidMethod(A.class, "foo", appInfo.dexItemFactory());
- ClassTypeLatticeElement latticeB =
- ClassTypeLatticeElement.create(typeB, Nullability.definitelyNotNull(), appView);
+ ClassTypeElement latticeB =
+ ClassTypeElement.create(typeB, Nullability.definitelyNotNull(), appView);
DexEncodedMethod singleTarget =
appInfo.lookupSingleVirtualTarget(fooA, typeMain, false, t -> false, typeA, latticeB);
assertNotNull(singleTarget);
@@ -73,8 +73,8 @@
DexType typeB = buildType(B.class, appInfo.dexItemFactory());
DexType typeMain = buildType(Main.class, appInfo.dexItemFactory());
DexMethod fooA = buildNullaryVoidMethod(A.class, "foo", appInfo.dexItemFactory());
- ClassTypeLatticeElement latticeB =
- ClassTypeLatticeElement.create(typeB, Nullability.definitelyNotNull(), appView);
+ ClassTypeElement latticeB =
+ ClassTypeElement.create(typeB, Nullability.definitelyNotNull(), appView);
DexEncodedMethod singleTarget =
appInfo.lookupSingleVirtualTarget(fooA, typeMain, false, t -> false, typeA, latticeB);
assertNotNull(singleTarget);
@@ -117,8 +117,8 @@
assert false;
});
assertEquals(expected, actual);
- ClassTypeLatticeElement latticeC =
- ClassTypeLatticeElement.create(typeC, Nullability.definitelyNotNull(), appView);
+ ClassTypeElement latticeC =
+ ClassTypeElement.create(typeC, Nullability.definitelyNotNull(), appView);
DexEncodedMethod singleTarget =
appInfo.lookupSingleVirtualTarget(fooA, typeMain, false, t -> false, typeA, latticeC);
assertNull(singleTarget);
diff --git a/src/test/java/com/android/tools/r8/rewrite/staticvalues/StaticValuesTest.java b/src/test/java/com/android/tools/r8/rewrite/staticvalues/StaticValuesTest.java
index f0270f1..662b22e 100644
--- a/src/test/java/com/android/tools/r8/rewrite/staticvalues/StaticValuesTest.java
+++ b/src/test/java/com/android/tools/r8/rewrite/staticvalues/StaticValuesTest.java
@@ -13,15 +13,6 @@
import com.android.tools.r8.code.SgetBoolean;
import com.android.tools.r8.graph.DexCode;
import com.android.tools.r8.graph.DexValue;
-import com.android.tools.r8.graph.DexValue.DexValueBoolean;
-import com.android.tools.r8.graph.DexValue.DexValueByte;
-import com.android.tools.r8.graph.DexValue.DexValueChar;
-import com.android.tools.r8.graph.DexValue.DexValueDouble;
-import com.android.tools.r8.graph.DexValue.DexValueFloat;
-import com.android.tools.r8.graph.DexValue.DexValueInt;
-import com.android.tools.r8.graph.DexValue.DexValueLong;
-import com.android.tools.r8.graph.DexValue.DexValueShort;
-import com.android.tools.r8.graph.DexValue.DexValueString;
import com.android.tools.r8.smali.SmaliBuilder;
import com.android.tools.r8.smali.SmaliTestBase;
import com.android.tools.r8.utils.AndroidApp;
@@ -102,48 +93,49 @@
DexValue value;
assertTrue(inspector.clazz("Test").field("boolean", "booleanField").hasExplicitStaticValue());
value = inspector.clazz("Test").field("boolean", "booleanField").getStaticValue();
- assertTrue(value instanceof DexValueBoolean);
- assertTrue(((DexValueBoolean) value).getValue());
+ assertTrue(value.isDexValueBoolean());
+ assertTrue(value.asDexValueBoolean().getValue());
assertTrue(inspector.clazz("Test").field("byte", "byteField").hasExplicitStaticValue());
value = inspector.clazz("Test").field("byte", "byteField").getStaticValue();
- assertTrue(value instanceof DexValueByte);
- assertEquals(1, ((DexValueByte) value).getValue());
+ assertTrue(value.isDexValueByte());
+ assertEquals(1, value.asDexValueByte().getValue());
assertTrue(inspector.clazz("Test").field("short", "shortField").hasExplicitStaticValue());
value = inspector.clazz("Test").field("short", "shortField").getStaticValue();
- assertTrue(value instanceof DexValueShort);
- assertEquals(2, ((DexValueShort) value).getValue());
+ assertTrue(value.isDexValueShort());
+ assertEquals(2, value.asDexValueShort().getValue());
assertTrue(inspector.clazz("Test").field("int", "intField").hasExplicitStaticValue());
value = inspector.clazz("Test").field("int", "intField").getStaticValue();
- assertTrue(value instanceof DexValueInt);
- assertEquals(3, ((DexValueInt) value).getValue());
+ assertTrue(value.isDexValueInt());
+ assertEquals(3, value.asDexValueInt().getValue());
assertTrue(inspector.clazz("Test").field("long", "longField").hasExplicitStaticValue());
value = inspector.clazz("Test").field("long", "longField").getStaticValue();
- assertTrue(value instanceof DexValueLong);
- assertEquals(4, ((DexValueLong) value).getValue());
+ assertTrue(value.isDexValueLong());
+ assertEquals(4, value.asDexValueLong().getValue());
assertTrue(inspector.clazz("Test").field("float", "floatField").hasExplicitStaticValue());
value = inspector.clazz("Test").field("float", "floatField").getStaticValue();
- assertTrue(value instanceof DexValueFloat);
- assertEquals(5.0f, ((DexValueFloat) value).getValue(), 0.0);
+ assertTrue(value.isDexValueFloat());
+ assertEquals(5.0f, value.asDexValueFloat().getValue(), 0.0);
assertTrue(inspector.clazz("Test").field("double", "doubleField").hasExplicitStaticValue());
value = inspector.clazz("Test").field("double", "doubleField").getStaticValue();
- assertTrue(value instanceof DexValueDouble);
- assertEquals(6.0f, ((DexValueDouble) value).getValue(), 0.0);
+ assertTrue(value.isDexValueDouble());
+ assertEquals(6.0f, value.asDexValueDouble().getValue(), 0.0);
assertTrue(inspector.clazz("Test").field("char", "charField").hasExplicitStaticValue());
value = inspector.clazz("Test").field("char", "charField").getStaticValue();
- assertTrue(value instanceof DexValueChar);
- assertEquals(0x30 + 7, ((DexValueChar) value).getValue());
+ assertTrue(value.isDexValueChar());
+ assertEquals(0x30 + 7, value.asDexValueChar().getValue());
- assertTrue(inspector.clazz("Test").field("java.lang.String", "stringField").hasExplicitStaticValue());
+ assertTrue(
+ inspector.clazz("Test").field("java.lang.String", "stringField").hasExplicitStaticValue());
value = inspector.clazz("Test").field("java.lang.String", "stringField").getStaticValue();
- assertTrue(value instanceof DexValueString);
- assertEquals(("8"), ((DexValueString) value).getValue().toString());
+ assertTrue(value.isDexValueString());
+ assertEquals(("8"), value.asDexValueString().getValue().toString());
String result = runArt(processedApplication);
@@ -319,13 +311,14 @@
DexValue value;
assertTrue(inspector.clazz("Test").field("int", "intField").hasExplicitStaticValue());
value = inspector.clazz("Test").field("int", "intField").getStaticValue();
- assertTrue(value instanceof DexValueInt);
- assertEquals(3, ((DexValueInt) value).getValue());
+ assertTrue(value.isDexValueInt());
+ assertEquals(3, value.asDexValueInt().getValue());
- assertTrue(inspector.clazz("Test").field("java.lang.String", "stringField").hasExplicitStaticValue());
+ assertTrue(
+ inspector.clazz("Test").field("java.lang.String", "stringField").hasExplicitStaticValue());
value = inspector.clazz("Test").field("java.lang.String", "stringField").getStaticValue();
- assertTrue(value instanceof DexValueString);
- assertEquals(("7"), ((DexValueString) value).getValue().toString());
+ assertTrue(value.isDexValueString());
+ assertEquals(("7"), value.asDexValueString().getValue().toString());
String result = runArt(processedApplication);
@@ -389,14 +382,15 @@
assertTrue(inspector.clazz("Test").field("int", "intField").hasExplicitStaticValue());
DexValue value = inspector.clazz("Test").field("int", "intField").getStaticValue();
- assertTrue(value instanceof DexValueInt);
- assertEquals(1, ((DexValueInt) value).getValue());
+ assertTrue(value.isDexValueInt());
+ assertEquals(1, value.asDexValueInt().getValue());
- assertTrue(inspector.clazz("Test").field("java.lang.String", "stringField").hasExplicitStaticValue());
+ assertTrue(
+ inspector.clazz("Test").field("java.lang.String", "stringField").hasExplicitStaticValue());
value = inspector.clazz("Test").field("java.lang.String", "stringField").getStaticValue();
- assertTrue(value instanceof DexValueString);
+ assertTrue(value.isDexValueString());
// We stop at control-flow and therefore the initial value for the string field will be 5.
- assertEquals(("5"), ((DexValueString) value).getValue().toString());
+ assertEquals(("5"), value.asDexValueString().getValue().toString());
DexCode code = inspector.clazz("Test").clinit().getMethod().getCode().asDexCode();
assertTrue(code.instructions[0] instanceof SgetBoolean);
diff --git a/src/test/java/com/android/tools/r8/shaking/EventuallyNonTargetedMethodTest.java b/src/test/java/com/android/tools/r8/shaking/EventuallyNonTargetedMethodTest.java
new file mode 100644
index 0000000..741496d
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/shaking/EventuallyNonTargetedMethodTest.java
@@ -0,0 +1,101 @@
+// 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.shaking;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.NeverMerge;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.StringUtils;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class EventuallyNonTargetedMethodTest extends TestBase {
+
+ static final String EXPECTED = StringUtils.lines("A::foo", "C::bar");
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ public EventuallyNonTargetedMethodTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void test() throws Exception {
+ testForR8(parameters.getBackend())
+ .enableInliningAnnotations()
+ .enableMergeAnnotations()
+ .enableNeverClassInliningAnnotations()
+ .addInnerClasses(EventuallyNonTargetedMethodTest.class)
+ .addKeepMainRule(Main.class)
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutput(EXPECTED)
+ .inspect(this::checkIsFooPresent);
+ }
+
+ private void checkIsFooPresent(CodeInspector inspector) {
+ ClassSubject classSubject = inspector.clazz(C.class);
+ assertThat(classSubject, isPresent());
+ // TODO(b/150445487): Member rebinding will rewrite B::foo to A::foo causing C::foo to remain.
+ assertThat(classSubject.uniqueMethodWithName("foo"), isPresent());
+ }
+
+ @NeverMerge
+ private static class A {
+ @NeverInline
+ public void foo() {
+ System.out.println("A::foo");
+ }
+ }
+
+ @NeverMerge
+ @NeverClassInline
+ private static class B extends A {
+ // No override of foo, but B::foo will be the only target.
+ }
+
+ @NeverClassInline
+ private static class C extends A {
+
+ // Non-targeted override.
+ @Override
+ public void foo() {
+ System.out.println("C::foo");
+ }
+
+ @NeverInline
+ public void bar() {
+ System.out.println("C::bar");
+ }
+ }
+
+ private static class Main {
+ static boolean effectivelyFinalFalse = false;
+
+ public static void main(String[] args) {
+ new B().foo();
+ new C().bar();
+ if (effectivelyFinalFalse) {
+ // First round of tree shaking the below reference to A::foo will keep it live.
+ // This branch will then be removed and it should be possible to conclude C::foo dead.
+ new A().foo();
+ }
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/shaking/LibraryMethodOverrideInLambdaMarkingTest.java b/src/test/java/com/android/tools/r8/shaking/LibraryMethodOverrideInLambdaMarkingTest.java
index e3925ca..9d16769 100644
--- a/src/test/java/com/android/tools/r8/shaking/LibraryMethodOverrideInLambdaMarkingTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/LibraryMethodOverrideInLambdaMarkingTest.java
@@ -63,7 +63,11 @@
DexEncodedMethod method =
clazz.lookupVirtualMethod(m -> m.method.name.toString().equals("iterator"));
// TODO(b/149976493): Mark library overrides from lambda instances.
- assertTrue(method.isLibraryMethodOverride().isFalse());
+ if (parameters.isCfRuntime()) {
+ assertTrue(method.isLibraryMethodOverride().isFalse());
+ } else {
+ assertTrue(method.isLibraryMethodOverride().isTrue());
+ }
}
static class TestClass {
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
index 63c85d5..1f25605 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
@@ -26,7 +26,6 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DexValue;
import com.android.tools.r8.graph.DexValue.DexValueArray;
-import com.android.tools.r8.graph.DexValue.DexValueString;
import com.android.tools.r8.ir.desugar.InterfaceMethodRewriter;
import com.android.tools.r8.naming.ClassNameMapper;
import com.android.tools.r8.naming.ClassNamingForNameMapper;
@@ -228,13 +227,12 @@
}
assert annotation.annotation.elements.length == 1;
DexAnnotationElement element = annotation.annotation.elements[0];
- assert element.value instanceof DexValueArray;
+ assert element.value.isDexValueArray();
StringBuilder builder = new StringBuilder();
- DexValueArray valueArray = (DexValueArray) element.value;
+ DexValueArray valueArray = element.value.asDexValueArray();
for (DexValue value : valueArray.getValues()) {
- assertTrue(value instanceof DexValueString);
- DexValueString s = (DexValueString) value;
- builder.append(s.getValue());
+ assertTrue(value.isDexValueString());
+ builder.append(value.asDexValueString().getValue());
}
return builder.toString();
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/KotlinClassMetadataReader.java b/src/test/java/com/android/tools/r8/utils/codeinspector/KotlinClassMetadataReader.java
index b3a0143..73972f4 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/KotlinClassMetadataReader.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/KotlinClassMetadataReader.java
@@ -8,7 +8,6 @@
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexValue;
import com.android.tools.r8.graph.DexValue.DexValueArray;
-import com.android.tools.r8.graph.DexValue.DexValueString;
import com.android.tools.r8.kotlin.Kotlin;
import java.util.IdentityHashMap;
import java.util.Map;
@@ -51,10 +50,10 @@
}
private static int[] getUnboxedIntArray(DexValue v, String elementName) {
- if (!(v instanceof DexValueArray)) {
+ if (!v.isDexValueArray()) {
throw new MetadataError("invalid '" + elementName + "' value: " + v.toSourceString());
}
- DexValueArray intArrayValue = (DexValueArray) v;
+ DexValueArray intArrayValue = v.asDexValueArray();
DexValue[] values = intArrayValue.getValues();
int[] result = new int [values.length];
for (int i = 0; i < values.length; i++) {
@@ -64,10 +63,10 @@
}
private static String[] getUnboxedStringArray(DexValue v, String elementName) {
- if (!(v instanceof DexValueArray)) {
+ if (!v.isDexValueArray()) {
throw new MetadataError("invalid '" + elementName + "' value: " + v.toSourceString());
}
- DexValueArray stringArrayValue = (DexValueArray) v;
+ DexValueArray stringArrayValue = v.asDexValueArray();
DexValue[] values = stringArrayValue.getValues();
String[] result = new String [values.length];
for (int i = 0; i < values.length; i++) {
@@ -77,10 +76,10 @@
}
private static String getUnboxedString(DexValue v, String elementName) {
- if (!(v instanceof DexValueString)) {
+ if (!v.isDexValueString()) {
throw new MetadataError("invalid '" + elementName + "' value: " + v.toSourceString());
}
- return ((DexValueString) v).getValue().toString();
+ return v.asDexValueString().getValue().toString();
}
private static class MetadataError extends RuntimeException {
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/MemberSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/MemberSubject.java
index a5cca23..e2561b0 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/MemberSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/MemberSubject.java
@@ -6,7 +6,7 @@
import com.android.tools.r8.graph.DexAnnotationElement;
import com.android.tools.r8.graph.DexValue;
-import com.android.tools.r8.graph.DexValue.DexValueString;
+import com.android.tools.r8.graph.DexValue.DexValueArray;
import com.android.tools.r8.naming.MemberNaming.Signature;
public abstract class MemberSubject extends Subject {
@@ -66,12 +66,12 @@
assert annotation.getAnnotation().elements.length == 1;
DexAnnotationElement element = annotation.getAnnotation().elements[0];
assert element.name.toString().equals("value");
- assert element.value instanceof DexValue.DexValueArray;
- DexValue.DexValueArray array = (DexValue.DexValueArray) element.value;
+ assert element.value.isDexValueArray();
+ DexValueArray array = element.value.asDexValueArray();
StringBuilder builder = new StringBuilder();
for (DexValue value : array.getValues()) {
- if (value instanceof DexValueString) {
- builder.append(((DexValueString) value).value);
+ if (value.isDexValueString()) {
+ builder.append(value.asDexValueString().value);
} else {
builder.append(value.toString());
}
diff --git a/tools/fmt-diff.py b/tools/fmt-diff.py
new file mode 100755
index 0000000..4e97f3a
--- /dev/null
+++ b/tools/fmt-diff.py
@@ -0,0 +1,31 @@
+#!/usr/bin/env python
+# 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.
+
+import os
+import subprocess
+import sys
+
+import utils
+
+from subprocess import Popen, PIPE
+
+GOOGLE_JAVA_FORMAT_DIFF = os.path.join(
+ utils.THIRD_PARTY,
+ 'google-java-format',
+ 'google-java-format-google-java-format-1.7',
+ 'scripts',
+ 'google-java-format-diff.py')
+
+def main():
+ upstream = subprocess.check_output(['git', 'cl', 'upstream']).strip()
+ git_diff_process = Popen(['git', 'diff', '-U0', upstream], stdout=PIPE)
+ fmt_process = Popen(
+ ['python', GOOGLE_JAVA_FORMAT_DIFF, '-p1', '-i'],
+ stdin=git_diff_process.stdout)
+ git_diff_process.stdout.close()
+ fmt_process.communicate()
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/tools/jdk.py b/tools/jdk.py
index 5791e50..bc40873 100755
--- a/tools/jdk.py
+++ b/tools/jdk.py
@@ -20,6 +20,15 @@
else:
return os.environ['JAVA_HOME']
+def GetJdk8Home():
+ root = os.path.join(JDK_DIR, 'jdk8')
+ if defines.IsLinux():
+ return os.path.join(root, 'linux-x86')
+ elif defines.IsOsX():
+ return os.path.join(root, 'darwin-x86')
+ else:
+ return os.environ['JAVA_HOME']
+
def GetJavaExecutable(jdkHome=None):
jdkHome = jdkHome if jdkHome else GetJdkHome()
executable = 'java.exe' if defines.IsWindows() else 'java'
diff --git a/tools/run_on_app.py b/tools/run_on_app.py
index 07de70c..1687797 100755
--- a/tools/run_on_app.py
+++ b/tools/run_on_app.py
@@ -109,6 +109,10 @@
help='Run without debug asserts.',
default=False,
action='store_true')
+ result.add_option('--debug-agent',
+ help='Run with debug agent.',
+ default=False,
+ action='store_true')
result.add_option('--version',
help='The version of the app to run')
result.add_option('-k',
@@ -519,6 +523,12 @@
if 'allow-type-errors' in values:
extra_args.append('-Dcom.android.tools.r8.allowTypeErrors=1')
+ if options.debug_agent:
+ if not options.compiler_build == 'full':
+ print('WARNING: Running debugging agent on r8lib is questionable...')
+ extra_args.append(
+ '-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005')
+
if not options.no_libraries:
for lib in libraries:
args.extend(['--lib', lib])
diff --git a/tools/run_on_as_app.py b/tools/run_on_as_app.py
index abd0f71..6d6f0fe 100755
--- a/tools/run_on_as_app.py
+++ b/tools/run_on_as_app.py
@@ -60,7 +60,8 @@
'name': None,
'releaseTarget': None,
'signed_apk_name': None,
- 'skip': False
+ 'skip': False,
+ 'has_lint_task': True
}
self.__dict__ = dict(defaults.items() + fields.items())
@@ -98,7 +99,8 @@
'id': 'com.numix.calculator',
'dir': 'Calculator',
'name': 'numix-calculator',
- 'has_instrumentation_tests': True
+ 'has_instrumentation_tests': True,
+ 'has_lint_task': False
})
]
}),
@@ -157,7 +159,8 @@
'revision': '6e53458f167b6d78398da60c20fd0da01a232617',
'apps': [
App({
- 'id': 'com.chanapps.four.activity'
+ 'id': 'com.chanapps.four.activity',
+ 'has_lint_task': False
})
]
}),
@@ -203,7 +206,8 @@
'id': 'com.google.samples.apps.iosched',
'module': 'mobile',
'min_sdk': 21,
- 'compile_sdk': 29
+ 'compile_sdk': 29,
+ 'has_lint_task': False
})
]
}),
@@ -256,7 +260,8 @@
'revision': 'ed543099c7823be00f15d9340f94bdb7cb37d1e6',
'apps': [
App({
- 'id': 'org.schabi.newpipe'
+ 'id': 'org.schabi.newpipe',
+ 'has_lint_task': False
})
]
}),
@@ -305,7 +310,8 @@
'apps': [
App({
'id': 'com.simplemobiletools.calendar.pro',
- 'signed_apk_name': 'calendar-release.apk'
+ 'signed_apk_name': 'calendar-release.apk',
+ 'has_lint_task': False
})
]
}),
@@ -316,7 +322,8 @@
'apps': [
App({
'id': 'com.simplemobiletools.camera.pro',
- 'signed_apk_name': 'camera-release.apk'
+ 'signed_apk_name': 'camera-release.apk',
+ 'has_lint_task': False
})
]
}),
@@ -327,7 +334,8 @@
'apps': [
App({
'id': 'com.simplemobiletools.filemanager.pro',
- 'signed_apk_name': 'file-manager-release.apk'
+ 'signed_apk_name': 'file-manager-release.apk',
+ 'has_lint_task': False
})
]
}),
@@ -338,7 +346,8 @@
'apps': [
App({
'id': 'com.simplemobiletools.gallery.pro',
- 'signed_apk_name': 'gallery-release.apk'
+ 'signed_apk_name': 'gallery-release.apk',
+ 'has_lint_task': False
})
]
}),
@@ -364,7 +373,8 @@
App({
'id': 'eu.kanade.tachiyomi',
'flavor': 'dev',
- 'min_sdk': 16
+ 'min_sdk': 16,
+ 'has_lint_task': False
})
]
}),
@@ -377,6 +387,7 @@
'id': 'app.tivi',
'min_sdk': 23,
'compile_sdk': 28,
+ 'has_lint_task': False
})
]
}),
@@ -708,20 +719,24 @@
app, checkout_dir, proguard_config_dest)
env_vars = {}
+ env_vars['JAVA_HOME'] = jdk.GetJdk8Home()
env_vars['ANDROID_HOME'] = utils.getAndroidHome()
if not options.disable_assertions:
env_vars['JAVA_OPTS'] = '-ea:com.android.tools.r8...'
release_target = app.releaseTarget
if not release_target:
- release_target = app.module.replace('/', ':') + ':' + 'assemble' + (
- app.flavor.capitalize() if app.flavor else '') + 'Release'
+ app_module = app.module.replace('/', ':')
+ app_flavor = (app.flavor.capitalize() if app.flavor else '') + 'Release'
+ release_target = app_module + ':' + 'assemble' + app_flavor
# Build using gradle.
args = [release_target,
'-g=' + os.path.join(checkout_dir, GRADLE_USER_HOME),
'-Pandroid.enableR8=' + str(IsR8(shrinker)).lower(),
'-Pandroid.enableR8.fullMode=' + str(IsR8FullMode(shrinker)).lower()]
+ if app.has_lint_task:
+ args.extend(['-x', app_module + ':lintVital' + app_flavor])
# Warm up gradle if pre_runs > 0. For posterity we generate the same sequence
# as the benchmarking at https://github.com/madsager/santa-tracker-android.
diff --git a/tools/toolhelper.py b/tools/toolhelper.py
index cc1a9cb..1eee1f7 100644
--- a/tools/toolhelper.py
+++ b/tools/toolhelper.py
@@ -14,9 +14,10 @@
def run(tool, args, build=None, debug=True,
profile=False, track_memory_file=None, extra_args=None,
stderr=None, stdout=None, return_stdout=False, timeout=0, quiet=False,
- cmd_prefix=[]):
+ cmd_prefix=None):
cmd = []
- cmd.extend(cmd_prefix)
+ if cmd_prefix:
+ cmd.extend(cmd_prefix)
if build is None:
build, args = extract_build_from_args(args)
if build: