19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 *
24 */
25
26 #include "precompiled.hpp"
27 #include "asm/macroAssembler.inline.hpp"
28 #include "gc/shared/gcArguments.hpp"
29 #include "gc/shared/gc_globals.hpp"
30 #include "gc/shenandoah/shenandoahBarrierSet.hpp"
31 #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
32 #include "gc/shenandoah/shenandoahForwarding.hpp"
33 #include "gc/shenandoah/shenandoahHeap.hpp"
34 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
35 #include "gc/shenandoah/shenandoahHeapRegion.hpp"
36 #include "gc/shenandoah/shenandoahRuntime.hpp"
37 #include "gc/shenandoah/shenandoahThreadLocalData.hpp"
38 #include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp"
39 #include "interpreter/interpreter.hpp"
40 #include "macroAssembler_ppc.hpp"
41 #include "runtime/javaThread.hpp"
42 #include "runtime/sharedRuntime.hpp"
43 #include "utilities/globalDefinitions.hpp"
44 #include "vm_version_ppc.hpp"
45 #ifdef COMPILER1
46 #include "c1/c1_LIRAssembler.hpp"
47 #include "c1/c1_MacroAssembler.hpp"
48 #include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp"
49 #endif
50
51 #define __ masm->
52
53 void ShenandoahBarrierSetAssembler::satb_write_barrier(MacroAssembler *masm,
54 Register base, RegisterOrConstant ind_or_offs,
55 Register tmp1, Register tmp2, Register tmp3,
56 MacroAssembler::PreservationLevel preservation_level) {
57 if (ShenandoahSATBBarrier) {
58 __ block_comment("satb_write_barrier (shenandoahgc) {");
59 satb_write_barrier_impl(masm, 0, base, ind_or_offs, tmp1, tmp2, tmp3, preservation_level);
60 __ block_comment("} satb_write_barrier (shenandoahgc)");
61 }
62 }
63
64 void ShenandoahBarrierSetAssembler::load_reference_barrier(MacroAssembler *masm, DecoratorSet decorators,
65 Register base, RegisterOrConstant ind_or_offs,
66 Register dst,
67 Register tmp1, Register tmp2,
68 MacroAssembler::PreservationLevel preservation_level) {
69 if (ShenandoahLoadRefBarrier) {
70 __ block_comment("load_reference_barrier (shenandoahgc) {");
71 load_reference_barrier_impl(masm, decorators, base, ind_or_offs, dst, tmp1, tmp2, preservation_level);
72 __ block_comment("} load_reference_barrier (shenandoahgc)");
73 }
74 }
75
76 void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler *masm, DecoratorSet decorators, BasicType type,
77 Register src, Register dst, Register count,
78 Register preserve1, Register preserve2) {
79 __ block_comment("arraycopy_prologue (shenandoahgc) {");
80
81 Register R11_tmp = R11_scratch1;
82
83 assert_different_registers(src, dst, count, R11_tmp, noreg);
84 if (preserve1 != noreg) {
85 // Technically not required, but likely to indicate an error.
86 assert_different_registers(preserve1, preserve2);
87 }
88
89 /* ==== Check whether barrier is required (optimizations) ==== */
90 // Fast path: Component type of array is not a reference type.
91 if (!is_reference_type(type)) {
92 return;
93 }
94
95 bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0;
96
97 // Fast path: No barrier required if for every barrier type, it is either disabled or would not store
98 // any useful information.
99 if ((!ShenandoahSATBBarrier || dest_uninitialized) && !ShenandoahLoadRefBarrier) {
100 return;
101 }
102
103 Label skip_prologue;
104
105 // Fast path: Array is of length zero.
106 __ cmpdi(CCR0, count, 0);
107 __ beq(CCR0, skip_prologue);
108
109 /* ==== Check whether barrier is required (gc state) ==== */
110 __ lbz(R11_tmp, in_bytes(ShenandoahThreadLocalData::gc_state_offset()),
111 R16_thread);
112
113 // The set of garbage collection states requiring barriers depends on the available barrier types and the
114 // type of the reference in question.
115 // For instance, satb barriers may be skipped if it is certain that the overridden values are not relevant
116 // for the garbage collector.
117 const int required_states = ShenandoahSATBBarrier && dest_uninitialized
118 ? ShenandoahHeap::HAS_FORWARDED
119 : ShenandoahHeap::HAS_FORWARDED | ShenandoahHeap::MARKING;
120
121 __ andi_(R11_tmp, R11_tmp, required_states);
122 __ beq(CCR0, skip_prologue);
156 {
157 __ pop_frame();
158 __ restore_LR(R11_tmp);
159
160 __ ld(count, -BytesPerWord * highest_preserve_register_index--, R1_SP);
161 __ ld(dst, -BytesPerWord * highest_preserve_register_index--, R1_SP);
162 __ ld(src, -BytesPerWord * highest_preserve_register_index--, R1_SP);
163
164 if (preserve2 != noreg && preserve2 != preserve1 && preserve2->is_volatile()) {
165 __ ld(preserve2, -BytesPerWord * highest_preserve_register_index--, R1_SP);
166 }
167 if (preserve1 != noreg && preserve1->is_volatile()) {
168 __ ld(preserve1, -BytesPerWord * highest_preserve_register_index--, R1_SP);
169 }
170 }
171
172 __ bind(skip_prologue);
173 __ block_comment("} arraycopy_prologue (shenandoahgc)");
174 }
175
176 // The to-be-enqueued value can either be determined
177 // - dynamically by passing the reference's address information (load mode) or
178 // - statically by passing a register the value is stored in (preloaded mode)
179 // - for performance optimizations in cases where the previous value is known (currently not implemented) and
180 // - for incremental-update barriers.
181 //
182 // decorators: The previous value's decorator set.
183 // In "load mode", the value must equal '0'.
184 // base: Base register of the reference's address (load mode).
185 // In "preloaded mode", the register must equal 'noreg'.
186 // ind_or_offs: Index or offset of the reference's address (load mode).
187 // If 'base' equals 'noreg' (preloaded mode), the passed value is ignored.
188 // pre_val: Register holding the to-be-stored value (preloaded mode).
189 // In "load mode", this register acts as a temporary register and must
190 // thus not be 'noreg'. In "preloaded mode", its content will be sustained.
191 // tmp1/tmp2: Temporary registers, one of which must be non-volatile in "preloaded mode".
192 void ShenandoahBarrierSetAssembler::satb_write_barrier_impl(MacroAssembler *masm, DecoratorSet decorators,
193 Register base, RegisterOrConstant ind_or_offs,
194 Register pre_val,
195 Register tmp1, Register tmp2,
559
560 __ mr_if_needed(dst, intermediate_dst);
561 } else {
562 BarrierSetAssembler::load_at(masm, decorators, type,
563 base, ind_or_offs,
564 dst,
565 tmp1, tmp2,
566 preservation_level, L_handle_null);
567 }
568
569 /* ==== Apply keep-alive barrier, if required (e.g., to inhibit weak reference resurrection) ==== */
570 if (ShenandoahBarrierSet::need_keep_alive_barrier(decorators, type)) {
571 if (ShenandoahSATBBarrier) {
572 __ block_comment("keep_alive_barrier (shenandoahgc) {");
573 satb_write_barrier_impl(masm, 0, noreg, noreg, dst, tmp1, tmp2, preservation_level);
574 __ block_comment("} keep_alive_barrier (shenandoahgc)");
575 }
576 }
577 }
578
579 // base: Base register of the reference's address.
580 // ind_or_offs: Index or offset of the reference's address.
581 // val: To-be-stored value/reference's new value.
582 void ShenandoahBarrierSetAssembler::store_at(MacroAssembler *masm, DecoratorSet decorators, BasicType type,
583 Register base, RegisterOrConstant ind_or_offs, Register val,
584 Register tmp1, Register tmp2, Register tmp3,
585 MacroAssembler::PreservationLevel preservation_level) {
586 if (is_reference_type(type)) {
587 if (ShenandoahSATBBarrier) {
588 satb_write_barrier(masm, base, ind_or_offs, tmp1, tmp2, tmp3, preservation_level);
589 }
590 }
591
592 BarrierSetAssembler::store_at(masm, decorators, type,
593 base, ind_or_offs,
594 val,
595 tmp1, tmp2, tmp3,
596 preservation_level);
597 }
598
599 void ShenandoahBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler *masm,
600 Register dst, Register jni_env, Register obj,
601 Register tmp, Label &slowpath) {
602 __ block_comment("try_resolve_jobject_in_native (shenandoahgc) {");
603
604 assert_different_registers(jni_env, obj, tmp);
605
606 Label done;
607
608 // Fast path: Reference is null (JNI tags are zero for null pointers).
609 __ cmpdi(CCR0, obj, 0);
610 __ beq(CCR0, done);
611
612 // Resolve jobject using standard implementation.
613 BarrierSetAssembler::try_resolve_jobject_in_native(masm, dst, jni_env, obj, tmp, slowpath);
614
615 // Check whether heap is stable.
616 __ lbz(tmp,
726 // unlikely case should be handled by the smallest possible code. Instead of emitting a third,
727 // explicit CAS operation, the code jumps back and reuses the first CAS operation (step 1)
728 // (passed arguments are identical).
729 //
730 // A failure of the CAS operation in step 1 would imply that the overall CAS operation is supposed
731 // to fail. Jumping back to step 1 requires, however, that step 2 and step 3 are re-executed as well.
732 // It is thus important to ensure that a re-execution of those steps does not put program correctness
733 // at risk:
734 // - Step 2: Either terminates in failure (desired result) or falls through to step 3.
735 // - Step 3: Terminates if the comparison between the forwarded, fetched pointer and the expected value
736 // fails. Unless the reference has been updated in the meanwhile once again, this is
737 // guaranteed to be the case.
738 // In case of a concurrent update, the CAS would be retried again. This is legitimate
739 // in terms of program correctness (even though it is not desired).
740 __ bne(CCR0, step_four);
741
742 __ bind(done);
743 __ block_comment("} cmpxchg_oop (shenandoahgc)");
744 }
745
746 #undef __
747
748 #ifdef COMPILER1
749
750 #define __ ce->masm()->
751
752 void ShenandoahBarrierSetAssembler::gen_pre_barrier_stub(LIR_Assembler *ce, ShenandoahPreBarrierStub *stub) {
753 __ block_comment("gen_pre_barrier_stub (shenandoahgc) {");
754
755 ShenandoahBarrierSetC1 *bs = (ShenandoahBarrierSetC1*) BarrierSet::barrier_set()->barrier_set_c1();
756 __ bind(*stub->entry());
757
758 // GC status has already been verified by 'ShenandoahBarrierSetC1::pre_barrier'.
759 // This stub is the slowpath of that function.
760
761 assert(stub->pre_val()->is_register(), "pre_val must be a register");
762 Register pre_val = stub->pre_val()->as_register();
763
764 // If 'do_load()' returns false, the to-be-stored value is already available in 'stub->pre_val()'
765 // ("preloaded mode" of the store barrier).
|
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 *
24 */
25
26 #include "precompiled.hpp"
27 #include "asm/macroAssembler.inline.hpp"
28 #include "gc/shared/gcArguments.hpp"
29 #include "gc/shared/gc_globals.hpp"
30 #include "gc/shenandoah/shenandoahBarrierSet.hpp"
31 #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
32 #include "gc/shenandoah/shenandoahForwarding.hpp"
33 #include "gc/shenandoah/shenandoahHeap.hpp"
34 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
35 #include "gc/shenandoah/shenandoahHeapRegion.hpp"
36 #include "gc/shenandoah/shenandoahRuntime.hpp"
37 #include "gc/shenandoah/shenandoahThreadLocalData.hpp"
38 #include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp"
39 #include "gc/shenandoah/mode/shenandoahMode.hpp"
40 #include "interpreter/interpreter.hpp"
41 #include "macroAssembler_ppc.hpp"
42 #include "runtime/javaThread.hpp"
43 #include "runtime/sharedRuntime.hpp"
44 #include "utilities/globalDefinitions.hpp"
45 #include "vm_version_ppc.hpp"
46 #ifdef COMPILER1
47 #include "c1/c1_LIRAssembler.hpp"
48 #include "c1/c1_MacroAssembler.hpp"
49 #include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp"
50 #endif
51
52 #define __ masm->
53
54 void ShenandoahBarrierSetAssembler::satb_write_barrier(MacroAssembler *masm,
55 Register base, RegisterOrConstant ind_or_offs,
56 Register tmp1, Register tmp2, Register tmp3,
57 MacroAssembler::PreservationLevel preservation_level) {
58 if (ShenandoahSATBBarrier) {
59 __ block_comment("satb_write_barrier (shenandoahgc) {");
60 satb_write_barrier_impl(masm, 0, base, ind_or_offs, tmp1, tmp2, tmp3, preservation_level);
61 __ block_comment("} satb_write_barrier (shenandoahgc)");
62 }
63 }
64
65 void ShenandoahBarrierSetAssembler::load_reference_barrier(MacroAssembler *masm, DecoratorSet decorators,
66 Register base, RegisterOrConstant ind_or_offs,
67 Register dst,
68 Register tmp1, Register tmp2,
69 MacroAssembler::PreservationLevel preservation_level) {
70 if (ShenandoahLoadRefBarrier) {
71 __ block_comment("load_reference_barrier (shenandoahgc) {");
72 load_reference_barrier_impl(masm, decorators, base, ind_or_offs, dst, tmp1, tmp2, preservation_level);
73 __ block_comment("} load_reference_barrier (shenandoahgc)");
74 }
75 }
76
77 void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler *masm, DecoratorSet decorators, BasicType type,
78 Register src, Register dst, Register count,
79 Register preserve1, Register preserve2) {
80 Register R11_tmp = R11_scratch1;
81
82 assert_different_registers(src, dst, count, R11_tmp, noreg);
83 if (preserve1 != noreg) {
84 // Technically not required, but likely to indicate an error.
85 assert_different_registers(preserve1, preserve2);
86 }
87
88 /* ==== Check whether barrier is required (optimizations) ==== */
89 // Fast path: Component type of array is not a reference type.
90 if (!is_reference_type(type)) {
91 return;
92 }
93
94 bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0;
95
96 // Fast path: No barrier required if for every barrier type, it is either disabled or would not store
97 // any useful information.
98 if ((!ShenandoahSATBBarrier || dest_uninitialized) && !ShenandoahLoadRefBarrier) {
99 return;
100 }
101
102 __ block_comment("arraycopy_prologue (shenandoahgc) {");
103 Label skip_prologue;
104
105 // Fast path: Array is of length zero.
106 __ cmpdi(CCR0, count, 0);
107 __ beq(CCR0, skip_prologue);
108
109 /* ==== Check whether barrier is required (gc state) ==== */
110 __ lbz(R11_tmp, in_bytes(ShenandoahThreadLocalData::gc_state_offset()),
111 R16_thread);
112
113 // The set of garbage collection states requiring barriers depends on the available barrier types and the
114 // type of the reference in question.
115 // For instance, satb barriers may be skipped if it is certain that the overridden values are not relevant
116 // for the garbage collector.
117 const int required_states = ShenandoahSATBBarrier && dest_uninitialized
118 ? ShenandoahHeap::HAS_FORWARDED
119 : ShenandoahHeap::HAS_FORWARDED | ShenandoahHeap::MARKING;
120
121 __ andi_(R11_tmp, R11_tmp, required_states);
122 __ beq(CCR0, skip_prologue);
156 {
157 __ pop_frame();
158 __ restore_LR(R11_tmp);
159
160 __ ld(count, -BytesPerWord * highest_preserve_register_index--, R1_SP);
161 __ ld(dst, -BytesPerWord * highest_preserve_register_index--, R1_SP);
162 __ ld(src, -BytesPerWord * highest_preserve_register_index--, R1_SP);
163
164 if (preserve2 != noreg && preserve2 != preserve1 && preserve2->is_volatile()) {
165 __ ld(preserve2, -BytesPerWord * highest_preserve_register_index--, R1_SP);
166 }
167 if (preserve1 != noreg && preserve1->is_volatile()) {
168 __ ld(preserve1, -BytesPerWord * highest_preserve_register_index--, R1_SP);
169 }
170 }
171
172 __ bind(skip_prologue);
173 __ block_comment("} arraycopy_prologue (shenandoahgc)");
174 }
175
176 void ShenandoahBarrierSetAssembler::arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
177 Register dst, Register count,
178 Register preserve) {
179 if (ShenandoahCardBarrier && is_reference_type(type)) {
180 __ block_comment("arraycopy_epilogue (shenandoahgc) {");
181 gen_write_ref_array_post_barrier(masm, decorators, dst, count, preserve);
182 __ block_comment("} arraycopy_epilogue (shenandoahgc)");
183 }
184 }
185
186 // The to-be-enqueued value can either be determined
187 // - dynamically by passing the reference's address information (load mode) or
188 // - statically by passing a register the value is stored in (preloaded mode)
189 // - for performance optimizations in cases where the previous value is known (currently not implemented) and
190 // - for incremental-update barriers.
191 //
192 // decorators: The previous value's decorator set.
193 // In "load mode", the value must equal '0'.
194 // base: Base register of the reference's address (load mode).
195 // In "preloaded mode", the register must equal 'noreg'.
196 // ind_or_offs: Index or offset of the reference's address (load mode).
197 // If 'base' equals 'noreg' (preloaded mode), the passed value is ignored.
198 // pre_val: Register holding the to-be-stored value (preloaded mode).
199 // In "load mode", this register acts as a temporary register and must
200 // thus not be 'noreg'. In "preloaded mode", its content will be sustained.
201 // tmp1/tmp2: Temporary registers, one of which must be non-volatile in "preloaded mode".
202 void ShenandoahBarrierSetAssembler::satb_write_barrier_impl(MacroAssembler *masm, DecoratorSet decorators,
203 Register base, RegisterOrConstant ind_or_offs,
204 Register pre_val,
205 Register tmp1, Register tmp2,
569
570 __ mr_if_needed(dst, intermediate_dst);
571 } else {
572 BarrierSetAssembler::load_at(masm, decorators, type,
573 base, ind_or_offs,
574 dst,
575 tmp1, tmp2,
576 preservation_level, L_handle_null);
577 }
578
579 /* ==== Apply keep-alive barrier, if required (e.g., to inhibit weak reference resurrection) ==== */
580 if (ShenandoahBarrierSet::need_keep_alive_barrier(decorators, type)) {
581 if (ShenandoahSATBBarrier) {
582 __ block_comment("keep_alive_barrier (shenandoahgc) {");
583 satb_write_barrier_impl(masm, 0, noreg, noreg, dst, tmp1, tmp2, preservation_level);
584 __ block_comment("} keep_alive_barrier (shenandoahgc)");
585 }
586 }
587 }
588
589 void ShenandoahBarrierSetAssembler::store_check(MacroAssembler* masm, Register base, RegisterOrConstant ind_or_offs, Register tmp) {
590 assert(ShenandoahCardBarrier, "Should have been checked by caller");
591
592 ShenandoahBarrierSet* ctbs = ShenandoahBarrierSet::barrier_set();
593 CardTable* ct = ctbs->card_table();
594 assert_different_registers(base, tmp, R0);
595
596 if (ind_or_offs.is_constant()) {
597 __ add_const_optimized(base, base, ind_or_offs.as_constant(), tmp);
598 } else {
599 __ add(base, ind_or_offs.as_register(), base);
600 }
601
602 __ load_const_optimized(tmp, (address)ct->byte_map_base(), R0);
603 __ srdi(base, base, CardTable::card_shift());
604 __ li(R0, CardTable::dirty_card_val());
605 __ stbx(R0, tmp, base);
606 }
607
608 // base: Base register of the reference's address.
609 // ind_or_offs: Index or offset of the reference's address.
610 // val: To-be-stored value/reference's new value.
611 void ShenandoahBarrierSetAssembler::store_at(MacroAssembler *masm, DecoratorSet decorators, BasicType type,
612 Register base, RegisterOrConstant ind_or_offs, Register val,
613 Register tmp1, Register tmp2, Register tmp3,
614 MacroAssembler::PreservationLevel preservation_level) {
615 if (is_reference_type(type)) {
616 if (ShenandoahSATBBarrier) {
617 satb_write_barrier(masm, base, ind_or_offs, tmp1, tmp2, tmp3, preservation_level);
618 }
619 }
620
621 BarrierSetAssembler::store_at(masm, decorators, type,
622 base, ind_or_offs,
623 val,
624 tmp1, tmp2, tmp3,
625 preservation_level);
626
627 // No need for post barrier if storing NULL
628 if (ShenandoahCardBarrier && is_reference_type(type) && val != noreg) {
629 store_check(masm, base, ind_or_offs, tmp1);
630 }
631 }
632
633 void ShenandoahBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler *masm,
634 Register dst, Register jni_env, Register obj,
635 Register tmp, Label &slowpath) {
636 __ block_comment("try_resolve_jobject_in_native (shenandoahgc) {");
637
638 assert_different_registers(jni_env, obj, tmp);
639
640 Label done;
641
642 // Fast path: Reference is null (JNI tags are zero for null pointers).
643 __ cmpdi(CCR0, obj, 0);
644 __ beq(CCR0, done);
645
646 // Resolve jobject using standard implementation.
647 BarrierSetAssembler::try_resolve_jobject_in_native(masm, dst, jni_env, obj, tmp, slowpath);
648
649 // Check whether heap is stable.
650 __ lbz(tmp,
760 // unlikely case should be handled by the smallest possible code. Instead of emitting a third,
761 // explicit CAS operation, the code jumps back and reuses the first CAS operation (step 1)
762 // (passed arguments are identical).
763 //
764 // A failure of the CAS operation in step 1 would imply that the overall CAS operation is supposed
765 // to fail. Jumping back to step 1 requires, however, that step 2 and step 3 are re-executed as well.
766 // It is thus important to ensure that a re-execution of those steps does not put program correctness
767 // at risk:
768 // - Step 2: Either terminates in failure (desired result) or falls through to step 3.
769 // - Step 3: Terminates if the comparison between the forwarded, fetched pointer and the expected value
770 // fails. Unless the reference has been updated in the meanwhile once again, this is
771 // guaranteed to be the case.
772 // In case of a concurrent update, the CAS would be retried again. This is legitimate
773 // in terms of program correctness (even though it is not desired).
774 __ bne(CCR0, step_four);
775
776 __ bind(done);
777 __ block_comment("} cmpxchg_oop (shenandoahgc)");
778 }
779
780 void ShenandoahBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
781 Register addr, Register count, Register preserve) {
782 assert(ShenandoahCardBarrier, "Should have been checked by caller");
783
784 ShenandoahBarrierSet* bs = ShenandoahBarrierSet::barrier_set();
785 CardTable* ct = bs->card_table();
786 assert_different_registers(addr, count, R0);
787
788 Label L_skip_loop, L_store_loop;
789
790 __ sldi_(count, count, LogBytesPerHeapOop);
791
792 // Zero length? Skip.
793 __ beq(CCR0, L_skip_loop);
794
795 __ addi(count, count, -BytesPerHeapOop);
796 __ add(count, addr, count);
797 // Use two shifts to clear out those low order two bits! (Cannot opt. into 1.)
798 __ srdi(addr, addr, CardTable::card_shift());
799 __ srdi(count, count, CardTable::card_shift());
800 __ subf(count, addr, count);
801 __ add_const_optimized(addr, addr, (address)ct->byte_map_base(), R0);
802 __ addi(count, count, 1);
803 __ li(R0, 0);
804 __ mtctr(count);
805
806 // Byte store loop
807 __ bind(L_store_loop);
808 __ stb(R0, 0, addr);
809 __ addi(addr, addr, 1);
810 __ bdnz(L_store_loop);
811 __ bind(L_skip_loop);
812 }
813
814 #undef __
815
816 #ifdef COMPILER1
817
818 #define __ ce->masm()->
819
820 void ShenandoahBarrierSetAssembler::gen_pre_barrier_stub(LIR_Assembler *ce, ShenandoahPreBarrierStub *stub) {
821 __ block_comment("gen_pre_barrier_stub (shenandoahgc) {");
822
823 ShenandoahBarrierSetC1 *bs = (ShenandoahBarrierSetC1*) BarrierSet::barrier_set()->barrier_set_c1();
824 __ bind(*stub->entry());
825
826 // GC status has already been verified by 'ShenandoahBarrierSetC1::pre_barrier'.
827 // This stub is the slowpath of that function.
828
829 assert(stub->pre_val()->is_register(), "pre_val must be a register");
830 Register pre_val = stub->pre_val()->as_register();
831
832 // If 'do_load()' returns false, the to-be-stored value is already available in 'stub->pre_val()'
833 // ("preloaded mode" of the store barrier).
|