• 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 <array>
21 #include <string_view>
22 
23 #include "base/atomic.h"
24 #include "base/locks.h"  // For Locks::mutator_lock_.
25 #include "heap_poisoning.h"
26 #include "obj_ptr.h"
27 #include "runtime_globals.h"
28 
29 namespace art {
30 namespace mirror {
31 
32 class Object;
33 
34 // Classes shared with the managed side of the world need to be packed so that they don't have
35 // extra platform specific padding.
36 #define MANAGED PACKED(4)
37 #define MIRROR_CLASS(desc) \
38   static_assert(::art::mirror::IsMirroredDescriptor(desc), \
39                 desc " is not a known mirror class. Please update" \
40                 " IsMirroredDescriptor to include it!")
41 
IsMirroredDescriptor(std::string_view desc)42 constexpr bool IsMirroredDescriptor(std::string_view desc) {
43   if (desc[0] != 'L') {
44     // All primitives and arrays are mirrored
45     return true;
46   }
47 #define MIRROR_DESCRIPTORS(vis)                       \
48     vis("Ljava/lang/Class;")                          \
49     vis("Ljava/lang/ClassLoader;")                    \
50     vis("Ljava/lang/ClassNotFoundException;")         \
51     vis("Ljava/lang/DexCache;")                       \
52     vis("Ljava/lang/Object;")                         \
53     vis("Ljava/lang/StackTraceElement;")              \
54     vis("Ljava/lang/String;")                         \
55     vis("Ljava/lang/Throwable;")                      \
56     vis("Ljava/lang/invoke/ArrayElementVarHandle;")   \
57     vis("Ljava/lang/invoke/ByteArrayViewVarHandle;")  \
58     vis("Ljava/lang/invoke/ByteBufferViewVarHandle;") \
59     vis("Ljava/lang/invoke/CallSite;")                \
60     vis("Ljava/lang/invoke/FieldVarHandle;")          \
61     vis("Ljava/lang/invoke/StaticFieldVarHandle;")    \
62     vis("Ljava/lang/invoke/MethodHandle;")            \
63     vis("Ljava/lang/invoke/MethodHandleImpl;")        \
64     vis("Ljava/lang/invoke/MethodHandles$Lookup;")    \
65     vis("Ljava/lang/invoke/MethodType;")              \
66     vis("Ljava/lang/invoke/VarHandle;")               \
67     vis("Ljava/lang/ref/FinalizerReference;")         \
68     vis("Ljava/lang/ref/Reference;")                  \
69     vis("Ljava/lang/reflect/AccessibleObject;")       \
70     vis("Ljava/lang/reflect/Constructor;")            \
71     vis("Ljava/lang/reflect/Executable;")             \
72     vis("Ljava/lang/reflect/Field;")                  \
73     vis("Ljava/lang/reflect/Method;")                 \
74     vis("Ljava/lang/reflect/Proxy;")                  \
75     vis("Ldalvik/system/ClassExt;")                   \
76     vis("Ldalvik/system/EmulatedStackFrame;")
77   // TODO: Once we are C++ 20 we can just have a constexpr array and std::find.
78   // constexpr std::array<std::string_view, 28> kMirrorTypes{
79   //    // Fill in
80   // };
81   // return std::find(kMirrorTypes.begin(), kMirrorTypes.end(), desc) != kMirrorTypes.end();
82 #define CHECK_DESCRIPTOR(descriptor)          \
83   if (std::string_view(descriptor) == desc) { \
84     return true;                              \
85   }
86   MIRROR_DESCRIPTORS(CHECK_DESCRIPTOR)
87 #undef CHECK_DESCRIPTOR
88   return false;
89 #undef MIRROR_DESCRIPTORS
90 }
91 
92 template<bool kPoisonReferences, class MirrorType>
93 class PtrCompression {
94  public:
95   // Compress reference to its bit representation.
Compress(MirrorType * mirror_ptr)96   static uint32_t Compress(MirrorType* mirror_ptr) {
97     uintptr_t as_bits = reinterpret_cast<uintptr_t>(mirror_ptr);
98     return static_cast<uint32_t>(kPoisonReferences ? -as_bits : as_bits);
99   }
100 
101   // Uncompress an encoded reference from its bit representation.
Decompress(uint32_t ref)102   static MirrorType* Decompress(uint32_t ref) {
103     uintptr_t as_bits = kPoisonReferences ? -ref : ref;
104     return reinterpret_cast<MirrorType*>(as_bits);
105   }
106 
107   // Convert an ObjPtr to a compressed reference.
108   static uint32_t Compress(ObjPtr<MirrorType> ptr) REQUIRES_SHARED(Locks::mutator_lock_);
109 };
110 
111 // Value type representing a reference to a mirror::Object of type MirrorType.
112 template<bool kPoisonReferences, class MirrorType>
113 class MANAGED ObjectReference {
114  private:
115   using Compression = PtrCompression<kPoisonReferences, MirrorType>;
116 
117  public:
118   /*
119    * Returns a pointer to the mirror of the managed object this reference is for.
120    *
121    * This does NOT return the current object (which isn't derived from, and
122    * therefor cannot be a mirror::Object) as a mirror pointer.  Instead, this
123    * returns a pointer to the mirror of the managed object this refers to.
124    *
125    * TODO (chriswailes): Rename to GetPtr().
126    */
AsMirrorPtr()127   MirrorType* AsMirrorPtr() const {
128     return Compression::Decompress(reference_);
129   }
130 
Assign(MirrorType * other)131   void Assign(MirrorType* other) {
132     reference_ = Compression::Compress(other);
133   }
134 
135   void Assign(ObjPtr<MirrorType> ptr) REQUIRES_SHARED(Locks::mutator_lock_);
136 
Clear()137   void Clear() {
138     reference_ = 0;
139     DCHECK(IsNull());
140   }
141 
IsNull()142   bool IsNull() const {
143     return reference_ == 0;
144   }
145 
AsVRegValue()146   uint32_t AsVRegValue() const {
147     return reference_;
148   }
149 
FromMirrorPtr(MirrorType * mirror_ptr)150   static ObjectReference<kPoisonReferences, MirrorType> FromMirrorPtr(MirrorType* mirror_ptr)
151       REQUIRES_SHARED(Locks::mutator_lock_) {
152     return ObjectReference<kPoisonReferences, MirrorType>(mirror_ptr);
153   }
154 
155  protected:
ObjectReference(MirrorType * mirror_ptr)156   explicit ObjectReference(MirrorType* mirror_ptr) REQUIRES_SHARED(Locks::mutator_lock_)
157       : reference_(Compression::Compress(mirror_ptr)) {
158   }
159 
160   // The encoded reference to a mirror::Object.
161   uint32_t reference_;
162 };
163 
164 // References between objects within the managed heap.
165 // Similar API to ObjectReference, but not a value type. Supports atomic access.
166 template<class MirrorType>
167 class MANAGED HeapReference {
168  private:
169   using Compression = PtrCompression<kPoisonHeapReferences, MirrorType>;
170 
171  public:
HeapReference()172   HeapReference() REQUIRES_SHARED(Locks::mutator_lock_) : HeapReference(nullptr) {}
173 
174   template <bool kIsVolatile = false>
AsMirrorPtr()175   MirrorType* AsMirrorPtr() const REQUIRES_SHARED(Locks::mutator_lock_) {
176     return Compression::Decompress(
177         kIsVolatile ? reference_.load(std::memory_order_seq_cst) : reference_.LoadJavaData());
178   }
179 
180   template <bool kIsVolatile = false>
Assign(MirrorType * other)181   void Assign(MirrorType* other) REQUIRES_SHARED(Locks::mutator_lock_) {
182     if (kIsVolatile) {
183       reference_.store(Compression::Compress(other), std::memory_order_seq_cst);
184     } else {
185       reference_.StoreJavaData(Compression::Compress(other));
186     }
187   }
188 
189   template <bool kIsVolatile = false>
190   void Assign(ObjPtr<MirrorType> ptr) REQUIRES_SHARED(Locks::mutator_lock_);
191 
Clear()192   void Clear() {
193     reference_.StoreJavaData(0);
194     DCHECK(IsNull());
195   }
196 
IsNull()197   bool IsNull() const {
198     return reference_.LoadJavaData() == 0;
199   }
200 
FromMirrorPtr(MirrorType * mirror_ptr)201   static HeapReference<MirrorType> FromMirrorPtr(MirrorType* mirror_ptr)
202       REQUIRES_SHARED(Locks::mutator_lock_) {
203     return HeapReference<MirrorType>(mirror_ptr);
204   }
205 
206   bool CasWeakRelaxed(MirrorType* old_ptr, MirrorType* new_ptr)
207       REQUIRES_SHARED(Locks::mutator_lock_);
208 
209  private:
HeapReference(MirrorType * mirror_ptr)210   explicit HeapReference(MirrorType* mirror_ptr) REQUIRES_SHARED(Locks::mutator_lock_)
211       : reference_(Compression::Compress(mirror_ptr)) {}
212 
213   // The encoded reference to a mirror::Object. Atomically updateable.
214   Atomic<uint32_t> reference_;
215 };
216 
217 static_assert(sizeof(mirror::HeapReference<mirror::Object>) == kHeapReferenceSize,
218               "heap reference size does not match");
219 
220 // Standard compressed reference used in the runtime. Used for StackReference and GC roots.
221 template<class MirrorType>
222 class MANAGED CompressedReference : public mirror::ObjectReference<false, MirrorType> {
223  public:
REQUIRES_SHARED(Locks::mutator_lock_)224   CompressedReference<MirrorType>() REQUIRES_SHARED(Locks::mutator_lock_)
225       : mirror::ObjectReference<false, MirrorType>(nullptr) {}
226 
FromMirrorPtr(MirrorType * p)227   static CompressedReference<MirrorType> FromMirrorPtr(MirrorType* p)
228       REQUIRES_SHARED(Locks::mutator_lock_) {
229     return CompressedReference<MirrorType>(p);
230   }
231 
232  private:
CompressedReference(MirrorType * p)233   explicit CompressedReference(MirrorType* p) REQUIRES_SHARED(Locks::mutator_lock_)
234       : mirror::ObjectReference<false, MirrorType>(p) {}
235 };
236 
237 }  // namespace mirror
238 }  // namespace art
239 
240 #endif  // ART_RUNTIME_MIRROR_OBJECT_REFERENCE_H_
241