test: Modify 586-checker-null-array-get for javac/dx

Previously 1 of the methods were failing checker with javac/dx.
Move their old bytecode to a smali file to retain testing of those
optimizations.

Rewrite the checker tests in Main.java to use the javac/dx-generated
bytecode.

Test: art/test/run-test --64 --host --optimizing --build-with-javac-dx 586-checker-null-array-get
Bug: 62950048
Bug: 36902714
Change-Id: Ib320509422a358e116c24bb1b33442c0cf09ba25
diff --git a/test/586-checker-null-array-get/build b/test/586-checker-null-array-get/build
new file mode 100755
index 0000000..49292c9
--- /dev/null
+++ b/test/586-checker-null-array-get/build
@@ -0,0 +1,23 @@
+#!/bin/bash
+#
+# Copyright 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This checker test is incompatible with jack bytecode output,
+# so force it to use javac/dx.
+export USE_JACK=false
+# Also disable desugar because it is missing in jack platform builds.
+export DESUGAR=false
+
+./default-build "$@"
diff --git a/test/586-checker-null-array-get/smali/SmaliTests.smali b/test/586-checker-null-array-get/smali/SmaliTests.smali
new file mode 100644
index 0000000..f58af36
--- /dev/null
+++ b/test/586-checker-null-array-get/smali/SmaliTests.smali
@@ -0,0 +1,96 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class public LSmaliTests;
+.super Ljava/lang/Object;
+
+## CHECK-START: void SmaliTests.bar() load_store_elimination (after)
+## CHECK-DAG: <<Null:l\d+>>       NullConstant
+## CHECK-DAG: <<BoundType:l\d+>>  BoundType [<<Null>>]
+## CHECK-DAG: <<CheckL:l\d+>>     NullCheck [<<BoundType>>]
+## CHECK-DAG: <<GetL0:l\d+>>      ArrayGet [<<CheckL>>,{{i\d+}}]
+## CHECK-DAG: <<GetL1:l\d+>>      ArrayGet [<<CheckL>>,{{i\d+}}]
+## CHECK-DAG: <<GetL2:l\d+>>      ArrayGet [<<CheckL>>,{{i\d+}}]
+## CHECK-DAG: <<GetL3:l\d+>>      ArrayGet [<<CheckL>>,{{i\d+}}]
+## CHECK-DAG: <<CheckJ:l\d+>>     NullCheck [<<Null>>]
+## CHECK-DAG: <<GetJ0:j\d+>>      ArrayGet [<<CheckJ>>,{{i\d+}}]
+## CHECK-DAG: <<GetJ1:j\d+>>      ArrayGet [<<CheckJ>>,{{i\d+}}]
+## CHECK-DAG: <<GetJ2:j\d+>>      ArrayGet [<<CheckJ>>,{{i\d+}}]
+## CHECK-DAG: <<GetJ3:j\d+>>      ArrayGet [<<CheckJ>>,{{i\d+}}]
+.method public static bar()V
+    .registers 7
+
+    .prologue
+    const/4 v6, 0x3
+    const/4 v5, 0x2
+    const/4 v4, 0x1
+    const/4 v3, 0x0
+
+    # We create multiple accesses that will lead the bounds check
+    # elimination pass to add a HDeoptimize. Not having the bounds check helped
+    # the load store elimination think it could merge two ArrayGet with different
+    # types.
+
+    # String[] array = (String[])getNull();
+    invoke-static {}, LMain;->getNull()Ljava/lang/Object;
+    move-result-object v0
+    check-cast v0, [Ljava/lang/String;
+
+    # objectField = array[0];
+    aget-object v2, v0, v3
+    sput-object v2, LMain;->objectField:Ljava/lang/Object;
+    # objectField = array[1];
+    aget-object v2, v0, v4
+    sput-object v2, LMain;->objectField:Ljava/lang/Object;
+    # objectField = array[2];
+    aget-object v2, v0, v5
+    sput-object v2, LMain;->objectField:Ljava/lang/Object;
+    # objectField = array[3];
+    aget-object v2, v0, v6
+    sput-object v2, LMain;->objectField:Ljava/lang/Object;
+
+    # long[] longArray = getLongArray();
+    invoke-static {}, LMain;->getLongArray()[J
+    move-result-object v1
+
+    # longField = longArray[0];
+    aget-wide v2, v1, v3
+    sput-wide v2, LMain;->longField:J
+    # longField = longArray[1];
+    aget-wide v2, v1, v4
+    sput-wide v2, LMain;->longField:J
+    # longField = longArray[2];
+    aget-wide v2, v1, v5
+    sput-wide v2, LMain;->longField:J
+    # longField = longArray[3];
+    aget-wide v2, v1, v6
+    sput-wide v2, LMain;->longField:J
+
+    return-void
+.end method
+
+
+# static fields
+.field static doThrow:Z # boolean
+
+# direct methods
+.method static constructor <clinit>()V
+    .registers 1
+
+    .prologue
+    # doThrow = false
+    const/4 v0, 0x0
+    sput-boolean v0, LSmaliTests;->doThrow:Z
+    return-void
+.end method
diff --git a/test/586-checker-null-array-get/src/Main.java b/test/586-checker-null-array-get/src/Main.java
index 0ea7d34..09ebff1 100644
--- a/test/586-checker-null-array-get/src/Main.java
+++ b/test/586-checker-null-array-get/src/Main.java
@@ -14,6 +14,9 @@
  * limitations under the License.
  */
 
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+
 class Test1 {
   int[] iarr;
 }
@@ -29,6 +32,18 @@
   public static Test1 getNullTest1() { return null; }
   public static Test2 getNullTest2() { return null; }
 
+  public static void $noinline$runSmaliTest(String name) throws Throwable {
+    try {
+      Class<?> c = Class.forName("SmaliTests");
+      Method m = c.getMethod(name);
+      m.invoke(null);
+    } catch (InvocationTargetException ex) {
+      throw ex.getCause(); // re-raise expected exception.
+    } catch (Exception ex) {
+      throw new Error(ex);
+    }
+  }
+
   public static void main(String[] args) {
     try {
       foo();
@@ -43,6 +58,15 @@
       // Expected.
     }
     try {
+      $noinline$runSmaliTest("bar");
+      throw new Error("Expected NullPointerException");
+    } catch (NullPointerException e) {
+      // Expected.
+    } catch (Throwable t) {
+      throw new Error("Unexpected Throwable", t);
+    }
+
+    try {
       test1();
       throw new Error("Expected NullPointerException");
     } catch (NullPointerException e) {
@@ -62,7 +86,8 @@
 
   /// CHECK-START: void Main.bar() load_store_elimination (after)
   /// CHECK-DAG: <<Null:l\d+>>       NullConstant
-  /// CHECK-DAG: <<BoundType:l\d+>>  BoundType [<<Null>>]
+  /// CHECK-DAG: <<BoundFirst:l\d+>> BoundType [<<Null>>]
+  /// CHECK-DAG: <<BoundType:l\d+>>  BoundType [<<BoundFirst>>]
   /// CHECK-DAG: <<CheckL:l\d+>>     NullCheck [<<BoundType>>]
   /// CHECK-DAG: <<GetL0:l\d+>>      ArrayGet [<<CheckL>>,{{i\d+}}]
   /// CHECK-DAG: <<GetL1:l\d+>>      ArrayGet [<<CheckL>>,{{i\d+}}]
diff --git a/test/knownfailures.json b/test/knownfailures.json
index ad6d390..df8fa60 100644
--- a/test/knownfailures.json
+++ b/test/knownfailures.json
@@ -603,7 +603,6 @@
     {
         "tests": [
             "567-checker-compare",
-            "586-checker-null-array-get",
             "633-checker-rtp-getclass"
         ],
         "description": "Checker tests failing when run with --build-with-javac-dx.",