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