Abstract SetField functions with Transaction check

Abstracted several functions which set objects' fields with a check to
test whether transaction is active to determine one template argument,
this make more object modification operations support transaction.

Replaced some function calls with transaction checking version to
support clinit for app image to run under transaction.

Tests shows not breaking anything, testcase cover this situation will be
added shortly.

Test: make test-art-host -j64
Change-Id: Ic15a4428a7c7cce6832651e1894eb760354de009
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 419a4db..003cd4e 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -673,11 +673,7 @@
 }
 
 inline void Class::SetClinitThreadId(pid_t new_clinit_thread_id) {
-  if (Runtime::Current()->IsActiveTransaction()) {
-    SetField32<true>(OFFSET_OF_OBJECT_MEMBER(Class, clinit_thread_id_), new_clinit_thread_id);
-  } else {
-    SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, clinit_thread_id_), new_clinit_thread_id);
-  }
+  SetField32Transaction(OFFSET_OF_OBJECT_MEMBER(Class, clinit_thread_id_), new_clinit_thread_id);
 }
 
 inline String* Class::GetName() {
@@ -685,11 +681,7 @@
 }
 
 inline void Class::SetName(ObjPtr<String> name) {
-  if (Runtime::Current()->IsActiveTransaction()) {
-    SetFieldObject<true>(OFFSET_OF_OBJECT_MEMBER(Class, name_), name);
-  } else {
-    SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, name_), name);
-  }
+    SetFieldObjectTransaction(OFFSET_OF_OBJECT_MEMBER(Class, name_), name);
 }
 
 template<VerifyObjectFlags kVerifyFlags>
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index e4b5320..b0e5b6a 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -191,7 +191,7 @@
 }
 
 void Class::SetDexCache(ObjPtr<DexCache> new_dex_cache) {
-  SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_), new_dex_cache);
+  SetFieldObjectTransaction(OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_), new_dex_cache);
 }
 
 void Class::SetClassSize(uint32_t new_class_size) {
@@ -200,8 +200,7 @@
     LOG(FATAL_WITHOUT_ABORT) << new_class_size << " vs " << GetClassSize();
     LOG(FATAL) << "class=" << PrettyTypeOf();
   }
-  // Not called within a transaction.
-  SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), new_class_size);
+  SetField32Transaction(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), new_class_size);
 }
 
 // Return the class' name. The exact format is bizarre, but it's the specified behavior for
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 00498bc..b60ddcf 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -408,7 +408,7 @@
     DCHECK_EQ(v32 & kPrimitiveTypeMask, v32) << "upper 16 bits aren't zero";
     // Store the component size shift in the upper 16 bits.
     v32 |= Primitive::ComponentSizeShift(new_type) << kPrimitiveTypeSizeShiftShift;
-    SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, primitive_type_), v32);
+    SetField32Transaction(OFFSET_OF_OBJECT_MEMBER(Class, primitive_type_), v32);
   }
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
@@ -1169,8 +1169,7 @@
   }
 
   void SetDexClassDefIndex(uint16_t class_def_idx) REQUIRES_SHARED(Locks::mutator_lock_) {
-    // Not called within a transaction.
-    SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, dex_class_def_idx_), class_def_idx);
+    SetField32Transaction(OFFSET_OF_OBJECT_MEMBER(Class, dex_class_def_idx_), class_def_idx);
   }
 
   dex::TypeIndex GetDexTypeIndex() REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -1179,8 +1178,7 @@
   }
 
   void SetDexTypeIndex(dex::TypeIndex type_idx) REQUIRES_SHARED(Locks::mutator_lock_) {
-    // Not called within a transaction.
-    SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, dex_type_idx_), type_idx.index_);
+    SetField32Transaction(OFFSET_OF_OBJECT_MEMBER(Class, dex_type_idx_), type_idx.index_);
   }
 
   dex::TypeIndex FindTypeIndexInOtherDexFile(const DexFile& dex_file)
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index 95f829d..43d70b7 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -560,6 +560,15 @@
   SetField32<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset, new_value);
 }
 
+template<bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
+inline void Object::SetField32Transaction(MemberOffset field_offset, int32_t new_value) {
+  if (Runtime::Current()->IsActiveTransaction()) {
+    SetField32<true, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value);
+  } else {
+    SetField32<false, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value);
+  }
+}
+
 // TODO: Pass memory_order_ and strong/weak as arguments to avoid code duplication?
 
 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
@@ -657,6 +666,15 @@
                                                                                new_value);
 }
 
+template<bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
+inline void Object::SetField64Transaction(MemberOffset field_offset, int32_t new_value) {
+  if (Runtime::Current()->IsActiveTransaction()) {
+    SetField64<true, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value);
+  } else {
+    SetField64<false, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value);
+  }
+}
+
 template<typename kSize>
 inline kSize Object::GetFieldAcquire(MemberOffset field_offset) {
   const uint8_t* raw_addr = reinterpret_cast<const uint8_t*>(this) + field_offset.Int32Value();
@@ -775,6 +793,15 @@
                                                                             new_value);
 }
 
+template<bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
+inline void Object::SetFieldObjectTransaction(MemberOffset field_offset, ObjPtr<Object> new_value) {
+  if (Runtime::Current()->IsActiveTransaction()) {
+    SetFieldObject<true, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value);
+  } else {
+    SetFieldObject<false, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value);
+  }
+}
+
 template <VerifyObjectFlags kVerifyFlags>
 inline HeapReference<Object>* Object::GetFieldObjectReferenceAddr(MemberOffset field_offset) {
   if (kVerifyFlags & kVerifyThis) {
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index 9cf4252..886780f 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -312,6 +312,11 @@
                                             ObjPtr<Object> new_value)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
+  template<bool kCheckTransaction = true, VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
+           bool kIsVolatile = false>
+  ALWAYS_INLINE void SetFieldObjectTransaction(MemberOffset field_offset, ObjPtr<Object> new_value)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+
   template<bool kTransactionActive,
            bool kCheckTransaction = true,
            VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
@@ -470,6 +475,12 @@
   ALWAYS_INLINE void SetField32Volatile(MemberOffset field_offset, int32_t new_value)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
+  template<bool kCheckTransaction = true,
+           VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
+           bool kIsVolatile = false>
+  ALWAYS_INLINE void SetField32Transaction(MemberOffset field_offset, int32_t new_value)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+
   template<bool kTransactionActive, bool kCheckTransaction = true,
       VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   ALWAYS_INLINE bool CasFieldWeakSequentiallyConsistent32(MemberOffset field_offset,
@@ -525,6 +536,12 @@
   ALWAYS_INLINE void SetField64Volatile(MemberOffset field_offset, int64_t new_value)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
+  template<bool kCheckTransaction = true,
+           VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
+           bool kIsVolatile = false>
+  ALWAYS_INLINE void SetField64Transaction(MemberOffset field_offset, int32_t new_value)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+
   template<bool kTransactionActive, bool kCheckTransaction = true,
       VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool CasFieldWeakSequentiallyConsistent64(MemberOffset field_offset, int64_t old_value,