blob: 0894e9bee5397bcb9c720d8ba916fae785cfaded [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;
Andreas Gampec73cb642017-02-22 10:11:30 -080027template<class MirrorType> class ObjPtr;
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -070028
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -080029namespace mirror {
30class Object;
31} // namespace mirror
32
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -070033template <size_t kBufferSize>
34class BufferedRootVisitor;
35
Mathieu Chartier4809d0a2015-04-07 10:39:04 -070036// Dependent on pointer size so that we don't have frames that are too big on 64 bit.
37static const size_t kDefaultBufferedRootCount = 1024 / sizeof(void*);
38
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -080039enum RootType {
40 kRootUnknown = 0,
41 kRootJNIGlobal,
42 kRootJNILocal,
43 kRootJavaFrame,
44 kRootNativeStack,
45 kRootStickyClass,
46 kRootThreadBlock,
47 kRootMonitorUsed,
48 kRootThreadObject,
49 kRootInternedString,
Man Cao1ed11b92015-06-11 22:47:35 -070050 kRootFinalizing, // used for HPROF's conversion to HprofHeapTag
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -080051 kRootDebugger,
Man Cao1ed11b92015-06-11 22:47:35 -070052 kRootReferenceCleanup, // used for HPROF's conversion to HprofHeapTag
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -080053 kRootVMInternal,
54 kRootJNIMonitor,
55};
56std::ostream& operator<<(std::ostream& os, const RootType& root_type);
57
Mathieu Chartierd3ed9a32015-04-10 14:23:35 -070058// Only used by hprof. thread_id_ and type_ are only used by hprof.
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -080059class RootInfo {
60 public:
61 // Thread id 0 is for non thread roots.
62 explicit RootInfo(RootType type, uint32_t thread_id = 0)
63 : type_(type), thread_id_(thread_id) {
64 }
Andreas Gampe758a8012015-04-03 21:28:42 -070065 RootInfo(const RootInfo&) = default;
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -080066 virtual ~RootInfo() {
67 }
68 RootType GetType() const {
69 return type_;
70 }
71 uint32_t GetThreadId() const {
72 return thread_id_;
73 }
74 virtual void Describe(std::ostream& os) const {
75 os << "Type=" << type_ << " thread_id=" << thread_id_;
76 }
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -070077 std::string ToString() const;
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -080078
79 private:
80 const RootType type_;
81 const uint32_t thread_id_;
82};
83
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -070084inline std::ostream& operator<<(std::ostream& os, const RootInfo& root_info) {
85 root_info.Describe(os);
86 return os;
87}
88
Andreas Gampe585da952016-12-02 14:52:29 -080089// Not all combinations of flags are valid. You may not visit all roots as well as the new roots
90// (no logical reason to do this). You also may not start logging new roots and stop logging new
91// roots (also no logical reason to do this).
92//
93// The precise flag ensures that more metadata is supplied. An example is vreg data for compiled
94// method frames.
95enum VisitRootFlags : uint8_t {
96 kVisitRootFlagAllRoots = 0x1,
97 kVisitRootFlagNewRoots = 0x2,
98 kVisitRootFlagStartLoggingNewRoots = 0x4,
99 kVisitRootFlagStopLoggingNewRoots = 0x8,
100 kVisitRootFlagClearRootLog = 0x10,
101 kVisitRootFlagClassLoader = 0x20,
102 kVisitRootFlagPrecise = 0x80,
103};
104
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700105class RootVisitor {
106 public:
107 virtual ~RootVisitor() { }
108
Mathieu Chartierd3ed9a32015-04-10 14:23:35 -0700109 // Single root version, not overridable.
Mathieu Chartier9b1c71e2015-09-02 18:51:54 -0700110 ALWAYS_INLINE void VisitRoot(mirror::Object** root, const RootInfo& info)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700111 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier9b1c71e2015-09-02 18:51:54 -0700112 VisitRoots(&root, 1, info);
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700113 }
114
Mathieu Chartierd3ed9a32015-04-10 14:23:35 -0700115 // Single root version, not overridable.
Mathieu Chartier9b1c71e2015-09-02 18:51:54 -0700116 ALWAYS_INLINE void VisitRootIfNonNull(mirror::Object** root, const RootInfo& info)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700117 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier9b1c71e2015-09-02 18:51:54 -0700118 if (*root != nullptr) {
119 VisitRoot(root, info);
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700120 }
121 }
122
123 virtual void VisitRoots(mirror::Object*** roots, size_t count, const RootInfo& info)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700124 REQUIRES_SHARED(Locks::mutator_lock_) = 0;
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700125
126 virtual void VisitRoots(mirror::CompressedReference<mirror::Object>** roots, size_t count,
127 const RootInfo& info)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700128 REQUIRES_SHARED(Locks::mutator_lock_) = 0;
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700129};
130
131// Only visits roots one at a time, doesn't handle updating roots. Used when performance isn't
132// critical.
133class SingleRootVisitor : public RootVisitor {
134 private:
135 void VisitRoots(mirror::Object*** roots, size_t count, const RootInfo& info) OVERRIDE
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700136 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700137 for (size_t i = 0; i < count; ++i) {
138 VisitRoot(*roots[i], info);
139 }
140 }
141
142 void VisitRoots(mirror::CompressedReference<mirror::Object>** roots, size_t count,
143 const RootInfo& info) OVERRIDE
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700144 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700145 for (size_t i = 0; i < count; ++i) {
146 VisitRoot(roots[i]->AsMirrorPtr(), info);
147 }
148 }
149
150 virtual void VisitRoot(mirror::Object* root, const RootInfo& info) = 0;
151};
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -0800152
Hiroshi Yamauchi3f64f252015-06-12 18:35:06 -0700153class GcRootSource {
154 public:
155 GcRootSource()
156 : field_(nullptr), method_(nullptr) {
157 }
158 explicit GcRootSource(ArtField* field)
159 : field_(field), method_(nullptr) {
160 }
161 explicit GcRootSource(ArtMethod* method)
162 : field_(nullptr), method_(method) {
163 }
164 ArtField* GetArtField() const {
165 return field_;
166 }
167 ArtMethod* GetArtMethod() const {
168 return method_;
169 }
170 bool HasArtField() const {
171 return field_ != nullptr;
172 }
173 bool HasArtMethod() const {
174 return method_ != nullptr;
175 }
176
177 private:
178 ArtField* const field_;
179 ArtMethod* const method_;
180
181 DISALLOW_COPY_AND_ASSIGN(GcRootSource);
182};
183
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700184template<class MirrorType>
Hiroshi Yamauchi9e47bfa2015-02-23 11:14:40 -0800185class GcRoot {
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700186 public:
187 template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
Hiroshi Yamauchi3f64f252015-06-12 18:35:06 -0700188 ALWAYS_INLINE MirrorType* Read(GcRootSource* gc_root_source = nullptr) const
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700189 REQUIRES_SHARED(Locks::mutator_lock_);
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700190
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700191 void VisitRoot(RootVisitor* visitor, const RootInfo& info) const
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700192 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700193 DCHECK(!IsNull());
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700194 mirror::CompressedReference<mirror::Object>* roots[1] = { &root_ };
195 visitor->VisitRoots(roots, 1u, info);
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700196 DCHECK(!IsNull());
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700197 }
198
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700199 void VisitRootIfNonNull(RootVisitor* visitor, const RootInfo& info) const
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700200 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -0800201 if (!IsNull()) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700202 VisitRoot(visitor, info);
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -0800203 }
204 }
205
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700206 ALWAYS_INLINE mirror::CompressedReference<mirror::Object>* AddressWithoutBarrier() {
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700207 return &root_;
208 }
209
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700210 ALWAYS_INLINE bool IsNull() const {
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700211 // It's safe to null-check it without a read barrier.
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700212 return root_.IsNull();
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700213 }
214
Mathieu Chartier65975772016-08-05 10:46:36 -0700215 ALWAYS_INLINE GcRoot() {}
Mathieu Chartier3398c782016-09-30 10:27:43 -0700216 explicit ALWAYS_INLINE GcRoot(MirrorType* ref)
217 REQUIRES_SHARED(Locks::mutator_lock_);
Andreas Gampec73cb642017-02-22 10:11:30 -0800218 explicit ALWAYS_INLINE GcRoot(ObjPtr<MirrorType> ref)
Mathieu Chartier3398c782016-09-30 10:27:43 -0700219 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700220
221 private:
Roland Levillain0d5a2812015-11-13 10:07:31 +0000222 // Root visitors take pointers to root_ and place them in CompressedReference** arrays. We use a
Mathieu Chartier9086b652015-04-14 09:35:18 -0700223 // CompressedReference<mirror::Object> here since it violates strict aliasing requirements to
224 // cast CompressedReference<MirrorType>* to CompressedReference<mirror::Object>*.
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700225 mutable mirror::CompressedReference<mirror::Object> root_;
226
227 template <size_t kBufferSize> friend class BufferedRootVisitor;
228};
229
230// Simple data structure for buffered root visiting to avoid virtual dispatch overhead. Currently
231// only for CompressedReferences since these are more common than the Object** roots which are only
232// for thread local roots.
233template <size_t kBufferSize>
234class BufferedRootVisitor {
235 public:
236 BufferedRootVisitor(RootVisitor* visitor, const RootInfo& root_info)
237 : visitor_(visitor), root_info_(root_info), buffer_pos_(0) {
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700238 }
239
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700240 ~BufferedRootVisitor() {
241 Flush();
242 }
243
244 template <class MirrorType>
245 ALWAYS_INLINE void VisitRootIfNonNull(GcRoot<MirrorType>& root)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700246 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700247 if (!root.IsNull()) {
248 VisitRoot(root);
249 }
250 }
251
252 template <class MirrorType>
253 ALWAYS_INLINE void VisitRootIfNonNull(mirror::CompressedReference<MirrorType>* root)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700254 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700255 if (!root->IsNull()) {
256 VisitRoot(root);
257 }
258 }
259
260 template <class MirrorType>
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700261 void VisitRoot(GcRoot<MirrorType>& root) REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700262 VisitRoot(root.AddressWithoutBarrier());
263 }
264
265 template <class MirrorType>
266 void VisitRoot(mirror::CompressedReference<MirrorType>* root)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700267 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700268 if (UNLIKELY(buffer_pos_ >= kBufferSize)) {
269 Flush();
270 }
271 roots_[buffer_pos_++] = root;
272 }
273
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700274 void Flush() REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700275 visitor_->VisitRoots(roots_, buffer_pos_, root_info_);
276 buffer_pos_ = 0;
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700277 }
278
279 private:
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700280 RootVisitor* const visitor_;
281 RootInfo root_info_;
282 mirror::CompressedReference<mirror::Object>* roots_[kBufferSize];
283 size_t buffer_pos_;
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700284};
285
Mathieu Chartier58c3f6a2016-12-01 14:21:11 -0800286class UnbufferedRootVisitor {
287 public:
288 UnbufferedRootVisitor(RootVisitor* visitor, const RootInfo& root_info)
289 : visitor_(visitor), root_info_(root_info) {}
290
291 template <class MirrorType>
292 ALWAYS_INLINE void VisitRootIfNonNull(GcRoot<MirrorType>& root) const
293 REQUIRES_SHARED(Locks::mutator_lock_) {
294 if (!root.IsNull()) {
295 VisitRoot(root);
296 }
297 }
298
299 template <class MirrorType>
300 ALWAYS_INLINE void VisitRootIfNonNull(mirror::CompressedReference<MirrorType>* root) const
301 REQUIRES_SHARED(Locks::mutator_lock_) {
302 if (!root->IsNull()) {
303 VisitRoot(root);
304 }
305 }
306
307 template <class MirrorType>
308 void VisitRoot(GcRoot<MirrorType>& root) const REQUIRES_SHARED(Locks::mutator_lock_) {
309 VisitRoot(root.AddressWithoutBarrier());
310 }
311
312 template <class MirrorType>
313 void VisitRoot(mirror::CompressedReference<MirrorType>* root) const
314 REQUIRES_SHARED(Locks::mutator_lock_) {
315 visitor_->VisitRoots(&root, 1, root_info_);
316 }
317
318 private:
319 RootVisitor* const visitor_;
320 RootInfo root_info_;
321};
322
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700323} // namespace art
324
325#endif // ART_RUNTIME_GC_ROOT_H_