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) 62 : type_(type), thread_id_(thread_id) { 63 } 64 RootInfo(const RootInfo&) = default; 65 virtual ~RootInfo() { 66 } 67 RootType GetType() const { 68 return type_; 69 } 70 uint32_t GetThreadId() const { 71 return thread_id_; 72 } 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: 90 virtual ~RootVisitor() { } 91 92 // Single root version, not overridable. 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. 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: 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 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: 138 GcRootSource() 139 : field_(nullptr), method_(nullptr) { 140 } 141 explicit GcRootSource(ArtField* field) 142 : field_(field), method_(nullptr) { 143 } 144 explicit GcRootSource(ArtMethod* method) 145 : field_(nullptr), method_(method) { 146 } 147 ArtField* GetArtField() const { 148 return field_; 149 } 150 ArtMethod* GetArtMethod() const { 151 return method_; 152 } 153 bool HasArtField() const { 154 return field_ != nullptr; 155 } 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 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 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 189 ALWAYS_INLINE mirror::CompressedReference<mirror::Object>* AddressWithoutBarrier() { 190 return &root_; 191 } 192 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() {} 199 explicit ALWAYS_INLINE GcRoot(MirrorType* ref) SHARED_REQUIRES(Locks::mutator_lock_); 200 201 private: 202 // Root visitors take pointers to root_ and place them in CompressedReference** arrays. We use a 203 // CompressedReference<mirror::Object> here since it violates strict aliasing requirements to 204 // cast CompressedReference<MirrorType>* to CompressedReference<mirror::Object>*. 205 mutable mirror::CompressedReference<mirror::Object> root_; 206 207 template <size_t kBufferSize> friend class BufferedRootVisitor; 208 }; 209 210 // Simple data structure for buffered root visiting to avoid virtual dispatch overhead. Currently 211 // only for CompressedReferences since these are more common than the Object** roots which are only 212 // for thread local roots. 213 template <size_t kBufferSize> 214 class BufferedRootVisitor { 215 public: 216 BufferedRootVisitor(RootVisitor* visitor, const RootInfo& root_info) 217 : visitor_(visitor), root_info_(root_info), buffer_pos_(0) { 218 } 219 220 ~BufferedRootVisitor() { 221 Flush(); 222 } 223 224 template <class MirrorType> 225 ALWAYS_INLINE void VisitRootIfNonNull(GcRoot<MirrorType>& root) 226 SHARED_REQUIRES(Locks::mutator_lock_) { 227 if (!root.IsNull()) { 228 VisitRoot(root); 229 } 230 } 231 232 template <class MirrorType> 233 ALWAYS_INLINE void VisitRootIfNonNull(mirror::CompressedReference<MirrorType>* root) 234 SHARED_REQUIRES(Locks::mutator_lock_) { 235 if (!root->IsNull()) { 236 VisitRoot(root); 237 } 238 } 239 240 template <class MirrorType> 241 void VisitRoot(GcRoot<MirrorType>& root) SHARED_REQUIRES(Locks::mutator_lock_) { 242 VisitRoot(root.AddressWithoutBarrier()); 243 } 244 245 template <class MirrorType> 246 void VisitRoot(mirror::CompressedReference<MirrorType>* root) 247 SHARED_REQUIRES(Locks::mutator_lock_) { 248 if (UNLIKELY(buffer_pos_ >= kBufferSize)) { 249 Flush(); 250 } 251 roots_[buffer_pos_++] = root; 252 } 253 254 void Flush() SHARED_REQUIRES(Locks::mutator_lock_) { 255 visitor_->VisitRoots(roots_, buffer_pos_, root_info_); 256 buffer_pos_ = 0; 257 } 258 259 private: 260 RootVisitor* const visitor_; 261 RootInfo root_info_; 262 mirror::CompressedReference<mirror::Object>* roots_[kBufferSize]; 263 size_t buffer_pos_; 264 }; 265 266 } // namespace art 267 268 #endif // ART_RUNTIME_GC_ROOT_H_ 269