Merge "Support for CONST_STRING in optimizing compiler."
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index 0f9e56a..2939961 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -201,7 +201,7 @@
 LOCAL_CFLAGS := $(ART_TARGET_CFLAGS)
 LOCAL_SRC_FILES := runtime/common_runtime_test.cc compiler/common_compiler_test.cc
 LOCAL_C_INCLUDES := $(ART_C_INCLUDES) art/runtime art/compiler
-LOCAL_SHARED_LIBRARIES := libcutils libartd libartd-compiler libdl
+LOCAL_SHARED_LIBRARIES := libartd libartd-compiler libdl
 LOCAL_STATIC_LIBRARIES += libgtest_libc++
 LOCAL_CLANG := $(ART_TARGET_CLANG)
 LOCAL_ADDITIONAL_DEPENDENCIES := art/build/Android.common_build.mk
@@ -217,8 +217,7 @@
 LOCAL_SRC_FILES := runtime/common_runtime_test.cc compiler/common_compiler_test.cc
 LOCAL_C_INCLUDES := $(ART_C_INCLUDES) art/runtime art/compiler
 LOCAL_SHARED_LIBRARIES := libartd libartd-compiler
-LOCAL_STATIC_LIBRARIES := libcutils
-LOCAL_STATIC_LIBRARIES += libgtest_libc++_host
+LOCAL_STATIC_LIBRARIES := libgtest_libc++_host
 LOCAL_LDLIBS += -ldl -lpthread
 LOCAL_MULTILIB := both
 LOCAL_CLANG := $(ART_HOST_CLANG)
@@ -392,8 +391,7 @@
   else # host
     LOCAL_CLANG := $$(ART_HOST_CLANG)
     LOCAL_CFLAGS += $$(ART_HOST_CFLAGS) $$(ART_HOST_DEBUG_CFLAGS)
-    LOCAL_SHARED_LIBRARIES += libicuuc-host libicui18n-host libnativehelper libz-host
-    LOCAL_STATIC_LIBRARIES += libcutils libvixl
+    LOCAL_SHARED_LIBRARIES += libicuuc-host libicui18n-host libnativehelper libziparchive-host libz-host libvixl
     LOCAL_LDLIBS := $(ART_HOST_LDLIBS) -lpthread -ldl
     LOCAL_IS_HOST_MODULE := true
     LOCAL_MULTILIB := both
diff --git a/compiler/Android.mk b/compiler/Android.mk
index 172c96c..2d38629 100644
--- a/compiler/Android.mk
+++ b/compiler/Android.mk
@@ -233,9 +233,6 @@
     endif
   endif
 
-  # TODO: clean up the compilers and remove this.
-  LOCAL_CFLAGS += -Wno-unused-parameter
-
   ifeq ($(ART_USE_PORTABLE_COMPILER),true)
     LOCAL_SHARED_LIBRARIES += libLLVM
     LOCAL_CFLAGS += -DART_USE_PORTABLE_COMPILER=1
@@ -261,15 +258,18 @@
   LOCAL_C_INCLUDES += $(ART_C_INCLUDES) art/runtime
 
   ifeq ($$(art_target_or_host),host)
-    LOCAL_LDLIBS += -ldl -lpthread
+    # For compiler driver TLS.
+    LOCAL_LDLIBS += -lpthread
   endif
   LOCAL_ADDITIONAL_DEPENDENCIES := art/build/Android.common_build.mk
   LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
+  # Vixl assembly support for ARM64 targets.
+  LOCAL_SHARED_LIBRARIES += libvixl
   ifeq ($$(art_target_or_host),target)
-    LOCAL_SHARED_LIBRARIES += libcutils libvixl
+    # For atrace.
+    LOCAL_SHARED_LIBRARIES += libcutils
     include $(BUILD_SHARED_LIBRARY)
   else # host
-    LOCAL_STATIC_LIBRARIES += libcutils libvixl
     LOCAL_MULTILIB := both
     include $(BUILD_HOST_SHARED_LIBRARY)
   endif
diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc
index d76a870..215257b 100644
--- a/compiler/dex/quick/gen_common.cc
+++ b/compiler/dex/quick/gen_common.cc
@@ -2156,25 +2156,25 @@
   const uint16_t entries = table[1];
   // Chained cmp-and-branch.
   const int32_t* as_int32 = reinterpret_cast<const int32_t*>(&table[2]);
-  int32_t current_key = as_int32[0];
+  int32_t starting_key = as_int32[0];
   const int32_t* targets = &as_int32[1];
   rl_src = LoadValue(rl_src, kCoreReg);
   int i = 0;
-  for (; i < entries; i++, current_key++) {
-    if (!InexpensiveConstantInt(current_key, Instruction::Code::IF_EQ)) {
+  for (; i < entries; i++) {
+    if (!InexpensiveConstantInt(starting_key + i, Instruction::Code::IF_EQ)) {
       // Switch to using a temp and add.
       break;
     }
     BasicBlock* case_block =
         mir_graph_->FindBlock(current_dalvik_offset_ + targets[i]);
-    OpCmpImmBranch(kCondEq, rl_src.reg, current_key, &block_label_list_[case_block->id]);
+    OpCmpImmBranch(kCondEq, rl_src.reg, starting_key + i, &block_label_list_[case_block->id]);
   }
   if (i < entries) {
     // The rest do not seem to be inexpensive. Try to allocate a temp and use add.
     RegStorage key_temp = AllocTypedTemp(false, kCoreReg, false);
     if (key_temp.Valid()) {
-      LoadConstantNoClobber(key_temp, current_key);
-      for (; i < entries - 1; i++, current_key++) {
+      LoadConstantNoClobber(key_temp, starting_key + i);
+      for (; i < entries - 1; i++) {
         BasicBlock* case_block =
             mir_graph_->FindBlock(current_dalvik_offset_ + targets[i]);
         OpCmpBranch(kCondEq, rl_src.reg, key_temp, &block_label_list_[case_block->id]);
@@ -2185,10 +2185,10 @@
       OpCmpBranch(kCondEq, rl_src.reg, key_temp, &block_label_list_[case_block->id]);
     } else {
       // No free temp, just finish the old loop.
-      for (; i < entries; i++, current_key++) {
+      for (; i < entries; i++) {
         BasicBlock* case_block =
             mir_graph_->FindBlock(current_dalvik_offset_ + targets[i]);
-        OpCmpImmBranch(kCondEq, rl_src.reg, current_key, &block_label_list_[case_block->id]);
+        OpCmpImmBranch(kCondEq, rl_src.reg, starting_key + i, &block_label_list_[case_block->id]);
       }
     }
   }
diff --git a/compiler/elf_writer_quick.cc b/compiler/elf_writer_quick.cc
index c75d8f8..575886b 100644
--- a/compiler/elf_writer_quick.cc
+++ b/compiler/elf_writer_quick.cc
@@ -686,6 +686,13 @@
     symtab->AddSymbol(it->method_name_, &builder->GetTextBuilder(), it->low_pc_, true,
                       it->high_pc_ - it->low_pc_, STB_GLOBAL, STT_FUNC);
 
+    // Conforming to aaelf, add $t mapping symbol to indicate start of a sequence of thumb2
+    // instructions, so that disassembler tools can correctly disassemble.
+    if (it->compiled_method_->GetInstructionSet() == kThumb2) {
+      symtab->AddSymbol("$t", &builder->GetTextBuilder(), it->low_pc_ & ~1, true,
+                        0, STB_LOCAL, STT_NOTYPE);
+    }
+
     // Include CFI for compiled method, if possible.
     if (cfi_info.get() != nullptr) {
       DCHECK(it->compiled_method_ != nullptr);
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index c61e991..ac72a33 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -122,8 +122,8 @@
   return -1;
 }
 
-size_t CodeGenerator::FindTwoFreeConsecutiveEntries(bool* array, size_t length) {
-  for (size_t i = 0; i < length - 1; ++i) {
+size_t CodeGenerator::FindTwoFreeConsecutiveAlignedEntries(bool* array, size_t length) {
+  for (size_t i = 0; i < length - 1; i += 2) {
     if (!array[i] && !array[i + 1]) {
       array[i] = true;
       array[i + 1] = true;
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h
index bf9d2c0..71f0b1b 100644
--- a/compiler/optimizing/code_generator.h
+++ b/compiler/optimizing/code_generator.h
@@ -190,7 +190,7 @@
   virtual Location AllocateFreeRegister(Primitive::Type type) const = 0;
 
   static size_t FindFreeEntry(bool* array, size_t length);
-  static size_t FindTwoFreeConsecutiveEntries(bool* array, size_t length);
+  static size_t FindTwoFreeConsecutiveAlignedEntries(bool* array, size_t length);
 
   virtual Location GetStackLocation(HLoadLocal* load) const = 0;
 
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 9297475..c812f6b 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -327,7 +327,8 @@
     }
 
     case Primitive::kPrimDouble: {
-      int reg = FindTwoFreeConsecutiveEntries(blocked_fpu_registers_, kNumberOfSRegisters);
+      int reg = FindTwoFreeConsecutiveAlignedEntries(blocked_fpu_registers_, kNumberOfSRegisters);
+      DCHECK_EQ(reg % 2, 0);
       return Location::FpuRegisterPairLocation(reg, reg + 1);
     }
 
@@ -372,6 +373,14 @@
   blocked_fpu_registers_[S21] = true;
   blocked_fpu_registers_[S22] = true;
   blocked_fpu_registers_[S23] = true;
+  blocked_fpu_registers_[S24] = true;
+  blocked_fpu_registers_[S25] = true;
+  blocked_fpu_registers_[S26] = true;
+  blocked_fpu_registers_[S27] = true;
+  blocked_fpu_registers_[S28] = true;
+  blocked_fpu_registers_[S29] = true;
+  blocked_fpu_registers_[S30] = true;
+  blocked_fpu_registers_[S31] = true;
 
   UpdateBlockedPairRegisters();
 }
diff --git a/dex2oat/Android.mk b/dex2oat/Android.mk
index 2ef826b..4f39c42 100644
--- a/dex2oat/Android.mk
+++ b/dex2oat/Android.mk
@@ -38,8 +38,8 @@
 
 # We always build dex2oat and dependencies, even if the host build is otherwise disabled, since they are used to cross compile for the target.
 ifeq ($(ART_BUILD_HOST_NDEBUG),true)
-  $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libart-compiler,art/compiler,host,ndebug))
+  $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libart-compiler libziparchive-host,art/compiler,host,ndebug))
 endif
 ifeq ($(ART_BUILD_HOST_DEBUG),true)
-  $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libartd-compiler,art/compiler,host,debug))
+  $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libartd-compiler libziparchive-host,art/compiler,host,debug))
 endif
diff --git a/disassembler/Android.mk b/disassembler/Android.mk
index eb3b024..f2dd1ee 100644
--- a/disassembler/Android.mk
+++ b/disassembler/Android.mk
@@ -84,11 +84,11 @@
   LOCAL_ADDITIONAL_DEPENDENCIES := art/build/Android.common_build.mk
   LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
   include external/libcxx/libcxx.mk
+  # For disassembler_arm64.
+  LOCAL_SHARED_LIBRARIES += libvixl
   ifeq ($$(art_target_or_host),target)
-    LOCAL_SHARED_LIBRARIES += libcutils libvixl
     include $(BUILD_SHARED_LIBRARY)
   else # host
-    LOCAL_STATIC_LIBRARIES += libcutils libvixl
     include $(BUILD_HOST_SHARED_LIBRARY)
   endif
 endef
diff --git a/oatdump/Android.mk b/oatdump/Android.mk
index 25d10bd..a8f120f 100644
--- a/oatdump/Android.mk
+++ b/oatdump/Android.mk
@@ -25,14 +25,14 @@
   $(eval $(call build-art-executable,oatdump,$(OATDUMP_SRC_FILES),libcutils libart-disassembler libart-compiler,art/disassembler art/compiler,target,ndebug))
 endif
 ifeq ($(ART_BUILD_TARGET_DEBUG),true)
-  $(eval $(call build-art-executable,oatdump,$(OATDUMP_SRC_FILES),libcutils libartd-disassembler libart-compiler,art/disassembler art/compiler,target,debug))
+  $(eval $(call build-art-executable,oatdump,$(OATDUMP_SRC_FILES),libcutils libartd-disassembler libartd-compiler,art/disassembler art/compiler,target,debug))
 endif
 
 ifeq ($(ART_BUILD_HOST_NDEBUG),true)
   $(eval $(call build-art-executable,oatdump,$(OATDUMP_SRC_FILES),libart-disassembler libart-compiler,art/disassembler art/compiler,host,ndebug))
 endif
 ifeq ($(ART_BUILD_HOST_DEBUG),true)
-  $(eval $(call build-art-executable,oatdump,$(OATDUMP_SRC_FILES),libartd-disassembler libart-compiler,art/disassembler art/compiler,host,debug))
+  $(eval $(call build-art-executable,oatdump,$(OATDUMP_SRC_FILES),libartd-disassembler libartd-compiler,art/disassembler art/compiler,host,debug))
 endif
 
 ########################################################################
diff --git a/runtime/Android.mk b/runtime/Android.mk
index 6f6dcbc..a2fc24a 100644
--- a/runtime/Android.mk
+++ b/runtime/Android.mk
@@ -457,15 +457,21 @@
   LOCAL_C_INCLUDES += $$(ART_C_INCLUDES)
   LOCAL_C_INCLUDES += art/sigchainlib
 
-  LOCAL_SHARED_LIBRARIES += liblog libnativehelper libnativebridge
+  LOCAL_SHARED_LIBRARIES := libnativehelper libnativebridge libsigchain
   include external/libcxx/libcxx.mk
   LOCAL_SHARED_LIBRARIES += libbacktrace_libc++
   ifeq ($$(art_target_or_host),target)
-    LOCAL_SHARED_LIBRARIES += libcutils libdl libutils libsigchain
+    LOCAL_SHARED_LIBRARIES += libdl
+    # ZipArchive support, the order matters here to get all symbols.
     LOCAL_STATIC_LIBRARIES := libziparchive libz
+    # For android::FileMap used by libziparchive.
+    LOCAL_SHARED_LIBRARIES += libutils
+    # For liblog, atrace, properties, ashmem, set_sched_policy and socket_peer_is_trusted.
+    LOCAL_SHARED_LIBRARIES += libcutils
   else # host
-    LOCAL_STATIC_LIBRARIES += libcutils libziparchive-host libz libutils
-    LOCAL_SHARED_LIBRARIES += libsigchain
+    LOCAL_SHARED_LIBRARIES += libziparchive-host
+    # For ashmem_create_region.
+    LOCAL_STATIC_LIBRARIES += libcutils
   endif
   ifeq ($$(ART_USE_PORTABLE_COMPILER),true)
     include $$(LLVM_GEN_INTRINSICS_MK)
diff --git a/runtime/base/bit_vector.cc b/runtime/base/bit_vector.cc
index 71dec7a..63e9355 100644
--- a/runtime/base/bit_vector.cc
+++ b/runtime/base/bit_vector.cc
@@ -16,6 +16,7 @@
 
 #include "bit_vector.h"
 
+#include <limits>
 #include <sstream>
 
 #include "allocator.h"
@@ -218,13 +219,13 @@
   uint32_t idx;
   // We can set every storage element with -1.
   for (idx = 0; idx < WordIndex(num_bits); idx++) {
-    storage_[idx] = -1;
+    storage_[idx] = std::numeric_limits<uint32_t>::max();
   }
 
   // Handle the potentially last few bits.
   uint32_t rem_num_bits = num_bits & 0x1f;
   if (rem_num_bits != 0) {
-    storage_[idx] = (1 << rem_num_bits) - 1;
+    storage_[idx] = (1U << rem_num_bits) - 1;
     ++idx;
   }
 
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index e2514ec..d99e373 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1161,9 +1161,13 @@
     image_patch_delta = image_header->GetPatchDelta();
   }
   const OatHeader& oat_header = oat_file->GetOatHeader();
-  bool ret = ((oat_header.GetImageFileLocationOatChecksum() == image_oat_checksum)
-              && (oat_header.GetImagePatchDelta() == image_patch_delta)
-              && (oat_header.GetImageFileLocationOatDataBegin() == image_oat_data_begin));
+  bool ret = (oat_header.GetImageFileLocationOatChecksum() == image_oat_checksum);
+
+  // If the oat file is PIC, it doesn't care if/how image was relocated. Ignore these checks.
+  if (!oat_file->IsPic()) {
+    ret = ret && (oat_header.GetImagePatchDelta() == image_patch_delta)
+              && (oat_header.GetImageFileLocationOatDataBegin() == image_oat_data_begin);
+  }
   if (!ret) {
     *error_msg = StringPrintf("oat file '%s' mismatch (0x%x, %d, %d) with (0x%x, %" PRIdPTR ", %d)",
                               oat_file->GetLocation().c_str(),
@@ -4223,8 +4227,8 @@
       mirror::ArtField* resolved_field = dex_cache->GetResolvedField(field_idx);
       if (resolved_field == nullptr) {
         dex_cache->SetResolvedField(field_idx, field);
-      } else if (kIsDebugBuild) {
-        CHECK_EQ(field, resolved_field);
+      } else {
+        DCHECK_EQ(field, resolved_field);
       }
     }
 
@@ -4632,7 +4636,14 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) :
       dex_file_(method->GetDexFile()), mid_(&dex_file_->GetMethodId(method->GetDexMethodIndex())),
       name_(nullptr), name_len_(0) {
-    DCHECK(!method->IsProxyMethod())  << PrettyMethod(method);
+    DCHECK(!method->IsProxyMethod()) << PrettyMethod(method);
+  }
+
+  const char* GetName() {
+    if (name_ == nullptr) {
+      name_ = dex_file_->StringDataAndUtf16LengthByIdx(mid_->name_idx_, &name_len_);
+    }
+    return name_;
   }
 
   bool HasSameNameAndSignature(mirror::ArtMethod* other)
@@ -4643,9 +4654,7 @@
     if (dex_file_ == other_dex_file) {
       return mid_->name_idx_ == other_mid.name_idx_ && mid_->proto_idx_ == other_mid.proto_idx_;
     }
-    if (name_ == nullptr) {
-      name_ = dex_file_->StringDataAndUtf16LengthByIdx(mid_->name_idx_, &name_len_);
-    }
+    GetName();  // Only used to make sure its calculated.
     uint32_t other_name_len;
     const char* other_name = other_dex_file->StringDataAndUtf16LengthByIdx(other_mid.name_idx_,
                                                                            &other_name_len);
@@ -4666,12 +4675,72 @@
   uint32_t name_len_;
 };
 
+class LinkVirtualHashTable {
+ public:
+  LinkVirtualHashTable(Handle<mirror::Class> klass, size_t hash_size, uint32_t* hash_table)
+     : klass_(klass), hash_size_(hash_size), hash_table_(hash_table) {
+    std::fill(hash_table_, hash_table_ + hash_size_, invalid_index_);
+  }
+  void Add(uint32_t virtual_method_index) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    mirror::ArtMethod* local_method = klass_->GetVirtualMethodDuringLinking(virtual_method_index);
+    const char* name = local_method->GetName();
+    uint32_t hash = Hash(name);
+    uint32_t index = hash % hash_size_;
+    // Linear probe until we have an empty slot.
+    while (hash_table_[index] != invalid_index_) {
+      if (++index == hash_size_) {
+        index = 0;
+      }
+    }
+    hash_table_[index] = virtual_method_index;
+  }
+  uint32_t FindAndRemove(MethodNameAndSignatureComparator* comparator)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    const char* name = comparator->GetName();
+    uint32_t hash = Hash(name);
+    size_t index = hash % hash_size_;
+    while (true) {
+      const uint32_t value = hash_table_[index];
+      // Since linear probe makes continuous blocks, hitting an invalid index means we are done
+      // the block and can safely assume not found.
+      if (value == invalid_index_) {
+        break;
+      }
+      if (value != removed_index_) {  // This signifies not already overriden.
+        mirror::ArtMethod* virtual_method =
+            klass_->GetVirtualMethodDuringLinking(value);
+        if (comparator->HasSameNameAndSignature(virtual_method->GetInterfaceMethodIfProxy())) {
+          hash_table_[index] = removed_index_;
+          return value;
+        }
+      }
+      if (++index == hash_size_) {
+        index = 0;
+      }
+    }
+    return GetNotFoundIndex();
+  }
+  static uint32_t GetNotFoundIndex() {
+    return invalid_index_;
+  }
+
+ private:
+  static const uint32_t invalid_index_;
+  static const uint32_t removed_index_;
+
+  Handle<mirror::Class> klass_;
+  const size_t hash_size_;
+  uint32_t* const hash_table_;
+};
+
+const uint32_t LinkVirtualHashTable::invalid_index_ = std::numeric_limits<uint32_t>::max();
+const uint32_t LinkVirtualHashTable::removed_index_ = std::numeric_limits<uint32_t>::max() - 1;
+
 bool ClassLinker::LinkVirtualMethods(Thread* self, Handle<mirror::Class> klass) {
   const size_t num_virtual_methods = klass->NumVirtualMethods();
   if (klass->HasSuperClass()) {
     const size_t super_vtable_length = klass->GetSuperClass()->GetVTableLength();
     const size_t max_count = num_virtual_methods + super_vtable_length;
-    size_t actual_count = super_vtable_length;
     StackHandleScope<2> hs(self);
     Handle<mirror::Class> super_class(hs.NewHandle(klass->GetSuperClass()));
     MutableHandle<mirror::ObjectArray<mirror::ArtMethod>> vtable;
@@ -4684,50 +4753,87 @@
       for (size_t i = 0; i < super_vtable_length; i++) {
         vtable->SetWithoutChecks<false>(i, super_class->GetEmbeddedVTableEntry(i));
       }
+      if (num_virtual_methods == 0) {
+        klass->SetVTable(vtable.Get());
+        return true;
+      }
     } else {
-      CHECK(super_class->GetVTable() != nullptr) << PrettyClass(super_class.Get());
-      vtable = hs.NewHandle(super_class->GetVTable()->CopyOf(self, max_count));
+      mirror::ObjectArray<mirror::ArtMethod>* super_vtable = super_class->GetVTable();
+      CHECK(super_vtable != nullptr) << PrettyClass(super_class.Get());
+      if (num_virtual_methods == 0) {
+        klass->SetVTable(super_vtable);
+        return true;
+      }
+      vtable = hs.NewHandle(super_vtable->CopyOf(self, max_count));
       if (UNLIKELY(vtable.Get() == nullptr)) {
         CHECK(self->IsExceptionPending());  // OOME.
         return false;
       }
     }
-
-    // See if any of our virtual methods override the superclass.
+    // How the algorithm works:
+    // 1. Populate hash table by adding num_virtual_methods from klass. The values in the hash
+    // table are: invalid_index for unused slots, index super_vtable_length + i for a virtual
+    // method which has not been matched to a vtable method, and j if the virtual method at the
+    // index overrode the super virtual method at index j.
+    // 2. Loop through super virtual methods, if they overwrite, update hash table to j
+    // (j < super_vtable_length) to avoid redundant checks. (TODO maybe use this info for reducing
+    // the need for the initial vtable which we later shrink back down).
+    // 3. Add non overridden methods to the end of the vtable.
+    static constexpr size_t kMaxStackHash = 250;
+    const size_t hash_table_size = num_virtual_methods * 3;
+    uint32_t* hash_table_ptr;
+    std::unique_ptr<uint32_t[]> hash_heap_storage;
+    if (hash_table_size <= kMaxStackHash) {
+      hash_table_ptr = reinterpret_cast<uint32_t*>(
+          alloca(hash_table_size * sizeof(*hash_table_ptr)));
+    } else {
+      hash_heap_storage.reset(new uint32_t[hash_table_size]);
+      hash_table_ptr = hash_heap_storage.get();
+    }
+    LinkVirtualHashTable hash_table(klass, hash_table_size, hash_table_ptr);
+    // Add virtual methods to the hash table.
     for (size_t i = 0; i < num_virtual_methods; ++i) {
-      mirror::ArtMethod* local_method = klass->GetVirtualMethodDuringLinking(i);
-      MethodNameAndSignatureComparator
-          virtual_method_name_comparator(local_method->GetInterfaceMethodIfProxy());
-      size_t j = 0;
-      for (; j < actual_count; ++j) {
-        mirror::ArtMethod* super_method = vtable->GetWithoutChecks(j);
-        if (super_method->GetDeclaringClass() == klass.Get()) {
-          continue;  // A previously overridden method.
-        }
-        if (virtual_method_name_comparator.HasSameNameAndSignature(super_method)) {
-          if (klass->CanAccessMember(super_method->GetDeclaringClass(),
-                                     super_method->GetAccessFlags())) {
-            if (super_method->IsFinal()) {
-              ThrowLinkageError(klass.Get(), "Method %s overrides final method in class %s",
-                                PrettyMethod(local_method).c_str(),
-                                super_method->GetDeclaringClassDescriptor());
-              return false;
-            }
-            vtable->SetWithoutChecks<false>(j, local_method);
-            local_method->SetMethodIndex(j);
-            break;
+      hash_table.Add(i);
+    }
+    // Loop through each super vtable method and see if they are overriden by a method we added to
+    // the hash table.
+    for (size_t j = 0; j < super_vtable_length; ++j) {
+      // Search the hash table to see if we are overidden by any method.
+      mirror::ArtMethod* super_method = vtable->GetWithoutChecks(j);
+      MethodNameAndSignatureComparator super_method_name_comparator(
+          super_method->GetInterfaceMethodIfProxy());
+      uint32_t hash_index = hash_table.FindAndRemove(&super_method_name_comparator);
+      if (hash_index != hash_table.GetNotFoundIndex()) {
+        mirror::ArtMethod* virtual_method = klass->GetVirtualMethodDuringLinking(hash_index);
+        if (klass->CanAccessMember(super_method->GetDeclaringClass(),
+                                   super_method->GetAccessFlags())) {
+          if (super_method->IsFinal()) {
+            ThrowLinkageError(klass.Get(), "Method %s overrides final method in class %s",
+                              PrettyMethod(virtual_method).c_str(),
+                              super_method->GetDeclaringClassDescriptor());
+            return false;
           }
-          LOG(WARNING) << "Before Android 4.1, method " << PrettyMethod(local_method)
+          vtable->SetWithoutChecks<false>(j, virtual_method);
+          virtual_method->SetMethodIndex(j);
+        } else {
+          LOG(WARNING) << "Before Android 4.1, method " << PrettyMethod(virtual_method)
                        << " would have incorrectly overridden the package-private method in "
                        << PrettyDescriptor(super_method->GetDeclaringClassDescriptor());
         }
       }
-      if (j == actual_count) {
-        // Not overriding, append.
-        vtable->SetWithoutChecks<false>(actual_count, local_method);
-        local_method->SetMethodIndex(actual_count);
-        ++actual_count;
+    }
+    // Add the non overridden methods at the end.
+    size_t actual_count = super_vtable_length;
+    for (size_t i = 0; i < num_virtual_methods; ++i) {
+      mirror::ArtMethod* local_method = klass->GetVirtualMethodDuringLinking(i);
+      size_t method_idx = local_method->GetMethodIndexDuringLinking();
+      if (method_idx < super_vtable_length &&
+          local_method == vtable->GetWithoutChecks(method_idx)) {
+        continue;
       }
+      vtable->SetWithoutChecks<false>(actual_count, local_method);
+      local_method->SetMethodIndex(actual_count);
+      ++actual_count;
     }
     if (!IsUint(16, actual_count)) {
       ThrowClassFormatError(klass.Get(), "Too many methods defined on class: %zd", actual_count);
@@ -4962,7 +5068,8 @@
       }
       for (size_t j = 0; j < num_methods; ++j) {
         mirror::ArtMethod* interface_method = iftable->GetInterface(i)->GetVirtualMethod(j);
-        MethodNameAndSignatureComparator interface_name_comparator(interface_method);
+        MethodNameAndSignatureComparator interface_name_comparator(
+            interface_method->GetInterfaceMethodIfProxy());
         int32_t k;
         // For each method listed in the interface's method list, find the
         // matching method in our class's method list.  We want to favor the
@@ -4977,7 +5084,7 @@
           mirror::ArtMethod* vtable_method_for_name_comparison =
               vtable_method->GetInterfaceMethodIfProxy();
           if (interface_name_comparator.HasSameNameAndSignature(
-                  vtable_method_for_name_comparison)) {
+              vtable_method_for_name_comparison)) {
             if (!vtable_method->IsAbstract() && !vtable_method->IsPublic()) {
               ThrowIllegalAccessError(
                   klass.Get(),
@@ -4996,10 +5103,10 @@
             } else if (imt_ref != conflict_method) {
               // If we are not a conflict and we have the same signature and name as the imt entry,
               // it must be that we overwrote a superclass vtable entry.
-              MethodNameAndSignatureComparator
-                  imt_ref_name_comparator(imt_ref->GetInterfaceMethodIfProxy());
+              MethodNameAndSignatureComparator imt_ref_name_comparator(
+                  imt_ref->GetInterfaceMethodIfProxy());
               if (imt_ref_name_comparator.HasSameNameAndSignature(
-                      vtable_method_for_name_comparison)) {
+                  vtable_method_for_name_comparison)) {
                 out_imt->SetReference(imt_index, vtable_method);
               } else {
                 out_imt->SetReference(imt_index, conflict_method);
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index d9061c8..5409d54 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -4373,7 +4373,7 @@
   // Send a series of heap segment chunks.
   HeapChunkContext context((what == HPSG_WHAT_MERGED_OBJECTS), native);
   if (native) {
-#ifdef USE_DLMALLOC
+#if defined(HAVE_ANDROID_OS) && defined(USE_DLMALLOC)
     dlmalloc_inspect_all(HeapChunkContext::HeapChunkCallback, &context);
 #else
     UNIMPLEMENTED(WARNING) << "Native heap inspection is only supported with dlmalloc";
diff --git a/runtime/dex_instruction.h b/runtime/dex_instruction.h
index b913220..72802e4 100644
--- a/runtime/dex_instruction.h
+++ b/runtime/dex_instruction.h
@@ -88,6 +88,7 @@
     DEX_INSTRUCTION_LIST(INSTRUCTION_ENUM)
 #undef DEX_INSTRUCTION_LIST
 #undef INSTRUCTION_ENUM
+    RSUB_INT_LIT16 = RSUB_INT,
   };
 
   enum Format {
diff --git a/runtime/gc/allocator/dlmalloc.h b/runtime/gc/allocator/dlmalloc.h
index c820b19..c7ecbc8 100644
--- a/runtime/gc/allocator/dlmalloc.h
+++ b/runtime/gc/allocator/dlmalloc.h
@@ -30,10 +30,12 @@
 
 #include "../../bionic/libc/upstream-dlmalloc/malloc.h"
 
+#ifdef HAVE_ANDROID_OS
 // Define dlmalloc routines from bionic that cannot be included directly because of redefining
 // symbols from the include above.
 extern "C" void dlmalloc_inspect_all(void(*handler)(void*, void *, size_t, void*), void* arg);
 extern "C" int  dlmalloc_trim(size_t);
+#endif
 
 // Callback for dlmalloc_inspect_all or mspace_inspect_all that will madvise(2) unused
 // pages back to the kernel.
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index c0008aa..6730dfe 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -1017,6 +1017,8 @@
   // We never move things in the native heap, so we can finish the GC at this point.
   FinishGC(self, collector::kGcTypeNone);
   size_t native_reclaimed = 0;
+
+#ifdef HAVE_ANDROID_OS
   // Only trim the native heap if we don't care about pauses.
   if (!CareAboutPauseTimes()) {
 #if defined(USE_DLMALLOC)
@@ -1029,6 +1031,7 @@
     UNIMPLEMENTED(WARNING) << "Add trimming support";
 #endif
   }
+#endif  // HAVE_ANDROID_OS
   uint64_t end_ns = NanoTime();
   VLOG(heap) << "Heap trim of managed (duration=" << PrettyDuration(gc_heap_end_ns - start_ns)
       << ", advised=" << PrettySize(managed_reclaimed) << ") and native (duration="
diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h
index 6a0aaf2..7f6303a 100644
--- a/runtime/interpreter/interpreter_common.h
+++ b/runtime/interpreter/interpreter_common.h
@@ -216,7 +216,7 @@
 static inline bool DoIntDivide(ShadowFrame& shadow_frame, size_t result_reg,
                                int32_t dividend, int32_t divisor)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  const int32_t kMinInt = std::numeric_limits<int32_t>::min();
+  constexpr int32_t kMinInt = std::numeric_limits<int32_t>::min();
   if (UNLIKELY(divisor == 0)) {
     ThrowArithmeticExceptionDivideByZero();
     return false;
@@ -234,7 +234,7 @@
 static inline bool DoIntRemainder(ShadowFrame& shadow_frame, size_t result_reg,
                                   int32_t dividend, int32_t divisor)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  const int32_t kMinInt = std::numeric_limits<int32_t>::min();
+  constexpr int32_t kMinInt = std::numeric_limits<int32_t>::min();
   if (UNLIKELY(divisor == 0)) {
     ThrowArithmeticExceptionDivideByZero();
     return false;
diff --git a/runtime/interpreter/interpreter_goto_table_impl.cc b/runtime/interpreter/interpreter_goto_table_impl.cc
index 3a177eb..6350c56 100644
--- a/runtime/interpreter/interpreter_goto_table_impl.cc
+++ b/runtime/interpreter/interpreter_goto_table_impl.cc
@@ -15,6 +15,7 @@
  */
 
 #include "interpreter_common.h"
+#include "safe_math.h"
 
 namespace art {
 namespace interpreter {
@@ -1634,22 +1635,22 @@
 
   HANDLE_INSTRUCTION_START(ADD_INT)
     shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
-                         shadow_frame.GetVReg(inst->VRegB_23x()) +
-                         shadow_frame.GetVReg(inst->VRegC_23x()));
+                         SafeAdd(shadow_frame.GetVReg(inst->VRegB_23x()),
+                                 shadow_frame.GetVReg(inst->VRegC_23x())));
     ADVANCE(2);
   HANDLE_INSTRUCTION_END();
 
   HANDLE_INSTRUCTION_START(SUB_INT)
     shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
-                         shadow_frame.GetVReg(inst->VRegB_23x()) -
-                         shadow_frame.GetVReg(inst->VRegC_23x()));
+                         SafeSub(shadow_frame.GetVReg(inst->VRegB_23x()),
+                                 shadow_frame.GetVReg(inst->VRegC_23x())));
     ADVANCE(2);
   HANDLE_INSTRUCTION_END();
 
   HANDLE_INSTRUCTION_START(MUL_INT)
     shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
-                         shadow_frame.GetVReg(inst->VRegB_23x()) *
-                         shadow_frame.GetVReg(inst->VRegC_23x()));
+                         SafeMul(shadow_frame.GetVReg(inst->VRegB_23x()),
+                                 shadow_frame.GetVReg(inst->VRegC_23x())));
     ADVANCE(2);
   HANDLE_INSTRUCTION_END();
 
@@ -1713,22 +1714,22 @@
 
   HANDLE_INSTRUCTION_START(ADD_LONG)
     shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
-                             shadow_frame.GetVRegLong(inst->VRegB_23x()) +
-                             shadow_frame.GetVRegLong(inst->VRegC_23x()));
+                             SafeAdd(shadow_frame.GetVRegLong(inst->VRegB_23x()),
+                                     shadow_frame.GetVRegLong(inst->VRegC_23x())));
     ADVANCE(2);
   HANDLE_INSTRUCTION_END();
 
   HANDLE_INSTRUCTION_START(SUB_LONG)
     shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
-                             shadow_frame.GetVRegLong(inst->VRegB_23x()) -
-                             shadow_frame.GetVRegLong(inst->VRegC_23x()));
+                             SafeSub(shadow_frame.GetVRegLong(inst->VRegB_23x()),
+                                     shadow_frame.GetVRegLong(inst->VRegC_23x())));
     ADVANCE(2);
   HANDLE_INSTRUCTION_END();
 
   HANDLE_INSTRUCTION_START(MUL_LONG)
     shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
-                             shadow_frame.GetVRegLong(inst->VRegB_23x()) *
-                             shadow_frame.GetVRegLong(inst->VRegC_23x()));
+                             SafeMul(shadow_frame.GetVRegLong(inst->VRegB_23x()),
+                                     shadow_frame.GetVRegLong(inst->VRegC_23x())));
     ADVANCE(2);
   HANDLE_INSTRUCTION_END();
 
@@ -1863,8 +1864,8 @@
   HANDLE_INSTRUCTION_START(ADD_INT_2ADDR) {
     uint32_t vregA = inst->VRegA_12x(inst_data);
     shadow_frame.SetVReg(vregA,
-                         shadow_frame.GetVReg(vregA) +
-                         shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
+                         SafeAdd(shadow_frame.GetVReg(vregA),
+                                 shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
     ADVANCE(1);
   }
   HANDLE_INSTRUCTION_END();
@@ -1872,8 +1873,8 @@
   HANDLE_INSTRUCTION_START(SUB_INT_2ADDR) {
     uint32_t vregA = inst->VRegA_12x(inst_data);
     shadow_frame.SetVReg(vregA,
-                         shadow_frame.GetVReg(vregA) -
-                         shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
+                         SafeSub(shadow_frame.GetVReg(vregA),
+                                 shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
     ADVANCE(1);
   }
   HANDLE_INSTRUCTION_END();
@@ -1881,8 +1882,8 @@
   HANDLE_INSTRUCTION_START(MUL_INT_2ADDR) {
     uint32_t vregA = inst->VRegA_12x(inst_data);
     shadow_frame.SetVReg(vregA,
-                         shadow_frame.GetVReg(vregA) *
-                         shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
+                         SafeMul(shadow_frame.GetVReg(vregA),
+                                 shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
     ADVANCE(1);
   }
   HANDLE_INSTRUCTION_END();
@@ -1960,8 +1961,8 @@
   HANDLE_INSTRUCTION_START(ADD_LONG_2ADDR) {
     uint32_t vregA = inst->VRegA_12x(inst_data);
     shadow_frame.SetVRegLong(vregA,
-                             shadow_frame.GetVRegLong(vregA) +
-                             shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
+                             SafeAdd(shadow_frame.GetVRegLong(vregA),
+                                     shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data))));
     ADVANCE(1);
   }
   HANDLE_INSTRUCTION_END();
@@ -1969,8 +1970,8 @@
   HANDLE_INSTRUCTION_START(SUB_LONG_2ADDR) {
     uint32_t vregA = inst->VRegA_12x(inst_data);
     shadow_frame.SetVRegLong(vregA,
-                             shadow_frame.GetVRegLong(vregA) -
-                             shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
+                             SafeSub(shadow_frame.GetVRegLong(vregA),
+                                     shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data))));
     ADVANCE(1);
   }
   HANDLE_INSTRUCTION_END();
@@ -1978,8 +1979,8 @@
   HANDLE_INSTRUCTION_START(MUL_LONG_2ADDR) {
     uint32_t vregA = inst->VRegA_12x(inst_data);
     shadow_frame.SetVRegLong(vregA,
-                             shadow_frame.GetVRegLong(vregA) *
-                             shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
+                             SafeMul(shadow_frame.GetVRegLong(vregA),
+                                     shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data))));
     ADVANCE(1);
   }
   HANDLE_INSTRUCTION_END();
@@ -2146,22 +2147,22 @@
 
   HANDLE_INSTRUCTION_START(ADD_INT_LIT16)
     shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
-                         shadow_frame.GetVReg(inst->VRegB_22s(inst_data)) +
-                         inst->VRegC_22s());
+                         SafeAdd(shadow_frame.GetVReg(inst->VRegB_22s(inst_data)),
+                                 inst->VRegC_22s()));
     ADVANCE(2);
   HANDLE_INSTRUCTION_END();
 
   HANDLE_INSTRUCTION_START(RSUB_INT)
     shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
-                         inst->VRegC_22s() -
-                         shadow_frame.GetVReg(inst->VRegB_22s(inst_data)));
+                         SafeSub(inst->VRegC_22s(),
+                                 shadow_frame.GetVReg(inst->VRegB_22s(inst_data))));
     ADVANCE(2);
   HANDLE_INSTRUCTION_END();
 
   HANDLE_INSTRUCTION_START(MUL_INT_LIT16)
     shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
-                         shadow_frame.GetVReg(inst->VRegB_22s(inst_data)) *
-                         inst->VRegC_22s());
+                         SafeMul(shadow_frame.GetVReg(inst->VRegB_22s(inst_data)),
+                                 inst->VRegC_22s()));
     ADVANCE(2);
   HANDLE_INSTRUCTION_END();
 
@@ -2202,22 +2203,22 @@
 
   HANDLE_INSTRUCTION_START(ADD_INT_LIT8)
     shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
-                         shadow_frame.GetVReg(inst->VRegB_22b()) +
-                         inst->VRegC_22b());
+                         SafeAdd(shadow_frame.GetVReg(inst->VRegB_22b()),
+                                 inst->VRegC_22b()));
     ADVANCE(2);
   HANDLE_INSTRUCTION_END();
 
   HANDLE_INSTRUCTION_START(RSUB_INT_LIT8)
     shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
-                         inst->VRegC_22b() -
-                         shadow_frame.GetVReg(inst->VRegB_22b()));
+                         SafeSub(inst->VRegC_22b(),
+                                 shadow_frame.GetVReg(inst->VRegB_22b())));
     ADVANCE(2);
   HANDLE_INSTRUCTION_END();
 
   HANDLE_INSTRUCTION_START(MUL_INT_LIT8)
     shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
-                         shadow_frame.GetVReg(inst->VRegB_22b()) *
-                         inst->VRegC_22b());
+                         SafeMul(shadow_frame.GetVReg(inst->VRegB_22b()),
+                                 inst->VRegC_22b()));
     ADVANCE(2);
   HANDLE_INSTRUCTION_END();
 
diff --git a/runtime/interpreter/interpreter_switch_impl.cc b/runtime/interpreter/interpreter_switch_impl.cc
index 9fb90f1..1b6f53e 100644
--- a/runtime/interpreter/interpreter_switch_impl.cc
+++ b/runtime/interpreter/interpreter_switch_impl.cc
@@ -15,6 +15,7 @@
  */
 
 #include "interpreter_common.h"
+#include "safe_math.h"
 
 namespace art {
 namespace interpreter {
@@ -1495,25 +1496,26 @@
                              static_cast<int16_t>(shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
         inst = inst->Next_1xx();
         break;
-      case Instruction::ADD_INT:
+      case Instruction::ADD_INT: {
         PREAMBLE();
         shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
-                             shadow_frame.GetVReg(inst->VRegB_23x()) +
-                             shadow_frame.GetVReg(inst->VRegC_23x()));
+                             SafeAdd(shadow_frame.GetVReg(inst->VRegB_23x()),
+                                     shadow_frame.GetVReg(inst->VRegC_23x())));
         inst = inst->Next_2xx();
         break;
+      }
       case Instruction::SUB_INT:
         PREAMBLE();
         shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
-                             shadow_frame.GetVReg(inst->VRegB_23x()) -
-                             shadow_frame.GetVReg(inst->VRegC_23x()));
+                             SafeSub(shadow_frame.GetVReg(inst->VRegB_23x()),
+                                     shadow_frame.GetVReg(inst->VRegC_23x())));
         inst = inst->Next_2xx();
         break;
       case Instruction::MUL_INT:
         PREAMBLE();
         shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
-                             shadow_frame.GetVReg(inst->VRegB_23x()) *
-                             shadow_frame.GetVReg(inst->VRegC_23x()));
+                             SafeMul(shadow_frame.GetVReg(inst->VRegB_23x()),
+                                     shadow_frame.GetVReg(inst->VRegC_23x())));
         inst = inst->Next_2xx();
         break;
       case Instruction::DIV_INT: {
@@ -1577,29 +1579,29 @@
       case Instruction::ADD_LONG:
         PREAMBLE();
         shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
-                                 shadow_frame.GetVRegLong(inst->VRegB_23x()) +
-                                 shadow_frame.GetVRegLong(inst->VRegC_23x()));
+                                 SafeAdd(shadow_frame.GetVRegLong(inst->VRegB_23x()),
+                                         shadow_frame.GetVRegLong(inst->VRegC_23x())));
         inst = inst->Next_2xx();
         break;
       case Instruction::SUB_LONG:
         PREAMBLE();
         shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
-                                 shadow_frame.GetVRegLong(inst->VRegB_23x()) -
-                                 shadow_frame.GetVRegLong(inst->VRegC_23x()));
+                                 SafeSub(shadow_frame.GetVRegLong(inst->VRegB_23x()),
+                                         shadow_frame.GetVRegLong(inst->VRegC_23x())));
         inst = inst->Next_2xx();
         break;
       case Instruction::MUL_LONG:
         PREAMBLE();
         shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
-                                 shadow_frame.GetVRegLong(inst->VRegB_23x()) *
-                                 shadow_frame.GetVRegLong(inst->VRegC_23x()));
+                                 SafeMul(shadow_frame.GetVRegLong(inst->VRegB_23x()),
+                                         shadow_frame.GetVRegLong(inst->VRegC_23x())));
         inst = inst->Next_2xx();
         break;
       case Instruction::DIV_LONG:
         PREAMBLE();
         DoLongDivide(shadow_frame, inst->VRegA_23x(inst_data),
                      shadow_frame.GetVRegLong(inst->VRegB_23x()),
-                    shadow_frame.GetVRegLong(inst->VRegC_23x()));
+                     shadow_frame.GetVRegLong(inst->VRegC_23x()));
         POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_2xx);
         break;
       case Instruction::REM_LONG:
@@ -1724,9 +1726,8 @@
       case Instruction::ADD_INT_2ADDR: {
         PREAMBLE();
         uint4_t vregA = inst->VRegA_12x(inst_data);
-        shadow_frame.SetVReg(vregA,
-                             shadow_frame.GetVReg(vregA) +
-                             shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
+        shadow_frame.SetVReg(vregA, SafeAdd(shadow_frame.GetVReg(vregA),
+                                            shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
         inst = inst->Next_1xx();
         break;
       }
@@ -1734,8 +1735,8 @@
         PREAMBLE();
         uint4_t vregA = inst->VRegA_12x(inst_data);
         shadow_frame.SetVReg(vregA,
-                             shadow_frame.GetVReg(vregA) -
-                             shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
+                             SafeSub(shadow_frame.GetVReg(vregA),
+                                     shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
         inst = inst->Next_1xx();
         break;
       }
@@ -1743,8 +1744,8 @@
         PREAMBLE();
         uint4_t vregA = inst->VRegA_12x(inst_data);
         shadow_frame.SetVReg(vregA,
-                             shadow_frame.GetVReg(vregA) *
-                             shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
+                             SafeMul(shadow_frame.GetVReg(vregA),
+                                     shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
         inst = inst->Next_1xx();
         break;
       }
@@ -1822,8 +1823,8 @@
         PREAMBLE();
         uint4_t vregA = inst->VRegA_12x(inst_data);
         shadow_frame.SetVRegLong(vregA,
-                                 shadow_frame.GetVRegLong(vregA) +
-                                 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
+                                 SafeAdd(shadow_frame.GetVRegLong(vregA),
+                                         shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data))));
         inst = inst->Next_1xx();
         break;
       }
@@ -1831,8 +1832,8 @@
         PREAMBLE();
         uint4_t vregA = inst->VRegA_12x(inst_data);
         shadow_frame.SetVRegLong(vregA,
-                                 shadow_frame.GetVRegLong(vregA) -
-                                 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
+                                 SafeSub(shadow_frame.GetVRegLong(vregA),
+                                         shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data))));
         inst = inst->Next_1xx();
         break;
       }
@@ -1840,8 +1841,8 @@
         PREAMBLE();
         uint4_t vregA = inst->VRegA_12x(inst_data);
         shadow_frame.SetVRegLong(vregA,
-                                 shadow_frame.GetVRegLong(vregA) *
-                                 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
+                                 SafeMul(shadow_frame.GetVRegLong(vregA),
+                                         shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data))));
         inst = inst->Next_1xx();
         break;
       }
@@ -2008,22 +2009,22 @@
       case Instruction::ADD_INT_LIT16:
         PREAMBLE();
         shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
-                             shadow_frame.GetVReg(inst->VRegB_22s(inst_data)) +
-                             inst->VRegC_22s());
+                             SafeAdd(shadow_frame.GetVReg(inst->VRegB_22s(inst_data)),
+                                     inst->VRegC_22s()));
         inst = inst->Next_2xx();
         break;
-      case Instruction::RSUB_INT:
+      case Instruction::RSUB_INT_LIT16:
         PREAMBLE();
         shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
-                             inst->VRegC_22s() -
-                             shadow_frame.GetVReg(inst->VRegB_22s(inst_data)));
+                             SafeSub(inst->VRegC_22s(),
+                                     shadow_frame.GetVReg(inst->VRegB_22s(inst_data))));
         inst = inst->Next_2xx();
         break;
       case Instruction::MUL_INT_LIT16:
         PREAMBLE();
         shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
-                             shadow_frame.GetVReg(inst->VRegB_22s(inst_data)) *
-                             inst->VRegC_22s());
+                             SafeMul(shadow_frame.GetVReg(inst->VRegB_22s(inst_data)),
+                                     inst->VRegC_22s()));
         inst = inst->Next_2xx();
         break;
       case Instruction::DIV_INT_LIT16: {
@@ -2064,22 +2065,19 @@
       case Instruction::ADD_INT_LIT8:
         PREAMBLE();
         shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
-                             shadow_frame.GetVReg(inst->VRegB_22b()) +
-                             inst->VRegC_22b());
+                             SafeAdd(shadow_frame.GetVReg(inst->VRegB_22b()), inst->VRegC_22b()));
         inst = inst->Next_2xx();
         break;
       case Instruction::RSUB_INT_LIT8:
         PREAMBLE();
         shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
-                             inst->VRegC_22b() -
-                             shadow_frame.GetVReg(inst->VRegB_22b()));
+                             SafeSub(inst->VRegC_22b(), shadow_frame.GetVReg(inst->VRegB_22b())));
         inst = inst->Next_2xx();
         break;
       case Instruction::MUL_INT_LIT8:
         PREAMBLE();
         shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
-                             shadow_frame.GetVReg(inst->VRegB_22b()) *
-                             inst->VRegC_22b());
+                             SafeMul(shadow_frame.GetVReg(inst->VRegB_22b()), inst->VRegC_22b()));
         inst = inst->Next_2xx();
         break;
       case Instruction::DIV_INT_LIT8: {
diff --git a/runtime/interpreter/safe_math.h b/runtime/interpreter/safe_math.h
new file mode 100644
index 0000000..78b3539
--- /dev/null
+++ b/runtime/interpreter/safe_math.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef ART_RUNTIME_INTERPRETER_SAFE_MATH_H_
+#define ART_RUNTIME_INTERPRETER_SAFE_MATH_H_
+
+#include <functional>
+#include <type_traits>
+
+namespace art {
+namespace interpreter {
+
+// Declares a type which is the larger in bit size of the two template parameters.
+template <typename T1, typename T2>
+struct select_bigger {
+  typedef typename std::conditional<sizeof(T1) >= sizeof(T2), T1, T2>::type type;
+};
+
+// Perform signed arithmetic Op on 'a' and 'b' with defined wrapping behavior.
+template<template <typename OpT> class Op, typename T1, typename T2>
+static inline typename select_bigger<T1, T2>::type SafeMath(T1 a, T2 b) {
+  typedef typename select_bigger<T1, T2>::type biggest_T;
+  typedef typename std::make_unsigned<biggest_T>::type unsigned_biggest_T;
+  static_assert(std::is_signed<T1>::value, "Expected T1 to be signed");
+  static_assert(std::is_signed<T2>::value, "Expected T2 to be signed");
+  unsigned_biggest_T val1 = static_cast<unsigned_biggest_T>(static_cast<biggest_T>(a));
+  unsigned_biggest_T val2 = static_cast<unsigned_biggest_T>(b);
+  return static_cast<biggest_T>(Op<unsigned_biggest_T>()(val1, val2));
+}
+
+// Perform signed a signed add on 'a' and 'b' with defined wrapping behavior.
+template<typename T1, typename T2>
+static inline typename select_bigger<T1, T2>::type SafeAdd(T1 a, T2 b) {
+  return SafeMath<std::plus>(a, b);
+}
+
+// Perform signed a signed substract on 'a' and 'b' with defined wrapping behavior.
+template<typename T1, typename T2>
+static inline typename select_bigger<T1, T2>::type SafeSub(T1 a, T2 b) {
+  return SafeMath<std::minus>(a, b);
+}
+
+// Perform signed a signed multiply on 'a' and 'b' with defined wrapping behavior.
+template<typename T1, typename T2>
+static inline typename select_bigger<T1, T2>::type SafeMul(T1 a, T2 b) {
+  return SafeMath<std::multiplies>(a, b);
+}
+
+}  // namespace interpreter
+}  // namespace art
+
+#endif  // ART_RUNTIME_INTERPRETER_SAFE_MATH_H_
diff --git a/runtime/mirror/art_method-inl.h b/runtime/mirror/art_method-inl.h
index ca361f8..494fa2f 100644
--- a/runtime/mirror/art_method-inl.h
+++ b/runtime/mirror/art_method-inl.h
@@ -68,6 +68,10 @@
   return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, method_index_));
 }
 
+inline uint16_t ArtMethod::GetMethodIndexDuringLinking() {
+  return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, method_index_));
+}
+
 inline uint32_t ArtMethod::GetDexMethodIndex() {
 #ifdef ART_SEA_IR_MODE
   // TODO: Re-add this check for (PORTABLE + SMALL + ) SEA IR when PORTABLE IS fixed!
diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h
index 6927f1d..08c0996 100644
--- a/runtime/mirror/art_method.h
+++ b/runtime/mirror/art_method.h
@@ -178,6 +178,9 @@
 
   uint16_t GetMethodIndex() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  // Doesn't do erroneous / unresolved class checks.
+  uint16_t GetMethodIndexDuringLinking() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   size_t GetVtableIndex() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     return GetMethodIndex();
   }
diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc
index 9578c97..4227723 100644
--- a/runtime/mirror/object.cc
+++ b/runtime/mirror/object.cc
@@ -135,11 +135,11 @@
   return copy;
 }
 
-int32_t Object::GenerateIdentityHashCode() {
-  static AtomicInteger seed(987654321 + std::time(nullptr));
-  int32_t expected_value, new_value;
+uint32_t Object::GenerateIdentityHashCode() {
+  static Atomic<uint32_t> seed(987654321U + std::time(nullptr));
+  uint32_t expected_value, new_value;
   do {
-    expected_value = static_cast<uint32_t>(seed.LoadRelaxed());
+    expected_value = seed.LoadRelaxed();
     new_value = expected_value * 1103515245 + 12345;
   } while ((expected_value & LockWord::kHashMask) == 0 ||
       !seed.CompareExchangeWeakRelaxed(expected_value, new_value));
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index b2b2420..0ce5231 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -451,7 +451,7 @@
   }
 
   // Generate an identity hash code.
-  static int32_t GenerateIdentityHashCode();
+  static uint32_t GenerateIdentityHashCode();
 
   // A utility function that copies an object in a read barrier and
   // write barrier-aware way. This is internally used by Clone() and
diff --git a/runtime/utf.cc b/runtime/utf.cc
index 02cbe3b..735815d 100644
--- a/runtime/utf.cc
+++ b/runtime/utf.cc
@@ -70,27 +70,27 @@
 
 int32_t ComputeUtf16Hash(mirror::CharArray* chars, int32_t offset,
                          size_t char_count) {
-  int32_t hash = 0;
+  uint32_t hash = 0;
   for (size_t i = 0; i < char_count; i++) {
     hash = hash * 31 + chars->Get(offset + i);
   }
-  return hash;
+  return static_cast<int32_t>(hash);
 }
 
 int32_t ComputeUtf16Hash(const uint16_t* chars, size_t char_count) {
-  int32_t hash = 0;
+  uint32_t hash = 0;
   while (char_count--) {
     hash = hash * 31 + *chars++;
   }
-  return hash;
+  return static_cast<int32_t>(hash);
 }
 
 int32_t ComputeUtf8Hash(const char* chars) {
-  int32_t hash = 0;
+  uint32_t hash = 0;
   while (*chars != '\0') {
     hash = hash * 31 + GetUtf16FromUtf8(&chars);
   }
-  return hash;
+  return static_cast<int32_t>(hash);
 }
 
 int CompareModifiedUtf8ToUtf16AsCodePointValues(const char* utf8_1, const uint16_t* utf8_2) {
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 6e792d4..7380a50 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -2650,7 +2650,7 @@
                                          reg_types_.DoubleLo(), reg_types_.DoubleHi());
       break;
     case Instruction::ADD_INT_LIT16:
-    case Instruction::RSUB_INT:
+    case Instruction::RSUB_INT_LIT16:
     case Instruction::MUL_INT_LIT16:
     case Instruction::DIV_INT_LIT16:
     case Instruction::REM_INT_LIT16:
diff --git a/test/117-nopatchoat/expected.txt b/test/117-nopatchoat/expected.txt
index a1293ae..5cc02d1 100644
--- a/test/117-nopatchoat/expected.txt
+++ b/test/117-nopatchoat/expected.txt
@@ -1,9 +1,9 @@
 Run without dex2oat/patchoat
-dex2oat & patchoat are disabled, has oat is true, has executable oat is false.
+dex2oat & patchoat are disabled, has oat is true, has executable oat is expected.
 This is a function call
 Run with dexoat/patchoat
-dex2oat & patchoat are enabled, has oat is true, has executable oat is true.
+dex2oat & patchoat are enabled, has oat is true, has executable oat is expected.
 This is a function call
 Run default
-dex2oat & patchoat are enabled, has oat is true, has executable oat is true.
+dex2oat & patchoat are enabled, has oat is true, has executable oat is expected.
 This is a function call
diff --git a/test/117-nopatchoat/nopatchoat.cc b/test/117-nopatchoat/nopatchoat.cc
index 5994653..da276f2 100644
--- a/test/117-nopatchoat/nopatchoat.cc
+++ b/test/117-nopatchoat/nopatchoat.cc
@@ -24,18 +24,41 @@
 
 class NoPatchoatTest {
  public:
-  static bool hasExecutableOat(jclass cls) {
+  static const OatFile::OatDexFile* getOatDexFile(jclass cls) {
     ScopedObjectAccess soa(Thread::Current());
     mirror::Class* klass = soa.Decode<mirror::Class*>(cls);
     const DexFile& dex_file = klass->GetDexFile();
+
     const OatFile::OatDexFile* oat_dex_file =
         Runtime::Current()->GetClassLinker()->FindOpenedOatDexFileForDexFile(dex_file);
+
+    return oat_dex_file;
+  }
+
+  static bool hasExecutableOat(jclass cls) {
+    const OatFile::OatDexFile* oat_dex_file = getOatDexFile(cls);
+
     return oat_dex_file != nullptr && oat_dex_file->GetOatFile()->IsExecutable();
   }
+
+  static bool isPic(jclass cls) {
+    const OatFile::OatDexFile* oat_dex_file = getOatDexFile(cls);
+
+    if (oat_dex_file == nullptr) {
+      return false;
+    }
+
+    const OatFile* oat_file = oat_dex_file->GetOatFile();
+    return oat_file->IsPic();
+  }
 };
 
 extern "C" JNIEXPORT jboolean JNICALL Java_Main_hasExecutableOat(JNIEnv*, jclass cls) {
   return NoPatchoatTest::hasExecutableOat(cls);
 }
 
+extern "C" JNIEXPORT jboolean JNICALL Java_Main_isPic(JNIEnv*, jclass cls) {
+  return NoPatchoatTest::isPic(cls);
+}
+
 }  // namespace art
diff --git a/test/117-nopatchoat/src/Main.java b/test/117-nopatchoat/src/Main.java
index f3f91ce..7bc9dbb 100644
--- a/test/117-nopatchoat/src/Main.java
+++ b/test/117-nopatchoat/src/Main.java
@@ -16,9 +16,14 @@
 
 public class Main {
   public static void main(String[] args) {
+    boolean executable_correct = (isPic() ?
+                                  hasExecutableOat() == true :
+                                  hasExecutableOat() == isDex2OatEnabled());
+
     System.out.println(
         "dex2oat & patchoat are " + ((isDex2OatEnabled()) ? "enabled" : "disabled") +
-        ", has oat is " + hasOat() + ", has executable oat is " + hasExecutableOat() + ".");
+        ", has oat is " + hasOat() + ", has executable oat is " + (
+        executable_correct ? "expected" : "not expected") + ".");
 
     if (!hasOat() && isDex2OatEnabled()) {
       throw new Error("Application with dex2oat enabled runs without an oat file");
@@ -42,6 +47,8 @@
 
   private native static boolean isDex2OatEnabled();
 
+  private native static boolean isPic();
+
   private native static boolean hasOat();
 
   private native static boolean hasExecutableOat();