Merge "Move x86 constant area code to its own file"
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 02f2e0b..b569f50 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -3486,28 +3486,31 @@
   if (!klass->IsInterface()) {
     // Initialize interfaces with default methods for the JLS.
     size_t num_direct_interfaces = klass->NumDirectInterfaces();
-    for (size_t i = 0; i < num_direct_interfaces; i++) {
+    // Only setup the (expensive) handle scope if we actually need to.
+    if (UNLIKELY(num_direct_interfaces > 0)) {
       StackHandleScope<1> hs_iface(self);
-      Handle<mirror::Class> handle_scope_iface(
-          hs_iface.NewHandle(mirror::Class::GetDirectInterface(self, klass, i)));
-      CHECK(handle_scope_iface.Get() != nullptr);
-      CHECK(handle_scope_iface->IsInterface());
-      if (handle_scope_iface->HasBeenRecursivelyInitialized()) {
-        // We have already done this once for this interface. Skip it.
-        continue;
-      }
-      // We cannot just call initialize class directly because we need to ensure that ALL interfaces
-      // with default methods are initialized. Non-default interface initialization will not affect
-      // other non-default super-interfaces.
-      bool iface_initialized = InitializeDefaultInterfaceRecursive(self,
-                                                                   handle_scope_iface,
-                                                                   can_init_statics,
-                                                                   can_init_parents);
-      if (!iface_initialized) {
-        ObjectLock<mirror::Class> lock(self, klass);
-        // Initialization failed because one of our interfaces with default methods is erroneous.
-        mirror::Class::SetStatus(klass, mirror::Class::kStatusError, self);
-        return false;
+      MutableHandle<mirror::Class> handle_scope_iface(hs_iface.NewHandle<mirror::Class>(nullptr));
+      for (size_t i = 0; i < num_direct_interfaces; i++) {
+        handle_scope_iface.Assign(mirror::Class::GetDirectInterface(self, klass, i));
+        CHECK(handle_scope_iface.Get() != nullptr);
+        CHECK(handle_scope_iface->IsInterface());
+        if (handle_scope_iface->HasBeenRecursivelyInitialized()) {
+          // We have already done this for this interface. Skip it.
+          continue;
+        }
+        // We cannot just call initialize class directly because we need to ensure that ALL
+        // interfaces with default methods are initialized. Non-default interface initialization
+        // will not affect other non-default super-interfaces.
+        bool iface_initialized = InitializeDefaultInterfaceRecursive(self,
+                                                                     handle_scope_iface,
+                                                                     can_init_statics,
+                                                                     can_init_parents);
+        if (!iface_initialized) {
+          ObjectLock<mirror::Class> lock(self, klass);
+          // Initialization failed because one of our interfaces with default methods is erroneous.
+          mirror::Class::SetStatus(klass, mirror::Class::kStatusError, self);
+          return false;
+        }
       }
     }
   }
@@ -3609,18 +3612,22 @@
                                                       bool can_init_parents) {
   CHECK(iface->IsInterface());
   size_t num_direct_ifaces = iface->NumDirectInterfaces();
-  // First we initialize all of iface's super-interfaces recursively.
-  for (size_t i = 0; i < num_direct_ifaces; i++) {
-    mirror::Class* super_iface = mirror::Class::GetDirectInterface(self, iface, i);
-    if (!super_iface->HasBeenRecursivelyInitialized()) {
-      // Recursive step
-      StackHandleScope<1> hs(self);
-      Handle<mirror::Class> handle_super_iface(hs.NewHandle(super_iface));
-      if (!InitializeDefaultInterfaceRecursive(self,
-                                               handle_super_iface,
-                                               can_init_statics,
-                                               can_init_parents)) {
-        return false;
+  // Only create the (expensive) handle scope if we need it.
+  if (UNLIKELY(num_direct_ifaces > 0)) {
+    StackHandleScope<1> hs(self);
+    MutableHandle<mirror::Class> handle_super_iface(hs.NewHandle<mirror::Class>(nullptr));
+    // First we initialize all of iface's super-interfaces recursively.
+    for (size_t i = 0; i < num_direct_ifaces; i++) {
+      mirror::Class* super_iface = mirror::Class::GetDirectInterface(self, iface, i);
+      if (!super_iface->HasBeenRecursivelyInitialized()) {
+        // Recursive step
+        handle_super_iface.Assign(super_iface);
+        if (!InitializeDefaultInterfaceRecursive(self,
+                                                 handle_super_iface,
+                                                 can_init_statics,
+                                                 can_init_parents)) {
+          return false;
+        }
       }
     }
   }
diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc
index 1a6bead..8e6eae9 100644
--- a/runtime/native/dalvik_system_DexFile.cc
+++ b/runtime/native/dalvik_system_DexFile.cc
@@ -74,7 +74,7 @@
                                              const OatFile* oat_file,
                                              std::vector<std::unique_ptr<const DexFile>>& vec) {
   // Add one for the oat file.
-  jlongArray long_array = env->NewLongArray(static_cast<jsize>(1u + vec.size()));
+  jlongArray long_array = env->NewLongArray(static_cast<jsize>(kDexFileIndexStart + vec.size()));
   if (env->ExceptionCheck() == JNI_TRUE) {
     return nullptr;
   }
@@ -230,7 +230,8 @@
     }
   }
 
-  if (all_deleted) {
+  // oat_file can be null if we are running without dex2oat.
+  if (all_deleted && oat_file != nullptr) {
     // If all of the dex files are no longer in use we can unmap the corresponding oat file.
     VLOG(class_linker) << "Unregistering " << oat_file;
     runtime->GetOatFileManager().UnRegisterAndDeleteOatFile(oat_file);
diff --git a/runtime/oat_file_manager.cc b/runtime/oat_file_manager.cc
index 3371a39..9eee156 100644
--- a/runtime/oat_file_manager.cc
+++ b/runtime/oat_file_manager.cc
@@ -22,7 +22,7 @@
 
 #include "base/logging.h"
 #include "base/stl_util.h"
-#include "dex_file.h"
+#include "dex_file-inl.h"
 #include "gc/space/image_space.h"
 #include "oat_file_assistant.h"
 #include "thread-inl.h"
@@ -30,7 +30,9 @@
 namespace art {
 
 // For b/21333911.
-static constexpr bool kDuplicateClassesCheck = false;
+// Only enabled for debug builds to prevent bit rot. There are too many performance regressions for
+// normal builds.
+static constexpr bool kDuplicateClassesCheck = kIsDebugBuild;
 
 const OatFile* OatFileManager::RegisterOatFile(std::unique_ptr<const OatFile> oat_file) {
   WriterMutexLock mu(Thread::Current(), *Locks::oat_file_manager_lock_);
@@ -115,9 +117,9 @@
        current_class_index_(current_class_index),
        from_loaded_oat_(from_loaded_oat) {}
 
-  DexFileAndClassPair(DexFileAndClassPair&& rhs) = default;
+  DexFileAndClassPair(const DexFileAndClassPair& rhs) = default;
 
-  DexFileAndClassPair& operator=(DexFileAndClassPair&& rhs) = default;
+  DexFileAndClassPair& operator=(const DexFileAndClassPair& rhs) = default;
 
   const char* GetCachedDescriptor() const {
     return cached_descriptor_;
@@ -139,7 +141,7 @@
 
   void Next() {
     ++current_class_index_;
-    cached_descriptor_ = nullptr;
+    cached_descriptor_ = GetClassDescriptor(dex_file_.get(), current_class_index_);
   }
 
   size_t GetCurrentClassIndex() const {
@@ -162,7 +164,7 @@
   }
 
   const char* cached_descriptor_;
-  std::unique_ptr<const DexFile> dex_file_;
+  std::shared_ptr<const DexFile> dex_file_;
   size_t current_class_index_;
   bool from_loaded_oat_;  // We only need to compare mismatches between what we load now
                           // and what was loaded before. Any old duplicates must have been
@@ -215,8 +217,17 @@
 
   // Add dex files from already loaded oat files, but skip boot.
   const OatFile* boot_oat = GetBootOatFile();
+  // The same OatFile can be loaded multiple times at different addresses. In this case, we don't
+  // need to check both against each other since they would have resolved the same way at compile
+  // time.
+  std::unordered_set<std::string> unique_locations;
   for (const std::unique_ptr<const OatFile>& loaded_oat_file : oat_files_) {
-    if (loaded_oat_file.get() != boot_oat) {
+    DCHECK_NE(loaded_oat_file.get(), oat_file);
+    const std::string& location = loaded_oat_file->GetLocation();
+    if (loaded_oat_file.get() != boot_oat &&
+        location != oat_file->GetLocation() &&
+        unique_locations.find(location) == unique_locations.end()) {
+      unique_locations.insert(location);
       AddDexFilesFromOat(loaded_oat_file.get(), /*already_loaded*/true, &queue);
     }
   }
@@ -232,12 +243,12 @@
   // Now drain the queue.
   while (!queue.empty()) {
     // Modifying the top element is only safe if we pop right after.
-    DexFileAndClassPair compare_pop(std::move(const_cast<DexFileAndClassPair&>(queue.top())));
+    DexFileAndClassPair compare_pop(queue.top());
     queue.pop();
 
     // Compare against the following elements.
     while (!queue.empty()) {
-      DexFileAndClassPair top(std::move(const_cast<DexFileAndClassPair&>(queue.top())));
+      DexFileAndClassPair top(queue.top());
 
       if (strcmp(compare_pop.GetCachedDescriptor(), top.GetCachedDescriptor()) == 0) {
         // Same descriptor. Check whether it's crossing old-oat-files to new-oat-files.
@@ -249,7 +260,6 @@
                            top.GetDexFile()->GetLocation().c_str());
           return true;
         }
-        // Pop it.
         queue.pop();
         AddNext(&top, &queue);
       } else {
diff --git a/runtime/verifier/register_line.cc b/runtime/verifier/register_line.cc
index 33c90e3..02c93cf 100644
--- a/runtime/verifier/register_line.cc
+++ b/runtime/verifier/register_line.cc
@@ -391,6 +391,34 @@
   }
 }
 
+// Check whether there is another register in the search map that is locked the same way as the
+// register in the src map. This establishes an alias.
+static bool FindLockAliasedRegister(
+    uint32_t src,
+    const AllocationTrackingSafeMap<uint32_t, uint32_t, kAllocatorTagVerifier>& src_map,
+    const AllocationTrackingSafeMap<uint32_t, uint32_t, kAllocatorTagVerifier>& search_map) {
+  auto it = src_map.find(src);
+  if (it == src_map.end()) {
+    // "Not locked" is trivially aliased.
+    return true;
+  }
+  uint32_t src_lock_levels = it->second;
+  if (src_lock_levels == 0) {
+    // "Not locked" is trivially aliased.
+    return true;
+  }
+
+  // Scan the map for the same value.
+  for (const std::pair<uint32_t, uint32_t>& pair : search_map) {
+    if (pair.first != src && pair.second == src_lock_levels) {
+      return true;
+    }
+  }
+
+  // Nothing found, no alias.
+  return false;
+}
+
 bool RegisterLine::MergeRegisters(MethodVerifier* verifier, const RegisterLine* incoming_line) {
   bool changed = false;
   DCHECK(incoming_line != nullptr);
@@ -417,9 +445,29 @@
         size_t depths = reg_to_lock_depths_.count(idx);
         size_t incoming_depths = incoming_line->reg_to_lock_depths_.count(idx);
         if (depths != incoming_depths) {
-          if (depths == 0 || incoming_depths == 0) {
-            reg_to_lock_depths_.erase(idx);
-          } else {
+          // Stack levels aren't matching. This is potentially bad, as we don't do a
+          // flow-sensitive analysis.
+          // However, this could be an alias of something locked in one path, and the alias was
+          // destroyed in another path. It is fine to drop this as long as there's another alias
+          // for the lock around. The last vanishing alias will then report that things would be
+          // left unlocked. We need to check for aliases for both lock levels.
+          //
+          // Example (lock status in curly braces as pair of register and lock leels):
+          //
+          //                            lock v1 {v1=1}
+          //                        |                    |
+          //              v0 = v1 {v0=1, v1=1}       v0 = v2 {v1=1}
+          //                        |                    |
+          //                                 {v1=1}
+          //                                         // Dropping v0, as the status can't be merged
+          //                                         // but the lock info ("locked at depth 1" and)
+          //                                         // "not locked at all") is available.
+          if (!FindLockAliasedRegister(idx,
+                                       reg_to_lock_depths_,
+                                       reg_to_lock_depths_) ||
+              !FindLockAliasedRegister(idx,
+                                       incoming_line->reg_to_lock_depths_,
+                                       reg_to_lock_depths_)) {
             verifier->Fail(VERIFY_ERROR_LOCKING);
             if (kDumpLockFailures) {
               LOG(WARNING) << "mismatched stack depths for register v" << idx
@@ -429,20 +477,51 @@
             }
             break;
           }
+          // We found aliases, set this to zero.
+          reg_to_lock_depths_.erase(idx);
         } else if (depths > 0) {
           // Check whether they're actually the same levels.
           uint32_t locked_levels = reg_to_lock_depths_.find(idx)->second;
           uint32_t incoming_locked_levels = incoming_line->reg_to_lock_depths_.find(idx)->second;
           if (locked_levels != incoming_locked_levels) {
-            verifier->Fail(VERIFY_ERROR_LOCKING);
-            if (kDumpLockFailures) {
-              LOG(WARNING) << "mismatched lock levels for register v" << idx << ": "
-                  << std::hex << locked_levels << std::dec  << " != "
-                  << std::hex << incoming_locked_levels << std::dec << " in "
-                  << PrettyMethod(verifier->GetMethodReference().dex_method_index,
-                                  *verifier->GetMethodReference().dex_file);
+            // Lock levels aren't matching. This is potentially bad, as we don't do a
+            // flow-sensitive analysis.
+            // However, this could be an alias of something locked in one path, and the alias was
+            // destroyed in another path. It is fine to drop this as long as there's another alias
+            // for the lock around. The last vanishing alias will then report that things would be
+            // left unlocked. We need to check for aliases for both lock levels.
+            //
+            // Example (lock status in curly braces as pair of register and lock leels):
+            //
+            //                          lock v1 {v1=1}
+            //                          lock v2 {v1=1, v2=2}
+            //                        |                      |
+            //         v0 = v1 {v0=1, v1=1, v2=2}  v0 = v2 {v0=2, v1=1, v2=2}
+            //                        |                      |
+            //                             {v1=1, v2=2}
+            //                                           // Dropping v0, as the status can't be
+            //                                           // merged but the lock info ("locked at
+            //                                           // depth 1" and "locked at depth 2") is
+            //                                           // available.
+            if (!FindLockAliasedRegister(idx,
+                                         reg_to_lock_depths_,
+                                         reg_to_lock_depths_) ||
+                !FindLockAliasedRegister(idx,
+                                         incoming_line->reg_to_lock_depths_,
+                                         reg_to_lock_depths_)) {
+              // No aliases for both current and incoming, we'll lose information.
+              verifier->Fail(VERIFY_ERROR_LOCKING);
+              if (kDumpLockFailures) {
+                LOG(WARNING) << "mismatched lock levels for register v" << idx << ": "
+                    << std::hex << locked_levels << std::dec  << " != "
+                    << std::hex << incoming_locked_levels << std::dec << " in "
+                    << PrettyMethod(verifier->GetMethodReference().dex_method_index,
+                                    *verifier->GetMethodReference().dex_file);
+              }
+              break;
             }
-            break;
+            // We found aliases, set this to zero.
+            reg_to_lock_depths_.erase(idx);
           }
         }
       }
diff --git a/test/088-monitor-verification/src/TwoPath.java b/test/088-monitor-verification/src/TwoPath.java
index 2542de7..bdc15ad 100644
--- a/test/088-monitor-verification/src/TwoPath.java
+++ b/test/088-monitor-verification/src/TwoPath.java
@@ -31,6 +31,8 @@
      * Conditionally uses one of the synchronized objects.
      */
     public static void twoPath(Object obj1, Object obj2, int x) {
+        Main.assertIsManaged();
+
         Object localObj;
 
         synchronized (obj1) {
diff --git a/test/131-structural-change/expected.txt b/test/131-structural-change/expected.txt
index cc7713d..1d19278 100644
--- a/test/131-structural-change/expected.txt
+++ b/test/131-structural-change/expected.txt
@@ -1,2 +1,3 @@
+JNI_OnLoad called
 Should really reach here.
 Done.
diff --git a/test/131-structural-change/src/Main.java b/test/131-structural-change/src/Main.java
index 6cbbd12..c748899 100644
--- a/test/131-structural-change/src/Main.java
+++ b/test/131-structural-change/src/Main.java
@@ -35,7 +35,7 @@
             e.printStackTrace(System.out);
         }
 
-        boolean haveOatFile = hasOat();
+        boolean haveOatFile = hasOatFile();
         boolean gotError = false;
         try {
             Class<?> bClass = getClass().getClassLoader().loadClass("B");
@@ -45,10 +45,10 @@
             e.printStackTrace(System.out);
         }
         if (haveOatFile ^ gotError) {
-            System.out.println("Did not get expected error.");
+            System.out.println("Did not get expected error. " + haveOatFile + " " + gotError);
         }
         System.out.println("Done.");
     }
 
-    private native static boolean hasOat();
+    private native static boolean hasOatFile();
 }
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index ad64b68..e114a2e 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -214,19 +214,24 @@
   055-enum-performance \
   133-static-invoke-super
 
+# disable timing sensitive tests on "dist" builds.
+ifdef dist_goal
+  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_TIMING_SENSITIVE_RUN_TESTS), $(ALL_ADDRESS_SIZES))
+endif
+
 # Tests that require python3.
 TEST_ART_PYTHON3_DEPENDENCY_RUN_TESTS := \
   960-default-smali \
   961-default-iface-resolution-generated \
   964-default-iface-init-generated \
 
-# disable timing sensitive tests on "dist" builds.
-ifdef dist_goal
-  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_TIMING_SENSITIVE_RUN_TESTS), $(ALL_ADDRESS_SIZES))
+# Check if we have python3 to run our tests.
+ifeq ($(wildcard /usr/bin/python3),)
+  $(warning "No python3 found. Disabling tests: $(TEST_ART_PYTHON3_DEPENDENCY_RUN_TESTS)")
 
-  # Currently disable tsts requiring python3.
+  # Currently disable tests requiring python3 when it is not installed.
   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_PYTHON3_DEPENDENCY_RUN_TESTS), $(ALL_ADDRESS_SIZES))
@@ -324,13 +329,15 @@
     $(PICTEST_TYPES),$(DEBUGGABLE_TYPES),130-hprof,$(ALL_ADDRESS_SIZES))
 
 # 131 is an old test. The functionality has been implemented at an earlier stage and is checked
-# in tests 138.
-ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \
+# in tests 138. Blacklisted for debug builds since these builds have duplicate classes checks which
+# punt to interpreter.
+ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),debug,$(PREBUILD_TYPES), \
     $(COMPILER_TYPES),$(RELOCATE_TYPES),$(TRACE_TYPES),$(GC_TYPES),$(JNI_TYPES),$(IMAGE_TYPES), \
     $(PICTEST_TYPES),$(DEBUGGABLE_TYPES),131-structural-change,$(ALL_ADDRESS_SIZES))
 
-# 138-duplicate-classes-check. Turned off temporarily, b/21333911.
-ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \
+# 138-duplicate-classes-check. Turned on for debug builds since debug builds have duplicate classes
+# checks enabled, b/2133391.
+ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),ndebug,$(PREBUILD_TYPES), \
     $(COMPILER_TYPES),$(RELOCATE_TYPES),$(TRACE_TYPES),$(GC_TYPES),$(JNI_TYPES),$(IMAGE_TYPES), \
     $(PICTEST_TYPES),$(DEBUGGABLE_TYPES),138-duplicate-classes-check,$(ALL_ADDRESS_SIZES))