blob: f01bcbd83ae4b895782cd87d6fe27dc488febc58 [file] [log] [blame]
Ian Rogersef7d42f2014-01-06 12:55:46 -08001/*
2 * Copyright (C) 2014 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_MIRROR_OBJECT_REFERENCE_H_
18#define ART_RUNTIME_MIRROR_OBJECT_REFERENCE_H_
19
David Sehrc431b9d2018-03-02 12:01:51 -080020#include "base/atomic.h"
Andreas Gampe7fbc4a52018-11-28 08:26:47 -080021#include "base/locks.h" // For Locks::mutator_lock_.
Andreas Gampe09659c22017-09-18 18:23:32 -070022#include "heap_poisoning.h"
Mathieu Chartiera058fdf2016-10-06 15:13:58 -070023#include "obj_ptr.h"
Andreas Gampe5a0430d2019-01-04 14:33:57 -080024#include "runtime_globals.h"
Ian Rogersef7d42f2014-01-06 12:55:46 -080025
26namespace art {
27namespace mirror {
28
29class Object;
30
31// Classes shared with the managed side of the world need to be packed so that they don't have
32// extra platform specific padding.
33#define MANAGED PACKED(4)
34
Hans Boehmcc55e1d2017-07-27 15:28:07 -070035template<bool kPoisonReferences, class MirrorType>
36class PtrCompression {
37 public:
38 // Compress reference to its bit representation.
39 static uint32_t Compress(MirrorType* mirror_ptr) {
40 uintptr_t as_bits = reinterpret_cast<uintptr_t>(mirror_ptr);
41 return static_cast<uint32_t>(kPoisonReferences ? -as_bits : as_bits);
42 }
43
44 // Uncompress an encoded reference from its bit representation.
45 static MirrorType* Decompress(uint32_t ref) {
46 uintptr_t as_bits = kPoisonReferences ? -ref : ref;
47 return reinterpret_cast<MirrorType*>(as_bits);
48 }
49
50 // Convert an ObjPtr to a compressed reference.
Vladimir Markof57f2ed2019-03-25 15:55:42 +000051 static uint32_t Compress(ObjPtr<MirrorType> ptr) REQUIRES_SHARED(Locks::mutator_lock_);
Hans Boehmcc55e1d2017-07-27 15:28:07 -070052};
53
Ian Rogersef7d42f2014-01-06 12:55:46 -080054// Value type representing a reference to a mirror::Object of type MirrorType.
55template<bool kPoisonReferences, class MirrorType>
56class MANAGED ObjectReference {
Hans Boehmcc55e1d2017-07-27 15:28:07 -070057 private:
58 using Compression = PtrCompression<kPoisonReferences, MirrorType>;
59
Ian Rogersef7d42f2014-01-06 12:55:46 -080060 public:
Chris Wailes0c61be42018-09-26 17:27:34 -070061 /*
62 * Returns a pointer to the mirror of the managed object this reference is for.
63 *
64 * This does NOT return the current object (which isn't derived from, and
65 * therefor cannot be a mirror::Object) as a mirror pointer. Instead, this
66 * returns a pointer to the mirror of the managed object this refers to.
67 *
68 * TODO (chriswailes): Rename to GetPtr().
69 */
Hans Boehmcc55e1d2017-07-27 15:28:07 -070070 MirrorType* AsMirrorPtr() const {
71 return Compression::Decompress(reference_);
Ian Rogersef7d42f2014-01-06 12:55:46 -080072 }
73
Hans Boehmcc55e1d2017-07-27 15:28:07 -070074 void Assign(MirrorType* other) {
75 reference_ = Compression::Compress(other);
Ian Rogersef7d42f2014-01-06 12:55:46 -080076 }
77
Hans Boehmcc55e1d2017-07-27 15:28:07 -070078 void Assign(ObjPtr<MirrorType> ptr) REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartier1a5337f2016-10-13 13:48:23 -070079
Ian Rogersef7d42f2014-01-06 12:55:46 -080080 void Clear() {
81 reference_ = 0;
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -070082 DCHECK(IsNull());
83 }
84
85 bool IsNull() const {
86 return reference_ == 0;
Ian Rogersef7d42f2014-01-06 12:55:46 -080087 }
88
89 uint32_t AsVRegValue() const {
90 return reference_;
91 }
92
Hans Boehmcc55e1d2017-07-27 15:28:07 -070093 static ObjectReference<kPoisonReferences, MirrorType> FromMirrorPtr(MirrorType* mirror_ptr)
94 REQUIRES_SHARED(Locks::mutator_lock_) {
95 return ObjectReference<kPoisonReferences, MirrorType>(mirror_ptr);
96 }
97
Ian Rogersef7d42f2014-01-06 12:55:46 -080098 protected:
Hans Boehmcc55e1d2017-07-27 15:28:07 -070099 explicit ObjectReference(MirrorType* mirror_ptr) REQUIRES_SHARED(Locks::mutator_lock_)
100 : reference_(Compression::Compress(mirror_ptr)) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800101 }
102
Ian Rogersef7d42f2014-01-06 12:55:46 -0800103 // The encoded reference to a mirror::Object.
104 uint32_t reference_;
105};
106
107// References between objects within the managed heap.
Hans Boehmcc55e1d2017-07-27 15:28:07 -0700108// Similar API to ObjectReference, but not a value type. Supports atomic access.
Ian Rogersef7d42f2014-01-06 12:55:46 -0800109template<class MirrorType>
Hans Boehmcc55e1d2017-07-27 15:28:07 -0700110class MANAGED HeapReference {
111 private:
112 using Compression = PtrCompression<kPoisonHeapReferences, MirrorType>;
113
Ian Rogersef7d42f2014-01-06 12:55:46 -0800114 public:
Mathieu Chartierad8ebb32017-08-09 20:13:18 -0700115 HeapReference() REQUIRES_SHARED(Locks::mutator_lock_) : HeapReference(nullptr) {}
116
Hans Boehmcc55e1d2017-07-27 15:28:07 -0700117 template <bool kIsVolatile = false>
118 MirrorType* AsMirrorPtr() const REQUIRES_SHARED(Locks::mutator_lock_) {
119 return Compression::Decompress(
Orion Hodson88591fe2018-03-06 13:35:43 +0000120 kIsVolatile ? reference_.load(std::memory_order_seq_cst) : reference_.LoadJavaData());
Hans Boehmcc55e1d2017-07-27 15:28:07 -0700121 }
122
123 template <bool kIsVolatile = false>
124 void Assign(MirrorType* other) REQUIRES_SHARED(Locks::mutator_lock_) {
125 if (kIsVolatile) {
Orion Hodson88591fe2018-03-06 13:35:43 +0000126 reference_.store(Compression::Compress(other), std::memory_order_seq_cst);
Hans Boehmcc55e1d2017-07-27 15:28:07 -0700127 } else {
128 reference_.StoreJavaData(Compression::Compress(other));
129 }
130 }
131
132 template <bool kIsVolatile = false>
133 void Assign(ObjPtr<MirrorType> ptr) REQUIRES_SHARED(Locks::mutator_lock_);
134
135 void Clear() {
136 reference_.StoreJavaData(0);
137 DCHECK(IsNull());
138 }
139
140 bool IsNull() const {
141 return reference_.LoadJavaData() == 0;
142 }
143
Ian Rogersef7d42f2014-01-06 12:55:46 -0800144 static HeapReference<MirrorType> FromMirrorPtr(MirrorType* mirror_ptr)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700145 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800146 return HeapReference<MirrorType>(mirror_ptr);
147 }
Mathieu Chartiera058fdf2016-10-06 15:13:58 -0700148
Hiroshi Yamauchi65f5f242016-12-19 11:44:47 -0800149 bool CasWeakRelaxed(MirrorType* old_ptr, MirrorType* new_ptr)
150 REQUIRES_SHARED(Locks::mutator_lock_);
151
Ian Rogersef7d42f2014-01-06 12:55:46 -0800152 private:
Chih-Hung Hsieha5931182016-09-01 15:08:13 -0700153 explicit HeapReference(MirrorType* mirror_ptr) REQUIRES_SHARED(Locks::mutator_lock_)
Mathieu Chartierad8ebb32017-08-09 20:13:18 -0700154 : reference_(Compression::Compress(mirror_ptr)) {}
Hans Boehmcc55e1d2017-07-27 15:28:07 -0700155
156 // The encoded reference to a mirror::Object. Atomically updateable.
157 Atomic<uint32_t> reference_;
Ian Rogersef7d42f2014-01-06 12:55:46 -0800158};
159
Mathieu Chartiera058fdf2016-10-06 15:13:58 -0700160static_assert(sizeof(mirror::HeapReference<mirror::Object>) == kHeapReferenceSize,
161 "heap reference size does not match");
162
Mathieu Chartierd3ed9a32015-04-10 14:23:35 -0700163// Standard compressed reference used in the runtime. Used for StackReference and GC roots.
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700164template<class MirrorType>
165class MANAGED CompressedReference : public mirror::ObjectReference<false, MirrorType> {
166 public:
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700167 CompressedReference<MirrorType>() REQUIRES_SHARED(Locks::mutator_lock_)
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700168 : mirror::ObjectReference<false, MirrorType>(nullptr) {}
169
170 static CompressedReference<MirrorType> FromMirrorPtr(MirrorType* p)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700171 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700172 return CompressedReference<MirrorType>(p);
173 }
174
175 private:
Chih-Hung Hsieha5931182016-09-01 15:08:13 -0700176 explicit CompressedReference(MirrorType* p) REQUIRES_SHARED(Locks::mutator_lock_)
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700177 : mirror::ObjectReference<false, MirrorType>(p) {}
178};
179
Ian Rogersef7d42f2014-01-06 12:55:46 -0800180} // namespace mirror
181} // namespace art
182
183#endif // ART_RUNTIME_MIRROR_OBJECT_REFERENCE_H_