Merge "ART: X86: Improve multiply in div/rem by literal"
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index ad436d0..1e64c00 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -785,7 +785,19 @@
   return NULL;
 }
 
-static bool LoadMultiDexFilesFromOatFile(const OatFile* oat_file, const char* dex_location,
+
+// Loads all multi dex files from the given oat file returning true on success.
+//
+// Parameters:
+//   oat_file - the oat file to load from
+//   dex_location - the dex location used to generate the oat file
+//   dex_location_checksum - the checksum of the dex_location (may be null for pre-opted files)
+//   generated - whether or not the oat_file existed before or was just (re)generated
+//   error_msgs - any error messages will be appended here
+//   dex_files - the loaded dex_files will be appended here (only if the loading succeeds)
+static bool LoadMultiDexFilesFromOatFile(const OatFile* oat_file,
+                                         const char* dex_location,
+                                         const uint32_t* dex_location_checksum,
                                          bool generated,
                                          std::vector<std::string>* error_msgs,
                                          std::vector<const DexFile*>* dex_files) {
@@ -800,12 +812,20 @@
     std::string next_name_str = DexFile::GetMultiDexClassesDexName(i, dex_location);
     const char* next_name = next_name_str.c_str();
 
-    uint32_t dex_location_checksum;
-    uint32_t* dex_location_checksum_pointer = &dex_location_checksum;
+    uint32_t next_location_checksum;
+    uint32_t* next_location_checksum_pointer = &next_location_checksum;
     std::string error_msg;
-    if (!DexFile::GetChecksum(next_name, dex_location_checksum_pointer, &error_msg)) {
+    if ((i == 0) && (strcmp(next_name, dex_location) == 0)) {
+      // When i=0 the multidex name should be the same as the location name. We already have the
+      // checksum it so we don't need to recompute it.
+      if (dex_location_checksum == nullptr) {
+        next_location_checksum_pointer = nullptr;
+      } else {
+        next_location_checksum = *dex_location_checksum;
+      }
+    } else if (!DexFile::GetChecksum(next_name, next_location_checksum_pointer, &error_msg)) {
       DCHECK_EQ(false, i == 0 && generated);
-      dex_location_checksum_pointer = nullptr;
+      next_location_checksum_pointer = nullptr;
     }
 
     const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(next_name, nullptr, false);
@@ -814,7 +834,7 @@
       if (i == 0 && generated) {
         std::string error_msg;
         error_msg = StringPrintf("\nFailed to find dex file '%s' (checksum 0x%x) in generated out "
-                                 " file'%s'", dex_location, dex_location_checksum,
+                                 " file'%s'", dex_location, next_location_checksum,
                                  oat_file->GetLocation().c_str());
         error_msgs->push_back(error_msg);
       }
@@ -823,8 +843,8 @@
 
     // Checksum test. Test must succeed when generated.
     success = !generated;
-    if (dex_location_checksum_pointer != nullptr) {
-      success = dex_location_checksum == oat_dex_file->GetDexFileLocationChecksum();
+    if (next_location_checksum_pointer != nullptr) {
+      success = next_location_checksum == oat_dex_file->GetDexFileLocationChecksum();
     }
 
     if (success) {
@@ -840,7 +860,7 @@
     // When we generated the file, we expect success, or something is terribly wrong.
     CHECK_EQ(false, generated && !success)
         << "dex_location=" << next_name << " oat_location=" << oat_file->GetLocation().c_str()
-        << std::hex << " dex_location_checksum=" << dex_location_checksum
+        << std::hex << " dex_location_checksum=" << next_location_checksum
         << " OatDexFile::GetLocationChecksum()=" << oat_dex_file->GetDexFileLocationChecksum();
   }
 
@@ -877,6 +897,7 @@
   bool have_checksum = true;
   std::string checksum_error_msg;
   if (!DexFile::GetChecksum(dex_location, dex_location_checksum_pointer, &checksum_error_msg)) {
+    // This happens for pre-opted files since the corresponding dex files are no longer on disk.
     dex_location_checksum_pointer = nullptr;
     have_checksum = false;
   }
@@ -942,8 +963,9 @@
 
   // 3) If we have an oat file, check all contained multidex files for our dex_location.
   // Note: LoadMultiDexFilesFromOatFile will check for nullptr in the first argument.
-  bool success = LoadMultiDexFilesFromOatFile(open_oat_file.get(), dex_location, false, error_msgs,
-                                              dex_files);
+  bool success = LoadMultiDexFilesFromOatFile(open_oat_file.get(), dex_location,
+                                              dex_location_checksum_pointer,
+                                              false, error_msgs, dex_files);
   if (success) {
     const OatFile* oat_file = open_oat_file.release();  // Avoid deleting it.
     if (needs_registering) {
@@ -1004,8 +1026,8 @@
   }
 
   // Try to load again, but stronger checks.
-  success = LoadMultiDexFilesFromOatFile(open_oat_file.get(), dex_location, true, error_msgs,
-                                         dex_files);
+  success = LoadMultiDexFilesFromOatFile(open_oat_file.get(), dex_location, dex_location_checksum_pointer,
+                                         true, error_msgs, dex_files);
   if (success) {
     RegisterOatFile(open_oat_file.release());
     return true;
@@ -1189,24 +1211,18 @@
     return false;
   }
 
-  if (dex_location_checksum != oat_dex_file->GetDexFileLocationChecksum()) {
-    *error_msg = StringPrintf("oat file '%s' mismatch (0x%x) with '%s' (0x%x)",
-                              oat_file->GetLocation().c_str(),
-                              oat_dex_file->GetDexFileLocationChecksum(),
-                              dex_location, dex_location_checksum);
-    return false;
-  }
+  DCHECK_EQ(dex_location_checksum, oat_dex_file->GetDexFileLocationChecksum());
   return true;
 }
 
 bool ClassLinker::VerifyOatWithDexFile(const OatFile* oat_file,
                                        const char* dex_location,
+                                       const uint32_t* dex_location_checksum,
                                        std::string* error_msg) {
   CHECK(oat_file != nullptr);
   CHECK(dex_location != nullptr);
   std::unique_ptr<const DexFile> dex_file;
-  uint32_t dex_location_checksum;
-  if (!DexFile::GetChecksum(dex_location, &dex_location_checksum, error_msg)) {
+  if (dex_location_checksum == nullptr) {
     // If no classes.dex found in dex_location, it has been stripped or is corrupt, assume oat is
     // up-to-date. This is the common case in user builds for jar's and apk's in the /system
     // directory.
@@ -1219,13 +1235,13 @@
     }
     dex_file.reset(oat_dex_file->OpenDexFile(error_msg));
   } else {
-    bool verified = VerifyOatAndDexFileChecksums(oat_file, dex_location, dex_location_checksum,
+    bool verified = VerifyOatAndDexFileChecksums(oat_file, dex_location, *dex_location_checksum,
                                                  kRuntimeISA, error_msg);
     if (!verified) {
       return false;
     }
     dex_file.reset(oat_file->GetOatDexFile(dex_location,
-                                           &dex_location_checksum)->OpenDexFile(error_msg));
+                                           dex_location_checksum)->OpenDexFile(error_msg));
   }
   return dex_file.get() != nullptr;
 }
@@ -1249,7 +1265,8 @@
                                        dex_location));
     return nullptr;
   } else if (oat_file->IsExecutable() &&
-             !VerifyOatWithDexFile(oat_file.get(), dex_location, &error_msg)) {
+             !VerifyOatWithDexFile(oat_file.get(), dex_location,
+                                   dex_location_checksum, &error_msg)) {
     error_msgs->push_back(StringPrintf("Failed to verify oat file '%s' found for dex location "
                                        "'%s': %s", oat_file->GetLocation().c_str(), dex_location,
                                        error_msg.c_str()));
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 7750c8e..d1f5aa0 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -613,9 +613,18 @@
                                                              bool* obsolete_file_cleanup_failed)
       LOCKS_EXCLUDED(dex_lock_, Locks::mutator_lock_);
 
-  // verify an oat file with the given dex file. Will return false when the dex file could not be
-  // verified. Will return true otherwise.
+  // Verifies:
+  //  - that the oat file contains the dex file (with a matching checksum, which may be null if the
+  // file was pre-opted)
+  //  - the checksums of the oat file (against the image space)
+  //  - the checksum of the dex file against dex_location_checksum
+  //  - that the dex file can be opened
+  // Returns true iff all verification succeed.
+  //
+  // The dex_location is the dex location as stored in the oat file header.
+  // (see DexFile::GetDexCanonicalLocation for a description of location conventions)
   bool VerifyOatWithDexFile(const OatFile* oat_file, const char* dex_location,
+                            const uint32_t* dex_location_checksum,
                             std::string* error_msg);
 
   mirror::ArtMethod* CreateProxyConstructor(Thread* self, ConstHandle<mirror::Class> klass,
diff --git a/runtime/fault_handler.cc b/runtime/fault_handler.cc
index cc1038c..47696f9 100644
--- a/runtime/fault_handler.cc
+++ b/runtime/fault_handler.cc
@@ -186,8 +186,6 @@
   action.sa_restorer = nullptr;
 #endif
 
-  bool signal_handled = false;
-
   // Catch SIGSEGV and SIGABRT to invoke our nested handler
   int e1 = sigaction(SIGSEGV, &action, &oldsegvaction);
   int e2 = sigaction(SIGABRT, &action, &oldabortaction);
@@ -200,8 +198,12 @@
     if (setjmp(*self->GetNestedSignalState()) == 0) {
       for (const auto& handler : other_handlers_) {
         if (handler->Action(sig, info, context)) {
-          signal_handled = true;
-          break;
+          // Restore the signal handlers, reinit the fault manager and return.  Signal was
+          // handled.
+          sigaction(SIGSEGV, &oldsegvaction, nullptr);
+          sigaction(SIGABRT, &oldabortaction, nullptr);
+          fault_manager.Init();
+          return;
         }
       }
     } else {
@@ -216,13 +218,11 @@
   // Now put the fault manager back in place.
   fault_manager.Init();
 
-  if (!signal_handled) {
-    // Set a breakpoint in this function to catch unhandled signals.
-    art_sigsegv_fault();
+  // Set a breakpoint in this function to catch unhandled signals.
+  art_sigsegv_fault();
 
-    // Pass this on to the next handler in the chain, or the default if none.
-    InvokeUserSignalHandler(sig, info, context);
-  }
+  // Pass this on to the next handler in the chain, or the default if none.
+  InvokeUserSignalHandler(sig, info, context);
 }
 
 void FaultManager::AddHandler(FaultHandler* handler, bool generated_code) {
diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc
index df6055d..c3c8c25 100644
--- a/runtime/native/dalvik_system_ZygoteHooks.cc
+++ b/runtime/native/dalvik_system_ZygoteHooks.cc
@@ -17,9 +17,11 @@
 #include <stdlib.h>
 
 #include "debugger.h"
+#include "instruction_set.h"
 #include "java_vm_ext.h"
 #include "jni_internal.h"
 #include "JNIHelp.h"
+#include "ScopedUtfChars.h"
 #include "thread-inl.h"
 
 #if defined(HAVE_PRCTL)
@@ -102,17 +104,27 @@
   return reinterpret_cast<jlong>(self);
 }
 
-static void ZygoteHooks_nativePostForkChild(JNIEnv* env, jclass, jlong token, jint debug_flags) {
+static void ZygoteHooks_nativePostForkChild(JNIEnv* env, jclass, jlong token, jint debug_flags,
+                                            jstring instruction_set) {
   Thread* thread = reinterpret_cast<Thread*>(token);
   // Our system thread ID, etc, has changed so reset Thread state.
   thread->InitAfterFork();
   EnableDebugFeatures(debug_flags);
-  Runtime::Current()->DidForkFromZygote();
+
+  Runtime::NativeBridgeAction action = Runtime::NativeBridgeAction::kUnload;
+  if (instruction_set != nullptr) {
+    ScopedUtfChars isa_string(env, instruction_set);
+    InstructionSet isa = GetInstructionSetFromString(isa_string.c_str());
+    if (isa != kNone && isa != kRuntimeISA) {
+      action = Runtime::NativeBridgeAction::kInitialize;
+    }
+  }
+  Runtime::Current()->DidForkFromZygote(action);
 }
 
 static JNINativeMethod gMethods[] = {
   NATIVE_METHOD(ZygoteHooks, nativePreFork, "()J"),
-  NATIVE_METHOD(ZygoteHooks, nativePostForkChild, "(JI)V"),
+  NATIVE_METHOD(ZygoteHooks, nativePostForkChild, "(JILjava/lang/String;)V"),
 };
 
 void register_dalvik_system_ZygoteHooks(JNIEnv* env) {
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 5adb5d0..89ad505 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -428,7 +428,7 @@
       return false;
     }
   } else {
-    DidForkFromZygote();
+    DidForkFromZygote(NativeBridgeAction::kInitialize);
   }
 
   StartDaemonThreads();
@@ -506,9 +506,19 @@
 #endif
 }
 
-void Runtime::DidForkFromZygote() {
+void Runtime::DidForkFromZygote(NativeBridgeAction action) {
   is_zygote_ = false;
 
+  switch (action) {
+    case NativeBridgeAction::kUnload:
+      android::UnloadNativeBridge();
+      break;
+
+    case NativeBridgeAction::kInitialize:
+      android::InitializeNativeBridge();
+      break;
+  }
+
   // Create the thread pool.
   heap_->CreateThreadPool();
 
@@ -833,8 +843,34 @@
   self->ClearException();
 
   // Look for a native bridge.
+  //
+  // The intended flow here is, in the case of a running system:
+  //
+  // Runtime::Init() (zygote):
+  //   LoadNativeBridge -> dlopen from cmd line parameter.
+  //  |
+  //  V
+  // Runtime::Start() (zygote):
+  //   No-op wrt native bridge.
+  //  |
+  //  | start app
+  //  V
+  // DidForkFromZygote(action)
+  //   action = kUnload -> dlclose native bridge.
+  //   action = kInitialize -> initialize library
+  //
+  //
+  // The intended flow here is, in the case of a simple dalvikvm call:
+  //
+  // Runtime::Init():
+  //   LoadNativeBridge -> dlopen from cmd line parameter.
+  //  |
+  //  V
+  // Runtime::Start():
+  //   DidForkFromZygote(kInitialize) -> try to initialize any native bridge given.
+  //   No-op wrt native bridge.
   native_bridge_library_filename_ = options->native_bridge_library_filename_;
-  android::SetupNativeBridge(native_bridge_library_filename_.c_str(), &native_bridge_art_callbacks_);
+  android::LoadNativeBridge(native_bridge_library_filename_.c_str(), &native_bridge_art_callbacks_);
   VLOG(startup) << "Runtime::Setup native bridge library: "
                 << (native_bridge_library_filename_.empty() ?
                     "(empty)" : native_bridge_library_filename_);
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 632806f..a0993ca 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -393,9 +393,13 @@
 
   void SetStatsEnabled(bool new_state);
 
+  enum class NativeBridgeAction {  // private
+    kUnload,
+    kInitialize
+  };
   void PreZygoteFork();
   bool InitZygote();
-  void DidForkFromZygote();
+  void DidForkFromZygote(NativeBridgeAction action);
 
   const instrumentation::Instrumentation* GetInstrumentation() const {
     return &instrumentation_;
diff --git a/test/036-finalizer/expected.txt b/test/036-finalizer/expected.txt
index a2a74fc..36fa5f8 100644
--- a/test/036-finalizer/expected.txt
+++ b/test/036-finalizer/expected.txt
@@ -11,3 +11,4 @@
 sleep
 reborn: [FinalizerTest message=nothing, finalized=false]
 wimp: null
+Finalized 1024 / 1024
diff --git a/test/036-finalizer/src/Main.java b/test/036-finalizer/src/Main.java
index 328425f..390472d 100644
--- a/test/036-finalizer/src/Main.java
+++ b/test/036-finalizer/src/Main.java
@@ -120,6 +120,39 @@
 
         System.out.println("reborn: " + FinalizerTest.mReborn);
         System.out.println("wimp: " + wimpString(wimp));
+        // Test runFinalization with multiple objects.
+        runFinalizationTest();
+    }
+
+    static class FinalizeCounter {
+      private static Object finalizeLock = new Object();
+      private static volatile int finalizeCount = 0;
+      private int index;
+      static int getCount() {
+        return finalizeCount;
+      }
+      FinalizeCounter(int index) {
+        this.index = index;
+      }
+      protected void finalize() {
+        synchronized(finalizeLock) {
+          ++finalizeCount;
+        }
+      }
+    }
+
+    private static void runFinalizationTest() {
+      int count = 1024;
+      Object[] objs = new Object[count];
+      for (int i = 0; i < count; ++i) {
+        objs[i] = new FinalizeCounter(i);
+      }
+      for (int i = 0; i < count; ++i) {
+        objs[i] = null;
+      }
+      System.gc();
+      System.runFinalization();
+      System.out.println("Finalized " + FinalizeCounter.getCount() + " / "  + count);
     }
 
     public static class FinalizerTest {
diff --git a/test/115-native-bridge/expected.txt b/test/115-native-bridge/expected.txt
index 5b41606..808d968 100644
--- a/test/115-native-bridge/expected.txt
+++ b/test/115-native-bridge/expected.txt
@@ -1,5 +1,5 @@
-Ready for native bridge tests.
 Native bridge initialized.
+Ready for native bridge tests.
 Checking for support.
 Getting trampoline for JNI_OnLoad with shorty (null).
 Test ART callbacks: all JNI function number is 9.
diff --git a/test/etc/host-run-test-jar b/test/etc/host-run-test-jar
index 54a0865..4485590 100755
--- a/test/etc/host-run-test-jar
+++ b/test/etc/host-run-test-jar
@@ -208,7 +208,16 @@
 fi
 
 cd $ANDROID_BUILD_TOP
-# If we are execing /bin/false we might not be on the same ISA as libsigchain.so
-# ld.so will helpfully warn us of this. Unfortunately this messes up our error
-# checking so we will just filter out the error with a grep.
-$mkdir_cmd && $prebuild_cmd && LD_PRELOAD=libsigchain.so $cmdline "$@" 2>&1 | grep -v -E "^ERROR: ld\.so: object '.+\.so' from LD_PRELOAD cannot be preloaded: ignored\.$"
+
+$mkdir_cmd || exit 1
+$prebuild_cmd || exit 2
+
+if [ "$GDB" = "y" ]; then
+  # When running under gdb, we cannot do piping and grepping...
+  LD_PRELOAD=libsigchain.so $cmdline "$@"
+else
+  # If we are execing /bin/false we might not be on the same ISA as libsigchain.so
+  # ld.so will helpfully warn us of this. Unfortunately this messes up our error
+  # checking so we will just filter out the error with a grep.
+  LD_PRELOAD=libsigchain.so $cmdline "$@" 2>&1 | grep -v -E "^ERROR: ld\.so: object '.+\.so' from LD_PRELOAD cannot be preloaded: ignored\.$"
+fi
\ No newline at end of file