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/locks.h" // For Locks::mutator_lock_. 22 #include "heap_poisoning.h" 23 #include "obj_ptr.h" 24 #include "runtime_globals.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. 51 static uint32_t Compress(ObjPtr<MirrorType> ptr) REQUIRES_SHARED(Locks::mutator_lock_); 52 }; 53 54 // Value type representing a reference to a mirror::Object of type MirrorType. 55 template<bool kPoisonReferences, class MirrorType> 56 class MANAGED ObjectReference { 57 private: 58 using Compression = PtrCompression<kPoisonReferences, MirrorType>; 59 60 public: 61 /* 62 * Returns a pointer to the mirror of the managed object this reference is for. 63 * 64 * This does NOT return the current object (which isn't derived from, and 65 * therefor cannot be a mirror::Object) as a mirror pointer. Instead, this 66 * returns a pointer to the mirror of the managed object this refers to. 67 * 68 * TODO (chriswailes): Rename to GetPtr(). 69 */ AsMirrorPtr()70 MirrorType* AsMirrorPtr() const { 71 return Compression::Decompress(reference_); 72 } 73 Assign(MirrorType * other)74 void Assign(MirrorType* other) { 75 reference_ = Compression::Compress(other); 76 } 77 78 void Assign(ObjPtr<MirrorType> ptr) REQUIRES_SHARED(Locks::mutator_lock_); 79 Clear()80 void Clear() { 81 reference_ = 0; 82 DCHECK(IsNull()); 83 } 84 IsNull()85 bool IsNull() const { 86 return reference_ == 0; 87 } 88 AsVRegValue()89 uint32_t AsVRegValue() const { 90 return reference_; 91 } 92 FromMirrorPtr(MirrorType * mirror_ptr)93 static ObjectReference<kPoisonReferences, MirrorType> FromMirrorPtr(MirrorType* mirror_ptr) 94 REQUIRES_SHARED(Locks::mutator_lock_) { 95 return ObjectReference<kPoisonReferences, MirrorType>(mirror_ptr); 96 } 97 98 protected: ObjectReference(MirrorType * mirror_ptr)99 explicit ObjectReference(MirrorType* mirror_ptr) REQUIRES_SHARED(Locks::mutator_lock_) 100 : reference_(Compression::Compress(mirror_ptr)) { 101 } 102 103 // The encoded reference to a mirror::Object. 104 uint32_t reference_; 105 }; 106 107 // References between objects within the managed heap. 108 // Similar API to ObjectReference, but not a value type. Supports atomic access. 109 template<class MirrorType> 110 class MANAGED HeapReference { 111 private: 112 using Compression = PtrCompression<kPoisonHeapReferences, MirrorType>; 113 114 public: HeapReference()115 HeapReference() REQUIRES_SHARED(Locks::mutator_lock_) : HeapReference(nullptr) {} 116 117 template <bool kIsVolatile = false> AsMirrorPtr()118 MirrorType* AsMirrorPtr() const REQUIRES_SHARED(Locks::mutator_lock_) { 119 return Compression::Decompress( 120 kIsVolatile ? reference_.load(std::memory_order_seq_cst) : reference_.LoadJavaData()); 121 } 122 123 template <bool kIsVolatile = false> Assign(MirrorType * other)124 void Assign(MirrorType* other) REQUIRES_SHARED(Locks::mutator_lock_) { 125 if (kIsVolatile) { 126 reference_.store(Compression::Compress(other), std::memory_order_seq_cst); 127 } else { 128 reference_.StoreJavaData(Compression::Compress(other)); 129 } 130 } 131 132 template <bool kIsVolatile = false> 133 void Assign(ObjPtr<MirrorType> ptr) REQUIRES_SHARED(Locks::mutator_lock_); 134 Clear()135 void Clear() { 136 reference_.StoreJavaData(0); 137 DCHECK(IsNull()); 138 } 139 IsNull()140 bool IsNull() const { 141 return reference_.LoadJavaData() == 0; 142 } 143 FromMirrorPtr(MirrorType * mirror_ptr)144 static HeapReference<MirrorType> FromMirrorPtr(MirrorType* mirror_ptr) 145 REQUIRES_SHARED(Locks::mutator_lock_) { 146 return HeapReference<MirrorType>(mirror_ptr); 147 } 148 149 bool CasWeakRelaxed(MirrorType* old_ptr, MirrorType* new_ptr) 150 REQUIRES_SHARED(Locks::mutator_lock_); 151 152 private: HeapReference(MirrorType * mirror_ptr)153 explicit HeapReference(MirrorType* mirror_ptr) REQUIRES_SHARED(Locks::mutator_lock_) 154 : reference_(Compression::Compress(mirror_ptr)) {} 155 156 // The encoded reference to a mirror::Object. Atomically updateable. 157 Atomic<uint32_t> reference_; 158 }; 159 160 static_assert(sizeof(mirror::HeapReference<mirror::Object>) == kHeapReferenceSize, 161 "heap reference size does not match"); 162 163 // Standard compressed reference used in the runtime. Used for StackReference and GC roots. 164 template<class MirrorType> 165 class MANAGED CompressedReference : public mirror::ObjectReference<false, MirrorType> { 166 public: REQUIRES_SHARED(Locks::mutator_lock_)167 CompressedReference<MirrorType>() REQUIRES_SHARED(Locks::mutator_lock_) 168 : mirror::ObjectReference<false, MirrorType>(nullptr) {} 169 FromMirrorPtr(MirrorType * p)170 static CompressedReference<MirrorType> FromMirrorPtr(MirrorType* p) 171 REQUIRES_SHARED(Locks::mutator_lock_) { 172 return CompressedReference<MirrorType>(p); 173 } 174 175 private: CompressedReference(MirrorType * p)176 explicit CompressedReference(MirrorType* p) REQUIRES_SHARED(Locks::mutator_lock_) 177 : mirror::ObjectReference<false, MirrorType>(p) {} 178 }; 179 180 } // namespace mirror 181 } // namespace art 182 183 #endif // ART_RUNTIME_MIRROR_OBJECT_REFERENCE_H_ 184