< prev index next >

src/cpu/x86/vm/stubGenerator_x86_32.cpp

Print this page




  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)


< prev index next >