• 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_INL_H_
18  #define ART_RUNTIME_OBJ_PTR_INL_H_
19  
20  #include <ostream>
21  
22  #include "base/bit_utils.h"
23  #include "obj_ptr.h"
24  #include "thread-current-inl.h"
25  
26  namespace art {
27  
28  template<class MirrorType>
GetCurrentTrimedCookie()29  inline uintptr_t ObjPtr<MirrorType>::GetCurrentTrimedCookie() {
30    Thread* self = Thread::Current();
31    if (UNLIKELY(self == nullptr)) {
32      return kCookieMask;
33    }
34    return self->GetPoisonObjectCookie() & kCookieMask;
35  }
36  
37  template<class MirrorType>
IsValid()38  inline bool ObjPtr<MirrorType>::IsValid() const {
39    if (!kObjPtrPoisoning || IsNull()) {
40      return true;
41    }
42    return GetCookie() == GetCurrentTrimedCookie();
43  }
44  
45  template<class MirrorType>
AssertValid()46  inline void ObjPtr<MirrorType>::AssertValid() const {
47    if (kObjPtrPoisoning) {
48      CHECK(IsValid()) << "Stale object pointer " << PtrUnchecked() << " , expected cookie "
49          << GetCurrentTrimedCookie() << " but got " << GetCookie();
50    }
51  }
52  
53  template<class MirrorType>
Encode(MirrorType * ptr)54  inline uintptr_t ObjPtr<MirrorType>::Encode(MirrorType* ptr) {
55    uintptr_t ref = reinterpret_cast<uintptr_t>(ptr);
56    DCHECK_ALIGNED(ref, kObjectAlignment);
57    if (kObjPtrPoisoning && ref != 0) {
58      DCHECK_LE(ref, 0xFFFFFFFFU);
59      ref >>= kObjectAlignmentShift;
60      // Put cookie in high bits.
61      ref |= GetCurrentTrimedCookie() << kCookieShift;
62    }
63    return ref;
64  }
65  
66  template<class MirrorType>
67  template <typename Type,
68            typename /* = typename std::enable_if_t<std::is_base_of_v<MirrorType, Type>> */>
ObjPtr(Type * ptr)69  inline ObjPtr<MirrorType>::ObjPtr(Type* ptr)
70      : reference_(Encode(static_cast<MirrorType*>(ptr))) {
71  }
72  
73  template<class MirrorType>
74  template <typename Type,
75            typename /* = typename std::enable_if_t<std::is_base_of_v<MirrorType, Type>> */>
ObjPtr(const ObjPtr<Type> & other)76  inline ObjPtr<MirrorType>::ObjPtr(const ObjPtr<Type>& other)
77      : reference_(other.reference_) {
78    if (kObjPtrPoisoningValidateOnCopy) {
79      AssertValid();
80    }
81  }
82  
83  template<class MirrorType>
84  template <typename Type,
85            typename /* = typename std::enable_if_t<std::is_base_of_v<MirrorType, Type>> */>
86  inline ObjPtr<MirrorType>& ObjPtr<MirrorType>::operator=(const ObjPtr<Type>& other) {
87    reference_ = other.reference_;
88    if (kObjPtrPoisoningValidateOnCopy) {
89      AssertValid();
90    }
91    return *this;
92  }
93  
94  template<class MirrorType>
95  OBJPTR_INLINE ObjPtr<MirrorType>& ObjPtr<MirrorType>::operator=(MirrorType* ptr) {
96    Assign(ptr);
97    return *this;
98  }
99  
100  template<class MirrorType>
Assign(MirrorType * ptr)101  inline void ObjPtr<MirrorType>::Assign(MirrorType* ptr) {
102    reference_ = Encode(ptr);
103  }
104  
105  template<class MirrorType>
106  inline MirrorType* ObjPtr<MirrorType>::operator->() const {
107    return Ptr();
108  }
109  
110  template<class MirrorType>
Ptr()111  inline MirrorType* ObjPtr<MirrorType>::Ptr() const {
112    AssertValid();
113    return PtrUnchecked();
114  }
115  
116  template<class MirrorType>
117  template <typename SourceType>
DownCast(ObjPtr<SourceType> ptr)118  inline ObjPtr<MirrorType> ObjPtr<MirrorType>::DownCast(ObjPtr<SourceType> ptr) {
119    static_assert(std::is_base_of_v<SourceType, MirrorType>,
120                  "Target type must be a subtype of source type");
121    return static_cast<MirrorType*>(ptr.Ptr());
122  }
123  
124  template<class MirrorType>
125  template <typename SourceType>
DownCast(SourceType * ptr)126  inline ObjPtr<MirrorType> ObjPtr<MirrorType>::DownCast(SourceType* ptr) {
127    static_assert(std::is_base_of_v<SourceType, MirrorType>,
128                  "Target type must be a subtype of source type");
129    return static_cast<MirrorType*>(ptr);
130  }
131  
132  template<class MirrorType>
operator()133  size_t HashObjPtr::operator()(const ObjPtr<MirrorType>& ptr) const {
134    return std::hash<MirrorType*>()(ptr.Ptr());
135  }
136  
137  template<class MirrorType1, class MirrorType2>
138  inline std::enable_if_t<std::is_base_of_v<MirrorType1, MirrorType2> ||
139                          std::is_base_of_v<MirrorType2, MirrorType1>, bool>
140  operator==(ObjPtr<MirrorType1> lhs, ObjPtr<MirrorType2> rhs) {
141    return lhs.Ptr() == rhs.Ptr();
142  }
143  
144  template<class MirrorType1, class MirrorType2>
145  inline std::enable_if_t<std::is_base_of_v<MirrorType1, MirrorType2> ||
146                          std::is_base_of_v<MirrorType2, MirrorType1>, bool>
147  operator==(const MirrorType1* lhs, ObjPtr<MirrorType2> rhs) {
148    return lhs == rhs.Ptr();
149  }
150  
151  template<class MirrorType1, class MirrorType2>
152  inline std::enable_if_t<std::is_base_of_v<MirrorType1, MirrorType2> ||
153                          std::is_base_of_v<MirrorType2, MirrorType1>, bool>
154  operator==(ObjPtr<MirrorType1> lhs, const MirrorType2* rhs) {
155    return lhs.Ptr() == rhs;
156  }
157  
158  template<class MirrorType1, class MirrorType2>
159  inline std::enable_if_t<std::is_base_of_v<MirrorType1, MirrorType2> ||
160                          std::is_base_of_v<MirrorType2, MirrorType1>, bool>
161  operator!=(ObjPtr<MirrorType1> lhs, ObjPtr<MirrorType2> rhs) {
162    return !(lhs == rhs);
163  }
164  
165  template<class MirrorType1, class MirrorType2>
166  inline std::enable_if_t<std::is_base_of_v<MirrorType1, MirrorType2> ||
167                          std::is_base_of_v<MirrorType2, MirrorType1>, bool>
168  operator!=(const MirrorType1* lhs, ObjPtr<MirrorType2> rhs) {
169    return !(lhs == rhs);
170  }
171  
172  template<class MirrorType1, class MirrorType2>
173  inline std::enable_if_t<std::is_base_of_v<MirrorType1, MirrorType2> ||
174                          std::is_base_of_v<MirrorType2, MirrorType1>, bool>
175  operator!=(ObjPtr<MirrorType1> lhs, const MirrorType2* rhs) {
176    return !(lhs == rhs);
177  }
178  
179  template<class MirrorType>
180  inline std::ostream& operator<<(std::ostream& os, ObjPtr<MirrorType> ptr) {
181    // May be used for dumping bad pointers, do not use the checked version.
182    return os << ptr.PtrUnchecked();
183  }
184  
185  }  // namespace art
186  
187  #endif  // ART_RUNTIME_OBJ_PTR_INL_H_
188