• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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