17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #ifndef SHARE_OOPS_OOP_INLINE_HPP
26 #define SHARE_OOPS_OOP_INLINE_HPP
27
28 #include "oops/oop.hpp"
29
30 #include "memory/universe.hpp"
31 #include "memory/iterator.inline.hpp"
32 #include "oops/access.inline.hpp"
33 #include "oops/arrayKlass.hpp"
34 #include "oops/arrayOop.hpp"
35 #include "oops/compressedKlass.inline.hpp"
36 #include "oops/instanceKlass.hpp"
37 #include "oops/markWord.hpp"
38 #include "oops/oopsHierarchy.hpp"
39 #include "runtime/atomic.hpp"
40 #include "runtime/globals.hpp"
41 #include "utilities/align.hpp"
42 #include "utilities/debug.hpp"
43 #include "utilities/macros.hpp"
44 #include "utilities/globalDefinitions.hpp"
45
46 // Implementation of all inlined member functions defined in oop.hpp
47 // We need a separate file to avoid circular references
48
49 markWord oopDesc::mark() const {
50 return Atomic::load(&_mark);
51 }
52
53 markWord oopDesc::mark_acquire() const {
54 return Atomic::load_acquire(&_mark);
55 }
56
57 markWord* oopDesc::mark_addr() const {
58 return (markWord*) &_mark;
59 }
60
65 void oopDesc::set_mark(HeapWord* mem, markWord m) {
66 *(markWord*)(((char*)mem) + mark_offset_in_bytes()) = m;
67 }
68
69 void oopDesc::release_set_mark(HeapWord* mem, markWord m) {
70 Atomic::release_store((markWord*)(((char*)mem) + mark_offset_in_bytes()), m);
71 }
72
73 void oopDesc::release_set_mark(markWord m) {
74 Atomic::release_store(&_mark, m);
75 }
76
77 markWord oopDesc::cas_set_mark(markWord new_mark, markWord old_mark) {
78 return Atomic::cmpxchg(&_mark, old_mark, new_mark);
79 }
80
81 markWord oopDesc::cas_set_mark(markWord new_mark, markWord old_mark, atomic_memory_order order) {
82 return Atomic::cmpxchg(&_mark, old_mark, new_mark, order);
83 }
84
85 void oopDesc::init_mark() {
86 set_mark(markWord::prototype());
87 }
88
89 Klass* oopDesc::klass() const {
90 if (UseCompressedClassPointers) {
91 return CompressedKlassPointers::decode_not_null(_metadata._compressed_klass);
92 } else {
93 return _metadata._klass;
94 }
95 }
96
97 Klass* oopDesc::klass_or_null() const {
98 if (UseCompressedClassPointers) {
99 return CompressedKlassPointers::decode(_metadata._compressed_klass);
100 } else {
101 return _metadata._klass;
102 }
103 }
104
105 Klass* oopDesc::klass_or_null_acquire() const {
106 if (UseCompressedClassPointers) {
107 narrowKlass nklass = Atomic::load_acquire(&_metadata._compressed_klass);
108 return CompressedKlassPointers::decode(nklass);
109 } else {
110 return Atomic::load_acquire(&_metadata._klass);
111 }
112 }
113
114 Klass* oopDesc::klass_raw() const {
115 if (UseCompressedClassPointers) {
116 return CompressedKlassPointers::decode_raw(_metadata._compressed_klass);
117 } else {
118 return _metadata._klass;
119 }
120 }
121
122 void oopDesc::set_klass(Klass* k) {
123 assert(Universe::is_bootstrapping() || (k != nullptr && k->is_klass()), "incorrect Klass");
124 if (UseCompressedClassPointers) {
125 _metadata._compressed_klass = CompressedKlassPointers::encode_not_null(k);
126 } else {
127 _metadata._klass = k;
128 }
129 }
130
131 void oopDesc::release_set_klass(HeapWord* mem, Klass* k) {
132 assert(Universe::is_bootstrapping() || (k != nullptr && k->is_klass()), "incorrect Klass");
133 char* raw_mem = ((char*)mem + klass_offset_in_bytes());
134 if (UseCompressedClassPointers) {
135 Atomic::release_store((narrowKlass*)raw_mem,
136 CompressedKlassPointers::encode_not_null(k));
137 } else {
138 Atomic::release_store((Klass**)raw_mem, k);
139 }
140 }
141
142 void oopDesc::set_klass_gap(HeapWord* mem, int v) {
143 if (UseCompressedClassPointers) {
144 *(int*)(((char*)mem) + klass_gap_offset_in_bytes()) = v;
145 }
146 }
147
148 bool oopDesc::is_a(Klass* k) const {
149 return klass()->is_subtype_of(k);
150 }
151
152 size_t oopDesc::size() {
153 return size_given_klass(klass());
154 }
155
156 size_t oopDesc::size_given_klass(Klass* klass) {
157 int lh = klass->layout_helper();
158 size_t s;
159
160 // lh is now a value computed at class initialization that may hint
161 // at the size. For instances, this is positive and equal to the
162 // size. For arrays, this is negative and provides log2 of the
254
255 bool oopDesc::is_unlocked() const {
256 return mark().is_unlocked();
257 }
258
259 // Used only for markSweep, scavenging
260 bool oopDesc::is_gc_marked() const {
261 return mark().is_marked();
262 }
263
264 // Used by scavengers
265 bool oopDesc::is_forwarded() const {
266 // The extra heap check is needed since the obj might be locked, in which case the
267 // mark would point to a stack location and have the sentinel bit cleared
268 return mark().is_marked();
269 }
270
271 // Used by scavengers
272 void oopDesc::forward_to(oop p) {
273 markWord m = markWord::encode_pointer_as_mark(p);
274 assert(m.decode_pointer() == p, "encoding must be reversible");
275 set_mark(m);
276 }
277
278 oop oopDesc::forward_to_atomic(oop p, markWord compare, atomic_memory_order order) {
279 markWord m = markWord::encode_pointer_as_mark(p);
280 assert(m.decode_pointer() == p, "encoding must be reversible");
281 markWord old_mark = cas_set_mark(m, compare, order);
282 if (old_mark == compare) {
283 return nullptr;
284 } else {
285 return cast_to_oop(old_mark.decode_pointer());
286 }
287 }
288
289 // Note that the forwardee is not the same thing as the displaced_mark.
290 // The forwardee is used when copying during scavenge and mark-sweep.
291 // It does need to clear the low two locking- and GC-related bits.
292 oop oopDesc::forwardee() const {
293 assert(is_forwarded(), "only decode when actually forwarded");
294 return cast_to_oop(mark().decode_pointer());
295 }
296
297 // The following method needs to be MT safe.
298 uint oopDesc::age() const {
299 markWord m = mark();
300 assert(!m.is_marked(), "Attempt to read age from forwarded mark");
301 if (m.has_displaced_mark_helper()) {
302 return m.displaced_mark_helper().age();
303 } else {
304 return m.age();
305 }
306 }
307
308 void oopDesc::incr_age() {
309 markWord m = mark();
310 assert(!m.is_marked(), "Attempt to increment age of forwarded mark");
311 if (m.has_displaced_mark_helper()) {
312 m.set_displaced_mark_helper(m.displaced_mark_helper().incr_age());
313 } else {
314 set_mark(m.incr_age());
331 size_t size = size_given_klass(k);
332 OopIteratorClosureDispatch::oop_oop_iterate(cl, this, k);
333 return size;
334 }
335
336 template <typename OopClosureType>
337 size_t oopDesc::oop_iterate_size(OopClosureType* cl, MemRegion mr) {
338 Klass* k = klass();
339 size_t size = size_given_klass(k);
340 OopIteratorClosureDispatch::oop_oop_iterate(cl, this, k, mr);
341 return size;
342 }
343
344 template <typename OopClosureType>
345 void oopDesc::oop_iterate_backwards(OopClosureType* cl) {
346 oop_iterate_backwards(cl, klass());
347 }
348
349 template <typename OopClosureType>
350 void oopDesc::oop_iterate_backwards(OopClosureType* cl, Klass* k) {
351 assert(k == klass(), "wrong klass");
352 OopIteratorClosureDispatch::oop_oop_iterate_backwards(cl, this, k);
353 }
354
355 bool oopDesc::is_instanceof_or_null(oop obj, Klass* klass) {
356 return obj == nullptr || obj->klass()->is_subtype_of(klass);
357 }
358
359 intptr_t oopDesc::identity_hash() {
360 // Fast case; if the object is unlocked and the hash value is set, no locking is needed
361 // Note: The mark must be read into local variable to avoid concurrent updates.
362 markWord mrk = mark();
363 if (mrk.is_unlocked() && !mrk.has_no_hash()) {
364 return mrk.hash();
365 } else if (mrk.is_marked()) {
366 return mrk.hash();
367 } else {
368 return slow_identity_hash();
369 }
370 }
371
|
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #ifndef SHARE_OOPS_OOP_INLINE_HPP
26 #define SHARE_OOPS_OOP_INLINE_HPP
27
28 #include "oops/oop.hpp"
29
30 #include "memory/universe.hpp"
31 #include "memory/iterator.inline.hpp"
32 #include "oops/access.inline.hpp"
33 #include "oops/arrayKlass.hpp"
34 #include "oops/arrayOop.hpp"
35 #include "oops/compressedKlass.inline.hpp"
36 #include "oops/instanceKlass.hpp"
37 #include "oops/markWord.inline.hpp"
38 #include "oops/oopsHierarchy.hpp"
39 #include "runtime/atomic.hpp"
40 #include "runtime/globals.hpp"
41 #include "runtime/objectMonitor.inline.hpp"
42 #include "runtime/safepoint.hpp"
43 #include "runtime/synchronizer.hpp"
44 #include "utilities/align.hpp"
45 #include "utilities/debug.hpp"
46 #include "utilities/macros.hpp"
47 #include "utilities/globalDefinitions.hpp"
48
49 // Implementation of all inlined member functions defined in oop.hpp
50 // We need a separate file to avoid circular references
51
52 markWord oopDesc::mark() const {
53 return Atomic::load(&_mark);
54 }
55
56 markWord oopDesc::mark_acquire() const {
57 return Atomic::load_acquire(&_mark);
58 }
59
60 markWord* oopDesc::mark_addr() const {
61 return (markWord*) &_mark;
62 }
63
68 void oopDesc::set_mark(HeapWord* mem, markWord m) {
69 *(markWord*)(((char*)mem) + mark_offset_in_bytes()) = m;
70 }
71
72 void oopDesc::release_set_mark(HeapWord* mem, markWord m) {
73 Atomic::release_store((markWord*)(((char*)mem) + mark_offset_in_bytes()), m);
74 }
75
76 void oopDesc::release_set_mark(markWord m) {
77 Atomic::release_store(&_mark, m);
78 }
79
80 markWord oopDesc::cas_set_mark(markWord new_mark, markWord old_mark) {
81 return Atomic::cmpxchg(&_mark, old_mark, new_mark);
82 }
83
84 markWord oopDesc::cas_set_mark(markWord new_mark, markWord old_mark, atomic_memory_order order) {
85 return Atomic::cmpxchg(&_mark, old_mark, new_mark, order);
86 }
87
88 markWord oopDesc::resolve_mark() const {
89 assert(LockingMode != LM_LEGACY, "Not safe with legacy stack-locking");
90 markWord hdr = mark();
91 if (hdr.has_monitor()) {
92 ObjectMonitor* monitor = hdr.monitor();
93 return monitor->header();
94 }
95 return hdr;
96 }
97
98 void oopDesc::init_mark() {
99 #ifdef _LP64
100 if (UseCompactObjectHeaders) {
101 markWord header = resolve_mark();
102 assert(UseCompressedClassPointers, "expect compressed klass pointers");
103 set_mark(markWord((header.value() & markWord::klass_mask_in_place) | markWord::prototype().value()));
104 } else
105 #endif
106 set_mark(markWord::prototype());
107 }
108
109 Klass* oopDesc::klass() const {
110 #ifdef _LP64
111 if (UseCompactObjectHeaders) {
112 assert(UseCompressedClassPointers, "only with compressed class pointers");
113 markWord header = resolve_mark();
114 return header.klass();
115 } else if (UseCompressedClassPointers) {
116 return CompressedKlassPointers::decode_not_null(_metadata._compressed_klass);
117 } else
118 #endif
119 return _metadata._klass;
120 }
121
122 Klass* oopDesc::klass_or_null() const {
123 #ifdef _LP64
124 if (UseCompactObjectHeaders) {
125 assert(UseCompressedClassPointers, "only with compressed class pointers");
126 markWord header = resolve_mark();
127 return header.klass_or_null();
128 } else if (UseCompressedClassPointers) {
129 return CompressedKlassPointers::decode(_metadata._compressed_klass);
130 } else
131 #endif
132 return _metadata._klass;
133 }
134
135 Klass* oopDesc::klass_or_null_acquire() const {
136 #ifdef _LP64
137 if (UseCompactObjectHeaders) {
138 assert(UseCompressedClassPointers, "only with compressed class pointers");
139 markWord header = mark_acquire();
140 if (header.has_monitor()) {
141 header = header.monitor()->header();
142 }
143 return header.klass_or_null();
144 } else if (UseCompressedClassPointers) {
145 narrowKlass nklass = Atomic::load_acquire(&_metadata._compressed_klass);
146 return CompressedKlassPointers::decode(nklass);
147 } else
148 #endif
149 return Atomic::load_acquire(&_metadata._klass);
150 }
151
152 Klass* oopDesc::klass_raw() const {
153 return klass();
154 }
155
156 void oopDesc::set_klass(Klass* k) {
157 assert(Universe::is_bootstrapping() || (k != NULL && k->is_klass()), "incorrect Klass");
158 assert(!UseCompactObjectHeaders, "don't set Klass* with compact headers");
159 if (UseCompressedClassPointers) {
160 _metadata._compressed_klass = CompressedKlassPointers::encode_not_null(k);
161 } else {
162 _metadata._klass = k;
163 }
164 }
165
166 void oopDesc::release_set_klass(HeapWord* mem, Klass* k) {
167 assert(Universe::is_bootstrapping() || (k != NULL && k->is_klass()), "incorrect Klass");
168 assert(!UseCompactObjectHeaders, "don't set Klass* with compact headers");
169 char* raw_mem = ((char*)mem + klass_offset_in_bytes());
170 if (UseCompressedClassPointers) {
171 Atomic::release_store((narrowKlass*)raw_mem,
172 CompressedKlassPointers::encode_not_null(k));
173 } else {
174 Atomic::release_store((Klass**)raw_mem, k);
175 }
176 }
177
178 void oopDesc::set_klass_gap(HeapWord* mem, int v) {
179 assert(!UseCompactObjectHeaders, "don't set Klass* gap with compact headers");
180 if (UseCompressedClassPointers) {
181 *(int*)(((char*)mem) + klass_gap_offset_in_bytes()) = v;
182 }
183 }
184
185 bool oopDesc::is_a(Klass* k) const {
186 return klass()->is_subtype_of(k);
187 }
188
189 size_t oopDesc::size() {
190 return size_given_klass(klass());
191 }
192
193 size_t oopDesc::size_given_klass(Klass* klass) {
194 int lh = klass->layout_helper();
195 size_t s;
196
197 // lh is now a value computed at class initialization that may hint
198 // at the size. For instances, this is positive and equal to the
199 // size. For arrays, this is negative and provides log2 of the
291
292 bool oopDesc::is_unlocked() const {
293 return mark().is_unlocked();
294 }
295
296 // Used only for markSweep, scavenging
297 bool oopDesc::is_gc_marked() const {
298 return mark().is_marked();
299 }
300
301 // Used by scavengers
302 bool oopDesc::is_forwarded() const {
303 // The extra heap check is needed since the obj might be locked, in which case the
304 // mark would point to a stack location and have the sentinel bit cleared
305 return mark().is_marked();
306 }
307
308 // Used by scavengers
309 void oopDesc::forward_to(oop p) {
310 markWord m = markWord::encode_pointer_as_mark(p);
311 assert(forwardee(m) == p, "encoding must be reversable");
312 set_mark(m);
313 }
314
315 void oopDesc::forward_to_self() {
316 #ifdef _LP64
317 markWord m = mark();
318 // If mark is displaced, we need to preserve the Klass* from real header.
319 assert(SafepointSynchronize::is_at_safepoint(), "we can only safely fetch the displaced header at safepoint");
320 if (m.has_displaced_mark_helper()) {
321 m = m.displaced_mark_helper();
322 }
323 m = m.set_self_forwarded();
324 assert(forwardee(m) == cast_to_oop(this), "encoding must be reversable");
325 set_mark(m);
326 #else
327 forward_to(oop(this));
328 #endif
329 }
330
331 oop oopDesc::forward_to_atomic(oop p, markWord compare, atomic_memory_order order) {
332 markWord m = markWord::encode_pointer_as_mark(p);
333 assert(forwardee(m) == p, "encoding must be reversable");
334 markWord old_mark = cas_set_mark(m, compare, order);
335 if (old_mark == compare) {
336 return nullptr;
337 } else {
338 return forwardee(old_mark);
339 }
340 }
341
342 oop oopDesc::forward_to_self_atomic(markWord compare, atomic_memory_order order) {
343 #ifdef _LP64
344 markWord m = compare;
345 // If mark is displaced, we need to preserve the Klass* from real header.
346 assert(SafepointSynchronize::is_at_safepoint(), "we can only safely fetch the displaced header at safepoint");
347 if (m.has_displaced_mark_helper()) {
348 m = m.displaced_mark_helper();
349 }
350 m = m.set_self_forwarded();
351 assert(forwardee(m) == cast_to_oop(this), "encoding must be reversable");
352 markWord old_mark = cas_set_mark(m, compare, order);
353 if (old_mark == compare) {
354 return NULL;
355 } else {
356 assert(old_mark.is_marked(), "must be marked here");
357 return forwardee(old_mark);
358 }
359 #else
360 return forward_to_atomic(oop(this), compare, order);
361 #endif
362 }
363
364 // Note that the forwardee is not the same thing as the displaced_mark.
365 // The forwardee is used when copying during scavenge and mark-sweep.
366 // It does need to clear the low two locking- and GC-related bits.
367 oop oopDesc::forwardee() const {
368 return forwardee(mark());
369 }
370
371 oop oopDesc::forwardee(markWord header) const {
372 assert(header.is_marked(), "must be forwarded");
373 #ifdef _LP64
374 if (header.self_forwarded()) {
375 return cast_to_oop(this);
376 } else
377 #endif
378 {
379 assert(header.is_marked(), "only decode when actually forwarded");
380 return cast_to_oop(header.decode_pointer());
381 }
382 }
383
384 // The following method needs to be MT safe.
385 uint oopDesc::age() const {
386 markWord m = mark();
387 assert(!m.is_marked(), "Attempt to read age from forwarded mark");
388 if (m.has_displaced_mark_helper()) {
389 return m.displaced_mark_helper().age();
390 } else {
391 return m.age();
392 }
393 }
394
395 void oopDesc::incr_age() {
396 markWord m = mark();
397 assert(!m.is_marked(), "Attempt to increment age of forwarded mark");
398 if (m.has_displaced_mark_helper()) {
399 m.set_displaced_mark_helper(m.displaced_mark_helper().incr_age());
400 } else {
401 set_mark(m.incr_age());
418 size_t size = size_given_klass(k);
419 OopIteratorClosureDispatch::oop_oop_iterate(cl, this, k);
420 return size;
421 }
422
423 template <typename OopClosureType>
424 size_t oopDesc::oop_iterate_size(OopClosureType* cl, MemRegion mr) {
425 Klass* k = klass();
426 size_t size = size_given_klass(k);
427 OopIteratorClosureDispatch::oop_oop_iterate(cl, this, k, mr);
428 return size;
429 }
430
431 template <typename OopClosureType>
432 void oopDesc::oop_iterate_backwards(OopClosureType* cl) {
433 oop_iterate_backwards(cl, klass());
434 }
435
436 template <typename OopClosureType>
437 void oopDesc::oop_iterate_backwards(OopClosureType* cl, Klass* k) {
438 OopIteratorClosureDispatch::oop_oop_iterate_backwards(cl, this, k);
439 }
440
441 bool oopDesc::is_instanceof_or_null(oop obj, Klass* klass) {
442 return obj == nullptr || obj->klass()->is_subtype_of(klass);
443 }
444
445 intptr_t oopDesc::identity_hash() {
446 // Fast case; if the object is unlocked and the hash value is set, no locking is needed
447 // Note: The mark must be read into local variable to avoid concurrent updates.
448 markWord mrk = mark();
449 if (mrk.is_unlocked() && !mrk.has_no_hash()) {
450 return mrk.hash();
451 } else if (mrk.is_marked()) {
452 return mrk.hash();
453 } else {
454 return slow_identity_hash();
455 }
456 }
457
|