Merge "Only inline constructors if the receiver remains the this value."
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 a11d924..dfe10cf 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
@@ -20,6 +20,7 @@
 import com.android.tools.r8.ir.code.InstructionIterator;
 import com.android.tools.r8.ir.code.InstructionListIterator;
 import com.android.tools.r8.ir.code.Invoke;
+import com.android.tools.r8.ir.code.InvokeDirect;
 import com.android.tools.r8.ir.code.InvokeMethod;
 import com.android.tools.r8.ir.code.Value;
 import com.android.tools.r8.ir.code.ValueNumberGenerator;
@@ -272,12 +273,17 @@
       return true;
     }
 
+    // We cannot invoke <init> on other values than |this| on Dalvik 4.4.4. Compute whether
+    // the receiver to the call was the this value at the call-site.
+    boolean receiverOfInnerCallIsThisOfOuter = invoke.asInvokeDirect().getReceiver().isThis();
+
     // Don't allow inlining a constructor into a non-constructor if the first use of the
     // un-initialized object is not an argument of an invoke of <init>.
     // Also, we cannot inline a constructor if it initializes final fields, as such is only allowed
     // from within a constructor of the corresponding class.
     // Lastly, we can only inline a constructor, if its own <init> call is on the method's class. If
-    // we inline into a constructor, calls to super.<init> are also OK.
+    // we inline into a constructor, calls to super.<init> are also OK if the receiver of the
+    // super.<init> call is the this argument.
     InstructionIterator iterator = code.instructionIterator();
     Instruction instruction = iterator.next();
     // A constructor always has the un-initialized object as the first argument.
@@ -290,11 +296,17 @@
         if (instruction.isInvokeDirect() && !seenSuperInvoke) {
           DexMethod target = instruction.asInvokeDirect().getInvokedMethod();
           seenSuperInvoke = appInfo.dexItemFactory.isConstructor(target);
+          boolean callOnSupertypeOfThisInConstructor =
+              methodHolder.isImmediateSubtypeOf(target.holder)
+                  && instruction.asInvokeDirect().getReceiver() == unInitializedObject
+                  && receiverOfInnerCallIsThisOfOuter
+                  && methodIsConstructor;
           if (seenSuperInvoke
               // Calls to init on same class are always OK.
               && target.holder != methodHolder
-              // If we are inlining into a constructor, calls to superclass init are OK.
-              && (!methodHolder.isImmediateSubtypeOf(target.holder) || !methodIsConstructor)) {
+              // If we are inlining into a constructor, calls to superclass init are OK on the
+              // |this| value in the outer context.
+              && !callOnSupertypeOfThisInConstructor) {
             return false;
           }
         }