Dex2oat support for multiple oat file and image file outputs.

Multiple changes to dex2oat and the runtime to support a --multi-image
option. This generates a separate oat file and image file output for
each dex file input.

Change-Id: Ie1d6f0b8afa8aed5790065b8c2eb177990c60129
diff --git a/test/117-nopatchoat/nopatchoat.cc b/test/117-nopatchoat/nopatchoat.cc
index b6b1c43..1337442 100644
--- a/test/117-nopatchoat/nopatchoat.cc
+++ b/test/117-nopatchoat/nopatchoat.cc
@@ -35,8 +35,9 @@
   }
 
   static bool isRelocationDeltaZero() {
-    gc::space::ImageSpace* space = Runtime::Current()->GetHeap()->GetBootImageSpace();
-    return space != nullptr && space->GetImageHeader().GetPatchDelta() == 0;
+    std::vector<gc::space::ImageSpace*> spaces =
+        Runtime::Current()->GetHeap()->GetBootImageSpaces();
+    return !spaces.empty() && spaces[0]->GetImageHeader().GetPatchDelta() == 0;
   }
 
   static bool hasExecutableOat(jclass cls) {
diff --git a/test/137-cfi/cfi.cc b/test/137-cfi/cfi.cc
index 7762b2d..9bfe429 100644
--- a/test/137-cfi/cfi.cc
+++ b/test/137-cfi/cfi.cc
@@ -92,9 +92,10 @@
 // detecting this.
 #if __linux__
 static bool IsPicImage() {
-  gc::space::ImageSpace* image_space = Runtime::Current()->GetHeap()->GetBootImageSpace();
-  CHECK(image_space != nullptr);  // We should be running with an image.
-  const OatFile* oat_file = image_space->GetOatFile();
+  std::vector<gc::space::ImageSpace*> image_spaces =
+      Runtime::Current()->GetHeap()->GetBootImageSpaces();
+  CHECK(!image_spaces.empty());  // We should be running with an image.
+  const OatFile* oat_file = image_spaces[0]->GetOatFile();
   CHECK(oat_file != nullptr);     // We should have an oat file to go with the image.
   return oat_file->IsPic();
 }
diff --git a/test/464-checker-inline-sharpen-calls/src/Main.java b/test/464-checker-inline-sharpen-calls/src/Main.java
index 5080f142..2222e0f 100644
--- a/test/464-checker-inline-sharpen-calls/src/Main.java
+++ b/test/464-checker-inline-sharpen-calls/src/Main.java
@@ -16,6 +16,14 @@
 
 public final class Main {
 
+  public final static class Helper {
+    private int foo = 3;
+
+    public int getFoo() {
+        return foo;
+    }
+  }
+
   public void invokeVirtual() {
   }
 
@@ -31,25 +39,25 @@
     m.invokeVirtual();
   }
 
-  /// CHECK-START: int Main.inlineSharpenStringInvoke() ssa_builder (after)
-  /// CHECK-DAG:     <<Invoke:i\d+>>  InvokeVirtual
+  /// CHECK-START: int Main.inlineSharpenHelperInvoke() ssa_builder (after)
+  /// CHECK-DAG:     <<Invoke:i\d+>>  InvokeVirtual {{.*\.getFoo.*}}
   /// CHECK-DAG:                      Return [<<Invoke>>]
 
-  /// CHECK-START: int Main.inlineSharpenStringInvoke() inliner (after)
-  /// CHECK-NOT:                      InvokeStaticOrDirect
-  /// CHECK-NOT:                      InvokeVirtual
+  /// CHECK-START: int Main.inlineSharpenHelperInvoke() inliner (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect {{.*\.getFoo.*}}
+  /// CHECK-NOT:                      InvokeVirtual {{.*\.getFoo.*}}
 
-  /// CHECK-START: int Main.inlineSharpenStringInvoke() inliner (after)
+  /// CHECK-START: int Main.inlineSharpenHelperInvoke() inliner (after)
   /// CHECK-DAG:     <<Field:i\d+>>   InstanceFieldGet
   /// CHECK-DAG:                      Return [<<Field>>]
 
-  public static int inlineSharpenStringInvoke() {
-    return "Foo".length();
+  public static int inlineSharpenHelperInvoke() {
+    return new Helper().getFoo();
   }
 
   public static void main(String[] args) {
     inlineSharpenInvokeVirtual(new Main());
-    if (inlineSharpenStringInvoke() != 3) {
+    if (inlineSharpenHelperInvoke() != 3) {
       throw new Error("Expected 3");
     }
   }
diff --git a/test/490-checker-inline/src/Main.java b/test/490-checker-inline/src/Main.java
index 21a0189..2e2deea 100644
--- a/test/490-checker-inline/src/Main.java
+++ b/test/490-checker-inline/src/Main.java
@@ -39,7 +39,7 @@
   /// CHECK-DAG:     InvokeInterface
 
   /// CHECK-START: void Main.testMethod() inliner (after)
-  /// CHECK-NOT:     Invoke{{.*}}
+  /// CHECK-NOT:     Invoke{{.*Object\.<init>.*}}
 
   public static void testMethod() {
     createMain().invokeVirtual();
diff --git a/test/492-checker-inline-invoke-interface/src/Main.java b/test/492-checker-inline-invoke-interface/src/Main.java
index a8b6307..3106ce4 100644
--- a/test/492-checker-inline-invoke-interface/src/Main.java
+++ b/test/492-checker-inline-invoke-interface/src/Main.java
@@ -32,14 +32,14 @@
   }
 
   /// CHECK-START: void Main.main(java.lang.String[]) ssa_builder (after)
-  /// CHECK:           InvokeStaticOrDirect
+  /// CHECK:           InvokeStaticOrDirect {{.*Main.<init>.*}}
   /// CHECK:           InvokeInterface
 
   /// CHECK-START: void Main.main(java.lang.String[]) inliner (before)
   /// CHECK-NOT:       ClinitCheck
 
   /// CHECK-START: void Main.main(java.lang.String[]) inliner (after)
-  /// CHECK-NOT:       InvokeStaticOrDirect
+  /// CHECK-NOT:       InvokeStaticOrDirect {{.*Main.<init>.*}}
   /// CHECK-NOT:       InvokeVirtual
   /// CHECK-NOT:       InvokeInterface
 
diff --git a/test/493-checker-inline-invoke-interface/src/Main.java b/test/493-checker-inline-invoke-interface/src/Main.java
index 44b727f..171405c 100644
--- a/test/493-checker-inline-invoke-interface/src/Main.java
+++ b/test/493-checker-inline-invoke-interface/src/Main.java
@@ -36,7 +36,7 @@
   /// CHECK:           InvokeInterface
 
   /// CHECK-START: void Main.main(java.lang.String[]) inliner (after)
-  /// CHECK-NOT:       Invoke{{.*}}
+  /// CHECK-NOT:       Invoke{{.*Object\.<init>.*}}
   public static void main(String[] args) {
     Itf itf = bar();
     itf.foo();
diff --git a/test/536-checker-intrinsic-optimization/src/Main.java b/test/536-checker-intrinsic-optimization/src/Main.java
index 3f65d5a..be666e9 100644
--- a/test/536-checker-intrinsic-optimization/src/Main.java
+++ b/test/536-checker-intrinsic-optimization/src/Main.java
@@ -47,7 +47,7 @@
   }
 
   /// CHECK-START-X86: boolean Main.stringArgumentNotNull(java.lang.Object) disassembly (after)
-  /// CHECK:          InvokeVirtual
+  /// CHECK:          InvokeVirtual {{.*\.equals.*}}
   /// CHECK-NOT:      test
   public static boolean stringArgumentNotNull(Object obj) {
     obj.getClass();
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index afd833e..81cfb70 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -155,8 +155,14 @@
 ifeq ($(ART_TEST_RUN_TEST_NO_IMAGE),true)
   IMAGE_TYPES += no-image
 endif
+ifeq ($(ART_TEST_RUN_TEST_MULTI_IMAGE),true)
+  IMAGE_TYPES := multiimage
+endif
 ifeq ($(ART_TEST_PIC_IMAGE),true)
   IMAGE_TYPES += picimage
+  ifeq ($(ART_TEST_RUN_TEST_MULTI_IMAGE),true)
+    IMAGE_TYPES := multipicimage
+  endif
 endif
 PICTEST_TYPES := npictest
 ifeq ($(ART_TEST_PIC_TEST),true)
@@ -581,6 +587,19 @@
 TEST_ART_BROKEN_DEFAULT_HEAP_POISONING_RUN_TESTS :=
 TEST_ART_BROKEN_OPTIMIZING_HEAP_POISONING_RUN_TESTS :=
 
+
+# Tests broken by multi-image. b/26317072
+TEST_ART_BROKEN_MULTI_IMAGE_RUN_TESTS := \
+  476-checker-ctor-memory-barrier \
+  530-checker-lse
+
+ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \
+    $(COMPILER_TYPES),$(RELOCATE_TYPES),$(TRACE_TYPES),$(GC_TYPES),$(JNI_TYPES), \
+    $(IMAGE_TYPES), $(PICTEST_TYPES), $(DEBUGGABLE_TYPES), \
+    $(TEST_ART_BROKEN_MULTI_IMAGE_RUN_TESTS),  $(ALL_ADDRESS_SIZES))
+
+TEST_ART_BROKEN_MULTI_IMAGE_RUN_TESTS :=
+
 # Clear variables ahead of appending to them when defining tests.
 $(foreach target, $(TARGET_TYPES), $(eval ART_RUN_TEST_$(call name-to-var,$(target))_RULES :=))
 $(foreach target, $(TARGET_TYPES), \
@@ -839,7 +858,27 @@
           prereq_rule += $$(TARGET_CORE_IMAGE_$$(image_suffix)_pic_$(13))
         endif
       else
-        $$(error found $(9) expected $(IMAGE_TYPES))
+        ifeq ($(9),multiimage)
+          test_groups += ART_RUN_TEST_$$(uc_host_or_target)_IMAGE_RULES
+          run_test_options += --multi-image
+      		ifeq ($(1),host)
+        		prereq_rule += $$(HOST_CORE_IMAGE_$$(image_suffix)_no-pic_multi_$(13))
+      		else
+        		prereq_rule += $$(TARGET_CORE_IMAGE_$$(image_suffix)_no-pic_multi_$(13))
+      		endif
+        else
+          ifeq ($(9),multipicimage)
+            test_groups += ART_RUN_TEST_$$(uc_host_or_target)_PICIMAGE_RULES
+        		run_test_options += --pic-image --multi-image
+        		ifeq ($(1),host)
+          		prereq_rule += $$(HOST_CORE_IMAGE_$$(image_suffix)_pic_multi_$(13))
+        		else
+          		prereq_rule += $$(TARGET_CORE_IMAGE_$$(image_suffix)_pic_multi_$(13))
+        		endif
+          else
+            $$(error found $(9) expected $(IMAGE_TYPES))
+          endif
+        endif
       endif
     endif
   endif
diff --git a/test/common/runtime_state.cc b/test/common/runtime_state.cc
index 082c9b3..fd41fd2 100644
--- a/test/common/runtime_state.cc
+++ b/test/common/runtime_state.cc
@@ -56,7 +56,7 @@
 
 extern "C" JNIEXPORT jboolean JNICALL Java_Main_hasImage(JNIEnv* env ATTRIBUTE_UNUSED,
                                                          jclass cls ATTRIBUTE_UNUSED) {
-  return Runtime::Current()->GetHeap()->HasImageSpace();
+  return Runtime::Current()->GetHeap()->HasBootImageSpace();
 }
 
 // public static native boolean isImageDex2OatEnabled();
diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar
index 3efa6ff..6ff356f 100755
--- a/test/etc/run-test-jar
+++ b/test/etc/run-test-jar
@@ -361,13 +361,17 @@
 dex2oat_cmdline="true"
 mkdir_cmdline="mkdir -p ${DEX_LOCATION}/dalvik-cache/$ISA"
 
+# TODO: allow app-image to work with multi-image. b/26317072
+app_image=""
+# app_image="--app-image-file=$DEX_LOCATION/dalvik-cache/$ISA/$(echo $DEX_LOCATION/$TEST_NAME.jar/classes.art | cut -d/ -f 2- | sed "s:/:@:g")"
+
 if [ "$PREBUILD" = "y" ]; then
   dex2oat_cmdline="$INVOKE_WITH $ANDROID_ROOT/bin/dex2oatd \
                       $COMPILE_FLAGS \
                       --boot-image=${BOOT_IMAGE} \
                       --dex-file=$DEX_LOCATION/$TEST_NAME.jar \
                       --oat-file=$DEX_LOCATION/dalvik-cache/$ISA/$(echo $DEX_LOCATION/$TEST_NAME.jar/classes.dex | cut -d/ -f 2- | sed "s:/:@:g") \
-                      --app-image-file=$DEX_LOCATION/dalvik-cache/$ISA/$(echo $DEX_LOCATION/$TEST_NAME.jar/classes.art | cut -d/ -f 2- | sed "s:/:@:g") \
+                      ${app_image} \
                       --instruction-set=$ISA"
   if [ "x$INSTRUCTION_SET_FEATURES" != "x" ] ; then
     dex2oat_cmdline="${dex2oat_cmdline} --instruction-set-features=${INSTRUCTION_SET_FEATURES}"
diff --git a/test/run-test b/test/run-test
index ac2b52c..d076687 100755
--- a/test/run-test
+++ b/test/run-test
@@ -135,6 +135,7 @@
 have_image="yes"
 image_suffix=""
 pic_image_suffix=""
+multi_image_suffix=""
 android_root="/system"
 
 while true; do
@@ -184,6 +185,9 @@
     elif [ "x$1" = "x--pic-image" ]; then
         pic_image_suffix="-pic"
         shift
+    elif [ "x$1" = "x--multi-image" ]; then
+        multi_image_suffix="-multi"
+        shift
     elif [ "x$1" = "x--pic-test" ]; then
         run_args="${run_args} --pic-test"
         shift
@@ -470,12 +474,12 @@
             export ANDROID_HOST_OUT=${OUT_DIR:-$ANDROID_BUILD_TOP/out/}host/linux-x86
         fi
         guess_host_arch_name
-        run_args="${run_args} --boot ${ANDROID_HOST_OUT}/framework/core${image_suffix}${pic_image_suffix}.art"
+        run_args="${run_args} --boot ${ANDROID_HOST_OUT}/framework/core${image_suffix}${pic_image_suffix}${multi_image_suffix}.art"
         run_args="${run_args} --runtime-option -Djava.library.path=${ANDROID_HOST_OUT}/lib${suffix64}"
     else
         guess_target_arch_name
         run_args="${run_args} --runtime-option -Djava.library.path=/data/art-test/${target_arch_name}"
-        run_args="${run_args} --boot /data/art-test/core${image_suffix}${pic_image_suffix}.art"
+        run_args="${run_args} --boot /data/art-test/core${image_suffix}${pic_image_suffix}${multi_image_suffix}.art"
     fi
     if [ "$relocate" = "yes" ]; then
       run_args="${run_args} --relocate"
@@ -612,6 +616,8 @@
         echo "                          Set instruction-set-features for compilation."
         echo "    --pic-image           Use an image compiled with position independent code for the"
         echo "                          boot class path."
+        echo "    --multi-image         Use a set of images compiled with dex2oat multi-image for"
+        echo "                          the boot class path."
         echo "    --pic-test            Compile the test code position independent."
         echo "    --quiet               Don't print anything except failure messages"
     ) 1>&2  # Direct to stderr so usage is not printed if --quiet is set.