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. Compress(MirrorType * mirror_ptr)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. Decompress(uint32_t ref)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. Compress(ObjPtr<MirrorType> ptr)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: AsMirrorPtr()63 MirrorType* AsMirrorPtr() const { 64 return Compression::Decompress(reference_); 65 } 66 Assign(MirrorType * other)67 void Assign(MirrorType* other) { 68 reference_ = Compression::Compress(other); 69 } 70 71 void Assign(ObjPtr<MirrorType> ptr) REQUIRES_SHARED(Locks::mutator_lock_); 72 Clear()73 void Clear() { 74 reference_ = 0; 75 DCHECK(IsNull()); 76 } 77 IsNull()78 bool IsNull() const { 79 return reference_ == 0; 80 } 81 AsVRegValue()82 uint32_t AsVRegValue() const { 83 return reference_; 84 } 85 FromMirrorPtr(MirrorType * mirror_ptr)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: ObjectReference(MirrorType * mirror_ptr)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: HeapReference()108 HeapReference() REQUIRES_SHARED(Locks::mutator_lock_) : HeapReference(nullptr) {} 109 110 template <bool kIsVolatile = false> AsMirrorPtr()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> Assign(MirrorType * other)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 Clear()128 void Clear() { 129 reference_.StoreJavaData(0); 130 DCHECK(IsNull()); 131 } 132 IsNull()133 bool IsNull() const { 134 return reference_.LoadJavaData() == 0; 135 } 136 FromMirrorPtr(MirrorType * mirror_ptr)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: HeapReference(MirrorType * mirror_ptr)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: REQUIRES_SHARED(Locks::mutator_lock_)160 CompressedReference<MirrorType>() REQUIRES_SHARED(Locks::mutator_lock_) 161 : mirror::ObjectReference<false, MirrorType>(nullptr) {} 162 FromMirrorPtr(MirrorType * p)163 static CompressedReference<MirrorType> FromMirrorPtr(MirrorType* p) 164 REQUIRES_SHARED(Locks::mutator_lock_) { 165 return CompressedReference<MirrorType>(p); 166 } 167 168 private: CompressedReference(MirrorType * p)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