Clean up ScopedThreadStateChange to use ObjPtr

Also fixed inclusion of -inl.h files in .h files by adding
scoped_object_access-inl.h and scoped_fast_natvie_object_access-inl.h

Changed AddLocalReference / Decode to use ObjPtr.

Changed libartbenchmark to be debug to avoid linkage errors.

Bug: 31113334

Test: test-art-host

Change-Id: I4d2e160483a29d21e1e0e440585ed328b9811483
diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc
index 384de34..0677d5b 100644
--- a/runtime/native/dalvik_system_DexFile.cc
+++ b/runtime/native/dalvik_system_DexFile.cc
@@ -34,7 +34,7 @@
 #include "oat_file_manager.h"
 #include "os.h"
 #include "runtime.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
 #include "ScopedLocalRef.h"
 #include "ScopedUtfChars.h"
 #include "utils.h"
@@ -217,7 +217,7 @@
   bool all_deleted = true;
   {
     ScopedObjectAccess soa(env);
-    mirror::Object* dex_files_object = soa.Decode<mirror::Object*>(cookie);
+    ObjPtr<mirror::Object> dex_files_object = soa.Decode<mirror::Object>(cookie);
     mirror::LongArray* long_dex_files = dex_files_object->AsLongArray();
     // Delete dex files associated with this dalvik.system.DexFile since there should not be running
     // code using it. dex_files is a vector due to multidex.
@@ -277,7 +277,7 @@
       ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
       StackHandleScope<1> hs(soa.Self());
       Handle<mirror::ClassLoader> class_loader(
-          hs.NewHandle(soa.Decode<mirror::ClassLoader*>(javaLoader)));
+          hs.NewHandle(soa.Decode<mirror::ClassLoader>(javaLoader)));
       class_linker->RegisterDexFile(*dex_file, class_loader.Get());
       mirror::Class* result = class_linker->DefineClass(soa.Self(),
                                                         descriptor.c_str(),
@@ -287,7 +287,7 @@
                                                         *dex_class_def);
       // Add the used dex file. This only required for the DexFile.loadClass API since normal
       // class loaders already keep their dex files live.
-      class_linker->InsertDexFileInToClassLoader(soa.Decode<mirror::Object*>(dexFile),
+      class_linker->InsertDexFileInToClassLoader(soa.Decode<mirror::Object>(dexFile).Decode(),
                                                  class_loader.Get());
       if (result != nullptr) {
         VLOG(class_linker) << "DexFile_defineClassNative returning " << result
diff --git a/runtime/native/dalvik_system_InMemoryDexClassLoader_DexData.cc b/runtime/native/dalvik_system_InMemoryDexClassLoader_DexData.cc
index 94933bc..fdced21 100644
--- a/runtime/native/dalvik_system_InMemoryDexClassLoader_DexData.cc
+++ b/runtime/native/dalvik_system_InMemoryDexClassLoader_DexData.cc
@@ -24,7 +24,7 @@
 #include "mirror/class_loader.h"
 #include "mirror/object-inl.h"
 #include "oat_file.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
 #include "ScopedUtfChars.h"
 
 namespace art {
@@ -148,7 +148,7 @@
     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
     StackHandleScope<1> handle_scope(soa.Self());
     Handle<mirror::ClassLoader> class_loader(
-        handle_scope.NewHandle(soa.Decode<mirror::ClassLoader*>(loader)));
+        handle_scope.NewHandle(soa.Decode<mirror::ClassLoader>(loader)));
     class_linker->RegisterDexFile(*dex_file, class_loader.Get());
     mirror::Class* result = class_linker->DefineClass(
         soa.Self(), class_descriptor, hash, class_loader, *dex_file, *dex_class_def);
@@ -157,7 +157,7 @@
       // InMemoryClassLoader/DexData instance now that a class has
       // been loaded.
       class_linker->InsertDexFileInToClassLoader(
-          soa.Decode<mirror::Object*>(dexData), class_loader.Get());
+          soa.Decode<mirror::Object>(dexData).Decode(), class_loader.Get());
       return soa.AddLocalReference<jclass>(result);
     }
   }
diff --git a/runtime/native/dalvik_system_VMDebug.cc b/runtime/native/dalvik_system_VMDebug.cc
index f09c067..73c4664 100644
--- a/runtime/native/dalvik_system_VMDebug.cc
+++ b/runtime/native/dalvik_system_VMDebug.cc
@@ -36,7 +36,7 @@
 #include "mirror/class.h"
 #include "ScopedLocalRef.h"
 #include "ScopedUtfChars.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
 #include "trace.h"
 #include "well_known_classes.h"
 
@@ -259,11 +259,11 @@
   ScopedObjectAccess soa(env);
   gc::Heap* const heap = Runtime::Current()->GetHeap();
   // Caller's responsibility to do GC if desired.
-  mirror::Class* c = soa.Decode<mirror::Class*>(javaClass);
+  ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(javaClass);
   if (c == nullptr) {
     return 0;
   }
-  std::vector<mirror::Class*> classes {c};
+  std::vector<mirror::Class*> classes {c.Decode()};
   uint64_t count = 0;
   heap->CountInstances(classes, countAssignable, &count);
   return count;
@@ -274,7 +274,8 @@
   ScopedObjectAccess soa(env);
   gc::Heap* const heap = Runtime::Current()->GetHeap();
   // Caller's responsibility to do GC if desired.
-  auto* decoded_classes = soa.Decode<mirror::ObjectArray<mirror::Class>*>(javaClasses);
+  ObjPtr<mirror::ObjectArray<mirror::Class>> decoded_classes =
+      soa.Decode<mirror::ObjectArray<mirror::Class>>(javaClasses);
   if (decoded_classes == nullptr) {
     return nullptr;
   }
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index d88c9d4..c7fb44ec 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -46,8 +46,8 @@
 #include "mirror/dex_cache-inl.h"
 #include "mirror/object-inl.h"
 #include "runtime.h"
-#include "scoped_fast_native_object_access.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_fast_native_object_access-inl.h"
+#include "scoped_thread_state_change-inl.h"
 #include "thread.h"
 #include "thread_list.h"
 
@@ -74,7 +74,7 @@
     ThrowNegativeArraySizeException(length);
     return nullptr;
   }
-  mirror::Class* element_class = soa.Decode<mirror::Class*>(javaElementClass);
+  mirror::Class* element_class = soa.Decode<mirror::Class>(javaElementClass).Decode();
   if (UNLIKELY(element_class == nullptr)) {
     ThrowNullPointerException("element class == null");
     return nullptr;
@@ -99,7 +99,7 @@
     ThrowNegativeArraySizeException(length);
     return nullptr;
   }
-  mirror::Class* element_class = soa.Decode<mirror::Class*>(javaElementClass);
+  mirror::Class* element_class = soa.Decode<mirror::Class>(javaElementClass).Decode();
   if (UNLIKELY(element_class == nullptr)) {
     ThrowNullPointerException("element class == null");
     return nullptr;
@@ -122,12 +122,12 @@
     return 0;
   }
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Array* array = soa.Decode<mirror::Array*>(javaArray);
+  ObjPtr<mirror::Array> array = soa.Decode<mirror::Array>(javaArray);
   if (!array->IsArrayInstance()) {
     ThrowIllegalArgumentException("not an array");
     return 0;
   }
-  if (Runtime::Current()->GetHeap()->IsMovableObject(array)) {
+  if (Runtime::Current()->GetHeap()->IsMovableObject(array.Decode())) {
     ThrowRuntimeException("Trying to get address of movable array object");
     return 0;
   }
diff --git a/runtime/native/dalvik_system_VMStack.cc b/runtime/native/dalvik_system_VMStack.cc
index 9da40b9..0dd8cdd 100644
--- a/runtime/native/dalvik_system_VMStack.cc
+++ b/runtime/native/dalvik_system_VMStack.cc
@@ -22,8 +22,8 @@
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
 #include "mirror/object-inl.h"
-#include "scoped_fast_native_object_access.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_fast_native_object_access-inl.h"
+#include "scoped_thread_state_change-inl.h"
 #include "thread_list.h"
 
 namespace art {
@@ -31,7 +31,7 @@
 static jobject GetThreadStack(const ScopedFastNativeObjectAccess& soa, jobject peer)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   jobject trace = nullptr;
-  if (soa.Decode<mirror::Object*>(peer) == soa.Self()->GetPeer()) {
+  if (soa.Decode<mirror::Object>(peer) == soa.Self()->GetPeer()) {
     trace = soa.Self()->CreateInternalStackTrace<false>(soa);
   } else {
     // Suspend thread to build stack trace.
diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc
index fe3cbe7..a78909b 100644
--- a/runtime/native/dalvik_system_ZygoteHooks.cc
+++ b/runtime/native/dalvik_system_ZygoteHooks.cc
@@ -24,7 +24,7 @@
 #include "jit/jit.h"
 #include "jni_internal.h"
 #include "JNIHelp.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_thread_state_change-inl.h"
 #include "ScopedUtfChars.h"
 #include "thread-inl.h"
 #include "trace.h"
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index b6260e9..49eccd8 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -35,8 +35,8 @@
 #include "mirror/string-inl.h"
 #include "obj_ptr-inl.h"
 #include "reflection.h"
-#include "scoped_thread_state_change.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_thread_state_change-inl.h"
+#include "scoped_fast_native_object_access-inl.h"
 #include "ScopedLocalRef.h"
 #include "ScopedUtfChars.h"
 #include "utf.h"
@@ -44,10 +44,10 @@
 
 namespace art {
 
-ALWAYS_INLINE static inline mirror::Class* DecodeClass(
+ALWAYS_INLINE static inline ObjPtr<mirror::Class> DecodeClass(
     const ScopedFastNativeObjectAccess& soa, jobject java_class)
     REQUIRES_SHARED(Locks::mutator_lock_) {
-  mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
+  ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
   DCHECK(c != nullptr);
   DCHECK(c->IsClass());
   // TODO: we could EnsureInitialized here, rather than on every reflective get/set or invoke .
@@ -76,16 +76,19 @@
 
   std::string descriptor(DotToDescriptor(name.c_str()));
   StackHandleScope<2> hs(soa.Self());
-  Handle<mirror::ClassLoader> class_loader(hs.NewHandle(soa.Decode<mirror::ClassLoader*>(javaLoader)));
+  Handle<mirror::ClassLoader> class_loader(
+      hs.NewHandle(soa.Decode<mirror::ClassLoader>(javaLoader)));
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   Handle<mirror::Class> c(
       hs.NewHandle(class_linker->FindClass(soa.Self(), descriptor.c_str(), class_loader)));
   if (c.Get() == nullptr) {
     ScopedLocalRef<jthrowable> cause(env, env->ExceptionOccurred());
     env->ExceptionClear();
-    jthrowable cnfe = reinterpret_cast<jthrowable>(env->NewObject(WellKnownClasses::java_lang_ClassNotFoundException,
-                                                                  WellKnownClasses::java_lang_ClassNotFoundException_init,
-                                                                  javaName, cause.get()));
+    jthrowable cnfe = reinterpret_cast<jthrowable>(
+        env->NewObject(WellKnownClasses::java_lang_ClassNotFoundException,
+                       WellKnownClasses::java_lang_ClassNotFoundException_init,
+                       javaName,
+                       cause.get()));
     if (cnfe != nullptr) {
       // Make sure allocation didn't fail with an OOME.
       env->Throw(cnfe);
@@ -101,18 +104,18 @@
 static jstring Class_getNameNative(JNIEnv* env, jobject javaThis) {
   ScopedFastNativeObjectAccess soa(env);
   StackHandleScope<1> hs(soa.Self());
-  mirror::Class* const c = DecodeClass(soa, javaThis);
+  ObjPtr<mirror::Class> c = DecodeClass(soa, javaThis);
   return soa.AddLocalReference<jstring>(mirror::Class::ComputeName(hs.NewHandle(c)));
 }
 
 static jobjectArray Class_getProxyInterfaces(JNIEnv* env, jobject javaThis) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Class* c = DecodeClass(soa, javaThis);
+  ObjPtr<mirror::Class> c = DecodeClass(soa, javaThis);
   return soa.AddLocalReference<jobjectArray>(c->GetInterfaces()->Clone(soa.Self()));
 }
 
 static mirror::ObjectArray<mirror::Field>* GetDeclaredFields(
-    Thread* self, mirror::Class* klass, bool public_only, bool force_resolve)
+    Thread* self, ObjPtr<mirror::Class> klass, bool public_only, bool force_resolve)
       REQUIRES_SHARED(Locks::mutator_lock_) {
   StackHandleScope<1> hs(self);
   IterationRange<StrideIterator<ArtField>> ifields = klass->GetIFields();
@@ -192,8 +195,8 @@
 // Performs a binary search through an array of fields, TODO: Is this fast enough if we don't use
 // the dex cache for lookups? I think CompareModifiedUtf8ToUtf16AsCodePointValues should be fairly
 // fast.
-ALWAYS_INLINE static inline ArtField* FindFieldByName(
-    Thread* self ATTRIBUTE_UNUSED, mirror::String* name, LengthPrefixedArray<ArtField>* fields)
+ALWAYS_INLINE static inline ArtField* FindFieldByName(ObjPtr<mirror::String> name,
+                                                      LengthPrefixedArray<ArtField>* fields)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   if (fields == nullptr) {
     return nullptr;
@@ -237,14 +240,15 @@
   return nullptr;
 }
 
-ALWAYS_INLINE static inline mirror::Field* GetDeclaredField(
-    Thread* self, mirror::Class* c, mirror::String* name)
+ALWAYS_INLINE static inline mirror::Field* GetDeclaredField(Thread* self,
+                                                            ObjPtr<mirror::Class> c,
+                                                            ObjPtr<mirror::String> name)
     REQUIRES_SHARED(Locks::mutator_lock_) {
-  ArtField* art_field = FindFieldByName(self, name, c->GetIFieldsPtr());
+  ArtField* art_field = FindFieldByName(name, c->GetIFieldsPtr());
   if (art_field != nullptr) {
     return mirror::Field::CreateFromArtField<kRuntimePointerSize>(self, art_field, true);
   }
-  art_field = FindFieldByName(self, name, c->GetSFieldsPtr());
+  art_field = FindFieldByName(name, c->GetSFieldsPtr());
   if (art_field != nullptr) {
     return mirror::Field::CreateFromArtField<kRuntimePointerSize>(self, art_field, true);
   }
@@ -252,7 +256,7 @@
 }
 
 static mirror::Field* GetPublicFieldRecursive(
-    Thread* self, mirror::Class* clazz, mirror::String* name)
+    Thread* self, ObjPtr<mirror::Class> clazz, ObjPtr<mirror::String> name)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   DCHECK(clazz != nullptr);
   DCHECK(name != nullptr);
@@ -302,7 +306,7 @@
 
 static jobject Class_getPublicFieldRecursive(JNIEnv* env, jobject javaThis, jstring name) {
   ScopedFastNativeObjectAccess soa(env);
-  auto* name_string = soa.Decode<mirror::String*>(name);
+  auto name_string = soa.Decode<mirror::String>(name);
   if (UNLIKELY(name_string == nullptr)) {
     ThrowNullPointerException("name == null");
     return nullptr;
@@ -313,13 +317,13 @@
 
 static jobject Class_getDeclaredField(JNIEnv* env, jobject javaThis, jstring name) {
   ScopedFastNativeObjectAccess soa(env);
-  auto* name_string = soa.Decode<mirror::String*>(name);
+  auto name_string = soa.Decode<mirror::String>(name);
   if (name_string == nullptr) {
     ThrowNullPointerException("name == null");
     return nullptr;
   }
-  auto* klass = DecodeClass(soa, javaThis);
-  mirror::Field* result = GetDeclaredField(soa.Self(), klass, name_string);
+  ObjPtr<mirror::Class> klass = DecodeClass(soa, javaThis);
+  ObjPtr<mirror::Field> result = GetDeclaredField(soa.Self(), klass, name_string);
   if (result == nullptr) {
     std::string name_str = name_string->ToModifiedUtf8();
     if (name_str == "value" && klass->IsStringClass()) {
@@ -333,7 +337,7 @@
     }
     // We may have a pending exception if we failed to resolve.
     if (!soa.Self()->IsExceptionPending()) {
-      ThrowNoSuchFieldException(DecodeClass(soa, javaThis), name_str.c_str());
+      ThrowNoSuchFieldException(DecodeClass(soa, javaThis).Decode(), name_str.c_str());
     }
     return nullptr;
   }
@@ -345,11 +349,11 @@
   ScopedFastNativeObjectAccess soa(env);
   DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), kRuntimePointerSize);
   DCHECK(!Runtime::Current()->IsActiveTransaction());
-  mirror::Constructor* result = mirror::Class::GetDeclaredConstructorInternal<kRuntimePointerSize,
-                                                                              false>(
+  ObjPtr<mirror::Constructor> result =
+      mirror::Class::GetDeclaredConstructorInternal<kRuntimePointerSize, false>(
       soa.Self(),
-      DecodeClass(soa, javaThis),
-      soa.Decode<mirror::ObjectArray<mirror::Class>*>(args));
+      DecodeClass(soa, javaThis).Decode(),
+      soa.Decode<mirror::ObjectArray<mirror::Class>>(args).Decode());
   return soa.AddLocalReference<jobject>(result);
 }
 
@@ -399,9 +403,9 @@
   DCHECK(!Runtime::Current()->IsActiveTransaction());
   mirror::Method* result = mirror::Class::GetDeclaredMethodInternal<kRuntimePointerSize, false>(
       soa.Self(),
-      DecodeClass(soa, javaThis),
-      soa.Decode<mirror::String*>(name),
-      soa.Decode<mirror::ObjectArray<mirror::Class>*>(args));
+      DecodeClass(soa, javaThis).Decode(),
+      soa.Decode<mirror::String>(name).Decode(),
+      soa.Decode<mirror::ObjectArray<mirror::Class>>(args).Decode());
   return soa.AddLocalReference<jobject>(result);
 }
 
@@ -454,7 +458,7 @@
   if (klass->IsProxyClass() || klass->GetDexCache() == nullptr) {
     return nullptr;
   }
-  Handle<mirror::Class> annotation_class(hs.NewHandle(soa.Decode<mirror::Class*>(annotationClass)));
+  Handle<mirror::Class> annotation_class(hs.NewHandle(soa.Decode<mirror::Class>(annotationClass)));
   return soa.AddLocalReference<jobject>(
       annotations::GetAnnotationForClass(klass, annotation_class));
 }
@@ -465,10 +469,12 @@
   Handle<mirror::Class> klass(hs.NewHandle(DecodeClass(soa, javaThis)));
   if (klass->IsProxyClass() || klass->GetDexCache() == nullptr) {
     // Return an empty array instead of a null pointer.
-    mirror::Class* annotation_array_class =
-        soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_annotation_Annotation__array);
+    ObjPtr<mirror::Class>  annotation_array_class =
+        soa.Decode<mirror::Class>(WellKnownClasses::java_lang_annotation_Annotation__array);
     mirror::ObjectArray<mirror::Object>* empty_array =
-        mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), annotation_array_class, 0);
+        mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(),
+                                                   annotation_array_class.Decode(),
+                                                   0);
     return soa.AddLocalReference<jobjectArray>(empty_array);
   }
   return soa.AddLocalReference<jobjectArray>(annotations::GetAnnotationsForClass(klass));
@@ -520,8 +526,8 @@
   }
   mirror::Object* method = annotations::GetEnclosingMethod(klass);
   if (method != nullptr) {
-    if (method->GetClass() ==
-        soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Constructor)) {
+    if (soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Constructor) ==
+        method->GetClass()) {
       return soa.AddLocalReference<jobject>(method);
     }
   }
@@ -537,8 +543,8 @@
   }
   mirror::Object* method = annotations::GetEnclosingMethod(klass);
   if (method != nullptr) {
-    if (method->GetClass() ==
-        soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Method)) {
+    if (soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Method) ==
+        method->GetClass()) {
       return soa.AddLocalReference<jobject>(method);
     }
   }
@@ -599,7 +605,7 @@
   if (klass->IsProxyClass() || klass->GetDexCache() == nullptr) {
     return false;
   }
-  Handle<mirror::Class> annotation_class(hs.NewHandle(soa.Decode<mirror::Class*>(annotationType)));
+  Handle<mirror::Class> annotation_class(hs.NewHandle(soa.Decode<mirror::Class>(annotationType)));
   return annotations::IsClassAnnotationPresent(klass, annotation_class);
 }
 
diff --git a/runtime/native/java_lang_DexCache.cc b/runtime/native/java_lang_DexCache.cc
index f0140a3..5efafe7 100644
--- a/runtime/native/java_lang_DexCache.cc
+++ b/runtime/native/java_lang_DexCache.cc
@@ -21,14 +21,14 @@
 #include "mirror/class-inl.h"
 #include "mirror/dex_cache-inl.h"
 #include "mirror/object-inl.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
 #include "well_known_classes.h"
 
 namespace art {
 
 static jobject DexCache_getDexNative(JNIEnv* env, jobject javaDexCache) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::DexCache* dex_cache = soa.Decode<mirror::DexCache*>(javaDexCache);
+  ObjPtr<mirror::DexCache> dex_cache = soa.Decode<mirror::DexCache>(javaDexCache);
   // Should only be called while holding the lock on the dex cache.
   DCHECK_EQ(dex_cache->GetLockOwnerThreadId(), soa.Self()->GetThreadId());
   const DexFile* dex_file = dex_cache->GetDexFile();
@@ -51,14 +51,14 @@
 
 static jobject DexCache_getResolvedType(JNIEnv* env, jobject javaDexCache, jint type_index) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::DexCache* dex_cache = soa.Decode<mirror::DexCache*>(javaDexCache);
+  ObjPtr<mirror::DexCache> dex_cache = soa.Decode<mirror::DexCache>(javaDexCache);
   CHECK_LT(static_cast<size_t>(type_index), dex_cache->NumResolvedTypes());
   return soa.AddLocalReference<jobject>(dex_cache->GetResolvedType(type_index));
 }
 
 static jobject DexCache_getResolvedString(JNIEnv* env, jobject javaDexCache, jint string_index) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::DexCache* dex_cache = soa.Decode<mirror::DexCache*>(javaDexCache);
+  ObjPtr<mirror::DexCache> dex_cache = soa.Decode<mirror::DexCache>(javaDexCache);
   CHECK_LT(static_cast<size_t>(string_index), dex_cache->GetDexFile()->NumStringIds());
   return soa.AddLocalReference<jobject>(dex_cache->GetResolvedString(string_index));
 }
@@ -66,17 +66,17 @@
 static void DexCache_setResolvedType(JNIEnv* env, jobject javaDexCache, jint type_index,
                                      jobject type) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::DexCache* dex_cache = soa.Decode<mirror::DexCache*>(javaDexCache);
+  ObjPtr<mirror::DexCache> dex_cache = soa.Decode<mirror::DexCache>(javaDexCache);
   CHECK_LT(static_cast<size_t>(type_index), dex_cache->NumResolvedTypes());
-  dex_cache->SetResolvedType(type_index, soa.Decode<mirror::Class*>(type));
+  dex_cache->SetResolvedType(type_index, soa.Decode<mirror::Class>(type).Decode());
 }
 
 static void DexCache_setResolvedString(JNIEnv* env, jobject javaDexCache, jint string_index,
                                        jobject string) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::DexCache* dex_cache = soa.Decode<mirror::DexCache*>(javaDexCache);
+  ObjPtr<mirror::DexCache> dex_cache = soa.Decode<mirror::DexCache>(javaDexCache);
   CHECK_LT(static_cast<size_t>(string_index), dex_cache->GetDexFile()->NumStringIds());
-  dex_cache->SetResolvedString(string_index, soa.Decode<mirror::String*>(string));
+  dex_cache->SetResolvedString(string_index, soa.Decode<mirror::String>(string).Decode());
 }
 
 static JNINativeMethod gMethods[] = {
diff --git a/runtime/native/java_lang_Object.cc b/runtime/native/java_lang_Object.cc
index 2a36059..6493865 100644
--- a/runtime/native/java_lang_Object.cc
+++ b/runtime/native/java_lang_Object.cc
@@ -18,39 +18,35 @@
 
 #include "jni_internal.h"
 #include "mirror/object-inl.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
 
 
 namespace art {
 
 static jobject Object_internalClone(JNIEnv* env, jobject java_this) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Object* o = soa.Decode<mirror::Object*>(java_this);
+  ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_this);
   return soa.AddLocalReference<jobject>(o->Clone(soa.Self()));
 }
 
 static void Object_notify(JNIEnv* env, jobject java_this) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Object* o = soa.Decode<mirror::Object*>(java_this);
-  o->Notify(soa.Self());
+  soa.Decode<mirror::Object>(java_this)->Notify(soa.Self());
 }
 
 static void Object_notifyAll(JNIEnv* env, jobject java_this) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Object* o = soa.Decode<mirror::Object*>(java_this);
-  o->NotifyAll(soa.Self());
+  soa.Decode<mirror::Object>(java_this)->NotifyAll(soa.Self());
 }
 
 static void Object_wait(JNIEnv* env, jobject java_this) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Object* o = soa.Decode<mirror::Object*>(java_this);
-  o->Wait(soa.Self());
+  soa.Decode<mirror::Object>(java_this)->Wait(soa.Self());
 }
 
 static void Object_waitJI(JNIEnv* env, jobject java_this, jlong ms, jint ns) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Object* o = soa.Decode<mirror::Object*>(java_this);
-  o->Wait(soa.Self(), ms, ns);
+  soa.Decode<mirror::Object>(java_this)->Wait(soa.Self(), ms, ns);
 }
 
 static JNINativeMethod gMethods[] = {
diff --git a/runtime/native/java_lang_String.cc b/runtime/native/java_lang_String.cc
index aa64b79..b3a967d 100644
--- a/runtime/native/java_lang_String.cc
+++ b/runtime/native/java_lang_String.cc
@@ -22,8 +22,8 @@
 #include "mirror/object-inl.h"
 #include "mirror/string.h"
 #include "mirror/string-inl.h"
-#include "scoped_fast_native_object_access.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_fast_native_object_access-inl.h"
+#include "scoped_thread_state_change-inl.h"
 #include "ScopedLocalRef.h"
 #include "verify_object-inl.h"
 
@@ -31,7 +31,7 @@
 
 static jchar String_charAt(JNIEnv* env, jobject java_this, jint index) {
   ScopedFastNativeObjectAccess soa(env);
-  return soa.Decode<mirror::String*>(java_this)->CharAt(index);
+  return soa.Decode<mirror::String>(java_this)->CharAt(index);
 }
 
 static jint String_compareTo(JNIEnv* env, jobject java_this, jobject java_rhs) {
@@ -40,7 +40,8 @@
     ThrowNullPointerException("rhs == null");
     return -1;
   } else {
-    return soa.Decode<mirror::String*>(java_this)->CompareTo(soa.Decode<mirror::String*>(java_rhs));
+    return soa.Decode<mirror::String>(java_this)->CompareTo(
+        soa.Decode<mirror::String>(java_rhs).Decode());
   }
 }
 
@@ -51,8 +52,8 @@
     return nullptr;
   }
   StackHandleScope<2> hs(soa.Self());
-  Handle<mirror::String> string_this(hs.NewHandle(soa.Decode<mirror::String*>(java_this)));
-  Handle<mirror::String> string_arg(hs.NewHandle(soa.Decode<mirror::String*>(java_string_arg)));
+  Handle<mirror::String> string_this(hs.NewHandle(soa.Decode<mirror::String>(java_this)));
+  Handle<mirror::String> string_arg(hs.NewHandle(soa.Decode<mirror::String>(java_string_arg)));
   int32_t length_this = string_this->GetLength();
   int32_t length_arg = string_arg->GetLength();
   if (length_arg > 0 && length_this > 0) {
@@ -67,13 +68,13 @@
   ScopedFastNativeObjectAccess soa(env);
   // This method does not handle supplementary characters. They're dealt with in managed code.
   DCHECK_LE(ch, 0xffff);
-  return soa.Decode<mirror::String*>(java_this)->FastIndexOf(ch, start);
+  return soa.Decode<mirror::String>(java_this)->FastIndexOf(ch, start);
 }
 
 static jstring String_fastSubstring(JNIEnv* env, jobject java_this, jint start, jint length) {
   ScopedFastNativeObjectAccess soa(env);
   StackHandleScope<1> hs(soa.Self());
-  Handle<mirror::String> string_this(hs.NewHandle(soa.Decode<mirror::String*>(java_this)));
+  Handle<mirror::String> string_this(hs.NewHandle(soa.Decode<mirror::String>(java_this)));
   gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
   mirror::String* result = mirror::String::AllocFromString<true>(soa.Self(), length, string_this,
                                                                  start, allocator_type);
@@ -84,25 +85,24 @@
                                    jcharArray buffer, jint index) {
   ScopedFastNativeObjectAccess soa(env);
   StackHandleScope<1> hs(soa.Self());
-  Handle<mirror::CharArray> char_array(hs.NewHandle(soa.Decode<mirror::CharArray*>(buffer)));
-  soa.Decode<mirror::String*>(java_this)->GetChars(start, end, char_array, index);
+  Handle<mirror::CharArray> char_array(hs.NewHandle(soa.Decode<mirror::CharArray>(buffer)));
+  soa.Decode<mirror::String>(java_this)->GetChars(start, end, char_array, index);
 }
 
 static jstring String_intern(JNIEnv* env, jobject java_this) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::String* s = soa.Decode<mirror::String*>(java_this);
-  mirror::String* result = s->Intern();
+  ObjPtr<mirror::String> result = soa.Decode<mirror::String>(java_this)->Intern();
   return soa.AddLocalReference<jstring>(result);
 }
 
 static void String_setCharAt(JNIEnv* env, jobject java_this, jint index, jchar c) {
   ScopedFastNativeObjectAccess soa(env);
-  soa.Decode<mirror::String*>(java_this)->SetCharAt(index, c);
+  soa.Decode<mirror::String>(java_this)->SetCharAt(index, c);
 }
 
 static jcharArray String_toCharArray(JNIEnv* env, jobject java_this) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::String* s = soa.Decode<mirror::String*>(java_this);
+  ObjPtr<mirror::String> s = soa.Decode<mirror::String>(java_this);
   return soa.AddLocalReference<jcharArray>(s->ToCharArray(soa.Self()));
 }
 
diff --git a/runtime/native/java_lang_StringFactory.cc b/runtime/native/java_lang_StringFactory.cc
index 5a219ef..119f2b8 100644
--- a/runtime/native/java_lang_StringFactory.cc
+++ b/runtime/native/java_lang_StringFactory.cc
@@ -20,8 +20,8 @@
 #include "jni_internal.h"
 #include "mirror/object-inl.h"
 #include "mirror/string.h"
-#include "scoped_fast_native_object_access.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_fast_native_object_access-inl.h"
+#include "scoped_thread_state_change-inl.h"
 #include "ScopedLocalRef.h"
 #include "ScopedPrimitiveArray.h"
 
@@ -35,7 +35,7 @@
     return nullptr;
   }
   StackHandleScope<1> hs(soa.Self());
-  Handle<mirror::ByteArray> byte_array(hs.NewHandle(soa.Decode<mirror::ByteArray*>(java_data)));
+  Handle<mirror::ByteArray> byte_array(hs.NewHandle(soa.Decode<mirror::ByteArray>(java_data)));
   int32_t data_size = byte_array->GetLength();
   if ((offset | byte_count) < 0 || byte_count > data_size - offset) {
     soa.Self()->ThrowNewExceptionF("Ljava/lang/StringIndexOutOfBoundsException;",
@@ -56,7 +56,7 @@
   DCHECK(java_data != nullptr);
   ScopedFastNativeObjectAccess soa(env);
   StackHandleScope<1> hs(soa.Self());
-  Handle<mirror::CharArray> char_array(hs.NewHandle(soa.Decode<mirror::CharArray*>(java_data)));
+  Handle<mirror::CharArray> char_array(hs.NewHandle(soa.Decode<mirror::CharArray>(java_data)));
   gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
   mirror::String* result = mirror::String::AllocFromCharArray<true>(soa.Self(), char_count,
                                                                     char_array, offset,
@@ -71,7 +71,7 @@
     return nullptr;
   }
   StackHandleScope<1> hs(soa.Self());
-  Handle<mirror::String> string(hs.NewHandle(soa.Decode<mirror::String*>(to_copy)));
+  Handle<mirror::String> string(hs.NewHandle(soa.Decode<mirror::String>(to_copy)));
   gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
   mirror::String* result = mirror::String::AllocFromString<true>(soa.Self(), string->GetLength(),
                                                                  string, 0, allocator_type);
diff --git a/runtime/native/java_lang_System.cc b/runtime/native/java_lang_System.cc
index 1b399aa..8b9d0c7 100644
--- a/runtime/native/java_lang_System.cc
+++ b/runtime/native/java_lang_System.cc
@@ -24,7 +24,7 @@
 #include "mirror/class-inl.h"
 #include "mirror/object-inl.h"
 #include "mirror/object_array-inl.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
 
 namespace art {
 
@@ -60,14 +60,14 @@
   }
 
   // Make sure source and destination are both arrays.
-  mirror::Object* srcObject = soa.Decode<mirror::Object*>(javaSrc);
+  ObjPtr<mirror::Object> srcObject = soa.Decode<mirror::Object>(javaSrc);
   if (UNLIKELY(!srcObject->IsArrayInstance())) {
-    ThrowArrayStoreException_NotAnArray("source", srcObject);
+    ThrowArrayStoreException_NotAnArray("source", srcObject.Decode());
     return;
   }
-  mirror::Object* dstObject = soa.Decode<mirror::Object*>(javaDst);
+  ObjPtr<mirror::Object> dstObject = soa.Decode<mirror::Object>(javaDst);
   if (UNLIKELY(!dstObject->IsArrayInstance())) {
-    ThrowArrayStoreException_NotAnArray("destination", dstObject);
+    ThrowArrayStoreException_NotAnArray("destination", dstObject.Decode());
     return;
   }
   mirror::Array* srcArray = srcObject->AsArray();
@@ -164,8 +164,8 @@
 inline void System_arraycopyTUnchecked(JNIEnv* env, jobject javaSrc, jint srcPos,
                                        jobject javaDst, jint dstPos, jint count) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Object* srcObject = soa.Decode<mirror::Object*>(javaSrc);
-  mirror::Object* dstObject = soa.Decode<mirror::Object*>(javaDst);
+  ObjPtr<mirror::Object> srcObject = soa.Decode<mirror::Object>(javaSrc);
+  ObjPtr<mirror::Object> dstObject = soa.Decode<mirror::Object>(javaDst);
   DCHECK(dstObject != nullptr);
   mirror::Array* srcArray = srcObject->AsArray();
   mirror::Array* dstArray = dstObject->AsArray();
@@ -228,7 +228,7 @@
     return 0;
   }
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Object* o = soa.Decode<mirror::Object*>(javaObject);
+  ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(javaObject);
   return static_cast<jint>(o->IdentityHashCode());
 }
 
diff --git a/runtime/native/java_lang_Thread.cc b/runtime/native/java_lang_Thread.cc
index a742e81..0635261 100644
--- a/runtime/native/java_lang_Thread.cc
+++ b/runtime/native/java_lang_Thread.cc
@@ -20,8 +20,8 @@
 #include "jni_internal.h"
 #include "monitor.h"
 #include "mirror/object.h"
-#include "scoped_fast_native_object_access.h"
-#include "scoped_thread_state_change.h"
+#include "scoped_fast_native_object_access-inl.h"
+#include "scoped_thread_state_change-inl.h"
 #include "ScopedUtfChars.h"
 #include "thread.h"
 #include "thread_list.h"
@@ -109,14 +109,14 @@
 
 static jboolean Thread_nativeHoldsLock(JNIEnv* env, jobject java_thread, jobject java_object) {
   ScopedObjectAccess soa(env);
-  mirror::Object* object = soa.Decode<mirror::Object*>(java_object);
+  ObjPtr<mirror::Object> object = soa.Decode<mirror::Object>(java_object);
   if (object == nullptr) {
     ThrowNullPointerException("object == null");
     return JNI_FALSE;
   }
   MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
   Thread* thread = Thread::FromManagedThread(soa, java_thread);
-  return thread->HoldsLock(object);
+  return thread->HoldsLock(object.Decode());
 }
 
 static void Thread_nativeInterrupt(JNIEnv* env, jobject java_thread) {
@@ -132,7 +132,7 @@
   ScopedUtfChars name(env, java_name);
   {
     ScopedObjectAccess soa(env);
-    if (soa.Decode<mirror::Object*>(peer) == soa.Self()->GetPeer()) {
+    if (soa.Decode<mirror::Object>(peer) == soa.Self()->GetPeer()) {
       soa.Self()->SetThreadName(name.c_str());
       return;
     }
@@ -172,8 +172,8 @@
 
 static void Thread_sleep(JNIEnv* env, jclass, jobject java_lock, jlong ms, jint ns) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Object* lock = soa.Decode<mirror::Object*>(java_lock);
-  Monitor::Wait(Thread::Current(), lock, ms, ns, true, kSleeping);
+  ObjPtr<mirror::Object> lock = soa.Decode<mirror::Object>(java_lock);
+  Monitor::Wait(Thread::Current(), lock.Decode(), ms, ns, true, kSleeping);
 }
 
 /*
diff --git a/runtime/native/java_lang_Throwable.cc b/runtime/native/java_lang_Throwable.cc
index cb8a869..ff3e044 100644
--- a/runtime/native/java_lang_Throwable.cc
+++ b/runtime/native/java_lang_Throwable.cc
@@ -17,7 +17,7 @@
 #include "java_lang_Throwable.h"
 
 #include "jni_internal.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
 #include "thread.h"
 
 namespace art {
diff --git a/runtime/native/java_lang_VMClassLoader.cc b/runtime/native/java_lang_VMClassLoader.cc
index 6f735aa..0694c4d 100644
--- a/runtime/native/java_lang_VMClassLoader.cc
+++ b/runtime/native/java_lang_VMClassLoader.cc
@@ -20,7 +20,7 @@
 #include "jni_internal.h"
 #include "mirror/class_loader.h"
 #include "mirror/object-inl.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
 #include "ScopedUtfChars.h"
 #include "zip_archive.h"
 
@@ -29,7 +29,7 @@
 static jclass VMClassLoader_findLoadedClass(JNIEnv* env, jclass, jobject javaLoader,
                                             jstring javaName) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::ClassLoader* loader = soa.Decode<mirror::ClassLoader*>(javaLoader);
+  ObjPtr<mirror::ClassLoader> loader = soa.Decode<mirror::ClassLoader>(javaLoader);
   ScopedUtfChars name(env, javaName);
   if (name.c_str() == nullptr) {
     return nullptr;
@@ -37,7 +37,10 @@
   ClassLinker* cl = Runtime::Current()->GetClassLinker();
   std::string descriptor(DotToDescriptor(name.c_str()));
   const size_t descriptor_hash = ComputeModifiedUtf8Hash(descriptor.c_str());
-  mirror::Class* c = cl->LookupClass(soa.Self(), descriptor.c_str(), descriptor_hash, loader);
+  mirror::Class* c = cl->LookupClass(soa.Self(),
+                                     descriptor.c_str(),
+                                     descriptor_hash,
+                                     loader.Decode());
   if (c != nullptr && c->IsResolved()) {
     return soa.AddLocalReference<jclass>(c);
   }
diff --git a/runtime/native/java_lang_ref_FinalizerReference.cc b/runtime/native/java_lang_ref_FinalizerReference.cc
index 0532c35..08bcc38 100644
--- a/runtime/native/java_lang_ref_FinalizerReference.cc
+++ b/runtime/native/java_lang_ref_FinalizerReference.cc
@@ -21,14 +21,15 @@
 #include "jni_internal.h"
 #include "mirror/object-inl.h"
 #include "mirror/reference-inl.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
 
 namespace art {
 
 static jboolean FinalizerReference_makeCircularListIfUnenqueued(JNIEnv* env, jobject javaThis) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::FinalizerReference* const ref = soa.Decode<mirror::FinalizerReference*>(javaThis);
-  return Runtime::Current()->GetHeap()->GetReferenceProcessor()->MakeCircularListIfUnenqueued(ref);
+  ObjPtr<mirror::FinalizerReference> ref = soa.Decode<mirror::FinalizerReference>(javaThis);
+  return Runtime::Current()->GetHeap()->GetReferenceProcessor()->MakeCircularListIfUnenqueued(
+      ref.Decode());
 }
 
 static JNINativeMethod gMethods[] = {
diff --git a/runtime/native/java_lang_ref_Reference.cc b/runtime/native/java_lang_ref_Reference.cc
index d232059..9a088ed 100644
--- a/runtime/native/java_lang_ref_Reference.cc
+++ b/runtime/native/java_lang_ref_Reference.cc
@@ -21,15 +21,15 @@
 #include "jni_internal.h"
 #include "mirror/object-inl.h"
 #include "mirror/reference-inl.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
 
 namespace art {
 
 static jobject Reference_getReferent(JNIEnv* env, jobject javaThis) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Reference* const ref = soa.Decode<mirror::Reference*>(javaThis);
+  ObjPtr<mirror::Reference> ref = soa.Decode<mirror::Reference>(javaThis);
   mirror::Object* const referent =
-      Runtime::Current()->GetHeap()->GetReferenceProcessor()->GetReferent(soa.Self(), ref);
+      Runtime::Current()->GetHeap()->GetReferenceProcessor()->GetReferent(soa.Self(), ref.Decode());
   return soa.AddLocalReference<jobject>(referent);
 }
 
diff --git a/runtime/native/java_lang_reflect_Array.cc b/runtime/native/java_lang_reflect_Array.cc
index beb953b..3718ce8 100644
--- a/runtime/native/java_lang_reflect_Array.cc
+++ b/runtime/native/java_lang_reflect_Array.cc
@@ -22,7 +22,7 @@
 #include "jni_internal.h"
 #include "mirror/class-inl.h"
 #include "mirror/object-inl.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
 #include "handle_scope-inl.h"
 
 namespace art {
@@ -32,15 +32,15 @@
   ScopedFastNativeObjectAccess soa(env);
   DCHECK(javaElementClass != nullptr);
   StackHandleScope<2> hs(soa.Self());
-  Handle<mirror::Class> element_class(hs.NewHandle(soa.Decode<mirror::Class*>(javaElementClass)));
+  Handle<mirror::Class> element_class(hs.NewHandle(soa.Decode<mirror::Class>(javaElementClass)));
   DCHECK(element_class->IsClass());
   DCHECK(javaDimArray != nullptr);
-  mirror::Object* dimensions_obj = soa.Decode<mirror::Object*>(javaDimArray);
+  ObjPtr<mirror::Object> dimensions_obj = soa.Decode<mirror::Object>(javaDimArray);
   DCHECK(dimensions_obj->IsArrayInstance());
   DCHECK_EQ(dimensions_obj->GetClass()->GetComponentType()->GetPrimitiveType(),
             Primitive::kPrimInt);
   Handle<mirror::IntArray> dimensions_array(
-      hs.NewHandle(down_cast<mirror::IntArray*>(dimensions_obj)));
+      hs.NewHandle(down_cast<mirror::IntArray*>(dimensions_obj.Decode())));
   mirror::Array* new_array = mirror::Array::CreateMultiArray(soa.Self(), element_class,
                                                              dimensions_array);
   return soa.AddLocalReference<jobject>(new_array);
@@ -53,7 +53,7 @@
     ThrowNegativeArraySizeException(length);
     return nullptr;
   }
-  mirror::Class* element_class = soa.Decode<mirror::Class*>(javaElementClass);
+  mirror::Class* element_class = soa.Decode<mirror::Class>(javaElementClass).Decode();
   Runtime* runtime = Runtime::Current();
   ClassLinker* class_linker = runtime->GetClassLinker();
   mirror::Class* array_class = class_linker->FindArrayClass(soa.Self(), &element_class);
diff --git a/runtime/native/java_lang_reflect_Constructor.cc b/runtime/native/java_lang_reflect_Constructor.cc
index 47c49d5..7de0147 100644
--- a/runtime/native/java_lang_reflect_Constructor.cc
+++ b/runtime/native/java_lang_reflect_Constructor.cc
@@ -26,7 +26,7 @@
 #include "mirror/method.h"
 #include "mirror/object-inl.h"
 #include "reflection.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
 #include "well_known_classes.h"
 
 namespace art {
@@ -60,7 +60,7 @@
  */
 static jobject Constructor_newInstance0(JNIEnv* env, jobject javaMethod, jobjectArray javaArgs) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Constructor* m = soa.Decode<mirror::Constructor*>(javaMethod);
+  ObjPtr<mirror::Constructor> m = soa.Decode<mirror::Constructor>(javaMethod);
   StackHandleScope<1> hs(soa.Self());
   Handle<mirror::Class> c(hs.NewHandle(m->GetDeclaringClass()));
   if (UNLIKELY(c->IsAbstract())) {
diff --git a/runtime/native/java_lang_reflect_Executable.cc b/runtime/native/java_lang_reflect_Executable.cc
index f345c09..c7c8008 100644
--- a/runtime/native/java_lang_reflect_Executable.cc
+++ b/runtime/native/java_lang_reflect_Executable.cc
@@ -25,7 +25,7 @@
 #include "mirror/object-inl.h"
 #include "mirror/object_array-inl.h"
 #include "reflection.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
 #include "well_known_classes.h"
 
 namespace art {
@@ -35,10 +35,10 @@
   ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod);
   if (method->GetDeclaringClass()->IsProxyClass()) {
     // Return an empty array instead of a null pointer.
-    mirror::Class* annotation_array_class =
-        soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_annotation_Annotation__array);
-    mirror::ObjectArray<mirror::Object>* empty_array =
-        mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), annotation_array_class, 0);
+    ObjPtr<mirror::Class> annotation_array_class =
+        soa.Decode<mirror::Class>(WellKnownClasses::java_lang_annotation_Annotation__array);
+    ObjPtr<mirror::ObjectArray<mirror::Object>> empty_array =
+        mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), annotation_array_class.Decode(), 0);
     return soa.AddLocalReference<jobjectArray>(empty_array);
   }
   return soa.AddLocalReference<jobjectArray>(annotations::GetAnnotationsForMethod(method));
@@ -53,7 +53,7 @@
   if (method->IsProxyMethod()) {
     return nullptr;
   } else {
-    Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class*>(annotationType)));
+    Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class>(annotationType)));
     return soa.AddLocalReference<jobject>(annotations::GetAnnotationForMethod(method, klass));
   }
 }
@@ -84,7 +84,7 @@
   Thread* self = soa.Self();
   StackHandleScope<8> hs(self);
 
-  Handle<mirror::Method> executable = hs.NewHandle(soa.Decode<mirror::Method*>(javaMethod));
+  Handle<mirror::Method> executable = hs.NewHandle(soa.Decode<mirror::Method>(javaMethod));
   ArtMethod* art_method = executable.Get()->GetArtMethod();
   if (art_method->GetDeclaringClass()->IsProxyClass()) {
     return nullptr;
@@ -122,7 +122,7 @@
   // Instantiate a Parameter[] to hold the result.
   Handle<mirror::Class> parameter_array_class =
       hs.NewHandle(
-          soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Parameter__array));
+          soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Parameter__array));
   Handle<mirror::ObjectArray<mirror::Object>> parameter_array =
       hs.NewHandle(
           mirror::ObjectArray<mirror::Object>::Alloc(self,
@@ -134,7 +134,7 @@
   }
 
   Handle<mirror::Class> parameter_class =
-      hs.NewHandle(soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Parameter));
+      hs.NewHandle(soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Parameter));
   ArtMethod* parameter_init =
       soa.DecodeMethod(WellKnownClasses::java_lang_reflect_Parameter_init);
 
@@ -186,7 +186,7 @@
     return false;
   }
   StackHandleScope<1> hs(soa.Self());
-  Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class*>(annotationType)));
+  Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class>(annotationType)));
   return annotations::IsMethodAnnotationPresent(method, klass);
 }
 
diff --git a/runtime/native/java_lang_reflect_Field.cc b/runtime/native/java_lang_reflect_Field.cc
index dab510d..2519225 100644
--- a/runtime/native/java_lang_reflect_Field.cc
+++ b/runtime/native/java_lang_reflect_Field.cc
@@ -25,7 +25,7 @@
 #include "mirror/class-inl.h"
 #include "mirror/field.h"
 #include "reflection-inl.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
 #include "utils.h"
 
 namespace art {
@@ -127,7 +127,7 @@
     *class_or_rcvr = declaringClass;
     return true;
   }
-  *class_or_rcvr = soa.Decode<mirror::Object*>(j_rcvr);
+  *class_or_rcvr = soa.Decode<mirror::Object>(j_rcvr).Decode();
   if (!VerifyObjectIsClass(MakeObjPtr(*class_or_rcvr), MakeObjPtr(declaringClass))) {
     DCHECK(soa.Self()->IsExceptionPending());
     return false;
@@ -137,7 +137,7 @@
 
 static jobject Field_get(JNIEnv* env, jobject javaField, jobject javaObj) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Field* f = soa.Decode<mirror::Field*>(javaField);
+  mirror::Field* f = soa.Decode<mirror::Field>(javaField).Decode();
   mirror::Object* o = nullptr;
   if (!CheckReceiver(soa, javaObj, &f, &o)) {
     DCHECK(soa.Self()->IsExceptionPending());
@@ -163,7 +163,7 @@
 ALWAYS_INLINE inline static JValue GetPrimitiveField(JNIEnv* env, jobject javaField,
                                                      jobject javaObj) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Field* f = soa.Decode<mirror::Field*>(javaField);
+  mirror::Field* f = soa.Decode<mirror::Field>(javaField).Decode();
   mirror::Object* o = nullptr;
   if (!CheckReceiver(soa, javaObj, &f, &o)) {
     DCHECK(soa.Self()->IsExceptionPending());
@@ -307,7 +307,7 @@
 
 static void Field_set(JNIEnv* env, jobject javaField, jobject javaObj, jobject javaValue) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Field* f = soa.Decode<mirror::Field*>(javaField);
+  mirror::Field* f = soa.Decode<mirror::Field>(javaField).Decode();
   // Check that the receiver is non-null and an instance of the field's declaring class.
   mirror::Object* o = nullptr;
   if (!CheckReceiver(soa, javaObj, &f, &o)) {
@@ -325,9 +325,9 @@
   }
   // We now don't expect suspension unless an exception is thrown.
   // Unbox the value, if necessary.
-  mirror::Object* boxed_value = soa.Decode<mirror::Object*>(javaValue);
+  ObjPtr<mirror::Object> boxed_value = soa.Decode<mirror::Object>(javaValue);
   JValue unboxed_value;
-  if (!UnboxPrimitiveForField(MakeObjPtr(boxed_value),
+  if (!UnboxPrimitiveForField(boxed_value,
                               MakeObjPtr(field_type),
                               f->GetArtField(),
                               &unboxed_value)) {
@@ -346,7 +346,7 @@
 static void SetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj,
                               const JValue& new_value) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Field* f = soa.Decode<mirror::Field*>(javaField);
+  mirror::Field* f = soa.Decode<mirror::Field>(javaField).Decode();
   mirror::Object* o = nullptr;
   if (!CheckReceiver(soa, javaObj, &f, &o)) {
     return;
@@ -426,21 +426,22 @@
 static jobject Field_getAnnotationNative(JNIEnv* env, jobject javaField, jclass annotationType) {
   ScopedFastNativeObjectAccess soa(env);
   StackHandleScope<1> hs(soa.Self());
-  ArtField* field = soa.Decode<mirror::Field*>(javaField)->GetArtField();
+  ArtField* field = soa.Decode<mirror::Field>(javaField)->GetArtField();
   if (field->GetDeclaringClass()->IsProxyClass()) {
     return nullptr;
   }
-  Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class*>(annotationType)));
+  Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class>(annotationType)));
   return soa.AddLocalReference<jobject>(annotations::GetAnnotationForField(field, klass));
 }
 
 static jobjectArray Field_getDeclaredAnnotations(JNIEnv* env, jobject javaField) {
   ScopedFastNativeObjectAccess soa(env);
-  ArtField* field = soa.Decode<mirror::Field*>(javaField)->GetArtField();
+  ArtField* field = soa.Decode<mirror::Field>(javaField)->GetArtField();
   if (field->GetDeclaringClass()->IsProxyClass()) {
     // Return an empty array instead of a null pointer.
     mirror::Class* annotation_array_class =
-        soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_annotation_Annotation__array);
+        soa.Decode<mirror::Class>(
+            WellKnownClasses::java_lang_annotation_Annotation__array).Decode();
     mirror::ObjectArray<mirror::Object>* empty_array =
         mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), annotation_array_class, 0);
     return soa.AddLocalReference<jobjectArray>(empty_array);
@@ -450,7 +451,7 @@
 
 static jobjectArray Field_getSignatureAnnotation(JNIEnv* env, jobject javaField) {
   ScopedFastNativeObjectAccess soa(env);
-  ArtField* field = soa.Decode<mirror::Field*>(javaField)->GetArtField();
+  ArtField* field = soa.Decode<mirror::Field>(javaField)->GetArtField();
   if (field->GetDeclaringClass()->IsProxyClass()) {
     return nullptr;
   }
@@ -461,11 +462,11 @@
                                                 jclass annotationType) {
   ScopedFastNativeObjectAccess soa(env);
   StackHandleScope<1> hs(soa.Self());
-  ArtField* field = soa.Decode<mirror::Field*>(javaField)->GetArtField();
+  ArtField* field = soa.Decode<mirror::Field>(javaField)->GetArtField();
   if (field->GetDeclaringClass()->IsProxyClass()) {
     return false;
   }
-  Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class*>(annotationType)));
+  Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class>(annotationType)));
   return annotations::IsFieldAnnotationPresent(field, klass);
 }
 
diff --git a/runtime/native/java_lang_reflect_Method.cc b/runtime/native/java_lang_reflect_Method.cc
index b8efb14..b5f2f7c 100644
--- a/runtime/native/java_lang_reflect_Method.cc
+++ b/runtime/native/java_lang_reflect_Method.cc
@@ -26,7 +26,7 @@
 #include "mirror/object-inl.h"
 #include "mirror/object_array-inl.h"
 #include "reflection.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
 #include "well_known_classes.h"
 
 namespace art {
diff --git a/runtime/native/java_lang_reflect_Parameter.cc b/runtime/native/java_lang_reflect_Parameter.cc
index c2a803c..6060b8a 100644
--- a/runtime/native/java_lang_reflect_Parameter.cc
+++ b/runtime/native/java_lang_reflect_Parameter.cc
@@ -21,7 +21,7 @@
 #include "dex_file-inl.h"
 #include "dex_file_annotations.h"
 #include "jni_internal.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
 #include "utils.h"
 
 namespace art {
@@ -53,7 +53,7 @@
   }
 
   StackHandleScope<1> hs(soa.Self());
-  Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class*>(annotationType)));
+  Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class>(annotationType)));
   return soa.AddLocalReference<jobject>(
       annotations::GetAnnotationForMethodParameter(method, parameterIndex, klass));
 }
diff --git a/runtime/native/java_lang_reflect_Proxy.cc b/runtime/native/java_lang_reflect_Proxy.cc
index 4a6ab40..ece0338 100644
--- a/runtime/native/java_lang_reflect_Proxy.cc
+++ b/runtime/native/java_lang_reflect_Proxy.cc
@@ -21,7 +21,7 @@
 #include "mirror/class_loader.h"
 #include "mirror/object_array.h"
 #include "mirror/string.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
 #include "verify_object-inl.h"
 
 namespace art {
diff --git a/runtime/native/libcore_util_CharsetUtils.cc b/runtime/native/libcore_util_CharsetUtils.cc
index 64d56f6..2590452 100644
--- a/runtime/native/libcore_util_CharsetUtils.cc
+++ b/runtime/native/libcore_util_CharsetUtils.cc
@@ -18,7 +18,7 @@
 #include "mirror/string.h"
 #include "mirror/string-inl.h"
 #include "native/libcore_util_CharsetUtils.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
 #include "ScopedPrimitiveArray.h"
 #include "unicode/utf16.h"
 
@@ -154,7 +154,7 @@
                                jchar maxValidChar) {
   ScopedObjectAccess soa(env);
   StackHandleScope<1> hs(soa.Self());
-  Handle<mirror::String> string(hs.NewHandle(soa.Decode<mirror::String*>(java_string)));
+  Handle<mirror::String> string(hs.NewHandle(soa.Decode<mirror::String>(java_string)));
   if (string.Get() == nullptr) {
     return nullptr;
   }
@@ -191,7 +191,7 @@
                                            jint length) {
   ScopedObjectAccess soa(env);
   StackHandleScope<1> hs(soa.Self());
-  Handle<mirror::String> string(hs.NewHandle(soa.Decode<mirror::String*>(java_string)));
+  Handle<mirror::String> string(hs.NewHandle(soa.Decode<mirror::String>(java_string)));
   if (string.Get() == nullptr) {
     return nullptr;
   }
diff --git a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmServer.cc b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmServer.cc
index 0ab2979..5356498 100644
--- a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmServer.cc
+++ b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmServer.cc
@@ -19,7 +19,7 @@
 #include "base/logging.h"
 #include "debugger.h"
 #include "jni_internal.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
 #include "ScopedPrimitiveArray.h"
 
 namespace art {
diff --git a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
index 9ed0e7e..ca17c26 100644
--- a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
+++ b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
@@ -20,7 +20,7 @@
 #include "base/mutex.h"
 #include "debugger.h"
 #include "jni_internal.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
 #include "ScopedLocalRef.h"
 #include "ScopedPrimitiveArray.h"
 #include "thread_list.h"
diff --git a/runtime/native/scoped_fast_native_object_access-inl.h b/runtime/native/scoped_fast_native_object_access-inl.h
new file mode 100644
index 0000000..1d73813
--- /dev/null
+++ b/runtime/native/scoped_fast_native_object_access-inl.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2016 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_NATIVE_SCOPED_FAST_NATIVE_OBJECT_ACCESS_INL_H_
+#define ART_RUNTIME_NATIVE_SCOPED_FAST_NATIVE_OBJECT_ACCESS_INL_H_
+
+#include "scoped_fast_native_object_access.h"
+
+#include "art_method-inl.h"
+#include "scoped_thread_state_change-inl.h"
+
+namespace art {
+
+inline ScopedFastNativeObjectAccess::ScopedFastNativeObjectAccess(JNIEnv* env)
+    : ScopedObjectAccessAlreadyRunnable(env) {
+  Locks::mutator_lock_->AssertSharedHeld(Self());
+  DCHECK((*Self()->GetManagedStack()->GetTopQuickFrame())->IsFastNative());
+  // Don't work with raw objects in non-runnable states.
+  DCHECK_EQ(Self()->GetState(), kRunnable);
+}
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_NATIVE_SCOPED_FAST_NATIVE_OBJECT_ACCESS_INL_H_
diff --git a/runtime/native/scoped_fast_native_object_access.h b/runtime/native/scoped_fast_native_object_access.h
index c4a33df..6a9365d 100644
--- a/runtime/native/scoped_fast_native_object_access.h
+++ b/runtime/native/scoped_fast_native_object_access.h
@@ -17,7 +17,8 @@
 #ifndef ART_RUNTIME_NATIVE_SCOPED_FAST_NATIVE_OBJECT_ACCESS_H_
 #define ART_RUNTIME_NATIVE_SCOPED_FAST_NATIVE_OBJECT_ACCESS_H_
 
-#include "art_method-inl.h"
+#include <jni.h>
+
 #include "scoped_thread_state_change.h"
 
 namespace art {
@@ -26,18 +27,11 @@
 // JNI methods.
 class ScopedFastNativeObjectAccess : public ScopedObjectAccessAlreadyRunnable {
  public:
-  explicit ScopedFastNativeObjectAccess(JNIEnv* env)
+  ALWAYS_INLINE explicit ScopedFastNativeObjectAccess(JNIEnv* env)
     REQUIRES(!Locks::thread_suspend_count_lock_)
-    SHARED_LOCK_FUNCTION(Locks::mutator_lock_) ALWAYS_INLINE
-     : ScopedObjectAccessAlreadyRunnable(env) {
-    Locks::mutator_lock_->AssertSharedHeld(Self());
-    DCHECK((*Self()->GetManagedStack()->GetTopQuickFrame())->IsFastNative());
-    // Don't work with raw objects in non-runnable states.
-    DCHECK_EQ(Self()->GetState(), kRunnable);
-  }
+    SHARED_LOCK_FUNCTION(Locks::mutator_lock_);
 
-  ~ScopedFastNativeObjectAccess() UNLOCK_FUNCTION(Locks::mutator_lock_) ALWAYS_INLINE {
-  }
+  ALWAYS_INLINE ~ScopedFastNativeObjectAccess() UNLOCK_FUNCTION(Locks::mutator_lock_) {}
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ScopedFastNativeObjectAccess);
diff --git a/runtime/native/sun_misc_Unsafe.cc b/runtime/native/sun_misc_Unsafe.cc
index 472340c..2fae3cc 100644
--- a/runtime/native/sun_misc_Unsafe.cc
+++ b/runtime/native/sun_misc_Unsafe.cc
@@ -21,7 +21,7 @@
 #include "mirror/array.h"
 #include "mirror/class-inl.h"
 #include "mirror/object-inl.h"
-#include "scoped_fast_native_object_access.h"
+#include "scoped_fast_native_object_access-inl.h"
 
 #include <unistd.h>
 #include <stdlib.h>
@@ -33,61 +33,64 @@
 static jboolean Unsafe_compareAndSwapInt(JNIEnv* env, jobject, jobject javaObj, jlong offset,
                                          jint expectedValue, jint newValue) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
+  ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
   // JNI must use non transactional mode.
   bool success = obj->CasFieldStrongSequentiallyConsistent32<false>(MemberOffset(offset),
-                                                                    expectedValue, newValue);
+                                                                    expectedValue,
+                                                                    newValue);
   return success ? JNI_TRUE : JNI_FALSE;
 }
 
 static jboolean Unsafe_compareAndSwapLong(JNIEnv* env, jobject, jobject javaObj, jlong offset,
                                           jlong expectedValue, jlong newValue) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
+  ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
   // JNI must use non transactional mode.
   bool success = obj->CasFieldStrongSequentiallyConsistent64<false>(MemberOffset(offset),
-                                                                    expectedValue, newValue);
+                                                                    expectedValue,
+                                                                    newValue);
   return success ? JNI_TRUE : JNI_FALSE;
 }
 
 static jboolean Unsafe_compareAndSwapObject(JNIEnv* env, jobject, jobject javaObj, jlong offset,
                                             jobject javaExpectedValue, jobject javaNewValue) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
-  mirror::Object* expectedValue = soa.Decode<mirror::Object*>(javaExpectedValue);
-  mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue);
+  ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
+  ObjPtr<mirror::Object> expectedValue = soa.Decode<mirror::Object>(javaExpectedValue);
+  ObjPtr<mirror::Object> newValue = soa.Decode<mirror::Object>(javaNewValue);
   // JNI must use non transactional mode.
   if (kUseReadBarrier) {
     // Need to make sure the reference stored in the field is a to-space one before attempting the
     // CAS or the CAS could fail incorrectly.
     mirror::HeapReference<mirror::Object>* field_addr =
         reinterpret_cast<mirror::HeapReference<mirror::Object>*>(
-            reinterpret_cast<uint8_t*>(obj) + static_cast<size_t>(offset));
+            reinterpret_cast<uint8_t*>(obj.Decode()) + static_cast<size_t>(offset));
     ReadBarrier::Barrier<mirror::Object, kWithReadBarrier, /*kAlwaysUpdateField*/true>(
-        obj,
+        obj.Decode(),
         MemberOffset(offset),
         field_addr);
   }
   bool success = obj->CasFieldStrongSequentiallyConsistentObject<false>(MemberOffset(offset),
-                                                                        expectedValue, newValue);
+                                                                        expectedValue.Decode(),
+                                                                        newValue.Decode());
   return success ? JNI_TRUE : JNI_FALSE;
 }
 
 static jint Unsafe_getInt(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
+  ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
   return obj->GetField32(MemberOffset(offset));
 }
 
 static jint Unsafe_getIntVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
+  ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
   return obj->GetField32Volatile(MemberOffset(offset));
 }
 
 static void Unsafe_putInt(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint newValue) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
+  ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
   // JNI must use non transactional mode.
   obj->SetField32<false>(MemberOffset(offset), newValue);
 }
@@ -95,7 +98,7 @@
 static void Unsafe_putIntVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset,
                                   jint newValue) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
+  ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
   // JNI must use non transactional mode.
   obj->SetField32Volatile<false>(MemberOffset(offset), newValue);
 }
@@ -103,7 +106,7 @@
 static void Unsafe_putOrderedInt(JNIEnv* env, jobject, jobject javaObj, jlong offset,
                                  jint newValue) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
+  ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
   QuasiAtomic::ThreadFenceRelease();
   // JNI must use non transactional mode.
   obj->SetField32<false>(MemberOffset(offset), newValue);
@@ -111,19 +114,19 @@
 
 static jlong Unsafe_getLong(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
+  ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
   return obj->GetField64(MemberOffset(offset));
 }
 
 static jlong Unsafe_getLongVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
+  ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
   return obj->GetField64Volatile(MemberOffset(offset));
 }
 
 static void Unsafe_putLong(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong newValue) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
+  ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
   // JNI must use non transactional mode.
   obj->SetField64<false>(MemberOffset(offset), newValue);
 }
@@ -131,7 +134,7 @@
 static void Unsafe_putLongVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset,
                                    jlong newValue) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
+  ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
   // JNI must use non transactional mode.
   obj->SetField64Volatile<false>(MemberOffset(offset), newValue);
 }
@@ -139,7 +142,7 @@
 static void Unsafe_putOrderedLong(JNIEnv* env, jobject, jobject javaObj, jlong offset,
                                   jlong newValue) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
+  ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
   QuasiAtomic::ThreadFenceRelease();
   // JNI must use non transactional mode.
   obj->SetField64<false>(MemberOffset(offset), newValue);
@@ -147,56 +150,56 @@
 
 static jobject Unsafe_getObjectVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
-  mirror::Object* value = obj->GetFieldObjectVolatile<mirror::Object>(MemberOffset(offset));
+  ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
+  ObjPtr<mirror::Object> value = obj->GetFieldObjectVolatile<mirror::Object>(MemberOffset(offset));
   return soa.AddLocalReference<jobject>(value);
 }
 
 static jobject Unsafe_getObject(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
-  mirror::Object* value = obj->GetFieldObject<mirror::Object>(MemberOffset(offset));
+  ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
+  ObjPtr<mirror::Object> value = obj->GetFieldObject<mirror::Object>(MemberOffset(offset));
   return soa.AddLocalReference<jobject>(value);
 }
 
 static void Unsafe_putObject(JNIEnv* env, jobject, jobject javaObj, jlong offset,
                              jobject javaNewValue) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
-  mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue);
+  ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
+  ObjPtr<mirror::Object> newValue = soa.Decode<mirror::Object>(javaNewValue);
   // JNI must use non transactional mode.
-  obj->SetFieldObject<false>(MemberOffset(offset), newValue);
+  obj->SetFieldObject<false>(MemberOffset(offset), newValue.Decode());
 }
 
 static void Unsafe_putObjectVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset,
                                      jobject javaNewValue) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
-  mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue);
+  ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
+  ObjPtr<mirror::Object> newValue = soa.Decode<mirror::Object>(javaNewValue);
   // JNI must use non transactional mode.
-  obj->SetFieldObjectVolatile<false>(MemberOffset(offset), newValue);
+  obj->SetFieldObjectVolatile<false>(MemberOffset(offset), newValue.Decode());
 }
 
 static void Unsafe_putOrderedObject(JNIEnv* env, jobject, jobject javaObj, jlong offset,
                                     jobject javaNewValue) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
-  mirror::Object* newValue = soa.Decode<mirror::Object*>(javaNewValue);
+  ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
+  ObjPtr<mirror::Object> newValue = soa.Decode<mirror::Object>(javaNewValue);
   QuasiAtomic::ThreadFenceRelease();
   // JNI must use non transactional mode.
-  obj->SetFieldObject<false>(MemberOffset(offset), newValue);
+  obj->SetFieldObject<false>(MemberOffset(offset), newValue.Decode());
 }
 
 static jint Unsafe_getArrayBaseOffsetForComponentType(JNIEnv* env, jclass, jobject component_class) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Class* component = soa.Decode<mirror::Class*>(component_class);
+  ObjPtr<mirror::Class> component = soa.Decode<mirror::Class>(component_class);
   Primitive::Type primitive_type = component->GetPrimitiveType();
   return mirror::Array::DataOffset(Primitive::ComponentSize(primitive_type)).Int32Value();
 }
 
 static jint Unsafe_getArrayIndexScaleForComponentType(JNIEnv* env, jclass, jobject component_class) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Class* component = soa.Decode<mirror::Class*>(component_class);
+  ObjPtr<mirror::Class> component = soa.Decode<mirror::Class>(component_class);
   Primitive::Type primitive_type = component->GetPrimitiveType();
   return Primitive::ComponentSize(primitive_type);
 }
@@ -289,16 +292,16 @@
 
 static void Unsafe_copyMemory(JNIEnv *env, jobject unsafe ATTRIBUTE_UNUSED, jlong src,
                               jlong dst, jlong size) {
-    if (size == 0) {
-        return;
-    }
-    // size is nonnegative and fits into size_t
-    if (size < 0 || size != (jlong)(size_t) size) {
-        ScopedFastNativeObjectAccess soa(env);
-        ThrowIllegalAccessException("wrong number of bytes");
-    }
-    size_t sz = (size_t)size;
-    memcpy(reinterpret_cast<void *>(dst), reinterpret_cast<void *>(src), sz);
+  if (size == 0) {
+    return;
+  }
+  // size is nonnegative and fits into size_t
+  if (size < 0 || size != (jlong)(size_t) size) {
+    ScopedFastNativeObjectAccess soa(env);
+    ThrowIllegalAccessException("wrong number of bytes");
+  }
+  size_t sz = (size_t)size;
+  memcpy(reinterpret_cast<void *>(dst), reinterpret_cast<void *>(src), sz);
 }
 
 template<typename T>
@@ -306,12 +309,12 @@
                         size_t array_offset,
                         size_t size)
         REQUIRES_SHARED(Locks::mutator_lock_) {
-    const T* src = reinterpret_cast<T*>(srcAddr);
-    size_t sz = size / sizeof(T);
-    size_t of = array_offset / sizeof(T);
-    for (size_t i = 0; i < sz; ++i) {
-        array->Set(i + of, *(src + i));
-    }
+  const T* src = reinterpret_cast<T*>(srcAddr);
+  size_t sz = size / sizeof(T);
+  size_t of = array_offset / sizeof(T);
+  for (size_t i = 0; i < sz; ++i) {
+    array->Set(i + of, *(src + i));
+  }
 }
 
 template<typename T>
@@ -319,12 +322,12 @@
                           size_t array_offset,
                           size_t size)
         REQUIRES_SHARED(Locks::mutator_lock_) {
-    T* dst = reinterpret_cast<T*>(dstAddr);
-    size_t sz = size / sizeof(T);
-    size_t of = array_offset / sizeof(T);
-    for (size_t i = 0; i < sz; ++i) {
-        *(dst + i) = array->Get(i + of);
-    }
+  T* dst = reinterpret_cast<T*>(dstAddr);
+  size_t sz = size / sizeof(T);
+  size_t of = array_offset / sizeof(T);
+  for (size_t i = 0; i < sz; ++i) {
+    *(dst + i) = array->Get(i + of);
+  }
 }
 
 static void Unsafe_copyMemoryToPrimitiveArray(JNIEnv *env,
@@ -333,29 +336,29 @@
                                               jobject dstObj,
                                               jlong dstOffset,
                                               jlong size) {
-    ScopedObjectAccess soa(env);
-    if (size == 0) {
-        return;
-    }
-    // size is nonnegative and fits into size_t
-    if (size < 0 || size != (jlong)(size_t) size) {
-        ThrowIllegalAccessException("wrong number of bytes");
-    }
-    size_t sz = (size_t)size;
-    size_t dst_offset = (size_t)dstOffset;
-    mirror::Object* dst = soa.Decode<mirror::Object*>(dstObj);
-    mirror::Class* component_type = dst->GetClass()->GetComponentType();
-    if (component_type->IsPrimitiveByte() || component_type->IsPrimitiveBoolean()) {
-        copyToArray(srcAddr, dst->AsByteSizedArray(), dst_offset, sz);
-    } else if (component_type->IsPrimitiveShort() || component_type->IsPrimitiveChar()) {
-        copyToArray(srcAddr, dst->AsShortSizedArray(), dst_offset, sz);
-    } else if (component_type->IsPrimitiveInt() || component_type->IsPrimitiveFloat()) {
-        copyToArray(srcAddr, dst->AsIntArray(), dst_offset, sz);
-    } else if (component_type->IsPrimitiveLong() || component_type->IsPrimitiveDouble()) {
-        copyToArray(srcAddr, dst->AsLongArray(), dst_offset, sz);
-    } else {
-        ThrowIllegalAccessException("not a primitive array");
-    }
+  ScopedObjectAccess soa(env);
+  if (size == 0) {
+    return;
+  }
+  // size is nonnegative and fits into size_t
+  if (size < 0 || size != (jlong)(size_t) size) {
+    ThrowIllegalAccessException("wrong number of bytes");
+  }
+  size_t sz = (size_t)size;
+  size_t dst_offset = (size_t)dstOffset;
+  ObjPtr<mirror::Object> dst = soa.Decode<mirror::Object>(dstObj);
+  mirror::Class* component_type = dst->GetClass()->GetComponentType();
+  if (component_type->IsPrimitiveByte() || component_type->IsPrimitiveBoolean()) {
+    copyToArray(srcAddr, dst->AsByteSizedArray(), dst_offset, sz);
+  } else if (component_type->IsPrimitiveShort() || component_type->IsPrimitiveChar()) {
+    copyToArray(srcAddr, dst->AsShortSizedArray(), dst_offset, sz);
+  } else if (component_type->IsPrimitiveInt() || component_type->IsPrimitiveFloat()) {
+    copyToArray(srcAddr, dst->AsIntArray(), dst_offset, sz);
+  } else if (component_type->IsPrimitiveLong() || component_type->IsPrimitiveDouble()) {
+    copyToArray(srcAddr, dst->AsLongArray(), dst_offset, sz);
+  } else {
+    ThrowIllegalAccessException("not a primitive array");
+  }
 }
 
 static void Unsafe_copyMemoryFromPrimitiveArray(JNIEnv *env,
@@ -364,85 +367,85 @@
                                                 jlong srcOffset,
                                                 jlong dstAddr,
                                                 jlong size) {
-    ScopedObjectAccess soa(env);
-    if (size == 0) {
-        return;
-    }
-    // size is nonnegative and fits into size_t
-    if (size < 0 || size != (jlong)(size_t) size) {
-        ThrowIllegalAccessException("wrong number of bytes");
-    }
-    size_t sz = (size_t)size;
-    size_t src_offset = (size_t)srcOffset;
-    mirror::Object* src = soa.Decode<mirror::Object*>(srcObj);
-    mirror::Class* component_type = src->GetClass()->GetComponentType();
-    if (component_type->IsPrimitiveByte() || component_type->IsPrimitiveBoolean()) {
-        copyFromArray(dstAddr, src->AsByteSizedArray(), src_offset, sz);
-    } else if (component_type->IsPrimitiveShort() || component_type->IsPrimitiveChar()) {
-        copyFromArray(dstAddr, src->AsShortSizedArray(), src_offset, sz);
-    } else if (component_type->IsPrimitiveInt() || component_type->IsPrimitiveFloat()) {
-        copyFromArray(dstAddr, src->AsIntArray(), src_offset, sz);
-    } else if (component_type->IsPrimitiveLong() || component_type->IsPrimitiveDouble()) {
-        copyFromArray(dstAddr, src->AsLongArray(), src_offset, sz);
-    } else {
-        ThrowIllegalAccessException("not a primitive array");
-    }
+  ScopedObjectAccess soa(env);
+  if (size == 0) {
+    return;
+  }
+  // size is nonnegative and fits into size_t
+  if (size < 0 || size != (jlong)(size_t) size) {
+    ThrowIllegalAccessException("wrong number of bytes");
+  }
+  size_t sz = (size_t)size;
+  size_t src_offset = (size_t)srcOffset;
+  ObjPtr<mirror::Object> src = soa.Decode<mirror::Object>(srcObj);
+  mirror::Class* component_type = src->GetClass()->GetComponentType();
+  if (component_type->IsPrimitiveByte() || component_type->IsPrimitiveBoolean()) {
+    copyFromArray(dstAddr, src->AsByteSizedArray(), src_offset, sz);
+  } else if (component_type->IsPrimitiveShort() || component_type->IsPrimitiveChar()) {
+    copyFromArray(dstAddr, src->AsShortSizedArray(), src_offset, sz);
+  } else if (component_type->IsPrimitiveInt() || component_type->IsPrimitiveFloat()) {
+    copyFromArray(dstAddr, src->AsIntArray(), src_offset, sz);
+  } else if (component_type->IsPrimitiveLong() || component_type->IsPrimitiveDouble()) {
+    copyFromArray(dstAddr, src->AsLongArray(), src_offset, sz);
+  } else {
+    ThrowIllegalAccessException("not a primitive array");
+  }
 }
 static jboolean Unsafe_getBoolean(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
-    ScopedFastNativeObjectAccess soa(env);
-    mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
-    return obj->GetFieldBoolean(MemberOffset(offset));
+  ScopedFastNativeObjectAccess soa(env);
+  ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
+  return obj->GetFieldBoolean(MemberOffset(offset));
 }
 
 static void Unsafe_putBoolean(JNIEnv* env, jobject, jobject javaObj, jlong offset, jboolean newValue) {
-    ScopedFastNativeObjectAccess soa(env);
-    mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
-    // JNI must use non transactional mode (SetField8 is non-transactional).
-    obj->SetFieldBoolean<false>(MemberOffset(offset), newValue);
+  ScopedFastNativeObjectAccess soa(env);
+  ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
+  // JNI must use non transactional mode (SetField8 is non-transactional).
+  obj->SetFieldBoolean<false>(MemberOffset(offset), newValue);
 }
 
 static jbyte Unsafe_getByte(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
-    ScopedFastNativeObjectAccess soa(env);
-    mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
-    return obj->GetFieldByte(MemberOffset(offset));
+  ScopedFastNativeObjectAccess soa(env);
+  ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
+  return obj->GetFieldByte(MemberOffset(offset));
 }
 
 static void Unsafe_putByte(JNIEnv* env, jobject, jobject javaObj, jlong offset, jbyte newValue) {
-    ScopedFastNativeObjectAccess soa(env);
-    mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
-    // JNI must use non transactional mode.
-    obj->SetFieldByte<false>(MemberOffset(offset), newValue);
+  ScopedFastNativeObjectAccess soa(env);
+  ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
+  // JNI must use non transactional mode.
+  obj->SetFieldByte<false>(MemberOffset(offset), newValue);
 }
 
 static jchar Unsafe_getChar(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
-    ScopedFastNativeObjectAccess soa(env);
-    mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
-    return obj->GetFieldChar(MemberOffset(offset));
+  ScopedFastNativeObjectAccess soa(env);
+  ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
+  return obj->GetFieldChar(MemberOffset(offset));
 }
 
 static void Unsafe_putChar(JNIEnv* env, jobject, jobject javaObj, jlong offset, jchar newValue) {
-    ScopedFastNativeObjectAccess soa(env);
-    mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
-    // JNI must use non transactional mode.
-    obj->SetFieldChar<false>(MemberOffset(offset), newValue);
+  ScopedFastNativeObjectAccess soa(env);
+  ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
+  // JNI must use non transactional mode.
+  obj->SetFieldChar<false>(MemberOffset(offset), newValue);
 }
 
 static jshort Unsafe_getShort(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
-    ScopedFastNativeObjectAccess soa(env);
-    mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
-    return obj->GetFieldShort(MemberOffset(offset));
+  ScopedFastNativeObjectAccess soa(env);
+  ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
+  return obj->GetFieldShort(MemberOffset(offset));
 }
 
 static void Unsafe_putShort(JNIEnv* env, jobject, jobject javaObj, jlong offset, jshort newValue) {
-    ScopedFastNativeObjectAccess soa(env);
-    mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
-    // JNI must use non transactional mode.
-    obj->SetFieldShort<false>(MemberOffset(offset), newValue);
+  ScopedFastNativeObjectAccess soa(env);
+  ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
+  // JNI must use non transactional mode.
+  obj->SetFieldShort<false>(MemberOffset(offset), newValue);
 }
 
 static jfloat Unsafe_getFloat(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
+  ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
   union {int32_t val; jfloat converted;} conv;
   conv.val = obj->GetField32(MemberOffset(offset));
   return conv.converted;
@@ -450,7 +453,7 @@
 
 static void Unsafe_putFloat(JNIEnv* env, jobject, jobject javaObj, jlong offset, jfloat newValue) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
+  ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
   union {int32_t converted; jfloat val;} conv;
   conv.val = newValue;
   // JNI must use non transactional mode.
@@ -459,7 +462,7 @@
 
 static jdouble Unsafe_getDouble(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
+  ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
   union {int64_t val; jdouble converted;} conv;
   conv.val = obj->GetField64(MemberOffset(offset));
   return conv.converted;
@@ -467,7 +470,7 @@
 
 static void Unsafe_putDouble(JNIEnv* env, jobject, jobject javaObj, jlong offset, jdouble newValue) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
+  ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
   union {int64_t converted; jdouble val;} conv;
   conv.val = newValue;
   // JNI must use non transactional mode.