1 /*
2  * Copyright (C) 2016 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_OBJ_PTR_H_
18 #define ART_RUNTIME_OBJ_PTR_H_
19 
20 #include <ostream>
21 #include <type_traits>
22 
23 #include "base/macros.h"
24 #include "base/mutex.h"  // For Locks::mutator_lock_.
25 #include "globals.h"
26 
27 namespace art {
28 
29 constexpr bool kObjPtrPoisoning = kIsDebugBuild;
30 
31 // Value type representing a pointer to a mirror::Object of type MirrorType
32 // Pass kPoison as a template boolean for testing in non-debug builds.
33 // Since the cookie is thread based, it is not safe to share an ObjPtr between threads.
34 template<class MirrorType>
35 class ObjPtr {
36   static constexpr size_t kCookieShift =
37       sizeof(kHeapReferenceSize) * kBitsPerByte - kObjectAlignmentShift;
38   static constexpr size_t kCookieBits = sizeof(uintptr_t) * kBitsPerByte - kCookieShift;
39   static constexpr uintptr_t kCookieMask = (static_cast<uintptr_t>(1u) << kCookieBits) - 1;
40 
41   static_assert(kCookieBits >= kObjectAlignmentShift,
42                 "must have a least kObjectAlignmentShift bits");
43 
44  public:
ObjPtr()45   ALWAYS_INLINE ObjPtr() REQUIRES_SHARED(Locks::mutator_lock_) : reference_(0u) {}
46 
47   // Note: The following constructors allow implicit conversion. This simplifies code that uses
48   //       them, e.g., for parameter passing. However, in general, implicit-conversion constructors
49   //       are discouraged and detected by cpplint and clang-tidy. So mark these constructors
50   //       as NOLINT (without category, as the categories are different).
51 
ObjPtr(std::nullptr_t)52   ALWAYS_INLINE ObjPtr(std::nullptr_t)  // NOLINT
53       REQUIRES_SHARED(Locks::mutator_lock_)
54       : reference_(0u) {}
55 
56   template <typename Type,
57             typename = typename std::enable_if<std::is_base_of<MirrorType, Type>::value>::type>
ObjPtr(Type * ptr)58   ALWAYS_INLINE ObjPtr(Type* ptr)  // NOLINT
59       REQUIRES_SHARED(Locks::mutator_lock_)
60       : reference_(Encode(static_cast<MirrorType*>(ptr))) {
61   }
62 
63   template <typename Type,
64             typename = typename std::enable_if<std::is_base_of<MirrorType, Type>::value>::type>
ObjPtr(const ObjPtr<Type> & other)65   ALWAYS_INLINE ObjPtr(const ObjPtr<Type>& other)  // NOLINT
66       REQUIRES_SHARED(Locks::mutator_lock_)
67       : reference_(Encode(static_cast<MirrorType*>(other.Ptr()))) {
68   }
69 
70   template <typename Type,
71             typename = typename std::enable_if<std::is_base_of<MirrorType, Type>::value>::type>
72   ALWAYS_INLINE ObjPtr& operator=(const ObjPtr<Type>& other)
REQUIRES_SHARED(Locks::mutator_lock_)73       REQUIRES_SHARED(Locks::mutator_lock_) {
74     reference_ = Encode(static_cast<MirrorType*>(other.Ptr()));
75     return *this;
76   }
77 
REQUIRES_SHARED(Locks::mutator_lock_)78   ALWAYS_INLINE ObjPtr& operator=(MirrorType* ptr) REQUIRES_SHARED(Locks::mutator_lock_) {
79     Assign(ptr);
80     return *this;
81   }
82 
Assign(MirrorType * ptr)83   ALWAYS_INLINE void Assign(MirrorType* ptr) REQUIRES_SHARED(Locks::mutator_lock_) {
84     reference_ = Encode(ptr);
85   }
86 
87   ALWAYS_INLINE MirrorType* operator->() const REQUIRES_SHARED(Locks::mutator_lock_) {
88     return Ptr();
89   }
90 
IsNull()91   ALWAYS_INLINE bool IsNull() const {
92     return reference_ == 0;
93   }
94 
95   // Ptr makes sure that the object pointer is valid.
Ptr()96   ALWAYS_INLINE MirrorType* Ptr() const REQUIRES_SHARED(Locks::mutator_lock_) {
97     AssertValid();
98     return PtrUnchecked();
99   }
100 
101   ALWAYS_INLINE bool IsValid() const REQUIRES_SHARED(Locks::mutator_lock_);
102 
103   ALWAYS_INLINE void AssertValid() const REQUIRES_SHARED(Locks::mutator_lock_);
104 
105   ALWAYS_INLINE bool operator==(const ObjPtr& ptr) const REQUIRES_SHARED(Locks::mutator_lock_) {
106     return Ptr() == ptr.Ptr();
107   }
108 
109   template <typename PointerType>
110   ALWAYS_INLINE bool operator==(const PointerType* ptr) const
111       REQUIRES_SHARED(Locks::mutator_lock_) {
112     return Ptr() == ptr;
113   }
114 
115   ALWAYS_INLINE bool operator==(std::nullptr_t) const {
116     return IsNull();
117   }
118 
119   ALWAYS_INLINE bool operator!=(const ObjPtr& ptr) const REQUIRES_SHARED(Locks::mutator_lock_) {
120     return Ptr() != ptr.Ptr();
121   }
122 
123   template <typename PointerType>
124   ALWAYS_INLINE bool operator!=(const PointerType* ptr) const
125       REQUIRES_SHARED(Locks::mutator_lock_) {
126     return Ptr() != ptr;
127   }
128 
129   ALWAYS_INLINE bool operator!=(std::nullptr_t) const {
130     return !IsNull();
131   }
132 
133   // Ptr unchecked does not check that object pointer is valid. Do not use if you can avoid it.
PtrUnchecked()134   ALWAYS_INLINE MirrorType* PtrUnchecked() const {
135     if (kObjPtrPoisoning) {
136       return reinterpret_cast<MirrorType*>(
137           static_cast<uintptr_t>(static_cast<uint32_t>(reference_ << kObjectAlignmentShift)));
138     } else {
139       return reinterpret_cast<MirrorType*>(reference_);
140     }
141   }
142 
143   // Static function to be friendly with null pointers.
144   template <typename SourceType>
DownCast(ObjPtr<SourceType> ptr)145   static ObjPtr<MirrorType> DownCast(ObjPtr<SourceType> ptr) REQUIRES_SHARED(Locks::mutator_lock_) {
146     static_assert(std::is_base_of<SourceType, MirrorType>::value,
147                   "Target type must be a subtype of source type");
148     return static_cast<MirrorType*>(ptr.Ptr());
149   }
150 
151  private:
152   // Trim off high bits of thread local cookie.
TrimCookie(uintptr_t cookie)153   ALWAYS_INLINE static uintptr_t TrimCookie(uintptr_t cookie) {
154     return cookie & kCookieMask;
155   }
156 
GetCookie()157   ALWAYS_INLINE uintptr_t GetCookie() const {
158     return reference_ >> kCookieShift;
159   }
160 
161   ALWAYS_INLINE static uintptr_t Encode(MirrorType* ptr) REQUIRES_SHARED(Locks::mutator_lock_);
162   // The encoded reference and cookie.
163   uintptr_t reference_;
164 };
165 
166 static_assert(std::is_trivially_copyable<ObjPtr<void>>::value,
167               "ObjPtr should be trivially copyable");
168 
169 // Hash function for stl data structures.
170 class HashObjPtr {
171  public:
172   template<class MirrorType>
operator()173   size_t operator()(const ObjPtr<MirrorType>& ptr) const NO_THREAD_SAFETY_ANALYSIS {
174     return std::hash<MirrorType*>()(ptr.Ptr());
175   }
176 };
177 
178 template<class MirrorType, typename PointerType>
179 ALWAYS_INLINE bool operator==(const PointerType* a, const ObjPtr<MirrorType>& b)
180     REQUIRES_SHARED(Locks::mutator_lock_) {
181   return b == a;
182 }
183 
184 template<class MirrorType>
185 ALWAYS_INLINE bool operator==(std::nullptr_t, const ObjPtr<MirrorType>& b) {
186   return b == nullptr;
187 }
188 
189 template<typename MirrorType, typename PointerType>
190 ALWAYS_INLINE bool operator!=(const PointerType* a, const ObjPtr<MirrorType>& b)
191     REQUIRES_SHARED(Locks::mutator_lock_) {
192   return b != a;
193 }
194 
195 template<class MirrorType>
196 ALWAYS_INLINE bool operator!=(std::nullptr_t, const ObjPtr<MirrorType>& b) {
197   return b != nullptr;
198 }
199 
200 template<class MirrorType>
MakeObjPtr(MirrorType * ptr)201 static inline ObjPtr<MirrorType> MakeObjPtr(MirrorType* ptr) {
202   return ObjPtr<MirrorType>(ptr);
203 }
204 
205 template<class MirrorType>
MakeObjPtr(ObjPtr<MirrorType> ptr)206 static inline ObjPtr<MirrorType> MakeObjPtr(ObjPtr<MirrorType> ptr) {
207   return ObjPtr<MirrorType>(ptr);
208 }
209 
210 template<class MirrorType>
211 ALWAYS_INLINE std::ostream& operator<<(std::ostream& os, ObjPtr<MirrorType> ptr);
212 
213 }  // namespace art
214 
215 #endif  // ART_RUNTIME_OBJ_PTR_H_
216