Home | History | Annotate | Download | only in runtime
      1 /*
      2  * Copyright (C) 2009 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_INDIRECT_REFERENCE_TABLE_H_
     18 #define ART_RUNTIME_INDIRECT_REFERENCE_TABLE_H_
     19 
     20 #include <stdint.h>
     21 
     22 #include <iosfwd>
     23 #include <string>
     24 
     25 #include "base/logging.h"
     26 #include "base/mutex.h"
     27 #include "gc_root.h"
     28 #include "mem_map.h"
     29 #include "object_callbacks.h"
     30 #include "offsets.h"
     31 #include "read_barrier_option.h"
     32 
     33 namespace art {
     34 
     35 class RootInfo;
     36 
     37 namespace mirror {
     38 class Object;
     39 }  // namespace mirror
     40 
     41 /*
     42  * Maintain a table of indirect references.  Used for local/global JNI
     43  * references.
     44  *
     45  * The table contains object references that are part of the GC root set.
     46  * When an object is added we return an IndirectRef that is not a valid
     47  * pointer but can be used to find the original value in O(1) time.
     48  * Conversions to and from indirect references are performed on upcalls
     49  * and downcalls, so they need to be very fast.
     50  *
     51  * To be efficient for JNI local variable storage, we need to provide
     52  * operations that allow us to operate on segments of the table, where
     53  * segments are pushed and popped as if on a stack.  For example, deletion
     54  * of an entry should only succeed if it appears in the current segment,
     55  * and we want to be able to strip off the current segment quickly when
     56  * a method returns.  Additions to the table must be made in the current
     57  * segment even if space is available in an earlier area.
     58  *
     59  * A new segment is created when we call into native code from interpreted
     60  * code, or when we handle the JNI PushLocalFrame function.
     61  *
     62  * The GC must be able to scan the entire table quickly.
     63  *
     64  * In summary, these must be very fast:
     65  *  - adding or removing a segment
     66  *  - adding references to a new segment
     67  *  - converting an indirect reference back to an Object
     68  * These can be a little slower, but must still be pretty quick:
     69  *  - adding references to a "mature" segment
     70  *  - removing individual references
     71  *  - scanning the entire table straight through
     72  *
     73  * If there's more than one segment, we don't guarantee that the table
     74  * will fill completely before we fail due to lack of space.  We do ensure
     75  * that the current segment will pack tightly, which should satisfy JNI
     76  * requirements (e.g. EnsureLocalCapacity).
     77  *
     78  * To make everything fit nicely in 32-bit integers, the maximum size of
     79  * the table is capped at 64K.
     80  *
     81  * Only SynchronizedGet is synchronized.
     82  */
     83 
     84 /*
     85  * Indirect reference definition.  This must be interchangeable with JNI's
     86  * jobject, and it's convenient to let null be null, so we use void*.
     87  *
     88  * We need a 16-bit table index and a 2-bit reference type (global, local,
     89  * weak global).  Real object pointers will have zeroes in the low 2 or 3
     90  * bits (4- or 8-byte alignment), so it's useful to put the ref type
     91  * in the low bits and reserve zero as an invalid value.
     92  *
     93  * The remaining 14 bits can be used to detect stale indirect references.
     94  * For example, if objects don't move, we can use a hash of the original
     95  * Object* to make sure the entry hasn't been re-used.  (If the Object*
     96  * we find there doesn't match because of heap movement, we could do a
     97  * secondary check on the preserved hash value; this implies that creating
     98  * a global/local ref queries the hash value and forces it to be saved.)
     99  *
    100  * A more rigorous approach would be to put a serial number in the extra
    101  * bits, and keep a copy of the serial number in a parallel table.  This is
    102  * easier when objects can move, but requires 2x the memory and additional
    103  * memory accesses on add/get.  It will catch additional problems, e.g.:
    104  * create iref1 for obj, delete iref1, create iref2 for same obj, lookup
    105  * iref1.  A pattern based on object bits will miss this.
    106  */
    107 typedef void* IndirectRef;
    108 
    109 // Magic failure values; must not pass Heap::ValidateObject() or Heap::IsHeapAddress().
    110 static mirror::Object* const kInvalidIndirectRefObject = reinterpret_cast<mirror::Object*>(0xdead4321);
    111 static mirror::Object* const kClearedJniWeakGlobal = reinterpret_cast<mirror::Object*>(0xdead1234);
    112 
    113 /*
    114  * Indirect reference kind, used as the two low bits of IndirectRef.
    115  *
    116  * For convenience these match up with enum jobjectRefType from jni.h.
    117  */
    118 enum IndirectRefKind {
    119   kHandleScopeOrInvalid = 0,  // <<stack indirect reference table or invalid reference>>
    120   kLocal         = 1,  // <<local reference>>
    121   kGlobal        = 2,  // <<global reference>>
    122   kWeakGlobal    = 3   // <<weak global reference>>
    123 };
    124 std::ostream& operator<<(std::ostream& os, const IndirectRefKind& rhs);
    125 
    126 /*
    127  * Determine what kind of indirect reference this is.
    128  */
    129 static inline IndirectRefKind GetIndirectRefKind(IndirectRef iref) {
    130   return static_cast<IndirectRefKind>(reinterpret_cast<uintptr_t>(iref) & 0x03);
    131 }
    132 
    133 /* use as initial value for "cookie", and when table has only one segment */
    134 static const uint32_t IRT_FIRST_SEGMENT = 0;
    135 
    136 /*
    137  * Table definition.
    138  *
    139  * For the global reference table, the expected common operations are
    140  * adding a new entry and removing a recently-added entry (usually the
    141  * most-recently-added entry).  For JNI local references, the common
    142  * operations are adding a new entry and removing an entire table segment.
    143  *
    144  * If "alloc_entries_" is not equal to "max_entries_", the table may expand
    145  * when entries are added, which means the memory may move.  If you want
    146  * to keep pointers into "table" rather than offsets, you must use a
    147  * fixed-size table.
    148  *
    149  * If we delete entries from the middle of the list, we will be left with
    150  * "holes".  We track the number of holes so that, when adding new elements,
    151  * we can quickly decide to do a trivial append or go slot-hunting.
    152  *
    153  * When the top-most entry is removed, any holes immediately below it are
    154  * also removed.  Thus, deletion of an entry may reduce "topIndex" by more
    155  * than one.
    156  *
    157  * To get the desired behavior for JNI locals, we need to know the bottom
    158  * and top of the current "segment".  The top is managed internally, and
    159  * the bottom is passed in as a function argument.  When we call a native method or
    160  * push a local frame, the current top index gets pushed on, and serves
    161  * as the new bottom.  When we pop a frame off, the value from the stack
    162  * becomes the new top index, and the value stored in the previous frame
    163  * becomes the new bottom.
    164  *
    165  * To avoid having to re-scan the table after a pop, we want to push the
    166  * number of holes in the table onto the stack.  Because of our 64K-entry
    167  * cap, we can combine the two into a single unsigned 32-bit value.
    168  * Instead of a "bottom" argument we take a "cookie", which includes the
    169  * bottom index and the count of holes below the bottom.
    170  *
    171  * Common alternative implementation: make IndirectRef a pointer to the
    172  * actual reference slot.  Instead of getting a table and doing a lookup,
    173  * the lookup can be done instantly.  Operations like determining the
    174  * type and deleting the reference are more expensive because the table
    175  * must be hunted for (i.e. you have to do a pointer comparison to see
    176  * which table it's in), you can't move the table when expanding it (so
    177  * realloc() is out), and tricks like serial number checking to detect
    178  * stale references aren't possible (though we may be able to get similar
    179  * benefits with other approaches).
    180  *
    181  * TODO: consider a "lastDeleteIndex" for quick hole-filling when an
    182  * add immediately follows a delete; must invalidate after segment pop
    183  * (which could increase the cost/complexity of method call/return).
    184  * Might be worth only using it for JNI globals.
    185  *
    186  * TODO: may want completely different add/remove algorithms for global
    187  * and local refs to improve performance.  A large circular buffer might
    188  * reduce the amortized cost of adding global references.
    189  *
    190  */
    191 union IRTSegmentState {
    192   uint32_t          all;
    193   struct {
    194     uint32_t      topIndex:16;            /* index of first unused entry */
    195     uint32_t      numHoles:16;            /* #of holes in entire table */
    196   } parts;
    197 };
    198 
    199 // Try to choose kIRTPrevCount so that sizeof(IrtEntry) is a power of 2.
    200 // Contains multiple entries but only one active one, this helps us detect use after free errors
    201 // since the serial stored in the indirect ref wont match.
    202 static const size_t kIRTPrevCount = kIsDebugBuild ? 7 : 3;
    203 class PACKED(4) IrtEntry {
    204  public:
    205   void Add(mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    206     ++serial_;
    207     if (serial_ == kIRTPrevCount) {
    208       serial_ = 0;
    209     }
    210     references_[serial_] = GcRoot<mirror::Object>(obj);
    211   }
    212   GcRoot<mirror::Object>* GetReference() {
    213     DCHECK_LT(serial_, kIRTPrevCount);
    214     return &references_[serial_];
    215   }
    216   uint32_t GetSerial() const {
    217     return serial_;
    218   }
    219 
    220  private:
    221   uint32_t serial_;
    222   GcRoot<mirror::Object> references_[kIRTPrevCount];
    223 };
    224 
    225 class IrtIterator {
    226  public:
    227   explicit IrtIterator(IrtEntry* table, size_t i, size_t capacity)
    228       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    229       : table_(table), i_(i), capacity_(capacity) {
    230     SkipNullsAndTombstones();
    231   }
    232 
    233   IrtIterator& operator++() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    234     ++i_;
    235     SkipNullsAndTombstones();
    236     return *this;
    237   }
    238 
    239   mirror::Object** operator*() {
    240     // This does not have a read barrier as this is used to visit roots.
    241     return table_[i_].GetReference()->AddressWithoutBarrier();
    242   }
    243 
    244   bool equals(const IrtIterator& rhs) const {
    245     return (i_ == rhs.i_ && table_ == rhs.table_);
    246   }
    247 
    248  private:
    249   void SkipNullsAndTombstones() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    250     // We skip NULLs and tombstones. Clients don't want to see implementation details.
    251     while (i_ < capacity_ &&
    252            (table_[i_].GetReference()->IsNull() ||
    253             table_[i_].GetReference()->Read<kWithoutReadBarrier>() == kClearedJniWeakGlobal)) {
    254       ++i_;
    255     }
    256   }
    257 
    258   IrtEntry* const table_;
    259   size_t i_;
    260   size_t capacity_;
    261 };
    262 
    263 bool inline operator==(const IrtIterator& lhs, const IrtIterator& rhs) {
    264   return lhs.equals(rhs);
    265 }
    266 
    267 bool inline operator!=(const IrtIterator& lhs, const IrtIterator& rhs) {
    268   return !lhs.equals(rhs);
    269 }
    270 
    271 class IndirectReferenceTable {
    272  public:
    273   IndirectReferenceTable(size_t initialCount, size_t maxCount, IndirectRefKind kind);
    274 
    275   ~IndirectReferenceTable();
    276 
    277   /*
    278    * Add a new entry.  "obj" must be a valid non-NULL object reference.
    279    *
    280    * Returns NULL if the table is full (max entries reached, or alloc
    281    * failed during expansion).
    282    */
    283   IndirectRef Add(uint32_t cookie, mirror::Object* obj)
    284       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    285 
    286   /*
    287    * Given an IndirectRef in the table, return the Object it refers to.
    288    *
    289    * Returns kInvalidIndirectRefObject if iref is invalid.
    290    */
    291   template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
    292   mirror::Object* Get(IndirectRef iref) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
    293       ALWAYS_INLINE;
    294 
    295   // Synchronized get which reads a reference, acquiring a lock if necessary.
    296   template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
    297   mirror::Object* SynchronizedGet(Thread* /*self*/, ReaderWriterMutex* /*mutex*/,
    298                                   IndirectRef iref) const
    299       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    300     return Get<kReadBarrierOption>(iref);
    301   }
    302 
    303   /*
    304    * Remove an existing entry.
    305    *
    306    * If the entry is not between the current top index and the bottom index
    307    * specified by the cookie, we don't remove anything.  This is the behavior
    308    * required by JNI's DeleteLocalRef function.
    309    *
    310    * Returns "false" if nothing was removed.
    311    */
    312   bool Remove(uint32_t cookie, IndirectRef iref);
    313 
    314   void AssertEmpty();
    315 
    316   void Dump(std::ostream& os) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    317 
    318   /*
    319    * Return the #of entries in the entire table.  This includes holes, and
    320    * so may be larger than the actual number of "live" entries.
    321    */
    322   size_t Capacity() const {
    323     return segment_state_.parts.topIndex;
    324   }
    325 
    326   // Note IrtIterator does not have a read barrier as it's used to visit roots.
    327   IrtIterator begin() {
    328     return IrtIterator(table_, 0, Capacity());
    329   }
    330 
    331   IrtIterator end() {
    332     return IrtIterator(table_, Capacity(), Capacity());
    333   }
    334 
    335   void VisitRoots(RootCallback* callback, void* arg, const RootInfo& root_info)
    336       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    337 
    338   uint32_t GetSegmentState() const {
    339     return segment_state_.all;
    340   }
    341 
    342   void SetSegmentState(uint32_t new_state) {
    343     segment_state_.all = new_state;
    344   }
    345 
    346   static Offset SegmentStateOffset() {
    347     return Offset(OFFSETOF_MEMBER(IndirectReferenceTable, segment_state_));
    348   }
    349 
    350   // Release pages past the end of the table that may have previously held references.
    351   void Trim() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    352 
    353  private:
    354   // Extract the table index from an indirect reference.
    355   static uint32_t ExtractIndex(IndirectRef iref) {
    356     uintptr_t uref = reinterpret_cast<uintptr_t>(iref);
    357     return (uref >> 2) & 0xffff;
    358   }
    359 
    360   /*
    361    * The object pointer itself is subject to relocation in some GC
    362    * implementations, so we shouldn't really be using it here.
    363    */
    364   IndirectRef ToIndirectRef(uint32_t tableIndex) const {
    365     DCHECK_LT(tableIndex, 65536U);
    366     uint32_t serialChunk = table_[tableIndex].GetSerial();
    367     uintptr_t uref = (serialChunk << 20) | (tableIndex << 2) | kind_;
    368     return reinterpret_cast<IndirectRef>(uref);
    369   }
    370 
    371   // Abort if check_jni is not enabled.
    372   static void AbortIfNoCheckJNI();
    373 
    374   /* extra debugging checks */
    375   bool GetChecked(IndirectRef) const;
    376   bool CheckEntry(const char*, IndirectRef, int) const;
    377 
    378   /* semi-public - read/write by jni down calls */
    379   IRTSegmentState segment_state_;
    380 
    381   // Mem map where we store the indirect refs.
    382   std::unique_ptr<MemMap> table_mem_map_;
    383   // bottom of the stack. Do not directly access the object references
    384   // in this as they are roots. Use Get() that has a read barrier.
    385   IrtEntry* table_;
    386   /* bit mask, ORed into all irefs */
    387   const IndirectRefKind kind_;
    388   /* max #of entries allowed */
    389   const size_t max_entries_;
    390 };
    391 
    392 }  // namespace art
    393 
    394 #endif  // ART_RUNTIME_INDIRECT_REFERENCE_TABLE_H_
    395