• 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() REQUIRES_SHARED(Locks::mutator_lock_) : reference_(0u) {}
52 
53   // Note: The following constructors allow implicit conversion. This simplifies code that uses
54   //       them, e.g., for parameter passing. However, in general, implicit-conversion constructors
55   //       are discouraged and detected by clang-tidy.
56 
ObjPtr(std::nullptr_t)57   OBJPTR_INLINE ObjPtr(std::nullptr_t)
58       REQUIRES_SHARED(Locks::mutator_lock_)
59       : reference_(0u) {}
60 
61   template <typename Type,
62             typename = typename std::enable_if_t<std::is_base_of_v<MirrorType, Type>>>
63   OBJPTR_INLINE ObjPtr(Type* ptr) REQUIRES_SHARED(Locks::mutator_lock_);
64 
65   template <typename Type,
66             typename = typename std::enable_if_t<std::is_base_of_v<MirrorType, Type>>>
67   OBJPTR_INLINE ObjPtr(const ObjPtr<Type>& other) REQUIRES_SHARED(Locks::mutator_lock_);
68 
69   template <typename Type,
70             typename = typename std::enable_if_t<std::is_base_of_v<MirrorType, Type>>>
71   OBJPTR_INLINE ObjPtr& operator=(const ObjPtr<Type>& other) REQUIRES_SHARED(Locks::mutator_lock_);
72 
73   OBJPTR_INLINE ObjPtr& operator=(MirrorType* ptr) REQUIRES_SHARED(Locks::mutator_lock_);
74 
75   OBJPTR_INLINE void Assign(MirrorType* ptr) REQUIRES_SHARED(Locks::mutator_lock_);
76 
77   OBJPTR_INLINE MirrorType* operator->() const REQUIRES_SHARED(Locks::mutator_lock_);
78 
IsNull()79   OBJPTR_INLINE bool IsNull() const {
80     return reference_ == 0;
81   }
82 
83   // Ptr makes sure that the object pointer is valid.
84   OBJPTR_INLINE MirrorType* Ptr() const REQUIRES_SHARED(Locks::mutator_lock_);
85 
86   OBJPTR_INLINE bool IsValid() const REQUIRES_SHARED(Locks::mutator_lock_);
87 
88   OBJPTR_INLINE void AssertValid() const REQUIRES_SHARED(Locks::mutator_lock_);
89 
90   // Ptr unchecked does not check that object pointer is valid. Do not use if you can avoid it.
PtrUnchecked()91   OBJPTR_INLINE MirrorType* PtrUnchecked() const {
92     if (kObjPtrPoisoning) {
93       return reinterpret_cast<MirrorType*>(
94           static_cast<uintptr_t>(static_cast<uint32_t>(reference_ << kObjectAlignmentShift)));
95     } else {
96       return reinterpret_cast<MirrorType*>(reference_);
97     }
98   }
99 
100   // Static function to be friendly with null pointers.
101   template <typename SourceType>
102   static ObjPtr<MirrorType> DownCast(ObjPtr<SourceType> ptr) REQUIRES_SHARED(Locks::mutator_lock_);
103 
104   // Static function to be friendly with null pointers.
105   template <typename SourceType>
106   static ObjPtr<MirrorType> DownCast(SourceType* ptr) REQUIRES_SHARED(Locks::mutator_lock_);
107 
108  private:
109   // Trim off high bits of thread local cookie.
110   OBJPTR_INLINE static uintptr_t GetCurrentTrimedCookie();
111 
GetCookie()112   OBJPTR_INLINE uintptr_t GetCookie() const {
113     return reference_ >> kCookieShift;
114   }
115 
116   OBJPTR_INLINE static uintptr_t Encode(MirrorType* ptr) REQUIRES_SHARED(Locks::mutator_lock_);
117   // The encoded reference and cookie.
118   uintptr_t reference_;
119 
120   template <class T> friend class ObjPtr;  // Required for reference_ access in copy cons/operator.
121 };
122 
123 static_assert(std::is_trivially_copyable<ObjPtr<void>>::value,
124               "ObjPtr should be trivially copyable");
125 
126 // Hash function for stl data structures.
127 class HashObjPtr {
128  public:
129   template<class MirrorType>
130   size_t operator()(const ObjPtr<MirrorType>& ptr) const NO_THREAD_SAFETY_ANALYSIS;
131 };
132 
133 template<class MirrorType1, class MirrorType2>
134 OBJPTR_INLINE std::enable_if_t<std::is_base_of_v<MirrorType1, MirrorType2> ||
135                                std::is_base_of_v<MirrorType2, MirrorType1>, bool>
136 operator==(ObjPtr<MirrorType1> lhs, ObjPtr<MirrorType2> rhs)
137     REQUIRES_SHARED(Locks::mutator_lock_);
138 
139 template<class MirrorType1, class MirrorType2>
140 OBJPTR_INLINE std::enable_if_t<std::is_base_of_v<MirrorType1, MirrorType2> ||
141                                std::is_base_of_v<MirrorType2, MirrorType1>, bool>
142 operator==(const MirrorType1* lhs, ObjPtr<MirrorType2> rhs)
143     REQUIRES_SHARED(Locks::mutator_lock_);
144 
145 template<class MirrorType1, class MirrorType2>
146 OBJPTR_INLINE std::enable_if_t<std::is_base_of_v<MirrorType1, MirrorType2> ||
147                                std::is_base_of_v<MirrorType2, MirrorType1>, bool>
148 operator==(ObjPtr<MirrorType1> lhs, const MirrorType2* rhs)
149     REQUIRES_SHARED(Locks::mutator_lock_);
150 
151 template<class MirrorType>
152 OBJPTR_INLINE bool operator==(ObjPtr<MirrorType> ptr, std::nullptr_t) {
153   return ptr.IsNull();
154 }
155 
156 template<class MirrorType>
157 OBJPTR_INLINE bool operator==(std::nullptr_t, ObjPtr<MirrorType> ptr) {
158   return ptr.IsNull();
159 }
160 
161 template<class MirrorType1, class MirrorType2>
162 OBJPTR_INLINE std::enable_if_t<std::is_base_of_v<MirrorType1, MirrorType2> ||
163                                std::is_base_of_v<MirrorType2, MirrorType1>, bool>
164 operator!=(ObjPtr<MirrorType1> lhs, ObjPtr<MirrorType2> rhs)
165     REQUIRES_SHARED(Locks::mutator_lock_);
166 
167 template<class MirrorType1, class MirrorType2>
168 OBJPTR_INLINE std::enable_if_t<std::is_base_of_v<MirrorType1, MirrorType2> ||
169                                std::is_base_of_v<MirrorType2, MirrorType1>, bool>
170 operator!=(const MirrorType1* lhs, ObjPtr<MirrorType2> rhs)
171     REQUIRES_SHARED(Locks::mutator_lock_);
172 
173 template<class MirrorType1, class MirrorType2>
174 OBJPTR_INLINE std::enable_if_t<std::is_base_of_v<MirrorType1, MirrorType2> ||
175                                std::is_base_of_v<MirrorType2, MirrorType1>, bool>
176 operator!=(ObjPtr<MirrorType1> lhs, const MirrorType2* rhs)
177     REQUIRES_SHARED(Locks::mutator_lock_);
178 
179 template<class MirrorType>
180 OBJPTR_INLINE bool operator!=(ObjPtr<MirrorType> ptr, std::nullptr_t) {
181   return !(ptr == nullptr);
182 }
183 
184 template<class MirrorType>
185 OBJPTR_INLINE bool operator!=(std::nullptr_t, ObjPtr<MirrorType> ptr) {
186   return !(nullptr == ptr);
187 }
188 
189 template<class MirrorType>
190 OBJPTR_INLINE std::ostream& operator<<(std::ostream& os, ObjPtr<MirrorType> ptr);
191 
192 }  // namespace art
193 
194 #endif  // ART_RUNTIME_OBJ_PTR_H_
195