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