Home | History | Annotate | Download | only in mirror
      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_MIRROR_OBJECT_REFERENCE_H_
     18 #define ART_RUNTIME_MIRROR_OBJECT_REFERENCE_H_
     19 
     20 #include "base/atomic.h"
     21 #include "base/mutex.h"  // For Locks::mutator_lock_.
     22 #include "globals.h"
     23 #include "heap_poisoning.h"
     24 #include "obj_ptr.h"
     25 
     26 namespace art {
     27 namespace mirror {
     28 
     29 class Object;
     30 
     31 // Classes shared with the managed side of the world need to be packed so that they don't have
     32 // extra platform specific padding.
     33 #define MANAGED PACKED(4)
     34 
     35 template<bool kPoisonReferences, class MirrorType>
     36 class PtrCompression {
     37  public:
     38   // Compress reference to its bit representation.
     39   static uint32_t Compress(MirrorType* mirror_ptr) {
     40     uintptr_t as_bits = reinterpret_cast<uintptr_t>(mirror_ptr);
     41     return static_cast<uint32_t>(kPoisonReferences ? -as_bits : as_bits);
     42   }
     43 
     44   // Uncompress an encoded reference from its bit representation.
     45   static MirrorType* Decompress(uint32_t ref) {
     46     uintptr_t as_bits = kPoisonReferences ? -ref : ref;
     47     return reinterpret_cast<MirrorType*>(as_bits);
     48   }
     49 
     50   // Convert an ObjPtr to a compressed reference.
     51   static uint32_t Compress(ObjPtr<MirrorType> ptr) REQUIRES_SHARED(Locks::mutator_lock_) {
     52     return Compress(ptr.Ptr());
     53   }
     54 };
     55 
     56 // Value type representing a reference to a mirror::Object of type MirrorType.
     57 template<bool kPoisonReferences, class MirrorType>
     58 class MANAGED ObjectReference {
     59  private:
     60   using Compression = PtrCompression<kPoisonReferences, MirrorType>;
     61 
     62  public:
     63   MirrorType* AsMirrorPtr() const {
     64     return Compression::Decompress(reference_);
     65   }
     66 
     67   void Assign(MirrorType* other) {
     68     reference_ = Compression::Compress(other);
     69   }
     70 
     71   void Assign(ObjPtr<MirrorType> ptr) REQUIRES_SHARED(Locks::mutator_lock_);
     72 
     73   void Clear() {
     74     reference_ = 0;
     75     DCHECK(IsNull());
     76   }
     77 
     78   bool IsNull() const {
     79     return reference_ == 0;
     80   }
     81 
     82   uint32_t AsVRegValue() const {
     83     return reference_;
     84   }
     85 
     86   static ObjectReference<kPoisonReferences, MirrorType> FromMirrorPtr(MirrorType* mirror_ptr)
     87       REQUIRES_SHARED(Locks::mutator_lock_) {
     88     return ObjectReference<kPoisonReferences, MirrorType>(mirror_ptr);
     89   }
     90 
     91  protected:
     92   explicit ObjectReference(MirrorType* mirror_ptr) REQUIRES_SHARED(Locks::mutator_lock_)
     93       : reference_(Compression::Compress(mirror_ptr)) {
     94   }
     95 
     96   // The encoded reference to a mirror::Object.
     97   uint32_t reference_;
     98 };
     99 
    100 // References between objects within the managed heap.
    101 // Similar API to ObjectReference, but not a value type. Supports atomic access.
    102 template<class MirrorType>
    103 class MANAGED HeapReference {
    104  private:
    105   using Compression = PtrCompression<kPoisonHeapReferences, MirrorType>;
    106 
    107  public:
    108   HeapReference() REQUIRES_SHARED(Locks::mutator_lock_) : HeapReference(nullptr) {}
    109 
    110   template <bool kIsVolatile = false>
    111   MirrorType* AsMirrorPtr() const REQUIRES_SHARED(Locks::mutator_lock_) {
    112     return Compression::Decompress(
    113         kIsVolatile ? reference_.LoadSequentiallyConsistent() : reference_.LoadJavaData());
    114   }
    115 
    116   template <bool kIsVolatile = false>
    117   void Assign(MirrorType* other) REQUIRES_SHARED(Locks::mutator_lock_) {
    118     if (kIsVolatile) {
    119       reference_.StoreSequentiallyConsistent(Compression::Compress(other));
    120     } else {
    121       reference_.StoreJavaData(Compression::Compress(other));
    122     }
    123   }
    124 
    125   template <bool kIsVolatile = false>
    126   void Assign(ObjPtr<MirrorType> ptr) REQUIRES_SHARED(Locks::mutator_lock_);
    127 
    128   void Clear() {
    129     reference_.StoreJavaData(0);
    130     DCHECK(IsNull());
    131   }
    132 
    133   bool IsNull() const {
    134     return reference_.LoadJavaData() == 0;
    135   }
    136 
    137   static HeapReference<MirrorType> FromMirrorPtr(MirrorType* mirror_ptr)
    138       REQUIRES_SHARED(Locks::mutator_lock_) {
    139     return HeapReference<MirrorType>(mirror_ptr);
    140   }
    141 
    142   bool CasWeakRelaxed(MirrorType* old_ptr, MirrorType* new_ptr)
    143       REQUIRES_SHARED(Locks::mutator_lock_);
    144 
    145  private:
    146   explicit HeapReference(MirrorType* mirror_ptr) REQUIRES_SHARED(Locks::mutator_lock_)
    147       : reference_(Compression::Compress(mirror_ptr)) {}
    148 
    149   // The encoded reference to a mirror::Object. Atomically updateable.
    150   Atomic<uint32_t> reference_;
    151 };
    152 
    153 static_assert(sizeof(mirror::HeapReference<mirror::Object>) == kHeapReferenceSize,
    154               "heap reference size does not match");
    155 
    156 // Standard compressed reference used in the runtime. Used for StackReference and GC roots.
    157 template<class MirrorType>
    158 class MANAGED CompressedReference : public mirror::ObjectReference<false, MirrorType> {
    159  public:
    160   CompressedReference<MirrorType>() REQUIRES_SHARED(Locks::mutator_lock_)
    161       : mirror::ObjectReference<false, MirrorType>(nullptr) {}
    162 
    163   static CompressedReference<MirrorType> FromMirrorPtr(MirrorType* p)
    164       REQUIRES_SHARED(Locks::mutator_lock_) {
    165     return CompressedReference<MirrorType>(p);
    166   }
    167 
    168  private:
    169   explicit CompressedReference(MirrorType* p) REQUIRES_SHARED(Locks::mutator_lock_)
    170       : mirror::ObjectReference<false, MirrorType>(p) {}
    171 };
    172 
    173 }  // namespace mirror
    174 }  // namespace art
    175 
    176 #endif  // ART_RUNTIME_MIRROR_OBJECT_REFERENCE_H_
    177