ART: Add complex UnresolvedMergedType test case

Add a test case that stresses the verifier. Add dex2oat timeout
to the host prebuild configuration.

Bug: 22881413
Change-Id: Ic4a0d16a4dc69f3d43bac40a560b6e6884df263f
diff --git a/test/800-smali/expected.txt b/test/800-smali/expected.txt
index 728ccea..884f280 100644
--- a/test/800-smali/expected.txt
+++ b/test/800-smali/expected.txt
@@ -37,4 +37,5 @@
 b/22411633 (4)
 b/22411633 (5)
 b/22777307
+b/22881413
 Done!
diff --git a/test/800-smali/smali/b_22881413.smali b/test/800-smali/smali/b_22881413.smali
new file mode 100644
index 0000000..f624734
--- /dev/null
+++ b/test/800-smali/smali/b_22881413.smali
@@ -0,0 +1,291 @@
+.class public LB22881413;
+.super Ljava/lang/Object;
+
+# A couple of fields to allow "loading" resolved and unresolved types. Use non-final classes to
+# avoid automatically getting precise reference types.
+.field private static res1:Ljava/lang/Number;
+.field private static res2:Ljava/lang/ClassLoader;
+.field private static res3:Ljava/lang/Package;
+.field private static res4:Ljava/lang/RuntimeException;
+.field private static res5:Ljava/lang/Exception;
+.field private static res6:Ljava/util/ArrayList;
+.field private static res7:Ljava/util/LinkedList;
+.field private static res8:Ljava/lang/Thread;
+.field private static res9:Ljava/lang/ThreadGroup;
+.field private static res10:Ljava/lang/Runtime;
+
+.field private static unres1:La/b/c/d1;
+.field private static unres2:La/b/c/d2;
+.field private static unres3:La/b/c/d3;
+.field private static unres4:La/b/c/d4;
+.field private static unres5:La/b/c/d5;
+.field private static unres6:La/b/c/d6;
+.field private static unres7:La/b/c/d7;
+.field private static unres8:La/b/c/d8;
+.field private static unres9:La/b/c/d9;
+.field private static unres10:La/b/c/d10;
+
+.field private static unresBase0:La/b/c/dBase0;
+.field private static unresBase1:La/b/c/dBase1;
+.field private static unresBase2:La/b/c/dBase2;
+.field private static unresBase3:La/b/c/dBase3;
+.field private static unresBase4:La/b/c/dBase4;
+.field private static unresBase5:La/b/c/dBase5;
+.field private static unresBase6:La/b/c/dBase6;
+.field private static unresBase7:La/b/c/dBase7;
+.field private static unresBase8:La/b/c/dBase8;
+
+# Empty, ignore this. We want to see if the other method can be verified in a reasonable amount of
+# time.
+.method public static run()V
+.registers 2
+       return-void
+.end method
+
+.method public static foo(IZZ) V
+.registers 11
+       # v8 = int, v9 = boolean, v10 = boolean
+
+       sget-object v0, LB22881413;->unresBase0:La/b/c/dBase0;
+       const v1, 0
+       const v2, 0
+
+# We're trying to create something like this (with more loops to amplify things).
+#
+# v0 = Unresolved1
+# while (something) {
+#
+#   [Repeatedly]
+#   if (cond) {
+#     v0 = ResolvedX;
+#   } else {
+#     v0 = UnresolvedX;
+#   }
+#
+#   v0 = Unresolved2
+# };
+#
+# Important points:
+#   1) Use a while, so that the end of the loop is a goto. That way, the merging of outer-loop
+#      unresolved classes is postponed.
+#   2) Put the else cases after all if cases. That way there are backward gotos that will lead
+#      to stabilization loops in the body.
+#
+
+:Loop1
+
+       const v6, 0
+       add-int/lit16 v8, v8, -1
+       if-ge v8, v6, :Loop1End
+
+:Loop2
+
+       const v6, 0
+       add-int/lit16 v8, v8, -1
+       if-ge v8, v6, :Loop2End
+
+:Loop3
+
+       const v6, 0
+       add-int/lit16 v8, v8, -1
+       if-ge v8, v6, :Loop3End
+
+:Loop4
+
+       const v6, 0
+       add-int/lit16 v8, v8, -1
+       if-ge v8, v6, :Loop4End
+
+:Loop5
+
+       const v6, 0
+       add-int/lit16 v8, v8, -1
+       if-ge v8, v6, :Loop5End
+
+:Loop6
+
+       const v6, 0
+       add-int/lit16 v8, v8, -1
+       if-ge v8, v6, :Loop6End
+
+:Loop7
+
+       const v6, 0
+       add-int/lit16 v8, v8, -1
+       if-ge v8, v6, :Loop7End
+
+:Loop8
+
+       const v6, 0
+       add-int/lit16 v8, v8, -1
+       if-ge v8, v6, :Loop8End
+
+# Prototype:
+#
+#       if-eqz v9, :ElseX
+#       sget-object v0, LB22881413;->res1:Ljava/lang/Number;
+#:JoinX
+#
+# And somewhere at the end
+#
+#:ElseX
+#       sget-object v0, LB22881413;->unresX:La/b/c/dX;
+#       goto :JoinX
+#
+#
+
+       if-eqz v10, :Join1
+       if-eqz v9, :Else1
+       sget-object v0, LB22881413;->res1:Ljava/lang/Number;
+:Join1
+
+
+       if-eqz v10, :Join2
+       if-eqz v9, :Else2
+       sget-object v0, LB22881413;->res2:Ljava/lang/ClassLoader;
+:Join2
+
+
+       if-eqz v10, :Join3
+       if-eqz v9, :Else3
+       sget-object v0, LB22881413;->res3:Ljava/lang/Package;
+:Join3
+
+
+       if-eqz v10, :Join4
+       if-eqz v9, :Else4
+       sget-object v0, LB22881413;->res4:Ljava/lang/RuntimeException;
+:Join4
+
+
+       if-eqz v10, :Join5
+       if-eqz v9, :Else5
+       sget-object v0, LB22881413;->res5:Ljava/lang/Exception;
+:Join5
+
+
+       if-eqz v10, :Join6
+       if-eqz v9, :Else6
+       sget-object v0, LB22881413;->res6:Ljava/util/ArrayList;
+:Join6
+
+
+       if-eqz v10, :Join7
+       if-eqz v9, :Else7
+       sget-object v0, LB22881413;->res7:Ljava/util/LinkedList;
+:Join7
+
+
+       if-eqz v10, :Join8
+       if-eqz v9, :Else8
+       sget-object v0, LB22881413;->res8:Ljava/lang/Thread;
+:Join8
+
+
+       if-eqz v10, :Join9
+       if-eqz v9, :Else9
+       sget-object v0, LB22881413;->res9:Ljava/lang/ThreadGroup;
+:Join9
+
+
+       if-eqz v10, :Join10
+       if-eqz v9, :Else10
+       sget-object v0, LB22881413;->res10:Ljava/lang/Runtime;
+:Join10
+
+
+       goto :InnerMostLoopEnd
+
+:Else1
+       sget-object v0, LB22881413;->unres1:La/b/c/d1;
+       goto :Join1
+
+:Else2
+       sget-object v0, LB22881413;->unres2:La/b/c/d2;
+       goto :Join2
+
+:Else3
+       sget-object v0, LB22881413;->unres3:La/b/c/d3;
+       goto :Join3
+
+:Else4
+       sget-object v0, LB22881413;->unres4:La/b/c/d4;
+       goto :Join4
+
+:Else5
+       sget-object v0, LB22881413;->unres5:La/b/c/d5;
+       goto :Join5
+
+:Else6
+       sget-object v0, LB22881413;->unres6:La/b/c/d6;
+       goto :Join6
+
+:Else7
+       sget-object v0, LB22881413;->unres7:La/b/c/d7;
+       goto :Join7
+
+:Else8
+       sget-object v0, LB22881413;->unres8:La/b/c/d8;
+       goto :Join8
+
+:Else9
+       sget-object v0, LB22881413;->unres9:La/b/c/d9;
+       goto :Join9
+
+:Else10
+       sget-object v0, LB22881413;->unres10:La/b/c/d10;
+       goto :Join10
+
+:InnerMostLoopEnd
+
+       # Loop 8 end of body.
+       sget-object v0, LB22881413;->unresBase8:La/b/c/dBase8;
+       goto :Loop8
+
+:Loop8End
+
+       # Loop 7 end of body.
+       sget-object v0, LB22881413;->unresBase7:La/b/c/dBase7;
+       goto :Loop7
+
+:Loop7End
+
+       # Loop 6 end of body.
+       sget-object v0, LB22881413;->unresBase6:La/b/c/dBase6;
+       goto :Loop6
+
+:Loop6End
+
+       # Loop 5 end of body
+       sget-object v0, LB22881413;->unresBase5:La/b/c/dBase5;
+       goto :Loop5
+
+:Loop5End
+
+       # Loop 4 end of body
+       sget-object v0, LB22881413;->unresBase4:La/b/c/dBase4;
+       goto :Loop4
+
+:Loop4End
+
+       # Loop 3 end of body
+       sget-object v0, LB22881413;->unresBase3:La/b/c/dBase3;
+       goto :Loop3
+
+:Loop3End
+
+       # Loop 2 end of body
+       sget-object v0, LB22881413;->unresBase2:La/b/c/dBase2;
+       goto :Loop2
+
+:Loop2End
+
+       # Loop 1 end of body
+       sget-object v0, LB22881413;->unresBase1:La/b/c/dBase1;
+       goto :Loop1
+
+:Loop1End
+
+       return-void
+
+.end method
diff --git a/test/800-smali/src/Main.java b/test/800-smali/src/Main.java
index 438e214..e1ac749 100644
--- a/test/800-smali/src/Main.java
+++ b/test/800-smali/src/Main.java
@@ -121,6 +121,7 @@
                 null, null));
         testCases.add(new TestCase("b/22777307", "B22777307", "run", null, new InstantiationError(),
                 null));
+        testCases.add(new TestCase("b/22881413", "B22881413", "run", null, null, null));
     }
 
     public void runTests() {
diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar
index 750a29f..a1af577 100755
--- a/test/etc/run-test-jar
+++ b/test/etc/run-test-jar
@@ -338,6 +338,17 @@
   if [ "x$INSTRUCTION_SET_FEATURES" != "x" ] ; then
     dex2oat_cmdline="${dex2oat_cmdline} --instruction-set-features=${INSTRUCTION_SET_FEATURES}"
   fi
+
+  # Add in a timeout. This is important for testing the compilation/verification time of
+  # pathological cases.
+  # Note: as we don't know how decent targets are (e.g., emulator), only do this on the host for
+  #       now. We should try to improve this.
+  #       The current value is rather arbitrary. run-tests should compile quickly.
+  if [ "$HOST" != "n" ]; then
+    # Use SIGRTMIN+2 to try to dump threads.
+    # Use -k 1m to SIGKILL it a minute later if it hasn't ended.
+    dex2oat_cmdline="timeout -k 1m -s SIGRTMIN+2 1m ${dex2oat_cmdline}"
+  fi
 fi
 
 DALVIKVM_ISA_FEATURES_ARGS=""