Merge "Port 311886c6c6fcd3b531531f592d56caab5e2a259c to art." into dalvik-dev
diff --git a/Android.mk b/Android.mk
index 6de5eff..cd96c52 100644
--- a/Android.mk
+++ b/Android.mk
@@ -177,7 +177,7 @@
 define declare-oat-target-target
 .PHONY: oat-target-$(1)
 oat-target-$(1): $(PRODUCT_OUT)/$(1) $(TARGET_BOOT_IMG_OUT) $(DEX2OAT_DEPENDENCY)
-	$(DEX2OAT) --runtime-arg -Xms64m --runtime-arg -Xmx64m --boot-image=$(TARGET_BOOT_IMG_OUT) --dex-file=$(PRODUCT_OUT)/$(1) --dex-location=/$(1) --oat-file=$(call art-cache-out,$(1).oat) --host-prefix=$(PRODUCT_OUT)
+	$(DEX2OAT) $(PARALLEL_ART_COMPILE_JOBS) --runtime-arg -Xms64m --runtime-arg -Xmx64m --boot-image=$(TARGET_BOOT_IMG_OUT) --dex-file=$(PRODUCT_OUT)/$(1) --dex-location=/$(1) --oat-file=$(call art-cache-out,$(1).oat) --host-prefix=$(PRODUCT_OUT)
 
 OAT_TARGET_TARGETS += oat-target-$(1)
 endef
diff --git a/build/Android.common.mk b/build/Android.common.mk
index e62602c..cec90e6 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -79,8 +79,9 @@
 ART_HOST_NON_DEBUG_CFLAGS := $(art_non_debug_cflags)
 ART_TARGET_NON_DEBUG_CFLAGS := $(art_non_debug_cflags)
 
-# TODO: move -fkeep-inline-functions to art_debug_cflags when target gcc > 4.4
+# TODO: move -fkeep-inline-functions to art_debug_cflags when target gcc > 4.4 (and -lsupc++)
 ART_HOST_DEBUG_CFLAGS := $(art_debug_cflags) -fkeep-inline-functions
+ART_HOST_DEBUG_LDLIBS := -lsupc++
 
 ifneq ($(HOST_OS),linux)
   # Some Mac OS pthread header files are broken with -fkeep-inline-functions.
@@ -89,6 +90,10 @@
 
 ART_TARGET_DEBUG_CFLAGS := $(art_debug_cflags)
 
+ifeq ($(ART_USE_LLVM_COMPILER),true)
+PARALLEL_ART_COMPILE_JOBS := -j8
+endif
+
 DEX2OAT_SRC_FILES := \
 	src/dex2oat.cc
 
@@ -96,6 +101,7 @@
 	src/oatdump.cc \
 	src/disassembler.cc \
 	src/disassembler_arm.cc \
+	src/disassembler_mips.cc \
 	src/disassembler_x86.cc
 
 OATEXEC_SRC_FILES := \
diff --git a/build/Android.libart-compiler-llvm.mk b/build/Android.libart-compiler-llvm.mk
index d52e6d2..c2ecf20 100644
--- a/build/Android.libart-compiler-llvm.mk
+++ b/build/Android.libart-compiler-llvm.mk
@@ -21,7 +21,6 @@
 	src/compiler_llvm/compilation_unit.cc \
 	src/compiler_llvm/compiler_llvm.cc \
 	src/compiler_llvm/dalvik_reg.cc \
-	src/compiler_llvm/frontend.cc \
 	src/compiler_llvm/generated/art_module.cc \
 	src/compiler_llvm/inferred_reg_category_map.cc \
 	src/compiler_llvm/ir_builder.cc \
diff --git a/build/Android.libart.mk b/build/Android.libart.mk
index c7a85ef..a6a7070 100644
--- a/build/Android.libart.mk
+++ b/build/Android.libart.mk
@@ -79,6 +79,7 @@
       LOCAL_CFLAGS += $(ART_TARGET_DEBUG_CFLAGS)
     else # host
       LOCAL_CFLAGS += $(ART_HOST_DEBUG_CFLAGS)
+      LOCAL_LDLIBS += $(ART_HOST_DEBUG_LDLIBS)
       LOCAL_STATIC_LIBRARIES := libgtest_host
     endif
   else
@@ -102,7 +103,7 @@
     LOCAL_STATIC_LIBRARIES += libcutils
     LOCAL_SHARED_LIBRARIES += libz-host
     LOCAL_SHARED_LIBRARIES += libdynamic_annotations-host # tsan support
-    LOCAL_LDLIBS := -ldl -lpthread
+    LOCAL_LDLIBS += -ldl -lpthread
     ifeq ($(HOST_OS),linux)
       LOCAL_LDLIBS += -lrt
     endif
diff --git a/build/Android.oat.mk b/build/Android.oat.mk
index 05bddf4..372992f 100644
--- a/build/Android.oat.mk
+++ b/build/Android.oat.mk
@@ -53,29 +53,15 @@
 HOST_CORE_IMG_OUT := $(HOST_OUT_JAVA_LIBRARIES)/core.art
 TARGET_CORE_IMG_OUT := $(ART_TEST_OUT)/core.art
 
-ifeq ($(ART_USE_LLVM_COMPILER),true)
- $(HOST_CORE_IMG_OUT): $(HOST_CORE_DEX_FILES) $(DEX2OAT_DEPENDENCY)
+$(HOST_CORE_IMG_OUT): $(HOST_CORE_DEX_FILES) $(DEX2OAT_DEPENDENCY)
 	@echo "host dex2oat: $@ ($?)"
 	@mkdir -p $(dir $@)
-	$(hide) $(DEX2OAT) -j8 --runtime-arg -Xms16m --runtime-arg -Xmx16m --image-classes=$(PRELOADED_CLASSES) $(addprefix --dex-file=,$(HOST_CORE_DEX_FILES)) $(addprefix --dex-location=,$(HOST_CORE_DEX_LOCATIONS)) --oat-file=$(HOST_CORE_OAT_OUT) --oat-location=$(HOST_CORE_OAT) --image=$(HOST_CORE_IMG_OUT) --base=$(IMG_HOST_BASE_ADDRESS) --instruction-set=X86
-else
- $(HOST_CORE_IMG_OUT): $(HOST_CORE_DEX_FILES) $(DEX2OAT_DEPENDENCY)
-	@echo "host dex2oat: $@ ($?)"
-	@mkdir -p $(dir $@)
-	$(hide) $(DEX2OAT) --runtime-arg -Xms16m --runtime-arg -Xmx16m --image-classes=$(PRELOADED_CLASSES) $(addprefix --dex-file=,$(HOST_CORE_DEX_FILES)) $(addprefix --dex-location=,$(HOST_CORE_DEX_LOCATIONS)) --oat-file=$(HOST_CORE_OAT_OUT) --oat-location=$(HOST_CORE_OAT) --image=$(HOST_CORE_IMG_OUT) --base=$(IMG_HOST_BASE_ADDRESS) --instruction-set=X86
-endif
+	$(hide) $(DEX2OAT) $(PARALLEL_ART_COMPILE_JOBS) --runtime-arg -Xms16m --runtime-arg -Xmx16m --image-classes=$(PRELOADED_CLASSES) $(addprefix --dex-file=,$(HOST_CORE_DEX_FILES)) $(addprefix --dex-location=,$(HOST_CORE_DEX_LOCATIONS)) --oat-file=$(HOST_CORE_OAT_OUT) --oat-location=$(HOST_CORE_OAT) --image=$(HOST_CORE_IMG_OUT) --base=$(IMG_HOST_BASE_ADDRESS) --instruction-set=X86
 
-ifeq ($(ART_USE_LLVM_COMPILER),true)
 $(TARGET_CORE_IMG_OUT): $(TARGET_CORE_DEX_FILES) $(DEX2OAT_DEPENDENCY)
 	@echo "target dex2oat: $@ ($?)"
 	@mkdir -p $(dir $@)
-	$(hide) $(DEX2OAT) -j8 --runtime-arg -Xms16m --runtime-arg -Xmx16m --image-classes=$(PRELOADED_CLASSES) $(addprefix --dex-file=,$(TARGET_CORE_DEX_FILES)) $(addprefix --dex-location=,$(TARGET_CORE_DEX_LOCATIONS)) --oat-file=$(TARGET_CORE_OAT_OUT) --oat-location=$(TARGET_CORE_OAT) --image=$(TARGET_CORE_IMG_OUT) --base=$(IMG_TARGET_BASE_ADDRESS) --host-prefix=$(PRODUCT_OUT)
-else
-$(TARGET_CORE_IMG_OUT): $(TARGET_CORE_DEX_FILES) $(DEX2OAT_DEPENDENCY)
-	@echo "target dex2oat: $@ ($?)"
-	@mkdir -p $(dir $@)
-	$(hide) $(DEX2OAT) --runtime-arg -Xms16m --runtime-arg -Xmx16m --image-classes=$(PRELOADED_CLASSES) $(addprefix --dex-file=,$(TARGET_CORE_DEX_FILES)) $(addprefix --dex-location=,$(TARGET_CORE_DEX_LOCATIONS)) --oat-file=$(TARGET_CORE_OAT_OUT) --oat-location=$(TARGET_CORE_OAT) --image=$(TARGET_CORE_IMG_OUT) --base=$(IMG_TARGET_BASE_ADDRESS) --host-prefix=$(PRODUCT_OUT)
-endif
+	$(hide) $(DEX2OAT) $(PARALLEL_ART_COMPILE_JOBS) --runtime-arg -Xms16m --runtime-arg -Xmx16m --image-classes=$(PRELOADED_CLASSES) $(addprefix --dex-file=,$(TARGET_CORE_DEX_FILES)) $(addprefix --dex-location=,$(TARGET_CORE_DEX_LOCATIONS)) --oat-file=$(TARGET_CORE_OAT_OUT) --oat-location=$(TARGET_CORE_OAT) --image=$(TARGET_CORE_IMG_OUT) --base=$(IMG_TARGET_BASE_ADDRESS) --host-prefix=$(PRODUCT_OUT)
 
 $(HOST_CORE_OAT_OUT): $(HOST_CORE_IMG_OUT)
 
@@ -91,17 +77,10 @@
 TARGET_BOOT_OAT_OUT := $(patsubst %.art,%.oat,$(TARGET_BOOT_IMG_OUT))
 TARGET_BOOT_OAT := $(subst $(PRODUCT_OUT),,$(TARGET_BOOT_OAT_OUT))
 
-ifeq ($(ART_USE_LLVM_COMPILER),true)
- $(TARGET_BOOT_IMG_OUT): $(TARGET_BOOT_DEX_FILES) $(DEX2OAT_DEPENDENCY)
+$(TARGET_BOOT_IMG_OUT): $(TARGET_BOOT_DEX_FILES) $(DEX2OAT_DEPENDENCY)
 	@echo "target dex2oat: $@ ($?)"
 	@mkdir -p $(dir $@)
-	$(hide) $(DEX2OAT) -j8 --runtime-arg -Xms256m --runtime-arg -Xmx256m --image-classes=$(PRELOADED_CLASSES) $(addprefix --dex-file=,$(TARGET_BOOT_DEX_FILES)) $(addprefix --dex-location=,$(TARGET_BOOT_DEX_LOCATIONS)) --oat-file=$(TARGET_BOOT_OAT_OUT) --oat-location=$(TARGET_BOOT_OAT) --image=$(TARGET_BOOT_IMG_OUT) --base=$(IMG_TARGET_BASE_ADDRESS) --host-prefix=$(PRODUCT_OUT)
-else
- $(TARGET_BOOT_IMG_OUT): $(TARGET_BOOT_DEX_FILES) $(DEX2OAT_DEPENDENCY)
-	@echo "target dex2oat: $@ ($?)"
-	@mkdir -p $(dir $@)
-	$(hide) $(DEX2OAT) --runtime-arg -Xms256m --runtime-arg -Xmx256m --image-classes=$(PRELOADED_CLASSES) $(addprefix --dex-file=,$(TARGET_BOOT_DEX_FILES)) $(addprefix --dex-location=,$(TARGET_BOOT_DEX_LOCATIONS)) --oat-file=$(TARGET_BOOT_OAT_OUT) --oat-location=$(TARGET_BOOT_OAT) --image=$(TARGET_BOOT_IMG_OUT) --base=$(IMG_TARGET_BASE_ADDRESS) --host-prefix=$(PRODUCT_OUT)
-endif
+	$(hide) $(DEX2OAT) $(PARALLEL_ART_COMPILE_JOBS) --runtime-arg -Xms256m --runtime-arg -Xmx256m --image-classes=$(PRELOADED_CLASSES) $(addprefix --dex-file=,$(TARGET_BOOT_DEX_FILES)) $(addprefix --dex-location=,$(TARGET_BOOT_DEX_LOCATIONS)) --oat-file=$(TARGET_BOOT_OAT_OUT) --oat-location=$(TARGET_BOOT_OAT) --image=$(TARGET_BOOT_IMG_OUT) --base=$(IMG_TARGET_BASE_ADDRESS) --host-prefix=$(PRODUCT_OUT)
 
 $(TARGET_BOOT_OAT_OUT): $(TARGET_BOOT_IMG_OUT)
 
diff --git a/src/atomic.cc b/src/atomic.cc
index 0625f1f..b923f91 100644
--- a/src/atomic.cc
+++ b/src/atomic.cc
@@ -16,73 +16,54 @@
 
 #include "atomic.h"
 
-#include <sched.h>
+#include <pthread.h>
+
+#include "mutex.h"
+#include "stl_util.h"
+#include "stringprintf.h"
+
+#if defined(__APPLE__)
+#include <libkern/OSAtomic.h>
+#endif
+#if defined(__arm__)
+#include <machine/cpu-features.h>
+#endif
 
 namespace art {
 
-/*
- * Quasi-atomic 64-bit operations, for platforms that lack the real thing.
- *
- * TODO: unify ARMv6/x86/sh implementations using the to-be-written
- * spin lock implementation.  We don't want to rely on mutex innards,
- * and it would be great if all platforms were running the same code.
- */
-
 #if defined(HAVE_MACOSX_IPC)
-
-#include <libkern/OSAtomic.h>
-
-#if defined(__ppc__)        \
-    || defined(__PPC__)     \
-    || defined(__powerpc__) \
-    || defined(__powerpc)   \
-    || defined(__POWERPC__) \
-    || defined(_M_PPC)      \
-    || defined(__PPC)
-#define NEED_QUASIATOMICS 1
-#else
-
-int QuasiAtomicCas64(int64_t old_value, int64_t new_value, volatile int64_t* addr) {
-  return OSAtomicCompareAndSwap64Barrier(old_value, new_value, const_cast<int64_t*>(addr)) == 0;
-}
-
-static inline int64_t QuasiAtomicSwap64Impl(int64_t value, volatile int64_t* addr) {
-  int64_t old_value;
-  do {
-    old_value = *addr;
-  } while (QuasiAtomicCas64(old_value, value, addr));
-  return old_value;
-}
-
-int64_t QuasiAtomicSwap64(int64_t value, volatile int64_t* addr) {
-  return QuasiAtomicSwap64Impl(value, addr);
-}
-
-int64_t QuasiAtomicSwap64Sync(int64_t value, volatile int64_t* addr) {
-  ANDROID_MEMBAR_STORE();
-  int64_t old_value = QuasiAtomicSwap64Impl(value, addr);
-  /* TUNING: barriers can be avoided on some architectures */
-  ANDROID_MEMBAR_FULL();
-  return old_value;
-}
-
-int64_t QuasiAtomicRead64(volatile const int64_t* addr) {
-  return OSAtomicAdd64Barrier(0, const_cast<volatile int64_t*>(addr));
-}
-#endif
+#define NEED_MAC_QUASI_ATOMICS 1
 
 #elif defined(__i386__) || defined(__x86_64__)
-#define NEED_QUASIATOMICS 1
+#define NEED_PTHREADS_QUASI_ATOMICS 1
 
-#elif __arm__
-#include <machine/cpu-features.h>
+#elif defined(__mips__)
+#define NEED_PTHREADS_QUASI_ATOMICS 1
 
-#ifdef __ARM_HAVE_LDREXD
+#elif defined(__arm__)
+
+#if defined(__ARM_HAVE_LDREXD)
+#define NEED_ARM_LDREXD_QUASI_ATOMICS 1
+#else
+#define NEED_PTHREADS_QUASI_ATOMICS 1
+#endif
+
+#elif defined(__sh__)
+#define NEED_PTHREADS_QUASI_ATOMICS 1
+
+#else
+#error "QuasiAtomic unsupported on this platform"
+#endif
+
+// *****************************************************************************
+
+#if NEED_ARM_LDREXD_QUASI_ATOMICS
+
 static inline int64_t QuasiAtomicSwap64Impl(int64_t new_value, volatile int64_t* addr) {
   int64_t prev;
   int status;
   do {
-    __asm__ __volatile__("@ QuasiAtomicSwap64\n"
+    __asm__ __volatile__("@ QuasiAtomic::Swap64\n"
         "ldrexd     %0, %H0, [%3]\n"
         "strexd     %1, %4, %H4, [%3]"
         : "=&r" (prev), "=&r" (status), "+m"(*addr)
@@ -92,22 +73,31 @@
   return prev;
 }
 
-int64_t QuasiAtomicSwap64(int64_t new_value, volatile int64_t* addr) {
+int64_t QuasiAtomic::Swap64(int64_t new_value, volatile int64_t* addr) {
   return QuasiAtomicSwap64Impl(new_value, addr);
 }
 
-int64_t QuasiAtomicSwap64Sync(int64_t new_value, volatile int64_t* addr) {
+int64_t QuasiAtomic::Swap64Sync(int64_t new_value, volatile int64_t* addr) {
   ANDROID_MEMBAR_STORE();
   int64_t old_value = QuasiAtomicSwap64Impl(new_value, addr);
   ANDROID_MEMBAR_FULL();
   return old_value;
 }
 
-int QuasiAtomicCas64(int64_t old_value, int64_t new_value, volatile int64_t* addr) {
+int64_t QuasiAtomic::Read64(volatile const int64_t* addr) {
+  int64_t value;
+  __asm__ __volatile__("@ QuasiAtomic::Read64\n"
+      "ldrexd     %0, %H0, [%1]"
+      : "=&r" (value)
+      : "r" (addr));
+  return value;
+}
+
+int QuasiAtomic::Cas64(int64_t old_value, int64_t new_value, volatile int64_t* addr) {
   int64_t prev;
   int status;
   do {
-    __asm__ __volatile__("@ QuasiAtomicCas64\n"
+    __asm__ __volatile__("@ QuasiAtomic::Cas64\n"
         "ldrexd     %0, %H0, [%3]\n"
         "mov        %1, #0\n"
         "teq        %0, %4\n"
@@ -120,180 +110,101 @@
   return prev != old_value;
 }
 
-int64_t QuasiAtomicRead64(volatile const int64_t* addr) {
-  int64_t value;
-  __asm__ __volatile__("@ QuasiAtomicRead64\n"
-      "ldrexd     %0, %H0, [%1]"
-      : "=&r" (value)
-      : "r" (addr));
-  return value;
-}
+#endif
 
-#else
+// *****************************************************************************
 
-// on the device, we implement the 64-bit atomic operations through
-// mutex locking. normally, this is bad because we must initialize
-// a pthread_mutex_t before being able to use it, and this means
-// having to do an initialization check on each function call, and
-// that's where really ugly things begin...
-//
-// BUT, as a special twist, we take advantage of the fact that in our
-// pthread library, a mutex is simply a volatile word whose value is always
-// initialized to 0. In other words, simply declaring a static mutex
-// object initializes it !
-//
-// another twist is that we use a small array of mutexes to dispatch
-// the contention locks from different memory addresses
-//
+#if NEED_MAC_QUASI_ATOMICS
 
-#include <pthread.h>
-
-#define SWAP_LOCK_COUNT  32U
-static pthread_mutex_t  _swap_locks[SWAP_LOCK_COUNT];
-
-#define SWAP_LOCK(addr) &_swap_locks[((unsigned)(void*)(addr) >> 3U) % SWAP_LOCK_COUNT]
-
-int64_t QuasiAtomicSwap64(int64_t value, volatile int64_t* addr) {
-  pthread_mutex_t*  lock = SWAP_LOCK(addr);
-
-  pthread_mutex_lock(lock);
-
-  int64_t old_value = *addr;
-  *addr = value;
-
-  pthread_mutex_unlock(lock);
+static inline int64_t QuasiAtomicSwap64Impl(int64_t value, volatile int64_t* addr) {
+  int64_t old_value;
+  do {
+    old_value = *addr;
+  } while (QuasiAtomic::Cas64(old_value, value, addr));
   return old_value;
 }
 
-int64_t QuasiAtomicSwap64Sync(int64_t value, volatile int64_t* addr) {
-  // Same as QuasiAtomicSwap64 - mutex handles barrier.
-  return QuasiAtomicSwap64(value, addr);
+int64_t QuasiAtomic::Swap64(int64_t value, volatile int64_t* addr) {
+  return QuasiAtomicSwap64Impl(value, addr);
 }
 
-int QuasiAtomicCas64(int64_t old_value, int64_t new_value, volatile int64_t* addr) {
-  int result;
-  pthread_mutex_t*  lock = SWAP_LOCK(addr);
+int64_t QuasiAtomic::Swap64Sync(int64_t value, volatile int64_t* addr) {
+  ANDROID_MEMBAR_STORE();
+  int64_t old_value = QuasiAtomicSwap64Impl(value, addr);
+  // TUNING: barriers can be avoided on some architectures.
+  ANDROID_MEMBAR_FULL();
+  return old_value;
+}
 
-  pthread_mutex_lock(lock);
+int64_t QuasiAtomic::Read64(volatile const int64_t* addr) {
+  return OSAtomicAdd64Barrier(0, const_cast<volatile int64_t*>(addr));
+}
 
+int QuasiAtomic::Cas64(int64_t old_value, int64_t new_value, volatile int64_t* addr) {
+  return OSAtomicCompareAndSwap64Barrier(old_value, new_value, const_cast<int64_t*>(addr)) == 0;
+}
+
+#endif
+
+// *****************************************************************************
+
+#if NEED_PTHREADS_QUASI_ATOMICS
+
+// In the absence of a better implementation, we implement the 64-bit atomic
+// operations through mutex locking.
+
+// We stripe across a bunch of different mutexes to reduce contention.
+static const size_t kSwapLockCount = 32;
+static std::vector<Mutex*>* gSwapLocks;
+
+void QuasiAtomic::Startup() {
+  gSwapLocks = new std::vector<Mutex*>;
+  for (size_t i = 0; i < kSwapLockCount; ++i) {
+    gSwapLocks->push_back(new Mutex(StringPrintf("QuasiAtomic stripe %d", i).c_str()));
+  }
+}
+
+void QuasiAtomic::Shutdown() {
+  STLDeleteElements(gSwapLocks);
+  delete gSwapLocks;
+}
+
+static inline Mutex& GetSwapLock(const volatile int64_t* addr) {
+  return *(*gSwapLocks)[((unsigned)(void*)(addr) >> 3U) % kSwapLockCount];
+}
+
+int64_t QuasiAtomic::Swap64(int64_t value, volatile int64_t* addr) {
+  MutexLock mu(GetSwapLock(addr));
+  int64_t old_value = *addr;
+  *addr = value;
+  return old_value;
+}
+
+int64_t QuasiAtomic::Swap64Sync(int64_t value, volatile int64_t* addr) {
+  // Same as QuasiAtomicSwap64 - mutex handles barrier.
+  return QuasiAtomic::Swap64(value, addr);
+}
+
+int QuasiAtomic::Cas64(int64_t old_value, int64_t new_value, volatile int64_t* addr) {
+  MutexLock mu(GetSwapLock(addr));
   if (*addr == old_value) {
     *addr  = new_value;
-    result = 0;
-  } else {
-    result = 1;
+    return 0;
   }
-  pthread_mutex_unlock(lock);
-  return result;
+  return 1;
 }
 
-int64_t QuasiAtomicRead64(volatile const int64_t* addr) {
-  int64_t result;
-  pthread_mutex_t*  lock = SWAP_LOCK(addr);
-
-  pthread_mutex_lock(lock);
-  result = *addr;
-  pthread_mutex_unlock(lock);
-  return result;
+int64_t QuasiAtomic::Read64(volatile const int64_t* addr) {
+  MutexLock mu(GetSwapLock(addr));
+  return *addr;
 }
 
-#endif /*__ARM_HAVE_LDREXD*/
-
-/*****************************************************************************/
-#elif __sh__
-#define NEED_QUASIATOMICS 1
-
 #else
-#error "Unsupported atomic operations for this platform"
+
+// The other implementations don't need any special setup.
+void QuasiAtomic::Startup() {}
+void QuasiAtomic::Shutdown() {}
+
 #endif
 
-
-#if NEED_QUASIATOMICS
-
-/* Note that a spinlock is *not* a good idea in general
- * since they can introduce subtle issues. For example,
- * a real-time thread trying to acquire a spinlock already
- * acquired by another thread will never yeld, making the
- * CPU loop endlessly!
- *
- * However, this code is only used on the Linux simulator
- * so it's probably ok for us.
- *
- * The alternative is to use a pthread mutex, but
- * these must be initialized before being used, and
- * then you have the problem of lazily initializing
- * a mutex without any other synchronization primitive.
- *
- * TODO: these currently use sched_yield(), which is not guaranteed to
- * do anything at all.  We need to use dvmIterativeSleep or a wait /
- * notify mechanism if the initial attempt fails.
- */
-
-/* global spinlock for all 64-bit quasiatomic operations */
-static int32_t quasiatomic_spinlock = 0;
-
-int QuasiAtomicCas64(int64_t old_value, int64_t new_value, volatile int64_t* addr) {
-  int result;
-
-  while (android_atomic_acquire_cas(0, 1, &quasiatomic_spinlock)) {
-#ifdef HAVE_WIN32_THREADS
-    Sleep(0);
-#else
-    sched_yield();
-#endif
-  }
-
-  if (*addr == old_value) {
-    *addr = new_value;
-    result = 0;
-  } else {
-    result = 1;
-  }
-
-  android_atomic_release_store(0, &quasiatomic_spinlock);
-
-  return result;
-}
-
-int64_t QuasiAtomicRead64(volatile const int64_t* addr) {
-  int64_t result;
-
-  while (android_atomic_acquire_cas(0, 1, &quasiatomic_spinlock)) {
-#ifdef HAVE_WIN32_THREADS
-    Sleep(0);
-#else
-    sched_yield();
-#endif
-  }
-
-  result = *addr;
-  android_atomic_release_store(0, &quasiatomic_spinlock);
-
-  return result;
-}
-
-int64_t QuasiAtomicSwap64(int64_t value, volatile int64_t* addr) {
-  int64_t result;
-
-  while (android_atomic_acquire_cas(0, 1, &quasiatomic_spinlock)) {
-#ifdef HAVE_WIN32_THREADS
-    Sleep(0);
-#else
-    sched_yield();
-#endif
-  }
-
-  result = *addr;
-  *addr = value;
-  android_atomic_release_store(0, &quasiatomic_spinlock);
-
-  return result;
-}
-
-int64_t QuasiAtomicSwap64Sync(int64_t value, volatile int64_t* addr) {
-  // Same as QuasiAtomicSwap64 - syscall handles barrier.
-  return QuasiAtomicSwap64(value, addr);
-}
-
-#endif /*NEED_QUASIATOMICS*/
-
 }  // namespace art
diff --git a/src/atomic.h b/src/atomic.h
index dab625e..c6c0f7d 100644
--- a/src/atomic.h
+++ b/src/atomic.h
@@ -17,44 +17,46 @@
 #ifndef ART_SRC_ATOMIC_H_
 #define ART_SRC_ATOMIC_H_
 
-#include <cutils/atomic.h>          /* use common Android atomic ops */
-#include <cutils/atomic-inline.h>   /* and some uncommon ones */
+#include <stdint.h>
+
+#include "cutils/atomic.h"
+#include "cutils/atomic-inline.h"
+#include "macros.h"
 
 namespace art {
 
-/*
- * NOTE: Two "quasiatomic" operations on the exact same memory address
- * are guaranteed to operate atomically with respect to each other,
- * but no guarantees are made about quasiatomic operations mixed with
- * non-quasiatomic operations on the same address, nor about
- * quasiatomic operations that are performed on partially-overlapping
- * memory.
- *
- * Only the "Sync" functions provide a memory barrier.
- */
+// NOTE: Two "quasiatomic" operations on the exact same memory address
+// are guaranteed to operate atomically with respect to each other,
+// but no guarantees are made about quasiatomic operations mixed with
+// non-quasiatomic operations on the same address, nor about
+// quasiatomic operations that are performed on partially-overlapping
+// memory.
+//
+// Only the "Sync" functions provide a memory barrier.
+class QuasiAtomic {
+ public:
+  static void Startup();
 
-/*
- * Swap the 64-bit value at "addr" with "value".  Returns the previous
- * value. No memory barriers.
- */
-int64_t QuasiAtomicSwap64(int64_t value, volatile int64_t* addr);
+  static void Shutdown();
 
-/*
- * Swap the 64-bit value at "addr" with "value".  Returns the previous
- * value. Provides memory barriers.
- */
-int64_t QuasiAtomicSwap64Sync(int64_t value, volatile int64_t* addr);
+  // Swaps the 64-bit value at "addr" with "value".  Returns the previous
+  // value. No memory barriers.
+  static int64_t Swap64(int64_t value, volatile int64_t* addr);
 
-/*
- * Read the 64-bit value at "addr".
- */
-int64_t QuasiAtomicRead64(volatile const int64_t* addr);
+  // Swaps the 64-bit value at "addr" with "value".  Returns the previous
+  // value. Provides memory barriers.
+  static int64_t Swap64Sync(int64_t value, volatile int64_t* addr);
 
-/*
- * If the value at "addr" is equal to "old_value", replace it with "new_value"
- * and return 0.  Otherwise, don't swap, and return nonzero.
- */
-int QuasiAtomicCas64(int64_t old_value, int64_t new_value, volatile int64_t* addr);
+  // Reads the 64-bit value at "addr".
+  static int64_t Read64(volatile const int64_t* addr);
+
+  // If the value at "addr" is equal to "old_value", replace it with "new_value"
+  // and return 0. Otherwise, don't swap, and return nonzero.
+  static int Cas64(int64_t old_value, int64_t new_value, volatile int64_t* addr);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(QuasiAtomic);
+};
 
 }  // namespace art
 
diff --git a/src/compiled_method.cc b/src/compiled_method.cc
index 2340cbd..980fdc9 100644
--- a/src/compiled_method.cc
+++ b/src/compiled_method.cc
@@ -134,10 +134,12 @@
     case kArm:
     case kThumb2:
       return RoundUp(offset, kArmAlignment);
+    case kMips:
+      return RoundUp(offset, kMipsAlignment);
     case kX86:
       return RoundUp(offset, kX86Alignment);
     default:
-      LOG(FATAL) << "Unknown InstructionSet: " << static_cast<int>(instruction_set);
+      LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
       return 0;
   }
 }
@@ -145,6 +147,7 @@
 size_t CompiledMethod::CodeDelta() const {
   switch (instruction_set_) {
     case kArm:
+    case kMips:
     case kX86:
       return 0;
     case kThumb2: {
@@ -152,7 +155,7 @@
       return 1;
     }
     default:
-      LOG(FATAL) << "Unknown InstructionSet: " << static_cast<int>(instruction_set_);
+      LOG(FATAL) << "Unknown InstructionSet: " << instruction_set_;
       return 0;
   }
 }
@@ -161,6 +164,7 @@
                                         InstructionSet instruction_set) {
   switch (instruction_set) {
     case kArm:
+    case kMips:
     case kX86:
       return code_pointer;
     case kThumb2: {
@@ -170,7 +174,7 @@
       return reinterpret_cast<const void*>(address);
     }
     default:
-      LOG(FATAL) << "Unknown InstructionSet: " << static_cast<int>(instruction_set);
+      LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
       return NULL;
   }
 }
diff --git a/src/compiler/codegen/mips/Mips32/Factory.cc b/src/compiler/codegen/mips/Mips32/Factory.cc
index 1162702..649aed3 100644
--- a/src/compiler/codegen/mips/Mips32/Factory.cc
+++ b/src/compiler/codegen/mips/Mips32/Factory.cc
@@ -434,7 +434,6 @@
                                 int rIndex, int rSrc, int scale, OpSize size)
 {
     LIR *first = NULL;
-    LIR *res;
     MipsOpCode opcode = kMipsNop;
     int rNewIndex = rIndex;
     int tReg = oatAllocTemp(cUnit);
@@ -477,7 +476,7 @@
         default:
             LOG(FATAL) << "Bad case in storeBaseIndexed";
     }
-    res = newLIR3(cUnit, opcode, rSrc, 0, tReg);
+    newLIR3(cUnit, opcode, rSrc, 0, tReg);
     oatFreeTemp(cUnit, rNewIndex);
     return first;
 }
diff --git a/src/compiler/codegen/x86/Assemble.cc b/src/compiler/codegen/x86/Assemble.cc
index d9cdabf..3a86bed 100644
--- a/src/compiler/codegen/x86/Assemble.cc
+++ b/src/compiler/codegen/x86/Assemble.cc
@@ -134,9 +134,9 @@
   { kX86Imul16RMI,   kRegMemImm,   IS_LOAD | IS_QUAD_OP     | SETS_CCODES, { 0x66, 0, 0x69, 0, 0, 0, 0, 2 }, "Imul16RMI", "!0r,[!1r+!2d],!3d" },
   { kX86Imul16RAI,   kRegArrayImm, IS_LOAD | IS_SEXTUPLE_OP | SETS_CCODES, { 0x66, 0, 0x69, 0, 0, 0, 0, 2 }, "Imul16RAI", "!0r,[!1r+!2r<<!3d+!4d],!5d" },
 
-  { kX86Imul32RRI,   kRegRegImm,             IS_TERTIARY_OP | SETS_CCODES, { 0, 0, 0x69, 0, 0, 0, 0, 2 }, "Imul32RRI", "!0r,!1r,!2d" },
-  { kX86Imul32RMI,   kRegMemImm,   IS_LOAD | IS_QUAD_OP     | SETS_CCODES, { 0, 0, 0x69, 0, 0, 0, 0, 2 }, "Imul32RMI", "!0r,[!1r+!2d],!3d" },
-  { kX86Imul32RAI,   kRegArrayImm, IS_LOAD | IS_SEXTUPLE_OP | SETS_CCODES, { 0, 0, 0x69, 0, 0, 0, 0, 2 }, "Imul32RAI", "!0r,[!1r+!2r<<!3d+!4d],!5d" },
+  { kX86Imul32RRI,   kRegRegImm,             IS_TERTIARY_OP | SETS_CCODES, { 0, 0, 0x69, 0, 0, 0, 0, 4 }, "Imul32RRI", "!0r,!1r,!2d" },
+  { kX86Imul32RMI,   kRegMemImm,   IS_LOAD | IS_QUAD_OP     | SETS_CCODES, { 0, 0, 0x69, 0, 0, 0, 0, 4 }, "Imul32RMI", "!0r,[!1r+!2d],!3d" },
+  { kX86Imul32RAI,   kRegArrayImm, IS_LOAD | IS_SEXTUPLE_OP | SETS_CCODES, { 0, 0, 0x69, 0, 0, 0, 0, 4 }, "Imul32RAI", "!0r,[!1r+!2r<<!3d+!4d],!5d" },
   { kX86Imul32RRI8,  kRegRegImm,             IS_TERTIARY_OP | SETS_CCODES, { 0, 0, 0x6B, 0, 0, 0, 0, 1 }, "Imul32RRI8", "!0r,!1r,!2d" },
   { kX86Imul32RMI8,  kRegMemImm,   IS_LOAD | IS_QUAD_OP     | SETS_CCODES, { 0, 0, 0x6B, 0, 0, 0, 0, 1 }, "Imul32RMI8", "!0r,[!1r+!2d],!3d" },
   { kX86Imul32RAI8,  kRegArrayImm, IS_LOAD | IS_SEXTUPLE_OP | SETS_CCODES, { 0, 0, 0x6B, 0, 0, 0, 0, 1 }, "Imul32RAI8", "!0r,[!1r+!2r<<!3d+!4d],!5d" },
diff --git a/src/compiler/codegen/x86/X86/Factory.cc b/src/compiler/codegen/x86/X86/Factory.cc
index 2bd5b42..8e991a0 100644
--- a/src/compiler/codegen/x86/X86/Factory.cc
+++ b/src/compiler/codegen/x86/X86/Factory.cc
@@ -567,15 +567,12 @@
                           int rSrc, int rSrcHi,
                           OpSize size, int sReg) {
   LIR *store = NULL;
-  LIR *store2 = NULL;
   bool isArray = rIndex != INVALID_REG;
   bool pair = false;
-  bool is64bit = false;
   X86OpCode opcode = kX86Nop;
   switch (size) {
     case kLong:
     case kDouble:
-      is64bit = true;
       if (FPREG(rSrc)) {
         opcode = isArray ? kX86MovsdAR : kX86MovsdMR;
         if (DOUBLEREG(rSrc)) {
@@ -619,14 +616,14 @@
       store = newLIR3(cUnit, opcode, rBase, displacement + LOWORD_OFFSET, rSrc);
     } else {
       store = newLIR3(cUnit, opcode, rBase, displacement + LOWORD_OFFSET, rSrc);
-      store2 = newLIR3(cUnit, opcode, rBase, displacement + HIWORD_OFFSET, rSrcHi);
+      newLIR3(cUnit, opcode, rBase, displacement + HIWORD_OFFSET, rSrcHi);
     }
   } else {
     if (!pair) {
       store = newLIR5(cUnit, opcode, rBase, rIndex, scale, displacement + LOWORD_OFFSET, rSrc);
     } else {
       store = newLIR5(cUnit, opcode, rBase, rIndex, scale, displacement + LOWORD_OFFSET, rSrc);
-      store2 = newLIR5(cUnit, opcode, rBase, rIndex, scale, displacement + HIWORD_OFFSET, rSrcHi);
+      newLIR5(cUnit, opcode, rBase, rIndex, scale, displacement + HIWORD_OFFSET, rSrcHi);
     }
   }
 
diff --git a/src/compiler_llvm/compilation_unit.h b/src/compiler_llvm/compilation_unit.h
index 2f98521..fb5f4e4 100644
--- a/src/compiler_llvm/compilation_unit.h
+++ b/src/compiler_llvm/compilation_unit.h
@@ -98,7 +98,7 @@
 
   bool IsMaterializeThresholdReached() const {
     MutexLock GUARD(cunit_lock_);
-    return (mem_usage_ > 100000000u); // (threshold: 100 MB)
+    return (mem_usage_ > 10000000u); // (threshold: 10 MB)
   }
 
   void AddMemUsageApproximation(size_t usage) {
diff --git a/src/compiler_llvm/frontend.cc b/src/compiler_llvm/frontend.cc
deleted file mode 100644
index 7507b26..0000000
--- a/src/compiler_llvm/frontend.cc
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#include "dex_file.h"
-#include "logging.h"
-
-#include <stdint.h>
-
-namespace art {
-
-int oatVRegOffset(const DexFile::CodeItem* code_item,
-                  uint32_t core_spills, uint32_t fp_spills,
-                  size_t frame_size, int reg) {
-
-  // TODO: Remove oatVRegOffset() after we have adapted the OatWriter
-  // and OatFile.
-
-  UNIMPLEMENTED(WARNING) << "oatVRegOffset() is not and won't be "
-                         << "implemented in LLVM backend";
-  return 0;
-}
-
-} // namespace art
diff --git a/src/compiler_llvm/jni_compiler.cc b/src/compiler_llvm/jni_compiler.cc
index 02985f7..5a8cc46 100644
--- a/src/compiler_llvm/jni_compiler.cc
+++ b/src/compiler_llvm/jni_compiler.cc
@@ -112,11 +112,6 @@
   llvm::StructType* shadow_frame_type = irb_.getShadowFrameTy(sirt_size);
   llvm::AllocaInst* shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
 
-  // Zero-initialization of the shadow frame
-  llvm::ConstantAggregateZero* zero_initializer =
-    llvm::ConstantAggregateZero::get(shadow_frame_type);
-  irb_.CreateStore(zero_initializer, shadow_frame_);
-
   // Store the method pointer
   llvm::Value* method_field_addr =
     irb_.CreatePtrDisp(shadow_frame_,
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index 8d6b251..f9a2833 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -36,12 +36,9 @@
 #include <iomanip>
 
 #include <llvm/BasicBlock.h>
-#include <llvm/DerivedTypes.h>
 #include <llvm/Function.h>
 #include <llvm/GlobalVariable.h>
 #include <llvm/Intrinsics.h>
-#include <llvm/Module.h>
-#include <llvm/Type.h>
 
 namespace art {
 namespace compiler_llvm {
@@ -66,7 +63,7 @@
     irb_(*cunit->GetIRBuilder()), func_(NULL), retval_reg_(NULL),
     basic_block_stack_overflow_(NULL),
     basic_block_reg_alloca_(NULL), basic_block_shadow_frame_alloca_(NULL),
-    basic_block_reg_zero_init_(NULL), basic_block_reg_arg_init_(NULL),
+    basic_block_reg_arg_init_(NULL),
     basic_blocks_(code_item_->insns_size_in_code_units_),
     basic_block_landing_pads_(code_item_->tries_size_, NULL),
     basic_block_unwind_(NULL), basic_block_unreachable_(NULL),
@@ -151,9 +148,6 @@
   basic_block_shadow_frame_alloca_ =
     llvm::BasicBlock::Create(*context_, "prologue.shadowframe", func_);
 
-  basic_block_reg_zero_init_ =
-    llvm::BasicBlock::Create(*context_, "prologue.zeroinit", func_);
-
   basic_block_reg_arg_init_ =
     llvm::BasicBlock::Create(*context_, "prologue.arginit", func_);
 
@@ -238,9 +232,6 @@
   irb_.CreateBr(basic_block_shadow_frame_alloca_);
 
   irb_.SetInsertPoint(basic_block_shadow_frame_alloca_);
-  irb_.CreateBr(basic_block_reg_zero_init_);
-
-  irb_.SetInsertPoint(basic_block_reg_zero_init_);
   irb_.CreateBr(basic_block_reg_arg_init_);
 }
 
@@ -2131,15 +2122,13 @@
     EmitGuard_GarbageCollectionSuspend(dex_pc);
   }
 
-  if (src1_reg_cat == kRegZero && src2_reg_cat == kRegZero) {
-    irb_.CreateBr(GetBasicBlock(dex_pc + branch_offset));
-    return;
-  }
-
   llvm::Value* src1_value;
   llvm::Value* src2_value;
 
-  if (src1_reg_cat != kRegZero && src2_reg_cat != kRegZero) {
+  if (src1_reg_cat == kRegZero && src2_reg_cat == kRegZero) {
+    src1_value = irb_.getInt32(0);
+    src2_value = irb_.getInt32(0);
+  } else if (src1_reg_cat != kRegZero && src2_reg_cat != kRegZero) {
     CHECK_EQ(src1_reg_cat, src2_reg_cat);
 
     if (src1_reg_cat == kRegCat1nr) {
@@ -2199,15 +2188,13 @@
     EmitGuard_GarbageCollectionSuspend(dex_pc);
   }
 
-  if (src_reg_cat == kRegZero) {
-    irb_.CreateBr(GetBasicBlock(dex_pc + branch_offset));
-    return;
-  }
-
   llvm::Value* src1_value;
   llvm::Value* src2_value;
 
-  if (src_reg_cat == kRegCat1nr) {
+  if (src_reg_cat == kRegZero) {
+    src1_value = irb_.getInt32(0);
+    src2_value = irb_.getInt32(0);
+  } else if (src_reg_cat == kRegCat1nr) {
     src1_value = EmitLoadDalvikReg(dec_insn.vA, kInt, kAccurate);
     src2_value = irb_.getInt32(0);
   } else {
@@ -2840,8 +2827,8 @@
       if (direct_method != 0u &&
           direct_method != static_cast<uintptr_t>(-1)) {
         callee_method_object_addr =
-          EmitLoadSDCalleeDirectMethodObjectAddr(callee_method_idx,
-                                                 direct_method);
+          irb_.CreateIntToPtr(irb_.getPtrEquivInt(direct_method),
+                              irb_.getJObjectTy());
       } else {
         callee_method_object_addr =
           EmitLoadSDCalleeMethodObjectAddr(callee_method_idx);
@@ -2992,27 +2979,6 @@
 
 
 llvm::Value* MethodCompiler::
-EmitLoadSDCalleeDirectMethodObjectAddr(uint32_t callee_method_idx,
-                                       uintptr_t direct_method) {
-  std::string direct_method_name(
-    StringPrintf("ArtMethodObject_%08lx",
-                 static_cast<unsigned long>(direct_method)));
-
-  llvm::GlobalVariable* direct_method_addr =
-    module_->getGlobalVariable(direct_method_name);
-
-  if (direct_method_addr == NULL) {
-    direct_method_addr =
-      new llvm::GlobalVariable(*module_, irb_.getJObjectTy()->getElementType(),
-                               false, llvm::GlobalVariable::ExternalLinkage,
-                               NULL, direct_method_name);
-  }
-
-  return direct_method_addr;
-}
-
-
-llvm::Value* MethodCompiler::
 EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx) {
   llvm::Value* callee_method_object_field_addr =
     EmitLoadDexCacheResolvedMethodFieldAddr(callee_method_idx);
@@ -3875,16 +3841,11 @@
   // Find catch block with matching type
   llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
 
-  // TODO: Maybe passing try item offset will be a better idea?  For now,
-  // we are passing dex_pc, so that we can use existing runtime support
-  // function directly.  However, in the runtime supporting function we
-  // have to search for try item with binary search which can be
-  // eliminated.
-  llvm::Value* dex_pc_value = irb_.getInt32(ti->start_addr_);
+  llvm::Value* ti_offset_value = irb_.getInt32(ti_offset);
 
   llvm::Value* catch_handler_index_value =
     irb_.CreateCall2(irb_.GetRuntime(FindCatchBlock),
-                     method_object_addr, dex_pc_value);
+                     method_object_addr, ti_offset_value);
 
   // Switch instruction (Go to unwind basic block by default)
   llvm::SwitchInst* sw =
@@ -3954,18 +3915,12 @@
     irb_.SetInsertPoint(basic_block_reg_alloca_);
     reg_addr = irb_.CreateAlloca(irb_.getJIntTy(), 0,
                                  StringPrintf("r%u", reg_idx));
-
-    irb_.SetInsertPoint(basic_block_reg_zero_init_);
-    irb_.CreateStore(irb_.getJInt(0), reg_addr);
     break;
 
   case kRegCat2:
     irb_.SetInsertPoint(basic_block_reg_alloca_);
     reg_addr = irb_.CreateAlloca(irb_.getJLongTy(), 0,
                                  StringPrintf("w%u", reg_idx));
-
-    irb_.SetInsertPoint(basic_block_reg_zero_init_);
-    irb_.CreateStore(irb_.getJLong(0), reg_addr);
     break;
 
   case kRegObject:
@@ -3980,9 +3935,6 @@
 
       reg_addr = irb_.CreateGEP(shadow_frame_, gep_index,
                                 StringPrintf("p%u", reg_idx));
-
-      irb_.SetInsertPoint(basic_block_reg_zero_init_);
-      irb_.CreateStore(irb_.getJNull(), reg_addr);
     }
     break;
 
diff --git a/src/compiler_llvm/method_compiler.h b/src/compiler_llvm/method_compiler.h
index 84c55d6..d5a4374 100644
--- a/src/compiler_llvm/method_compiler.h
+++ b/src/compiler_llvm/method_compiler.h
@@ -215,9 +215,6 @@
 
   llvm::Value* EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx);
 
-  llvm::Value* EmitLoadSDCalleeDirectMethodObjectAddr(uint32_t callee_method_idx,
-                                                      uintptr_t direct_method);
-
   llvm::Value* EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx,
                                                      llvm::Value* this_addr);
 
@@ -459,7 +456,6 @@
   llvm::BasicBlock* basic_block_stack_overflow_;
   llvm::BasicBlock* basic_block_reg_alloca_;
   llvm::BasicBlock* basic_block_shadow_frame_alloca_;
-  llvm::BasicBlock* basic_block_reg_zero_init_;
   llvm::BasicBlock* basic_block_reg_arg_init_;
   std::vector<llvm::BasicBlock*> basic_blocks_;
 
diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc
index 1ebbef9..bdfd222 100644
--- a/src/compiler_llvm/runtime_support_llvm.cc
+++ b/src/compiler_llvm/runtime_support_llvm.cc
@@ -159,14 +159,18 @@
   ThrowVerificationError(art_get_current_thread_from_code(), current_method, kind, ref);
 }
 
-int32_t art_find_catch_block_from_code(Method* current_method, int32_t dex_pc) {
+int32_t art_find_catch_block_from_code(Method* current_method,
+                                       uint32_t ti_offset) {
   Thread* thread = art_get_current_thread_from_code();
   Class* exception_type = thread->GetException()->GetClass();
   MethodHelper mh(current_method);
   const DexFile::CodeItem* code_item = mh.GetCodeItem();
+  DCHECK_LT(ti_offset, code_item->tries_size_);
+  const DexFile::TryItem* try_item = DexFile::GetTryItems(*code_item, ti_offset);
+
   int iter_index = 0;
   // Iterate over the catch handlers associated with dex_pc
-  for (CatchHandlerIterator it(*code_item, dex_pc); it.HasNext(); it.Next()) {
+  for (CatchHandlerIterator it(*code_item, *try_item); it.HasNext(); it.Next()) {
     uint16_t iter_type_idx = it.GetHandlerTypeIndex();
     // Catch all case
     if (iter_type_idx == DexFile::kDexNoIndex16) {
@@ -509,8 +513,8 @@
     Thread* thread = art_get_current_thread_from_code();
     thread->ThrowNewExceptionF("Ljava/lang/ClassCastException;",
                                "%s cannot be cast to %s",
-                               PrettyDescriptor(dest_type).c_str(),
-                               PrettyDescriptor(src_type).c_str());
+                               PrettyDescriptor(src_type).c_str(),
+                               PrettyDescriptor(dest_type).c_str());
   }
 }
 
@@ -797,15 +801,6 @@
     }
   }
 
-  // Fixed method object address
-  const char method_object_prefix[] = "ArtMethodObject_";
-  const size_t method_object_prefix_len = sizeof(method_object_prefix) - 1;
-  if (strncmp(name, method_object_prefix, method_object_prefix_len) == 0) {
-    const char* addr_str = name + method_object_prefix_len;
-    unsigned long addr_int = strtoul(addr_str, NULL, 16);
-    return reinterpret_cast<void*>(addr_int);
-  }
-
   LOG(FATAL) << "Error: Can't find symbol " << name;
   return 0;
 }
diff --git a/src/compiler_llvm/runtime_support_llvm.h b/src/compiler_llvm/runtime_support_llvm.h
index 6e3b81c..f8228c5 100644
--- a/src/compiler_llvm/runtime_support_llvm.h
+++ b/src/compiler_llvm/runtime_support_llvm.h
@@ -59,7 +59,8 @@
 
 void art_throw_exception_from_code(Object* exception);
 
-int32_t art_find_catch_block_from_code(Method* current_method, int32_t dex_pc);
+int32_t art_find_catch_block_from_code(Method* current_method,
+                                       uint32_t ti_offset);
 
 
 void art_test_suspend_from_code(Thread* thread);
diff --git a/src/dex_file.cc b/src/dex_file.cc
index 85dafee..eb2a157 100644
--- a/src/dex_file.cc
+++ b/src/dex_file.cc
@@ -1001,9 +1001,19 @@
     default:
       offset = DexFile::FindCatchHandlerOffset(code_item, code_item.tries_size_, address);
   }
+  Init(code_item, offset);
+}
+
+CatchHandlerIterator::CatchHandlerIterator(const DexFile::CodeItem& code_item,
+                                           const DexFile::TryItem& try_item) {
+  handler_.address_ = -1;
+  Init(code_item, try_item.handler_off_);
+}
+
+void CatchHandlerIterator::Init(const DexFile::CodeItem& code_item,
+                                int32_t offset) {
   if (offset >= 0) {
-    const byte* handler_data = DexFile::GetCatchHandlerData(code_item, offset);
-    Init(handler_data);
+    Init(DexFile::GetCatchHandlerData(code_item, offset));
   } else {
     // Not found, initialize as empty
     current_data_ = NULL;
diff --git a/src/dex_file.h b/src/dex_file.h
index 9c16440..aeb7e89 100644
--- a/src/dex_file.h
+++ b/src/dex_file.h
@@ -307,6 +307,15 @@
     DISALLOW_COPY_AND_ASSIGN(AnnotationItem);
   };
 
+  struct PACKED Payload {
+    uint16_t ident; // kPackedSwitchSignature, kSparseSwitchSignature, or kArrayDataSignature.
+    uint16_t element_width;
+    uint32_t element_count;
+    uint8_t data[];
+   private:
+    DISALLOW_COPY_AND_ASSIGN(Payload);
+  };
+
   typedef std::pair<const DexFile*, const DexFile::ClassDef*> ClassPathEntry;
   typedef std::vector<const DexFile*> ClassPath;
 
@@ -1119,6 +1128,10 @@
 class CatchHandlerIterator {
   public:
     CatchHandlerIterator(const DexFile::CodeItem& code_item, uint32_t address);
+
+    CatchHandlerIterator(const DexFile::CodeItem& code_item,
+                         const DexFile::TryItem& try_item);
+
     explicit CatchHandlerIterator(const byte* handler_data) {
       Init(handler_data);
     }
@@ -1139,6 +1152,7 @@
       return current_data_;
     }
   private:
+    void Init(const DexFile::CodeItem& code_item, int32_t offset);
     void Init(const byte* handler_data);
 
     struct CatchHandlerItem {
diff --git a/src/dex_instruction.cc b/src/dex_instruction.cc
index e0b10f9..8744326 100644
--- a/src/dex_instruction.cc
+++ b/src/dex_instruction.cc
@@ -299,7 +299,17 @@
     case k22x:  os << StringPrintf("%s v%d, v%d", opcode, insn.vA, insn.vB); break;
     case k21t:  os << StringPrintf("%s v%d, %+d", opcode, insn.vA, insn.vB); break;
     case k21s:  os << StringPrintf("%s v%d, #%+d", opcode, insn.vA, insn.vB); break;
-    case k21h:  os << StringPrintf("%s v%d, #%+d00000[00000000]", opcode, insn.vA, insn.vB); break;
+    case k21h: {
+        // op vAA, #+BBBB0000[00000000]
+        if (insn.opcode == CONST_HIGH16) {
+          uint32_t value = insn.vB << 16;
+          os << StringPrintf("%s v%d, #int %+d // 0x%x", opcode, insn.vA, value, value);
+        } else {
+          uint64_t value = static_cast<uint64_t>(insn.vB) << 48;
+          os << StringPrintf("%s v%d, #long %+lld // 0x%llx", opcode, insn.vA, value, value);
+        }
+      }
+      break;
     case k21c:  os << StringPrintf("%s v%d, thing@%d", opcode, insn.vA, insn.vB); break;
     case k23x:  os << StringPrintf("%s v%d, v%d, v%d", opcode, insn.vA, insn.vB, insn.vC); break;
     case k22b:  os << StringPrintf("%s v%d, v%d, #%+d", opcode, insn.vA, insn.vB, insn.vC); break;
diff --git a/src/disassembler.cc b/src/disassembler.cc
index 3396229..8fe3dc7 100644
--- a/src/disassembler.cc
+++ b/src/disassembler.cc
@@ -19,6 +19,7 @@
 #include <iostream>
 
 #include "disassembler_arm.h"
+#include "disassembler_mips.h"
 #include "disassembler_x86.h"
 #include "logging.h"
 
@@ -27,6 +28,8 @@
 Disassembler* Disassembler::Create(InstructionSet instruction_set) {
   if (instruction_set == kArm || instruction_set == kThumb2) {
     return new arm::DisassemblerArm();
+  } else if (instruction_set == kMips) {
+    return new mips::DisassemblerMips();
   } else if (instruction_set == kX86) {
     return new x86::DisassemblerX86();
   } else {
diff --git a/src/disassembler_mips.cc b/src/disassembler_mips.cc
new file mode 100644
index 0000000..f7d755a
--- /dev/null
+++ b/src/disassembler_mips.cc
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#include "disassembler_mips.h"
+
+#include <iostream>
+
+#include "logging.h"
+#include "stringprintf.h"
+#include "thread.h"
+
+namespace art {
+namespace mips {
+
+struct MipsInstruction {
+  uint32_t mask;
+  uint32_t value;
+  const char* name;
+  const char* args_fmt;
+
+  bool Matches(uint32_t instruction) const {
+    return (instruction & mask) == value;
+  }
+};
+
+static const uint32_t kOpcodeShift = 26;
+
+static const uint32_t kCop1 = (17 << kOpcodeShift);
+
+static const uint32_t kITypeMask = (0x3f << kOpcodeShift);
+static const uint32_t kJTypeMask = (0x3f << kOpcodeShift);
+static const uint32_t kRTypeMask = ((0x3f << kOpcodeShift) | (0x3f));
+static const uint32_t kSpecial2Mask = (0x3f << kOpcodeShift);
+static const uint32_t kFpMask = kRTypeMask;
+
+static const MipsInstruction gMipsInstructions[] = {
+  // "sll r0, r0, 0" is the canonical "nop", used in delay slots.
+  { 0xffffffff, 0, "nop", "" },
+
+  // R-type instructions.
+  { kRTypeMask, 0, "sll", "DTA", },
+  // 0, 1, movci
+  { kRTypeMask, 2, "srl", "DTA", },
+  { kRTypeMask, 3, "sra", "DTA", },
+  { kRTypeMask, 4, "sllv", "DTS", },
+  { kRTypeMask, 6, "srlv", "DTS", },
+  { kRTypeMask, 7, "srav", "DTS", },
+  { kRTypeMask, 8, "jr", "S", },
+  { kRTypeMask | (0x1f << 11), 9 | (31 << 11), "jalr", "S", }, // rd = 31 is implicit.
+  { kRTypeMask, 9, "jalr", "DS", }, // General case.
+  { kRTypeMask | (0x1f << 6), 10, "movz", "DST", },
+  { kRTypeMask | (0x1f << 6), 11, "movn", "DST", },
+  { kRTypeMask, 12, "syscall", "", }, // TODO: code
+  { kRTypeMask, 13, "break", "", }, // TODO: code
+  { kRTypeMask, 15, "sync", "", }, // TODO: type
+  { kRTypeMask, 16, "mfhi", "D", },
+  { kRTypeMask, 17, "mthi", "S", },
+  { kRTypeMask, 18, "mflo", "D", },
+  { kRTypeMask, 19, "mtlo", "S", },
+  { kRTypeMask, 24, "mult", "ST", },
+  { kRTypeMask, 25, "multu", "ST", },
+  { kRTypeMask, 26, "div", "ST", },
+  { kRTypeMask, 27, "divu", "ST", },
+  { kRTypeMask, 32, "add", "DST", },
+  { kRTypeMask, 33, "addu", "DST", },
+  { kRTypeMask, 34, "sub", "DST", },
+  { kRTypeMask, 35, "subu", "DST", },
+  { kRTypeMask, 36, "and", "DST", },
+  { kRTypeMask, 37, "or", "DST", },
+  { kRTypeMask, 38, "xor", "DST", },
+  { kRTypeMask, 39, "nor", "DST", },
+  { kRTypeMask, 42, "slt", "DST", },
+  { kRTypeMask, 43, "sltu", "DST", },
+  // 0, 48, tge
+  // 0, 49, tgeu
+  // 0, 50, tlt
+  // 0, 51, tltu
+  // 0, 52, teq
+  // 0, 54, tne
+
+  // SPECIAL2
+  { kSpecial2Mask | 0x7ff, (28 << kOpcodeShift) | 2, "mul", "DST" },
+  { kSpecial2Mask | 0x7ff, (28 << kOpcodeShift) | 32, "clz", "DS" },
+  { kSpecial2Mask | 0xffff, (28 << kOpcodeShift) | 0, "madd", "ST" },
+  { kSpecial2Mask | 0xffff, (28 << kOpcodeShift) | 1, "maddu", "ST" },
+  { kSpecial2Mask | 0xffff, (28 << kOpcodeShift) | 2, "mul", "DST" },
+  { kSpecial2Mask | 0xffff, (28 << kOpcodeShift) | 4, "msub", "ST" },
+  { kSpecial2Mask | 0xffff, (28 << kOpcodeShift) | 5, "msubu", "ST" },
+  { kSpecial2Mask | 0x3f, (28 << kOpcodeShift) | 0x3f, "sdbbp", "" }, // TODO: code
+
+  // J-type instructions.
+  { kJTypeMask, 2 << kOpcodeShift, "j", "L" },
+  { kJTypeMask, 3 << kOpcodeShift, "jal", "L" },
+
+  // I-type instructions.
+  { kITypeMask, 4 << kOpcodeShift, "beq", "STB" },
+  { kITypeMask, 5 << kOpcodeShift, "bne", "STB" },
+  { kITypeMask | (0x1f << 16), 1 << kOpcodeShift | (1 << 16), "bgez", "SB" },
+  { kITypeMask | (0x1f << 16), 1 << kOpcodeShift | (0 << 16), "bltz", "SB" },
+  { kITypeMask | (0x1f << 16), 1 << kOpcodeShift | (2 << 16), "bltzl", "SB" },
+  { kITypeMask | (0x1f << 16), 1 << kOpcodeShift | (16 << 16), "bltzal", "SB" },
+  { kITypeMask | (0x1f << 16), 1 << kOpcodeShift | (18 << 16), "bltzall", "SB" },
+  { kITypeMask | (0x1f << 16), 6 << kOpcodeShift | (0 << 16), "blez", "SB" },
+  { kITypeMask | (0x1f << 16), 7 << kOpcodeShift | (0 << 16), "bgtz", "SB" },
+
+  { 0xffff0000, (4 << kOpcodeShift), "b", "B" },
+  { 0xffff0000, (1 << kOpcodeShift) | (17 << 16), "bal", "B" },
+
+  { kITypeMask, 8 << kOpcodeShift, "addi", "TSi", },
+  { kITypeMask, 9 << kOpcodeShift, "addiu", "TSi", },
+  { kITypeMask, 10 << kOpcodeShift, "slti", "TSi", },
+  { kITypeMask, 11 << kOpcodeShift, "sltiu", "TSi", },
+  { kITypeMask, 12 << kOpcodeShift, "andi", "TSi", },
+  { kITypeMask, 13 << kOpcodeShift, "ori", "TSi", },
+  { kITypeMask, 14 << kOpcodeShift, "ori", "TSi", },
+  { kITypeMask, 15 << kOpcodeShift, "lui", "TI", },
+
+  { kITypeMask, 32 << kOpcodeShift, "lb", "TO", },
+  { kITypeMask, 33 << kOpcodeShift, "lh", "TO", },
+  { kITypeMask, 35 << kOpcodeShift, "lw", "TO", },
+  { kITypeMask, 36 << kOpcodeShift, "lbu", "TO", },
+  { kITypeMask, 37 << kOpcodeShift, "lhu", "TO", },
+  { kITypeMask, 40 << kOpcodeShift, "sb", "TO", },
+  { kITypeMask, 41 << kOpcodeShift, "sh", "TO", },
+  { kITypeMask, 43 << kOpcodeShift, "sw", "TO", },
+  { kITypeMask, 49 << kOpcodeShift, "lwc1", "tO", },
+  { kITypeMask, 57 << kOpcodeShift, "swc1", "tO", },
+
+  // Floating point.
+  { kFpMask,                kCop1 | 0, "add", "fdst" },
+  { kFpMask,                kCop1 | 1, "sub", "fdst" },
+  { kFpMask,                kCop1 | 2, "mul", "fdst" },
+  { kFpMask,                kCop1 | 3, "div", "fdst" },
+  { kFpMask | (0x1f << 16), kCop1 | 4, "sqrt", "fdst" },
+  { kFpMask | (0x1f << 16), kCop1 | 5, "abs", "fds" },
+  { kFpMask | (0x1f << 16), kCop1 | 6, "mov", "fds" },
+  { kFpMask | (0x1f << 16), kCop1 | 7, "neg", "fds" },
+  { kFpMask | (0x1f << 16), kCop1 | 8, "round.l", "fds" },
+  { kFpMask | (0x1f << 16), kCop1 | 9, "trunc.l", "fds" },
+  { kFpMask | (0x1f << 16), kCop1 | 10, "ceil.l", "fds" },
+  { kFpMask | (0x1f << 16), kCop1 | 11, "floor.l", "fds" },
+  { kFpMask | (0x1f << 16), kCop1 | 12, "round.w", "fds" },
+  { kFpMask | (0x1f << 16), kCop1 | 13, "trunc.w", "fds" },
+  { kFpMask | (0x1f << 16), kCop1 | 14, "ceil.w", "fds" },
+  { kFpMask | (0x1f << 16), kCop1 | 15, "floor.w", "fds" },
+  { kFpMask | (0x1f << 16), kCop1 | 32, "cvt.s", "fds" },
+  { kFpMask | (0x1f << 16), kCop1 | 33, "cvt.d", "fds" },
+  { kFpMask | (0x1f << 16), kCop1 | 36, "cvt.w", "fds" },
+  { kFpMask | (0x1f << 16), kCop1 | 37, "cvt.l", "fds" },
+  { kFpMask | (0x1f << 16), kCop1 | 38, "cvt.ps", "fds" },
+};
+
+static uint32_t ReadU32(const uint8_t* ptr) {
+  // TODO: MIPS is bi. how do we handle that?
+  return ptr[3] | (ptr[2] << 8) | (ptr[1] << 16) | (ptr[0] << 24);
+  //return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);
+}
+
+static void DumpMips(std::ostream& os, const uint8_t* instr_ptr) {
+  uint32_t instruction = ReadU32(instr_ptr);
+
+  uint32_t rs = (instruction >> 21) & 0x1f; // I-type, R-type.
+  uint32_t rt = (instruction >> 16) & 0x1f; // I-type, R-type.
+  uint32_t rd = (instruction >> 11) & 0x1f; // R-type.
+  uint32_t sa = (instruction >>  6) & 0x1f; // R-type.
+
+  std::string opcode;
+  std::ostringstream args;
+
+  // TODO: remove this!
+  uint32_t op = (instruction >> 26) & 0x3f;
+  uint32_t function = (instruction & 0x3f); // R-type.
+  opcode = StringPrintf("op=%d fn=%d", op, function);
+
+  for (size_t i = 0; i < arraysize(gMipsInstructions); ++i) {
+    if (gMipsInstructions[i].Matches(instruction)) {
+      opcode = gMipsInstructions[i].name;
+      for (const char* args_fmt = gMipsInstructions[i].args_fmt; *args_fmt; ++args_fmt) {
+        switch (*args_fmt) {
+          case 'A': // sa (shift amount).
+            args << sa;
+            break;
+          case 'B': // Branch offset.
+            {
+              int32_t offset = static_cast<int16_t>(instruction & 0xffff);
+              offset <<= 2;
+              offset += 4; // Delay slot.
+              args << StringPrintf("%p  ; %+d", instr_ptr + offset, offset);
+            }
+            break;
+          case 'D': args << 'r' << rd; break;
+          case 'd': args << 'f' << rd; break;
+          case 'f': // Floating point "fmt".
+            {
+              size_t fmt = (instruction >> 21) & 0x7; // TODO: other fmts?
+              switch (fmt) {
+                case 0: opcode += ".s"; break;
+                case 1: opcode += ".d"; break;
+                case 4: opcode += ".w"; break;
+                case 5: opcode += ".l"; break;
+                case 6: opcode += ".ps"; break;
+                default: opcode += ".?"; break;
+              }
+              continue; // No ", ".
+            }
+            break;
+          case 'I': // Upper 16-bit immediate.
+            args << reinterpret_cast<void*>((instruction & 0xffff) << 16);
+            break;
+          case 'i': // Sign-extended lower 16-bit immediate.
+            args << static_cast<int16_t>(instruction & 0xffff);
+            break;
+          case 'L': // Jump label.
+            {
+              // TODO: is this right?
+              uint32_t instr_index = (instruction & 0x1ffffff);
+              uint32_t target = (instr_index << 2);
+              target |= (reinterpret_cast<uintptr_t>(instr_ptr + 4) & 0xf0000000);
+              args << reinterpret_cast<void*>(target);
+            }
+            break;
+          case 'O': // +x(rs)
+            {
+              int32_t offset = static_cast<int16_t>(instruction & 0xffff);
+              args << StringPrintf("%+d(r%d)", offset, rs);
+              if (rs == 17) {
+                args << "  ; ";
+                Thread::DumpThreadOffset(args, offset, 4);
+              }
+            }
+            break;
+          case 'S': args << 'r' << rs; break;
+          case 's': args << 'f' << rs; break;
+          case 'T': args << 'r' << rt; break;
+          case 't': args << 'f' << rt; break;
+        }
+        if (*(args_fmt + 1)) {
+          args << ", ";
+        }
+      }
+      break;
+    }
+  }
+
+  os << StringPrintf("\t\t\t%p: %08x\t%-7s ", instr_ptr, instruction, opcode.c_str()) << args.str() << '\n';
+}
+
+DisassemblerMips::DisassemblerMips() {
+}
+
+void DisassemblerMips::Dump(std::ostream& os, const uint8_t* begin, const uint8_t* end) {
+  for (const uint8_t* cur = begin; cur < end; cur += 4) {
+    DumpMips(os, cur);
+  }
+}
+
+}  // namespace mips
+}  // namespace art
diff --git a/src/disassembler_mips.h b/src/disassembler_mips.h
new file mode 100644
index 0000000..8c3d0dc
--- /dev/null
+++ b/src/disassembler_mips.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2012 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_SRC_DISASSEMBLER_MIPS_H_
+#define ART_SRC_DISASSEMBLER_MIPS_H_
+
+#include <vector>
+
+#include "disassembler.h"
+
+namespace art {
+namespace mips {
+
+class DisassemblerMips : public Disassembler {
+ public:
+  DisassemblerMips();
+  virtual void Dump(std::ostream& os, const uint8_t* begin, const uint8_t* end);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DisassemblerMips);
+};
+
+}  // namespace mips
+}  // namespace art
+
+#endif  // ART_SRC_DISASSEMBLER_MIPS_H_
diff --git a/src/globals.h b/src/globals.h
index 35a2113..5f0987a 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -46,6 +46,9 @@
 // ARM instruction alignment. ARM processors require code to be 4-byte aligned.
 const int kArmAlignment = 4;
 
+// MIPS instruction alignment.  MIPS processors require code to be 4-byte aligned.
+const int kMipsAlignment = 4;
+
 // X86 instruction alignment. This is the recommended alignment for maximum performance.
 const int kX86Alignment = 16;
 
diff --git a/src/jdwp/jdwp_handler.cc b/src/jdwp/jdwp_handler.cc
index 355fc5e..cf1e188 100644
--- a/src/jdwp/jdwp_handler.cc
+++ b/src/jdwp/jdwp_handler.cc
@@ -1016,9 +1016,7 @@
  * Get the monitor that the thread is waiting on.
  */
 static JdwpError handleTR_CurrentContendedMonitor(JdwpState*, const uint8_t* buf, int, ExpandBuf*) {
-  ObjectId threadId;
-
-  threadId = ReadObjectId(&buf);
+  ReadObjectId(&buf);  // threadId
 
   // TODO: create an Object to represent the monitor (we're currently
   // just using a raw Monitor struct in the VM)
@@ -1143,8 +1141,7 @@
 }
 
 static JdwpError handleCLR_VisibleClasses(JdwpState*, const uint8_t* buf, int, ExpandBuf* pReply) {
-  ObjectId classLoaderObject;
-  classLoaderObject = ReadObjectId(&buf);
+  ReadObjectId(&buf);  // classLoaderObject
   // TODO: we should only return classes which have the given class loader as a defining or
   // initiating loader. The former would be easy; the latter is hard, because we don't have
   // any such notion.
@@ -1629,7 +1626,7 @@
      * so waitForDebugger() doesn't return if we stall for a bit here.
      */
     Dbg::GoActive();
-    QuasiAtomicSwap64(0, &lastActivityWhen);
+    QuasiAtomic::Swap64(0, &lastActivityWhen);
   }
 
   /*
@@ -1698,7 +1695,7 @@
    * the initial setup.  Only update if this is a non-DDMS packet.
    */
   if (pHeader->cmdSet != kJDWPDdmCmdSet) {
-    QuasiAtomicSwap64(MilliTime(), &lastActivityWhen);
+    QuasiAtomic::Swap64(MilliTime(), &lastActivityWhen);
   }
 
   /* tell the VM that GC is okay again */
diff --git a/src/jdwp/jdwp_main.cc b/src/jdwp/jdwp_main.cc
index a820cc1..df24b8c 100644
--- a/src/jdwp/jdwp_main.cc
+++ b/src/jdwp/jdwp_main.cc
@@ -416,7 +416,7 @@
     return -1;
   }
 
-  int64_t last = QuasiAtomicRead64(&lastActivityWhen);
+  int64_t last = QuasiAtomic::Read64(&lastActivityWhen);
 
   /* initializing or in the middle of something? */
   if (last == 0) {
diff --git a/src/jdwp/jdwp_socket.cc b/src/jdwp/jdwp_socket.cc
index 9ff50f5..01eba12 100644
--- a/src/jdwp/jdwp_socket.cc
+++ b/src/jdwp/jdwp_socket.cc
@@ -558,7 +558,6 @@
   JdwpReqHeader hdr;
   uint32_t length, id;
   uint8_t flags, cmdSet, cmd;
-  uint16_t error;
   bool reply;
   int dataLen;
 
@@ -571,7 +570,7 @@
   flags = Read1(&buf);
   if ((flags & kJDWPFlagReply) != 0) {
     reply = true;
-    error = Read2BE(&buf);
+    Read2BE(&buf);  // error
   } else {
     reply = false;
     cmdSet = Read1(&buf);
diff --git a/src/native/sun_misc_Unsafe.cc b/src/native/sun_misc_Unsafe.cc
index 214771b..8cc549a 100644
--- a/src/native/sun_misc_Unsafe.cc
+++ b/src/native/sun_misc_Unsafe.cc
@@ -54,7 +54,7 @@
   byte* raw_addr = reinterpret_cast<byte*>(obj) + offset;
   volatile int64_t* address = reinterpret_cast<volatile int64_t*>(raw_addr);
   // Note: android_atomic_cmpxchg() returns 0 on success, not failure.
-  int result = QuasiAtomicCas64(expectedValue, newValue, address);
+  int result = QuasiAtomic::Cas64(expectedValue, newValue, address);
   return (result == 0);
 }
 
diff --git a/src/oat/jni/arm/jni_internal_arm.cc b/src/oat/jni/arm/jni_internal_arm.cc
index 2227742..78c3903 100644
--- a/src/oat/jni/arm/jni_internal_arm.cc
+++ b/src/oat/jni/arm/jni_internal_arm.cc
@@ -71,12 +71,7 @@
 
   // Can either get 3 or 2 arguments into registers
   size_t reg_bytes = (is_static ? 3 : 2) * kPointerSize;
-  // Bytes passed by stack
-  size_t stack_bytes;
-  if (num_arg_array_bytes > reg_bytes) {
-    stack_bytes = num_arg_array_bytes - reg_bytes;
-  } else {
-    stack_bytes = 0;
+  if (num_arg_array_bytes <= reg_bytes) {
     reg_bytes = num_arg_array_bytes;
   }
 
diff --git a/src/oat/runtime/arm/runtime_support_arm.S b/src/oat/runtime/arm/runtime_support_arm.S
index 2ef162e..638a7c3 100644
--- a/src/oat/runtime/arm/runtime_support_arm.S
+++ b/src/oat/runtime/arm/runtime_support_arm.S
@@ -254,7 +254,7 @@
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  @ save callee saves in case exception allocation triggers GC
     mov    r2, r9                          @ pass Thread::Current
     mov    r3, sp                          @ pass SP
-    bl     artHandleFillArrayDataFromCode  @ (Array* array, const uint16_t* table, Thread*, SP)
+    bl     artHandleFillArrayDataFromCode  @ (Array*, const DexFile::Payload*, Thread*, SP)
     RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
     cmp    r0, #0                          @ success?
     bxeq   lr                              @ return on success
diff --git a/src/oat/runtime/mips/runtime_support_mips.S b/src/oat/runtime/mips/runtime_support_mips.S
index 9b082bf..d4e87c0 100644
--- a/src/oat/runtime/mips/runtime_support_mips.S
+++ b/src/oat/runtime/mips/runtime_support_mips.S
@@ -416,7 +416,7 @@
 art_handle_fill_data_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  @ save callee saves in case exception allocation triggers GC
     move    a2, rSELF                          @ pass Thread::Current
-    jal     artHandleFillArrayDataFromCode     @ (Array* array, const uint16_t* table, Thread*, SP)
+    jal     artHandleFillArrayDataFromCode     @ (Array*, const DexFile::Payload*, Thread*, SP)
     move    a3, sp                             @ pass SP
     RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
     bnez    v0, 1f                             @ success?
diff --git a/src/oat/runtime/support_fillarray.cc b/src/oat/runtime/support_fillarray.cc
index eb1c46c..6f40177 100644
--- a/src/oat/runtime/support_fillarray.cc
+++ b/src/oat/runtime/support_fillarray.cc
@@ -15,6 +15,7 @@
  */
 
 #include "callee_save_frame.h"
+#include "dex_instruction.h"
 #include "object.h"
 
 namespace art {
@@ -34,25 +35,24 @@
  *  ubyte  data[size*width] table of data values (may contain a single-byte
  *                          padding at the end)
  */
-extern "C" int artHandleFillArrayDataFromCode(Array* array, const uint16_t* table,
+extern "C" int artHandleFillArrayDataFromCode(Array* array, const DexFile::Payload* payload,
                                               Thread* self, Method** sp) {
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  DCHECK_EQ(table[0], 0x0300);
+  DCHECK_EQ(payload->ident, static_cast<uint16_t>(Instruction::kArrayDataSignature));
   if (UNLIKELY(array == NULL)) {
     Thread::Current()->ThrowNewExceptionF("Ljava/lang/NullPointerException;",
-        "null array in fill array");
+        "null array in FILL_ARRAY_DATA");
     return -1;  // Error
   }
   DCHECK(array->IsArrayInstance() && !array->IsObjectArray());
-  uint32_t size = (uint32_t)table[2] | (((uint32_t)table[3]) << 16);
-  if (UNLIKELY(static_cast<int32_t>(size) > array->GetLength())) {
+  if (UNLIKELY(static_cast<int32_t>(payload->element_count) > array->GetLength())) {
     Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;",
-        "failed array fill. length=%d; index=%d", array->GetLength(), size);
+                                          "failed FILL_ARRAY_DATA; length=%d, index=%d",
+                                          array->GetLength(), payload->element_count);
     return -1;  // Error
   }
-  uint16_t width = table[1];
-  uint32_t size_in_bytes = size * width;
-  memcpy((char*)array + Array::DataOffset(width).Int32Value(), (char*)&table[4], size_in_bytes);
+  uint32_t size_in_bytes = payload->element_count * payload->element_width;
+  memcpy(array->GetRawData(payload->element_width), payload->data, size_in_bytes);
   return 0;  // Success
 }
 
diff --git a/src/oat/runtime/support_stubs.cc b/src/oat/runtime/support_stubs.cc
index ac5d6f9..2a46c8b 100644
--- a/src/oat/runtime/support_stubs.cc
+++ b/src/oat/runtime/support_stubs.cc
@@ -89,8 +89,10 @@
   bool is_static;
   bool is_virtual;
   uint32_t dex_method_idx;
+#if !defined(__i386__)
   const char* shorty;
   uint32_t shorty_len;
+#endif
   if (type == Runtime::kUnknownMethod) {
     DCHECK(called->IsRuntimeMethod());
     // less two as return address may span into next dex instruction
@@ -109,15 +111,19 @@
            (instr_code == Instruction::INVOKE_DIRECT_RANGE));
     DecodedInstruction dec_insn(instr);
     dex_method_idx = dec_insn.vB;
+#if !defined(__i386__)
     shorty = linker->MethodShorty(dex_method_idx, caller, &shorty_len);
+#endif
   } else {
     DCHECK(!called->IsRuntimeMethod());
     is_static = type == Runtime::kStaticMethod;
     is_virtual = false;
     dex_method_idx = called->GetDexMethodIndex();
+#if !defined(__i386__)
     MethodHelper mh(called);
     shorty = mh.GetShorty();
     shorty_len = mh.GetShortyLength();
+#endif
   }
 #if !defined(__i386__)
   // Discover shorty (avoid GCs)
diff --git a/src/oat_writer.cc b/src/oat_writer.cc
index 4d11237..ffdb0c8 100644
--- a/src/oat_writer.cc
+++ b/src/oat_writer.cc
@@ -258,8 +258,10 @@
                                     uint32_t method_idx, const DexFile* dex_file) {
   // derived from CompiledMethod if available
   uint32_t code_offset = 0;
+#if defined(ART_USE_LLVM_COMPILER)
   uint16_t code_elf_idx = static_cast<uint16_t>(-1u);
   uint16_t code_elf_func_idx = static_cast<uint16_t>(-1u);
+#endif
   uint32_t frame_size_in_bytes = kStackAlignment;
   uint32_t core_spill_mask = 0;
   uint32_t fp_spill_mask = 0;
@@ -268,15 +270,19 @@
   uint32_t gc_map_offset = 0;
   // derived from CompiledInvokeStub if available
   uint32_t invoke_stub_offset = 0;
+#if defined(ART_USE_LLVM_COMPILER)
   uint16_t invoke_stub_elf_idx = static_cast<uint16_t>(-1u);
   uint16_t invoke_stub_elf_func_idx = static_cast<uint16_t>(-1u);
+#endif
 
   CompiledMethod* compiled_method =
       compiler_->GetCompiledMethod(Compiler::MethodReference(dex_file, method_idx));
   if (compiled_method != NULL) {
     if (compiled_method->IsExecutableInElf()) {
+#if defined(ART_USE_LLVM_COMPILER)
       code_elf_idx = compiled_method->GetElfIndex();
       code_elf_func_idx = compiled_method->GetElfFuncIndex();
+#endif
       frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
     } else {
       offset = compiled_method->AlignCode(offset);
@@ -359,8 +365,10 @@
   const CompiledInvokeStub* compiled_invoke_stub = compiler_->FindInvokeStub(is_static, shorty);
   if (compiled_invoke_stub != NULL) {
     if (compiled_invoke_stub->IsExecutableInElf()) {
+#if defined(ART_USE_LLVM_COMPILER)
       invoke_stub_elf_idx = compiled_invoke_stub->GetElfIndex();
       invoke_stub_elf_func_idx = compiled_invoke_stub->GetElfFuncIndex();
+#endif
     } else {
       offset = CompiledMethod::AlignCode(offset, compiler_->GetInstructionSet());
       DCHECK_ALIGNED(offset, kArmAlignment);
@@ -600,10 +608,6 @@
   const CompiledMethod* compiled_method =
       compiler_->GetCompiledMethod(Compiler::MethodReference(&dex_file, method_idx));
 
-  uint32_t frame_size_in_bytes = 0;
-  uint32_t core_spill_mask = 0;
-  uint32_t fp_spill_mask = 0;
-
   OatMethodOffsets method_offsets =
       oat_classes_[oat_class_index]->method_offsets_[class_def_method_index];
 
@@ -647,9 +651,6 @@
         code_offset += code_size;
       }
       DCHECK_CODE_OFFSET();
-      frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
-      core_spill_mask = compiled_method->GetCoreSpillMask();
-      fp_spill_mask = compiled_method->GetFpSpillMask();
 
       const std::vector<uint32_t>& mapping_table = compiled_method->GetMappingTable();
       size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]);
diff --git a/src/object.h b/src/object.h
index 5e67f62..f5970f6 100644
--- a/src/object.h
+++ b/src/object.h
@@ -361,7 +361,7 @@
     const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value();
     const int64_t* addr = reinterpret_cast<const int64_t*>(raw_addr);
     if (UNLIKELY(is_volatile)) {
-      uint64_t result = QuasiAtomicRead64(addr);
+      uint64_t result = QuasiAtomic::Read64(addr);
       ANDROID_MEMBAR_FULL();
       return result;
     } else {
@@ -375,7 +375,7 @@
     int64_t* addr = reinterpret_cast<int64_t*>(raw_addr);
     if (UNLIKELY(is_volatile)) {
       ANDROID_MEMBAR_STORE();
-      QuasiAtomicSwap64(new_value, addr);
+      QuasiAtomic::Swap64(new_value, addr);
       // Post-store barrier not required due to use of atomic op or mutex.
     } else {
       *addr = new_value;
diff --git a/src/runtime.cc b/src/runtime.cc
index a94a93a..aabd86f 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -108,6 +108,8 @@
   delete intern_table_;
   delete java_vm_;
   Thread::Shutdown();
+  QuasiAtomic::Shutdown();
+
   // TODO: acquire a static mutex on Runtime to avoid racing.
   CHECK(instance_ == NULL || instance_ == this);
   instance_ = NULL;
@@ -615,6 +617,8 @@
   }
   VLOG(startup) << "Runtime::Init -verbose:startup enabled";
 
+  QuasiAtomic::Startup();
+
   SetJniGlobalsMax(options->jni_globals_max_);
   Monitor::Init(options->lock_profiling_threshold_, options->hook_is_sensitive_thread_);
 
diff --git a/src/runtime_linux.cc b/src/runtime_linux.cc
index 75540b8..e2c806d 100644
--- a/src/runtime_linux.cc
+++ b/src/runtime_linux.cc
@@ -118,7 +118,7 @@
     case SIGILL: return "SIGILL";
     case SIGPIPE: return "SIGPIPE";
     case SIGSEGV: return "SIGSEGV";
-#if defined(STIGSTLFKT)
+#if defined(SIGSTKFLT)
     case SIGSTKFLT: return "SIGSTKFLT";
 #endif
     case SIGTRAP: return "SIGTRAP";
diff --git a/src/thread.cc b/src/thread.cc
index 7f971c4..4554cee 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -412,9 +412,9 @@
       size_t old_stack_size = stack_size_;
       stack_size_ = default_stack_size;
       stack_begin_ += (old_stack_size - stack_size_);
-      LOG(WARNING) << "Limiting unlimited stack (reported as " << PrettySize(old_stack_size) << ")"
-                   << " to " << PrettySize(stack_size_)
-                   << " with base " << reinterpret_cast<void*>(stack_begin_);
+      VLOG(threads) << "Limiting unlimited stack (reported as " << PrettySize(old_stack_size) << ")"
+                    << " to " << PrettySize(stack_size_)
+                    << " with base " << reinterpret_cast<void*>(stack_begin_);
     }
   }
 #endif
@@ -502,7 +502,7 @@
 
   // Grab the scheduler stats for this thread.
   std::string scheduler_stats;
-  if (ReadFileToString(StringPrintf("/proc/self/task/%d/schedstat", GetTid()).c_str(), &scheduler_stats)) {
+  if (ReadFileToString(StringPrintf("/proc/self/task/%d/schedstat", GetTid()), &scheduler_stats)) {
     scheduler_stats.resize(scheduler_stats.size() - 1); // Lose the trailing '\n'.
   } else {
     scheduler_stats = "0 0 0";
@@ -564,6 +564,9 @@
   }
 
   virtual ~StackDumpVisitor() {
+    if (frame_count == 0) {
+      os << "  (no managed stack frames)\n";
+    }
   }
 
   bool VisitFrame(const Frame& frame, uintptr_t pc) {
@@ -620,12 +623,35 @@
 void Thread::DumpStack(std::ostream& os) const {
   // If we're currently in native code, dump that stack before dumping the managed stack.
   if (GetState() == kNative || GetState() == kVmWait) {
+    DumpKernelStack(os);
     DumpNativeStack(os);
   }
   StackDumpVisitor dumper(os, this);
   WalkStack(&dumper);
 }
 
+#if !defined(__APPLE__)
+void Thread::DumpKernelStack(std::ostream& os) const {
+  std::string kernel_stack_filename(StringPrintf("/proc/self/task/%d/stack", GetTid()));
+  std::string kernel_stack;
+  if (!ReadFileToString(kernel_stack_filename, &kernel_stack)) {
+    os << "  (couldn't read " << kernel_stack_filename << ")";
+  }
+
+  std::vector<std::string> kernel_stack_frames;
+  Split(kernel_stack, '\n', kernel_stack_frames);
+  // We skip the last stack frame because it's always equivalent to "[<ffffffff>] 0xffffffff",
+  // which looking at the source appears to be the kernel's way of saying "that's all, folks!".
+  kernel_stack_frames.pop_back();
+  for (size_t i = 0; i < kernel_stack_frames.size(); ++i) {
+    os << "  kernel: " << kernel_stack_frames[i] << "\n";
+  }
+}
+#else
+// TODO: can we get the kernel stack on Mac OS?
+void Thread::DumpKernelStack(std::ostream&) const {}
+#endif
+
 void Thread::SetStateWithoutSuspendCheck(ThreadState new_state) {
   volatile void* raw = reinterpret_cast<volatile void*>(&state_);
   volatile int32_t* addr = reinterpret_cast<volatile int32_t*>(raw);
diff --git a/src/thread.h b/src/thread.h
index c5695cf..8ff9dfb 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -484,6 +484,7 @@
 
   void DumpState(std::ostream& os) const;
   void DumpStack(std::ostream& os) const;
+  void DumpKernelStack(std::ostream& os) const;
   void DumpNativeStack(std::ostream& os) const;
 
   // Out-of-line conveniences for debugging in gdb.
diff --git a/src/thread_android.cc b/src/thread_android.cc
index d26f446..4d982b1 100644
--- a/src/thread_android.cc
+++ b/src/thread_android.cc
@@ -97,6 +97,7 @@
     os << "  (unwind_backtrace_thread failed for thread " << GetTid() << ".)";
     return;
   } else if (frame_count == 0) {
+    os << "  (no native stack frames)";
     return;
   }
 
diff --git a/src/utils.cc b/src/utils.cc
index bfa0c4f..629d513 100644
--- a/src/utils.cc
+++ b/src/utils.cc
@@ -855,7 +855,7 @@
 void GetTaskStats(pid_t tid, int& utime, int& stime, int& task_cpu) {
   utime = stime = task_cpu = 0;
   std::string stats;
-  if (!ReadFileToString(StringPrintf("/proc/self/task/%d/stat", tid).c_str(), &stats)) {
+  if (!ReadFileToString(StringPrintf("/proc/self/task/%d/stat", tid), &stats)) {
     return;
   }
   // Skip the command, which may contain spaces.
diff --git a/src/verifier/method_verifier.cc b/src/verifier/method_verifier.cc
index 60b17d6..7d56fa7 100644
--- a/src/verifier/method_verifier.cc
+++ b/src/verifier/method_verifier.cc
@@ -1848,7 +1848,7 @@
     case Instruction::INVOKE_DIRECT_RANGE: {
       bool is_range = (dec_insn.opcode == Instruction::INVOKE_DIRECT_RANGE);
       Method* called_method = VerifyInvocationArgs(dec_insn, METHOD_DIRECT, is_range, false);
-      if (called_method != NULL) {
+      if (called_method != NULL && called_method->IsConstructor()) {
         /*
          * Some additional checks when calling a constructor. We know from the invocation arg check
          * that the "this" argument is an instance of called_method->klass. Now we further restrict
@@ -1856,56 +1856,36 @@
          * allowing the latter only if the "this" argument is the same as the "this" argument to
          * this method (which implies that we're in a constructor ourselves).
          */
-        if (called_method->IsConstructor()) {
-          const RegType& this_type = work_line_->GetInvocationThis(dec_insn);
-          if (this_type.IsConflict())  // failure.
-            break;
+        const RegType& this_type = work_line_->GetInvocationThis(dec_insn);
+        if (this_type.IsConflict())  // failure.
+          break;
 
-          /* no null refs allowed (?) */
-          if (this_type.IsZero()) {
-            Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "unable to initialize null ref";
-            break;
-          }
-          if (called_method != NULL) {
-            /* must be in same class or in superclass */
-            const RegType& this_super_klass = this_type.GetSuperClass(&reg_types_);
-            if (this_super_klass.IsConflict()) {
-              // Unknown super class, fail so we re-check at runtime.
-              Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "super class unknown for '" << this_type << "'";
-              break;
-            } else {
-              if (!this_super_klass.IsZero() &&
-                  called_method->GetDeclaringClass() == this_super_klass.GetClass()) {
-                if (this_type.GetClass() != GetDeclaringClass().GetClass()) {
-                  Fail(VERIFY_ERROR_BAD_CLASS_HARD)
-                        << "invoke-direct <init> on super only allowed for 'this' in <init>"
-                        << " (this class '" << this_type << "', called class '"
-                        << PrettyDescriptor(called_method->GetDeclaringClass()) << "')";
-                  break;
-                }
-              } else if (this_type.GetClass() != called_method->GetDeclaringClass()) {
-                Fail(VERIFY_ERROR_BAD_CLASS_HARD)
-                      << "invoke-direct <init> must be on current class or super"
-                      << " (current class '" << this_type << "', called class '"
-                      << PrettyDescriptor(called_method->GetDeclaringClass()) << "')";
-                break;
-              }
-            }
-          }
-
-          /* arg must be an uninitialized reference */
-          if (!this_type.IsUninitializedTypes()) {
-            Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Expected initialization on uninitialized reference "
-                << this_type;
-            break;
-          }
-
-          /*
-           * Replace the uninitialized reference with an initialized one. We need to do this for all
-           * registers that have the same object instance in them, not just the "this" register.
-           */
-          work_line_->MarkRefsAsInitialized(this_type);
+        /* no null refs allowed (?) */
+        if (this_type.IsZero()) {
+          Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "unable to initialize null ref";
+          break;
         }
+
+        /* must be in same class or in superclass */
+        const RegType& this_super_klass = this_type.GetSuperClass(&reg_types_);
+        if (this_super_klass.IsConflict()) {
+          // Unknown super class, fail so we re-check at runtime.
+          Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "super class unknown for '" << this_type << "'";
+          break;
+        }
+
+        /* arg must be an uninitialized reference */
+        if (!this_type.IsUninitializedTypes()) {
+          Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Expected initialization on uninitialized reference "
+              << this_type;
+          break;
+        }
+
+        /*
+         * Replace the uninitialized reference with an initialized one. We need to do this for all
+         * registers that have the same object instance in them, not just the "this" register.
+         */
+        work_line_->MarkRefsAsInitialized(this_type);
       }
       const char* descriptor;
       if (called_method == NULL) {
@@ -2226,7 +2206,7 @@
 
   if (have_pending_hard_failure_) {
     if (!Runtime::Current()->IsStarted()) {
-      /* When compiling, check that the first failure is a hard failure */
+      /* When compiling, check that the last failure is a hard failure */
       CHECK_EQ(failures_[failures_.size() - 1], VERIFY_ERROR_BAD_CLASS_HARD);
     }
     /* immediate failure, reject class */
@@ -2540,7 +2520,7 @@
   if (!referrer.CanAccessMember(res_method->GetDeclaringClass(), res_method->GetAccessFlags())) {
     Fail(VERIFY_ERROR_ACCESS_METHOD) << "illegal method access (call " << PrettyMethod(res_method)
                                      << " from " << referrer << ")";
-    return NULL;
+    return res_method;
   }
   // Check that invoke-virtual and invoke-super are not used on private methods of the same class.
   if (res_method->IsPrivate() && method_type == METHOD_VIRTUAL) {
@@ -2585,20 +2565,20 @@
   if (is_super) {
     DCHECK(method_type == METHOD_VIRTUAL);
     const RegType& super = GetDeclaringClass().GetSuperClass(&reg_types_);
+    if (super.IsConflict()) {  // unknown super class
+      Fail(VERIFY_ERROR_NO_METHOD) << "unknown super class in invoke-super from "
+                                   << PrettyMethod(method_idx_, *dex_file_)
+                                   << " to super " << PrettyMethod(res_method);
+      return NULL;
+    }
     Class* super_klass = super.GetClass();
     if (res_method->GetMethodIndex() >= super_klass->GetVTable()->GetLength()) {
-      if (super.IsConflict()) {  // Only Object has no super class
-        Fail(VERIFY_ERROR_NO_METHOD) << "invalid invoke-super from "
-                                     << PrettyMethod(method_idx_, *dex_file_)
-                                     << " to super " << PrettyMethod(res_method);
-      } else {
-        MethodHelper mh(res_method);
-        Fail(VERIFY_ERROR_NO_METHOD) << "invalid invoke-super from "
-                                     << PrettyMethod(method_idx_, *dex_file_)
-                                     << " to super " << super
-                                     << "." << mh.GetName()
-                                     << mh.GetSignature();
-      }
+      MethodHelper mh(res_method);
+      Fail(VERIFY_ERROR_NO_METHOD) << "invalid invoke-super from "
+                                   << PrettyMethod(method_idx_, *dex_file_)
+                                   << " to super " << super
+                                   << "." << mh.GetName()
+                                   << mh.GetSignature();
       return NULL;
     }
   }
@@ -2663,7 +2643,7 @@
     const RegType& reg_type = reg_types_.FromDescriptor(class_loader_, descriptor);
     uint32_t get_reg = is_range ? dec_insn.vC + actual_args : dec_insn.arg[actual_args];
     if (!work_line_->VerifyRegisterType(get_reg, reg_type)) {
-      return NULL;
+      return res_method;
     }
     actual_args = reg_type.IsLongOrDoubleTypes() ? actual_args + 2 : actual_args + 1;
   }
@@ -2914,7 +2894,6 @@
       Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "expected field " << PrettyField(field)
                                         << " to be of type '" << insn_type
                                         << "' but found type '" << field_type << "' in get";
-      work_line_->SetRegisterType(dec_insn.vA, reg_types_.Conflict());
       return;
     }
   } else {
@@ -3021,10 +3000,10 @@
   size_t failure_number = failures_.size();
   CHECK_NE(failure_number, 0U);
   DCHECK_EQ(failure_messages_.size(), failure_number);
-  std::ostringstream* failure_message = failure_messages_[failure_number - 1];
-  VerifyError failure = failures_[failure_number - 1];
-  failures_.pop_back();
-  failure_messages_.pop_back();
+  std::ostringstream* failure_message = failure_messages_[0];
+  VerifyError failure = failures_[0];
+  failures_.clear();
+  failure_messages_.clear();
   have_pending_rewrite_failure_ = false;
 
   if (Runtime::Current()->IsStarted()) {
diff --git a/src/verifier/reg_type.h b/src/verifier/reg_type.h
index 9f89d07..6f0193f 100644
--- a/src/verifier/reg_type.h
+++ b/src/verifier/reg_type.h
@@ -144,13 +144,11 @@
   }
 
   bool IsReferenceTypes() const {
-    return IsReference() || IsUnresolvedReference() ||  IsZero() ||
-        IsUninitializedReference() ||  IsUninitializedThisReference() ||
-        IsUnresolvedAndUninitializedReference() || IsUnresolvedAndUninitializedThisReference();
+    return IsNonZeroReferenceTypes() || IsZero();
   }
   bool IsNonZeroReferenceTypes() const {
-    return IsReference() || IsUnresolvedReference() ||  IsZero() ||
-        IsUninitializedReference() ||  IsUninitializedThisReference() ||
+    return IsReference() || IsUnresolvedReference() ||
+        IsUninitializedReference() || IsUninitializedThisReference() ||
         IsUnresolvedAndUninitializedReference() || IsUnresolvedAndUninitializedThisReference();
   }
   bool IsCategory1Types() const {