blob: d6146f348f5776204fbc742db4e1f5a38559d043 [file] [log] [blame]
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -07001/*
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
Mathieu Chartierbad02672014-08-25 13:08:22 -070020#include "base/macros.h"
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -070021#include "base/mutex.h" // For Locks::mutator_lock_.
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -070022#include "mirror/object_reference.h"
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -070023
24namespace art {
Hiroshi Yamauchi3f64f252015-06-12 18:35:06 -070025class ArtField;
26class ArtMethod;
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -070027
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -080028namespace mirror {
29class Object;
30} // namespace mirror
31
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -070032template <size_t kBufferSize>
33class BufferedRootVisitor;
34
Mathieu Chartier4809d0a2015-04-07 10:39:04 -070035// 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
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -080038enum RootType {
39 kRootUnknown = 0,
40 kRootJNIGlobal,
41 kRootJNILocal,
42 kRootJavaFrame,
43 kRootNativeStack,
44 kRootStickyClass,
45 kRootThreadBlock,
46 kRootMonitorUsed,
47 kRootThreadObject,
48 kRootInternedString,
49 kRootDebugger,
50 kRootVMInternal,
51 kRootJNIMonitor,
52};
53std::ostream& operator<<(std::ostream& os, const RootType& root_type);
54
Mathieu Chartierd3ed9a32015-04-10 14:23:35 -070055// Only used by hprof. thread_id_ and type_ are only used by hprof.
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -080056class RootInfo {
57 public:
58 // Thread id 0 is for non thread roots.
59 explicit RootInfo(RootType type, uint32_t thread_id = 0)
60 : type_(type), thread_id_(thread_id) {
61 }
Andreas Gampe758a8012015-04-03 21:28:42 -070062 RootInfo(const RootInfo&) = default;
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -080063 virtual ~RootInfo() {
64 }
65 RootType GetType() const {
66 return type_;
67 }
68 uint32_t GetThreadId() const {
69 return thread_id_;
70 }
71 virtual void Describe(std::ostream& os) const {
72 os << "Type=" << type_ << " thread_id=" << thread_id_;
73 }
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -070074 std::string ToString() const;
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -080075
76 private:
77 const RootType type_;
78 const uint32_t thread_id_;
79};
80
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -070081inline std::ostream& operator<<(std::ostream& os, const RootInfo& root_info) {
82 root_info.Describe(os);
83 return os;
84}
85
86class RootVisitor {
87 public:
88 virtual ~RootVisitor() { }
89
Mathieu Chartierd3ed9a32015-04-10 14:23:35 -070090 // Single root version, not overridable.
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -070091 ALWAYS_INLINE void VisitRoot(mirror::Object** roots, const RootInfo& info)
92 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
93 VisitRoots(&roots, 1, info);
94 }
95
Mathieu Chartierd3ed9a32015-04-10 14:23:35 -070096 // Single root version, not overridable.
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -070097 ALWAYS_INLINE void VisitRootIfNonNull(mirror::Object** roots, const RootInfo& info)
98 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
99 if (*roots != nullptr) {
100 VisitRoot(roots, info);
101 }
102 }
103
104 virtual void VisitRoots(mirror::Object*** roots, size_t count, const RootInfo& info)
105 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
106
107 virtual void VisitRoots(mirror::CompressedReference<mirror::Object>** roots, size_t count,
108 const RootInfo& info)
109 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
110};
111
112// Only visits roots one at a time, doesn't handle updating roots. Used when performance isn't
113// critical.
114class SingleRootVisitor : public RootVisitor {
115 private:
116 void VisitRoots(mirror::Object*** roots, size_t count, const RootInfo& info) OVERRIDE
117 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
118 for (size_t i = 0; i < count; ++i) {
119 VisitRoot(*roots[i], info);
120 }
121 }
122
123 void VisitRoots(mirror::CompressedReference<mirror::Object>** roots, size_t count,
124 const RootInfo& info) OVERRIDE
125 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
126 for (size_t i = 0; i < count; ++i) {
127 VisitRoot(roots[i]->AsMirrorPtr(), info);
128 }
129 }
130
131 virtual void VisitRoot(mirror::Object* root, const RootInfo& info) = 0;
132};
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -0800133
Hiroshi Yamauchi3f64f252015-06-12 18:35:06 -0700134class GcRootSource {
135 public:
136 GcRootSource()
137 : field_(nullptr), method_(nullptr) {
138 }
139 explicit GcRootSource(ArtField* field)
140 : field_(field), method_(nullptr) {
141 }
142 explicit GcRootSource(ArtMethod* method)
143 : field_(nullptr), method_(method) {
144 }
145 ArtField* GetArtField() const {
146 return field_;
147 }
148 ArtMethod* GetArtMethod() const {
149 return method_;
150 }
151 bool HasArtField() const {
152 return field_ != nullptr;
153 }
154 bool HasArtMethod() const {
155 return method_ != nullptr;
156 }
157
158 private:
159 ArtField* const field_;
160 ArtMethod* const method_;
161
162 DISALLOW_COPY_AND_ASSIGN(GcRootSource);
163};
164
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700165template<class MirrorType>
Hiroshi Yamauchi9e47bfa2015-02-23 11:14:40 -0800166class GcRoot {
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700167 public:
168 template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
Hiroshi Yamauchi3f64f252015-06-12 18:35:06 -0700169 ALWAYS_INLINE MirrorType* Read(GcRootSource* gc_root_source = nullptr) const
170 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700171
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700172 void VisitRoot(RootVisitor* visitor, const RootInfo& info) const
173 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700174 DCHECK(!IsNull());
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700175 mirror::CompressedReference<mirror::Object>* roots[1] = { &root_ };
176 visitor->VisitRoots(roots, 1u, info);
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700177 DCHECK(!IsNull());
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700178 }
179
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700180 void VisitRootIfNonNull(RootVisitor* visitor, const RootInfo& info) const
181 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -0800182 if (!IsNull()) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700183 VisitRoot(visitor, info);
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -0800184 }
185 }
186
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700187 ALWAYS_INLINE mirror::CompressedReference<mirror::Object>* AddressWithoutBarrier() {
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700188 return &root_;
189 }
190
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700191 ALWAYS_INLINE bool IsNull() const {
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700192 // It's safe to null-check it without a read barrier.
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700193 return root_.IsNull();
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700194 }
195
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700196 ALWAYS_INLINE GcRoot(MirrorType* ref = nullptr) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
197
198 private:
Mathieu Chartier9086b652015-04-14 09:35:18 -0700199 // Root visitors take pointers to root_ and place the min CompressedReference** arrays. We use a
200 // CompressedReference<mirror::Object> here since it violates strict aliasing requirements to
201 // cast CompressedReference<MirrorType>* to CompressedReference<mirror::Object>*.
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700202 mutable mirror::CompressedReference<mirror::Object> root_;
203
204 template <size_t kBufferSize> friend class BufferedRootVisitor;
205};
206
207// Simple data structure for buffered root visiting to avoid virtual dispatch overhead. Currently
208// only for CompressedReferences since these are more common than the Object** roots which are only
209// for thread local roots.
210template <size_t kBufferSize>
211class BufferedRootVisitor {
212 public:
213 BufferedRootVisitor(RootVisitor* visitor, const RootInfo& root_info)
214 : visitor_(visitor), root_info_(root_info), buffer_pos_(0) {
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700215 }
216
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700217 ~BufferedRootVisitor() {
218 Flush();
219 }
220
221 template <class MirrorType>
222 ALWAYS_INLINE void VisitRootIfNonNull(GcRoot<MirrorType>& root)
223 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
224 if (!root.IsNull()) {
225 VisitRoot(root);
226 }
227 }
228
229 template <class MirrorType>
230 ALWAYS_INLINE void VisitRootIfNonNull(mirror::CompressedReference<MirrorType>* root)
231 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
232 if (!root->IsNull()) {
233 VisitRoot(root);
234 }
235 }
236
237 template <class MirrorType>
238 void VisitRoot(GcRoot<MirrorType>& root) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
239 VisitRoot(root.AddressWithoutBarrier());
240 }
241
242 template <class MirrorType>
243 void VisitRoot(mirror::CompressedReference<MirrorType>* root)
244 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
245 if (UNLIKELY(buffer_pos_ >= kBufferSize)) {
246 Flush();
247 }
248 roots_[buffer_pos_++] = root;
249 }
250
251 void Flush() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
252 visitor_->VisitRoots(roots_, buffer_pos_, root_info_);
253 buffer_pos_ = 0;
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700254 }
255
256 private:
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700257 RootVisitor* const visitor_;
258 RootInfo root_info_;
259 mirror::CompressedReference<mirror::Object>* roots_[kBufferSize];
260 size_t buffer_pos_;
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700261};
262
263} // namespace art
264
265#endif // ART_RUNTIME_GC_ROOT_H_