Introduce a clinit field in DexItemFactory
Change-Id: I4cc830861cd048ef633881db4ff9a23363f36388
Bug: 150349055
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 5618178..6b507da 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfoWithSubtyping.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfoWithSubtyping.java
@@ -510,13 +510,13 @@
if (clazz.isProgramClass()) {
if (lookUpwards) {
DexEncodedMethod resolutionResult =
- resolveMethod(type, dexItemFactory().objectMethods.finalize).getSingleTarget();
+ resolveMethod(type, dexItemFactory().objectMembers.finalize).getSingleTarget();
if (resolutionResult != null && resolutionResult.isProgramMethod(this)) {
mayHaveFinalizeMethodDirectlyOrIndirectlyCache.put(type, true);
return true;
}
} else {
- if (clazz.lookupVirtualMethod(dexItemFactory().objectMethods.finalize) != null) {
+ if (clazz.lookupVirtualMethod(dexItemFactory().objectMembers.finalize) != null) {
mayHaveFinalizeMethodDirectlyOrIndirectlyCache.put(type, true);
return true;
}
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 c474718..0fd4536 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClass.java
@@ -859,7 +859,7 @@
}
public boolean definesFinalizer(DexItemFactory factory) {
- return lookupVirtualMethod(factory.objectMethods.finalize) != null;
+ return lookupVirtualMethod(factory.objectMembers.finalize) != null;
}
public boolean defaultValuesForStaticFieldsMayTriggerAllocation() {
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 0f317ec..c9491e3 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
@@ -406,7 +406,7 @@
new StringBuildingMethods(stringBufferType);
public final BooleanMembers booleanMembers = new BooleanMembers();
public final ObjectsMethods objectsMethods = new ObjectsMethods();
- public final ObjectMethods objectMethods = new ObjectMethods();
+ public final ObjectMembers objectMembers = new ObjectMembers();
public final StringMethods stringMethods = new StringMethods();
public final LongMethods longMethods = new LongMethods();
public final DoubleMethods doubleMethods = new DoubleMethods();
@@ -595,8 +595,8 @@
public Map<DexMethod, Predicate<InvokeMethod>> libraryMethodsWithoutSideEffects =
Streams.<Pair<DexMethod, Predicate<InvokeMethod>>>concat(
Stream.of(new Pair<>(enumMethods.constructor, alwaysTrue())),
- Stream.of(new Pair<>(objectMethods.constructor, alwaysTrue())),
- Stream.of(new Pair<>(objectMethods.getClass, alwaysTrue())),
+ Stream.of(new Pair<>(objectMembers.constructor, alwaysTrue())),
+ Stream.of(new Pair<>(objectMembers.getClass, alwaysTrue())),
mapToPredicate(classMethods.getNames, alwaysTrue()),
mapToPredicate(
stringBufferMethods.constructorMethods,
@@ -735,7 +735,14 @@
}
}
- public class ObjectMethods {
+ public class ObjectMembers {
+
+ /**
+ * This field is not on {@link Object}, but will be synthesized on program classes as a static
+ * field, for the compiler to have a principled way to trigger the initialization of a given
+ * class.
+ */
+ public final DexField clinitField = createField(objectType, intType, "$r8$clinit");
public final DexMethod clone;
public final DexMethod getClass;
@@ -743,7 +750,7 @@
public final DexMethod finalize;
public final DexMethod toString;
- private ObjectMethods() {
+ private ObjectMembers() {
// The clone method is installed on each array, so one has to use method.match(clone).
clone = createMethod(objectType, createProto(objectType), cloneMethodName);
getClass = createMethod(objectDescriptor,
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/modeling/LibraryMethodReadSetModeling.java b/src/main/java/com/android/tools/r8/ir/analysis/modeling/LibraryMethodReadSetModeling.java
index 57f8d2e..34ab168 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/modeling/LibraryMethodReadSetModeling.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/modeling/LibraryMethodReadSetModeling.java
@@ -36,7 +36,7 @@
// Modeling of other library methods.
DexType holder = invokedMethod.holder;
if (holder == dexItemFactory.objectType) {
- if (invokedMethod == dexItemFactory.objectMethods.constructor) {
+ if (invokedMethod == dexItemFactory.objectMembers.constructor) {
return EmptyFieldSet.getInstance();
}
}
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 69c6281..a8e99cf 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
@@ -210,7 +210,7 @@
DexItemFactory dexItemFactory = appInfo.dexItemFactory();
DexEncodedMethod resolutionResult =
appInfo
- .resolveMethod(clazz.type, dexItemFactory.objectMethods.finalize)
+ .resolveMethod(clazz.type, dexItemFactory.objectMembers.finalize)
.getSingleTarget();
return resolutionResult != null && resolutionResult.isProgramMethod(appInfo);
}
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 e0043b9..0499be1 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
@@ -157,7 +157,7 @@
}
if (getInvokedMethod().holder.isArrayType()
- && getInvokedMethod().match(appView.dexItemFactory().objectMethods.clone)) {
+ && getInvokedMethod().match(appView.dexItemFactory().objectMembers.clone)) {
return false;
}
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 a8fa713..de95e53 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
@@ -180,11 +180,11 @@
// Verify that the object does not have a finalizer.
DexItemFactory dexItemFactory = appView.dexItemFactory();
ResolutionResult finalizeResolutionResult =
- appView.appInfo().resolveMethod(clazz, dexItemFactory.objectMethods.finalize);
+ appView.appInfo().resolveMethod(clazz, dexItemFactory.objectMembers.finalize);
if (finalizeResolutionResult.isSingleResolution()) {
DexMethod finalizeMethod = finalizeResolutionResult.getSingleTarget().method;
if (finalizeMethod != dexItemFactory.enumMethods.finalize
- && finalizeMethod != dexItemFactory.objectMethods.finalize) {
+ && finalizeMethod != dexItemFactory.objectMembers.finalize) {
return true;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaConstructorSourceCode.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaConstructorSourceCode.java
index 2900761..a8161d4 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaConstructorSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaConstructorSourceCode.java
@@ -22,7 +22,7 @@
@Override
protected void prepareInstructions() {
// Super constructor call (always java.lang.Object.<init>()).
- DexMethod objectInitMethod = factory().objectMethods.constructor;
+ DexMethod objectInitMethod = factory().objectMembers.constructor;
add(
builder -> {
assert builder.getReceiverValue() != null;
@@ -55,7 +55,7 @@
// be treated as equal, since it only has one call to super constructor,
// which is always java.lang.Object.<init>().
return captures().length == 0
- ? System.identityHashCode(factory().objectMethods.constructor)
+ ? System.identityHashCode(factory().objectMembers.constructor)
: super.hashCode();
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaConstructorSynthesizedCode.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaConstructorSynthesizedCode.java
index 906e15f..1809d69 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaConstructorSynthesizedCode.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaConstructorSynthesizedCode.java
@@ -22,7 +22,7 @@
@Override
public Consumer<UseRegistry> getRegistryCallback() {
return registry -> {
- registry.registerInvokeDirect(dexItemFactory().objectMethods.constructor);
+ registry.registerInvokeDirect(dexItemFactory().objectMembers.constructor);
DexType[] capturedTypes = captures();
for (int i = 0; i < capturedTypes.length; i++) {
registry.registerInstanceFieldWrite(lambda.getCaptureField(i));
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/backports/ObjectsMethodRewrites.java b/src/main/java/com/android/tools/r8/ir/desugar/backports/ObjectsMethodRewrites.java
index 911faa5..de16e98 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/backports/ObjectsMethodRewrites.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/backports/ObjectsMethodRewrites.java
@@ -35,7 +35,7 @@
DexItemFactory factory,
Set<Value> affectedValues) {
InvokeVirtual getClass =
- new InvokeVirtual(factory.objectMethods.getClass, null, invoke.inValues());
+ new InvokeVirtual(factory.objectMembers.getClass, null, invoke.inValues());
if (invoke.hasOutValue()) {
affectedValues.addAll(invoke.outValue().affectedValues());
invoke.outValue().replaceUsers(invoke.inValues().get(0));
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 80c36cc..d8d503d 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
@@ -3280,8 +3280,9 @@
iterator = isNotNullBlock.listIterator(code);
iterator.setInsertionPosition(position);
value = code.createValue(TypeLatticeElement.classClassType(appView, definitelyNotNull()));
- iterator.add(new InvokeVirtual(dexItemFactory.objectMethods.getClass, value,
- ImmutableList.of(arguments.get(i))));
+ iterator.add(
+ new InvokeVirtual(
+ dexItemFactory.objectMembers.getClass, value, ImmutableList.of(arguments.get(i))));
iterator.add(new InvokeVirtual(print, null, ImmutableList.of(out, value)));
}
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 e48fb6f..0a314aa 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
@@ -73,7 +73,7 @@
}
if (invokedMethod.holder.isArrayType()
- && invokedMethod.match(appView.dexItemFactory().objectMethods.clone)) {
+ && invokedMethod.match(appView.dexItemFactory().objectMembers.clone)) {
dynamicUpperBoundType =
TypeLatticeElement.fromDexType(invokedMethod.holder, definitelyNotNull(), appView);
dynamicLowerBoundType = null;
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 0403117..c9bf058 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
@@ -757,7 +757,7 @@
DexMethod requireNonNullMethod = appView.dexItemFactory().objectsMethods.requireNonNull;
iterator.add(new InvokeStatic(requireNonNullMethod, null, ImmutableList.of(receiver)));
} else {
- DexMethod getClassMethod = appView.dexItemFactory().objectMethods.getClass;
+ DexMethod getClassMethod = appView.dexItemFactory().objectMembers.getClass;
iterator.add(new InvokeVirtual(getClassMethod, null, ImmutableList.of(receiver)));
}
} else {
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 a28181f..48b8637 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
@@ -382,7 +382,7 @@
DexMethod requireNonNullMethod = appView.dexItemFactory().objectsMethods.requireNonNull;
replacement = new InvokeStatic(requireNonNullMethod, null, ImmutableList.of(receiver));
} else {
- DexMethod getClassMethod = appView.dexItemFactory().objectMethods.getClass;
+ DexMethod getClassMethod = appView.dexItemFactory().objectMembers.getClass;
replacement = new InvokeVirtual(getClassMethod, null, ImmutableList.of(receiver));
}
iterator.replaceCurrentInstruction(replacement);
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 fa41f210d..055eeca 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
@@ -83,7 +83,7 @@
DexItemFactory dexItemFactory = appView.dexItemFactory();
DexMethod invokedMethod = invoke.getInvokedMethod();
// Class<?> Object#getClass() is final and cannot be overridden.
- if (invokedMethod != dexItemFactory.objectMethods.getClass) {
+ if (invokedMethod != dexItemFactory.objectMembers.getClass) {
return null;
}
Value in = invoke.getReceiver();
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/ClassInliner.java b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/ClassInliner.java
index 291f4d5..6707fe1 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/ClassInliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/ClassInliner.java
@@ -343,7 +343,7 @@
DexItemFactory dexItemFactory = appView.dexItemFactory();
for (DexEncodedMethod method : clazz.virtualMethods()) {
if (method.method.name == dexItemFactory.finalizeMethodName
- && method.method.proto == dexItemFactory.objectMethods.finalize.proto) {
+ && method.method.proto == dexItemFactory.objectMembers.finalize.proto) {
return EligibilityStatus.HAS_FINALIZER;
}
}
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 5612322..22344de 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
@@ -446,7 +446,7 @@
}
DexMethod invokedMethod = invoke.getInvokedMethod();
- if (invokedMethod == dexItemFactory.objectMethods.constructor) {
+ if (invokedMethod == dexItemFactory.objectMembers.constructor) {
continue;
}
@@ -498,7 +498,7 @@
if (instruction.isInvokeMethodWithReceiver()) {
InvokeMethodWithReceiver invoke = instruction.asInvokeMethodWithReceiver();
DexMethod invokedMethod = invoke.getInvokedMethod();
- if (invokedMethod == dexItemFactory.objectMethods.constructor) {
+ if (invokedMethod == dexItemFactory.objectMembers.constructor) {
continue;
}
@@ -557,7 +557,7 @@
// Remove the call to java.lang.Object.<init>().
if (user.isInvokeDirect()) {
if (root.isNewInstance()
- && invoke.getInvokedMethod() == dexItemFactory.objectMethods.constructor) {
+ && invoke.getInvokedMethod() == dexItemFactory.objectMembers.constructor) {
removeInstruction(invoke);
continue;
}
@@ -743,7 +743,7 @@
// Check that the entire constructor chain can be inlined into the current context.
DexMethod parent = instanceInitializerInfo.getParent();
- while (parent != dexItemFactory.objectMethods.constructor) {
+ while (parent != dexItemFactory.objectMembers.constructor) {
if (parent == null) {
return null;
}
@@ -1177,7 +1177,7 @@
}
private boolean isInstanceInitializerEligibleForClassInlining(DexMethod method) {
- if (method == dexItemFactory.objectMethods.constructor) {
+ if (method == dexItemFactory.objectMembers.constructor) {
return true;
}
DexEncodedMethod encodedMethod = appView.definitionFor(method);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueOptimizer.java
index 908d125..30766c5 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueOptimizer.java
@@ -107,7 +107,7 @@
DexEncodedMethod singleTarget =
appView
.appInfo()
- .resolveMethodOnClass(valueInfo.type, factory.objectMethods.toString)
+ .resolveMethodOnClass(valueInfo.type, factory.objectMembers.toString)
.getSingleTarget();
if (singleTarget != null && singleTarget.method != factory.enumMethods.toString) {
continue;
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 d015712..9213a28 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
@@ -517,7 +517,7 @@
}
// java.lang.Enum.<init>() and java.lang.Object.<init>() are considered trivial.
if (invokedMethod == dexItemFactory.enumMethods.constructor
- || invokedMethod == dexItemFactory.objectMethods.constructor) {
+ || invokedMethod == dexItemFactory.objectMembers.constructor) {
builder.setParent(invokedMethod);
break;
}
@@ -984,12 +984,12 @@
ResolutionResult resolutionResult =
appView
.appInfo()
- .resolveMethodOnClass(clazz, appView.dexItemFactory().objectMethods.finalize);
+ .resolveMethodOnClass(clazz, appView.dexItemFactory().objectMembers.finalize);
DexEncodedMethod target = resolutionResult.getSingleTarget();
if (target != null
&& target.method != dexItemFactory.enumMethods.finalize
- && target.method != dexItemFactory.objectMethods.finalize) {
+ && target.method != dexItemFactory.objectMembers.finalize) {
return true;
}
return false;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/JStyleLambdaGroup.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/JStyleLambdaGroup.java
index df6f812..fbd189c 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/JStyleLambdaGroup.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/JStyleLambdaGroup.java
@@ -170,7 +170,7 @@
throws LambdaStructureError {
if (!(instructions[index] instanceof com.android.tools.r8.code.InvokeDirect
|| instructions[index] instanceof com.android.tools.r8.code.InvokeDirectRange)
- || instructions[index].getMethod() != kotlin.factory.objectMethods.constructor) {
+ || instructions[index].getMethod() != kotlin.factory.objectMembers.constructor) {
throw structureError(LAMBDA_INIT_CODE_VERIFICATION_FAILED);
}
index++;
@@ -218,7 +218,7 @@
DexMethod method,
Position callerPosition) {
super(lambdaGroupType, idField, fieldGenerator, method, callerPosition);
- this.objectInitializer = factory.objectMethods.constructor;
+ this.objectInitializer = factory.objectMembers.constructor;
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java
index 5af6c6f..8978657 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java
@@ -591,7 +591,7 @@
assert user.isInvokeDirect();
if (ignoreSuperClassInitInvoke
&& ListUtils.lastIndexMatching(invoke.inValues(), isAliasedValue) == 0
- && methodReferenced == factory.objectMethods.constructor) {
+ && methodReferenced == factory.objectMembers.constructor) {
// If we are inside candidate constructor and analyzing usages
// of the receiver, we want to ignore invocations of superclass
// constructor which will be removed after staticizing.