< prev index next >

src/hotspot/share/oops/oop.inline.hpp

Print this page

 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 
< prev index next >