232 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			232 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			C++
		
	
	
	
| /*
 | |
|  * Copyright (C) 2017 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_MIRROR_CLASS_EXT_INL_H_
 | |
| #define ART_RUNTIME_MIRROR_CLASS_EXT_INL_H_
 | |
| 
 | |
| #include "class_ext.h"
 | |
| 
 | |
| #include "array-inl.h"
 | |
| #include "art_method-inl.h"
 | |
| #include "base/enums.h"
 | |
| #include "base/globals.h"
 | |
| #include "handle_scope.h"
 | |
| #include "jni/jni_internal.h"
 | |
| #include "jni_id_type.h"
 | |
| #include "mirror/array.h"
 | |
| #include "mirror/object.h"
 | |
| #include "object-inl.h"
 | |
| #include "verify_object.h"
 | |
| #include "well_known_classes.h"
 | |
| 
 | |
| namespace art {
 | |
| namespace mirror {
 | |
| 
 | |
| template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
 | |
| inline bool ClassExt::EnsureJniIdsArrayPresent(MemberOffset off, size_t count) {
 | |
|   ObjPtr<Object> existing(
 | |
|       GetFieldObject<Object, kVerifyFlags, kReadBarrierOption>(off));
 | |
|   if (!existing.IsNull()) {
 | |
|     return true;
 | |
|   }
 | |
|   Thread* self = Thread::Current();
 | |
|   StackHandleScope<2> hs(self);
 | |
|   Handle<ClassExt> h_this(hs.NewHandle(this));
 | |
|   MutableHandle<Object> new_arr(hs.NewHandle<Object>(nullptr));
 | |
|   if (UNLIKELY(Runtime::Current()->GetJniIdType() == JniIdType::kSwapablePointer)) {
 | |
|     new_arr.Assign(Runtime::Current()->GetJniIdManager()->GetPointerMarker());
 | |
|   } else {
 | |
|     new_arr.Assign(Runtime::Current()->GetClassLinker()->AllocPointerArray(self, count));
 | |
|   }
 | |
|   if (new_arr.IsNull()) {
 | |
|     // Fail.
 | |
|     self->AssertPendingOOMException();
 | |
|     return false;
 | |
|   }
 | |
|   bool set;
 | |
|   // Set the ext_data_ field using CAS semantics.
 | |
|   if (Runtime::Current()->IsActiveTransaction()) {
 | |
|     set = h_this->CasFieldObject<true>(
 | |
|         off, nullptr, new_arr.Get(), CASMode::kStrong, std::memory_order_seq_cst);
 | |
|   } else {
 | |
|     set = h_this->CasFieldObject<false>(
 | |
|         off, nullptr, new_arr.Get(), CASMode::kStrong, std::memory_order_seq_cst);
 | |
|   }
 | |
|   if (kIsDebugBuild) {
 | |
|     ObjPtr<Object> ret(
 | |
|         set ? new_arr.Get()
 | |
|             : h_this->GetFieldObject<PointerArray, kVerifyFlags, kReadBarrierOption>(off));
 | |
|     CHECK(!ret.IsNull());
 | |
|   }
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
 | |
| inline bool ClassExt::EnsureJMethodIDsArrayPresent(size_t count) {
 | |
|   return EnsureJniIdsArrayPresent<kVerifyFlags, kReadBarrierOption>(
 | |
|       MemberOffset(OFFSET_OF_OBJECT_MEMBER(ClassExt, jmethod_ids_)), count);
 | |
| }
 | |
| template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
 | |
| inline bool ClassExt::EnsureStaticJFieldIDsArrayPresent(size_t count) {
 | |
|   return EnsureJniIdsArrayPresent<kVerifyFlags, kReadBarrierOption>(
 | |
|       MemberOffset(OFFSET_OF_OBJECT_MEMBER(ClassExt, static_jfield_ids_)), count);
 | |
| }
 | |
| template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
 | |
| inline bool ClassExt::EnsureInstanceJFieldIDsArrayPresent(size_t count) {
 | |
|   return EnsureJniIdsArrayPresent<kVerifyFlags, kReadBarrierOption>(
 | |
|       MemberOffset(OFFSET_OF_OBJECT_MEMBER(ClassExt, instance_jfield_ids_)), count);
 | |
| }
 | |
| 
 | |
| template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
 | |
| inline ObjPtr<Object> ClassExt::GetInstanceJFieldIDs() {
 | |
|   return GetFieldObject<Object, kVerifyFlags, kReadBarrierOption>(
 | |
|       OFFSET_OF_OBJECT_MEMBER(ClassExt, instance_jfield_ids_));
 | |
| }
 | |
| template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
 | |
| inline bool ClassExt::HasInstanceFieldPointerIdMarker() {
 | |
|   ObjPtr<Object> arr(GetInstanceJFieldIDs<kVerifyFlags, kReadBarrierOption>());
 | |
|   return !arr.IsNull() && !arr->IsArrayInstance();
 | |
| }
 | |
| template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
 | |
| inline ObjPtr<PointerArray> ClassExt::GetInstanceJFieldIDsPointerArray() {
 | |
|   DCHECK(!HasInstanceFieldPointerIdMarker());
 | |
|   return down_cast<PointerArray*>(GetInstanceJFieldIDs<kVerifyFlags, kReadBarrierOption>().Ptr());
 | |
| }
 | |
| 
 | |
| template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
 | |
| inline ObjPtr<Object> ClassExt::GetStaticJFieldIDs() {
 | |
|   return GetFieldObject<Object, kVerifyFlags, kReadBarrierOption>(
 | |
|       OFFSET_OF_OBJECT_MEMBER(ClassExt, static_jfield_ids_));
 | |
| }
 | |
| template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
 | |
| inline ObjPtr<PointerArray> ClassExt::GetStaticJFieldIDsPointerArray() {
 | |
|   DCHECK(!HasStaticFieldPointerIdMarker());
 | |
|   return down_cast<PointerArray*>(GetStaticJFieldIDs<kVerifyFlags, kReadBarrierOption>().Ptr());
 | |
| }
 | |
| template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
 | |
| inline bool ClassExt::HasStaticFieldPointerIdMarker() {
 | |
|   ObjPtr<Object> arr(GetStaticJFieldIDs<kVerifyFlags, kReadBarrierOption>());
 | |
|   return !arr.IsNull() && !arr->IsArrayInstance();
 | |
| }
 | |
| 
 | |
| template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
 | |
| inline ObjPtr<Class> ClassExt::GetObsoleteClass() {
 | |
|   return GetFieldObject<Class, kVerifyFlags, kReadBarrierOption>(
 | |
|       OFFSET_OF_OBJECT_MEMBER(ClassExt, obsolete_class_));
 | |
| }
 | |
| 
 | |
| template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
 | |
| inline ObjPtr<Object> ClassExt::GetJMethodIDs() {
 | |
|   return GetFieldObject<Object, kVerifyFlags, kReadBarrierOption>(
 | |
|       OFFSET_OF_OBJECT_MEMBER(ClassExt, jmethod_ids_));
 | |
| }
 | |
| template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
 | |
| inline ObjPtr<PointerArray> ClassExt::GetJMethodIDsPointerArray() {
 | |
|   DCHECK(!HasMethodPointerIdMarker());
 | |
|   return down_cast<PointerArray*>(GetJMethodIDs<kVerifyFlags, kReadBarrierOption>().Ptr());
 | |
| }
 | |
| template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
 | |
| inline bool ClassExt::HasMethodPointerIdMarker() {
 | |
|   ObjPtr<Object> arr(GetJMethodIDs<kVerifyFlags, kReadBarrierOption>());
 | |
|   return !arr.IsNull() && !arr->IsArrayInstance();
 | |
| }
 | |
| 
 | |
| inline ObjPtr<Throwable> ClassExt::GetErroneousStateError() {
 | |
|   return GetFieldObject<Throwable>(OFFSET_OF_OBJECT_MEMBER(ClassExt, erroneous_state_error_));
 | |
| }
 | |
| 
 | |
| inline ObjPtr<ObjectArray<DexCache>> ClassExt::GetObsoleteDexCaches() {
 | |
|   return GetFieldObject<ObjectArray<DexCache>>(
 | |
|       OFFSET_OF_OBJECT_MEMBER(ClassExt, obsolete_dex_caches_));
 | |
| }
 | |
| 
 | |
| template<VerifyObjectFlags kVerifyFlags,
 | |
|          ReadBarrierOption kReadBarrierOption>
 | |
| inline ObjPtr<PointerArray> ClassExt::GetObsoleteMethods() {
 | |
|   return GetFieldObject<PointerArray, kVerifyFlags, kReadBarrierOption>(
 | |
|       OFFSET_OF_OBJECT_MEMBER(ClassExt, obsolete_methods_));
 | |
| }
 | |
| 
 | |
| inline ObjPtr<Object> ClassExt::GetOriginalDexFile() {
 | |
|   return GetFieldObject<Object>(OFFSET_OF_OBJECT_MEMBER(ClassExt, original_dex_file_));
 | |
| }
 | |
| 
 | |
| template<ReadBarrierOption kReadBarrierOption, class Visitor>
 | |
| void ClassExt::VisitNativeRoots(Visitor& visitor, PointerSize pointer_size) {
 | |
|   VisitMethods<kReadBarrierOption>([&](ArtMethod* method) {
 | |
|     method->VisitRoots<kReadBarrierOption>(visitor, pointer_size);
 | |
|   }, pointer_size);
 | |
| }
 | |
| 
 | |
| template<ReadBarrierOption kReadBarrierOption, class Visitor>
 | |
| void ClassExt::VisitMethods(Visitor visitor, PointerSize pointer_size) {
 | |
|   ObjPtr<PointerArray> arr(GetObsoleteMethods<kDefaultVerifyFlags, kReadBarrierOption>());
 | |
|   if (!arr.IsNull()) {
 | |
|     int32_t len = arr->GetLength();
 | |
|     for (int32_t i = 0; i < len; i++) {
 | |
|       ArtMethod* method = arr->GetElementPtrSize<ArtMethod*>(i, pointer_size);
 | |
|       if (method != nullptr) {
 | |
|         visitor(method);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| template<ReadBarrierOption kReadBarrierOption, class Visitor>
 | |
| void ClassExt::VisitJMethodIDs(Visitor v) {
 | |
|   ObjPtr<Object> arr(GetJMethodIDs<kDefaultVerifyFlags, kReadBarrierOption>());
 | |
|   if (!arr.IsNull() && arr->IsArrayInstance()) {
 | |
|     ObjPtr<PointerArray> marr(down_cast<PointerArray*>(arr.Ptr()));
 | |
|     int32_t len = marr->GetLength();
 | |
|     for (int32_t i = 0; i < len; i++) {
 | |
|       jmethodID id = marr->GetElementPtrSize<jmethodID>(i, kRuntimePointerSize);
 | |
|       if (id != nullptr) {
 | |
|         v(id, i);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 | |
| template<ReadBarrierOption kReadBarrierOption, class Visitor>
 | |
| void ClassExt::VisitJFieldIDs(Visitor v) {
 | |
|   ObjPtr<Object> sarr_obj(GetStaticJFieldIDs<kDefaultVerifyFlags, kReadBarrierOption>());
 | |
|   if (!sarr_obj.IsNull() && sarr_obj->IsArrayInstance()) {
 | |
|     ObjPtr<PointerArray> sarr(down_cast<PointerArray*>(sarr_obj->AsArray().Ptr()));
 | |
|     int32_t len = sarr->GetLength();
 | |
|     for (int32_t i = 0; i < len; i++) {
 | |
|       jfieldID id = sarr->GetElementPtrSize<jfieldID>(i, kRuntimePointerSize);
 | |
|       if (id != nullptr) {
 | |
|         v(id, i, true);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   ObjPtr<PointerArray> iarr_obj(GetInstanceJFieldIDs<kDefaultVerifyFlags, kReadBarrierOption>());
 | |
|   if (!iarr_obj.IsNull() && iarr_obj->IsArrayInstance()) {
 | |
|     ObjPtr<PointerArray> iarr(down_cast<PointerArray*>(iarr_obj->AsArray().Ptr()));
 | |
|     int32_t len = iarr->GetLength();
 | |
|     for (int32_t i = 0; i < len; i++) {
 | |
|       jfieldID id = iarr->GetElementPtrSize<jfieldID>(i, kRuntimePointerSize);
 | |
|       if (id != nullptr) {
 | |
|         v(id, i, false);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| }  // namespace mirror
 | |
| }  // namespace art
 | |
| 
 | |
| #endif  // ART_RUNTIME_MIRROR_CLASS_EXT_INL_H_
 |