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 26namespace art { 27namespace mirror { 28 29class 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 35template<bool kPoisonReferences, class MirrorType> 36class 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. 57template<bool kPoisonReferences, class MirrorType> 58class 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. 102template<class MirrorType> 103class 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 153static_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. 157template<class MirrorType> 158class 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