Fix instance-put to uninitialized-object after inlining check
Change-Id: I22bd0465f0dec1384cbc1b9a220e8cd21aaa522d
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 05c83da..6f524f6 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
@@ -522,27 +522,24 @@
List<InvokeDirect> initCallsOnThis = new ArrayList<>();
for (Instruction instruction : inlinee.instructions()) {
- if (instruction.isInvokeDirect()) {
+ if (instruction.isInvokeConstructor(appView.dexItemFactory())) {
InvokeDirect initCall = instruction.asInvokeDirect();
- DexMethod invokedMethod = initCall.getInvokedMethod();
- if (appView.dexItemFactory().isConstructor(invokedMethod)) {
- Value receiver = initCall.getReceiver().getAliasedValue();
- if (receiver == thisValue) {
- // The <init>() call of the constructor must be on the same class.
- if (calleeMethodHolder != invokedMethod.holder) {
- whyAreYouNotInliningReporter
- .reportUnsafeConstructorInliningDueToIndirectConstructorCall(initCall);
- return false;
- }
- initCallsOnThis.add(initCall);
+ Value receiver = initCall.getReceiver().getAliasedValue();
+ if (receiver == thisValue) {
+ // The <init>() call of the constructor must be on the same class.
+ if (calleeMethodHolder != initCall.getInvokedMethod().getHolderType()) {
+ whyAreYouNotInliningReporter
+ .reportUnsafeConstructorInliningDueToIndirectConstructorCall(initCall);
+ return false;
}
+ initCallsOnThis.add(initCall);
}
} else if (instruction.isInstancePut()) {
// Final fields may not be initialized outside of a constructor in the enclosing class.
InstancePut instancePut = instruction.asInstancePut();
DexField field = instancePut.getField();
DexEncodedField target = appView.appInfo().lookupInstanceTarget(field);
- if (target == null || target.accessFlags.isFinal()) {
+ if (target == null || target.isFinal()) {
whyAreYouNotInliningReporter.reportUnsafeConstructorInliningDueToFinalFieldAssignment(
instancePut);
return false;
@@ -550,29 +547,22 @@
}
}
- // Check that there are no uses of the uninitialized object before it gets initialized.
- int markingColor = inlinee.reserveMarkingColor();
- for (InvokeDirect initCallOnThis : initCallsOnThis) {
- BasicBlock block = initCallOnThis.getBlock();
- for (Instruction instruction : block.instructionsBefore(initCallOnThis)) {
- for (Value inValue : instruction.inValues()) {
- Value root = inValue.getAliasedValue();
- if (root == thisValue) {
- inlinee.returnMarkingColor(markingColor);
- whyAreYouNotInliningReporter.reportUnsafeConstructorInliningDueToUninitializedObjectUse(
- instruction);
- return false;
- }
+ if (initCallsOnThis.isEmpty()) {
+ // In the unusual case where there is no parent/forwarding constructor call, there must be no
+ // instance-put instructions that assign fields on the receiver.
+ for (Instruction user : thisValue.uniqueUsers()) {
+ if (user.isInstancePut() && user.asInstancePut().object().getAliasedValue() == thisValue) {
+ whyAreYouNotInliningReporter.reportUnsafeConstructorInliningDueToUninitializedObjectUse(
+ user);
+ return false;
}
}
- for (BasicBlock predecessor : block.getPredecessors()) {
- inlinee.markTransitivePredecessors(predecessor, markingColor);
- }
- }
-
- for (BasicBlock block : inlinee.blocks) {
- if (block.isMarked(markingColor)) {
- for (Instruction instruction : block.getInstructions()) {
+ } else {
+ // Check that there are no uses of the uninitialized object before it gets initialized.
+ int markingColor = inlinee.reserveMarkingColor();
+ for (InvokeDirect initCallOnThis : initCallsOnThis) {
+ BasicBlock block = initCallOnThis.getBlock();
+ for (Instruction instruction : block.instructionsBefore(initCallOnThis)) {
for (Value inValue : instruction.inValues()) {
Value root = inValue.getAliasedValue();
if (root == thisValue) {
@@ -583,10 +573,29 @@
}
}
}
+ for (BasicBlock predecessor : block.getPredecessors()) {
+ inlinee.markTransitivePredecessors(predecessor, markingColor);
+ }
}
+
+ for (BasicBlock block : inlinee.getBlocks()) {
+ if (block.isMarked(markingColor)) {
+ for (Instruction instruction : block.getInstructions()) {
+ for (Value inValue : instruction.inValues()) {
+ Value root = inValue.getAliasedValue();
+ if (root == thisValue) {
+ inlinee.returnMarkingColor(markingColor);
+ whyAreYouNotInliningReporter
+ .reportUnsafeConstructorInliningDueToUninitializedObjectUse(instruction);
+ return false;
+ }
+ }
+ }
+ }
+ }
+ inlinee.returnMarkingColor(markingColor);
}
- inlinee.returnMarkingColor(markingColor);
inliningIRProvider.cacheInliningIR(invoke, inlinee);
return true;
}