blob: d4076beb3c1a46740392523f3e27a8049a7d3be2 [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
20#include "base/mutex.h" // For Locks::mutator_lock_.
21#include "globals.h"
22#include "mirror/object_reference.h"
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -070023
24namespace art {
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -070025
26// Value type representing a pointer to a mirror::Object of type MirrorType
27// Pass kPoison as a template boolean for testing in non-debug builds.
Mathieu Chartiera59d9b22016-09-26 18:13:17 -070028// Since the cookie is thread based, it is not safe to share an ObjPtr between threads.
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -070029template<class MirrorType, bool kPoison = kIsDebugBuild>
30class ObjPtr {
31 static constexpr size_t kCookieShift =
32 sizeof(mirror::HeapReference<mirror::Object>) * kBitsPerByte - kObjectAlignmentShift;
33 static constexpr size_t kCookieBits = sizeof(uintptr_t) * kBitsPerByte - kCookieShift;
34 static constexpr uintptr_t kCookieMask = (static_cast<uintptr_t>(1u) << kCookieBits) - 1;
35
36 static_assert(kCookieBits >= kObjectAlignmentShift,
37 "must have a least kObjectAlignmentShift bits");
38
39 public:
40 ALWAYS_INLINE ObjPtr() REQUIRES_SHARED(Locks::mutator_lock_) : reference_(0u) {}
41
Mathieu Chartiera59d9b22016-09-26 18:13:17 -070042 ALWAYS_INLINE ObjPtr(std::nullptr_t) REQUIRES_SHARED(Locks::mutator_lock_) : reference_(0u) {}
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -070043
Mathieu Chartiera59d9b22016-09-26 18:13:17 -070044 template <typename Type>
45 ALWAYS_INLINE ObjPtr(Type* ptr) REQUIRES_SHARED(Locks::mutator_lock_)
46 : reference_(Encode(static_cast<MirrorType*>(ptr))) {}
47
48 ALWAYS_INLINE ObjPtr(const ObjPtr& other) REQUIRES_SHARED(Locks::mutator_lock_) = default;
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -070049
50 ALWAYS_INLINE ObjPtr& operator=(const ObjPtr& other) {
51 reference_ = other.reference_;
52 return *this;
53 }
54
55 ALWAYS_INLINE ObjPtr& operator=(MirrorType* ptr) REQUIRES_SHARED(Locks::mutator_lock_) {
56 Assign(ptr);
57 return *this;
58 }
59
60 ALWAYS_INLINE void Assign(MirrorType* ptr) REQUIRES_SHARED(Locks::mutator_lock_) {
61 reference_ = Encode(ptr);
62 }
63
64 ALWAYS_INLINE MirrorType* operator->() const REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -070065 return Decode();
66 }
67
Mathieu Chartiera59d9b22016-09-26 18:13:17 -070068
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -070069 ALWAYS_INLINE bool IsNull() const {
70 return reference_ == 0;
71 }
72
Mathieu Chartiera59d9b22016-09-26 18:13:17 -070073 // Decode makes sure that the object pointer is valid.
74 ALWAYS_INLINE MirrorType* Decode() const REQUIRES_SHARED(Locks::mutator_lock_) {
75 AssertValid();
76 return DecodeUnchecked();
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -070077 }
78
Mathieu Chartiera59d9b22016-09-26 18:13:17 -070079 ALWAYS_INLINE bool IsValid() const REQUIRES_SHARED(Locks::mutator_lock_);
80
81 ALWAYS_INLINE void AssertValid() const REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -070082
83 ALWAYS_INLINE bool operator==(const ObjPtr& ptr) const REQUIRES_SHARED(Locks::mutator_lock_) {
84 return Decode() == ptr.Decode();
85 }
86
87 ALWAYS_INLINE bool operator==(const MirrorType* ptr) const REQUIRES_SHARED(Locks::mutator_lock_) {
88 return Decode() == ptr;
89 }
90
91 ALWAYS_INLINE bool operator==(std::nullptr_t) const REQUIRES_SHARED(Locks::mutator_lock_) {
92 return IsNull();
93 }
94
95 ALWAYS_INLINE bool operator!=(const ObjPtr& ptr) const REQUIRES_SHARED(Locks::mutator_lock_) {
96 return Decode() != ptr.Decode();
97 }
98
99 ALWAYS_INLINE bool operator!=(const MirrorType* ptr) const REQUIRES_SHARED(Locks::mutator_lock_) {
100 return Decode() != ptr;
101 }
102
103 ALWAYS_INLINE bool operator!=(std::nullptr_t) const REQUIRES_SHARED(Locks::mutator_lock_) {
104 return !IsNull();
105 }
106
107 private:
108 // Trim off high bits of thread local cookie.
109 ALWAYS_INLINE static uintptr_t TrimCookie(uintptr_t cookie) {
110 return cookie & kCookieMask;
111 }
112
113 ALWAYS_INLINE uintptr_t GetCookie() const {
114 return reference_ >> kCookieShift;
115 }
116
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -0700117 // Decode makes sure that the object pointer is valid.
Mathieu Chartiera59d9b22016-09-26 18:13:17 -0700118 ALWAYS_INLINE MirrorType* DecodeUnchecked() const REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -0700119 if (kPoison) {
120 return reinterpret_cast<MirrorType*>(
121 static_cast<uintptr_t>(static_cast<uint32_t>(reference_ << kObjectAlignmentShift)));
122 } else {
123 return reinterpret_cast<MirrorType*>(reference_);
124 }
125 }
126
Mathieu Chartiera59d9b22016-09-26 18:13:17 -0700127 ALWAYS_INLINE static uintptr_t Encode(MirrorType* ptr) REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -0700128 // The encoded reference and cookie.
129 uintptr_t reference_;
130};
131
Mathieu Chartiera59d9b22016-09-26 18:13:17 -0700132template<class MirrorType, bool kPoison = kIsDebugBuild>
133static inline ObjPtr<MirrorType, kPoison> MakeObjPtr(MirrorType* ptr) {
134 return ObjPtr<MirrorType, kPoison>(ptr);
135}
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -0700136
Mathieu Chartier3f7f03c2016-09-26 11:39:52 -0700137} // namespace art
138
Mathieu Chartiera59d9b22016-09-26 18:13:17 -0700139#endif // ART_RUNTIME_OBJ_PTR_H_