/* * 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 "class_root.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 inline bool ClassExt::EnsureJniIdsArrayPresent(MemberOffset off, size_t count) { ObjPtr existing( GetFieldObject(off)); if (!existing.IsNull()) { return true; } Thread* self = Thread::Current(); StackHandleScope<2> hs(self); Handle h_this(hs.NewHandle(this)); MutableHandle new_arr(hs.NewHandle(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( off, nullptr, new_arr.Get(), CASMode::kStrong, std::memory_order_seq_cst); } else { set = h_this->CasFieldObject( off, nullptr, new_arr.Get(), CASMode::kStrong, std::memory_order_seq_cst); } if (kIsDebugBuild) { ObjPtr ret( set ? new_arr.Get() : h_this->GetFieldObject(off)); CHECK(!ret.IsNull()); } return true; } template inline bool ClassExt::EnsureJMethodIDsArrayPresent(size_t count) { return EnsureJniIdsArrayPresent( MemberOffset(OFFSET_OF_OBJECT_MEMBER(ClassExt, jmethod_ids_)), count); } template inline bool ClassExt::EnsureStaticJFieldIDsArrayPresent(size_t count) { return EnsureJniIdsArrayPresent( MemberOffset(OFFSET_OF_OBJECT_MEMBER(ClassExt, static_jfield_ids_)), count); } template inline bool ClassExt::EnsureInstanceJFieldIDsArrayPresent(size_t count) { return EnsureJniIdsArrayPresent( MemberOffset(OFFSET_OF_OBJECT_MEMBER(ClassExt, instance_jfield_ids_)), count); } template inline ObjPtr ClassExt::GetInstanceJFieldIDs() { return GetFieldObject( OFFSET_OF_OBJECT_MEMBER(ClassExt, instance_jfield_ids_)); } template inline bool ClassExt::HasInstanceFieldPointerIdMarker() { ObjPtr arr(GetInstanceJFieldIDs()); return !arr.IsNull() && !arr->IsArrayInstance(); } template inline ObjPtr ClassExt::GetInstanceJFieldIDsPointerArray() { DCHECK(!HasInstanceFieldPointerIdMarker()); return down_cast(GetInstanceJFieldIDs().Ptr()); } template inline ObjPtr ClassExt::GetStaticJFieldIDs() { return GetFieldObject( OFFSET_OF_OBJECT_MEMBER(ClassExt, static_jfield_ids_)); } template inline ObjPtr ClassExt::GetStaticJFieldIDsPointerArray() { DCHECK(!HasStaticFieldPointerIdMarker()); return down_cast(GetStaticJFieldIDs().Ptr()); } template inline bool ClassExt::HasStaticFieldPointerIdMarker() { ObjPtr arr(GetStaticJFieldIDs()); return !arr.IsNull() && !arr->IsArrayInstance(); } template inline ObjPtr ClassExt::GetObsoleteClass() { return GetFieldObject( OFFSET_OF_OBJECT_MEMBER(ClassExt, obsolete_class_)); } template inline ObjPtr ClassExt::GetJMethodIDs() { return GetFieldObject( OFFSET_OF_OBJECT_MEMBER(ClassExt, jmethod_ids_)); } template inline ObjPtr ClassExt::GetJMethodIDsPointerArray() { DCHECK(!HasMethodPointerIdMarker()); return down_cast(GetJMethodIDs().Ptr()); } template inline bool ClassExt::HasMethodPointerIdMarker() { ObjPtr arr(GetJMethodIDs()); return !arr.IsNull() && !arr->IsArrayInstance(); } inline ObjPtr ClassExt::GetVerifyError() { return GetFieldObject(OFFSET_OF_OBJECT_MEMBER(ClassExt, verify_error_)); } inline ObjPtr> ClassExt::GetObsoleteDexCaches() { return GetFieldObject>( OFFSET_OF_OBJECT_MEMBER(ClassExt, obsolete_dex_caches_)); } template inline ObjPtr ClassExt::GetObsoleteMethods() { return GetFieldObject( OFFSET_OF_OBJECT_MEMBER(ClassExt, obsolete_methods_)); } inline ObjPtr ClassExt::GetOriginalDexFile() { return GetFieldObject(OFFSET_OF_OBJECT_MEMBER(ClassExt, original_dex_file_)); } template void ClassExt::VisitNativeRoots(Visitor& visitor, PointerSize pointer_size) { VisitMethods([&](ArtMethod* method) { method->VisitRoots(visitor, pointer_size); }, pointer_size); } template void ClassExt::VisitMethods(Visitor visitor, PointerSize pointer_size) { ObjPtr arr(GetObsoleteMethods()); if (!arr.IsNull()) { int32_t len = arr->GetLength(); for (int32_t i = 0; i < len; i++) { ArtMethod* method = arr->GetElementPtrSize(i, pointer_size); if (method != nullptr) { visitor(method); } } } } template void ClassExt::VisitJMethodIDs(Visitor v) { ObjPtr arr(GetJMethodIDs()); if (!arr.IsNull() && arr->IsArrayInstance()) { ObjPtr marr(down_cast(arr.Ptr())); int32_t len = marr->GetLength(); for (int32_t i = 0; i < len; i++) { jmethodID id = marr->GetElementPtrSize(i, kRuntimePointerSize); if (id != nullptr) { v(id, i); } } } } template void ClassExt::VisitJFieldIDs(Visitor v) { ObjPtr sarr_obj(GetStaticJFieldIDs()); if (!sarr_obj.IsNull() && sarr_obj->IsArrayInstance()) { ObjPtr sarr(down_cast(sarr_obj->AsArray().Ptr())); int32_t len = sarr->GetLength(); for (int32_t i = 0; i < len; i++) { jfieldID id = sarr->GetElementPtrSize(i, kRuntimePointerSize); if (id != nullptr) { v(id, i, true); } } } ObjPtr iarr_obj(GetInstanceJFieldIDs()); if (!iarr_obj.IsNull() && iarr_obj->IsArrayInstance()) { ObjPtr iarr(down_cast(iarr_obj->AsArray().Ptr())); int32_t len = iarr->GetLength(); for (int32_t i = 0; i < len; i++) { jfieldID id = iarr->GetElementPtrSize(i, kRuntimePointerSize); if (id != nullptr) { v(id, i, false); } } } } } // namespace mirror } // namespace art #endif // ART_RUNTIME_MIRROR_CLASS_EXT_INL_H_