Home | History | Annotate | Download | only in runtime
      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