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_GC_ROOT_H_
18#define ART_RUNTIME_GC_ROOT_H_
19
20#include "base/macros.h"
21#include "base/mutex.h"       // For Locks::mutator_lock_.
22#include "mirror/object_reference.h"
23
24namespace art {
25class ArtField;
26class ArtMethod;
27
28namespace mirror {
29class Object;
30}  // namespace mirror
31
32template <size_t kBufferSize>
33class BufferedRootVisitor;
34
35// Dependent on pointer size so that we don't have frames that are too big on 64 bit.
36static const size_t kDefaultBufferedRootCount = 1024 / sizeof(void*);
37
38enum RootType {
39  kRootUnknown = 0,
40  kRootJNIGlobal,
41  kRootJNILocal,
42  kRootJavaFrame,
43  kRootNativeStack,
44  kRootStickyClass,
45  kRootThreadBlock,
46  kRootMonitorUsed,
47  kRootThreadObject,
48  kRootInternedString,
49  kRootFinalizing,  // used for HPROF's conversion to HprofHeapTag
50  kRootDebugger,
51  kRootReferenceCleanup,  // used for HPROF's conversion to HprofHeapTag
52  kRootVMInternal,
53  kRootJNIMonitor,
54};
55std::ostream& operator<<(std::ostream& os, const RootType& root_type);
56
57// Only used by hprof. thread_id_ and type_ are only used by hprof.
58class RootInfo {
59 public:
60  // Thread id 0 is for non thread roots.
61  explicit RootInfo(RootType type, uint32_t thread_id = 0)
62     : type_(type), thread_id_(thread_id) {
63  }
64  RootInfo(const RootInfo&) = default;
65  virtual ~RootInfo() {
66  }
67  RootType GetType() const {
68    return type_;
69  }
70  uint32_t GetThreadId() const {
71    return thread_id_;
72  }
73  virtual void Describe(std::ostream& os) const {
74    os << "Type=" << type_ << " thread_id=" << thread_id_;
75  }
76  std::string ToString() const;
77
78 private:
79  const RootType type_;
80  const uint32_t thread_id_;
81};
82
83inline std::ostream& operator<<(std::ostream& os, const RootInfo& root_info) {
84  root_info.Describe(os);
85  return os;
86}
87
88class RootVisitor {
89 public:
90  virtual ~RootVisitor() { }
91
92  // Single root version, not overridable.
93  ALWAYS_INLINE void VisitRoot(mirror::Object** root, const RootInfo& info)
94      SHARED_REQUIRES(Locks::mutator_lock_) {
95    VisitRoots(&root, 1, info);
96  }
97
98  // Single root version, not overridable.
99  ALWAYS_INLINE void VisitRootIfNonNull(mirror::Object** root, const RootInfo& info)
100      SHARED_REQUIRES(Locks::mutator_lock_) {
101    if (*root != nullptr) {
102      VisitRoot(root, info);
103    }
104  }
105
106  virtual void VisitRoots(mirror::Object*** roots, size_t count, const RootInfo& info)
107      SHARED_REQUIRES(Locks::mutator_lock_) = 0;
108
109  virtual void VisitRoots(mirror::CompressedReference<mirror::Object>** roots, size_t count,
110                          const RootInfo& info)
111      SHARED_REQUIRES(Locks::mutator_lock_) = 0;
112};
113
114// Only visits roots one at a time, doesn't handle updating roots. Used when performance isn't
115// critical.
116class SingleRootVisitor : public RootVisitor {
117 private:
118  void VisitRoots(mirror::Object*** roots, size_t count, const RootInfo& info) OVERRIDE
119      SHARED_REQUIRES(Locks::mutator_lock_) {
120    for (size_t i = 0; i < count; ++i) {
121      VisitRoot(*roots[i], info);
122    }
123  }
124
125  void VisitRoots(mirror::CompressedReference<mirror::Object>** roots, size_t count,
126                          const RootInfo& info) OVERRIDE
127      SHARED_REQUIRES(Locks::mutator_lock_) {
128    for (size_t i = 0; i < count; ++i) {
129      VisitRoot(roots[i]->AsMirrorPtr(), info);
130    }
131  }
132
133  virtual void VisitRoot(mirror::Object* root, const RootInfo& info) = 0;
134};
135
136class GcRootSource {
137 public:
138  GcRootSource()
139      : field_(nullptr), method_(nullptr) {
140  }
141  explicit GcRootSource(ArtField* field)
142      : field_(field), method_(nullptr) {
143  }
144  explicit GcRootSource(ArtMethod* method)
145      : field_(nullptr), method_(method) {
146  }
147  ArtField* GetArtField() const {
148    return field_;
149  }
150  ArtMethod* GetArtMethod() const {
151    return method_;
152  }
153  bool HasArtField() const {
154    return field_ != nullptr;
155  }
156  bool HasArtMethod() const {
157    return method_ != nullptr;
158  }
159
160 private:
161  ArtField* const field_;
162  ArtMethod* const method_;
163
164  DISALLOW_COPY_AND_ASSIGN(GcRootSource);
165};
166
167template<class MirrorType>
168class GcRoot {
169 public:
170  template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
171  ALWAYS_INLINE MirrorType* Read(GcRootSource* gc_root_source = nullptr) const
172      SHARED_REQUIRES(Locks::mutator_lock_);
173
174  void VisitRoot(RootVisitor* visitor, const RootInfo& info) const
175      SHARED_REQUIRES(Locks::mutator_lock_) {
176    DCHECK(!IsNull());
177    mirror::CompressedReference<mirror::Object>* roots[1] = { &root_ };
178    visitor->VisitRoots(roots, 1u, info);
179    DCHECK(!IsNull());
180  }
181
182  void VisitRootIfNonNull(RootVisitor* visitor, const RootInfo& info) const
183      SHARED_REQUIRES(Locks::mutator_lock_) {
184    if (!IsNull()) {
185      VisitRoot(visitor, info);
186    }
187  }
188
189  ALWAYS_INLINE mirror::CompressedReference<mirror::Object>* AddressWithoutBarrier() {
190    return &root_;
191  }
192
193  ALWAYS_INLINE bool IsNull() const {
194    // It's safe to null-check it without a read barrier.
195    return root_.IsNull();
196  }
197
198  ALWAYS_INLINE GcRoot(MirrorType* ref = nullptr) SHARED_REQUIRES(Locks::mutator_lock_);
199
200 private:
201  // Root visitors take pointers to root_ and place them in CompressedReference** arrays. We use a
202  // CompressedReference<mirror::Object> here since it violates strict aliasing requirements to
203  // cast CompressedReference<MirrorType>* to CompressedReference<mirror::Object>*.
204  mutable mirror::CompressedReference<mirror::Object> root_;
205
206  template <size_t kBufferSize> friend class BufferedRootVisitor;
207};
208
209// Simple data structure for buffered root visiting to avoid virtual dispatch overhead. Currently
210// only for CompressedReferences since these are more common than the Object** roots which are only
211// for thread local roots.
212template <size_t kBufferSize>
213class BufferedRootVisitor {
214 public:
215  BufferedRootVisitor(RootVisitor* visitor, const RootInfo& root_info)
216      : visitor_(visitor), root_info_(root_info), buffer_pos_(0) {
217  }
218
219  ~BufferedRootVisitor() {
220    Flush();
221  }
222
223  template <class MirrorType>
224  ALWAYS_INLINE void VisitRootIfNonNull(GcRoot<MirrorType>& root)
225      SHARED_REQUIRES(Locks::mutator_lock_) {
226    if (!root.IsNull()) {
227      VisitRoot(root);
228    }
229  }
230
231  template <class MirrorType>
232  ALWAYS_INLINE void VisitRootIfNonNull(mirror::CompressedReference<MirrorType>* root)
233      SHARED_REQUIRES(Locks::mutator_lock_) {
234    if (!root->IsNull()) {
235      VisitRoot(root);
236    }
237  }
238
239  template <class MirrorType>
240  void VisitRoot(GcRoot<MirrorType>& root) SHARED_REQUIRES(Locks::mutator_lock_) {
241    VisitRoot(root.AddressWithoutBarrier());
242  }
243
244  template <class MirrorType>
245  void VisitRoot(mirror::CompressedReference<MirrorType>* root)
246      SHARED_REQUIRES(Locks::mutator_lock_) {
247    if (UNLIKELY(buffer_pos_ >= kBufferSize)) {
248      Flush();
249    }
250    roots_[buffer_pos_++] = root;
251  }
252
253  void Flush() SHARED_REQUIRES(Locks::mutator_lock_) {
254    visitor_->VisitRoots(roots_, buffer_pos_, root_info_);
255    buffer_pos_ = 0;
256  }
257
258 private:
259  RootVisitor* const visitor_;
260  RootInfo root_info_;
261  mirror::CompressedReference<mirror::Object>* roots_[kBufferSize];
262  size_t buffer_pos_;
263};
264
265}  // namespace art
266
267#endif  // ART_RUNTIME_GC_ROOT_H_
268