• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <iosfwd>
21 #include <type_traits>
22 
23 #include "base/locks.h"  // For Locks::mutator_lock_.
24 #include "base/macros.h"
25 #include "runtime_globals.h"
26 
27 // Always inline ObjPtr methods even in debug builds.
28 #define OBJPTR_INLINE __attribute__ ((always_inline))
29 
30 namespace art {
31 
32 constexpr bool kObjPtrPoisoning = kIsDebugBuild;
33 
34 // It turns out that most of the performance overhead comes from copying. Don't validate for now.
35 // This defers finding stale ObjPtr objects until they are used.
36 constexpr bool kObjPtrPoisoningValidateOnCopy = false;
37 
38 // Value type representing a pointer to a mirror::Object of type MirrorType
39 // Since the cookie is thread based, it is not safe to share an ObjPtr between threads.
40 template<class MirrorType>
41 class ObjPtr {
42   static constexpr size_t kCookieShift =
43       kHeapReferenceSize * kBitsPerByte - kObjectAlignmentShift;
44   static constexpr size_t kCookieBits = sizeof(uintptr_t) * kBitsPerByte - kCookieShift;
45   static constexpr uintptr_t kCookieMask = (static_cast<uintptr_t>(1u) << kCookieBits) - 1;
46 
47   static_assert(kCookieBits >= kObjectAlignmentShift,
48                 "must have a least kObjectAlignmentShift bits");
49 
50  public:
ObjPtr()51   OBJPTR_INLINE ObjPtr() : ObjPtr(nullptr) {}
52 
ObjPtr(std::nullptr_t)53   OBJPTR_INLINE ObjPtr(std::nullptr_t)
54       : reference_(0u) {
55     DCHECK(IsNull());
56   }
57 
58   // Note: The following constructors allow implicit conversion. This simplifies code that uses
59   //       them, e.g., for parameter passing. However, in general, implicit-conversion constructors
60   //       are discouraged and detected by clang-tidy.
61 
62   template <typename Type,
63             typename = typename std::enable_if_t<std::is_base_of_v<MirrorType, Type>>>
64   OBJPTR_INLINE ObjPtr(Type* ptr) REQUIRES_SHARED(Locks::mutator_lock_);
65 
66   template <typename Type,
67             typename = typename std::enable_if_t<std::is_base_of_v<MirrorType, Type>>>
68   OBJPTR_INLINE ObjPtr(const ObjPtr<Type>& other) REQUIRES_SHARED(Locks::mutator_lock_);
69 
70   template <typename Type,
71             typename = typename std::enable_if_t<std::is_base_of_v<MirrorType, Type>>>
72   OBJPTR_INLINE ObjPtr& operator=(const ObjPtr<Type>& other) REQUIRES_SHARED(Locks::mutator_lock_);
73 
74   OBJPTR_INLINE ObjPtr& operator=(MirrorType* ptr) REQUIRES_SHARED(Locks::mutator_lock_);
75 
76   OBJPTR_INLINE void Assign(MirrorType* ptr) REQUIRES_SHARED(Locks::mutator_lock_);
77 
78   OBJPTR_INLINE MirrorType* operator->() const REQUIRES_SHARED(Locks::mutator_lock_);
79 
IsNull()80   OBJPTR_INLINE bool IsNull() const {
81     return reference_ == 0;
82   }
83 
84   // Ptr makes sure that the object pointer is valid.
85   OBJPTR_INLINE MirrorType* Ptr() const REQUIRES_SHARED(Locks::mutator_lock_);
86 
87   OBJPTR_INLINE bool IsValid() const REQUIRES_SHARED(Locks::mutator_lock_);
88 
89   OBJPTR_INLINE void AssertValid() const REQUIRES_SHARED(Locks::mutator_lock_);
90 
91   // Ptr unchecked does not check that object pointer is valid. Do not use if you can avoid it.
PtrUnchecked()92   OBJPTR_INLINE MirrorType* PtrUnchecked() const {
93     if (kObjPtrPoisoning) {
94       return reinterpret_cast<MirrorType*>(
95           static_cast<uintptr_t>(static_cast<uint32_t>(reference_ << kObjectAlignmentShift)));
96     } else {
97       return reinterpret_cast<MirrorType*>(reference_);
98     }
99   }
100 
101   // Static function to be friendly with null pointers.
102   template <typename SourceType>
103   static ObjPtr<MirrorType> DownCast(ObjPtr<SourceType> ptr) REQUIRES_SHARED(Locks::mutator_lock_);
104 
105   // Static function to be friendly with null pointers.
106   template <typename SourceType>
107   static ObjPtr<MirrorType> DownCast(SourceType* ptr) REQUIRES_SHARED(Locks::mutator_lock_);
108 
109  private:
110   // Trim off high bits of thread local cookie.
111   OBJPTR_INLINE static uintptr_t GetCurrentTrimedCookie();
112 
GetCookie()113   OBJPTR_INLINE uintptr_t GetCookie() const {
114     return reference_ >> kCookieShift;
115   }
116 
117   OBJPTR_INLINE static uintptr_t Encode(MirrorType* ptr) REQUIRES_SHARED(Locks::mutator_lock_);
118   // The encoded reference and cookie.
119   uintptr_t reference_;
120 
121   template <class T> friend class ObjPtr;  // Required for reference_ access in copy cons/operator.
122 };
123 
124 static_assert(std::is_trivially_copyable<ObjPtr<void>>::value,
125               "ObjPtr should be trivially copyable");
126 
127 // Hash function for stl data structures.
128 class HashObjPtr {
129  public:
130   template<class MirrorType>
131   size_t operator()(const ObjPtr<MirrorType>& ptr) const NO_THREAD_SAFETY_ANALYSIS;
132 };
133 
134 template<class MirrorType1, class MirrorType2>
135 OBJPTR_INLINE std::enable_if_t<std::is_base_of_v<MirrorType1, MirrorType2> ||
136                                std::is_base_of_v<MirrorType2, MirrorType1>, bool>
137 operator==(ObjPtr<MirrorType1> lhs, ObjPtr<MirrorType2> rhs)
138     REQUIRES_SHARED(Locks::mutator_lock_);
139 
140 template<class MirrorType1, class MirrorType2>
141 OBJPTR_INLINE std::enable_if_t<std::is_base_of_v<MirrorType1, MirrorType2> ||
142                                std::is_base_of_v<MirrorType2, MirrorType1>, bool>
143 operator==(const MirrorType1* lhs, ObjPtr<MirrorType2> rhs)
144     REQUIRES_SHARED(Locks::mutator_lock_);
145 
146 template<class MirrorType1, class MirrorType2>
147 OBJPTR_INLINE std::enable_if_t<std::is_base_of_v<MirrorType1, MirrorType2> ||
148                                std::is_base_of_v<MirrorType2, MirrorType1>, bool>
149 operator==(ObjPtr<MirrorType1> lhs, const MirrorType2* rhs)
150     REQUIRES_SHARED(Locks::mutator_lock_);
151 
152 template<class MirrorType>
153 OBJPTR_INLINE bool operator==(ObjPtr<MirrorType> ptr, std::nullptr_t) {
154   return ptr.IsNull();
155 }
156 
157 template<class MirrorType>
158 OBJPTR_INLINE bool operator==(std::nullptr_t, ObjPtr<MirrorType> ptr) {
159   return ptr.IsNull();
160 }
161 
162 template<class MirrorType1, class MirrorType2>
163 OBJPTR_INLINE std::enable_if_t<std::is_base_of_v<MirrorType1, MirrorType2> ||
164                                std::is_base_of_v<MirrorType2, MirrorType1>, bool>
165 operator!=(ObjPtr<MirrorType1> lhs, ObjPtr<MirrorType2> rhs)
166     REQUIRES_SHARED(Locks::mutator_lock_);
167 
168 template<class MirrorType1, class MirrorType2>
169 OBJPTR_INLINE std::enable_if_t<std::is_base_of_v<MirrorType1, MirrorType2> ||
170                                std::is_base_of_v<MirrorType2, MirrorType1>, bool>
171 operator!=(const MirrorType1* lhs, ObjPtr<MirrorType2> rhs)
172     REQUIRES_SHARED(Locks::mutator_lock_);
173 
174 template<class MirrorType1, class MirrorType2>
175 OBJPTR_INLINE std::enable_if_t<std::is_base_of_v<MirrorType1, MirrorType2> ||
176                                std::is_base_of_v<MirrorType2, MirrorType1>, bool>
177 operator!=(ObjPtr<MirrorType1> lhs, const MirrorType2* rhs)
178     REQUIRES_SHARED(Locks::mutator_lock_);
179 
180 template<class MirrorType>
181 OBJPTR_INLINE bool operator!=(ObjPtr<MirrorType> ptr, std::nullptr_t) {
182   return !(ptr == nullptr);
183 }
184 
185 template<class MirrorType>
186 OBJPTR_INLINE bool operator!=(std::nullptr_t, ObjPtr<MirrorType> ptr) {
187   return !(nullptr == ptr);
188 }
189 
190 template<class MirrorType>
191 OBJPTR_INLINE std::ostream& operator<<(std::ostream& os, ObjPtr<MirrorType> ptr);
192 
193 }  // namespace art
194 
195 #endif  // ART_RUNTIME_OBJ_PTR_H_
196