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(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:
    215   BufferedRootVisitor(RootVisitor* visitor, const RootInfo& root_info)
    216       : visitor_(visitor), root_info_(root_info), buffer_pos_(0) {
    217   }
    218 
    219   ~BufferedRootVisitor() {
    220     Flush();
    221   }
    222 
    223   template <class MirrorType>
    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>
    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>
    240   void VisitRoot(GcRoot<MirrorType>& root) SHARED_REQUIRES(Locks::mutator_lock_) {
    241     VisitRoot(root.AddressWithoutBarrier());
    242   }
    243 
    244   template <class MirrorType>
    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 
    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