blob: 74be44eb23e69954e55a80390a1de76c3bd41da2 [file] [log] [blame]
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -07001/*
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
Mathieu Chartiera59d9b22016-09-26 18:13:17 -070017#ifndef ART_RUNTIME_OBJ_PTR_H_
18#define ART_RUNTIME_OBJ_PTR_H_
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -070019
Mathieu Chartier0795f232016-09-27 18:43:30 -070020#include <ostream>
Mathieu Chartierf8ac97f2016-10-05 15:56:52 -070021#include <type_traits>
Mathieu Chartier0795f232016-09-27 18:43:30 -070022
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -070023#include "base/mutex.h" // For Locks::mutator_lock_.
24#include "globals.h"
25#include "mirror/object_reference.h"
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -070026
27namespace art {
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -070028
29// Value type representing a pointer to a mirror::Object of type MirrorType
30// Pass kPoison as a template boolean for testing in non-debug builds.
Mathieu Chartiera59d9b22016-09-26 18:13:17 -070031// Since the cookie is thread based, it is not safe to share an ObjPtr between threads.
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -070032template<class MirrorType, bool kPoison = kIsDebugBuild>
33class ObjPtr {
34 static constexpr size_t kCookieShift =
35 sizeof(mirror::HeapReference<mirror::Object>) * kBitsPerByte - kObjectAlignmentShift;
36 static constexpr size_t kCookieBits = sizeof(uintptr_t) * kBitsPerByte - kCookieShift;
37 static constexpr uintptr_t kCookieMask = (static_cast<uintptr_t>(1u) << kCookieBits) - 1;
38
39 static_assert(kCookieBits >= kObjectAlignmentShift,
40 "must have a least kObjectAlignmentShift bits");
41
42 public:
43 ALWAYS_INLINE ObjPtr() REQUIRES_SHARED(Locks::mutator_lock_) : reference_(0u) {}
44
Mathieu Chartiera59d9b22016-09-26 18:13:17 -070045 ALWAYS_INLINE ObjPtr(std::nullptr_t) REQUIRES_SHARED(Locks::mutator_lock_) : reference_(0u) {}
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -070046
Mathieu Chartiera59d9b22016-09-26 18:13:17 -070047 template <typename Type>
48 ALWAYS_INLINE ObjPtr(Type* ptr) REQUIRES_SHARED(Locks::mutator_lock_)
Mathieu Chartierf8ac97f2016-10-05 15:56:52 -070049 : reference_(Encode(static_cast<MirrorType*>(ptr))) {
50 static_assert(std::is_base_of<MirrorType, Type>::value,
51 "Input type must be a subtype of the ObjPtr type");
52 }
Mathieu Chartiera59d9b22016-09-26 18:13:17 -070053
Mathieu Chartier0795f232016-09-27 18:43:30 -070054 template <typename Type>
Mathieu Chartierf8ac97f2016-10-05 15:56:52 -070055 ALWAYS_INLINE ObjPtr(const ObjPtr<Type, kPoison>& other) REQUIRES_SHARED(Locks::mutator_lock_)
56 : reference_(Encode(static_cast<MirrorType*>(other.Ptr()))) {
57 static_assert(std::is_base_of<MirrorType, Type>::value,
58 "Input type must be a subtype of the ObjPtr type");
59 }
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -070060
Mathieu Chartier0795f232016-09-27 18:43:30 -070061 template <typename Type>
Mathieu Chartierf8ac97f2016-10-05 15:56:52 -070062 ALWAYS_INLINE ObjPtr& operator=(const ObjPtr<Type, kPoison>& other)
63 REQUIRES_SHARED(Locks::mutator_lock_) {
64 static_assert(std::is_base_of<MirrorType, Type>::value,
65 "Input type must be a subtype of the ObjPtr type");
Mathieu Chartier1cc62e42016-10-03 18:01:28 -070066 reference_ = Encode(static_cast<MirrorType*>(other.Ptr()));
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -070067 return *this;
68 }
69
70 ALWAYS_INLINE ObjPtr& operator=(MirrorType* ptr) REQUIRES_SHARED(Locks::mutator_lock_) {
71 Assign(ptr);
72 return *this;
73 }
74
75 ALWAYS_INLINE void Assign(MirrorType* ptr) REQUIRES_SHARED(Locks::mutator_lock_) {
76 reference_ = Encode(ptr);
77 }
78
79 ALWAYS_INLINE MirrorType* operator->() const REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier1cc62e42016-10-03 18:01:28 -070080 return Ptr();
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -070081 }
82
83 ALWAYS_INLINE bool IsNull() const {
84 return reference_ == 0;
85 }
86
Mathieu Chartier1cc62e42016-10-03 18:01:28 -070087 // Ptr makes sure that the object pointer is valid.
88 ALWAYS_INLINE MirrorType* Ptr() const REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartiera59d9b22016-09-26 18:13:17 -070089 AssertValid();
Mathieu Chartier1cc62e42016-10-03 18:01:28 -070090 return PtrUnchecked();
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -070091 }
92
Mathieu Chartiera59d9b22016-09-26 18:13:17 -070093 ALWAYS_INLINE bool IsValid() const REQUIRES_SHARED(Locks::mutator_lock_);
94
95 ALWAYS_INLINE void AssertValid() const REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -070096
97 ALWAYS_INLINE bool operator==(const ObjPtr& ptr) const REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier1cc62e42016-10-03 18:01:28 -070098 return Ptr() == ptr.Ptr();
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -070099 }
100
Mathieu Chartier3398c782016-09-30 10:27:43 -0700101 template <typename PointerType>
102 ALWAYS_INLINE bool operator==(const PointerType* ptr) const
103 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier1cc62e42016-10-03 18:01:28 -0700104 return Ptr() == ptr;
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -0700105 }
106
Mathieu Chartier3398c782016-09-30 10:27:43 -0700107 ALWAYS_INLINE bool operator==(std::nullptr_t) const {
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -0700108 return IsNull();
109 }
110
111 ALWAYS_INLINE bool operator!=(const ObjPtr& ptr) const REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier1cc62e42016-10-03 18:01:28 -0700112 return Ptr() != ptr.Ptr();
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -0700113 }
114
Mathieu Chartier3398c782016-09-30 10:27:43 -0700115 template <typename PointerType>
116 ALWAYS_INLINE bool operator!=(const PointerType* ptr) const
117 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier1cc62e42016-10-03 18:01:28 -0700118 return Ptr() != ptr;
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -0700119 }
120
Mathieu Chartier3398c782016-09-30 10:27:43 -0700121 ALWAYS_INLINE bool operator!=(std::nullptr_t) const {
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -0700122 return !IsNull();
123 }
124
Mathieu Chartier1cc62e42016-10-03 18:01:28 -0700125 // Ptr unchecked does not check that object pointer is valid. Do not use if you can avoid it.
126 ALWAYS_INLINE MirrorType* PtrUnchecked() const {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700127 if (kPoison) {
128 return reinterpret_cast<MirrorType*>(
129 static_cast<uintptr_t>(static_cast<uint32_t>(reference_ << kObjectAlignmentShift)));
130 } else {
131 return reinterpret_cast<MirrorType*>(reference_);
132 }
133 }
134
Mathieu Chartierc4f39252016-10-05 18:32:08 -0700135 // Static function to be friendly with null pointers.
136 template <typename SourceType>
137 static ObjPtr<MirrorType> DownCast(ObjPtr<SourceType> ptr) REQUIRES_SHARED(Locks::mutator_lock_) {
138 static_assert(std::is_base_of<SourceType, MirrorType>::value,
139 "Target type must be a subtype of source type");
140 return static_cast<MirrorType*>(ptr.Ptr());
141 }
142
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -0700143 private:
144 // Trim off high bits of thread local cookie.
145 ALWAYS_INLINE static uintptr_t TrimCookie(uintptr_t cookie) {
146 return cookie & kCookieMask;
147 }
148
149 ALWAYS_INLINE uintptr_t GetCookie() const {
150 return reference_ >> kCookieShift;
151 }
152
Mathieu Chartiera59d9b22016-09-26 18:13:17 -0700153 ALWAYS_INLINE static uintptr_t Encode(MirrorType* ptr) REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -0700154 // The encoded reference and cookie.
155 uintptr_t reference_;
156};
157
Mathieu Chartier3398c782016-09-30 10:27:43 -0700158template<class MirrorType, bool kPoison, typename PointerType>
159ALWAYS_INLINE bool operator==(const PointerType* a, const ObjPtr<MirrorType, kPoison>& b)
160 REQUIRES_SHARED(Locks::mutator_lock_) {
161 return b == a;
162}
163
164template<class MirrorType, bool kPoison>
165ALWAYS_INLINE bool operator==(std::nullptr_t, const ObjPtr<MirrorType, kPoison>& b) {
166 return b == nullptr;
167}
168
169template<typename MirrorType, bool kPoison, typename PointerType>
170ALWAYS_INLINE bool operator!=(const PointerType* a, const ObjPtr<MirrorType, kPoison>& b)
171 REQUIRES_SHARED(Locks::mutator_lock_) {
172 return b != a;
173}
174
175template<class MirrorType, bool kPoison>
176ALWAYS_INLINE bool operator!=(std::nullptr_t, const ObjPtr<MirrorType, kPoison>& b) {
177 return b != nullptr;
178}
179
Mathieu Chartiera59d9b22016-09-26 18:13:17 -0700180template<class MirrorType, bool kPoison = kIsDebugBuild>
181static inline ObjPtr<MirrorType, kPoison> MakeObjPtr(MirrorType* ptr) {
182 return ObjPtr<MirrorType, kPoison>(ptr);
183}
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -0700184
Mathieu Chartier3398c782016-09-30 10:27:43 -0700185template<class MirrorType, bool kPoison = kIsDebugBuild>
186static inline ObjPtr<MirrorType, kPoison> MakeObjPtr(ObjPtr<MirrorType, kPoison> ptr) {
187 return ObjPtr<MirrorType, kPoison>(ptr);
188}
189
Mathieu Chartier0795f232016-09-27 18:43:30 -0700190template<class MirrorType, bool kPoison>
Mathieu Chartier3398c782016-09-30 10:27:43 -0700191ALWAYS_INLINE std::ostream& operator<<(std::ostream& os, ObjPtr<MirrorType, kPoison> ptr);
Mathieu Chartier0795f232016-09-27 18:43:30 -0700192
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -0700193} // namespace art
194
Mathieu Chartiera59d9b22016-09-26 18:13:17 -0700195#endif // ART_RUNTIME_OBJ_PTR_H_