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