|  | /* | 
|  | * Copyright (C) 2014 The Android Open Source Project | 
|  | * | 
|  | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | * you may not use this file except in compliance with the License. | 
|  | * You may obtain a copy of the License at | 
|  | * | 
|  | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, software | 
|  | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | * See the License for the specific language governing permissions and | 
|  | * limitations under the License. | 
|  | */ | 
|  |  | 
|  | #ifndef ART_RUNTIME_MIRROR_REFERENCE_H_ | 
|  | #define ART_RUNTIME_MIRROR_REFERENCE_H_ | 
|  |  | 
|  | #include "class.h" | 
|  | #include "gc_root.h" | 
|  | #include "object.h" | 
|  | #include "object_callbacks.h" | 
|  | #include "read_barrier_option.h" | 
|  | #include "thread.h" | 
|  |  | 
|  | namespace art { | 
|  |  | 
|  | namespace gc { | 
|  |  | 
|  | class ReferenceProcessor; | 
|  | class ReferenceQueue; | 
|  |  | 
|  | }  // namespace gc | 
|  |  | 
|  | struct ReferenceOffsets; | 
|  | struct FinalizerReferenceOffsets; | 
|  |  | 
|  | namespace mirror { | 
|  |  | 
|  | // C++ mirror of java.lang.ref.Reference | 
|  | class MANAGED Reference : public Object { | 
|  | public: | 
|  | // Size of java.lang.ref.Reference.class. | 
|  | static uint32_t ClassSize(); | 
|  |  | 
|  | // Size of an instance of java.lang.ref.Reference. | 
|  | static constexpr uint32_t InstanceSize() { | 
|  | return sizeof(Reference); | 
|  | } | 
|  |  | 
|  | static MemberOffset PendingNextOffset() { | 
|  | return OFFSET_OF_OBJECT_MEMBER(Reference, pending_next_); | 
|  | } | 
|  | static MemberOffset QueueOffset() { | 
|  | return OFFSET_OF_OBJECT_MEMBER(Reference, queue_); | 
|  | } | 
|  | static MemberOffset QueueNextOffset() { | 
|  | return OFFSET_OF_OBJECT_MEMBER(Reference, queue_next_); | 
|  | } | 
|  | static MemberOffset ReferentOffset() { | 
|  | return OFFSET_OF_OBJECT_MEMBER(Reference, referent_); | 
|  | } | 
|  | template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier> | 
|  | Object* GetReferent() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { | 
|  | return GetFieldObjectVolatile<Object, kDefaultVerifyFlags, kReadBarrierOption>( | 
|  | ReferentOffset()); | 
|  | } | 
|  | template<bool kTransactionActive> | 
|  | void SetReferent(Object* referent) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { | 
|  | SetFieldObjectVolatile<kTransactionActive>(ReferentOffset(), referent); | 
|  | } | 
|  | template<bool kTransactionActive> | 
|  | void ClearReferent() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { | 
|  | SetFieldObjectVolatile<kTransactionActive>(ReferentOffset(), nullptr); | 
|  | } | 
|  | // Volatile read/write is not necessary since the java pending next is only accessed from | 
|  | // the java threads for cleared references. Once these cleared references have a null referent, | 
|  | // we never end up reading their pending next from the GC again. | 
|  | Reference* GetPendingNext() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { | 
|  | return GetFieldObject<Reference>(PendingNextOffset()); | 
|  | } | 
|  | template<bool kTransactionActive> | 
|  | void SetPendingNext(Reference* pending_next) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { | 
|  | SetFieldObject<kTransactionActive>(PendingNextOffset(), pending_next); | 
|  | } | 
|  |  | 
|  | bool IsEnqueued() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { | 
|  | // Since the references are stored as cyclic lists it means that once enqueued, the pending | 
|  | // next is always non-null. | 
|  | return GetPendingNext() != nullptr; | 
|  | } | 
|  |  | 
|  | bool IsEnqueuable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); | 
|  |  | 
|  | template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier> | 
|  | static Class* GetJavaLangRefReference() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { | 
|  | DCHECK(!java_lang_ref_Reference_.IsNull()); | 
|  | return java_lang_ref_Reference_.Read<kReadBarrierOption>(); | 
|  | } | 
|  | static void SetClass(Class* klass); | 
|  | static void ResetClass(void); | 
|  | static void VisitRoots(RootCallback* callback, void* arg); | 
|  |  | 
|  | private: | 
|  | // Note: This avoids a read barrier, it should only be used by the GC. | 
|  | HeapReference<Object>* GetReferentReferenceAddr() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { | 
|  | return GetFieldObjectReferenceAddr<kDefaultVerifyFlags>(ReferentOffset()); | 
|  | } | 
|  |  | 
|  | // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses". | 
|  | HeapReference<Reference> pending_next_;  // Note this is Java volatile: | 
|  | HeapReference<Object> queue_;  // Note this is Java volatile: | 
|  | HeapReference<Reference> queue_next_;  // Note this is Java volatile: | 
|  | HeapReference<Object> referent_;  // Note this is Java volatile: | 
|  |  | 
|  | static GcRoot<Class> java_lang_ref_Reference_; | 
|  |  | 
|  | friend struct art::ReferenceOffsets;  // for verifying offset information | 
|  | friend class gc::ReferenceProcessor; | 
|  | friend class gc::ReferenceQueue; | 
|  | DISALLOW_IMPLICIT_CONSTRUCTORS(Reference); | 
|  | }; | 
|  |  | 
|  | // C++ mirror of java.lang.ref.FinalizerReference | 
|  | class MANAGED FinalizerReference : public Reference { | 
|  | public: | 
|  | static MemberOffset ZombieOffset() { | 
|  | return OFFSET_OF_OBJECT_MEMBER(FinalizerReference, zombie_); | 
|  | } | 
|  |  | 
|  | template<bool kTransactionActive> | 
|  | void SetZombie(Object* zombie) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { | 
|  | return SetFieldObjectVolatile<kTransactionActive>(ZombieOffset(), zombie); | 
|  | } | 
|  | Object* GetZombie() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { | 
|  | return GetFieldObjectVolatile<Object>(ZombieOffset()); | 
|  | } | 
|  |  | 
|  | private: | 
|  | HeapReference<FinalizerReference> next_; | 
|  | HeapReference<FinalizerReference> prev_; | 
|  | HeapReference<Object> zombie_; | 
|  |  | 
|  | friend struct art::FinalizerReferenceOffsets;  // for verifying offset information | 
|  | DISALLOW_IMPLICIT_CONSTRUCTORS(FinalizerReference); | 
|  | }; | 
|  |  | 
|  | }  // namespace mirror | 
|  | }  // namespace art | 
|  |  | 
|  | #endif  // ART_RUNTIME_MIRROR_REFERENCE_H_ |