1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ART_RUNTIME_MIRROR_REFERENCE_H_
18 #define ART_RUNTIME_MIRROR_REFERENCE_H_
19 
20 #include "class.h"
21 #include "gc_root.h"
22 #include "object.h"
23 #include "object_callbacks.h"
24 #include "read_barrier_option.h"
25 #include "runtime.h"
26 #include "thread.h"
27 
28 namespace art {
29 
30 namespace gc {
31 
32 class ReferenceProcessor;
33 class ReferenceQueue;
34 
35 }  // namespace gc
36 
37 struct ReferenceOffsets;
38 struct FinalizerReferenceOffsets;
39 
40 namespace mirror {
41 
42 // C++ mirror of java.lang.ref.Reference
43 class MANAGED Reference : public Object {
44  public:
45   // Size of java.lang.ref.Reference.class.
46   static uint32_t ClassSize(size_t pointer_size);
47 
48   // Size of an instance of java.lang.ref.Reference.
InstanceSize()49   static constexpr uint32_t InstanceSize() {
50     return sizeof(Reference);
51   }
52 
PendingNextOffset()53   static MemberOffset PendingNextOffset() {
54     return OFFSET_OF_OBJECT_MEMBER(Reference, pending_next_);
55   }
QueueOffset()56   static MemberOffset QueueOffset() {
57     return OFFSET_OF_OBJECT_MEMBER(Reference, queue_);
58   }
QueueNextOffset()59   static MemberOffset QueueNextOffset() {
60     return OFFSET_OF_OBJECT_MEMBER(Reference, queue_next_);
61   }
ReferentOffset()62   static MemberOffset ReferentOffset() {
63     return OFFSET_OF_OBJECT_MEMBER(Reference, referent_);
64   }
65   template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
GetReferent()66   Object* GetReferent() SHARED_REQUIRES(Locks::mutator_lock_) {
67     return GetFieldObjectVolatile<Object, kDefaultVerifyFlags, kReadBarrierOption>(
68         ReferentOffset());
69   }
70   template<bool kTransactionActive>
SetReferent(Object * referent)71   void SetReferent(Object* referent) SHARED_REQUIRES(Locks::mutator_lock_) {
72     SetFieldObjectVolatile<kTransactionActive>(ReferentOffset(), referent);
73   }
74   template<bool kTransactionActive>
ClearReferent()75   void ClearReferent() SHARED_REQUIRES(Locks::mutator_lock_) {
76     SetFieldObjectVolatile<kTransactionActive>(ReferentOffset(), nullptr);
77   }
78 
GetPendingNext()79   Reference* GetPendingNext() SHARED_REQUIRES(Locks::mutator_lock_) {
80     return GetFieldObject<Reference>(PendingNextOffset());
81   }
82 
SetPendingNext(Reference * pending_next)83   void SetPendingNext(Reference* pending_next)
84       SHARED_REQUIRES(Locks::mutator_lock_) {
85     if (Runtime::Current()->IsActiveTransaction()) {
86       SetFieldObject<true>(PendingNextOffset(), pending_next);
87     } else {
88       SetFieldObject<false>(PendingNextOffset(), pending_next);
89     }
90   }
91 
92   // Returns true if the reference's pendingNext is null, indicating it is
93   // okay to process this reference.
94   //
95   // If pendingNext is not null, then one of the following cases holds:
96   // 1. The reference has already been enqueued to a java ReferenceQueue. In
97   // this case the referent should not be considered for reference processing
98   // ever again.
99   // 2. The reference is currently part of a list of references that may
100   // shortly be enqueued on a java ReferenceQueue. In this case the reference
101   // should not be processed again until and unless the reference has been
102   // removed from the list after having determined the reference is not ready
103   // to be enqueued on a java ReferenceQueue.
IsUnprocessed()104   bool IsUnprocessed() SHARED_REQUIRES(Locks::mutator_lock_) {
105     return GetPendingNext() == nullptr;
106   }
107 
108   template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
GetJavaLangRefReference()109   static Class* GetJavaLangRefReference() SHARED_REQUIRES(Locks::mutator_lock_) {
110     DCHECK(!java_lang_ref_Reference_.IsNull());
111     return java_lang_ref_Reference_.Read<kReadBarrierOption>();
112   }
113   static void SetClass(Class* klass);
114   static void ResetClass();
115   static void VisitRoots(RootVisitor* visitor) SHARED_REQUIRES(Locks::mutator_lock_);
116 
117  private:
118   // Note: This avoids a read barrier, it should only be used by the GC.
GetReferentReferenceAddr()119   HeapReference<Object>* GetReferentReferenceAddr() SHARED_REQUIRES(Locks::mutator_lock_) {
120     return GetFieldObjectReferenceAddr<kDefaultVerifyFlags>(ReferentOffset());
121   }
122 
123   // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
124   HeapReference<Reference> pending_next_;
125   HeapReference<Object> queue_;
126   HeapReference<Reference> queue_next_;
127   HeapReference<Object> referent_;  // Note this is Java volatile:
128 
129   static GcRoot<Class> java_lang_ref_Reference_;
130 
131   friend struct art::ReferenceOffsets;  // for verifying offset information
132   friend class gc::ReferenceProcessor;
133   friend class gc::ReferenceQueue;
134   DISALLOW_IMPLICIT_CONSTRUCTORS(Reference);
135 };
136 
137 // C++ mirror of java.lang.ref.FinalizerReference
138 class MANAGED FinalizerReference : public Reference {
139  public:
ZombieOffset()140   static MemberOffset ZombieOffset() {
141     return OFFSET_OF_OBJECT_MEMBER(FinalizerReference, zombie_);
142   }
143 
144   template<bool kTransactionActive>
SetZombie(Object * zombie)145   void SetZombie(Object* zombie) SHARED_REQUIRES(Locks::mutator_lock_) {
146     return SetFieldObjectVolatile<kTransactionActive>(ZombieOffset(), zombie);
147   }
GetZombie()148   Object* GetZombie() SHARED_REQUIRES(Locks::mutator_lock_) {
149     return GetFieldObjectVolatile<Object>(ZombieOffset());
150   }
151 
152  private:
153   HeapReference<FinalizerReference> next_;
154   HeapReference<FinalizerReference> prev_;
155   HeapReference<Object> zombie_;
156 
157   friend struct art::FinalizerReferenceOffsets;  // for verifying offset information
158   DISALLOW_IMPLICIT_CONSTRUCTORS(FinalizerReference);
159 };
160 
161 }  // namespace mirror
162 }  // namespace art
163 
164 #endif  // ART_RUNTIME_MIRROR_REFERENCE_H_
165