443 load_reference_barrier_not_null(masm, dst, src); |
444 load_reference_barrier_not_null(masm, dst, src); |
444 __ bind(done); |
445 __ bind(done); |
445 } |
446 } |
446 } |
447 } |
447 |
448 |
|
449 // |
|
450 // Arguments: |
|
451 // |
|
452 // Inputs: |
|
453 // src: oop location, might be clobbered |
|
454 // tmp1: scratch register, might not be valid. |
|
455 // |
|
456 // Output: |
|
457 // dst: oop loaded from src location |
|
458 // |
|
459 // Kill: |
|
460 // tmp1 (if it is valid) |
|
461 // |
448 void ShenandoahBarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, |
462 void ShenandoahBarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, |
449 Register dst, Address src, Register tmp1, Register tmp_thread) { |
463 Register dst, Address src, Register tmp1, Register tmp_thread) { |
450 bool on_oop = is_reference_type(type); |
464 // 1: non-reference load, no additional barrier is needed |
451 bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0; |
465 if (!is_reference_type(type)) { |
452 bool on_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0; |
466 BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread); |
453 bool not_in_heap = (decorators & IN_NATIVE) != 0; |
467 return; |
454 bool on_reference = on_weak || on_phantom; |
468 } |
455 bool is_traversal_mode = ShenandoahHeap::heap()->is_traversal_mode(); |
469 |
456 bool keep_alive = ((decorators & AS_NO_KEEPALIVE) == 0) || is_traversal_mode; |
470 // 2: load a reference from src location and apply LRB if ShenandoahLoadRefBarrier is set |
457 |
471 if (ShenandoahLoadRefBarrier) { |
458 Register result_dst = dst; |
472 Register result_dst = dst; |
459 bool use_tmp1_for_dst = false; |
473 bool use_tmp1_for_dst = false; |
460 |
474 |
461 if (on_oop) { |
475 // Preserve src location for LRB |
462 // We want to preserve src |
|
463 if (dst == src.base() || dst == src.index()) { |
476 if (dst == src.base() || dst == src.index()) { |
464 // Use tmp1 for dst if possible, as it is not used in BarrierAssembler::load_at() |
477 // Use tmp1 for dst if possible, as it is not used in BarrierAssembler::load_at() |
465 if (tmp1->is_valid() && tmp1 != src.base() && tmp1 != src.index()) { |
478 if (tmp1->is_valid() && tmp1 != src.base() && tmp1 != src.index()) { |
466 dst = tmp1; |
479 dst = tmp1; |
467 use_tmp1_for_dst = true; |
480 use_tmp1_for_dst = true; |
468 } else { |
481 } else { |
469 dst = rdi; |
482 dst = rdi; |
470 __ push(dst); |
483 __ push(dst); |
471 } |
484 } |
472 } |
485 assert_different_registers(dst, src.base(), src.index()); |
473 assert_different_registers(dst, src.base(), src.index()); |
486 } |
474 } |
487 |
475 |
488 BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread); |
476 BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread); |
489 |
477 |
490 // Native barrier is for concurrent root processing |
478 if (on_oop) { |
491 bool in_native = (decorators & IN_NATIVE) != 0; |
479 if (not_in_heap && !is_traversal_mode) { |
492 if (in_native && ShenandoahConcurrentRoots::can_do_concurrent_roots()) { |
480 load_reference_barrier_native(masm, dst, src); |
493 load_reference_barrier_native(masm, dst, src); |
481 } else { |
494 } else { |
482 load_reference_barrier(masm, dst, src); |
495 load_reference_barrier(masm, dst, src); |
483 } |
496 } |
484 |
497 |
|
498 // Move loaded oop to final destination |
485 if (dst != result_dst) { |
499 if (dst != result_dst) { |
486 __ movptr(result_dst, dst); |
500 __ movptr(result_dst, dst); |
487 |
501 |
488 if (!use_tmp1_for_dst) { |
502 if (!use_tmp1_for_dst) { |
489 __ pop(dst); |
503 __ pop(dst); |
490 } |
504 } |
491 |
505 |
492 dst = result_dst; |
506 dst = result_dst; |
493 } |
507 } |
494 |
508 } else { |
495 if (ShenandoahKeepAliveBarrier && on_reference && keep_alive) { |
509 BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread); |
|
510 } |
|
511 |
|
512 // 3: apply keep-alive barrier if ShenandoahKeepAliveBarrier is set |
|
513 if (ShenandoahKeepAliveBarrier) { |
|
514 bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0; |
|
515 bool on_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0; |
|
516 bool on_reference = on_weak || on_phantom; |
|
517 bool is_traversal_mode = ShenandoahHeap::heap()->is_traversal_mode(); |
|
518 bool keep_alive = ((decorators & AS_NO_KEEPALIVE) == 0) || is_traversal_mode; |
|
519 |
|
520 if (on_reference && keep_alive) { |
496 const Register thread = NOT_LP64(tmp_thread) LP64_ONLY(r15_thread); |
521 const Register thread = NOT_LP64(tmp_thread) LP64_ONLY(r15_thread); |
497 assert_different_registers(dst, tmp1, tmp_thread); |
522 assert_different_registers(dst, tmp1, tmp_thread); |
498 NOT_LP64(__ get_thread(thread)); |
523 NOT_LP64(__ get_thread(thread)); |
499 // Generate the SATB pre-barrier code to log the value of |
524 // Generate the SATB pre-barrier code to log the value of |
500 // the referent field in an SATB buffer. |
525 // the referent field in an SATB buffer. |