blob: 2f4da3f2cab696bd2429814a371513c696f8665d [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 {
25
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -080026namespace mirror {
27class Object;
28} // namespace mirror
29
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -070030template <size_t kBufferSize>
31class BufferedRootVisitor;
32
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -080033enum RootType {
34 kRootUnknown = 0,
35 kRootJNIGlobal,
36 kRootJNILocal,
37 kRootJavaFrame,
38 kRootNativeStack,
39 kRootStickyClass,
40 kRootThreadBlock,
41 kRootMonitorUsed,
42 kRootThreadObject,
43 kRootInternedString,
44 kRootDebugger,
45 kRootVMInternal,
46 kRootJNIMonitor,
47};
48std::ostream& operator<<(std::ostream& os, const RootType& root_type);
49
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -070050// Only used by hprof. tid and root_type are only used by hprof.
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -080051class RootInfo {
52 public:
53 // Thread id 0 is for non thread roots.
54 explicit RootInfo(RootType type, uint32_t thread_id = 0)
55 : type_(type), thread_id_(thread_id) {
56 }
Andreas Gampe758a8012015-04-03 21:28:42 -070057 RootInfo(const RootInfo&) = default;
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -080058 virtual ~RootInfo() {
59 }
60 RootType GetType() const {
61 return type_;
62 }
63 uint32_t GetThreadId() const {
64 return thread_id_;
65 }
66 virtual void Describe(std::ostream& os) const {
67 os << "Type=" << type_ << " thread_id=" << thread_id_;
68 }
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -070069 std::string ToString() const;
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -080070
71 private:
72 const RootType type_;
73 const uint32_t thread_id_;
74};
75
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -070076inline std::ostream& operator<<(std::ostream& os, const RootInfo& root_info) {
77 root_info.Describe(os);
78 return os;
79}
80
81class RootVisitor {
82 public:
83 virtual ~RootVisitor() { }
84
85 // Single root versions, not overridable.
86 ALWAYS_INLINE void VisitRoot(mirror::Object** roots, const RootInfo& info)
87 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
88 VisitRoots(&roots, 1, info);
89 }
90
91 ALWAYS_INLINE void VisitRootIfNonNull(mirror::Object** roots, const RootInfo& info)
92 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
93 if (*roots != nullptr) {
94 VisitRoot(roots, info);
95 }
96 }
97
98 virtual void VisitRoots(mirror::Object*** roots, size_t count, const RootInfo& info)
99 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
100
101 virtual void VisitRoots(mirror::CompressedReference<mirror::Object>** roots, size_t count,
102 const RootInfo& info)
103 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
104};
105
106// Only visits roots one at a time, doesn't handle updating roots. Used when performance isn't
107// critical.
108class SingleRootVisitor : public RootVisitor {
109 private:
110 void VisitRoots(mirror::Object*** roots, size_t count, const RootInfo& info) OVERRIDE
111 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
112 for (size_t i = 0; i < count; ++i) {
113 VisitRoot(*roots[i], info);
114 }
115 }
116
117 void VisitRoots(mirror::CompressedReference<mirror::Object>** roots, size_t count,
118 const RootInfo& info) OVERRIDE
119 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
120 for (size_t i = 0; i < count; ++i) {
121 VisitRoot(roots[i]->AsMirrorPtr(), info);
122 }
123 }
124
125 virtual void VisitRoot(mirror::Object* root, const RootInfo& info) = 0;
126};
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -0800127
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700128template<class MirrorType>
Hiroshi Yamauchi9e47bfa2015-02-23 11:14:40 -0800129class GcRoot {
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700130 public:
131 template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800132 ALWAYS_INLINE MirrorType* Read() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700133
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700134 void VisitRoot(RootVisitor* visitor, const RootInfo& info) const
135 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700136 DCHECK(!IsNull());
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700137 mirror::CompressedReference<mirror::Object>* roots[1] = { &root_ };
138 visitor->VisitRoots(roots, 1u, info);
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700139 DCHECK(!IsNull());
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700140 }
141
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700142 void VisitRootIfNonNull(RootVisitor* visitor, const RootInfo& info) const
143 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -0800144 if (!IsNull()) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700145 VisitRoot(visitor, info);
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -0800146 }
147 }
148
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700149 ALWAYS_INLINE mirror::CompressedReference<mirror::Object>* AddressWithoutBarrier() {
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700150 return &root_;
151 }
152
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700153 ALWAYS_INLINE bool IsNull() const {
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700154 // It's safe to null-check it without a read barrier.
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700155 return root_.IsNull();
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700156 }
157
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700158 ALWAYS_INLINE GcRoot(MirrorType* ref = nullptr) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
159
160 private:
161 mutable mirror::CompressedReference<mirror::Object> root_;
162
163 template <size_t kBufferSize> friend class BufferedRootVisitor;
164};
165
166// Simple data structure for buffered root visiting to avoid virtual dispatch overhead. Currently
167// only for CompressedReferences since these are more common than the Object** roots which are only
168// for thread local roots.
169template <size_t kBufferSize>
170class BufferedRootVisitor {
171 public:
172 BufferedRootVisitor(RootVisitor* visitor, const RootInfo& root_info)
173 : visitor_(visitor), root_info_(root_info), buffer_pos_(0) {
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700174 }
175
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700176 ~BufferedRootVisitor() {
177 Flush();
178 }
179
180 template <class MirrorType>
181 ALWAYS_INLINE void VisitRootIfNonNull(GcRoot<MirrorType>& root)
182 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
183 if (!root.IsNull()) {
184 VisitRoot(root);
185 }
186 }
187
188 template <class MirrorType>
189 ALWAYS_INLINE void VisitRootIfNonNull(mirror::CompressedReference<MirrorType>* root)
190 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
191 if (!root->IsNull()) {
192 VisitRoot(root);
193 }
194 }
195
196 template <class MirrorType>
197 void VisitRoot(GcRoot<MirrorType>& root) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
198 VisitRoot(root.AddressWithoutBarrier());
199 }
200
201 template <class MirrorType>
202 void VisitRoot(mirror::CompressedReference<MirrorType>* root)
203 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
204 if (UNLIKELY(buffer_pos_ >= kBufferSize)) {
205 Flush();
206 }
207 roots_[buffer_pos_++] = root;
208 }
209
210 void Flush() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
211 visitor_->VisitRoots(roots_, buffer_pos_, root_info_);
212 buffer_pos_ = 0;
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700213 }
214
215 private:
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700216 RootVisitor* const visitor_;
217 RootInfo root_info_;
218 mirror::CompressedReference<mirror::Object>* roots_[kBufferSize];
219 size_t buffer_pos_;
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -0700220};
221
222} // namespace art
223
224#endif // ART_RUNTIME_GC_ROOT_H_