24 |
24 |
25 #ifndef SHARE_VM_OOPS_OOP_INLINE_HPP |
25 #ifndef SHARE_VM_OOPS_OOP_INLINE_HPP |
26 #define SHARE_VM_OOPS_OOP_INLINE_HPP |
26 #define SHARE_VM_OOPS_OOP_INLINE_HPP |
27 |
27 |
28 #include "gc/shared/ageTable.hpp" |
28 #include "gc/shared/ageTable.hpp" |
29 #include "gc/shared/barrierSet.inline.hpp" |
|
30 #include "gc/shared/cardTableModRefBS.hpp" |
|
31 #include "gc/shared/collectedHeap.inline.hpp" |
29 #include "gc/shared/collectedHeap.inline.hpp" |
32 #include "gc/shared/genCollectedHeap.hpp" |
30 #include "gc/shared/genCollectedHeap.hpp" |
33 #include "gc/shared/generation.hpp" |
31 #include "gc/shared/generation.hpp" |
|
32 #include "oops/access.inline.hpp" |
34 #include "oops/arrayKlass.hpp" |
33 #include "oops/arrayKlass.hpp" |
35 #include "oops/arrayOop.hpp" |
34 #include "oops/arrayOop.hpp" |
36 #include "oops/klass.inline.hpp" |
35 #include "oops/klass.inline.hpp" |
37 #include "oops/markOop.inline.hpp" |
36 #include "oops/markOop.inline.hpp" |
38 #include "oops/oop.hpp" |
37 #include "oops/oop.hpp" |
39 #include "runtime/atomic.hpp" |
38 #include "runtime/atomic.hpp" |
40 #include "runtime/orderAccess.inline.hpp" |
39 #include "runtime/orderAccess.inline.hpp" |
41 #include "runtime/os.hpp" |
40 #include "runtime/os.hpp" |
42 #include "utilities/align.hpp" |
41 #include "utilities/align.hpp" |
43 #include "utilities/macros.hpp" |
42 #include "utilities/macros.hpp" |
44 |
|
45 inline void update_barrier_set(void* p, oop v, bool release = false) { |
|
46 assert(oopDesc::bs() != NULL, "Uninitialized bs in oop!"); |
|
47 oopDesc::bs()->write_ref_field(p, v, release); |
|
48 } |
|
49 |
|
50 template <class T> inline void update_barrier_set_pre(T* p, oop v) { |
|
51 oopDesc::bs()->write_ref_field_pre(p, v); |
|
52 } |
|
53 |
|
54 template <class T> void oop_store(T* p, oop v) { |
|
55 if (always_do_update_barrier) { |
|
56 oop_store((volatile T*)p, v); |
|
57 } else { |
|
58 update_barrier_set_pre(p, v); |
|
59 oopDesc::encode_store_heap_oop(p, v); |
|
60 // always_do_update_barrier == false => |
|
61 // Either we are at a safepoint (in GC) or CMS is not used. In both |
|
62 // cases it's unnecessary to mark the card as dirty with release sematics. |
|
63 update_barrier_set((void*)p, v, false /* release */); // cast away type |
|
64 } |
|
65 } |
|
66 |
|
67 template <class T> void oop_store(volatile T* p, oop v) { |
|
68 update_barrier_set_pre((T*)p, v); // cast away volatile |
|
69 // Used by release_obj_field_put, so use release_store. |
|
70 oopDesc::release_encode_store_heap_oop(p, v); |
|
71 // When using CMS we must mark the card corresponding to p as dirty |
|
72 // with release sematics to prevent that CMS sees the dirty card but |
|
73 // not the new value v at p due to reordering of the two |
|
74 // stores. Note that CMS has a concurrent precleaning phase, where |
|
75 // it reads the card table while the Java threads are running. |
|
76 update_barrier_set((void*)p, v, true /* release */); // cast away type |
|
77 } |
|
78 |
|
79 // Should replace *addr = oop assignments where addr type depends on UseCompressedOops |
|
80 // (without having to remember the function name this calls). |
|
81 inline void oop_store_raw(HeapWord* addr, oop value) { |
|
82 if (UseCompressedOops) { |
|
83 oopDesc::encode_store_heap_oop((narrowOop*)addr, value); |
|
84 } else { |
|
85 oopDesc::encode_store_heap_oop((oop*)addr, value); |
|
86 } |
|
87 } |
|
88 |
43 |
89 // Implementation of all inlined member functions defined in oop.hpp |
44 // Implementation of all inlined member functions defined in oop.hpp |
90 // We need a separate file to avoid circular references |
45 // We need a separate file to avoid circular references |
91 |
46 |
92 void oopDesc::release_set_mark(markOop m) { |
47 void oopDesc::release_set_mark(markOop m) { |
357 // Encode and store a heap oop allowing for null. |
324 // Encode and store a heap oop allowing for null. |
358 void oopDesc::encode_store_heap_oop(narrowOop* p, oop v) { |
325 void oopDesc::encode_store_heap_oop(narrowOop* p, oop v) { |
359 *p = encode_heap_oop(v); |
326 *p = encode_heap_oop(v); |
360 } |
327 } |
361 |
328 |
362 // Store heap oop as is for volatile fields. |
329 inline oop oopDesc::obj_field(int offset) const { return HeapAccess<>::oop_load_at(as_oop(), offset); } |
363 void oopDesc::release_store_heap_oop(volatile oop* p, oop v) { |
330 inline void oopDesc::obj_field_put(int offset, oop value) { HeapAccess<>::oop_store_at(as_oop(), offset, value); } |
364 OrderAccess::release_store(p, v); |
331 |
365 } |
332 inline jbyte oopDesc::byte_field(int offset) const { return HeapAccess<>::load_at(as_oop(), offset); } |
366 void oopDesc::release_store_heap_oop(volatile narrowOop* p, narrowOop v) { |
333 inline void oopDesc::byte_field_put(int offset, jbyte value) { HeapAccess<>::store_at(as_oop(), offset, value); } |
367 OrderAccess::release_store(p, v); |
334 |
368 } |
335 inline jchar oopDesc::char_field(int offset) const { return HeapAccess<>::load_at(as_oop(), offset); } |
369 |
336 inline void oopDesc::char_field_put(int offset, jchar value) { HeapAccess<>::store_at(as_oop(), offset, value); } |
370 void oopDesc::release_encode_store_heap_oop_not_null(volatile narrowOop* p, oop v) { |
337 |
371 // heap oop is not pointer sized. |
338 inline jboolean oopDesc::bool_field(int offset) const { return HeapAccess<>::load_at(as_oop(), offset); } |
372 OrderAccess::release_store(p, encode_heap_oop_not_null(v)); |
339 inline void oopDesc::bool_field_put(int offset, jboolean value) { HeapAccess<>::store_at(as_oop(), offset, jboolean(value & 1)); } |
373 } |
340 |
374 void oopDesc::release_encode_store_heap_oop_not_null(volatile oop* p, oop v) { |
341 inline jshort oopDesc::short_field(int offset) const { return HeapAccess<>::load_at(as_oop(), offset); } |
375 OrderAccess::release_store(p, v); |
342 inline void oopDesc::short_field_put(int offset, jshort value) { HeapAccess<>::store_at(as_oop(), offset, value); } |
376 } |
343 |
377 |
344 inline jint oopDesc::int_field(int offset) const { return HeapAccess<>::load_at(as_oop(), offset); } |
378 void oopDesc::release_encode_store_heap_oop(volatile oop* p, oop v) { |
345 inline void oopDesc::int_field_put(int offset, jint value) { HeapAccess<>::store_at(as_oop(), offset, value); } |
379 OrderAccess::release_store(p, v); |
346 |
380 } |
347 inline jlong oopDesc::long_field(int offset) const { return HeapAccess<>::load_at(as_oop(), offset); } |
381 void oopDesc::release_encode_store_heap_oop(volatile narrowOop* p, oop v) { |
348 inline void oopDesc::long_field_put(int offset, jlong value) { HeapAccess<>::store_at(as_oop(), offset, value); } |
382 OrderAccess::release_store(p, encode_heap_oop(v)); |
349 |
383 } |
350 inline jfloat oopDesc::float_field(int offset) const { return HeapAccess<>::load_at(as_oop(), offset); } |
384 |
351 inline void oopDesc::float_field_put(int offset, jfloat value) { HeapAccess<>::store_at(as_oop(), offset, value); } |
385 // These functions are only used to exchange oop fields in instances, |
352 |
386 // not headers. |
353 inline jdouble oopDesc::double_field(int offset) const { return HeapAccess<>::load_at(as_oop(), offset); } |
387 oop oopDesc::atomic_exchange_oop(oop exchange_value, volatile HeapWord *dest) { |
354 inline void oopDesc::double_field_put(int offset, jdouble value) { HeapAccess<>::store_at(as_oop(), offset, value); } |
388 if (UseCompressedOops) { |
|
389 // encode exchange value from oop to T |
|
390 narrowOop val = encode_heap_oop(exchange_value); |
|
391 narrowOop old = Atomic::xchg(val, (narrowOop*)dest); |
|
392 // decode old from T to oop |
|
393 return decode_heap_oop(old); |
|
394 } else { |
|
395 return Atomic::xchg(exchange_value, (oop*)dest); |
|
396 } |
|
397 } |
|
398 |
|
399 oop oopDesc::atomic_compare_exchange_oop(oop exchange_value, |
|
400 volatile HeapWord *dest, |
|
401 oop compare_value, |
|
402 bool prebarrier) { |
|
403 if (UseCompressedOops) { |
|
404 if (prebarrier) { |
|
405 update_barrier_set_pre((narrowOop*)dest, exchange_value); |
|
406 } |
|
407 // encode exchange and compare value from oop to T |
|
408 narrowOop val = encode_heap_oop(exchange_value); |
|
409 narrowOop cmp = encode_heap_oop(compare_value); |
|
410 |
|
411 narrowOop old = Atomic::cmpxchg(val, (narrowOop*)dest, cmp); |
|
412 // decode old from T to oop |
|
413 return decode_heap_oop(old); |
|
414 } else { |
|
415 if (prebarrier) { |
|
416 update_barrier_set_pre((oop*)dest, exchange_value); |
|
417 } |
|
418 return Atomic::cmpxchg(exchange_value, (oop*)dest, compare_value); |
|
419 } |
|
420 } |
|
421 |
|
422 // In order to put or get a field out of an instance, must first check |
|
423 // if the field has been compressed and uncompress it. |
|
424 oop oopDesc::obj_field(int offset) const { |
|
425 return UseCompressedOops ? |
|
426 load_decode_heap_oop(obj_field_addr<narrowOop>(offset)) : |
|
427 load_decode_heap_oop(obj_field_addr<oop>(offset)); |
|
428 } |
|
429 |
|
430 void oopDesc::obj_field_put(int offset, oop value) { |
|
431 UseCompressedOops ? oop_store(obj_field_addr<narrowOop>(offset), value) : |
|
432 oop_store(obj_field_addr<oop>(offset), value); |
|
433 } |
|
434 |
|
435 void oopDesc::obj_field_put_raw(int offset, oop value) { |
|
436 UseCompressedOops ? |
|
437 encode_store_heap_oop(obj_field_addr<narrowOop>(offset), value) : |
|
438 encode_store_heap_oop(obj_field_addr<oop>(offset), value); |
|
439 } |
|
440 void oopDesc::obj_field_put_volatile(int offset, oop value) { |
|
441 OrderAccess::release(); |
|
442 obj_field_put(offset, value); |
|
443 OrderAccess::fence(); |
|
444 } |
|
445 |
|
446 Metadata* oopDesc::metadata_field(int offset) const { return *metadata_field_addr(offset); } |
|
447 void oopDesc::metadata_field_put(int offset, Metadata* value) { *metadata_field_addr(offset) = value; } |
|
448 |
|
449 Metadata* oopDesc::metadata_field_acquire(int offset) const { |
|
450 return OrderAccess::load_acquire(metadata_field_addr(offset)); |
|
451 } |
|
452 |
|
453 void oopDesc::release_metadata_field_put(int offset, Metadata* value) { |
|
454 OrderAccess::release_store(metadata_field_addr(offset), value); |
|
455 } |
|
456 |
|
457 jbyte oopDesc::byte_field(int offset) const { return (jbyte) *byte_field_addr(offset); } |
|
458 void oopDesc::byte_field_put(int offset, jbyte contents) { *byte_field_addr(offset) = (jint) contents; } |
|
459 |
|
460 jchar oopDesc::char_field(int offset) const { return (jchar) *char_field_addr(offset); } |
|
461 void oopDesc::char_field_put(int offset, jchar contents) { *char_field_addr(offset) = (jint) contents; } |
|
462 |
|
463 jboolean oopDesc::bool_field(int offset) const { return (jboolean) *bool_field_addr(offset); } |
|
464 void oopDesc::bool_field_put(int offset, jboolean contents) { *bool_field_addr(offset) = (((jint) contents) & 1); } |
|
465 |
|
466 jint oopDesc::int_field(int offset) const { return *int_field_addr(offset); } |
|
467 void oopDesc::int_field_put(int offset, jint contents) { *int_field_addr(offset) = contents; } |
|
468 |
|
469 jshort oopDesc::short_field(int offset) const { return (jshort) *short_field_addr(offset); } |
|
470 void oopDesc::short_field_put(int offset, jshort contents) { *short_field_addr(offset) = (jint) contents;} |
|
471 |
|
472 jlong oopDesc::long_field(int offset) const { return *long_field_addr(offset); } |
|
473 void oopDesc::long_field_put(int offset, jlong contents) { *long_field_addr(offset) = contents; } |
|
474 |
|
475 jfloat oopDesc::float_field(int offset) const { return *float_field_addr(offset); } |
|
476 void oopDesc::float_field_put(int offset, jfloat contents) { *float_field_addr(offset) = contents; } |
|
477 |
|
478 jdouble oopDesc::double_field(int offset) const { return *double_field_addr(offset); } |
|
479 void oopDesc::double_field_put(int offset, jdouble contents) { *double_field_addr(offset) = contents; } |
|
480 |
|
481 address oopDesc::address_field(int offset) const { return *address_field_addr(offset); } |
|
482 void oopDesc::address_field_put(int offset, address contents) { *address_field_addr(offset) = contents; } |
|
483 |
|
484 oop oopDesc::obj_field_acquire(int offset) const { |
|
485 return UseCompressedOops ? |
|
486 decode_heap_oop((narrowOop) |
|
487 OrderAccess::load_acquire(obj_field_addr<narrowOop>(offset))) |
|
488 : decode_heap_oop( |
|
489 OrderAccess::load_acquire(obj_field_addr<oop>(offset))); |
|
490 } |
|
491 void oopDesc::release_obj_field_put(int offset, oop value) { |
|
492 UseCompressedOops ? |
|
493 oop_store((volatile narrowOop*)obj_field_addr<narrowOop>(offset), value) : |
|
494 oop_store((volatile oop*) obj_field_addr<oop>(offset), value); |
|
495 } |
|
496 |
|
497 jbyte oopDesc::byte_field_acquire(int offset) const { return OrderAccess::load_acquire(byte_field_addr(offset)); } |
|
498 void oopDesc::release_byte_field_put(int offset, jbyte contents) { OrderAccess::release_store(byte_field_addr(offset), contents); } |
|
499 |
|
500 jchar oopDesc::char_field_acquire(int offset) const { return OrderAccess::load_acquire(char_field_addr(offset)); } |
|
501 void oopDesc::release_char_field_put(int offset, jchar contents) { OrderAccess::release_store(char_field_addr(offset), contents); } |
|
502 |
|
503 jboolean oopDesc::bool_field_acquire(int offset) const { return OrderAccess::load_acquire(bool_field_addr(offset)); } |
|
504 void oopDesc::release_bool_field_put(int offset, jboolean contents) { OrderAccess::release_store(bool_field_addr(offset), jboolean(contents & 1)); } |
|
505 |
|
506 jint oopDesc::int_field_acquire(int offset) const { return OrderAccess::load_acquire(int_field_addr(offset)); } |
|
507 void oopDesc::release_int_field_put(int offset, jint contents) { OrderAccess::release_store(int_field_addr(offset), contents); } |
|
508 |
|
509 jshort oopDesc::short_field_acquire(int offset) const { return (jshort)OrderAccess::load_acquire(short_field_addr(offset)); } |
|
510 void oopDesc::release_short_field_put(int offset, jshort contents) { OrderAccess::release_store(short_field_addr(offset), contents); } |
|
511 |
|
512 jlong oopDesc::long_field_acquire(int offset) const { return OrderAccess::load_acquire(long_field_addr(offset)); } |
|
513 void oopDesc::release_long_field_put(int offset, jlong contents) { OrderAccess::release_store(long_field_addr(offset), contents); } |
|
514 |
|
515 jfloat oopDesc::float_field_acquire(int offset) const { return OrderAccess::load_acquire(float_field_addr(offset)); } |
|
516 void oopDesc::release_float_field_put(int offset, jfloat contents) { OrderAccess::release_store(float_field_addr(offset), contents); } |
|
517 |
|
518 jdouble oopDesc::double_field_acquire(int offset) const { return OrderAccess::load_acquire(double_field_addr(offset)); } |
|
519 void oopDesc::release_double_field_put(int offset, jdouble contents) { OrderAccess::release_store(double_field_addr(offset), contents); } |
|
520 |
|
521 address oopDesc::address_field_acquire(int offset) const { return OrderAccess::load_acquire(address_field_addr(offset)); } |
|
522 void oopDesc::release_address_field_put(int offset, address contents) { OrderAccess::release_store(address_field_addr(offset), contents); } |
|
523 |
355 |
524 bool oopDesc::is_locked() const { |
356 bool oopDesc::is_locked() const { |
525 return mark()->is_locked(); |
357 return mark()->is_locked(); |
526 } |
358 } |
527 |
359 |