2759
2760 int flags = op->flags();
2761 BasicType basic_type = default_type != NULL ? default_type->element_type()->basic_type() : T_ILLEGAL;
2762 if (basic_type == T_ARRAY) basic_type = T_OBJECT;
2763
2764 // If we don't know anything or it's an object array, just go through the generic arraycopy
2765 if (default_type == NULL) {
2766
2767 // save arguments, because they will be killed by a runtime call
2768 save_in_reserved_area(R0, R1, R2, R3);
2769
2770 #ifdef AARCH64
2771 // save length argument, will be killed by a runtime call
2772 __ raw_push(length, ZR);
2773 #else
2774 // pass length argument on SP[0]
2775 __ str(length, Address(SP, -2*wordSize, pre_indexed)); // 2 words for a proper stack alignment
2776 #endif // AARCH64
2777
2778 address copyfunc_addr = StubRoutines::generic_arraycopy();
2779 if (copyfunc_addr == NULL) { // Use C version if stub was not generated
2780 __ call(CAST_FROM_FN_PTR(address, Runtime1::arraycopy));
2781 } else {
2782 #ifndef PRODUCT
2783 if (PrintC1Statistics) {
2784 __ inc_counter((address)&Runtime1::_generic_arraycopystub_cnt, tmp, tmp2);
2785 }
2786 #endif // !PRODUCT
2787 // the stub is in the code cache so close enough
2788 __ call(copyfunc_addr, relocInfo::runtime_call_type);
2789 }
2790
2791 #ifdef AARCH64
2792 __ raw_pop(length, ZR);
2793 #else
2794 __ add(SP, SP, 2*wordSize);
2795 #endif // AARCH64
2796
2797 __ cbz_32(R0, *stub->continuation());
2798
2799 if (copyfunc_addr != NULL) {
2800 __ mvn_32(tmp, R0);
2801 restore_from_reserved_area(R0, R1, R2, R3); // load saved arguments in slow case only
2802 __ sub_32(length, length, tmp);
2803 __ add_32(src_pos, src_pos, tmp);
2804 __ add_32(dst_pos, dst_pos, tmp);
2805 } else {
2806 restore_from_reserved_area(R0, R1, R2, R3); // load saved arguments in slow case only
2807 }
2808
2809 __ b(*stub->entry());
2810
2811 __ bind(*stub->continuation());
2812 return;
2813 }
2814
2815 assert(default_type != NULL && default_type->is_array_klass() && default_type->is_loaded(),
2816 "must be true at this point");
2817 int elem_size = type2aelembytes(basic_type);
2818 int shift = exact_log2(elem_size);
2819
2820 // Check for NULL
2821 if (flags & LIR_OpArrayCopy::src_null_check) {
2822 if (flags & LIR_OpArrayCopy::dst_null_check) {
2823 __ cmp(src, 0);
2824 __ cond_cmp(dst, 0, ne); // make one instruction shorter if both checks are needed
2825 __ b(*stub->entry(), eq);
2826 } else {
|
2759
2760 int flags = op->flags();
2761 BasicType basic_type = default_type != NULL ? default_type->element_type()->basic_type() : T_ILLEGAL;
2762 if (basic_type == T_ARRAY) basic_type = T_OBJECT;
2763
2764 // If we don't know anything or it's an object array, just go through the generic arraycopy
2765 if (default_type == NULL) {
2766
2767 // save arguments, because they will be killed by a runtime call
2768 save_in_reserved_area(R0, R1, R2, R3);
2769
2770 #ifdef AARCH64
2771 // save length argument, will be killed by a runtime call
2772 __ raw_push(length, ZR);
2773 #else
2774 // pass length argument on SP[0]
2775 __ str(length, Address(SP, -2*wordSize, pre_indexed)); // 2 words for a proper stack alignment
2776 #endif // AARCH64
2777
2778 address copyfunc_addr = StubRoutines::generic_arraycopy();
2779 assert(copyfunc_addr != NULL, "generic arraycopy stub required");
2780 #ifndef PRODUCT
2781 if (PrintC1Statistics) {
2782 __ inc_counter((address)&Runtime1::_generic_arraycopystub_cnt, tmp, tmp2);
2783 }
2784 #endif // !PRODUCT
2785 // the stub is in the code cache so close enough
2786 __ call(copyfunc_addr, relocInfo::runtime_call_type);
2787
2788 #ifdef AARCH64
2789 __ raw_pop(length, ZR);
2790 #else
2791 __ add(SP, SP, 2*wordSize);
2792 #endif // AARCH64
2793
2794 __ cbz_32(R0, *stub->continuation());
2795
2796 __ mvn_32(tmp, R0);
2797 restore_from_reserved_area(R0, R1, R2, R3); // load saved arguments in slow case only
2798 __ sub_32(length, length, tmp);
2799 __ add_32(src_pos, src_pos, tmp);
2800 __ add_32(dst_pos, dst_pos, tmp);
2801
2802 __ b(*stub->entry());
2803
2804 __ bind(*stub->continuation());
2805 return;
2806 }
2807
2808 assert(default_type != NULL && default_type->is_array_klass() && default_type->is_loaded(),
2809 "must be true at this point");
2810 int elem_size = type2aelembytes(basic_type);
2811 int shift = exact_log2(elem_size);
2812
2813 // Check for NULL
2814 if (flags & LIR_OpArrayCopy::src_null_check) {
2815 if (flags & LIR_OpArrayCopy::dst_null_check) {
2816 __ cmp(src, 0);
2817 __ cond_cmp(dst, 0, ne); // make one instruction shorter if both checks are needed
2818 __ b(*stub->entry(), eq);
2819 } else {
|