Merge "Revert "Revert "ART: Extracts an utility function of the duplicated code"""
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index 4b655b5..8357b8e 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -17,6 +17,7 @@
 LOCAL_PATH := art
 
 RUNTIME_GTEST_COMMON_SRC_FILES := \
+	runtime/arch/stub_test.cc \
 	runtime/barrier_test.cc \
 	runtime/base/bit_field_test.cc \
 	runtime/base/bit_vector_test.cc \
diff --git a/runtime/Android.mk b/runtime/Android.mk
index d433fd5..bc971a9 100644
--- a/runtime/Android.mk
+++ b/runtime/Android.mk
@@ -36,10 +36,10 @@
 	base/unix_file/string_file.cc \
 	check_jni.cc \
 	catch_block_stack_visitor.cc \
-	catch_finder.cc \
 	class_linker.cc \
 	common_throws.cc \
 	debugger.cc \
+	deoptimize_stack_visitor.cc \
 	dex_file.cc \
 	dex_file_verifier.cc \
 	dex_instruction.cc \
@@ -129,6 +129,7 @@
 	os_linux.cc \
 	parsed_options.cc \
 	primitive.cc \
+	quick_exception_handler.cc \
 	quick/inline_method_analyser.cc \
 	reference_table.cc \
 	reflection.cc \
diff --git a/runtime/arch/arm/quick_entrypoints_arm.S b/runtime/arch/arm/quick_entrypoints_arm.S
index 4903732..7cc8da8 100644
--- a/runtime/arch/arm/quick_entrypoints_arm.S
+++ b/runtime/arch/arm/quick_entrypoints_arm.S
@@ -492,11 +492,22 @@
     blx lr
 .Lcheck_assignability:
     push {r0-r2, lr}             @ save arguments
+    .save {r0-r2, lr}
+    .cfi_adjust_cfa_offset 16
+    .cfi_rel_offset r0, 0
+    .cfi_rel_offset r1, 4
+    .cfi_rel_offset r2, 8
+    .cfi_rel_offset lr, 12
     mov r1, ip
     mov r0, r3
     bl artIsAssignableFromCode
     cbz r0, .Lthrow_array_store_exception
     pop {r0-r2, lr}
+    .cfi_restore r0
+    .cfi_restore r1
+    .cfi_restore r2
+    .cfi_restore lr
+    .cfi_adjust_cfa_offset -16
     add r3, r0, #OBJECT_ARRAY_DATA_OFFSET
     str r2, [r3, r1, lsl #2]
     ldr r3, [r9, #THREAD_CARD_TABLE_OFFSET]
@@ -505,6 +516,11 @@
     blx lr
 .Lthrow_array_store_exception:
     pop {r0-r2, lr}
+    .cfi_restore r0
+    .cfi_restore r1
+    .cfi_restore r2
+    .cfi_restore lr
+    .cfi_adjust_cfa_offset -16
     SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
     mov r1, r2
     mov r2, r9                   @ pass Thread::Current
diff --git a/runtime/arch/arm64/quick_entrypoints_arm64.S b/runtime/arch/arm64/quick_entrypoints_arm64.S
index 6ce5d06..1350198 100644
--- a/runtime/arch/arm64/quick_entrypoints_arm64.S
+++ b/runtime/arch/arm64/quick_entrypoints_arm64.S
@@ -864,7 +864,58 @@
 
 UNIMPLEMENTED art_quick_lock_object
 UNIMPLEMENTED art_quick_unlock_object
-UNIMPLEMENTED art_quick_check_cast
+
+    /*
+     * Entry from managed code that calls artIsAssignableFromCode and on failure calls
+     * artThrowClassCastException.
+     */
+    .extern artThrowClassCastException
+ENTRY art_quick_check_cast
+    // Store arguments and link register
+    sub sp, sp, #32                     // Stack needs to be 16b aligned on calls
+    .cfi_adjust_cfa_offset 32
+    stp x0, x1, [sp]
+    .cfi_rel_offset x0, 0
+    .cfi_rel_offset x1, 8
+    stp xSELF, xLR, [sp, #16]
+    .cfi_rel_offset x18, 16
+    .cfi_rel_offset x30, 24
+
+    // Call runtime code
+    bl artIsAssignableFromCode
+
+    // Check for exception
+    cbz x0, .Lthrow_class_cast_exception
+
+    // Restore and return
+    ldp x0, x1, [sp]
+    .cfi_restore x0
+    .cfi_restore x1
+    ldp xSELF, xLR, [sp, #16]
+    .cfi_restore x18
+    .cfi_restore x30
+    add sp, sp, #32
+    .cfi_adjust_cfa_offset -32
+    ret
+
+.Lthrow_class_cast_exception:
+    // Restore
+    ldp x0, x1, [sp]
+    .cfi_restore x0
+    .cfi_restore x1
+    ldp xSELF, xLR, [sp, #16]
+    .cfi_restore x18
+    .cfi_restore x30
+    add sp, sp, #32
+    .cfi_adjust_cfa_offset -32
+
+    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME  // save all registers as basis for long jump context
+    mov x2, xSELF                     // pass Thread::Current
+    mov x3, sp                        // pass SP
+    b artThrowClassCastException      // (Class*, Class*, Thread*, SP)
+    brk 0                             // We should not return here...
+END art_quick_check_cast
+
 UNIMPLEMENTED art_quick_aput_obj_with_null_and_bound_check
 UNIMPLEMENTED art_quick_aput_obj_with_bound_check
 UNIMPLEMENTED art_quick_aput_obj
diff --git a/runtime/arch/stub_test.cc b/runtime/arch/stub_test.cc
new file mode 100644
index 0000000..543e695
--- /dev/null
+++ b/runtime/arch/stub_test.cc
@@ -0,0 +1,357 @@
+/*
+ * 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.
+ */
+
+#include "common_runtime_test.h"
+
+#include <cstdio>
+
+namespace art {
+
+
+class StubTest : public CommonRuntimeTest {
+ protected:
+  // We need callee-save methods set up in the Runtime for exceptions.
+  void SetUp() OVERRIDE {
+    // Do the normal setup.
+    CommonRuntimeTest::SetUp();
+
+    {
+      // Create callee-save methods
+      ScopedObjectAccess soa(Thread::Current());
+      for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
+        Runtime::CalleeSaveType type = Runtime::CalleeSaveType(i);
+        if (!runtime_->HasCalleeSaveMethod(type)) {
+          runtime_->SetCalleeSaveMethod(runtime_->CreateCalleeSaveMethod(kRuntimeISA, type), type);
+        }
+      }
+    }
+  }
+
+
+  size_t Invoke3(size_t arg0, size_t arg1, size_t arg2, uintptr_t code, Thread* self) {
+    // Push a transition back into managed code onto the linked list in thread.
+    ManagedStack fragment;
+    self->PushManagedStackFragment(&fragment);
+
+    size_t result;
+#if defined(__i386__)
+    // TODO: Set the thread?
+    __asm__ __volatile__(
+        "pushl $0\n\t"               // Push nullptr to terminate quick stack
+        "call *%%edi\n\t"           // Call the stub
+        "addl $4, %%esp"               // Pop nullptr
+        : "=a" (result)
+          // Use the result from eax
+        : "a"(arg0), "c"(arg1), "d"(arg2), "D"(code)
+          // This places code into edi, arg0 into eax, arg1 into ecx, and arg2 into edx
+        : );  // clobber.
+    // TODO: Should we clobber the other registers? EBX gets clobbered by some of the stubs,
+    //       but compilation fails when declaring that.
+#elif defined(__arm__)
+    __asm__ __volatile__(
+        "push {r1-r2,r9, lr}\n\t"   // Save the link and thread register
+        ".cfi_adjust_cfa_offset 16\n\t"
+        "mov r0, %[arg0]\n\t"       // Set arg0-arg2
+        "mov r1, %[arg1]\n\t"       // TODO: Any way to use constraints like on x86?
+        "mov r2, %[arg2]\n\t"
+        // Use r9 last as we don't know whether it was used for arg0-arg2
+        "mov r9, #0\n\t"            // Push nullptr to terminate stack
+        "push {r9}\n\t"
+        ".cfi_adjust_cfa_offset 4\n\t"
+        "mov r9, %[self]\n\t"       // Set the thread
+        "blx %[code]\n\t"           // Call the stub
+        "pop {r1}\n\t"              // Pop nullptr
+        ".cfi_adjust_cfa_offset -4\n\t"
+        "pop {r1-r2,r9, lr}\n\t"    // Restore the link and thread register
+        ".cfi_adjust_cfa_offset -16\n\t"
+        "mov %[result], r0\n\t"     // Save the result
+        : [result] "=r" (result)
+          // Use the result from r0
+        : [arg0] "0"(arg0), [arg1] "r"(arg1), [arg2] "r"(arg2), [code] "r"(code), [self] "r"(self)
+        : );  // clobber.
+#elif defined(__aarch64__)
+    __asm__ __volatile__(
+        "sub sp, sp, #48\n\t"          // Reserve stack space, 16B aligned
+        "stp xzr, x1, [sp]\n\t"        // nullptr(end of quick stack), x1
+        "stp x2, x18, [sp, #16]\n\t"   // Save x2, x18(xSELF)
+        "str x30, [sp, #32]\n\t"       // Save xLR
+        "mov x0, %[arg0]\n\t"          // Set arg0-arg2
+        "mov x1, %[arg1]\n\t"          // TODO: Any way to use constraints like on x86?
+        "mov x2, %[arg2]\n\t"
+        // Use r18 last as we don't know whether it was used for arg0-arg2
+        "mov x18, %[self]\n\t"         // Set the thread
+        "blr %[code]\n\t"              // Call the stub
+        "ldp x1, x2, [sp, #8]\n\t"     // Restore x1, x2
+        "ldp x18, x30, [sp, #24]\n\t"  // Restore xSELF, xLR
+        "add sp, sp, #48\n\t"          // Free stack space
+        "mov %[result], x0\n\t"        // Save the result
+        : [result] "=r" (result)
+          // Use the result from r0
+        : [arg0] "0"(arg0), [arg1] "r"(arg1), [arg2] "r"(arg2), [code] "r"(code), [self] "r"(self)
+        : "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17");  // clobber.
+#elif defined(__x86_64__)
+    // Note: Uses the native convention
+    // TODO: Set the thread?
+    __asm__ __volatile__(
+        "pushq $0\n\t"                 // Push nullptr to terminate quick stack
+        "pushq $0\n\t"                 // 16B alignment padding
+        "call *%%rax\n\t"              // Call the stub
+        "addq $16, %%rsp"              // Pop nullptr and padding
+        : "=a" (result)
+          // Use the result from rax
+        : "D"(arg0), "S"(arg1), "d"(arg2), "a"(code)
+          // This places arg0 into rdi, arg1 into rsi, arg2 into rdx, and code into rax
+        : "rcx", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15");  // clobber all
+    // TODO: Should we clobber the other registers?
+    result = 0;
+#else
+    LOG(WARNING) << "Was asked to invoke for an architecture I do not understand.";
+    result = 0;
+#endif
+    // Pop transition.
+    self->PopManagedStackFragment(fragment);
+    return result;
+  }
+};
+
+
+#if defined(__i386__) || defined(__x86_64__)
+extern "C" void art_quick_memcpy(void);
+#endif
+
+TEST_F(StubTest, Memcpy) {
+#if defined(__i386__) || defined(__x86_64__)
+  Thread* self = Thread::Current();
+
+  uint32_t orig[20];
+  uint32_t trg[20];
+  for (size_t i = 0; i < 20; ++i) {
+    orig[i] = i;
+    trg[i] = 0;
+  }
+
+  Invoke3(reinterpret_cast<size_t>(&trg[4]), reinterpret_cast<size_t>(&orig[4]),
+          10 * sizeof(uint32_t), reinterpret_cast<uintptr_t>(&art_quick_memcpy), self);
+
+  EXPECT_EQ(orig[0], trg[0]);
+
+  for (size_t i = 1; i < 4; ++i) {
+    EXPECT_NE(orig[i], trg[i]);
+  }
+
+  for (size_t i = 4; i < 14; ++i) {
+    EXPECT_EQ(orig[i], trg[i]);
+  }
+
+  for (size_t i = 14; i < 20; ++i) {
+    EXPECT_NE(orig[i], trg[i]);
+  }
+
+  // TODO: Test overlapping?
+
+#else
+  LOG(INFO) << "Skipping memcpy as I don't know how to do that on " << kRuntimeISA;
+  // Force-print to std::cout so it's also outside the logcat.
+  std::cout << "Skipping memcpy as I don't know how to do that on " << kRuntimeISA << std::endl;
+#endif
+}
+
+
+#if defined(__i386__) || defined(__arm__)
+extern "C" void art_quick_lock_object(void);
+#endif
+
+TEST_F(StubTest, LockObject) {
+#if defined(__i386__) || defined(__arm__)
+  Thread* self = Thread::Current();
+  // Create an object
+  ScopedObjectAccess soa(self);
+  // garbage is created during ClassLinker::Init
+
+  SirtRef<mirror::String> obj(soa.Self(),
+                              mirror::String::AllocFromModifiedUtf8(soa.Self(), "hello, world!"));
+  LockWord lock = obj->GetLockWord(false);
+  LockWord::LockState old_state = lock.GetState();
+  EXPECT_EQ(LockWord::LockState::kUnlocked, old_state);
+
+  Invoke3(reinterpret_cast<size_t>(obj.get()), 0U, 0U,
+          reinterpret_cast<uintptr_t>(&art_quick_lock_object), self);
+
+  LockWord lock_after = obj->GetLockWord(false);
+  LockWord::LockState new_state = lock_after.GetState();
+  EXPECT_EQ(LockWord::LockState::kThinLocked, new_state);
+
+  Invoke3(reinterpret_cast<size_t>(obj.get()), 0U, 0U,
+          reinterpret_cast<uintptr_t>(&art_quick_lock_object), self);
+
+  LockWord lock_after2 = obj->GetLockWord(false);
+  LockWord::LockState new_state2 = lock_after2.GetState();
+  EXPECT_EQ(LockWord::LockState::kThinLocked, new_state2);
+
+  // TODO: Improve this test. Somehow force it to go to fat locked. But that needs another thread.
+
+#else
+  LOG(INFO) << "Skipping lock_object as I don't know how to do that on " << kRuntimeISA;
+  // Force-print to std::cout so it's also outside the logcat.
+  std::cout << "Skipping lock_object as I don't know how to do that on " << kRuntimeISA << std::endl;
+#endif
+}
+
+
+#if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || defined(__x86_64__)
+extern "C" void art_quick_check_cast(void);
+#endif
+
+TEST_F(StubTest, CheckCast) {
+#if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || defined(__x86_64__)
+  Thread* self = Thread::Current();
+  // Find some classes.
+  ScopedObjectAccess soa(self);
+  // garbage is created during ClassLinker::Init
+
+  SirtRef<mirror::Class> c(soa.Self(), class_linker_->FindSystemClass(soa.Self(),
+                                                                          "[Ljava/lang/Object;"));
+  SirtRef<mirror::Class> c2(soa.Self(), class_linker_->FindSystemClass(soa.Self(),
+                                                                            "[Ljava/lang/String;"));
+
+  EXPECT_FALSE(self->IsExceptionPending());
+
+  Invoke3(reinterpret_cast<size_t>(c.get()), reinterpret_cast<size_t>(c.get()), 0U,
+          reinterpret_cast<uintptr_t>(&art_quick_check_cast), self);
+
+  EXPECT_FALSE(self->IsExceptionPending());
+
+  Invoke3(reinterpret_cast<size_t>(c2.get()), reinterpret_cast<size_t>(c2.get()), 0U,
+          reinterpret_cast<uintptr_t>(&art_quick_check_cast), self);
+
+  EXPECT_FALSE(self->IsExceptionPending());
+
+  Invoke3(reinterpret_cast<size_t>(c.get()), reinterpret_cast<size_t>(c2.get()), 0U,
+          reinterpret_cast<uintptr_t>(&art_quick_check_cast), self);
+
+  EXPECT_FALSE(self->IsExceptionPending());
+
+  // TODO: Make the following work. But that would require correct managed frames.
+
+  Invoke3(reinterpret_cast<size_t>(c2.get()), reinterpret_cast<size_t>(c.get()), 0U,
+          reinterpret_cast<uintptr_t>(&art_quick_check_cast), self);
+
+  EXPECT_TRUE(self->IsExceptionPending());
+  self->ClearException();
+
+#else
+  LOG(INFO) << "Skipping check_cast as I don't know how to do that on " << kRuntimeISA;
+  // Force-print to std::cout so it's also outside the logcat.
+  std::cout << "Skipping check_cast as I don't know how to do that on " << kRuntimeISA << std::endl;
+#endif
+}
+
+
+#if defined(__i386__) || defined(__arm__)
+extern "C" void art_quick_aput_obj_with_null_and_bound_check(void);
+// Do not check non-checked ones, we'd need handlers and stuff...
+#endif
+
+TEST_F(StubTest, APutObj) {
+#if defined(__i386__) || defined(__arm__)
+  Thread* self = Thread::Current();
+  // Create an object
+  ScopedObjectAccess soa(self);
+  // garbage is created during ClassLinker::Init
+
+  SirtRef<mirror::Class> c(soa.Self(), class_linker_->FindSystemClass(soa.Self(),
+                                                                            "Ljava/lang/Object;"));
+  SirtRef<mirror::Class> c2(soa.Self(), class_linker_->FindSystemClass(soa.Self(),
+                                                                            "Ljava/lang/String;"));
+  SirtRef<mirror::Class> ca(soa.Self(), class_linker_->FindSystemClass(soa.Self(),
+                                                                            "[Ljava/lang/String;"));
+
+  // Build a string array of size 1
+  SirtRef<mirror::ObjectArray<mirror::Object> > array(soa.Self(),
+            mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), ca.get(), 1));
+
+  // Build a string -> should be assignable
+  SirtRef<mirror::Object> str_obj(soa.Self(),
+                                  mirror::String::AllocFromModifiedUtf8(soa.Self(), "hello, world!"));
+
+  // Build a generic object -> should fail assigning
+  SirtRef<mirror::Object> obj_obj(soa.Self(), c->AllocObject(soa.Self()));
+
+  // Play with it...
+
+  // 1) Success cases
+  // 1.1) Assign str_obj to array[0]
+
+  EXPECT_FALSE(self->IsExceptionPending());
+
+  Invoke3(reinterpret_cast<size_t>(array.get()), 0U, reinterpret_cast<size_t>(str_obj.get()),
+          reinterpret_cast<uintptr_t>(&art_quick_aput_obj_with_null_and_bound_check), self);
+
+  EXPECT_FALSE(self->IsExceptionPending());
+
+  // 1.2) Assign null to array[0]
+
+  Invoke3(reinterpret_cast<size_t>(array.get()), 0U, reinterpret_cast<size_t>(nullptr),
+          reinterpret_cast<uintptr_t>(&art_quick_aput_obj_with_null_and_bound_check), self);
+
+  EXPECT_FALSE(self->IsExceptionPending());
+
+  // TODO: Check _which_ exception is thrown. Then make 3) check that it's the right check order.
+
+  // 2) Failure cases (str into str[])
+  // 2.1) Array = null
+  // TODO: Throwing NPE needs actual DEX code
+
+//  Invoke3(reinterpret_cast<size_t>(nullptr), 0U, reinterpret_cast<size_t>(str_obj.get()),
+//          reinterpret_cast<uintptr_t>(&art_quick_aput_obj_with_null_and_bound_check), self);
+//
+//  EXPECT_TRUE(self->IsExceptionPending());
+//  self->ClearException();
+
+  // 2.2) Index < 0
+
+  Invoke3(reinterpret_cast<size_t>(array.get()), static_cast<size_t>(-1),
+          reinterpret_cast<size_t>(str_obj.get()),
+          reinterpret_cast<uintptr_t>(&art_quick_aput_obj_with_null_and_bound_check), self);
+
+  EXPECT_TRUE(self->IsExceptionPending());
+  self->ClearException();
+
+  // 2.3) Index > 0
+
+  Invoke3(reinterpret_cast<size_t>(array.get()), 1U, reinterpret_cast<size_t>(str_obj.get()),
+          reinterpret_cast<uintptr_t>(&art_quick_aput_obj_with_null_and_bound_check), self);
+
+  EXPECT_TRUE(self->IsExceptionPending());
+  self->ClearException();
+
+  // 3) Failure cases (obj into str[])
+
+  Invoke3(reinterpret_cast<size_t>(array.get()), 0U, reinterpret_cast<size_t>(obj_obj.get()),
+          reinterpret_cast<uintptr_t>(&art_quick_aput_obj_with_null_and_bound_check), self);
+
+  EXPECT_TRUE(self->IsExceptionPending());
+  self->ClearException();
+
+  // Tests done.
+#else
+  LOG(INFO) << "Skipping aput_obj as I don't know how to do that on " << kRuntimeISA;
+  // Force-print to std::cout so it's also outside the logcat.
+  std::cout << "Skipping aput_obj as I don't know how to do that on " << kRuntimeISA << std::endl;
+#endif
+}
+
+}  // namespace art
diff --git a/runtime/arch/x86_64/quick_entrypoints_x86_64.S b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
index 6509a9b..4951ad0 100644
--- a/runtime/arch/x86_64/quick_entrypoints_x86_64.S
+++ b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
@@ -666,8 +666,22 @@
 END_FUNCTION art_quick_is_assignable
 
 DEFINE_FUNCTION art_quick_check_cast
-    int3
-    int3
+    PUSH rdi                          // Save args for exc
+    PUSH rsi
+    call PLT_SYMBOL(artIsAssignableFromCode)  // (Class* klass, Class* ref_klass)
+    testq %rax, %rax
+    jz 1f                             // jump forward if not assignable
+    addq LITERAL(16), %rsp            // pop arguments
+    CFI_ADJUST_CFA_OFFSET(-16)
+    ret
+1:
+    POP rsi                           // Pop arguments
+    POP rdi
+    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME  // save all registers as basis for long jump context
+    mov %rsp, %rcx                    // pass SP
+    mov %gs:THREAD_SELF_OFFSET, %rdx  // pass Thread::Current()
+    call PLT_SYMBOL(artThrowClassCastException) // (Class* a, Class* b, Thread*, SP)
+    int3                              // unreached
 END_FUNCTION art_quick_check_cast
 
     /*
@@ -678,7 +692,12 @@
 UNIMPLEMENTED art_quick_aput_obj_with_null_and_bound_check
 UNIMPLEMENTED art_quick_aput_obj_with_bound_check
 UNIMPLEMENTED art_quick_aput_obj
-UNIMPLEMENTED art_quick_memcpy
+
+// TODO: This is quite silly on X86_64 now.
+DEFINE_FUNCTION art_quick_memcpy
+    call PLT_SYMBOL(memcpy)       // (void*, const void*, size_t)
+    ret
+END_FUNCTION art_quick_memcpy
 
 NO_ARG_DOWNCALL art_quick_test_suspend, artTestSuspendFromCode, ret
 
diff --git a/runtime/catch_block_stack_visitor.cc b/runtime/catch_block_stack_visitor.cc
index 410fff9..8d10a97 100644
--- a/runtime/catch_block_stack_visitor.cc
+++ b/runtime/catch_block_stack_visitor.cc
@@ -17,27 +17,26 @@
 #include "catch_block_stack_visitor.h"
 
 #include "dex_instruction.h"
-#include "catch_finder.h"
+#include "mirror/art_method-inl.h"
+#include "quick_exception_handler.h"
 #include "sirt_ref.h"
 #include "verifier/method_verifier.h"
 
 namespace art {
 
 bool CatchBlockStackVisitor::VisitFrame() {
-  catch_finder_->SetHandlerFrameId(GetFrameId());
+  exception_handler_->SetHandlerFrameId(GetFrameId());
   mirror::ArtMethod* method = GetMethod();
   if (method == nullptr) {
     // This is the upcall, we remember the frame and last pc so that we may long jump to them.
-    catch_finder_->SetHandlerQuickFramePc(GetCurrentQuickFramePc());
-    catch_finder_->SetHandlerQuickFrame(GetCurrentQuickFrame());
+    exception_handler_->SetHandlerQuickFramePc(GetCurrentQuickFramePc());
+    exception_handler_->SetHandlerQuickFrame(GetCurrentQuickFrame());
     return false;  // End stack walk.
   } else {
     if (method->IsRuntimeMethod()) {
       // Ignore callee save method.
       DCHECK(method->IsCalleeSaveMethod());
       return true;
-    } else if (is_deoptimization_) {
-      return HandleDeoptimization(method);
     } else {
       return HandleTryItems(method);
     }
@@ -46,68 +45,21 @@
 
 bool CatchBlockStackVisitor::HandleTryItems(mirror::ArtMethod* method) {
   uint32_t dex_pc = DexFile::kDexNoIndex;
-  if (method->IsNative()) {
-    ++native_method_count_;
-  } else {
+  if (!method->IsNative()) {
     dex_pc = GetDexPc();
   }
   if (dex_pc != DexFile::kDexNoIndex) {
     bool clear_exception = false;
-    SirtRef<mirror::Class> sirt_method_to_find(Thread::Current(), to_find_);
-    uint32_t found_dex_pc = method->FindCatchBlock(sirt_method_to_find, dex_pc, &clear_exception);
-    to_find_ = sirt_method_to_find.get();
-    catch_finder_->SetClearException(clear_exception);
+    uint32_t found_dex_pc = method->FindCatchBlock(to_find_, dex_pc, &clear_exception);
+    exception_handler_->SetClearException(clear_exception);
     if (found_dex_pc != DexFile::kDexNoIndex) {
-      catch_finder_->SetHandlerDexPc(found_dex_pc);
-      catch_finder_->SetHandlerQuickFramePc(method->ToNativePc(found_dex_pc));
-      catch_finder_->SetHandlerQuickFrame(GetCurrentQuickFrame());
+      exception_handler_->SetHandlerDexPc(found_dex_pc);
+      exception_handler_->SetHandlerQuickFramePc(method->ToNativePc(found_dex_pc));
+      exception_handler_->SetHandlerQuickFrame(GetCurrentQuickFrame());
       return false;  // End stack walk.
     }
   }
   return true;  // Continue stack walk.
 }
 
-bool CatchBlockStackVisitor::HandleDeoptimization(mirror::ArtMethod* m) {
-  MethodHelper mh(m);
-  const DexFile::CodeItem* code_item = mh.GetCodeItem();
-  CHECK(code_item != nullptr);
-  uint16_t num_regs = code_item->registers_size_;
-  uint32_t dex_pc = GetDexPc();
-  const Instruction* inst = Instruction::At(code_item->insns_ + dex_pc);
-  uint32_t new_dex_pc = dex_pc + inst->SizeInCodeUnits();
-  ShadowFrame* new_frame = ShadowFrame::Create(num_regs, nullptr, m, new_dex_pc);
-  SirtRef<mirror::DexCache> dex_cache(self_, mh.GetDexCache());
-  SirtRef<mirror::ClassLoader> class_loader(self_, mh.GetClassLoader());
-  verifier::MethodVerifier verifier(&mh.GetDexFile(), &dex_cache, &class_loader,
-                                    &mh.GetClassDef(), code_item, m->GetDexMethodIndex(), m,
-                                    m->GetAccessFlags(), false, true);
-  verifier.Verify();
-  std::vector<int32_t> kinds = verifier.DescribeVRegs(dex_pc);
-  for (uint16_t reg = 0; reg < num_regs; ++reg) {
-    VRegKind kind = static_cast<VRegKind>(kinds.at(reg * 2));
-    switch (kind) {
-      case kUndefined:
-        new_frame->SetVReg(reg, 0xEBADDE09);
-        break;
-      case kConstant:
-        new_frame->SetVReg(reg, kinds.at((reg * 2) + 1));
-        break;
-      case kReferenceVReg:
-        new_frame->SetVRegReference(reg,
-                                    reinterpret_cast<mirror::Object*>(GetVReg(m, reg, kind)));
-        break;
-      default:
-        new_frame->SetVReg(reg, GetVReg(m, reg, kind));
-        break;
-    }
-  }
-  if (prev_shadow_frame_ != nullptr) {
-    prev_shadow_frame_->SetLink(new_frame);
-  } else {
-    catch_finder_->SetTopShadowFrame(new_frame);
-  }
-  prev_shadow_frame_ = new_frame;
-  return true;
-}
-
 }  // namespace art
diff --git a/runtime/catch_block_stack_visitor.h b/runtime/catch_block_stack_visitor.h
index ce67e27..6f0fe11 100644
--- a/runtime/catch_block_stack_visitor.h
+++ b/runtime/catch_block_stack_visitor.h
@@ -17,39 +17,39 @@
 #ifndef ART_RUNTIME_CATCH_BLOCK_STACK_VISITOR_H_
 #define ART_RUNTIME_CATCH_BLOCK_STACK_VISITOR_H_
 
-#include "mirror/throwable.h"
-#include "thread.h"
+#include "mirror/object-inl.h"
+#include "stack.h"
+#include "sirt_ref-inl.h"
 
 namespace art {
-class CatchFinder;
+
+namespace mirror {
+class Throwable;
+}  // namespace mirror
+class Context;
+class QuickExceptionHandler;
+class Thread;
 class ThrowLocation;
 
 // Finds catch handler or prepares deoptimization.
-class CatchBlockStackVisitor : public StackVisitor {
+class CatchBlockStackVisitor FINAL : public StackVisitor {
  public:
-  CatchBlockStackVisitor(Thread* self, Context* context, mirror::Throwable* exception,
-                         bool is_deoptimization, CatchFinder* catch_finder)
+  CatchBlockStackVisitor(Thread* self, Context* context, SirtRef<mirror::Throwable>& exception,
+                         QuickExceptionHandler* exception_handler)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      : StackVisitor(self, context),
-        self_(self), is_deoptimization_(is_deoptimization),
-        to_find_(is_deoptimization ? nullptr : exception->GetClass()),
-        catch_finder_(catch_finder), native_method_count_(0), prev_shadow_frame_(nullptr) {
+      : StackVisitor(self, context), self_(self), to_find_(self, exception->GetClass()),
+        exception_handler_(exception_handler) {
   }
 
-  bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  bool VisitFrame() OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
  private:
   bool HandleTryItems(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  bool HandleDeoptimization(mirror::ArtMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   Thread* const self_;
-  const bool is_deoptimization_;
   // The type of the exception catch block to find.
-  mirror::Class* to_find_;
-  CatchFinder* const catch_finder_;
-  // Number of native methods passed in crawl (equates to number of SIRTs to pop)
-  uint32_t native_method_count_;
-  ShadowFrame* prev_shadow_frame_;
+  SirtRef<mirror::Class> to_find_;
+  QuickExceptionHandler* const exception_handler_;
 
   DISALLOW_COPY_AND_ASSIGN(CatchBlockStackVisitor);
 };
diff --git a/runtime/deoptimize_stack_visitor.cc b/runtime/deoptimize_stack_visitor.cc
new file mode 100644
index 0000000..f2eaf00
--- /dev/null
+++ b/runtime/deoptimize_stack_visitor.cc
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+
+#include "deoptimize_stack_visitor.h"
+
+#include "mirror/art_method-inl.h"
+#include "object_utils.h"
+#include "quick_exception_handler.h"
+#include "sirt_ref-inl.h"
+#include "verifier/method_verifier.h"
+
+namespace art {
+
+bool DeoptimizeStackVisitor::VisitFrame() {
+  exception_handler_->SetHandlerFrameId(GetFrameId());
+  mirror::ArtMethod* method = GetMethod();
+  if (method == nullptr) {
+    // This is the upcall, we remember the frame and last pc so that we may long jump to them.
+    exception_handler_->SetHandlerQuickFramePc(GetCurrentQuickFramePc());
+    exception_handler_->SetHandlerQuickFrame(GetCurrentQuickFrame());
+    return false;  // End stack walk.
+  } else if (method->IsRuntimeMethod()) {
+    // Ignore callee save method.
+    DCHECK(method->IsCalleeSaveMethod());
+    return true;
+  } else {
+    return HandleDeoptimization(method);
+  }
+}
+
+bool DeoptimizeStackVisitor::HandleDeoptimization(mirror::ArtMethod* m) {
+  MethodHelper mh(m);
+  const DexFile::CodeItem* code_item = mh.GetCodeItem();
+  CHECK(code_item != nullptr);
+  uint16_t num_regs = code_item->registers_size_;
+  uint32_t dex_pc = GetDexPc();
+  const Instruction* inst = Instruction::At(code_item->insns_ + dex_pc);
+  uint32_t new_dex_pc = dex_pc + inst->SizeInCodeUnits();
+  ShadowFrame* new_frame = ShadowFrame::Create(num_regs, nullptr, m, new_dex_pc);
+  SirtRef<mirror::DexCache> dex_cache(self_, mh.GetDexCache());
+  SirtRef<mirror::ClassLoader> class_loader(self_, mh.GetClassLoader());
+  verifier::MethodVerifier verifier(&mh.GetDexFile(), &dex_cache, &class_loader,
+                                    &mh.GetClassDef(), code_item, m->GetDexMethodIndex(), m,
+                                    m->GetAccessFlags(), false, true);
+  verifier.Verify();
+  std::vector<int32_t> kinds = verifier.DescribeVRegs(dex_pc);
+  for (uint16_t reg = 0; reg < num_regs; ++reg) {
+    VRegKind kind = static_cast<VRegKind>(kinds.at(reg * 2));
+    switch (kind) {
+      case kUndefined:
+        new_frame->SetVReg(reg, 0xEBADDE09);
+        break;
+      case kConstant:
+        new_frame->SetVReg(reg, kinds.at((reg * 2) + 1));
+        break;
+      case kReferenceVReg:
+        new_frame->SetVRegReference(reg,
+                                    reinterpret_cast<mirror::Object*>(GetVReg(m, reg, kind)));
+        break;
+      default:
+        new_frame->SetVReg(reg, GetVReg(m, reg, kind));
+        break;
+    }
+  }
+  if (prev_shadow_frame_ != nullptr) {
+    prev_shadow_frame_->SetLink(new_frame);
+  } else {
+    exception_handler_->SetTopShadowFrame(new_frame);
+  }
+  prev_shadow_frame_ = new_frame;
+  return true;
+}
+
+}  // namespace art
diff --git a/runtime/deoptimize_stack_visitor.h b/runtime/deoptimize_stack_visitor.h
new file mode 100644
index 0000000..c898e7d
--- /dev/null
+++ b/runtime/deoptimize_stack_visitor.h
@@ -0,0 +1,53 @@
+/*
+ * 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_DEOPTIMIZE_STACK_VISITOR_H_
+#define ART_RUNTIME_DEOPTIMIZE_STACK_VISITOR_H_
+
+#include "base/mutex.h"
+#include "stack.h"
+
+namespace art {
+
+namespace mirror {
+class ArtMethod;
+}  // namespace mirror
+class QuickExceptionHandler;
+class Thread;
+
+// Prepares deoptimization.
+class DeoptimizeStackVisitor FINAL : public StackVisitor {
+ public:
+  DeoptimizeStackVisitor(Thread* self, Context* context, QuickExceptionHandler* exception_handler)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+      : StackVisitor(self, context), self_(self), exception_handler_(exception_handler),
+        prev_shadow_frame_(nullptr) {
+  }
+
+  bool VisitFrame() OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ private:
+  bool HandleDeoptimization(mirror::ArtMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  Thread* const self_;
+  QuickExceptionHandler* const exception_handler_;
+  ShadowFrame* prev_shadow_frame_;
+
+  DISALLOW_COPY_AND_ASSIGN(DeoptimizeStackVisitor);
+};
+
+}  // namespace art
+#endif  // ART_RUNTIME_DEOPTIMIZE_STACK_VISITOR_H_
diff --git a/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc b/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
index 51c647a..6448045 100644
--- a/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
@@ -31,7 +31,7 @@
 extern "C" void artDeoptimize(Thread* self, mirror::ArtMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kSaveAll);
-  self->SetException(ThrowLocation(), reinterpret_cast<mirror::Throwable*>(-1));
+  self->SetException(ThrowLocation(), Thread::GetDeoptimizationException());
   self->QuickDeliverException();
 }
 
diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h
index 65bdf0e..cc1fa0c 100644
--- a/runtime/interpreter/interpreter_common.h
+++ b/runtime/interpreter/interpreter_common.h
@@ -169,6 +169,13 @@
       return false;
     }
   }
+  // Report this field access to instrumentation if needed.
+  instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
+  if (UNLIKELY(instrumentation->HasFieldReadListeners())) {
+    Object* this_object = f->IsStatic() ? nullptr : obj;
+    instrumentation->FieldReadEvent(self, this_object, shadow_frame.GetMethod(),
+                                    shadow_frame.GetDexPC(), f);
+  }
   uint32_t vregA = is_static ? inst->VRegA_21c(inst_data) : inst->VRegA_22c(inst_data);
   switch (field_type) {
     case Primitive::kPrimBoolean:
@@ -210,6 +217,17 @@
     return false;
   }
   MemberOffset field_offset(inst->VRegC_22c());
+  // Report this field access to instrumentation if needed. Since we only have the offset of
+  // the field from the base of the object, we need to look for it first.
+  instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
+  if (UNLIKELY(instrumentation->HasFieldReadListeners())) {
+    ArtField* f = ArtField::FindInstanceFieldWithOffset(obj->GetClass(),
+                                                        field_offset.Uint32Value());
+    DCHECK(f != nullptr);
+    DCHECK(!f->IsStatic());
+    instrumentation->FieldReadEvent(Thread::Current(), obj, shadow_frame.GetMethod(),
+                                    shadow_frame.GetDexPC(), f);
+  }
   const bool is_volatile = false;  // iget-x-quick only on non volatile fields.
   const uint32_t vregA = inst->VRegA_22c(inst_data);
   switch (field_type) {
@@ -228,6 +246,39 @@
   return true;
 }
 
+template<Primitive::Type field_type>
+static inline JValue GetFieldValue(const ShadowFrame& shadow_frame, uint32_t vreg)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  JValue field_value;
+  switch (field_type) {
+    case Primitive::kPrimBoolean:
+      field_value.SetZ(static_cast<uint8_t>(shadow_frame.GetVReg(vreg)));
+      break;
+    case Primitive::kPrimByte:
+      field_value.SetB(static_cast<int8_t>(shadow_frame.GetVReg(vreg)));
+      break;
+    case Primitive::kPrimChar:
+      field_value.SetC(static_cast<uint16_t>(shadow_frame.GetVReg(vreg)));
+      break;
+    case Primitive::kPrimShort:
+      field_value.SetS(static_cast<int16_t>(shadow_frame.GetVReg(vreg)));
+      break;
+    case Primitive::kPrimInt:
+      field_value.SetI(shadow_frame.GetVReg(vreg));
+      break;
+    case Primitive::kPrimLong:
+      field_value.SetJ(shadow_frame.GetVRegLong(vreg));
+      break;
+    case Primitive::kPrimNot:
+      field_value.SetL(shadow_frame.GetVRegReference(vreg));
+      break;
+    default:
+      LOG(FATAL) << "Unreachable: " << field_type;
+      break;
+  }
+  return field_value;
+}
+
 // Handles iput-XXX and sput-XXX instructions.
 // Returns true on success, otherwise throws an exception and returns false.
 template<FindFieldType find_type, Primitive::Type field_type, bool do_access_check, bool transaction_active>
@@ -254,6 +305,15 @@
     }
   }
   uint32_t vregA = is_static ? inst->VRegA_21c(inst_data) : inst->VRegA_22c(inst_data);
+  // Report this field access to instrumentation if needed. Since we only have the offset of
+  // the field from the base of the object, we need to look for it first.
+  instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
+  if (UNLIKELY(instrumentation->HasFieldWriteListeners())) {
+    JValue field_value = GetFieldValue<field_type>(shadow_frame, vregA);
+    Object* this_object = f->IsStatic() ? nullptr : obj;
+    instrumentation->FieldWriteEvent(self, this_object, shadow_frame.GetMethod(),
+                                     shadow_frame.GetDexPC(), f, field_value);
+  }
   switch (field_type) {
     case Primitive::kPrimBoolean:
       f->SetBoolean<transaction_active>(obj, shadow_frame.GetVReg(vregA));
@@ -309,8 +369,20 @@
     return false;
   }
   MemberOffset field_offset(inst->VRegC_22c());
-  const bool is_volatile = false;  // iput-x-quick only on non volatile fields.
   const uint32_t vregA = inst->VRegA_22c(inst_data);
+  // Report this field modification to instrumentation if needed. Since we only have the offset of
+  // the field from the base of the object, we need to look for it first.
+  instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
+  if (UNLIKELY(instrumentation->HasFieldWriteListeners())) {
+    ArtField* f = ArtField::FindInstanceFieldWithOffset(obj->GetClass(),
+                                                        field_offset.Uint32Value());
+    DCHECK(f != nullptr);
+    DCHECK(!f->IsStatic());
+    JValue field_value = GetFieldValue<field_type>(shadow_frame, vregA);
+    instrumentation->FieldWriteEvent(Thread::Current(), obj, shadow_frame.GetMethod(),
+                                     shadow_frame.GetDexPC(), f, field_value);
+  }
+  const bool is_volatile = false;  // iput-x-quick only on non volatile fields.
   switch (field_type) {
     case Primitive::kPrimInt:
       obj->SetField32<transaction_active>(field_offset, shadow_frame.GetVReg(vregA), is_volatile);
diff --git a/runtime/jdwp/jdwp_event.cc b/runtime/jdwp/jdwp_event.cc
index adc1074..223b7a1 100644
--- a/runtime/jdwp/jdwp_event.cc
+++ b/runtime/jdwp/jdwp_event.cc
@@ -108,7 +108,7 @@
  */
 struct ModBasket {
   ModBasket() : pLoc(NULL), threadId(0), classId(0), excepClassId(0),
-                caught(false), field(0), thisPtr(0) { }
+                caught(false), fieldTypeID(0), fieldId(0), thisPtr(0) { }
 
   const JdwpLocation* pLoc;           /* LocationOnly */
   std::string         className;      /* ClassMatch/ClassExclude */
@@ -116,7 +116,8 @@
   RefTypeId           classId;        /* ClassOnly */
   RefTypeId           excepClassId;   /* ExceptionOnly */
   bool                caught;         /* ExceptionOnly */
-  FieldId             field;          /* FieldOnly */
+  RefTypeId           fieldTypeID;    /* FieldOnly */
+  FieldId             fieldId;        /* FieldOnly */
   ObjectId            thisPtr;        /* InstanceOnly */
   /* nothing for StepOnly -- handled differently */
 };
@@ -457,7 +458,10 @@
       }
       break;
     case MK_FIELD_ONLY:
-      if (!Dbg::MatchType(basket->classId, pMod->fieldOnly.refTypeId) || pMod->fieldOnly.fieldId != basket->field) {
+      if (pMod->fieldOnly.fieldId != basket->fieldId) {
+        return false;
+      }
+      if (!Dbg::MatchType(basket->fieldTypeID, pMod->fieldOnly.refTypeId)) {
         return false;
       }
       break;
@@ -848,7 +852,8 @@
   basket.thisPtr = thisPtr;
   basket.threadId = Dbg::GetThreadSelfId();
   basket.className = Dbg::GetClassName(pLoc->class_id);
-  basket.field = fieldId;
+  basket.fieldTypeID = typeId;
+  basket.fieldId = fieldId;
 
   if (InvokeInProgress()) {
     VLOG(jdwp) << "Not posting field event during invoke";
diff --git a/runtime/jdwp/jdwp_handler.cc b/runtime/jdwp/jdwp_handler.cc
index 8ef375b..4843c2b 100644
--- a/runtime/jdwp/jdwp_handler.cc
+++ b/runtime/jdwp/jdwp_handler.cc
@@ -354,8 +354,8 @@
 
 static JdwpError VM_Capabilities(JdwpState*, Request&, ExpandBuf* reply)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  expandBufAdd1(reply, false);   // canWatchFieldModification
-  expandBufAdd1(reply, false);   // canWatchFieldAccess
+  expandBufAdd1(reply, true);    // canWatchFieldModification
+  expandBufAdd1(reply, true);    // canWatchFieldAccess
   expandBufAdd1(reply, true);    // canGetBytecodes
   expandBufAdd1(reply, true);    // canGetSyntheticAttribute
   expandBufAdd1(reply, true);    // canGetOwnedMonitorInfo
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index c04aabf..fd9c40b 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -513,14 +513,16 @@
   SafeMap<std::string, SharedLibrary*> libraries_;
 };
 
-#define CHECK_NON_NULL_ARGUMENT(fn, value) \
+#define CHECK_NON_NULL_ARGUMENT(value) CHECK_NON_NULL_ARGUMENT_FN_NAME(__FUNCTION__, value)
+
+#define CHECK_NON_NULL_ARGUMENT_FN_NAME(name, value) \
   if (UNLIKELY(value == nullptr)) { \
-    JniAbortF(#fn, #value " == null"); \
+    JniAbortF(name, #value " == null"); \
   }
 
-#define CHECK_NON_NULL_MEMCPY_ARGUMENT(fn, length, value) \
+#define CHECK_NON_NULL_MEMCPY_ARGUMENT(length, value) \
   if (UNLIKELY(length != 0 && value == nullptr)) { \
-    JniAbortF(#fn, #value " == null"); \
+    JniAbortF(__FUNCTION__, #value " == null"); \
   }
 
 class JNI {
@@ -535,7 +537,7 @@
   }
 
   static jclass FindClass(JNIEnv* env, const char* name) {
-    CHECK_NON_NULL_ARGUMENT(FindClass, name);
+    CHECK_NON_NULL_ARGUMENT(name);
     Runtime* runtime = Runtime::Current();
     ClassLinker* class_linker = runtime->GetClassLinker();
     std::string descriptor(NormalizeJniClassDescriptor(name));
@@ -551,19 +553,19 @@
   }
 
   static jmethodID FromReflectedMethod(JNIEnv* env, jobject jlr_method) {
-    CHECK_NON_NULL_ARGUMENT(FromReflectedMethod, jlr_method);
+    CHECK_NON_NULL_ARGUMENT(jlr_method);
     ScopedObjectAccess soa(env);
     return soa.EncodeMethod(mirror::ArtMethod::FromReflectedMethod(soa, jlr_method));
   }
 
   static jfieldID FromReflectedField(JNIEnv* env, jobject jlr_field) {
-    CHECK_NON_NULL_ARGUMENT(FromReflectedField, jlr_field);
+    CHECK_NON_NULL_ARGUMENT(jlr_field);
     ScopedObjectAccess soa(env);
     return soa.EncodeField(mirror::ArtField::FromReflectedField(soa, jlr_field));
   }
 
   static jobject ToReflectedMethod(JNIEnv* env, jclass, jmethodID mid, jboolean) {
-    CHECK_NON_NULL_ARGUMENT(ToReflectedMethod, mid);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     mirror::ArtMethod* m = soa.DecodeMethod(mid);
     CHECK(!kMovingMethods);
@@ -578,7 +580,7 @@
   }
 
   static jobject ToReflectedField(JNIEnv* env, jclass, jfieldID fid, jboolean) {
-    CHECK_NON_NULL_ARGUMENT(ToReflectedField, fid);
+    CHECK_NON_NULL_ARGUMENT(fid);
     ScopedObjectAccess soa(env);
     mirror::ArtField* f = soa.DecodeField(fid);
     jobject art_field = soa.AddLocalReference<jobject>(f);
@@ -592,22 +594,22 @@
   }
 
   static jclass GetObjectClass(JNIEnv* env, jobject java_object) {
-    CHECK_NON_NULL_ARGUMENT(GetObjectClass, java_object);
+    CHECK_NON_NULL_ARGUMENT(java_object);
     ScopedObjectAccess soa(env);
     mirror::Object* o = soa.Decode<mirror::Object*>(java_object);
     return soa.AddLocalReference<jclass>(o->GetClass());
   }
 
   static jclass GetSuperclass(JNIEnv* env, jclass java_class) {
-    CHECK_NON_NULL_ARGUMENT(GetSuperclass, java_class);
+    CHECK_NON_NULL_ARGUMENT(java_class);
     ScopedObjectAccess soa(env);
     mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
     return soa.AddLocalReference<jclass>(c->GetSuperClass());
   }
 
   static jboolean IsAssignableFrom(JNIEnv* env, jclass java_class1, jclass java_class2) {
-    CHECK_NON_NULL_ARGUMENT(IsAssignableFrom, java_class1);
-    CHECK_NON_NULL_ARGUMENT(IsAssignableFrom, java_class2);
+    CHECK_NON_NULL_ARGUMENT(java_class1);
+    CHECK_NON_NULL_ARGUMENT(java_class2);
     ScopedObjectAccess soa(env);
     mirror::Class* c1 = soa.Decode<mirror::Class*>(java_class1);
     mirror::Class* c2 = soa.Decode<mirror::Class*>(java_class2);
@@ -615,7 +617,7 @@
   }
 
   static jboolean IsInstanceOf(JNIEnv* env, jobject jobj, jclass java_class) {
-    CHECK_NON_NULL_ARGUMENT(IsInstanceOf, java_class);
+    CHECK_NON_NULL_ARGUMENT(java_class);
     if (jobj == nullptr) {
       // Note: JNI is different from regular Java instanceof in this respect
       return JNI_TRUE;
@@ -639,7 +641,7 @@
   }
 
   static jint ThrowNew(JNIEnv* env, jclass c, const char* msg) {
-    CHECK_NON_NULL_ARGUMENT(ThrowNew, c);
+    CHECK_NON_NULL_ARGUMENT(c);
     return ThrowNewException(env, c, msg, nullptr);
   }
 
@@ -797,7 +799,7 @@
   }
 
   static jobject AllocObject(JNIEnv* env, jclass java_class) {
-    CHECK_NON_NULL_ARGUMENT(AllocObject, java_class);
+    CHECK_NON_NULL_ARGUMENT(java_class);
     ScopedObjectAccess soa(env);
     mirror::Class* c = EnsureInitialized(soa.Self(), soa.Decode<mirror::Class*>(java_class));
     if (c == nullptr) {
@@ -809,16 +811,16 @@
   static jobject NewObject(JNIEnv* env, jclass java_class, jmethodID mid, ...) {
     va_list args;
     va_start(args, mid);
-    CHECK_NON_NULL_ARGUMENT(NewObject, java_class);
-    CHECK_NON_NULL_ARGUMENT(NewObject, mid);
+    CHECK_NON_NULL_ARGUMENT(java_class);
+    CHECK_NON_NULL_ARGUMENT(mid);
     jobject result = NewObjectV(env, java_class, mid, args);
     va_end(args);
     return result;
   }
 
   static jobject NewObjectV(JNIEnv* env, jclass java_class, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(NewObjectV, java_class);
-    CHECK_NON_NULL_ARGUMENT(NewObjectV, mid);
+    CHECK_NON_NULL_ARGUMENT(java_class);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     mirror::Class* c = EnsureInitialized(soa.Self(), soa.Decode<mirror::Class*>(java_class));
     if (c == nullptr) {
@@ -837,8 +839,8 @@
   }
 
   static jobject NewObjectA(JNIEnv* env, jclass java_class, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(NewObjectA, java_class);
-    CHECK_NON_NULL_ARGUMENT(NewObjectA, mid);
+    CHECK_NON_NULL_ARGUMENT(java_class);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     mirror::Class* c = EnsureInitialized(soa.Self(), soa.Decode<mirror::Class*>(java_class));
     if (c == nullptr) {
@@ -857,18 +859,18 @@
   }
 
   static jmethodID GetMethodID(JNIEnv* env, jclass java_class, const char* name, const char* sig) {
-    CHECK_NON_NULL_ARGUMENT(GetMethodID, java_class);
-    CHECK_NON_NULL_ARGUMENT(GetMethodID, name);
-    CHECK_NON_NULL_ARGUMENT(GetMethodID, sig);
+    CHECK_NON_NULL_ARGUMENT(java_class);
+    CHECK_NON_NULL_ARGUMENT(name);
+    CHECK_NON_NULL_ARGUMENT(sig);
     ScopedObjectAccess soa(env);
     return FindMethodID(soa, java_class, name, sig, false);
   }
 
   static jmethodID GetStaticMethodID(JNIEnv* env, jclass java_class, const char* name,
                                      const char* sig) {
-    CHECK_NON_NULL_ARGUMENT(GetStaticMethodID, java_class);
-    CHECK_NON_NULL_ARGUMENT(GetStaticMethodID, name);
-    CHECK_NON_NULL_ARGUMENT(GetStaticMethodID, sig);
+    CHECK_NON_NULL_ARGUMENT(java_class);
+    CHECK_NON_NULL_ARGUMENT(name);
+    CHECK_NON_NULL_ARGUMENT(sig);
     ScopedObjectAccess soa(env);
     return FindMethodID(soa, java_class, name, sig, true);
   }
@@ -876,8 +878,8 @@
   static jobject CallObjectMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(CallObjectMethod, obj);
-    CHECK_NON_NULL_ARGUMENT(CallObjectMethod, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -885,16 +887,16 @@
   }
 
   static jobject CallObjectMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(CallObjectMethodV, obj);
-    CHECK_NON_NULL_ARGUMENT(CallObjectMethodV, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args));
     return soa.AddLocalReference<jobject>(result.GetL());
   }
 
   static jobject CallObjectMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(CallObjectMethodA, obj);
-    CHECK_NON_NULL_ARGUMENT(CallObjectMethodA, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid,
                                                       args));
@@ -904,8 +906,8 @@
   static jboolean CallBooleanMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(CallBooleanMethod, obj);
-    CHECK_NON_NULL_ARGUMENT(CallBooleanMethod, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -913,15 +915,15 @@
   }
 
   static jboolean CallBooleanMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(CallBooleanMethodV, obj);
-    CHECK_NON_NULL_ARGUMENT(CallBooleanMethodV, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetZ();
   }
 
   static jboolean CallBooleanMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(CallBooleanMethodA, obj);
-    CHECK_NON_NULL_ARGUMENT(CallBooleanMethodA, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid,
                                                args).GetZ();
@@ -930,8 +932,8 @@
   static jbyte CallByteMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(CallByteMethod, obj);
-    CHECK_NON_NULL_ARGUMENT(CallByteMethod, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -939,15 +941,15 @@
   }
 
   static jbyte CallByteMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(CallByteMethodV, obj);
-    CHECK_NON_NULL_ARGUMENT(CallByteMethodV, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetB();
   }
 
   static jbyte CallByteMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(CallByteMethodA, obj);
-    CHECK_NON_NULL_ARGUMENT(CallByteMethodA, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid,
                                                args).GetB();
@@ -956,8 +958,8 @@
   static jchar CallCharMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(CallCharMethod, obj);
-    CHECK_NON_NULL_ARGUMENT(CallCharMethod, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -965,15 +967,15 @@
   }
 
   static jchar CallCharMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(CallCharMethodV, obj);
-    CHECK_NON_NULL_ARGUMENT(CallCharMethodV, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetC();
   }
 
   static jchar CallCharMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(CallCharMethodA, obj);
-    CHECK_NON_NULL_ARGUMENT(CallCharMethodA, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid,
                                                args).GetC();
@@ -982,8 +984,8 @@
   static jdouble CallDoubleMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(CallDoubleMethod, obj);
-    CHECK_NON_NULL_ARGUMENT(CallDoubleMethod, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -991,15 +993,15 @@
   }
 
   static jdouble CallDoubleMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(CallDoubleMethodV, obj);
-    CHECK_NON_NULL_ARGUMENT(CallDoubleMethodV, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetD();
   }
 
   static jdouble CallDoubleMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(CallDoubleMethodA, obj);
-    CHECK_NON_NULL_ARGUMENT(CallDoubleMethodA, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid,
                                                args).GetD();
@@ -1008,8 +1010,8 @@
   static jfloat CallFloatMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(CallFloatMethod, obj);
-    CHECK_NON_NULL_ARGUMENT(CallFloatMethod, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -1017,15 +1019,15 @@
   }
 
   static jfloat CallFloatMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(CallFloatMethodV, obj);
-    CHECK_NON_NULL_ARGUMENT(CallFloatMethodV, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetF();
   }
 
   static jfloat CallFloatMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(CallFloatMethodA, obj);
-    CHECK_NON_NULL_ARGUMENT(CallFloatMethodA, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid,
                                                args).GetF();
@@ -1034,8 +1036,8 @@
   static jint CallIntMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(CallIntMethod, obj);
-    CHECK_NON_NULL_ARGUMENT(CallIntMethod, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -1043,15 +1045,15 @@
   }
 
   static jint CallIntMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(CallIntMethodV, obj);
-    CHECK_NON_NULL_ARGUMENT(CallIntMethodV, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetI();
   }
 
   static jint CallIntMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(CallIntMethodA, obj);
-    CHECK_NON_NULL_ARGUMENT(CallIntMethodA, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid,
                                                args).GetI();
@@ -1060,8 +1062,8 @@
   static jlong CallLongMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(CallLongMethod, obj);
-    CHECK_NON_NULL_ARGUMENT(CallLongMethod, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -1069,15 +1071,15 @@
   }
 
   static jlong CallLongMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(CallLongMethodV, obj);
-    CHECK_NON_NULL_ARGUMENT(CallLongMethodV, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetJ();
   }
 
   static jlong CallLongMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(CallLongMethodA, obj);
-    CHECK_NON_NULL_ARGUMENT(CallLongMethodA, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid,
                                                args).GetJ();
@@ -1086,8 +1088,8 @@
   static jshort CallShortMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(CallShortMethod, obj);
-    CHECK_NON_NULL_ARGUMENT(CallShortMethod, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -1095,15 +1097,15 @@
   }
 
   static jshort CallShortMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(CallShortMethodV, obj);
-    CHECK_NON_NULL_ARGUMENT(CallShortMethodV, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetS();
   }
 
   static jshort CallShortMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(CallShortMethodA, obj);
-    CHECK_NON_NULL_ARGUMENT(CallShortMethodA, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid,
                                                args).GetS();
@@ -1112,23 +1114,23 @@
   static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(CallVoidMethod, obj);
-    CHECK_NON_NULL_ARGUMENT(CallVoidMethod, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap);
     va_end(ap);
   }
 
   static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(CallVoidMethodV, obj);
-    CHECK_NON_NULL_ARGUMENT(CallVoidMethodV, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args);
   }
 
   static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(CallVoidMethodA, obj);
-    CHECK_NON_NULL_ARGUMENT(CallVoidMethodA, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args);
   }
@@ -1136,8 +1138,8 @@
   static jobject CallNonvirtualObjectMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualObjectMethod, obj);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualObjectMethod, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
     jobject local_result = soa.AddLocalReference<jobject>(result.GetL());
@@ -1147,8 +1149,8 @@
 
   static jobject CallNonvirtualObjectMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                              va_list args) {
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualObjectMethodV, obj);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualObjectMethodV, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, obj, mid, args));
     return soa.AddLocalReference<jobject>(result.GetL());
@@ -1156,8 +1158,8 @@
 
   static jobject CallNonvirtualObjectMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                              jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualObjectMethodA, obj);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualObjectMethodA, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args));
     return soa.AddLocalReference<jobject>(result.GetL());
@@ -1167,8 +1169,8 @@
                                               ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualBooleanMethod, obj);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualBooleanMethod, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -1177,16 +1179,16 @@
 
   static jboolean CallNonvirtualBooleanMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                                va_list args) {
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualBooleanMethodV, obj);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualBooleanMethodV, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, obj, mid, args).GetZ();
   }
 
   static jboolean CallNonvirtualBooleanMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                                jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualBooleanMethodA, obj);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualBooleanMethodA, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetZ();
   }
@@ -1194,8 +1196,8 @@
   static jbyte CallNonvirtualByteMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualByteMethod, obj);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualByteMethod, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -1204,16 +1206,16 @@
 
   static jbyte CallNonvirtualByteMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                          va_list args) {
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualByteMethodV, obj);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualByteMethodV, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, obj, mid, args).GetB();
   }
 
   static jbyte CallNonvirtualByteMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                          jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualByteMethodA, obj);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualByteMethodA, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetB();
   }
@@ -1221,8 +1223,8 @@
   static jchar CallNonvirtualCharMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualCharMethod, obj);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualCharMethod, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -1231,16 +1233,16 @@
 
   static jchar CallNonvirtualCharMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                          va_list args) {
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualCharMethodV, obj);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualCharMethodV, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, obj, mid, args).GetC();
   }
 
   static jchar CallNonvirtualCharMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                          jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualCharMethodA, obj);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualCharMethodA, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetC();
   }
@@ -1248,8 +1250,8 @@
   static jshort CallNonvirtualShortMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualShortMethod, obj);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualShortMethod, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -1258,16 +1260,16 @@
 
   static jshort CallNonvirtualShortMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                            va_list args) {
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualShortMethodV, obj);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualShortMethodV, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, obj, mid, args).GetS();
   }
 
   static jshort CallNonvirtualShortMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                            jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualShortMethodA, obj);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualShortMethodA, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetS();
   }
@@ -1275,8 +1277,8 @@
   static jint CallNonvirtualIntMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualIntMethod, obj);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualIntMethod, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -1285,16 +1287,16 @@
 
   static jint CallNonvirtualIntMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                        va_list args) {
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualIntMethodV, obj);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualIntMethodV, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, obj, mid, args).GetI();
   }
 
   static jint CallNonvirtualIntMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                        jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualIntMethodA, obj);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualIntMethodA, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetI();
   }
@@ -1302,8 +1304,8 @@
   static jlong CallNonvirtualLongMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualLongMethod, obj);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualLongMethod, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -1312,16 +1314,16 @@
 
   static jlong CallNonvirtualLongMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                          va_list args) {
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualLongMethodV, obj);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualLongMethodV, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, obj, mid, args).GetJ();
   }
 
   static jlong CallNonvirtualLongMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                          jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualLongMethodA, obj);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualLongMethodA, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetJ();
   }
@@ -1329,8 +1331,8 @@
   static jfloat CallNonvirtualFloatMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualFloatMethod, obj);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualFloatMethod, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -1339,16 +1341,16 @@
 
   static jfloat CallNonvirtualFloatMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                            va_list args) {
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualFloatMethodV, obj);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualFloatMethodV, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, obj, mid, args).GetF();
   }
 
   static jfloat CallNonvirtualFloatMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                            jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualFloatMethodA, obj);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualFloatMethodA, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetF();
   }
@@ -1356,8 +1358,8 @@
   static jdouble CallNonvirtualDoubleMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualDoubleMethod, obj);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualDoubleMethod, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -1366,16 +1368,16 @@
 
   static jdouble CallNonvirtualDoubleMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                              va_list args) {
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualDoubleMethodV, obj);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualDoubleMethodV, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, obj, mid, args).GetD();
   }
 
   static jdouble CallNonvirtualDoubleMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                              jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualDoubleMethodA, obj);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualDoubleMethodA, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetD();
   }
@@ -1383,8 +1385,8 @@
   static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualVoidMethod, obj);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualVoidMethod, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     InvokeWithVarArgs(soa, obj, mid, ap);
     va_end(ap);
@@ -1392,40 +1394,40 @@
 
   static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                         va_list args) {
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualVoidMethodV, obj);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualVoidMethodV, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     InvokeWithVarArgs(soa, obj, mid, args);
   }
 
   static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                         jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualVoidMethodA, obj);
-    CHECK_NON_NULL_ARGUMENT(CallNonvirtualVoidMethodA, mid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args);
   }
 
   static jfieldID GetFieldID(JNIEnv* env, jclass java_class, const char* name, const char* sig) {
-    CHECK_NON_NULL_ARGUMENT(GetFieldID, java_class);
-    CHECK_NON_NULL_ARGUMENT(GetFieldID, name);
-    CHECK_NON_NULL_ARGUMENT(GetFieldID, sig);
+    CHECK_NON_NULL_ARGUMENT(java_class);
+    CHECK_NON_NULL_ARGUMENT(name);
+    CHECK_NON_NULL_ARGUMENT(sig);
     ScopedObjectAccess soa(env);
     return FindFieldID(soa, java_class, name, sig, false);
   }
 
   static jfieldID GetStaticFieldID(JNIEnv* env, jclass java_class, const char* name,
                                    const char* sig) {
-    CHECK_NON_NULL_ARGUMENT(GetStaticFieldID, java_class);
-    CHECK_NON_NULL_ARGUMENT(GetStaticFieldID, name);
-    CHECK_NON_NULL_ARGUMENT(GetFieldID, sig);
+    CHECK_NON_NULL_ARGUMENT(java_class);
+    CHECK_NON_NULL_ARGUMENT(name);
+    CHECK_NON_NULL_ARGUMENT(sig);
     ScopedObjectAccess soa(env);
     return FindFieldID(soa, java_class, name, sig, true);
   }
 
   static jobject GetObjectField(JNIEnv* env, jobject obj, jfieldID fid) {
-    CHECK_NON_NULL_ARGUMENT(GetObjectField, obj);
-    CHECK_NON_NULL_ARGUMENT(GetObjectField, fid);
+    CHECK_NON_NULL_ARGUMENT(obj);
+    CHECK_NON_NULL_ARGUMENT(fid);
     ScopedObjectAccess soa(env);
     mirror::Object* o = soa.Decode<mirror::Object*>(obj);
     mirror::ArtField* f = soa.DecodeField(fid);
@@ -1433,15 +1435,15 @@
   }
 
   static jobject GetStaticObjectField(JNIEnv* env, jclass, jfieldID fid) {
-    CHECK_NON_NULL_ARGUMENT(GetStaticObjectField, fid);
+    CHECK_NON_NULL_ARGUMENT(fid);
     ScopedObjectAccess soa(env);
     mirror::ArtField* f = soa.DecodeField(fid);
     return soa.AddLocalReference<jobject>(f->GetObject(f->GetDeclaringClass()));
   }
 
   static void SetObjectField(JNIEnv* env, jobject java_object, jfieldID fid, jobject java_value) {
-    CHECK_NON_NULL_ARGUMENT(SetObjectField, java_object);
-    CHECK_NON_NULL_ARGUMENT(SetObjectField, fid);
+    CHECK_NON_NULL_ARGUMENT(java_object);
+    CHECK_NON_NULL_ARGUMENT(fid);
     ScopedObjectAccess soa(env);
     mirror::Object* o = soa.Decode<mirror::Object*>(java_object);
     mirror::Object* v = soa.Decode<mirror::Object*>(java_value);
@@ -1450,7 +1452,7 @@
   }
 
   static void SetStaticObjectField(JNIEnv* env, jclass, jfieldID fid, jobject java_value) {
-    CHECK_NON_NULL_ARGUMENT(SetStaticObjectField, fid);
+    CHECK_NON_NULL_ARGUMENT(fid);
     ScopedObjectAccess soa(env);
     mirror::Object* v = soa.Decode<mirror::Object*>(java_value);
     mirror::ArtField* f = soa.DecodeField(fid);
@@ -1458,29 +1460,29 @@
   }
 
 #define GET_PRIMITIVE_FIELD(fn, instance) \
-  CHECK_NON_NULL_ARGUMENT(Get #fn Field, instance); \
-  CHECK_NON_NULL_ARGUMENT(Get #fn Field, fid); \
+  CHECK_NON_NULL_ARGUMENT(instance); \
+  CHECK_NON_NULL_ARGUMENT(fid); \
   ScopedObjectAccess soa(env); \
   mirror::Object* o = soa.Decode<mirror::Object*>(instance); \
   mirror::ArtField* f = soa.DecodeField(fid); \
   return f->Get ##fn (o)
 
 #define GET_STATIC_PRIMITIVE_FIELD(fn) \
-  CHECK_NON_NULL_ARGUMENT(GetStatic #fn Field, fid); \
+  CHECK_NON_NULL_ARGUMENT(fid); \
   ScopedObjectAccess soa(env); \
   mirror::ArtField* f = soa.DecodeField(fid); \
   return f->Get ##fn (f->GetDeclaringClass())
 
 #define SET_PRIMITIVE_FIELD(fn, instance, value) \
-  CHECK_NON_NULL_ARGUMENT(Set #fn Field, instance); \
-  CHECK_NON_NULL_ARGUMENT(Set #fn Field, fid); \
+  CHECK_NON_NULL_ARGUMENT(instance); \
+  CHECK_NON_NULL_ARGUMENT(fid); \
   ScopedObjectAccess soa(env); \
   mirror::Object* o = soa.Decode<mirror::Object*>(instance); \
   mirror::ArtField* f = soa.DecodeField(fid); \
   f->Set ##fn <false>(o, value)
 
 #define SET_STATIC_PRIMITIVE_FIELD(fn, value) \
-  CHECK_NON_NULL_ARGUMENT(SetStatic #fn Field, fid); \
+  CHECK_NON_NULL_ARGUMENT(fid); \
   ScopedObjectAccess soa(env); \
   mirror::ArtField* f = soa.DecodeField(fid); \
   f->Set ##fn <false>(f->GetDeclaringClass(), value)
@@ -1616,7 +1618,7 @@
   static jobject CallStaticObjectMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(CallStaticObjectMethod, mid);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, nullptr, mid, ap));
     jobject local_result = soa.AddLocalReference<jobject>(result.GetL());
@@ -1625,14 +1627,14 @@
   }
 
   static jobject CallStaticObjectMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(CallStaticObjectMethodV, mid);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, nullptr, mid, args));
     return soa.AddLocalReference<jobject>(result.GetL());
   }
 
   static jobject CallStaticObjectMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(CallStaticObjectMethodA, mid);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithJValues(soa, nullptr, mid, args));
     return soa.AddLocalReference<jobject>(result.GetL());
@@ -1641,7 +1643,7 @@
   static jboolean CallStaticBooleanMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(CallStaticBooleanMethod, mid);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, nullptr, mid, ap));
     va_end(ap);
@@ -1649,13 +1651,13 @@
   }
 
   static jboolean CallStaticBooleanMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(CallStaticBooleanMethodV, mid);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, nullptr, mid, args).GetZ();
   }
 
   static jboolean CallStaticBooleanMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(CallStaticBooleanMethodA, mid);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, nullptr, mid, args).GetZ();
   }
@@ -1663,7 +1665,7 @@
   static jbyte CallStaticByteMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(CallStaticByteMethod, mid);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, nullptr, mid, ap));
     va_end(ap);
@@ -1671,13 +1673,13 @@
   }
 
   static jbyte CallStaticByteMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(CallStaticByteMethodV, mid);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, nullptr, mid, args).GetB();
   }
 
   static jbyte CallStaticByteMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(CallStaticByteMethodA, mid);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, nullptr, mid, args).GetB();
   }
@@ -1685,7 +1687,7 @@
   static jchar CallStaticCharMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(CallStaticCharMethod, mid);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, nullptr, mid, ap));
     va_end(ap);
@@ -1693,13 +1695,13 @@
   }
 
   static jchar CallStaticCharMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(CallStaticCharMethodV, mid);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, nullptr, mid, args).GetC();
   }
 
   static jchar CallStaticCharMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(CallStaticCharMethodA, mid);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, nullptr, mid, args).GetC();
   }
@@ -1707,7 +1709,7 @@
   static jshort CallStaticShortMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(CallStaticShortMethod, mid);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, nullptr, mid, ap));
     va_end(ap);
@@ -1715,13 +1717,13 @@
   }
 
   static jshort CallStaticShortMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(CallStaticShortMethodV, mid);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, nullptr, mid, args).GetS();
   }
 
   static jshort CallStaticShortMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(CallStaticShortMethodA, mid);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, nullptr, mid, args).GetS();
   }
@@ -1729,7 +1731,7 @@
   static jint CallStaticIntMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(CallStaticIntMethod, mid);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, nullptr, mid, ap));
     va_end(ap);
@@ -1737,13 +1739,13 @@
   }
 
   static jint CallStaticIntMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(CallStaticIntMethodV, mid);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, nullptr, mid, args).GetI();
   }
 
   static jint CallStaticIntMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(CallStaticIntMethodA, mid);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, nullptr, mid, args).GetI();
   }
@@ -1751,7 +1753,7 @@
   static jlong CallStaticLongMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(CallStaticLongMethod, mid);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, nullptr, mid, ap));
     va_end(ap);
@@ -1759,13 +1761,13 @@
   }
 
   static jlong CallStaticLongMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(CallStaticLongMethodV, mid);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, nullptr, mid, args).GetJ();
   }
 
   static jlong CallStaticLongMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(CallStaticLongMethodA, mid);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, nullptr, mid, args).GetJ();
   }
@@ -1773,7 +1775,7 @@
   static jfloat CallStaticFloatMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(CallStaticFloatMethod, mid);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, nullptr, mid, ap));
     va_end(ap);
@@ -1781,13 +1783,13 @@
   }
 
   static jfloat CallStaticFloatMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(CallStaticFloatMethodV, mid);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, nullptr, mid, args).GetF();
   }
 
   static jfloat CallStaticFloatMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(CallStaticFloatMethodA, mid);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, nullptr, mid, args).GetF();
   }
@@ -1795,7 +1797,7 @@
   static jdouble CallStaticDoubleMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(CallStaticDoubleMethod, mid);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, nullptr, mid, ap));
     va_end(ap);
@@ -1803,13 +1805,13 @@
   }
 
   static jdouble CallStaticDoubleMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(CallStaticDoubleMethodV, mid);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, nullptr, mid, args).GetD();
   }
 
   static jdouble CallStaticDoubleMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(CallStaticDoubleMethodA, mid);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, nullptr, mid, args).GetD();
   }
@@ -1817,20 +1819,20 @@
   static void CallStaticVoidMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
-    CHECK_NON_NULL_ARGUMENT(CallStaticVoidMethod, mid);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     InvokeWithVarArgs(soa, nullptr, mid, ap);
     va_end(ap);
   }
 
   static void CallStaticVoidMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
-    CHECK_NON_NULL_ARGUMENT(CallStaticVoidMethodV, mid);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     InvokeWithVarArgs(soa, nullptr, mid, args);
   }
 
   static void CallStaticVoidMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
-    CHECK_NON_NULL_ARGUMENT(CallStaticVoidMethodA, mid);
+    CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
     InvokeWithJValues(soa, nullptr, mid, args);
   }
@@ -1859,26 +1861,26 @@
   }
 
   static jsize GetStringLength(JNIEnv* env, jstring java_string) {
-    CHECK_NON_NULL_ARGUMENT(GetStringLength, java_string);
+    CHECK_NON_NULL_ARGUMENT(java_string);
     ScopedObjectAccess soa(env);
     return soa.Decode<mirror::String*>(java_string)->GetLength();
   }
 
   static jsize GetStringUTFLength(JNIEnv* env, jstring java_string) {
-    CHECK_NON_NULL_ARGUMENT(GetStringLength, java_string);
+    CHECK_NON_NULL_ARGUMENT(java_string);
     ScopedObjectAccess soa(env);
     return soa.Decode<mirror::String*>(java_string)->GetUtfLength();
   }
 
   static void GetStringRegion(JNIEnv* env, jstring java_string, jsize start, jsize length,
                               jchar* buf) {
-    CHECK_NON_NULL_ARGUMENT(GetStringRegion, java_string);
+    CHECK_NON_NULL_ARGUMENT(java_string);
     ScopedObjectAccess soa(env);
     mirror::String* s = soa.Decode<mirror::String*>(java_string);
     if (start < 0 || length < 0 || start + length > s->GetLength()) {
       ThrowSIOOBE(soa, start, length, s->GetLength());
     } else {
-      CHECK_NON_NULL_MEMCPY_ARGUMENT(GetStringRegion, length, buf);
+      CHECK_NON_NULL_MEMCPY_ARGUMENT(length, buf);
       const jchar* chars = s->GetCharArray()->GetData() + s->GetOffset();
       memcpy(buf, chars + start, length * sizeof(jchar));
     }
@@ -1886,20 +1888,20 @@
 
   static void GetStringUTFRegion(JNIEnv* env, jstring java_string, jsize start, jsize length,
                                  char* buf) {
-    CHECK_NON_NULL_ARGUMENT(GetStringUTFRegion, java_string);
+    CHECK_NON_NULL_ARGUMENT(java_string);
     ScopedObjectAccess soa(env);
     mirror::String* s = soa.Decode<mirror::String*>(java_string);
     if (start < 0 || length < 0 || start + length > s->GetLength()) {
       ThrowSIOOBE(soa, start, length, s->GetLength());
     } else {
-      CHECK_NON_NULL_MEMCPY_ARGUMENT(GetStringUTFRegion, length, buf);
+      CHECK_NON_NULL_MEMCPY_ARGUMENT(length, buf);
       const jchar* chars = s->GetCharArray()->GetData() + s->GetOffset();
       ConvertUtf16ToModifiedUtf8(buf, chars + start, length);
     }
   }
 
   static const jchar* GetStringChars(JNIEnv* env, jstring java_string, jboolean* is_copy) {
-    CHECK_NON_NULL_ARGUMENT(GetStringChars, java_string);
+    CHECK_NON_NULL_ARGUMENT(java_string);
     ScopedObjectAccess soa(env);
     mirror::String* s = soa.Decode<mirror::String*>(java_string);
     mirror::CharArray* chars = s->GetCharArray();
@@ -1918,7 +1920,7 @@
   }
 
   static void ReleaseStringChars(JNIEnv* env, jstring java_string, const jchar* chars) {
-    CHECK_NON_NULL_ARGUMENT(ReleaseStringChars, java_string);
+    CHECK_NON_NULL_ARGUMENT(java_string);
     delete[] chars;
     ScopedObjectAccess soa(env);
     UnpinPrimitiveArray(soa, soa.Decode<mirror::String*>(java_string)->GetCharArray());
@@ -1955,7 +1957,7 @@
   }
 
   static jsize GetArrayLength(JNIEnv* env, jarray java_array) {
-    CHECK_NON_NULL_ARGUMENT(GetArrayLength, java_array);
+    CHECK_NON_NULL_ARGUMENT(java_array);
     ScopedObjectAccess soa(env);
     mirror::Object* obj = soa.Decode<mirror::Object*>(java_array);
     if (UNLIKELY(!obj->IsArrayInstance())) {
@@ -1966,7 +1968,7 @@
   }
 
   static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray java_array, jsize index) {
-    CHECK_NON_NULL_ARGUMENT(GetObjectArrayElement, java_array);
+    CHECK_NON_NULL_ARGUMENT(java_array);
     ScopedObjectAccess soa(env);
     mirror::ObjectArray<mirror::Object>* array =
         soa.Decode<mirror::ObjectArray<mirror::Object>*>(java_array);
@@ -1975,7 +1977,7 @@
 
   static void SetObjectArrayElement(JNIEnv* env, jobjectArray java_array, jsize index,
                                     jobject java_value) {
-    CHECK_NON_NULL_ARGUMENT(SetObjectArrayElement, java_array);
+    CHECK_NON_NULL_ARGUMENT(java_array);
     ScopedObjectAccess soa(env);
     mirror::ObjectArray<mirror::Object>* array =
         soa.Decode<mirror::ObjectArray<mirror::Object>*>(java_array);
@@ -2070,7 +2072,7 @@
   }
 
   static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray java_array, jboolean* is_copy) {
-    CHECK_NON_NULL_ARGUMENT(GetPrimitiveArrayCritical, java_array);
+    CHECK_NON_NULL_ARGUMENT(java_array);
     ScopedObjectAccess soa(env);
     mirror::Array* array = soa.Decode<mirror::Array*>(java_array);
     gc::Heap* heap = Runtime::Current()->GetHeap();
@@ -2087,54 +2089,54 @@
   }
 
   static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* elements, jint mode) {
-    CHECK_NON_NULL_ARGUMENT(ReleasePrimitiveArrayCritical, array);
+    CHECK_NON_NULL_ARGUMENT(array);
     ReleasePrimitiveArray(env, array, elements, mode);
   }
 
   static jboolean* GetBooleanArrayElements(JNIEnv* env, jbooleanArray array, jboolean* is_copy) {
-    CHECK_NON_NULL_ARGUMENT(GetBooleanArrayElements, array);
+    CHECK_NON_NULL_ARGUMENT(array);
     ScopedObjectAccess soa(env);
     return GetPrimitiveArray<jbooleanArray, jboolean*, mirror::BooleanArray>(soa, array, is_copy);
   }
 
   static jbyte* GetByteArrayElements(JNIEnv* env, jbyteArray array, jboolean* is_copy) {
-    CHECK_NON_NULL_ARGUMENT(GetByteArrayElements, array);
+    CHECK_NON_NULL_ARGUMENT(array);
     ScopedObjectAccess soa(env);
     return GetPrimitiveArray<jbyteArray, jbyte*, mirror::ByteArray>(soa, array, is_copy);
   }
 
   static jchar* GetCharArrayElements(JNIEnv* env, jcharArray array, jboolean* is_copy) {
-    CHECK_NON_NULL_ARGUMENT(GetCharArrayElements, array);
+    CHECK_NON_NULL_ARGUMENT(array);
     ScopedObjectAccess soa(env);
     return GetPrimitiveArray<jcharArray, jchar*, mirror::CharArray>(soa, array, is_copy);
   }
 
   static jdouble* GetDoubleArrayElements(JNIEnv* env, jdoubleArray array, jboolean* is_copy) {
-    CHECK_NON_NULL_ARGUMENT(GetDoubleArrayElements, array);
+    CHECK_NON_NULL_ARGUMENT(array);
     ScopedObjectAccess soa(env);
     return GetPrimitiveArray<jdoubleArray, jdouble*, mirror::DoubleArray>(soa, array, is_copy);
   }
 
   static jfloat* GetFloatArrayElements(JNIEnv* env, jfloatArray array, jboolean* is_copy) {
-    CHECK_NON_NULL_ARGUMENT(GetFloatArrayElements, array);
+    CHECK_NON_NULL_ARGUMENT(array);
     ScopedObjectAccess soa(env);
     return GetPrimitiveArray<jfloatArray, jfloat*, mirror::FloatArray>(soa, array, is_copy);
   }
 
   static jint* GetIntArrayElements(JNIEnv* env, jintArray array, jboolean* is_copy) {
-    CHECK_NON_NULL_ARGUMENT(GetIntArrayElements, array);
+    CHECK_NON_NULL_ARGUMENT(array);
     ScopedObjectAccess soa(env);
     return GetPrimitiveArray<jintArray, jint*, mirror::IntArray>(soa, array, is_copy);
   }
 
   static jlong* GetLongArrayElements(JNIEnv* env, jlongArray array, jboolean* is_copy) {
-    CHECK_NON_NULL_ARGUMENT(GetLongArrayElements, array);
+    CHECK_NON_NULL_ARGUMENT(array);
     ScopedObjectAccess soa(env);
     return GetPrimitiveArray<jlongArray, jlong*, mirror::LongArray>(soa, array, is_copy);
   }
 
   static jshort* GetShortArrayElements(JNIEnv* env, jshortArray array, jboolean* is_copy) {
-    CHECK_NON_NULL_ARGUMENT(GetShortArrayElements, array);
+    CHECK_NON_NULL_ARGUMENT(array);
     ScopedObjectAccess soa(env);
     return GetPrimitiveArray<jshortArray, jshort*, mirror::ShortArray>(soa, array, is_copy);
   }
@@ -2290,7 +2292,7 @@
       JniAbortF("RegisterNatives", "negative method count: %d", method_count);
       return JNI_ERR;  // Not reached.
     }
-    CHECK_NON_NULL_ARGUMENT(RegisterNatives, java_class);
+    CHECK_NON_NULL_ARGUMENT_FN_NAME("RegisterNatives", java_class);
     ScopedObjectAccess soa(env);
     mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
     if (UNLIKELY(method_count == 0)) {
@@ -2298,7 +2300,7 @@
           << PrettyDescriptor(c);
       return JNI_OK;
     }
-    CHECK_NON_NULL_ARGUMENT(RegisterNatives, methods);
+    CHECK_NON_NULL_ARGUMENT_FN_NAME("RegisterNatives", methods);
     for (jint i = 0; i < method_count; ++i) {
       const char* name = methods[i].name;
       const char* sig = methods[i].signature;
@@ -2335,7 +2337,7 @@
   }
 
   static jint UnregisterNatives(JNIEnv* env, jclass java_class) {
-    CHECK_NON_NULL_ARGUMENT(UnregisterNatives, java_class);
+    CHECK_NON_NULL_ARGUMENT(java_class);
     ScopedObjectAccess soa(env);
     mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
 
@@ -2358,7 +2360,7 @@
   }
 
   static jint MonitorEnter(JNIEnv* env, jobject java_object) NO_THREAD_SAFETY_ANALYSIS {
-    CHECK_NON_NULL_ARGUMENT(MonitorEnter, java_object);
+    CHECK_NON_NULL_ARGUMENT(java_object);
     ScopedObjectAccess soa(env);
     mirror::Object* o = soa.Decode<mirror::Object*>(java_object);
     o = o->MonitorEnter(soa.Self());
@@ -2370,7 +2372,7 @@
   }
 
   static jint MonitorExit(JNIEnv* env, jobject java_object) NO_THREAD_SAFETY_ANALYSIS {
-    CHECK_NON_NULL_ARGUMENT(MonitorExit, java_object);
+    CHECK_NON_NULL_ARGUMENT(java_object);
     ScopedObjectAccess soa(env);
     mirror::Object* o = soa.Decode<mirror::Object*>(java_object);
     o->MonitorExit(soa.Self());
@@ -2382,7 +2384,7 @@
   }
 
   static jint GetJavaVM(JNIEnv* env, JavaVM** vm) {
-    CHECK_NON_NULL_ARGUMENT(GetJavaVM, vm);
+    CHECK_NON_NULL_ARGUMENT(vm);
     Runtime* runtime = Runtime::Current();
     if (runtime != nullptr) {
       *vm = runtime->GetJavaVM();
@@ -2422,7 +2424,7 @@
   }
 
   static jobjectRefType GetObjectRefType(JNIEnv* env, jobject java_object) {
-    CHECK_NON_NULL_ARGUMENT(GetObjectRefType, java_object);
+    CHECK_NON_NULL_ARGUMENT(java_object);
 
     // Do we definitely know what kind of reference this is?
     IndirectRef ref = reinterpret_cast<IndirectRef>(java_object);
@@ -2543,12 +2545,12 @@
   static void GetPrimitiveArrayRegion(ScopedObjectAccess& soa, JavaArrayT java_array,
                                       jsize start, jsize length, JavaT* buf)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    CHECK_NON_NULL_ARGUMENT(GetPrimitiveArrayRegion, java_array);
+    CHECK_NON_NULL_ARGUMENT(java_array);
     ArrayT* array = soa.Decode<ArrayT*>(java_array);
     if (start < 0 || length < 0 || start + length > array->GetLength()) {
       ThrowAIOOBE(soa, array, start, length, "src");
     } else {
-      CHECK_NON_NULL_MEMCPY_ARGUMENT(GetStringRegion, length, buf);
+      CHECK_NON_NULL_MEMCPY_ARGUMENT(length, buf);
       JavaT* data = array->GetData();
       memcpy(buf, data + start, length * sizeof(JavaT));
     }
@@ -2558,12 +2560,12 @@
   static void SetPrimitiveArrayRegion(ScopedObjectAccess& soa, JavaArrayT java_array,
                                       jsize start, jsize length, const JavaT* buf)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    CHECK_NON_NULL_ARGUMENT(SetPrimitiveArrayRegion, java_array);
+    CHECK_NON_NULL_ARGUMENT(java_array);
     ArrayT* array = soa.Decode<ArrayT*>(java_array);
     if (start < 0 || length < 0 || start + length > array->GetLength()) {
       ThrowAIOOBE(soa, array, start, length, "dst");
     } else {
-      CHECK_NON_NULL_MEMCPY_ARGUMENT(GetStringRegion, length, buf);
+      CHECK_NON_NULL_MEMCPY_ARGUMENT(length, buf);
       JavaT* data = array->GetData();
       memcpy(data + start, buf, length * sizeof(JavaT));
     }
diff --git a/runtime/mirror/array-inl.h b/runtime/mirror/array-inl.h
index 3d2fd7b..7f974d0 100644
--- a/runtime/mirror/array-inl.h
+++ b/runtime/mirror/array-inl.h
@@ -27,10 +27,11 @@
 namespace art {
 namespace mirror {
 
-template<VerifyObjectFlags kVerifyFlags>
+template<VerifyObjectFlags kVerifyFlags, bool kDoReadBarrier>
 inline size_t Array::SizeOf() {
   // This is safe from overflow because the array was already allocated, so we know it's sane.
-  size_t component_size = GetClass<kVerifyFlags>()->GetComponentSize();
+  size_t component_size =
+      GetClass<kVerifyFlags, kDoReadBarrier>()->template GetComponentSize<kDoReadBarrier>();
   // Don't need to check this since we already check this in GetClass.
   int32_t component_count =
       GetLength<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>();
diff --git a/runtime/mirror/array.h b/runtime/mirror/array.h
index 772d303..6bfd5c8 100644
--- a/runtime/mirror/array.h
+++ b/runtime/mirror/array.h
@@ -41,7 +41,7 @@
                                  const SirtRef<IntArray>& dimensions)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kDoReadBarrier = true>
   size_t SizeOf() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   int32_t GetLength() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
diff --git a/runtime/mirror/art_field.cc b/runtime/mirror/art_field.cc
index f91cab1..7b0b94c 100644
--- a/runtime/mirror/art_field.cc
+++ b/runtime/mirror/art_field.cc
@@ -19,6 +19,7 @@
 #include "art_field-inl.h"
 #include "gc/accounting/card_table-inl.h"
 #include "object-inl.h"
+#include "object_array-inl.h"
 #include "object_utils.h"
 #include "runtime.h"
 #include "scoped_thread_state_change.h"
@@ -69,5 +70,25 @@
   }
 }
 
+// TODO: we could speed up the search if fields are ordered by offsets.
+ArtField* ArtField::FindInstanceFieldWithOffset(mirror::Class* klass, uint32_t field_offset) {
+  DCHECK(klass != nullptr);
+  ObjectArray<ArtField>* instance_fields = klass->GetIFields();
+  if (instance_fields != nullptr) {
+    for (int32_t i = 0, e = instance_fields->GetLength(); i < e; ++i) {
+      mirror::ArtField* field = instance_fields->GetWithoutChecks(i);
+      if (field->GetOffset().Uint32Value() == field_offset) {
+        return field;
+      }
+    }
+  }
+  // We did not find field in the class: look into superclass.
+  if (klass->GetSuperClass() != NULL) {
+    return FindInstanceFieldWithOffset(klass->GetSuperClass(), field_offset);
+  } else {
+    return nullptr;
+  }
+}
+
 }  // namespace mirror
 }  // namespace art
diff --git a/runtime/mirror/art_field.h b/runtime/mirror/art_field.h
index 0daa838..ba70cc6 100644
--- a/runtime/mirror/art_field.h
+++ b/runtime/mirror/art_field.h
@@ -132,6 +132,10 @@
     return (GetAccessFlags() & kAccVolatile) != 0;
   }
 
+  // Returns an instance field with this offset in the given class or nullptr if not found.
+  static ArtField* FindInstanceFieldWithOffset(mirror::Class* klass, uint32_t field_offset)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
  private:
   // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
   // The class we are a part of
diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc
index f3303a8..726004b 100644
--- a/runtime/mirror/art_method.cc
+++ b/runtime/mirror/art_method.cc
@@ -315,13 +315,13 @@
       } else {
         (*art_portable_invoke_stub)(this, args, args_size, self, result, shorty[0]);
       }
-      if (UNLIKELY(reinterpret_cast<intptr_t>(self->GetException(NULL)) == -1)) {
-        // Unusual case where we were running LLVM generated code and an
+      if (UNLIKELY(self->GetException(nullptr) == Thread::GetDeoptimizationException())) {
+        // Unusual case where we were running generated code and an
         // exception was thrown to force the activations to be removed from the
         // stack. Continue execution in the interpreter.
         self->ClearException();
         ShadowFrame* shadow_frame = self->GetAndClearDeoptimizationShadowFrame(result);
-        self->SetTopOfStack(NULL, 0);
+        self->SetTopOfStack(nullptr, 0);
         self->SetTopOfShadowStack(shadow_frame);
         interpreter::EnterInterpreterFromDeoptimize(self, shadow_frame, result);
       }
diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h
index d684266..4462036 100644
--- a/runtime/mirror/art_method.h
+++ b/runtime/mirror/art_method.h
@@ -426,7 +426,9 @@
 
   static void SetClass(Class* java_lang_reflect_ArtMethod);
 
+  template <bool kDoReadBarrier = true>
   static Class* GetJavaLangReflectArtMethod() {
+    // This does not need a RB because it is a root.
     return java_lang_reflect_ArtMethod_;
   }
 
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 025e62a..3c02aa0 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -478,6 +478,19 @@
   VisitStaticFieldsReferences<kVisitClass>(this, visitor);
 }
 
+template<bool kDoReadBarrier>
+bool Class::IsArtFieldClass() {
+  Class* java_lang_Class = GetClass<kVerifyNone, kDoReadBarrier>();
+  Class* java_lang_reflect_ArtField =
+      java_lang_Class->GetInstanceField(0)->GetClass<kVerifyNone, kDoReadBarrier>();
+  return this == java_lang_reflect_ArtField;
+}
+
+template<bool kDoReadBarrier>
+bool Class::IsArtMethodClass() {
+  return this == ArtMethod::GetJavaLangReflectArtMethod<kDoReadBarrier>();
+}
+
 }  // namespace mirror
 }  // namespace art
 
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 6dbb29d..ad86e1f 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -328,16 +328,6 @@
   return WellKnownClasses::ToClass(WellKnownClasses::java_lang_Throwable)->IsAssignableFrom(this);
 }
 
-bool Class::IsArtFieldClass() {
-  Class* java_lang_Class = GetClass();
-  Class* java_lang_reflect_ArtField = java_lang_Class->GetInstanceField(0)->GetClass();
-  return this == java_lang_reflect_ArtField;
-}
-
-bool Class::IsArtMethodClass() {
-  return this == ArtMethod::GetJavaLangReflectArtMethod();
-}
-
 void Class::SetClassLoader(ClassLoader* new_class_loader) {
   if (Runtime::Current()->IsActiveTransaction()) {
     SetFieldObject<true>(OFFSET_OF_OBJECT_MEMBER(Class, class_loader_), new_class_loader, false);
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index d955b97..226dee0 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -364,9 +364,9 @@
     return depth;
   }
 
-  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kDoReadBarrier = true>
   bool IsArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetComponentType<kVerifyFlags>() != NULL;
+    return GetComponentType<kVerifyFlags, kDoReadBarrier>() != NULL;
   }
 
   bool IsClassClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -375,17 +375,19 @@
 
   bool IsThrowableClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  template<bool kDoReadBarrier = true>
   bool IsArtFieldClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  template<bool kDoReadBarrier = true>
   bool IsArtMethodClass();
 
   static MemberOffset ComponentTypeOffset() {
     return OFFSET_OF_OBJECT_MEMBER(Class, component_type_);
   }
 
-  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kDoReadBarrier = true>
   Class* GetComponentType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetFieldObject<Class, kVerifyFlags>(ComponentTypeOffset(), false);
+    return GetFieldObject<Class, kVerifyFlags, kDoReadBarrier>(ComponentTypeOffset(), false);
   }
 
   void SetComponentType(Class* new_component_type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -395,8 +397,10 @@
     SetFieldObject<false, false>(ComponentTypeOffset(), new_component_type, false);
   }
 
+  template<bool kDoReadBarrier = true>
   size_t GetComponentSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return Primitive::ComponentSize(GetComponentType()->GetPrimitiveType());
+    return Primitive::ComponentSize(
+        GetComponentType<kDefaultVerifyFlags, kDoReadBarrier>()->GetPrimitiveType());
   }
 
   bool IsObjectClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -427,7 +431,7 @@
     return IsClassClass() || IsArrayClass();
   }
 
-  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kDoReadBarrier = true>
   uint32_t SizeOf() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     return GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), false);
   }
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index b195dea..04517ec 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -34,9 +34,10 @@
 namespace art {
 namespace mirror {
 
-template<VerifyObjectFlags kVerifyFlags>
+template<VerifyObjectFlags kVerifyFlags, bool kDoReadBarrier>
 inline Class* Object::GetClass() {
-  return GetFieldObject<Class, kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Object, klass_), false);
+  return GetFieldObject<Class, kVerifyFlags, kDoReadBarrier>(
+      OFFSET_OF_OBJECT_MEMBER(Object, klass_), false);
 }
 
 template<VerifyObjectFlags kVerifyFlags>
@@ -105,18 +106,45 @@
 #endif
 }
 
-inline void Object::SetReadBarrierPointer(Object* rb_pointer) {
+inline void Object::SetReadBarrierPointer(Object* rb_ptr) {
 #ifdef USE_BAKER_OR_BROOKS_READ_BARRIER
   DCHECK(kUseBakerOrBrooksReadBarrier);
   // We don't mark the card as this occurs as part of object allocation. Not all objects have
   // backing cards, such as large objects.
   SetFieldObjectWithoutWriteBarrier<false, false, kVerifyNone>(
-      OFFSET_OF_OBJECT_MEMBER(Object, x_rb_ptr_), rb_pointer, false);
+      OFFSET_OF_OBJECT_MEMBER(Object, x_rb_ptr_), rb_ptr, false);
 #else
   LOG(FATAL) << "Unreachable";
 #endif
 }
 
+inline bool Object::AtomicSetReadBarrierPointer(Object* expected_rb_ptr, Object* rb_ptr) {
+#ifdef USE_BAKER_OR_BROOKS_READ_BARRIER
+  DCHECK(kUseBakerOrBrooksReadBarrier);
+  MemberOffset offset = OFFSET_OF_OBJECT_MEMBER(Object, x_rb_ptr_);
+  byte* raw_addr = reinterpret_cast<byte*>(this) + offset.SizeValue();
+  HeapReference<Object>* ref = reinterpret_cast<HeapReference<Object>*>(raw_addr);
+  HeapReference<Object> expected_ref(HeapReference<Object>::FromMirrorPtr(expected_rb_ptr));
+  HeapReference<Object> new_ref(HeapReference<Object>::FromMirrorPtr(rb_ptr));
+  uint32_t expected_val = expected_ref.reference_;
+  uint32_t new_val;
+  do {
+    uint32_t old_val = ref->reference_;
+    if (old_val != expected_val) {
+      // Lost the race.
+      return false;
+    }
+    new_val = new_ref.reference_;
+  } while (!__sync_bool_compare_and_swap(
+      reinterpret_cast<uint32_t*>(raw_addr), expected_val, new_val));
+  DCHECK_EQ(new_val, ref->reference_);
+  return true;
+#else
+  LOG(FATAL) << "Unreachable";
+  return false;
+#endif
+}
+
 inline void Object::AssertReadBarrierPointer() const {
   if (kUseBakerReadBarrier) {
     Object* obj = const_cast<Object*>(this);
@@ -147,16 +175,17 @@
   return klass->IsAssignableFrom(GetClass<kVerifyFlags>());
 }
 
-template<VerifyObjectFlags kVerifyFlags>
+template<VerifyObjectFlags kVerifyFlags, bool kDoReadBarrier>
 inline bool Object::IsClass() {
-  Class* java_lang_Class = GetClass<kVerifyFlags>()->GetClass();
-  return GetClass<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>() ==
+  Class* java_lang_Class =
+      GetClass<kVerifyFlags, kDoReadBarrier>()->template GetClass<kVerifyFlags, kDoReadBarrier>();
+  return GetClass<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis), kDoReadBarrier>() ==
       java_lang_Class;
 }
 
-template<VerifyObjectFlags kVerifyFlags>
+template<VerifyObjectFlags kVerifyFlags, bool kDoReadBarrier>
 inline Class* Object::AsClass() {
-  DCHECK(IsClass<kVerifyFlags>());
+  DCHECK((IsClass<kVerifyFlags, kDoReadBarrier>()));
   return down_cast<Class*>(this);
 }
 
@@ -173,14 +202,15 @@
   return down_cast<ObjectArray<T>*>(this);
 }
 
-template<VerifyObjectFlags kVerifyFlags>
+template<VerifyObjectFlags kVerifyFlags, bool kDoReadBarrier>
 inline bool Object::IsArrayInstance() {
-  return GetClass<kVerifyFlags>()->IsArrayClass();
+  return GetClass<kVerifyFlags, kDoReadBarrier>()->
+      template IsArrayClass<kVerifyFlags, kDoReadBarrier>();
 }
 
-template<VerifyObjectFlags kVerifyFlags>
+template<VerifyObjectFlags kVerifyFlags, bool kDoReadBarrier>
 inline bool Object::IsArtField() {
-  return GetClass<kVerifyFlags>()->IsArtFieldClass();
+  return GetClass<kVerifyFlags, kDoReadBarrier>()->template IsArtFieldClass<kDoReadBarrier>();
 }
 
 template<VerifyObjectFlags kVerifyFlags>
@@ -189,9 +219,9 @@
   return down_cast<ArtField*>(this);
 }
 
-template<VerifyObjectFlags kVerifyFlags>
+template<VerifyObjectFlags kVerifyFlags, bool kDoReadBarrier>
 inline bool Object::IsArtMethod() {
-  return GetClass<kVerifyFlags>()->IsArtMethodClass();
+  return GetClass<kVerifyFlags, kDoReadBarrier>()->template IsArtMethodClass<kDoReadBarrier>();
 }
 
 template<VerifyObjectFlags kVerifyFlags>
@@ -211,9 +241,9 @@
   return down_cast<Reference*>(this);
 }
 
-template<VerifyObjectFlags kVerifyFlags>
+template<VerifyObjectFlags kVerifyFlags, bool kDoReadBarrier>
 inline Array* Object::AsArray() {
-  DCHECK(IsArrayInstance<kVerifyFlags>());
+  DCHECK((IsArrayInstance<kVerifyFlags, kDoReadBarrier>()));
   return down_cast<Array*>(this);
 }
 
@@ -339,20 +369,21 @@
   return GetClass<kVerifyFlags>()->IsPhantomReferenceClass();
 }
 
-template<VerifyObjectFlags kVerifyFlags>
+template<VerifyObjectFlags kVerifyFlags, bool kDoReadBarrier>
 inline size_t Object::SizeOf() {
   size_t result;
   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
-  if (IsArrayInstance<kVerifyFlags>()) {
-    result = AsArray<kNewFlags>()->template SizeOf<kNewFlags>();
-  } else if (IsClass<kNewFlags>()) {
-    result = AsClass<kNewFlags>()->template SizeOf<kNewFlags>();
+  if (IsArrayInstance<kVerifyFlags, kDoReadBarrier>()) {
+    result = AsArray<kNewFlags, kDoReadBarrier>()->template SizeOf<kNewFlags, kDoReadBarrier>();
+  } else if (IsClass<kNewFlags, kDoReadBarrier>()) {
+    result = AsClass<kNewFlags, kDoReadBarrier>()->template SizeOf<kNewFlags, kDoReadBarrier>();
   } else {
-    result = GetClass<kNewFlags>()->GetObjectSize();
+    result = GetClass<kNewFlags, kDoReadBarrier>()->GetObjectSize();
   }
-  DCHECK_GE(result, sizeof(Object)) << " class=" << PrettyTypeOf(GetClass<kNewFlags>());
-  DCHECK(!IsArtField<kNewFlags>()  || result == sizeof(ArtField));
-  DCHECK(!IsArtMethod<kNewFlags>() || result == sizeof(ArtMethod));
+  DCHECK_GE(result, sizeof(Object))
+      << " class=" << PrettyTypeOf(GetClass<kNewFlags, kDoReadBarrier>());
+  DCHECK(!(IsArtField<kNewFlags, kDoReadBarrier>())  || result == sizeof(ArtField));
+  DCHECK(!(IsArtMethod<kNewFlags, kDoReadBarrier>()) || result == sizeof(ArtMethod));
   return result;
 }
 
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index fd31dfb..370b3b8 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -72,14 +72,16 @@
     return OFFSET_OF_OBJECT_MEMBER(Object, klass_);
   }
 
-  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kDoReadBarrier = true>
   Class* GetClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   void SetClass(Class* new_klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   Object* GetReadBarrierPointer() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  void SetReadBarrierPointer(Object* rb_pointer) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void SetReadBarrierPointer(Object* rb_ptr) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  bool AtomicSetReadBarrierPointer(Object* expected_rb_ptr, Object* rb_ptr)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void AssertReadBarrierPointer() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // The verifier treats all interfaces as java.lang.Object and relies on runtime checks in
@@ -89,7 +91,7 @@
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool InstanceOf(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kDoReadBarrier = true>
   size_t SizeOf() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   Object* Clone(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -116,9 +118,9 @@
   void Wait(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void Wait(Thread* self, int64_t timeout, int32_t nanos) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kDoReadBarrier = true>
   bool IsClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kDoReadBarrier = true>
   Class* AsClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
@@ -126,9 +128,9 @@
   template<class T, VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   ObjectArray<T>* AsObjectArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kDoReadBarrier = true>
   bool IsArrayInstance() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kDoReadBarrier = true>
   Array* AsArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
@@ -161,12 +163,12 @@
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   Throwable* AsThrowable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kDoReadBarrier = true>
   bool IsArtMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   ArtMethod* AsArtMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kDoReadBarrier = true>
   bool IsArtField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   ArtField* AsArtField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/catch_finder.cc b/runtime/quick_exception_handler.cc
similarity index 67%
rename from runtime/catch_finder.cc
rename to runtime/quick_exception_handler.cc
index f0293d7..d5844b6 100644
--- a/runtime/catch_finder.cc
+++ b/runtime/quick_exception_handler.cc
@@ -14,37 +14,37 @@
  * limitations under the License.
  */
 
-#include "catch_finder.h"
+#include "quick_exception_handler.h"
+
 #include "catch_block_stack_visitor.h"
+#include "deoptimize_stack_visitor.h"
+#include "entrypoints/entrypoint_utils.h"
+#include "sirt_ref-inl.h"
 
 namespace art {
 
-CatchFinder::CatchFinder(Thread* self, const ThrowLocation& throw_location,
-            mirror::Throwable* exception, bool is_deoptimization)
-  : self_(self), context_(self->GetLongJumpContext()),
-    exception_(exception), is_deoptimization_(is_deoptimization), throw_location_(throw_location),
+QuickExceptionHandler::QuickExceptionHandler(Thread* self, bool is_deoptimization)
+  : self_(self), context_(self->GetLongJumpContext()), is_deoptimization_(is_deoptimization),
     method_tracing_active_(is_deoptimization ||
                            Runtime::Current()->GetInstrumentation()->AreExitStubsInstalled()),
-                           handler_quick_frame_(nullptr), handler_quick_frame_pc_(0),
-                           handler_dex_pc_(0), clear_exception_(false), top_shadow_frame_(nullptr),
-                           handler_frame_id_(kInvalidFrameId) {
-  // Exception not in root sets, can't allow GC.
-  last_no_assert_suspension_cause_ = self->StartAssertNoThreadSuspension("Finding catch block");
+    handler_quick_frame_(nullptr), handler_quick_frame_pc_(0), handler_dex_pc_(0),
+    clear_exception_(false), top_shadow_frame_(nullptr), handler_frame_id_(kInvalidFrameId) {
 }
 
-void CatchFinder::FindCatch() {
+void QuickExceptionHandler::FindCatch(const ThrowLocation& throw_location,
+                                      mirror::Throwable* exception) {
+  DCHECK(!is_deoptimization_);
+  SirtRef<mirror::Throwable> exception_ref(self_, exception);
+
   // Walk the stack to find catch handler or prepare for deoptimization.
-  CatchBlockStackVisitor visitor(self_, context_, exception_, is_deoptimization_, this);
+  CatchBlockStackVisitor visitor(self_, context_, exception_ref, this);
   visitor.WalkStack(true);
 
   mirror::ArtMethod* catch_method = *handler_quick_frame_;
-  if (catch_method == nullptr) {
-    if (kDebugExceptionDelivery) {
+  if (kDebugExceptionDelivery) {
+    if (catch_method == nullptr) {
       LOG(INFO) << "Handler is upcall";
-    }
-  } else {
-    CHECK(!is_deoptimization_);
-    if (kDebugExceptionDelivery) {
+    } else {
       const DexFile& dex_file = *catch_method->GetDeclaringClass()->GetDexCache()->GetDexFile();
       int line_number = dex_file.GetLineNumFromPC(catch_method, handler_dex_pc_);
       LOG(INFO) << "Handler: " << PrettyMethod(catch_method) << " (line: " << line_number << ")";
@@ -55,17 +55,23 @@
     DCHECK(!self_->IsExceptionPending());
   } else {
     // Put exception back in root set with clear throw location.
-    self_->SetException(ThrowLocation(), exception_);
+    self_->SetException(ThrowLocation(), exception_ref.get());
   }
-  self_->EndAssertNoThreadSuspension(last_no_assert_suspension_cause_);
-  // Do instrumentation events after allowing thread suspension again.
-  if (!is_deoptimization_) {
-    // The debugger may suspend this thread and walk its stack. Let's do this before popping
-    // instrumentation frames.
-    instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
-    instrumentation->ExceptionCaughtEvent(self_, throw_location_, catch_method, handler_dex_pc_,
-                                          exception_);
-  }
+  // The debugger may suspend this thread and walk its stack. Let's do this before popping
+  // instrumentation frames.
+  instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
+  instrumentation->ExceptionCaughtEvent(self_, throw_location, catch_method, handler_dex_pc_,
+                                        exception_ref.get());
+}
+
+void QuickExceptionHandler::DeoptimizeStack() {
+  DCHECK(is_deoptimization_);
+
+  DeoptimizeStackVisitor visitor(self_, context_, this);
+  visitor.WalkStack(true);
+
+  // Restore deoptimization exception
+  self_->SetException(ThrowLocation(), Thread::GetDeoptimizationException());
 }
 
 // Unwinds all instrumentation stack frame prior to catch handler or upcall.
@@ -105,7 +111,7 @@
   DISALLOW_COPY_AND_ASSIGN(InstrumentationStackVisitor);
 };
 
-void CatchFinder::UpdateInstrumentationStack() {
+void QuickExceptionHandler::UpdateInstrumentationStack() {
   if (method_tracing_active_) {
     InstrumentationStackVisitor visitor(self_, is_deoptimization_, handler_frame_id_);
     visitor.WalkStack(true);
@@ -118,7 +124,7 @@
   }
 }
 
-void CatchFinder::DoLongJump() {
+void QuickExceptionHandler::DoLongJump() {
   if (is_deoptimization_) {
     // TODO: proper return value.
     self_->SetDeoptimizationShadowFrame(top_shadow_frame_);
diff --git a/runtime/catch_finder.h b/runtime/quick_exception_handler.h
similarity index 76%
rename from runtime/catch_finder.h
rename to runtime/quick_exception_handler.h
index ebbafe2..d06ce7c 100644
--- a/runtime/catch_finder.h
+++ b/runtime/quick_exception_handler.h
@@ -14,29 +14,39 @@
  * limitations under the License.
  */
 
-#ifndef ART_RUNTIME_CATCH_FINDER_H_
-#define ART_RUNTIME_CATCH_FINDER_H_
+#ifndef ART_RUNTIME_QUICK_EXCEPTION_HANDLER_H_
+#define ART_RUNTIME_QUICK_EXCEPTION_HANDLER_H_
 
-#include "mirror/art_method-inl.h"
-#include "thread.h"
+#include "base/logging.h"
+#include "base/mutex.h"
 
 namespace art {
 
+namespace mirror {
+class ArtMethod;
+class Throwable;
+}  // namespace mirror
+class Context;
+class Thread;
+class ThrowLocation;
+class ShadowFrame;
+
 static constexpr bool kDebugExceptionDelivery = false;
 static constexpr size_t kInvalidFrameId = 0xffffffff;
 
 // Manages exception delivery for Quick backend. Not used by Portable backend.
-class CatchFinder {
+class QuickExceptionHandler {
  public:
-  CatchFinder(Thread* self, const ThrowLocation& throw_location, mirror::Throwable* exception,
-              bool is_deoptimization)
+  QuickExceptionHandler(Thread* self, bool is_deoptimization)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  ~CatchFinder() {
+  ~QuickExceptionHandler() {
     LOG(FATAL) << "UNREACHABLE";  // Expected to take long jump.
   }
 
-  void FindCatch() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void FindCatch(const ThrowLocation& throw_location, mirror::Throwable* exception)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void DeoptimizeStack() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void UpdateInstrumentationStack() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void DoLongJump() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -67,14 +77,9 @@
  private:
   Thread* const self_;
   Context* const context_;
-  mirror::Throwable* const exception_;
   const bool is_deoptimization_;
-  // Location of the throw.
-  const ThrowLocation& throw_location_;
   // Is method tracing active?
   const bool method_tracing_active_;
-  // Support for nesting no thread suspension checks.
-  const char* last_no_assert_suspension_cause_;
   // Quick frame with found handler or last frame if no handler found.
   mirror::ArtMethod** handler_quick_frame_;
   // PC to branch to for the handler.
@@ -88,8 +93,8 @@
   // Frame id of the catch handler or the upcall.
   size_t handler_frame_id_;
 
-  DISALLOW_COPY_AND_ASSIGN(CatchFinder);
+  DISALLOW_COPY_AND_ASSIGN(QuickExceptionHandler);
 };
 
 }  // namespace art
-#endif  // ART_RUNTIME_CATCH_FINDER_H_
+#endif  // ART_RUNTIME_QUICK_EXCEPTION_HANDLER_H_
diff --git a/runtime/scoped_thread_state_change.h b/runtime/scoped_thread_state_change.h
index 404c616..7698d6a 100644
--- a/runtime/scoped_thread_state_change.h
+++ b/runtime/scoped_thread_state_change.h
@@ -38,23 +38,18 @@
       Runtime* runtime = Runtime::Current();
       CHECK(runtime == NULL || !runtime->IsStarted() || runtime->IsShuttingDown(self_));
     } else {
-      bool runnable_transition;
       DCHECK_EQ(self, Thread::Current());
       // Read state without locks, ok as state is effectively thread local and we're not interested
       // in the suspend count (this will be handled in the runnable transitions).
       old_thread_state_ = self->GetState();
-      runnable_transition = old_thread_state_ == kRunnable || new_thread_state == kRunnable;
-      if (!runnable_transition) {
-        // A suspended transition to another effectively suspended transition, ok to use Unsafe.
-        self_->SetState(new_thread_state);
-      }
-
-      if (runnable_transition && old_thread_state_ != new_thread_state) {
+      if (old_thread_state_ != new_thread_state) {
         if (new_thread_state == kRunnable) {
           self_->TransitionFromSuspendedToRunnable();
-        } else {
-          DCHECK_EQ(old_thread_state_, kRunnable);
+        } else if (old_thread_state_ == kRunnable) {
           self_->TransitionFromRunnableToSuspended(new_thread_state);
+        } else {
+          // A suspended transition to another effectively suspended transition, ok to use Unsafe.
+          self_->SetState(new_thread_state);
         }
       }
     }
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 998579d..095404f 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -32,7 +32,6 @@
 
 #include "arch/context.h"
 #include "base/mutex.h"
-#include "catch_finder.h"
 #include "class_linker.h"
 #include "class_linker-inl.h"
 #include "cutils/atomic.h"
@@ -54,6 +53,7 @@
 #include "mirror/stack_trace_element.h"
 #include "monitor.h"
 #include "object_utils.h"
+#include "quick_exception_handler.h"
 #include "reflection.h"
 #include "runtime.h"
 #include "scoped_thread_state_change.h"
@@ -1841,7 +1841,7 @@
   // Don't leave exception visible while we try to find the handler, which may cause class
   // resolution.
   ClearException();
-  bool is_deoptimization = (exception == reinterpret_cast<mirror::Throwable*>(-1));
+  bool is_deoptimization = (exception == GetDeoptimizationException());
   if (kDebugExceptionDelivery) {
     if (!is_deoptimization) {
       mirror::String* msg = exception->GetDetailMessage();
@@ -1852,10 +1852,14 @@
       DumpStack(LOG(INFO) << "Deoptimizing: ");
     }
   }
-  CatchFinder catch_finder(this, throw_location, exception, is_deoptimization);
-  catch_finder.FindCatch();
-  catch_finder.UpdateInstrumentationStack();
-  catch_finder.DoLongJump();
+  QuickExceptionHandler exception_handler(this, is_deoptimization);
+  if (is_deoptimization) {
+    exception_handler.DeoptimizeStack();
+  } else {
+    exception_handler.FindCatch(throw_location, exception);
+  }
+  exception_handler.UpdateInstrumentationStack();
+  exception_handler.DoLongJump();
   LOG(FATAL) << "UNREACHABLE";
 }
 
@@ -2060,7 +2064,7 @@
   if (tlsPtr_.opeer != nullptr) {
     visitor(&tlsPtr_.opeer, arg, thread_id, kRootThreadObject);
   }
-  if (tlsPtr_.exception != nullptr) {
+  if (tlsPtr_.exception != nullptr && tlsPtr_.exception != GetDeoptimizationException()) {
     visitor(reinterpret_cast<mirror::Object**>(&tlsPtr_.exception), arg, thread_id, kRootNativeStack);
   }
   tlsPtr_.throw_location.VisitRoots(visitor, arg);
diff --git a/runtime/thread.h b/runtime/thread.h
index d25bbe9..e5e4cae 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -686,6 +686,11 @@
     return tlsPtr_.single_step_control;
   }
 
+  // Returns the fake exception used to activate deoptimization.
+  static mirror::Throwable* GetDeoptimizationException() {
+    return reinterpret_cast<mirror::Throwable*>(-1);
+  }
+
   void SetDeoptimizationShadowFrame(ShadowFrame* sf);
   void SetDeoptimizationReturnValue(const JValue& ret_val);
 
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 535c76d..91170f0 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -1176,8 +1176,11 @@
         // it's effectively considered initialized the instant we reach here (in the sense that we
         // can return without doing anything or call virtual methods).
         {
-          const RegType& reg_type = reg_types_.FromDescriptor(class_loader_->get(), descriptor,
-                                                              false);
+          const RegType& reg_type = ResolveClassAndCheckAccess(iterator.GetTypeIdx());
+          if (!reg_type.IsNonZeroReferenceTypes()) {
+            DCHECK(HasFailures());
+            return false;
+          }
           reg_line->SetRegisterType(arg_start + cur_arg, reg_type);
         }
         break;
@@ -2865,11 +2868,7 @@
             common_super = &reg_types_.JavaLangThrowable(false);
           } else {
             const RegType& exception = ResolveClassAndCheckAccess(iterator.GetHandlerTypeIndex());
-            if (common_super == NULL) {
-              // Unconditionally assign for the first handler. We don't assert this is a Throwable
-              // as that is caught at runtime
-              common_super = &exception;
-            } else if (!reg_types_.JavaLangThrowable(false).IsAssignableFrom(exception)) {
+            if (!reg_types_.JavaLangThrowable(false).IsAssignableFrom(exception)) {
               if (exception.IsUnresolvedTypes()) {
                 // We don't know enough about the type. Fail here and let runtime handle it.
                 Fail(VERIFY_ERROR_NO_CLASS) << "unresolved exception class " << exception;
@@ -2878,6 +2877,8 @@
                 Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "unexpected non-exception class " << exception;
                 return reg_types_.Conflict();
               }
+            } else if (common_super == nullptr) {
+              common_super = &exception;
             } else if (common_super->Equals(exception)) {
               // odd case, but nothing to do
             } else {
@@ -3596,29 +3597,6 @@
   }
 }
 
-// Look for an instance field with this offset.
-// TODO: we may speed up the search if offsets are sorted by doing a quick search.
-static mirror::ArtField* FindInstanceFieldWithOffset(mirror::Class* klass, uint32_t field_offset)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  mirror::ObjectArray<mirror::ArtField>* instance_fields = klass->GetIFields();
-  if (instance_fields != NULL) {
-    for (int32_t i = 0, e = instance_fields->GetLength(); i < e; ++i) {
-      mirror::ArtField* field = instance_fields->Get(i);
-      if (field->GetOffset().Uint32Value() == field_offset) {
-        return field;
-      }
-    }
-  }
-  // We did not find field in class: look into superclass.
-  if (klass->GetSuperClass() != NULL) {
-    return FindInstanceFieldWithOffset(klass->GetSuperClass(), field_offset);
-  } else {
-    VLOG(verifier) << "Failed to find instance field at offset '" << field_offset
-        << "' from '" << PrettyDescriptor(klass) << "'";
-    return nullptr;
-  }
-}
-
 mirror::ArtField* MethodVerifier::GetQuickFieldAccess(const Instruction* inst,
                                                       RegisterLine* reg_line) {
   DCHECK(inst->Opcode() == Instruction::IGET_QUICK ||
@@ -3633,7 +3611,13 @@
     return nullptr;
   }
   uint32_t field_offset = static_cast<uint32_t>(inst->VRegC_22c());
-  return FindInstanceFieldWithOffset(object_type.GetClass(), field_offset);
+  mirror::ArtField* f = mirror::ArtField::FindInstanceFieldWithOffset(object_type.GetClass(),
+                                                                      field_offset);
+  if (f == nullptr) {
+    VLOG(verifier) << "Failed to find instance field at offset '" << field_offset
+                   << "' from '" << PrettyDescriptor(object_type.GetClass()) << "'";
+  }
+  return f;
 }
 
 void MethodVerifier::VerifyIGetQuick(const Instruction* inst, const RegType& insn_type,