changeset 35232 | 76aed99c0ddd |
parent 35166 | 23125410af16 |
parent 35156 | a06b3d7455d6 |
child 35546 | b75e269c0922 |
35231:e89989198037 | 35232:76aed99c0ddd |
---|---|
46 #define BLOCK_COMMENT(str) // nothing |
46 #define BLOCK_COMMENT(str) // nothing |
47 #else |
47 #else |
48 #define BLOCK_COMMENT(str) __ block_comment(str) |
48 #define BLOCK_COMMENT(str) __ block_comment(str) |
49 #endif |
49 #endif |
50 |
50 |
51 #if defined(ABI_ELFv2) |
|
52 #define STUB_ENTRY(name) StubRoutines::name() |
|
53 #else |
|
54 #define STUB_ENTRY(name) ((FunctionDescriptor*)StubRoutines::name())->entry() |
|
55 #endif |
|
56 |
|
51 class StubGenerator: public StubCodeGenerator { |
57 class StubGenerator: public StubCodeGenerator { |
52 private: |
58 private: |
53 |
59 |
54 // Call stubs are used to call Java from C |
60 // Call stubs are used to call Java from C |
55 // |
61 // |
250 // F1 [C_FRAME] |
256 // F1 [C_FRAME] |
251 // ... |
257 // ... |
252 // |
258 // |
253 |
259 |
254 // global toc register |
260 // global toc register |
255 __ load_const(R29, MacroAssembler::global_toc(), R11_scratch1); |
261 __ load_const_optimized(R29_TOC, MacroAssembler::global_toc(), R11_scratch1); |
256 |
|
257 // Remember the senderSP so we interpreter can pop c2i arguments off of the stack |
262 // Remember the senderSP so we interpreter can pop c2i arguments off of the stack |
258 // when called via a c2i. |
263 // when called via a c2i. |
259 |
264 |
260 // Pass initial_caller_sp to framemanager. |
265 // Pass initial_caller_sp to framemanager. |
261 __ mr(R21_tmp1, R1_SP); |
266 __ mr(R21_tmp1, R1_SP); |
610 // tmp - scratch register |
615 // tmp - scratch register |
611 // |
616 // |
612 // Kills: |
617 // Kills: |
613 // nothing |
618 // nothing |
614 // |
619 // |
615 void gen_write_ref_array_pre_barrier(Register from, Register to, Register count, bool dest_uninitialized, Register Rtmp1) { |
620 void gen_write_ref_array_pre_barrier(Register from, Register to, Register count, bool dest_uninitialized, Register Rtmp1, |
621 Register preserve1 = noreg, Register preserve2 = noreg) { |
|
616 BarrierSet* const bs = Universe::heap()->barrier_set(); |
622 BarrierSet* const bs = Universe::heap()->barrier_set(); |
617 switch (bs->kind()) { |
623 switch (bs->kind()) { |
618 case BarrierSet::G1SATBCTLogging: |
624 case BarrierSet::G1SATBCTLogging: |
619 // With G1, don't generate the call if we statically know that the target in uninitialized |
625 // With G1, don't generate the call if we statically know that the target in uninitialized |
620 if (!dest_uninitialized) { |
626 if (!dest_uninitialized) { |
621 const int spill_slots = 4 * wordSize; |
627 int spill_slots = 3; |
622 const int frame_size = frame::abi_reg_args_size + spill_slots; |
628 if (preserve1 != noreg) { spill_slots++; } |
629 if (preserve2 != noreg) { spill_slots++; } |
|
630 const int frame_size = align_size_up(frame::abi_reg_args_size + spill_slots * BytesPerWord, frame::alignment_in_bytes); |
|
623 Label filtered; |
631 Label filtered; |
624 |
632 |
625 // Is marking active? |
633 // Is marking active? |
626 if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) { |
634 if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) { |
627 __ lwz(Rtmp1, in_bytes(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_active()), R16_thread); |
635 __ lwz(Rtmp1, in_bytes(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_active()), R16_thread); |
631 } |
639 } |
632 __ cmpdi(CCR0, Rtmp1, 0); |
640 __ cmpdi(CCR0, Rtmp1, 0); |
633 __ beq(CCR0, filtered); |
641 __ beq(CCR0, filtered); |
634 |
642 |
635 __ save_LR_CR(R0); |
643 __ save_LR_CR(R0); |
636 __ push_frame_reg_args(spill_slots, R0); |
644 __ push_frame(frame_size, R0); |
637 __ std(from, frame_size - 1 * wordSize, R1_SP); |
645 int slot_nr = 0; |
638 __ std(to, frame_size - 2 * wordSize, R1_SP); |
646 __ std(from, frame_size - (++slot_nr) * wordSize, R1_SP); |
639 __ std(count, frame_size - 3 * wordSize, R1_SP); |
647 __ std(to, frame_size - (++slot_nr) * wordSize, R1_SP); |
648 __ std(count, frame_size - (++slot_nr) * wordSize, R1_SP); |
|
649 if (preserve1 != noreg) { __ std(preserve1, frame_size - (++slot_nr) * wordSize, R1_SP); } |
|
650 if (preserve2 != noreg) { __ std(preserve2, frame_size - (++slot_nr) * wordSize, R1_SP); } |
|
640 |
651 |
641 __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre), to, count); |
652 __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre), to, count); |
642 |
653 |
643 __ ld(from, frame_size - 1 * wordSize, R1_SP); |
654 slot_nr = 0; |
644 __ ld(to, frame_size - 2 * wordSize, R1_SP); |
655 __ ld(from, frame_size - (++slot_nr) * wordSize, R1_SP); |
645 __ ld(count, frame_size - 3 * wordSize, R1_SP); |
656 __ ld(to, frame_size - (++slot_nr) * wordSize, R1_SP); |
646 __ pop_frame(); |
657 __ ld(count, frame_size - (++slot_nr) * wordSize, R1_SP); |
658 if (preserve1 != noreg) { __ ld(preserve1, frame_size - (++slot_nr) * wordSize, R1_SP); } |
|
659 if (preserve2 != noreg) { __ ld(preserve2, frame_size - (++slot_nr) * wordSize, R1_SP); } |
|
660 __ addi(R1_SP, R1_SP, frame_size); // pop_frame() |
|
647 __ restore_LR_CR(R0); |
661 __ restore_LR_CR(R0); |
648 |
662 |
649 __ bind(filtered); |
663 __ bind(filtered); |
650 } |
664 } |
651 break; |
665 break; |
665 // count - register containing element count |
679 // count - register containing element count |
666 // tmp - scratch register |
680 // tmp - scratch register |
667 // |
681 // |
668 // The input registers and R0 are overwritten. |
682 // The input registers and R0 are overwritten. |
669 // |
683 // |
670 void gen_write_ref_array_post_barrier(Register addr, Register count, Register tmp, bool branchToEnd) { |
684 void gen_write_ref_array_post_barrier(Register addr, Register count, Register tmp, Register preserve = noreg) { |
671 BarrierSet* const bs = Universe::heap()->barrier_set(); |
685 BarrierSet* const bs = Universe::heap()->barrier_set(); |
672 |
686 |
673 switch (bs->kind()) { |
687 switch (bs->kind()) { |
674 case BarrierSet::G1SATBCTLogging: |
688 case BarrierSet::G1SATBCTLogging: |
675 { |
689 { |
676 if (branchToEnd) { |
690 int spill_slots = (preserve != noreg) ? 1 : 0; |
677 __ save_LR_CR(R0); |
691 const int frame_size = align_size_up(frame::abi_reg_args_size + spill_slots * BytesPerWord, frame::alignment_in_bytes); |
678 // We need this frame only to spill LR. |
692 |
679 __ push_frame_reg_args(0, R0); |
693 __ save_LR_CR(R0); |
680 __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post), addr, count); |
694 __ push_frame(frame_size, R0); |
681 __ pop_frame(); |
695 if (preserve != noreg) { __ std(preserve, frame_size - 1 * wordSize, R1_SP); } |
682 __ restore_LR_CR(R0); |
696 __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post), addr, count); |
683 } else { |
697 if (preserve != noreg) { __ ld(preserve, frame_size - 1 * wordSize, R1_SP); } |
684 // Tail call: fake call from stub caller by branching without linking. |
698 __ addi(R1_SP, R1_SP, frame_size); // pop_frame(); |
685 address entry_point = (address)CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post); |
699 __ restore_LR_CR(R0); |
686 __ mr_if_needed(R3_ARG1, addr); |
|
687 __ mr_if_needed(R4_ARG2, count); |
|
688 __ load_const(R11, entry_point, R0); |
|
689 __ call_c_and_return_to_caller(R11); |
|
690 } |
|
691 } |
700 } |
692 break; |
701 break; |
693 case BarrierSet::CardTableForRS: |
702 case BarrierSet::CardTableForRS: |
694 case BarrierSet::CardTableExtension: |
703 case BarrierSet::CardTableExtension: |
695 { |
704 { |
720 __ bind(Lstore_loop); |
729 __ bind(Lstore_loop); |
721 __ stbx(R0, tmp, addr); |
730 __ stbx(R0, tmp, addr); |
722 __ addi(addr, addr, 1); |
731 __ addi(addr, addr, 1); |
723 __ bdnz(Lstore_loop); |
732 __ bdnz(Lstore_loop); |
724 __ bind(Lskip_loop); |
733 __ bind(Lskip_loop); |
725 |
|
726 if (!branchToEnd) __ blr(); |
|
727 } |
734 } |
728 break; |
735 break; |
729 case BarrierSet::ModRef: |
736 case BarrierSet::ModRef: |
730 if (!branchToEnd) __ blr(); |
|
731 break; |
737 break; |
732 default: |
738 default: |
733 ShouldNotReachHere(); |
739 ShouldNotReachHere(); |
734 } |
740 } |
735 } |
741 } |
754 Register tmp2_reg = R6_ARG4; |
760 Register tmp2_reg = R6_ARG4; |
755 Register zero_reg = R7_ARG5; |
761 Register zero_reg = R7_ARG5; |
756 |
762 |
757 // Procedure for large arrays (uses data cache block zero instruction). |
763 // Procedure for large arrays (uses data cache block zero instruction). |
758 Label dwloop, fast, fastloop, restloop, lastdword, done; |
764 Label dwloop, fast, fastloop, restloop, lastdword, done; |
759 int cl_size=VM_Version::get_cache_line_size(), cl_dwords=cl_size>>3, cl_dwordaddr_bits=exact_log2(cl_dwords); |
765 int cl_size = VM_Version::L1_data_cache_line_size(); |
760 int min_dcbz=2; // Needs to be positive, apply dcbz only to at least min_dcbz cache lines. |
766 int cl_dwords = cl_size >> 3; |
767 int cl_dwordaddr_bits = exact_log2(cl_dwords); |
|
768 int min_dcbz = 2; // Needs to be positive, apply dcbz only to at least min_dcbz cache lines. |
|
761 |
769 |
762 // Clear up to 128byte boundary if long enough, dword_cnt=(16-(base>>3))%16. |
770 // Clear up to 128byte boundary if long enough, dword_cnt=(16-(base>>3))%16. |
763 __ dcbtst(base_ptr_reg); // Indicate write access to first cache line ... |
771 __ dcbtst(base_ptr_reg); // Indicate write access to first cache line ... |
764 __ andi(tmp2_reg, cnt_dwords_reg, 1); // to check if number of dwords is even. |
772 __ andi(tmp2_reg, cnt_dwords_reg, 1); // to check if number of dwords is even. |
765 __ srdi_(tmp1_reg, cnt_dwords_reg, 1); // number of double dwords |
773 __ srdi_(tmp1_reg, cnt_dwords_reg, 1); // number of double dwords |
1072 // |
1080 // |
1073 void array_overlap_test(address no_overlap_target, int log2_elem_size) { |
1081 void array_overlap_test(address no_overlap_target, int log2_elem_size) { |
1074 Register tmp1 = R6_ARG4; |
1082 Register tmp1 = R6_ARG4; |
1075 Register tmp2 = R7_ARG5; |
1083 Register tmp2 = R7_ARG5; |
1076 |
1084 |
1077 Label l_overlap; |
|
1078 #ifdef ASSERT |
1085 #ifdef ASSERT |
1079 __ srdi_(tmp2, R5_ARG3, 31); |
1086 __ srdi_(tmp2, R5_ARG3, 31); |
1080 __ asm_assert_eq("missing zero extend", 0xAFFE); |
1087 __ asm_assert_eq("missing zero extend", 0xAFFE); |
1081 #endif |
1088 #endif |
1082 |
1089 |
1083 __ subf(tmp1, R3_ARG1, R4_ARG2); // distance in bytes |
1090 __ subf(tmp1, R3_ARG1, R4_ARG2); // distance in bytes |
1084 __ sldi(tmp2, R5_ARG3, log2_elem_size); // size in bytes |
1091 __ sldi(tmp2, R5_ARG3, log2_elem_size); // size in bytes |
1085 __ cmpld(CCR0, R3_ARG1, R4_ARG2); // Use unsigned comparison! |
1092 __ cmpld(CCR0, R3_ARG1, R4_ARG2); // Use unsigned comparison! |
1086 __ cmpld(CCR1, tmp1, tmp2); |
1093 __ cmpld(CCR1, tmp1, tmp2); |
1087 __ crand(CCR0, Assembler::less, CCR1, Assembler::less); |
1094 __ crnand(CCR0, Assembler::less, CCR1, Assembler::less); |
1088 __ blt(CCR0, l_overlap); // Src before dst and distance smaller than size. |
1095 // Overlaps if Src before dst and distance smaller than size. |
1089 |
1096 // Branch to forward copy routine otherwise (within range of 32kB). |
1090 // need to copy forwards |
1097 __ bc(Assembler::bcondCRbiIs1, Assembler::bi0(CCR0, Assembler::less), no_overlap_target); |
1091 if (__ is_within_range_of_b(no_overlap_target, __ pc())) { |
1098 |
1092 __ b(no_overlap_target); |
|
1093 } else { |
|
1094 __ load_const(tmp1, no_overlap_target, tmp2); |
|
1095 __ mtctr(tmp1); |
|
1096 __ bctr(); |
|
1097 } |
|
1098 |
|
1099 __ bind(l_overlap); |
|
1100 // need to copy backwards |
1099 // need to copy backwards |
1101 } |
1100 } |
1102 |
1101 |
1103 // The guideline in the implementations of generate_disjoint_xxx_copy |
1102 // The guideline in the implementations of generate_disjoint_xxx_copy |
1104 // (xxx=byte,short,int,long,oop) is to copy as many elements as possible with |
1103 // (xxx=byte,short,int,long,oop) is to copy as many elements as possible with |
1239 __ stbu(tmp2, 1, R4_ARG2); |
1238 __ stbu(tmp2, 1, R4_ARG2); |
1240 __ bdnz(l_5); |
1239 __ bdnz(l_5); |
1241 } |
1240 } |
1242 |
1241 |
1243 __ bind(l_4); |
1242 __ bind(l_4); |
1243 __ li(R3_RET, 0); // return 0 |
|
1244 __ blr(); |
1244 __ blr(); |
1245 |
1245 |
1246 return start; |
1246 return start; |
1247 } |
1247 } |
1248 |
1248 |
1260 |
1260 |
1261 Register tmp1 = R6_ARG4; |
1261 Register tmp1 = R6_ARG4; |
1262 Register tmp2 = R7_ARG5; |
1262 Register tmp2 = R7_ARG5; |
1263 Register tmp3 = R8_ARG6; |
1263 Register tmp3 = R8_ARG6; |
1264 |
1264 |
1265 #if defined(ABI_ELFv2) |
|
1266 address nooverlap_target = aligned ? |
1265 address nooverlap_target = aligned ? |
1267 StubRoutines::arrayof_jbyte_disjoint_arraycopy() : |
1266 STUB_ENTRY(arrayof_jbyte_disjoint_arraycopy) : |
1268 StubRoutines::jbyte_disjoint_arraycopy(); |
1267 STUB_ENTRY(jbyte_disjoint_arraycopy); |
1269 #else |
|
1270 address nooverlap_target = aligned ? |
|
1271 ((FunctionDescriptor*)StubRoutines::arrayof_jbyte_disjoint_arraycopy())->entry() : |
|
1272 ((FunctionDescriptor*)StubRoutines::jbyte_disjoint_arraycopy())->entry(); |
|
1273 #endif |
|
1274 |
1268 |
1275 array_overlap_test(nooverlap_target, 0); |
1269 array_overlap_test(nooverlap_target, 0); |
1276 // Do reverse copy. We assume the case of actual overlap is rare enough |
1270 // Do reverse copy. We assume the case of actual overlap is rare enough |
1277 // that we don't have to optimize it. |
1271 // that we don't have to optimize it. |
1278 Label l_1, l_2; |
1272 Label l_1, l_2; |
1283 __ bind(l_2); |
1277 __ bind(l_2); |
1284 __ addic_(R5_ARG3, R5_ARG3, -1); |
1278 __ addic_(R5_ARG3, R5_ARG3, -1); |
1285 __ lbzx(tmp1, R3_ARG1, R5_ARG3); |
1279 __ lbzx(tmp1, R3_ARG1, R5_ARG3); |
1286 __ bge(CCR0, l_1); |
1280 __ bge(CCR0, l_1); |
1287 |
1281 |
1282 __ li(R3_RET, 0); // return 0 |
|
1288 __ blr(); |
1283 __ blr(); |
1289 |
1284 |
1290 return start; |
1285 return start; |
1291 } |
1286 } |
1292 |
1287 |
1465 __ lhzu(tmp2, 2, R3_ARG1); |
1460 __ lhzu(tmp2, 2, R3_ARG1); |
1466 __ sthu(tmp2, 2, R4_ARG2); |
1461 __ sthu(tmp2, 2, R4_ARG2); |
1467 __ bdnz(l_5); |
1462 __ bdnz(l_5); |
1468 } |
1463 } |
1469 __ bind(l_4); |
1464 __ bind(l_4); |
1465 __ li(R3_RET, 0); // return 0 |
|
1470 __ blr(); |
1466 __ blr(); |
1471 |
1467 |
1472 return start; |
1468 return start; |
1473 } |
1469 } |
1474 |
1470 |
1486 |
1482 |
1487 Register tmp1 = R6_ARG4; |
1483 Register tmp1 = R6_ARG4; |
1488 Register tmp2 = R7_ARG5; |
1484 Register tmp2 = R7_ARG5; |
1489 Register tmp3 = R8_ARG6; |
1485 Register tmp3 = R8_ARG6; |
1490 |
1486 |
1491 #if defined(ABI_ELFv2) |
|
1492 address nooverlap_target = aligned ? |
1487 address nooverlap_target = aligned ? |
1493 StubRoutines::arrayof_jshort_disjoint_arraycopy() : |
1488 STUB_ENTRY(arrayof_jshort_disjoint_arraycopy) : |
1494 StubRoutines::jshort_disjoint_arraycopy(); |
1489 STUB_ENTRY(jshort_disjoint_arraycopy); |
1495 #else |
|
1496 address nooverlap_target = aligned ? |
|
1497 ((FunctionDescriptor*)StubRoutines::arrayof_jshort_disjoint_arraycopy())->entry() : |
|
1498 ((FunctionDescriptor*)StubRoutines::jshort_disjoint_arraycopy())->entry(); |
|
1499 #endif |
|
1500 |
1490 |
1501 array_overlap_test(nooverlap_target, 1); |
1491 array_overlap_test(nooverlap_target, 1); |
1502 |
1492 |
1503 Label l_1, l_2; |
1493 Label l_1, l_2; |
1504 __ sldi(tmp1, R5_ARG3, 1); |
1494 __ sldi(tmp1, R5_ARG3, 1); |
1508 __ bind(l_2); |
1498 __ bind(l_2); |
1509 __ addic_(tmp1, tmp1, -2); |
1499 __ addic_(tmp1, tmp1, -2); |
1510 __ lhzx(tmp2, R3_ARG1, tmp1); |
1500 __ lhzx(tmp2, R3_ARG1, tmp1); |
1511 __ bge(CCR0, l_1); |
1501 __ bge(CCR0, l_1); |
1512 |
1502 |
1503 __ li(R3_RET, 0); // return 0 |
|
1513 __ blr(); |
1504 __ blr(); |
1514 |
1505 |
1515 return start; |
1506 return start; |
1516 } |
1507 } |
1517 |
1508 |
1611 // |
1602 // |
1612 address generate_disjoint_int_copy(bool aligned, const char * name) { |
1603 address generate_disjoint_int_copy(bool aligned, const char * name) { |
1613 StubCodeMark mark(this, "StubRoutines", name); |
1604 StubCodeMark mark(this, "StubRoutines", name); |
1614 address start = __ function_entry(); |
1605 address start = __ function_entry(); |
1615 generate_disjoint_int_copy_core(aligned); |
1606 generate_disjoint_int_copy_core(aligned); |
1607 __ li(R3_RET, 0); // return 0 |
|
1616 __ blr(); |
1608 __ blr(); |
1617 return start; |
1609 return start; |
1618 } |
1610 } |
1619 |
1611 |
1620 // Generate core code for conjoint int copy (and oop copy on |
1612 // Generate core code for conjoint int copy (and oop copy on |
1695 // |
1687 // |
1696 address generate_conjoint_int_copy(bool aligned, const char * name) { |
1688 address generate_conjoint_int_copy(bool aligned, const char * name) { |
1697 StubCodeMark mark(this, "StubRoutines", name); |
1689 StubCodeMark mark(this, "StubRoutines", name); |
1698 address start = __ function_entry(); |
1690 address start = __ function_entry(); |
1699 |
1691 |
1700 #if defined(ABI_ELFv2) |
|
1701 address nooverlap_target = aligned ? |
1692 address nooverlap_target = aligned ? |
1702 StubRoutines::arrayof_jint_disjoint_arraycopy() : |
1693 STUB_ENTRY(arrayof_jint_disjoint_arraycopy) : |
1703 StubRoutines::jint_disjoint_arraycopy(); |
1694 STUB_ENTRY(jint_disjoint_arraycopy); |
1704 #else |
|
1705 address nooverlap_target = aligned ? |
|
1706 ((FunctionDescriptor*)StubRoutines::arrayof_jint_disjoint_arraycopy())->entry() : |
|
1707 ((FunctionDescriptor*)StubRoutines::jint_disjoint_arraycopy())->entry(); |
|
1708 #endif |
|
1709 |
1695 |
1710 array_overlap_test(nooverlap_target, 2); |
1696 array_overlap_test(nooverlap_target, 2); |
1711 |
1697 |
1712 generate_conjoint_int_copy_core(aligned); |
1698 generate_conjoint_int_copy_core(aligned); |
1713 |
1699 |
1700 __ li(R3_RET, 0); // return 0 |
|
1714 __ blr(); |
1701 __ blr(); |
1715 |
1702 |
1716 return start; |
1703 return start; |
1717 } |
1704 } |
1718 |
1705 |
1787 // |
1774 // |
1788 address generate_disjoint_long_copy(bool aligned, const char * name) { |
1775 address generate_disjoint_long_copy(bool aligned, const char * name) { |
1789 StubCodeMark mark(this, "StubRoutines", name); |
1776 StubCodeMark mark(this, "StubRoutines", name); |
1790 address start = __ function_entry(); |
1777 address start = __ function_entry(); |
1791 generate_disjoint_long_copy_core(aligned); |
1778 generate_disjoint_long_copy_core(aligned); |
1779 __ li(R3_RET, 0); // return 0 |
|
1792 __ blr(); |
1780 __ blr(); |
1793 |
1781 |
1794 return start; |
1782 return start; |
1795 } |
1783 } |
1796 |
1784 |
1869 // |
1857 // |
1870 address generate_conjoint_long_copy(bool aligned, const char * name) { |
1858 address generate_conjoint_long_copy(bool aligned, const char * name) { |
1871 StubCodeMark mark(this, "StubRoutines", name); |
1859 StubCodeMark mark(this, "StubRoutines", name); |
1872 address start = __ function_entry(); |
1860 address start = __ function_entry(); |
1873 |
1861 |
1874 #if defined(ABI_ELFv2) |
|
1875 address nooverlap_target = aligned ? |
1862 address nooverlap_target = aligned ? |
1876 StubRoutines::arrayof_jlong_disjoint_arraycopy() : |
1863 STUB_ENTRY(arrayof_jlong_disjoint_arraycopy) : |
1877 StubRoutines::jlong_disjoint_arraycopy(); |
1864 STUB_ENTRY(jlong_disjoint_arraycopy); |
1878 #else |
|
1879 address nooverlap_target = aligned ? |
|
1880 ((FunctionDescriptor*)StubRoutines::arrayof_jlong_disjoint_arraycopy())->entry() : |
|
1881 ((FunctionDescriptor*)StubRoutines::jlong_disjoint_arraycopy())->entry(); |
|
1882 #endif |
|
1883 |
1865 |
1884 array_overlap_test(nooverlap_target, 3); |
1866 array_overlap_test(nooverlap_target, 3); |
1885 generate_conjoint_long_copy_core(aligned); |
1867 generate_conjoint_long_copy_core(aligned); |
1886 |
1868 |
1869 __ li(R3_RET, 0); // return 0 |
|
1887 __ blr(); |
1870 __ blr(); |
1888 |
1871 |
1889 return start; |
1872 return start; |
1890 } |
1873 } |
1891 |
1874 |
1901 address generate_conjoint_oop_copy(bool aligned, const char * name, bool dest_uninitialized) { |
1884 address generate_conjoint_oop_copy(bool aligned, const char * name, bool dest_uninitialized) { |
1902 StubCodeMark mark(this, "StubRoutines", name); |
1885 StubCodeMark mark(this, "StubRoutines", name); |
1903 |
1886 |
1904 address start = __ function_entry(); |
1887 address start = __ function_entry(); |
1905 |
1888 |
1906 #if defined(ABI_ELFv2) |
|
1907 address nooverlap_target = aligned ? |
1889 address nooverlap_target = aligned ? |
1908 StubRoutines::arrayof_oop_disjoint_arraycopy() : |
1890 STUB_ENTRY(arrayof_oop_disjoint_arraycopy) : |
1909 StubRoutines::oop_disjoint_arraycopy(); |
1891 STUB_ENTRY(oop_disjoint_arraycopy); |
1910 #else |
|
1911 address nooverlap_target = aligned ? |
|
1912 ((FunctionDescriptor*)StubRoutines::arrayof_oop_disjoint_arraycopy())->entry() : |
|
1913 ((FunctionDescriptor*)StubRoutines::oop_disjoint_arraycopy())->entry(); |
|
1914 #endif |
|
1915 |
1892 |
1916 gen_write_ref_array_pre_barrier(R3_ARG1, R4_ARG2, R5_ARG3, dest_uninitialized, R9_ARG7); |
1893 gen_write_ref_array_pre_barrier(R3_ARG1, R4_ARG2, R5_ARG3, dest_uninitialized, R9_ARG7); |
1917 |
1894 |
1918 // Save arguments. |
1895 // Save arguments. |
1919 __ mr(R9_ARG7, R4_ARG2); |
1896 __ mr(R9_ARG7, R4_ARG2); |
1925 } else { |
1902 } else { |
1926 array_overlap_test(nooverlap_target, 3); |
1903 array_overlap_test(nooverlap_target, 3); |
1927 generate_conjoint_long_copy_core(aligned); |
1904 generate_conjoint_long_copy_core(aligned); |
1928 } |
1905 } |
1929 |
1906 |
1930 gen_write_ref_array_post_barrier(R9_ARG7, R10_ARG8, R11_scratch1, /*branchToEnd*/ false); |
1907 gen_write_ref_array_post_barrier(R9_ARG7, R10_ARG8, R11_scratch1); |
1908 __ li(R3_RET, 0); // return 0 |
|
1909 __ blr(); |
|
1931 return start; |
1910 return start; |
1932 } |
1911 } |
1933 |
1912 |
1934 // Generate stub for disjoint oop copy. If "aligned" is true, the |
1913 // Generate stub for disjoint oop copy. If "aligned" is true, the |
1935 // "from" and "to" addresses are assumed to be heapword aligned. |
1914 // "from" and "to" addresses are assumed to be heapword aligned. |
1955 generate_disjoint_int_copy_core(aligned); |
1934 generate_disjoint_int_copy_core(aligned); |
1956 } else { |
1935 } else { |
1957 generate_disjoint_long_copy_core(aligned); |
1936 generate_disjoint_long_copy_core(aligned); |
1958 } |
1937 } |
1959 |
1938 |
1960 gen_write_ref_array_post_barrier(R9_ARG7, R10_ARG8, R11_scratch1, /*branchToEnd*/ false); |
1939 gen_write_ref_array_post_barrier(R9_ARG7, R10_ARG8, R11_scratch1); |
1940 __ li(R3_RET, 0); // return 0 |
|
1941 __ blr(); |
|
1961 |
1942 |
1962 return start; |
1943 return start; |
1963 } |
1944 } |
1945 |
|
1946 |
|
1947 // Helper for generating a dynamic type check. |
|
1948 // Smashes only the given temp registers. |
|
1949 void generate_type_check(Register sub_klass, |
|
1950 Register super_check_offset, |
|
1951 Register super_klass, |
|
1952 Register temp, |
|
1953 Label& L_success) { |
|
1954 assert_different_registers(sub_klass, super_check_offset, super_klass); |
|
1955 |
|
1956 BLOCK_COMMENT("type_check:"); |
|
1957 |
|
1958 Label L_miss; |
|
1959 |
|
1960 __ check_klass_subtype_fast_path(sub_klass, super_klass, temp, R0, &L_success, &L_miss, NULL, |
|
1961 super_check_offset); |
|
1962 __ check_klass_subtype_slow_path(sub_klass, super_klass, temp, R0, &L_success, NULL); |
|
1963 |
|
1964 // Fall through on failure! |
|
1965 __ bind(L_miss); |
|
1966 } |
|
1967 |
|
1968 |
|
1969 // Generate stub for checked oop copy. |
|
1970 // |
|
1971 // Arguments for generated stub: |
|
1972 // from: R3 |
|
1973 // to: R4 |
|
1974 // count: R5 treated as signed |
|
1975 // ckoff: R6 (super_check_offset) |
|
1976 // ckval: R7 (super_klass) |
|
1977 // ret: R3 zero for success; (-1^K) where K is partial transfer count |
|
1978 // |
|
1979 address generate_checkcast_copy(const char *name, bool dest_uninitialized) { |
|
1980 |
|
1981 const Register R3_from = R3_ARG1; // source array address |
|
1982 const Register R4_to = R4_ARG2; // destination array address |
|
1983 const Register R5_count = R5_ARG3; // elements count |
|
1984 const Register R6_ckoff = R6_ARG4; // super_check_offset |
|
1985 const Register R7_ckval = R7_ARG5; // super_klass |
|
1986 |
|
1987 const Register R8_offset = R8_ARG6; // loop var, with stride wordSize |
|
1988 const Register R9_remain = R9_ARG7; // loop var, with stride -1 |
|
1989 const Register R10_oop = R10_ARG8; // actual oop copied |
|
1990 const Register R11_klass = R11_scratch1; // oop._klass |
|
1991 const Register R12_tmp = R12_scratch2; |
|
1992 |
|
1993 const Register R2_minus1 = R2; |
|
1994 |
|
1995 //__ align(CodeEntryAlignment); |
|
1996 StubCodeMark mark(this, "StubRoutines", name); |
|
1997 address start = __ function_entry(); |
|
1998 |
|
1999 // TODO: Assert that int is 64 bit sign extended and arrays are not conjoint. |
|
2000 |
|
2001 gen_write_ref_array_pre_barrier(R3_from, R4_to, R5_count, dest_uninitialized, R12_tmp, /* preserve: */ R6_ckoff, R7_ckval); |
|
2002 |
|
2003 //inc_counter_np(SharedRuntime::_checkcast_array_copy_ctr, R12_tmp, R3_RET); |
|
2004 |
|
2005 Label load_element, store_element, store_null, success, do_card_marks; |
|
2006 __ or_(R9_remain, R5_count, R5_count); // Initialize loop index, and test it. |
|
2007 __ li(R8_offset, 0); // Offset from start of arrays. |
|
2008 __ li(R2_minus1, -1); |
|
2009 __ bne(CCR0, load_element); |
|
2010 |
|
2011 // Empty array: Nothing to do. |
|
2012 __ li(R3_RET, 0); // Return 0 on (trivial) success. |
|
2013 __ blr(); |
|
2014 |
|
2015 // ======== begin loop ======== |
|
2016 // (Entry is load_element.) |
|
2017 __ align(OptoLoopAlignment); |
|
2018 __ bind(store_element); |
|
2019 if (UseCompressedOops) { |
|
2020 __ encode_heap_oop_not_null(R10_oop); |
|
2021 __ bind(store_null); |
|
2022 __ stw(R10_oop, R8_offset, R4_to); |
|
2023 } else { |
|
2024 __ bind(store_null); |
|
2025 __ std(R10_oop, R8_offset, R4_to); |
|
2026 } |
|
2027 |
|
2028 __ addi(R8_offset, R8_offset, heapOopSize); // Step to next offset. |
|
2029 __ add_(R9_remain, R2_minus1, R9_remain); // Decrement the count. |
|
2030 __ beq(CCR0, success); |
|
2031 |
|
2032 // ======== loop entry is here ======== |
|
2033 __ bind(load_element); |
|
2034 __ load_heap_oop(R10_oop, R8_offset, R3_from, &store_null); // Load the oop. |
|
2035 |
|
2036 __ load_klass(R11_klass, R10_oop); // Query the object klass. |
|
2037 |
|
2038 generate_type_check(R11_klass, R6_ckoff, R7_ckval, R12_tmp, |
|
2039 // Branch to this on success: |
|
2040 store_element); |
|
2041 // ======== end loop ======== |
|
2042 |
|
2043 // It was a real error; we must depend on the caller to finish the job. |
|
2044 // Register R9_remain has number of *remaining* oops, R5_count number of *total* oops. |
|
2045 // Emit GC store barriers for the oops we have copied (R5_count minus R9_remain), |
|
2046 // and report their number to the caller. |
|
2047 __ subf_(R5_count, R9_remain, R5_count); |
|
2048 __ nand(R3_RET, R5_count, R5_count); // report (-1^K) to caller |
|
2049 __ bne(CCR0, do_card_marks); |
|
2050 __ blr(); |
|
2051 |
|
2052 __ bind(success); |
|
2053 __ li(R3_RET, 0); |
|
2054 |
|
2055 __ bind(do_card_marks); |
|
2056 // Store check on R4_to[0..R5_count-1]. |
|
2057 gen_write_ref_array_post_barrier(R4_to, R5_count, R12_tmp, /* preserve: */ R3_RET); |
|
2058 __ blr(); |
|
2059 return start; |
|
2060 } |
|
2061 |
|
2062 |
|
2063 // Generate 'unsafe' array copy stub. |
|
2064 // Though just as safe as the other stubs, it takes an unscaled |
|
2065 // size_t argument instead of an element count. |
|
2066 // |
|
2067 // Arguments for generated stub: |
|
2068 // from: R3 |
|
2069 // to: R4 |
|
2070 // count: R5 byte count, treated as ssize_t, can be zero |
|
2071 // |
|
2072 // Examines the alignment of the operands and dispatches |
|
2073 // to a long, int, short, or byte copy loop. |
|
2074 // |
|
2075 address generate_unsafe_copy(const char* name, |
|
2076 address byte_copy_entry, |
|
2077 address short_copy_entry, |
|
2078 address int_copy_entry, |
|
2079 address long_copy_entry) { |
|
2080 |
|
2081 const Register R3_from = R3_ARG1; // source array address |
|
2082 const Register R4_to = R4_ARG2; // destination array address |
|
2083 const Register R5_count = R5_ARG3; // elements count (as long on PPC64) |
|
2084 |
|
2085 const Register R6_bits = R6_ARG4; // test copy of low bits |
|
2086 const Register R7_tmp = R7_ARG5; |
|
2087 |
|
2088 //__ align(CodeEntryAlignment); |
|
2089 StubCodeMark mark(this, "StubRoutines", name); |
|
2090 address start = __ function_entry(); |
|
2091 |
|
2092 // Bump this on entry, not on exit: |
|
2093 //inc_counter_np(SharedRuntime::_unsafe_array_copy_ctr, R6_bits, R7_tmp); |
|
2094 |
|
2095 Label short_copy, int_copy, long_copy; |
|
2096 |
|
2097 __ orr(R6_bits, R3_from, R4_to); |
|
2098 __ orr(R6_bits, R6_bits, R5_count); |
|
2099 __ andi_(R0, R6_bits, (BytesPerLong-1)); |
|
2100 __ beq(CCR0, long_copy); |
|
2101 |
|
2102 __ andi_(R0, R6_bits, (BytesPerInt-1)); |
|
2103 __ beq(CCR0, int_copy); |
|
2104 |
|
2105 __ andi_(R0, R6_bits, (BytesPerShort-1)); |
|
2106 __ beq(CCR0, short_copy); |
|
2107 |
|
2108 // byte_copy: |
|
2109 __ b(byte_copy_entry); |
|
2110 |
|
2111 __ bind(short_copy); |
|
2112 __ srwi(R5_count, R5_count, LogBytesPerShort); |
|
2113 __ b(short_copy_entry); |
|
2114 |
|
2115 __ bind(int_copy); |
|
2116 __ srwi(R5_count, R5_count, LogBytesPerInt); |
|
2117 __ b(int_copy_entry); |
|
2118 |
|
2119 __ bind(long_copy); |
|
2120 __ srwi(R5_count, R5_count, LogBytesPerLong); |
|
2121 __ b(long_copy_entry); |
|
2122 |
|
2123 return start; |
|
2124 } |
|
2125 |
|
2126 |
|
2127 // Perform range checks on the proposed arraycopy. |
|
2128 // Kills the two temps, but nothing else. |
|
2129 // Also, clean the sign bits of src_pos and dst_pos. |
|
2130 void arraycopy_range_checks(Register src, // source array oop |
|
2131 Register src_pos, // source position |
|
2132 Register dst, // destination array oop |
|
2133 Register dst_pos, // destination position |
|
2134 Register length, // length of copy |
|
2135 Register temp1, Register temp2, |
|
2136 Label& L_failed) { |
|
2137 BLOCK_COMMENT("arraycopy_range_checks:"); |
|
2138 |
|
2139 const Register array_length = temp1; // scratch |
|
2140 const Register end_pos = temp2; // scratch |
|
2141 |
|
2142 // if (src_pos + length > arrayOop(src)->length() ) FAIL; |
|
2143 __ lwa(array_length, arrayOopDesc::length_offset_in_bytes(), src); |
|
2144 __ add(end_pos, src_pos, length); // src_pos + length |
|
2145 __ cmpd(CCR0, end_pos, array_length); |
|
2146 __ bgt(CCR0, L_failed); |
|
2147 |
|
2148 // if (dst_pos + length > arrayOop(dst)->length() ) FAIL; |
|
2149 __ lwa(array_length, arrayOopDesc::length_offset_in_bytes(), dst); |
|
2150 __ add(end_pos, dst_pos, length); // src_pos + length |
|
2151 __ cmpd(CCR0, end_pos, array_length); |
|
2152 __ bgt(CCR0, L_failed); |
|
2153 |
|
2154 BLOCK_COMMENT("arraycopy_range_checks done"); |
|
2155 } |
|
2156 |
|
2157 |
|
2158 // |
|
2159 // Generate generic array copy stubs |
|
2160 // |
|
2161 // Input: |
|
2162 // R3 - src oop |
|
2163 // R4 - src_pos |
|
2164 // R5 - dst oop |
|
2165 // R6 - dst_pos |
|
2166 // R7 - element count |
|
2167 // |
|
2168 // Output: |
|
2169 // R3 == 0 - success |
|
2170 // R3 == -1 - need to call System.arraycopy |
|
2171 // |
|
2172 address generate_generic_copy(const char *name, |
|
2173 address entry_jbyte_arraycopy, |
|
2174 address entry_jshort_arraycopy, |
|
2175 address entry_jint_arraycopy, |
|
2176 address entry_oop_arraycopy, |
|
2177 address entry_disjoint_oop_arraycopy, |
|
2178 address entry_jlong_arraycopy, |
|
2179 address entry_checkcast_arraycopy) { |
|
2180 Label L_failed, L_objArray; |
|
2181 |
|
2182 // Input registers |
|
2183 const Register src = R3_ARG1; // source array oop |
|
2184 const Register src_pos = R4_ARG2; // source position |
|
2185 const Register dst = R5_ARG3; // destination array oop |
|
2186 const Register dst_pos = R6_ARG4; // destination position |
|
2187 const Register length = R7_ARG5; // elements count |
|
2188 |
|
2189 // registers used as temp |
|
2190 const Register src_klass = R8_ARG6; // source array klass |
|
2191 const Register dst_klass = R9_ARG7; // destination array klass |
|
2192 const Register lh = R10_ARG8; // layout handler |
|
2193 const Register temp = R2; |
|
2194 |
|
2195 //__ align(CodeEntryAlignment); |
|
2196 StubCodeMark mark(this, "StubRoutines", name); |
|
2197 address start = __ function_entry(); |
|
2198 |
|
2199 // Bump this on entry, not on exit: |
|
2200 //inc_counter_np(SharedRuntime::_generic_array_copy_ctr, lh, temp); |
|
2201 |
|
2202 // In principle, the int arguments could be dirty. |
|
2203 |
|
2204 //----------------------------------------------------------------------- |
|
2205 // Assembler stubs will be used for this call to arraycopy |
|
2206 // if the following conditions are met: |
|
2207 // |
|
2208 // (1) src and dst must not be null. |
|
2209 // (2) src_pos must not be negative. |
|
2210 // (3) dst_pos must not be negative. |
|
2211 // (4) length must not be negative. |
|
2212 // (5) src klass and dst klass should be the same and not NULL. |
|
2213 // (6) src and dst should be arrays. |
|
2214 // (7) src_pos + length must not exceed length of src. |
|
2215 // (8) dst_pos + length must not exceed length of dst. |
|
2216 BLOCK_COMMENT("arraycopy initial argument checks"); |
|
2217 |
|
2218 __ cmpdi(CCR1, src, 0); // if (src == NULL) return -1; |
|
2219 __ extsw_(src_pos, src_pos); // if (src_pos < 0) return -1; |
|
2220 __ cmpdi(CCR5, dst, 0); // if (dst == NULL) return -1; |
|
2221 __ cror(CCR1, Assembler::equal, CCR0, Assembler::less); |
|
2222 __ extsw_(dst_pos, dst_pos); // if (src_pos < 0) return -1; |
|
2223 __ cror(CCR5, Assembler::equal, CCR0, Assembler::less); |
|
2224 __ extsw_(length, length); // if (length < 0) return -1; |
|
2225 __ cror(CCR1, Assembler::equal, CCR5, Assembler::equal); |
|
2226 __ cror(CCR1, Assembler::equal, CCR0, Assembler::less); |
|
2227 __ beq(CCR1, L_failed); |
|
2228 |
|
2229 BLOCK_COMMENT("arraycopy argument klass checks"); |
|
2230 __ load_klass(src_klass, src); |
|
2231 __ load_klass(dst_klass, dst); |
|
2232 |
|
2233 // Load layout helper |
|
2234 // |
|
2235 // |array_tag| | header_size | element_type | |log2_element_size| |
|
2236 // 32 30 24 16 8 2 0 |
|
2237 // |
|
2238 // array_tag: typeArray = 0x3, objArray = 0x2, non-array = 0x0 |
|
2239 // |
|
2240 |
|
2241 int lh_offset = in_bytes(Klass::layout_helper_offset()); |
|
2242 |
|
2243 // Load 32-bits signed value. Use br() instruction with it to check icc. |
|
2244 __ lwz(lh, lh_offset, src_klass); |
|
2245 |
|
2246 // Handle objArrays completely differently... |
|
2247 jint objArray_lh = Klass::array_layout_helper(T_OBJECT); |
|
2248 __ load_const_optimized(temp, objArray_lh, R0); |
|
2249 __ cmpw(CCR0, lh, temp); |
|
2250 __ beq(CCR0, L_objArray); |
|
2251 |
|
2252 __ cmpd(CCR5, src_klass, dst_klass); // if (src->klass() != dst->klass()) return -1; |
|
2253 __ cmpwi(CCR6, lh, Klass::_lh_neutral_value); // if (!src->is_Array()) return -1; |
|
2254 |
|
2255 __ crnand(CCR5, Assembler::equal, CCR6, Assembler::less); |
|
2256 __ beq(CCR5, L_failed); |
|
2257 |
|
2258 // At this point, it is known to be a typeArray (array_tag 0x3). |
|
2259 #ifdef ASSERT |
|
2260 { Label L; |
|
2261 jint lh_prim_tag_in_place = (Klass::_lh_array_tag_type_value << Klass::_lh_array_tag_shift); |
|
2262 __ load_const_optimized(temp, lh_prim_tag_in_place, R0); |
|
2263 __ cmpw(CCR0, lh, temp); |
|
2264 __ bge(CCR0, L); |
|
2265 __ stop("must be a primitive array"); |
|
2266 __ bind(L); |
|
2267 } |
|
2268 #endif |
|
2269 |
|
2270 arraycopy_range_checks(src, src_pos, dst, dst_pos, length, |
|
2271 temp, dst_klass, L_failed); |
|
2272 |
|
2273 // TypeArrayKlass |
|
2274 // |
|
2275 // src_addr = (src + array_header_in_bytes()) + (src_pos << log2elemsize); |
|
2276 // dst_addr = (dst + array_header_in_bytes()) + (dst_pos << log2elemsize); |
|
2277 // |
|
2278 |
|
2279 const Register offset = dst_klass; // array offset |
|
2280 const Register elsize = src_klass; // log2 element size |
|
2281 |
|
2282 __ rldicl(offset, lh, 64 - Klass::_lh_header_size_shift, 64 - exact_log2(Klass::_lh_header_size_mask + 1)); |
|
2283 __ andi(elsize, lh, Klass::_lh_log2_element_size_mask); |
|
2284 __ add(src, offset, src); // src array offset |
|
2285 __ add(dst, offset, dst); // dst array offset |
|
2286 |
|
2287 // Next registers should be set before the jump to corresponding stub. |
|
2288 const Register from = R3_ARG1; // source array address |
|
2289 const Register to = R4_ARG2; // destination array address |
|
2290 const Register count = R5_ARG3; // elements count |
|
2291 |
|
2292 // 'from', 'to', 'count' registers should be set in this order |
|
2293 // since they are the same as 'src', 'src_pos', 'dst'. |
|
2294 |
|
2295 BLOCK_COMMENT("scale indexes to element size"); |
|
2296 __ sld(src_pos, src_pos, elsize); |
|
2297 __ sld(dst_pos, dst_pos, elsize); |
|
2298 __ add(from, src_pos, src); // src_addr |
|
2299 __ add(to, dst_pos, dst); // dst_addr |
|
2300 __ mr(count, length); // length |
|
2301 |
|
2302 BLOCK_COMMENT("choose copy loop based on element size"); |
|
2303 // Using conditional branches with range 32kB. |
|
2304 const int bo = Assembler::bcondCRbiIs1, bi = Assembler::bi0(CCR0, Assembler::equal); |
|
2305 __ cmpwi(CCR0, elsize, 0); |
|
2306 __ bc(bo, bi, entry_jbyte_arraycopy); |
|
2307 __ cmpwi(CCR0, elsize, LogBytesPerShort); |
|
2308 __ bc(bo, bi, entry_jshort_arraycopy); |
|
2309 __ cmpwi(CCR0, elsize, LogBytesPerInt); |
|
2310 __ bc(bo, bi, entry_jint_arraycopy); |
|
2311 #ifdef ASSERT |
|
2312 { Label L; |
|
2313 __ cmpwi(CCR0, elsize, LogBytesPerLong); |
|
2314 __ beq(CCR0, L); |
|
2315 __ stop("must be long copy, but elsize is wrong"); |
|
2316 __ bind(L); |
|
2317 } |
|
2318 #endif |
|
2319 __ b(entry_jlong_arraycopy); |
|
2320 |
|
2321 // ObjArrayKlass |
|
2322 __ bind(L_objArray); |
|
2323 // live at this point: src_klass, dst_klass, src[_pos], dst[_pos], length |
|
2324 |
|
2325 Label L_disjoint_plain_copy, L_checkcast_copy; |
|
2326 // test array classes for subtyping |
|
2327 __ cmpd(CCR0, src_klass, dst_klass); // usual case is exact equality |
|
2328 __ bne(CCR0, L_checkcast_copy); |
|
2329 |
|
2330 // Identically typed arrays can be copied without element-wise checks. |
|
2331 arraycopy_range_checks(src, src_pos, dst, dst_pos, length, |
|
2332 temp, lh, L_failed); |
|
2333 |
|
2334 __ addi(src, src, arrayOopDesc::base_offset_in_bytes(T_OBJECT)); //src offset |
|
2335 __ addi(dst, dst, arrayOopDesc::base_offset_in_bytes(T_OBJECT)); //dst offset |
|
2336 __ sldi(src_pos, src_pos, LogBytesPerHeapOop); |
|
2337 __ sldi(dst_pos, dst_pos, LogBytesPerHeapOop); |
|
2338 __ add(from, src_pos, src); // src_addr |
|
2339 __ add(to, dst_pos, dst); // dst_addr |
|
2340 __ mr(count, length); // length |
|
2341 __ b(entry_oop_arraycopy); |
|
2342 |
|
2343 __ bind(L_checkcast_copy); |
|
2344 // live at this point: src_klass, dst_klass |
|
2345 { |
|
2346 // Before looking at dst.length, make sure dst is also an objArray. |
|
2347 __ lwz(temp, lh_offset, dst_klass); |
|
2348 __ cmpw(CCR0, lh, temp); |
|
2349 __ bne(CCR0, L_failed); |
|
2350 |
|
2351 // It is safe to examine both src.length and dst.length. |
|
2352 arraycopy_range_checks(src, src_pos, dst, dst_pos, length, |
|
2353 temp, lh, L_failed); |
|
2354 |
|
2355 // Marshal the base address arguments now, freeing registers. |
|
2356 __ addi(src, src, arrayOopDesc::base_offset_in_bytes(T_OBJECT)); //src offset |
|
2357 __ addi(dst, dst, arrayOopDesc::base_offset_in_bytes(T_OBJECT)); //dst offset |
|
2358 __ sldi(src_pos, src_pos, LogBytesPerHeapOop); |
|
2359 __ sldi(dst_pos, dst_pos, LogBytesPerHeapOop); |
|
2360 __ add(from, src_pos, src); // src_addr |
|
2361 __ add(to, dst_pos, dst); // dst_addr |
|
2362 __ mr(count, length); // length |
|
2363 |
|
2364 Register sco_temp = R6_ARG4; // This register is free now. |
|
2365 assert_different_registers(from, to, count, sco_temp, |
|
2366 dst_klass, src_klass); |
|
2367 |
|
2368 // Generate the type check. |
|
2369 int sco_offset = in_bytes(Klass::super_check_offset_offset()); |
|
2370 __ lwz(sco_temp, sco_offset, dst_klass); |
|
2371 generate_type_check(src_klass, sco_temp, dst_klass, |
|
2372 temp, L_disjoint_plain_copy); |
|
2373 |
|
2374 // Fetch destination element klass from the ObjArrayKlass header. |
|
2375 int ek_offset = in_bytes(ObjArrayKlass::element_klass_offset()); |
|
2376 |
|
2377 // The checkcast_copy loop needs two extra arguments: |
|
2378 __ ld(R7_ARG5, ek_offset, dst_klass); // dest elem klass |
|
2379 __ lwz(R6_ARG4, sco_offset, R7_ARG5); // sco of elem klass |
|
2380 __ b(entry_checkcast_arraycopy); |
|
2381 } |
|
2382 |
|
2383 __ bind(L_disjoint_plain_copy); |
|
2384 __ b(entry_disjoint_oop_arraycopy); |
|
2385 |
|
2386 __ bind(L_failed); |
|
2387 __ li(R3_RET, -1); // return -1 |
|
2388 __ blr(); |
|
2389 return start; |
|
2390 } |
|
2391 |
|
1964 |
2392 |
1965 void generate_arraycopy_stubs() { |
2393 void generate_arraycopy_stubs() { |
1966 // Note: the disjoint stubs must be generated first, some of |
2394 // Note: the disjoint stubs must be generated first, some of |
1967 // the conjoint stubs use them. |
2395 // the conjoint stubs use them. |
1968 |
2396 |
1995 StubRoutines::_arrayof_jshort_arraycopy = generate_conjoint_short_copy(true, "arrayof_jshort_arraycopy"); |
2423 StubRoutines::_arrayof_jshort_arraycopy = generate_conjoint_short_copy(true, "arrayof_jshort_arraycopy"); |
1996 StubRoutines::_arrayof_jint_arraycopy = generate_conjoint_int_copy(true, "arrayof_jint_arraycopy"); |
2424 StubRoutines::_arrayof_jint_arraycopy = generate_conjoint_int_copy(true, "arrayof_jint_arraycopy"); |
1997 StubRoutines::_arrayof_jlong_arraycopy = generate_conjoint_long_copy(true, "arrayof_jlong_arraycopy"); |
2425 StubRoutines::_arrayof_jlong_arraycopy = generate_conjoint_long_copy(true, "arrayof_jlong_arraycopy"); |
1998 StubRoutines::_arrayof_oop_arraycopy = generate_conjoint_oop_copy(true, "arrayof_oop_arraycopy", false); |
2426 StubRoutines::_arrayof_oop_arraycopy = generate_conjoint_oop_copy(true, "arrayof_oop_arraycopy", false); |
1999 StubRoutines::_arrayof_oop_arraycopy_uninit = generate_conjoint_oop_copy(true, "arrayof_oop_arraycopy", true); |
2427 StubRoutines::_arrayof_oop_arraycopy_uninit = generate_conjoint_oop_copy(true, "arrayof_oop_arraycopy", true); |
2428 |
|
2429 // special/generic versions |
|
2430 StubRoutines::_checkcast_arraycopy = generate_checkcast_copy("checkcast_arraycopy", false); |
|
2431 StubRoutines::_checkcast_arraycopy_uninit = generate_checkcast_copy("checkcast_arraycopy_uninit", true); |
|
2432 |
|
2433 StubRoutines::_unsafe_arraycopy = generate_unsafe_copy("unsafe_arraycopy", |
|
2434 STUB_ENTRY(jbyte_arraycopy), |
|
2435 STUB_ENTRY(jshort_arraycopy), |
|
2436 STUB_ENTRY(jint_arraycopy), |
|
2437 STUB_ENTRY(jlong_arraycopy)); |
|
2438 StubRoutines::_generic_arraycopy = generate_generic_copy("generic_arraycopy", |
|
2439 STUB_ENTRY(jbyte_arraycopy), |
|
2440 STUB_ENTRY(jshort_arraycopy), |
|
2441 STUB_ENTRY(jint_arraycopy), |
|
2442 STUB_ENTRY(oop_arraycopy), |
|
2443 STUB_ENTRY(oop_disjoint_arraycopy), |
|
2444 STUB_ENTRY(jlong_arraycopy), |
|
2445 STUB_ENTRY(checkcast_arraycopy)); |
|
2000 |
2446 |
2001 // fill routines |
2447 // fill routines |
2002 StubRoutines::_jbyte_fill = generate_fill(T_BYTE, false, "jbyte_fill"); |
2448 StubRoutines::_jbyte_fill = generate_fill(T_BYTE, false, "jbyte_fill"); |
2003 StubRoutines::_jshort_fill = generate_fill(T_SHORT, false, "jshort_fill"); |
2449 StubRoutines::_jshort_fill = generate_fill(T_SHORT, false, "jshort_fill"); |
2004 StubRoutines::_jint_fill = generate_fill(T_INT, false, "jint_fill"); |
2450 StubRoutines::_jint_fill = generate_fill(T_INT, false, "jint_fill"); |
2226 #ifdef COMPILER2 |
2672 #ifdef COMPILER2 |
2227 if (UseMultiplyToLenIntrinsic) { |
2673 if (UseMultiplyToLenIntrinsic) { |
2228 StubRoutines::_multiplyToLen = generate_multiplyToLen(); |
2674 StubRoutines::_multiplyToLen = generate_multiplyToLen(); |
2229 } |
2675 } |
2230 #endif |
2676 #endif |
2677 |
|
2678 if (UseMontgomeryMultiplyIntrinsic) { |
|
2679 StubRoutines::_montgomeryMultiply |
|
2680 = CAST_FROM_FN_PTR(address, SharedRuntime::montgomery_multiply); |
|
2681 } |
|
2682 if (UseMontgomerySquareIntrinsic) { |
|
2683 StubRoutines::_montgomerySquare |
|
2684 = CAST_FROM_FN_PTR(address, SharedRuntime::montgomery_square); |
|
2685 } |
|
2231 } |
2686 } |
2232 |
2687 |
2233 public: |
2688 public: |
2234 StubGenerator(CodeBuffer* code, bool all) : StubCodeGenerator(code) { |
2689 StubGenerator(CodeBuffer* code, bool all) : StubCodeGenerator(code) { |
2235 // replace the standard masm with a special one: |
2690 // replace the standard masm with a special one: |