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 "base/enums.h"
21#include "class.h"
22#include "gc_root.h"
23#include "obj_ptr.h"
24#include "object.h"
25#include "object_callbacks.h"
26#include "read_barrier_option.h"
27#include "runtime.h"
28#include "thread.h"
29
30namespace art {
31
32namespace gc {
33
34class ReferenceProcessor;
35class ReferenceQueue;
36
37}  // namespace gc
38
39struct ReferenceOffsets;
40struct FinalizerReferenceOffsets;
41
42namespace mirror {
43
44// C++ mirror of java.lang.ref.Reference
45class MANAGED Reference : public Object {
46 public:
47  // Size of java.lang.ref.Reference.class.
48  static uint32_t ClassSize(PointerSize pointer_size);
49
50  // Size of an instance of java.lang.ref.Reference.
51  static constexpr uint32_t InstanceSize() {
52    return sizeof(Reference);
53  }
54
55  static MemberOffset PendingNextOffset() {
56    return OFFSET_OF_OBJECT_MEMBER(Reference, pending_next_);
57  }
58  static MemberOffset QueueOffset() {
59    return OFFSET_OF_OBJECT_MEMBER(Reference, queue_);
60  }
61  static MemberOffset QueueNextOffset() {
62    return OFFSET_OF_OBJECT_MEMBER(Reference, queue_next_);
63  }
64  static MemberOffset ReferentOffset() {
65    return OFFSET_OF_OBJECT_MEMBER(Reference, referent_);
66  }
67  template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
68  Object* GetReferent() REQUIRES_SHARED(Locks::mutator_lock_) {
69    return GetFieldObjectVolatile<Object, kDefaultVerifyFlags, kReadBarrierOption>(
70        ReferentOffset());
71  }
72  template<bool kTransactionActive>
73  void SetReferent(ObjPtr<Object> referent) REQUIRES_SHARED(Locks::mutator_lock_);
74  template<bool kTransactionActive>
75  void ClearReferent() REQUIRES_SHARED(Locks::mutator_lock_) {
76    SetFieldObjectVolatile<kTransactionActive>(ReferentOffset(), nullptr);
77  }
78
79  template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
80  Reference* GetPendingNext() REQUIRES_SHARED(Locks::mutator_lock_) {
81    return GetFieldObject<Reference, kDefaultVerifyFlags, kReadBarrierOption>(PendingNextOffset());
82  }
83
84  void SetPendingNext(ObjPtr<Reference> pending_next) REQUIRES_SHARED(Locks::mutator_lock_);
85
86  // Returns true if the reference's pendingNext is null, indicating it is
87  // okay to process this reference.
88  //
89  // If pendingNext is not null, then one of the following cases holds:
90  // 1. The reference has already been enqueued to a java ReferenceQueue. In
91  // this case the referent should not be considered for reference processing
92  // ever again.
93  // 2. The reference is currently part of a list of references that may
94  // shortly be enqueued on a java ReferenceQueue. In this case the reference
95  // should not be processed again until and unless the reference has been
96  // removed from the list after having determined the reference is not ready
97  // to be enqueued on a java ReferenceQueue.
98  bool IsUnprocessed() REQUIRES_SHARED(Locks::mutator_lock_) {
99    return GetPendingNext<kWithoutReadBarrier>() == nullptr;
100  }
101
102  template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
103  static Class* GetJavaLangRefReference() REQUIRES_SHARED(Locks::mutator_lock_) {
104    DCHECK(!java_lang_ref_Reference_.IsNull());
105    return java_lang_ref_Reference_.Read<kReadBarrierOption>();
106  }
107  static void SetClass(ObjPtr<Class> klass);
108  static void ResetClass();
109  static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
110
111 private:
112  // Note: This avoids a read barrier, it should only be used by the GC.
113  HeapReference<Object>* GetReferentReferenceAddr() REQUIRES_SHARED(Locks::mutator_lock_) {
114    return GetFieldObjectReferenceAddr<kDefaultVerifyFlags>(ReferentOffset());
115  }
116
117  // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
118  HeapReference<Reference> pending_next_;
119  HeapReference<Object> queue_;
120  HeapReference<Reference> queue_next_;
121  HeapReference<Object> referent_;  // Note this is Java volatile:
122
123  static GcRoot<Class> java_lang_ref_Reference_;
124
125  friend struct art::ReferenceOffsets;  // for verifying offset information
126  friend class gc::ReferenceProcessor;
127  friend class gc::ReferenceQueue;
128  DISALLOW_IMPLICIT_CONSTRUCTORS(Reference);
129};
130
131// C++ mirror of java.lang.ref.FinalizerReference
132class MANAGED FinalizerReference : public Reference {
133 public:
134  static MemberOffset ZombieOffset() {
135    return OFFSET_OF_OBJECT_MEMBER(FinalizerReference, zombie_);
136  }
137
138  template<bool kTransactionActive>
139  void SetZombie(ObjPtr<Object> zombie) REQUIRES_SHARED(Locks::mutator_lock_);
140
141  Object* GetZombie() REQUIRES_SHARED(Locks::mutator_lock_) {
142    return GetFieldObjectVolatile<Object>(ZombieOffset());
143  }
144
145 private:
146  HeapReference<FinalizerReference> next_;
147  HeapReference<FinalizerReference> prev_;
148  HeapReference<Object> zombie_;
149
150  friend struct art::FinalizerReferenceOffsets;  // for verifying offset information
151  DISALLOW_IMPLICIT_CONSTRUCTORS(FinalizerReference);
152};
153
154}  // namespace mirror
155}  // namespace art
156
157#endif  // ART_RUNTIME_MIRROR_REFERENCE_H_
158