21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "asm/macroAssembler.hpp"
27 #include "asm/macroAssembler.inline.hpp"
28 #include "interpreter/interpreter.hpp"
29 #include "nativeInst_x86.hpp"
30 #include "oops/instanceOop.hpp"
31 #include "oops/method.hpp"
32 #include "oops/objArrayKlass.hpp"
33 #include "oops/oop.inline.hpp"
34 #include "prims/methodHandles.hpp"
35 #include "runtime/frame.inline.hpp"
36 #include "runtime/handles.inline.hpp"
37 #include "runtime/sharedRuntime.hpp"
38 #include "runtime/stubCodeGenerator.hpp"
39 #include "runtime/stubRoutines.hpp"
40 #include "runtime/thread.inline.hpp"
41 #include "utilities/top.hpp"
42 #ifdef COMPILER2
43 #include "opto/runtime.hpp"
44 #endif
45
46 // Declaration and definition of StubGenerator (no .hpp file).
47 // For a more detailed description of the stub routine structure
48 // see the comment in stubRoutines.hpp
49
50 #define __ _masm->
51 #define a__ ((Assembler*)_masm)->
52
53 #ifdef PRODUCT
54 #define BLOCK_COMMENT(str) /* nothing */
55 #else
56 #define BLOCK_COMMENT(str) __ block_comment(str)
57 #endif
58
59 #define BIND(label) bind(label); BLOCK_COMMENT(#label ":")
60
61 const int MXCSR_MASK = 0xFFC0; // Mask out any pending exceptions
62 const int FPU_CNTRL_WRD_MASK = 0xFFFF;
63
64 // -------------------------------------------------------------------------------------------------------------------------
685
686 // handle errors
687 __ bind(error);
688 __ movptr(rax, Address(rsp, 5 * wordSize)); // get saved rax, back
689 __ pop(rdx); // get saved rdx back
690 __ popf(); // get saved EFLAGS off stack -- will be ignored
691 __ pusha(); // push registers (eip = return address & msg are already pushed)
692 BLOCK_COMMENT("call MacroAssembler::debug");
693 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, MacroAssembler::debug32)));
694 __ popa();
695 __ ret(3 * wordSize); // pop arguments
696 return start;
697 }
698
699 //
700 // Generate pre-barrier for array stores
701 //
702 // Input:
703 // start - starting address
704 // count - element count
705 void gen_write_ref_array_pre_barrier(Register start, Register count, bool uninitialized_target) {
706 assert_different_registers(start, count);
707 BarrierSet* bs = Universe::heap()->barrier_set();
708 switch (bs->kind()) {
709 case BarrierSet::G1SATBCT:
710 case BarrierSet::G1SATBCTLogging:
711 // With G1, don't generate the call if we statically know that the target in uninitialized
712 if (!uninitialized_target) {
713 __ pusha(); // push registers
714 __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre),
715 start, count);
716 __ popa();
717 }
718 break;
719 case BarrierSet::CardTableModRef:
720 case BarrierSet::CardTableExtension:
721 case BarrierSet::ModRef:
722 break;
723 default :
724 ShouldNotReachHere();
725
726 }
727 }
728
729
730 //
731 // Generate a post-barrier for an array store
732 //
733 // start - starting address
734 // count - element count
735 //
736 // The two input registers are overwritten.
737 //
738 void gen_write_ref_array_post_barrier(Register start, Register count) {
739 BarrierSet* bs = Universe::heap()->barrier_set();
740 assert_different_registers(start, count);
741 switch (bs->kind()) {
742 case BarrierSet::G1SATBCT:
755 CardTableModRefBS* ct = (CardTableModRefBS*)bs;
756 assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
757
758 Label L_loop;
759 const Register end = count; // elements count; end == start+count-1
760 assert_different_registers(start, end);
761
762 __ lea(end, Address(start, count, Address::times_ptr, -wordSize));
763 __ shrptr(start, CardTableModRefBS::card_shift);
764 __ shrptr(end, CardTableModRefBS::card_shift);
765 __ subptr(end, start); // end --> count
766 __ BIND(L_loop);
767 intptr_t disp = (intptr_t) ct->byte_map_base;
768 Address cardtable(start, count, Address::times_1, disp);
769 __ movb(cardtable, 0);
770 __ decrement(count);
771 __ jcc(Assembler::greaterEqual, L_loop);
772 }
773 break;
774 case BarrierSet::ModRef:
775 break;
776 default :
777 ShouldNotReachHere();
778
779 }
780 }
781
782
783 // Copy 64 bytes chunks
784 //
785 // Inputs:
786 // from - source array address
787 // to_from - destination array address - from
788 // qword_count - 8-bytes element count, negative
789 //
790 void xmm_copy_forward(Register from, Register to_from, Register qword_count) {
791 assert( UseSSE >= 2, "supported cpu only" );
792 Label L_copy_64_bytes_loop, L_copy_64_bytes, L_copy_8_bytes, L_exit;
793 // Copy 64-byte chunks
794 __ jmpb(L_copy_64_bytes);
920 const Register to = rdi; // destination array address
921 const Register count = rcx; // elements count
922 const Register to_from = to; // (to - from)
923 const Register saved_to = rdx; // saved destination array address
924
925 __ enter(); // required for proper stackwalking of RuntimeStub frame
926 __ push(rsi);
927 __ push(rdi);
928 __ movptr(from , Address(rsp, 12+ 4));
929 __ movptr(to , Address(rsp, 12+ 8));
930 __ movl(count, Address(rsp, 12+ 12));
931
932 if (entry != NULL) {
933 *entry = __ pc(); // Entry point from conjoint arraycopy stub.
934 BLOCK_COMMENT("Entry:");
935 }
936
937 if (t == T_OBJECT) {
938 __ testl(count, count);
939 __ jcc(Assembler::zero, L_0_count);
940 gen_write_ref_array_pre_barrier(to, count, dest_uninitialized);
941 __ mov(saved_to, to); // save 'to'
942 }
943
944 __ subptr(to, from); // to --> to_from
945 __ cmpl(count, 2<<shift); // Short arrays (< 8 bytes) copy by element
946 __ jcc(Assembler::below, L_copy_4_bytes); // use unsigned cmp
947 if (!UseUnalignedLoadStores && !aligned && (t == T_BYTE || t == T_SHORT)) {
948 // align source address at 4 bytes address boundary
949 if (t == T_BYTE) {
950 // One byte misalignment happens only for byte arrays
951 __ testl(from, 1);
952 __ jccb(Assembler::zero, L_skip_align1);
953 __ movb(rax, Address(from, 0));
954 __ movb(Address(from, to_from, Address::times_1, 0), rax);
955 __ increment(from);
956 __ decrement(count);
957 __ BIND(L_skip_align1);
958 }
959 // Two bytes misalignment happens only for byte and short (char) arrays
960 __ testl(from, 2);
1099 if (entry != NULL) {
1100 *entry = __ pc(); // Entry point from generic arraycopy stub.
1101 BLOCK_COMMENT("Entry:");
1102 }
1103
1104 // nooverlap_target expects arguments in rsi and rdi.
1105 __ mov(from, src);
1106 __ mov(to , dst);
1107
1108 // arrays overlap test: dispatch to disjoint stub if necessary.
1109 RuntimeAddress nooverlap(nooverlap_target);
1110 __ cmpptr(dst, src);
1111 __ lea(end, Address(src, count, sf, 0)); // src + count * elem_size
1112 __ jump_cc(Assembler::belowEqual, nooverlap);
1113 __ cmpptr(dst, end);
1114 __ jump_cc(Assembler::aboveEqual, nooverlap);
1115
1116 if (t == T_OBJECT) {
1117 __ testl(count, count);
1118 __ jcc(Assembler::zero, L_0_count);
1119 gen_write_ref_array_pre_barrier(dst, count, dest_uninitialized);
1120 }
1121
1122 // copy from high to low
1123 __ cmpl(count, 2<<shift); // Short arrays (< 8 bytes) copy by element
1124 __ jcc(Assembler::below, L_copy_4_bytes); // use unsigned cmp
1125 if (t == T_BYTE || t == T_SHORT) {
1126 // Align the end of destination array at 4 bytes address boundary
1127 __ lea(end, Address(dst, count, sf, 0));
1128 if (t == T_BYTE) {
1129 // One byte misalignment happens only for byte arrays
1130 __ testl(end, 1);
1131 __ jccb(Assembler::zero, L_skip_align1);
1132 __ decrement(count);
1133 __ movb(rdx, Address(from, count, sf, 0));
1134 __ movb(Address(to, count, sf, 0), rdx);
1135 __ BIND(L_skip_align1);
1136 }
1137 // Two bytes misalignment happens only for byte and short (char) arrays
1138 __ testl(end, 2);
1139 __ jccb(Assembler::zero, L_skip_align2);
1446 // Assembler stub will be used for this call to arraycopy
1447 // if the two arrays are subtypes of Object[] but the
1448 // destination array type is not equal to or a supertype
1449 // of the source type. Each element must be separately
1450 // checked.
1451
1452 // Loop-invariant addresses. They are exclusive end pointers.
1453 Address end_from_addr(from, length, Address::times_ptr, 0);
1454 Address end_to_addr(to, length, Address::times_ptr, 0);
1455
1456 Register end_from = from; // re-use
1457 Register end_to = to; // re-use
1458 Register count = length; // re-use
1459
1460 // Loop-variant addresses. They assume post-incremented count < 0.
1461 Address from_element_addr(end_from, count, Address::times_ptr, 0);
1462 Address to_element_addr(end_to, count, Address::times_ptr, 0);
1463 Address elem_klass_addr(elem, oopDesc::klass_offset_in_bytes());
1464
1465 // Copy from low to high addresses, indexed from the end of each array.
1466 gen_write_ref_array_pre_barrier(to, count, dest_uninitialized);
1467 __ lea(end_from, end_from_addr);
1468 __ lea(end_to, end_to_addr);
1469 assert(length == count, ""); // else fix next line:
1470 __ negptr(count); // negate and test the length
1471 __ jccb(Assembler::notZero, L_load_element);
1472
1473 // Empty array: Nothing to do.
1474 __ xorptr(rax, rax); // return 0 on (trivial) success
1475 __ jmp(L_done);
1476
1477 // ======== begin loop ========
1478 // (Loop is rotated; its entry is L_load_element.)
1479 // Loop control:
1480 // for (count = -count; count != 0; count++)
1481 // Base pointers src, dst are biased by 8*count,to last element.
1482 __ align(OptoLoopAlignment);
1483
1484 __ BIND(L_store_element);
1485 __ movptr(to_element_addr, elem); // store the oop
1486 __ increment(count); // increment the count toward zero
1487 __ jccb(Assembler::zero, L_do_card_marks);
1488
1489 // ======== loop entry is here ========
1490 __ BIND(L_load_element);
1491 __ movptr(elem, from_element_addr); // load the oop
1492 __ testptr(elem, elem);
1493 __ jccb(Assembler::zero, L_store_element);
1494
1495 // (Could do a trick here: Remember last successful non-null
1496 // element stored and make a quick oop equality check on it.)
1497
1498 __ movptr(elem_klass, elem_klass_addr); // query the object klass
1499 generate_type_check(elem_klass, ckoff_arg, ckval_arg, temp,
1500 &L_store_element, NULL);
1501 // (On fall-through, we have failed the element type check.)
1502 // ======== end loop ========
1503
1504 // It was a real error; we must depend on the caller to finish the job.
1505 // Register "count" = -1 * number of *remaining* oops, length_arg = *total* oops.
1506 // Emit GC store barriers for the oops we have copied (length_arg + count),
1507 // and report their number to the caller.
1508 assert_different_registers(to, count, rax);
1509 Label L_post_barrier;
1510 __ addl(count, length_arg); // transfers = (length - remaining)
1511 __ movl2ptr(rax, count); // save the value
1512 __ notptr(rax); // report (-1^K) to caller (does not affect flags)
|
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "asm/macroAssembler.hpp"
27 #include "asm/macroAssembler.inline.hpp"
28 #include "interpreter/interpreter.hpp"
29 #include "nativeInst_x86.hpp"
30 #include "oops/instanceOop.hpp"
31 #include "oops/method.hpp"
32 #include "oops/objArrayKlass.hpp"
33 #include "oops/oop.inline.hpp"
34 #include "prims/methodHandles.hpp"
35 #include "runtime/frame.inline.hpp"
36 #include "runtime/handles.inline.hpp"
37 #include "runtime/sharedRuntime.hpp"
38 #include "runtime/stubCodeGenerator.hpp"
39 #include "runtime/stubRoutines.hpp"
40 #include "runtime/thread.inline.hpp"
41 #include "utilities/macros.hpp"
42 #include "utilities/top.hpp"
43 #ifdef COMPILER2
44 #include "opto/runtime.hpp"
45 #endif
46 #if INCLUDE_ALL_GCS
47 #include "shenandoahBarrierSetAssembler_x86.hpp"
48 #endif
49
50 // Declaration and definition of StubGenerator (no .hpp file).
51 // For a more detailed description of the stub routine structure
52 // see the comment in stubRoutines.hpp
53
54 #define __ _masm->
55 #define a__ ((Assembler*)_masm)->
56
57 #ifdef PRODUCT
58 #define BLOCK_COMMENT(str) /* nothing */
59 #else
60 #define BLOCK_COMMENT(str) __ block_comment(str)
61 #endif
62
63 #define BIND(label) bind(label); BLOCK_COMMENT(#label ":")
64
65 const int MXCSR_MASK = 0xFFC0; // Mask out any pending exceptions
66 const int FPU_CNTRL_WRD_MASK = 0xFFFF;
67
68 // -------------------------------------------------------------------------------------------------------------------------
689
690 // handle errors
691 __ bind(error);
692 __ movptr(rax, Address(rsp, 5 * wordSize)); // get saved rax, back
693 __ pop(rdx); // get saved rdx back
694 __ popf(); // get saved EFLAGS off stack -- will be ignored
695 __ pusha(); // push registers (eip = return address & msg are already pushed)
696 BLOCK_COMMENT("call MacroAssembler::debug");
697 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, MacroAssembler::debug32)));
698 __ popa();
699 __ ret(3 * wordSize); // pop arguments
700 return start;
701 }
702
703 //
704 // Generate pre-barrier for array stores
705 //
706 // Input:
707 // start - starting address
708 // count - element count
709 void gen_write_ref_array_pre_barrier(Register src, Register start, Register count, bool uninitialized_target) {
710 assert_different_registers(start, count);
711 BarrierSet* bs = Universe::heap()->barrier_set();
712 switch (bs->kind()) {
713 case BarrierSet::G1SATBCT:
714 case BarrierSet::G1SATBCTLogging:
715 // With G1, don't generate the call if we statically know that the target in uninitialized
716 if (!uninitialized_target) {
717 __ pusha(); // push registers
718 __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre),
719 start, count);
720 __ popa();
721 }
722 break;
723 case BarrierSet::CardTableModRef:
724 case BarrierSet::CardTableExtension:
725 case BarrierSet::ModRef:
726 break;
727 #if INCLUDE_ALL_GCS
728 case BarrierSet::ShenandoahBarrierSet:
729 ShenandoahBarrierSetAssembler::bsasm()->arraycopy_prologue(_masm, uninitialized_target, src, start, count);
730 break;
731 #endif
732 default :
733 ShouldNotReachHere();
734
735 }
736 }
737
738
739 //
740 // Generate a post-barrier for an array store
741 //
742 // start - starting address
743 // count - element count
744 //
745 // The two input registers are overwritten.
746 //
747 void gen_write_ref_array_post_barrier(Register start, Register count) {
748 BarrierSet* bs = Universe::heap()->barrier_set();
749 assert_different_registers(start, count);
750 switch (bs->kind()) {
751 case BarrierSet::G1SATBCT:
764 CardTableModRefBS* ct = (CardTableModRefBS*)bs;
765 assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
766
767 Label L_loop;
768 const Register end = count; // elements count; end == start+count-1
769 assert_different_registers(start, end);
770
771 __ lea(end, Address(start, count, Address::times_ptr, -wordSize));
772 __ shrptr(start, CardTableModRefBS::card_shift);
773 __ shrptr(end, CardTableModRefBS::card_shift);
774 __ subptr(end, start); // end --> count
775 __ BIND(L_loop);
776 intptr_t disp = (intptr_t) ct->byte_map_base;
777 Address cardtable(start, count, Address::times_1, disp);
778 __ movb(cardtable, 0);
779 __ decrement(count);
780 __ jcc(Assembler::greaterEqual, L_loop);
781 }
782 break;
783 case BarrierSet::ModRef:
784 case BarrierSet::ShenandoahBarrierSet:
785 break;
786 default :
787 ShouldNotReachHere();
788
789 }
790 }
791
792
793 // Copy 64 bytes chunks
794 //
795 // Inputs:
796 // from - source array address
797 // to_from - destination array address - from
798 // qword_count - 8-bytes element count, negative
799 //
800 void xmm_copy_forward(Register from, Register to_from, Register qword_count) {
801 assert( UseSSE >= 2, "supported cpu only" );
802 Label L_copy_64_bytes_loop, L_copy_64_bytes, L_copy_8_bytes, L_exit;
803 // Copy 64-byte chunks
804 __ jmpb(L_copy_64_bytes);
930 const Register to = rdi; // destination array address
931 const Register count = rcx; // elements count
932 const Register to_from = to; // (to - from)
933 const Register saved_to = rdx; // saved destination array address
934
935 __ enter(); // required for proper stackwalking of RuntimeStub frame
936 __ push(rsi);
937 __ push(rdi);
938 __ movptr(from , Address(rsp, 12+ 4));
939 __ movptr(to , Address(rsp, 12+ 8));
940 __ movl(count, Address(rsp, 12+ 12));
941
942 if (entry != NULL) {
943 *entry = __ pc(); // Entry point from conjoint arraycopy stub.
944 BLOCK_COMMENT("Entry:");
945 }
946
947 if (t == T_OBJECT) {
948 __ testl(count, count);
949 __ jcc(Assembler::zero, L_0_count);
950 gen_write_ref_array_pre_barrier(from, to, count, dest_uninitialized);
951 __ mov(saved_to, to); // save 'to'
952 }
953
954 __ subptr(to, from); // to --> to_from
955 __ cmpl(count, 2<<shift); // Short arrays (< 8 bytes) copy by element
956 __ jcc(Assembler::below, L_copy_4_bytes); // use unsigned cmp
957 if (!UseUnalignedLoadStores && !aligned && (t == T_BYTE || t == T_SHORT)) {
958 // align source address at 4 bytes address boundary
959 if (t == T_BYTE) {
960 // One byte misalignment happens only for byte arrays
961 __ testl(from, 1);
962 __ jccb(Assembler::zero, L_skip_align1);
963 __ movb(rax, Address(from, 0));
964 __ movb(Address(from, to_from, Address::times_1, 0), rax);
965 __ increment(from);
966 __ decrement(count);
967 __ BIND(L_skip_align1);
968 }
969 // Two bytes misalignment happens only for byte and short (char) arrays
970 __ testl(from, 2);
1109 if (entry != NULL) {
1110 *entry = __ pc(); // Entry point from generic arraycopy stub.
1111 BLOCK_COMMENT("Entry:");
1112 }
1113
1114 // nooverlap_target expects arguments in rsi and rdi.
1115 __ mov(from, src);
1116 __ mov(to , dst);
1117
1118 // arrays overlap test: dispatch to disjoint stub if necessary.
1119 RuntimeAddress nooverlap(nooverlap_target);
1120 __ cmpptr(dst, src);
1121 __ lea(end, Address(src, count, sf, 0)); // src + count * elem_size
1122 __ jump_cc(Assembler::belowEqual, nooverlap);
1123 __ cmpptr(dst, end);
1124 __ jump_cc(Assembler::aboveEqual, nooverlap);
1125
1126 if (t == T_OBJECT) {
1127 __ testl(count, count);
1128 __ jcc(Assembler::zero, L_0_count);
1129 gen_write_ref_array_pre_barrier(src, dst, count, dest_uninitialized);
1130 }
1131
1132 // copy from high to low
1133 __ cmpl(count, 2<<shift); // Short arrays (< 8 bytes) copy by element
1134 __ jcc(Assembler::below, L_copy_4_bytes); // use unsigned cmp
1135 if (t == T_BYTE || t == T_SHORT) {
1136 // Align the end of destination array at 4 bytes address boundary
1137 __ lea(end, Address(dst, count, sf, 0));
1138 if (t == T_BYTE) {
1139 // One byte misalignment happens only for byte arrays
1140 __ testl(end, 1);
1141 __ jccb(Assembler::zero, L_skip_align1);
1142 __ decrement(count);
1143 __ movb(rdx, Address(from, count, sf, 0));
1144 __ movb(Address(to, count, sf, 0), rdx);
1145 __ BIND(L_skip_align1);
1146 }
1147 // Two bytes misalignment happens only for byte and short (char) arrays
1148 __ testl(end, 2);
1149 __ jccb(Assembler::zero, L_skip_align2);
1456 // Assembler stub will be used for this call to arraycopy
1457 // if the two arrays are subtypes of Object[] but the
1458 // destination array type is not equal to or a supertype
1459 // of the source type. Each element must be separately
1460 // checked.
1461
1462 // Loop-invariant addresses. They are exclusive end pointers.
1463 Address end_from_addr(from, length, Address::times_ptr, 0);
1464 Address end_to_addr(to, length, Address::times_ptr, 0);
1465
1466 Register end_from = from; // re-use
1467 Register end_to = to; // re-use
1468 Register count = length; // re-use
1469
1470 // Loop-variant addresses. They assume post-incremented count < 0.
1471 Address from_element_addr(end_from, count, Address::times_ptr, 0);
1472 Address to_element_addr(end_to, count, Address::times_ptr, 0);
1473 Address elem_klass_addr(elem, oopDesc::klass_offset_in_bytes());
1474
1475 // Copy from low to high addresses, indexed from the end of each array.
1476 gen_write_ref_array_pre_barrier(from, to, count, dest_uninitialized);
1477 __ lea(end_from, end_from_addr);
1478 __ lea(end_to, end_to_addr);
1479 assert(length == count, ""); // else fix next line:
1480 __ negptr(count); // negate and test the length
1481 __ jccb(Assembler::notZero, L_load_element);
1482
1483 // Empty array: Nothing to do.
1484 __ xorptr(rax, rax); // return 0 on (trivial) success
1485 __ jmp(L_done);
1486
1487 // ======== begin loop ========
1488 // (Loop is rotated; its entry is L_load_element.)
1489 // Loop control:
1490 // for (count = -count; count != 0; count++)
1491 // Base pointers src, dst are biased by 8*count,to last element.
1492 __ align(OptoLoopAlignment);
1493
1494 __ BIND(L_store_element);
1495 __ movptr(to_element_addr, elem); // store the oop
1496 __ increment(count); // increment the count toward zero
1497 #if INCLUDE_ALL_GCS
1498 if (UseShenandoahGC) {
1499 // Shenandoah barrier is too big for 8-bit offsets to work
1500 __ jcc(Assembler::zero, L_do_card_marks);
1501 } else
1502 #endif
1503 __ jccb(Assembler::zero, L_do_card_marks);
1504
1505 // ======== loop entry is here ========
1506 __ BIND(L_load_element);
1507 #if INCLUDE_ALL_GCS
1508 if (UseShenandoahGC) {
1509 // Needs GC barriers
1510 __ load_heap_oop(elem, from_element_addr);
1511 } else
1512 #endif
1513 __ movptr(elem, from_element_addr); // load the oop
1514 __ testptr(elem, elem);
1515 #if INCLUDE_ALL_GCS
1516 if (UseShenandoahGC) {
1517 // Shenandoah barrier is too big for 8-bit offsets to work
1518 __ jcc(Assembler::zero, L_store_element);
1519 } else
1520 #endif
1521 __ jccb(Assembler::zero, L_store_element);
1522
1523 // (Could do a trick here: Remember last successful non-null
1524 // element stored and make a quick oop equality check on it.)
1525
1526 __ movptr(elem_klass, elem_klass_addr); // query the object klass
1527 generate_type_check(elem_klass, ckoff_arg, ckval_arg, temp,
1528 &L_store_element, NULL);
1529 // (On fall-through, we have failed the element type check.)
1530 // ======== end loop ========
1531
1532 // It was a real error; we must depend on the caller to finish the job.
1533 // Register "count" = -1 * number of *remaining* oops, length_arg = *total* oops.
1534 // Emit GC store barriers for the oops we have copied (length_arg + count),
1535 // and report their number to the caller.
1536 assert_different_registers(to, count, rax);
1537 Label L_post_barrier;
1538 __ addl(count, length_arg); // transfers = (length - remaining)
1539 __ movl2ptr(rax, count); // save the value
1540 __ notptr(rax); // report (-1^K) to caller (does not affect flags)
|