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/locks.h" // For Locks::mutator_lock_. 21 #include "base/macros.h" 22 #include "mirror/object_reference.h" 23 #include "read_barrier_option.h" 24 25 namespace art { 26 class ArtField; 27 class ArtMethod; 28 template<class MirrorType> class ObjPtr; 29 30 namespace mirror { 31 class Object; 32 } // namespace mirror 33 34 template <size_t kBufferSize> 35 class BufferedRootVisitor; 36 37 // Dependent on pointer size so that we don't have frames that are too big on 64 bit. 38 static const size_t kDefaultBufferedRootCount = 1024 / sizeof(void*); 39 40 enum RootType { 41 kRootUnknown = 0, 42 kRootJNIGlobal, 43 kRootJNILocal, 44 kRootJavaFrame, 45 kRootNativeStack, 46 kRootStickyClass, 47 kRootThreadBlock, 48 kRootMonitorUsed, 49 kRootThreadObject, 50 kRootInternedString, 51 kRootFinalizing, // used for HPROF's conversion to HprofHeapTag 52 kRootDebugger, 53 kRootReferenceCleanup, // used for HPROF's conversion to HprofHeapTag 54 kRootVMInternal, 55 kRootJNIMonitor, 56 }; 57 std::ostream& operator<<(std::ostream& os, const RootType& root_type); 58 59 // Only used by hprof. thread_id_ and type_ are only used by hprof. 60 class RootInfo { 61 public: 62 // Thread id 0 is for non thread roots. 63 explicit RootInfo(RootType type, uint32_t thread_id = 0) type_(type)64 : type_(type), thread_id_(thread_id) { 65 } 66 RootInfo(const RootInfo&) = default; ~RootInfo()67 virtual ~RootInfo() { 68 } GetType()69 RootType GetType() const { 70 return type_; 71 } GetThreadId()72 uint32_t GetThreadId() const { 73 return thread_id_; 74 } Describe(std::ostream & os)75 virtual void Describe(std::ostream& os) const { 76 os << "Type=" << type_ << " thread_id=" << thread_id_; 77 } 78 std::string ToString() const; 79 80 private: 81 const RootType type_; 82 const uint32_t thread_id_; 83 }; 84 85 inline std::ostream& operator<<(std::ostream& os, const RootInfo& root_info) { 86 root_info.Describe(os); 87 return os; 88 } 89 90 // Not all combinations of flags are valid. You may not visit all roots as well as the new roots 91 // (no logical reason to do this). You also may not start logging new roots and stop logging new 92 // roots (also no logical reason to do this). 93 // 94 // The precise flag ensures that more metadata is supplied. An example is vreg data for compiled 95 // method frames. 96 enum VisitRootFlags : uint8_t { 97 kVisitRootFlagAllRoots = 0x1, 98 kVisitRootFlagNewRoots = 0x2, 99 kVisitRootFlagStartLoggingNewRoots = 0x4, 100 kVisitRootFlagStopLoggingNewRoots = 0x8, 101 kVisitRootFlagClearRootLog = 0x10, 102 kVisitRootFlagClassLoader = 0x20, 103 kVisitRootFlagPrecise = 0x80, 104 }; 105 106 class RootVisitor { 107 public: ~RootVisitor()108 virtual ~RootVisitor() { } 109 110 // Single root version, not overridable. VisitRoot(mirror::Object ** root,const RootInfo & info)111 ALWAYS_INLINE void VisitRoot(mirror::Object** root, const RootInfo& info) 112 REQUIRES_SHARED(Locks::mutator_lock_) { 113 VisitRoots(&root, 1, info); 114 } 115 116 // Single root version, not overridable. VisitRootIfNonNull(mirror::Object ** root,const RootInfo & info)117 ALWAYS_INLINE void VisitRootIfNonNull(mirror::Object** root, const RootInfo& info) 118 REQUIRES_SHARED(Locks::mutator_lock_) { 119 if (*root != nullptr) { 120 VisitRoot(root, info); 121 } 122 } 123 124 virtual void VisitRoots(mirror::Object*** roots, size_t count, const RootInfo& info) 125 REQUIRES_SHARED(Locks::mutator_lock_) = 0; 126 127 virtual void VisitRoots(mirror::CompressedReference<mirror::Object>** roots, size_t count, 128 const RootInfo& info) 129 REQUIRES_SHARED(Locks::mutator_lock_) = 0; 130 }; 131 132 // Only visits roots one at a time, doesn't handle updating roots. Used when performance isn't 133 // critical. 134 class SingleRootVisitor : public RootVisitor { 135 private: VisitRoots(mirror::Object *** roots,size_t count,const RootInfo & info)136 void VisitRoots(mirror::Object*** roots, size_t count, const RootInfo& info) override 137 REQUIRES_SHARED(Locks::mutator_lock_) { 138 for (size_t i = 0; i < count; ++i) { 139 VisitRoot(*roots[i], info); 140 } 141 } 142 VisitRoots(mirror::CompressedReference<mirror::Object> ** roots,size_t count,const RootInfo & info)143 void VisitRoots(mirror::CompressedReference<mirror::Object>** roots, size_t count, 144 const RootInfo& info) override 145 REQUIRES_SHARED(Locks::mutator_lock_) { 146 for (size_t i = 0; i < count; ++i) { 147 VisitRoot(roots[i]->AsMirrorPtr(), info); 148 } 149 } 150 151 virtual void VisitRoot(mirror::Object* root, const RootInfo& info) = 0; 152 }; 153 154 class GcRootSource { 155 public: GcRootSource()156 GcRootSource() 157 : field_(nullptr), method_(nullptr) { 158 } GcRootSource(ArtField * field)159 explicit GcRootSource(ArtField* field) 160 : field_(field), method_(nullptr) { 161 } GcRootSource(ArtMethod * method)162 explicit GcRootSource(ArtMethod* method) 163 : field_(nullptr), method_(method) { 164 } GetArtField()165 ArtField* GetArtField() const { 166 return field_; 167 } GetArtMethod()168 ArtMethod* GetArtMethod() const { 169 return method_; 170 } HasArtField()171 bool HasArtField() const { 172 return field_ != nullptr; 173 } HasArtMethod()174 bool HasArtMethod() const { 175 return method_ != nullptr; 176 } 177 178 private: 179 ArtField* const field_; 180 ArtMethod* const method_; 181 182 DISALLOW_COPY_AND_ASSIGN(GcRootSource); 183 }; 184 185 template<class MirrorType> 186 class GcRoot { 187 public: 188 template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier> 189 ALWAYS_INLINE MirrorType* Read(GcRootSource* gc_root_source = nullptr) const 190 REQUIRES_SHARED(Locks::mutator_lock_); 191 VisitRoot(RootVisitor * visitor,const RootInfo & info)192 void VisitRoot(RootVisitor* visitor, const RootInfo& info) const 193 REQUIRES_SHARED(Locks::mutator_lock_) { 194 DCHECK(!IsNull()); 195 mirror::CompressedReference<mirror::Object>* roots[1] = { &root_ }; 196 visitor->VisitRoots(roots, 1u, info); 197 DCHECK(!IsNull()); 198 } 199 VisitRootIfNonNull(RootVisitor * visitor,const RootInfo & info)200 void VisitRootIfNonNull(RootVisitor* visitor, const RootInfo& info) const 201 REQUIRES_SHARED(Locks::mutator_lock_) { 202 if (!IsNull()) { 203 VisitRoot(visitor, info); 204 } 205 } 206 AddressWithoutBarrier()207 ALWAYS_INLINE mirror::CompressedReference<mirror::Object>* AddressWithoutBarrier() { 208 return &root_; 209 } 210 IsNull()211 ALWAYS_INLINE bool IsNull() const { 212 // It's safe to null-check it without a read barrier. 213 return root_.IsNull(); 214 } 215 GcRoot()216 ALWAYS_INLINE GcRoot() {} 217 explicit ALWAYS_INLINE GcRoot(MirrorType* ref) 218 REQUIRES_SHARED(Locks::mutator_lock_); 219 explicit ALWAYS_INLINE GcRoot(ObjPtr<MirrorType> ref) 220 REQUIRES_SHARED(Locks::mutator_lock_); 221 222 private: 223 // Root visitors take pointers to root_ and place them in CompressedReference** arrays. We use a 224 // CompressedReference<mirror::Object> here since it violates strict aliasing requirements to 225 // cast CompressedReference<MirrorType>* to CompressedReference<mirror::Object>*. 226 mutable mirror::CompressedReference<mirror::Object> root_; 227 228 template <size_t kBufferSize> friend class BufferedRootVisitor; 229 }; 230 231 // Simple data structure for buffered root visiting to avoid virtual dispatch overhead. Currently 232 // only for CompressedReferences since these are more common than the Object** roots which are only 233 // for thread local roots. 234 template <size_t kBufferSize> 235 class BufferedRootVisitor { 236 public: BufferedRootVisitor(RootVisitor * visitor,const RootInfo & root_info)237 BufferedRootVisitor(RootVisitor* visitor, const RootInfo& root_info) 238 : visitor_(visitor), root_info_(root_info), buffer_pos_(0) { 239 } 240 ~BufferedRootVisitor()241 ~BufferedRootVisitor() { 242 Flush(); 243 } 244 245 template <class MirrorType> VisitRootIfNonNull(GcRoot<MirrorType> & root)246 ALWAYS_INLINE void VisitRootIfNonNull(GcRoot<MirrorType>& root) 247 REQUIRES_SHARED(Locks::mutator_lock_) { 248 if (!root.IsNull()) { 249 VisitRoot(root); 250 } 251 } 252 253 template <class MirrorType> VisitRootIfNonNull(mirror::CompressedReference<MirrorType> * root)254 ALWAYS_INLINE void VisitRootIfNonNull(mirror::CompressedReference<MirrorType>* root) 255 REQUIRES_SHARED(Locks::mutator_lock_) { 256 if (!root->IsNull()) { 257 VisitRoot(root); 258 } 259 } 260 261 template <class MirrorType> VisitRoot(GcRoot<MirrorType> & root)262 void VisitRoot(GcRoot<MirrorType>& root) REQUIRES_SHARED(Locks::mutator_lock_) { 263 VisitRoot(root.AddressWithoutBarrier()); 264 } 265 266 template <class MirrorType> VisitRoot(mirror::CompressedReference<MirrorType> * root)267 void VisitRoot(mirror::CompressedReference<MirrorType>* root) 268 REQUIRES_SHARED(Locks::mutator_lock_) { 269 if (UNLIKELY(buffer_pos_ >= kBufferSize)) { 270 Flush(); 271 } 272 roots_[buffer_pos_++] = root; 273 } 274 Flush()275 void Flush() REQUIRES_SHARED(Locks::mutator_lock_) { 276 visitor_->VisitRoots(roots_, buffer_pos_, root_info_); 277 buffer_pos_ = 0; 278 } 279 280 private: 281 RootVisitor* const visitor_; 282 RootInfo root_info_; 283 mirror::CompressedReference<mirror::Object>* roots_[kBufferSize]; 284 size_t buffer_pos_; 285 }; 286 287 class UnbufferedRootVisitor { 288 public: UnbufferedRootVisitor(RootVisitor * visitor,const RootInfo & root_info)289 UnbufferedRootVisitor(RootVisitor* visitor, const RootInfo& root_info) 290 : visitor_(visitor), root_info_(root_info) {} 291 292 template <class MirrorType> VisitRootIfNonNull(GcRoot<MirrorType> & root)293 ALWAYS_INLINE void VisitRootIfNonNull(GcRoot<MirrorType>& root) const 294 REQUIRES_SHARED(Locks::mutator_lock_) { 295 if (!root.IsNull()) { 296 VisitRoot(root); 297 } 298 } 299 300 template <class MirrorType> VisitRootIfNonNull(mirror::CompressedReference<MirrorType> * root)301 ALWAYS_INLINE void VisitRootIfNonNull(mirror::CompressedReference<MirrorType>* root) const 302 REQUIRES_SHARED(Locks::mutator_lock_) { 303 if (!root->IsNull()) { 304 VisitRoot(root); 305 } 306 } 307 308 template <class MirrorType> VisitRoot(GcRoot<MirrorType> & root)309 void VisitRoot(GcRoot<MirrorType>& root) const REQUIRES_SHARED(Locks::mutator_lock_) { 310 VisitRoot(root.AddressWithoutBarrier()); 311 } 312 313 template <class MirrorType> VisitRoot(mirror::CompressedReference<MirrorType> * root)314 void VisitRoot(mirror::CompressedReference<MirrorType>* root) const 315 REQUIRES_SHARED(Locks::mutator_lock_) { 316 visitor_->VisitRoots(&root, 1, root_info_); 317 } 318 319 private: 320 RootVisitor* const visitor_; 321 RootInfo root_info_; 322 }; 323 324 } // namespace art 325 326 #endif // ART_RUNTIME_GC_ROOT_H_ 327