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