Mercurial > hg > graal-jvmci-8
comparison src/cpu/x86/vm/stubGenerator_x86_64.cpp @ 2313:d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
Summary: Rearranged the pre-barrier placement in arraycopy stubs so that they are properly called in case of chained calls. Also refactored the code a little bit so that it looks uniform across the platforms and is more readable.
Reviewed-by: never, kvn
author | iveresov |
---|---|
date | Tue, 22 Feb 2011 15:25:02 -0800 |
parents | bbefa3ca1543 |
children | 0ac769a57c64 |
comparison
equal
deleted
inserted
replaced
2262:6bbaedb03534 | 2313:d89a22843c62 |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
1055 __ ret(4 * wordSize); // pop caller saved stuff | 1055 __ ret(4 * wordSize); // pop caller saved stuff |
1056 | 1056 |
1057 return start; | 1057 return start; |
1058 } | 1058 } |
1059 | 1059 |
1060 static address disjoint_byte_copy_entry; | |
1061 static address disjoint_short_copy_entry; | |
1062 static address disjoint_int_copy_entry; | |
1063 static address disjoint_long_copy_entry; | |
1064 static address disjoint_oop_copy_entry; | |
1065 | |
1066 static address byte_copy_entry; | |
1067 static address short_copy_entry; | |
1068 static address int_copy_entry; | |
1069 static address long_copy_entry; | |
1070 static address oop_copy_entry; | |
1071 | |
1072 static address checkcast_copy_entry; | |
1073 | |
1074 // | 1060 // |
1075 // Verify that a register contains clean 32-bits positive value | 1061 // Verify that a register contains clean 32-bits positive value |
1076 // (high 32-bits are 0) so it could be used in 64-bits shifts. | 1062 // (high 32-bits are 0) so it could be used in 64-bits shifts. |
1077 // | 1063 // |
1078 // Input: | 1064 // Input: |
1377 // | 1363 // |
1378 // Side Effects: | 1364 // Side Effects: |
1379 // disjoint_byte_copy_entry is set to the no-overlap entry point | 1365 // disjoint_byte_copy_entry is set to the no-overlap entry point |
1380 // used by generate_conjoint_byte_copy(). | 1366 // used by generate_conjoint_byte_copy(). |
1381 // | 1367 // |
1382 address generate_disjoint_byte_copy(bool aligned, const char *name) { | 1368 address generate_disjoint_byte_copy(bool aligned, address* entry, const char *name) { |
1383 __ align(CodeEntryAlignment); | 1369 __ align(CodeEntryAlignment); |
1384 StubCodeMark mark(this, "StubRoutines", name); | 1370 StubCodeMark mark(this, "StubRoutines", name); |
1385 address start = __ pc(); | 1371 address start = __ pc(); |
1386 | 1372 |
1387 Label L_copy_32_bytes, L_copy_8_bytes, L_copy_4_bytes, L_copy_2_bytes; | 1373 Label L_copy_32_bytes, L_copy_8_bytes, L_copy_4_bytes, L_copy_2_bytes; |
1397 // to the last unit copied: end_to[0] := end_from[0] | 1383 // to the last unit copied: end_to[0] := end_from[0] |
1398 | 1384 |
1399 __ enter(); // required for proper stackwalking of RuntimeStub frame | 1385 __ enter(); // required for proper stackwalking of RuntimeStub frame |
1400 assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int. | 1386 assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int. |
1401 | 1387 |
1402 disjoint_byte_copy_entry = __ pc(); | 1388 if (entry != NULL) { |
1403 BLOCK_COMMENT("Entry:"); | 1389 *entry = __ pc(); |
1404 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) | 1390 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) |
1391 BLOCK_COMMENT("Entry:"); | |
1392 } | |
1405 | 1393 |
1406 setup_arg_regs(); // from => rdi, to => rsi, count => rdx | 1394 setup_arg_regs(); // from => rdi, to => rsi, count => rdx |
1407 // r9 and r10 may be used to save non-volatile registers | 1395 // r9 and r10 may be used to save non-volatile registers |
1408 | 1396 |
1409 // 'from', 'to' and 'count' are now valid | 1397 // 'from', 'to' and 'count' are now valid |
1477 // If 'from' and/or 'to' are aligned on 4-, 2-, or 1-byte boundaries, | 1465 // If 'from' and/or 'to' are aligned on 4-, 2-, or 1-byte boundaries, |
1478 // we let the hardware handle it. The one to eight bytes within words, | 1466 // we let the hardware handle it. The one to eight bytes within words, |
1479 // dwords or qwords that span cache line boundaries will still be loaded | 1467 // dwords or qwords that span cache line boundaries will still be loaded |
1480 // and stored atomically. | 1468 // and stored atomically. |
1481 // | 1469 // |
1482 address generate_conjoint_byte_copy(bool aligned, const char *name) { | 1470 address generate_conjoint_byte_copy(bool aligned, address nooverlap_target, |
1471 address* entry, const char *name) { | |
1483 __ align(CodeEntryAlignment); | 1472 __ align(CodeEntryAlignment); |
1484 StubCodeMark mark(this, "StubRoutines", name); | 1473 StubCodeMark mark(this, "StubRoutines", name); |
1485 address start = __ pc(); | 1474 address start = __ pc(); |
1486 | 1475 |
1487 Label L_copy_32_bytes, L_copy_8_bytes, L_copy_4_bytes, L_copy_2_bytes; | 1476 Label L_copy_32_bytes, L_copy_8_bytes, L_copy_4_bytes, L_copy_2_bytes; |
1492 const Register qword_count = count; | 1481 const Register qword_count = count; |
1493 | 1482 |
1494 __ enter(); // required for proper stackwalking of RuntimeStub frame | 1483 __ enter(); // required for proper stackwalking of RuntimeStub frame |
1495 assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int. | 1484 assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int. |
1496 | 1485 |
1497 byte_copy_entry = __ pc(); | 1486 if (entry != NULL) { |
1498 BLOCK_COMMENT("Entry:"); | 1487 *entry = __ pc(); |
1499 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) | 1488 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) |
1500 | 1489 BLOCK_COMMENT("Entry:"); |
1501 array_overlap_test(disjoint_byte_copy_entry, Address::times_1); | 1490 } |
1491 | |
1492 array_overlap_test(nooverlap_target, Address::times_1); | |
1502 setup_arg_regs(); // from => rdi, to => rsi, count => rdx | 1493 setup_arg_regs(); // from => rdi, to => rsi, count => rdx |
1503 // r9 and r10 may be used to save non-volatile registers | 1494 // r9 and r10 may be used to save non-volatile registers |
1504 | 1495 |
1505 // 'from', 'to' and 'count' are now valid | 1496 // 'from', 'to' and 'count' are now valid |
1506 __ movptr(byte_count, count); | 1497 __ movptr(byte_count, count); |
1572 // | 1563 // |
1573 // Side Effects: | 1564 // Side Effects: |
1574 // disjoint_short_copy_entry is set to the no-overlap entry point | 1565 // disjoint_short_copy_entry is set to the no-overlap entry point |
1575 // used by generate_conjoint_short_copy(). | 1566 // used by generate_conjoint_short_copy(). |
1576 // | 1567 // |
1577 address generate_disjoint_short_copy(bool aligned, const char *name) { | 1568 address generate_disjoint_short_copy(bool aligned, address *entry, const char *name) { |
1578 __ align(CodeEntryAlignment); | 1569 __ align(CodeEntryAlignment); |
1579 StubCodeMark mark(this, "StubRoutines", name); | 1570 StubCodeMark mark(this, "StubRoutines", name); |
1580 address start = __ pc(); | 1571 address start = __ pc(); |
1581 | 1572 |
1582 Label L_copy_32_bytes, L_copy_8_bytes, L_copy_4_bytes,L_copy_2_bytes,L_exit; | 1573 Label L_copy_32_bytes, L_copy_8_bytes, L_copy_4_bytes,L_copy_2_bytes,L_exit; |
1591 // to the last unit copied: end_to[0] := end_from[0] | 1582 // to the last unit copied: end_to[0] := end_from[0] |
1592 | 1583 |
1593 __ enter(); // required for proper stackwalking of RuntimeStub frame | 1584 __ enter(); // required for proper stackwalking of RuntimeStub frame |
1594 assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int. | 1585 assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int. |
1595 | 1586 |
1596 disjoint_short_copy_entry = __ pc(); | 1587 if (entry != NULL) { |
1597 BLOCK_COMMENT("Entry:"); | 1588 *entry = __ pc(); |
1598 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) | 1589 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) |
1590 BLOCK_COMMENT("Entry:"); | |
1591 } | |
1599 | 1592 |
1600 setup_arg_regs(); // from => rdi, to => rsi, count => rdx | 1593 setup_arg_regs(); // from => rdi, to => rsi, count => rdx |
1601 // r9 and r10 may be used to save non-volatile registers | 1594 // r9 and r10 may be used to save non-volatile registers |
1602 | 1595 |
1603 // 'from', 'to' and 'count' are now valid | 1596 // 'from', 'to' and 'count' are now valid |
1684 // If 'from' and/or 'to' are aligned on 4- or 2-byte boundaries, we | 1677 // If 'from' and/or 'to' are aligned on 4- or 2-byte boundaries, we |
1685 // let the hardware handle it. The two or four words within dwords | 1678 // let the hardware handle it. The two or four words within dwords |
1686 // or qwords that span cache line boundaries will still be loaded | 1679 // or qwords that span cache line boundaries will still be loaded |
1687 // and stored atomically. | 1680 // and stored atomically. |
1688 // | 1681 // |
1689 address generate_conjoint_short_copy(bool aligned, const char *name) { | 1682 address generate_conjoint_short_copy(bool aligned, address nooverlap_target, |
1683 address *entry, const char *name) { | |
1690 __ align(CodeEntryAlignment); | 1684 __ align(CodeEntryAlignment); |
1691 StubCodeMark mark(this, "StubRoutines", name); | 1685 StubCodeMark mark(this, "StubRoutines", name); |
1692 address start = __ pc(); | 1686 address start = __ pc(); |
1693 | 1687 |
1694 Label L_copy_32_bytes, L_copy_8_bytes, L_copy_4_bytes; | 1688 Label L_copy_32_bytes, L_copy_8_bytes, L_copy_4_bytes; |
1699 const Register qword_count = count; | 1693 const Register qword_count = count; |
1700 | 1694 |
1701 __ enter(); // required for proper stackwalking of RuntimeStub frame | 1695 __ enter(); // required for proper stackwalking of RuntimeStub frame |
1702 assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int. | 1696 assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int. |
1703 | 1697 |
1704 short_copy_entry = __ pc(); | 1698 if (entry != NULL) { |
1705 BLOCK_COMMENT("Entry:"); | 1699 *entry = __ pc(); |
1706 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) | 1700 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) |
1707 | 1701 BLOCK_COMMENT("Entry:"); |
1708 array_overlap_test(disjoint_short_copy_entry, Address::times_2); | 1702 } |
1703 | |
1704 array_overlap_test(nooverlap_target, Address::times_2); | |
1709 setup_arg_regs(); // from => rdi, to => rsi, count => rdx | 1705 setup_arg_regs(); // from => rdi, to => rsi, count => rdx |
1710 // r9 and r10 may be used to save non-volatile registers | 1706 // r9 and r10 may be used to save non-volatile registers |
1711 | 1707 |
1712 // 'from', 'to' and 'count' are now valid | 1708 // 'from', 'to' and 'count' are now valid |
1713 __ movptr(word_count, count); | 1709 __ movptr(word_count, count); |
1771 // | 1767 // |
1772 // Side Effects: | 1768 // Side Effects: |
1773 // disjoint_int_copy_entry is set to the no-overlap entry point | 1769 // disjoint_int_copy_entry is set to the no-overlap entry point |
1774 // used by generate_conjoint_int_oop_copy(). | 1770 // used by generate_conjoint_int_oop_copy(). |
1775 // | 1771 // |
1776 address generate_disjoint_int_oop_copy(bool aligned, bool is_oop, const char *name) { | 1772 address generate_disjoint_int_oop_copy(bool aligned, bool is_oop, address* entry, const char *name) { |
1777 __ align(CodeEntryAlignment); | 1773 __ align(CodeEntryAlignment); |
1778 StubCodeMark mark(this, "StubRoutines", name); | 1774 StubCodeMark mark(this, "StubRoutines", name); |
1779 address start = __ pc(); | 1775 address start = __ pc(); |
1780 | 1776 |
1781 Label L_copy_32_bytes, L_copy_8_bytes, L_copy_4_bytes, L_exit; | 1777 Label L_copy_32_bytes, L_copy_8_bytes, L_copy_4_bytes, L_exit; |
1791 // to the last unit copied: end_to[0] := end_from[0] | 1787 // to the last unit copied: end_to[0] := end_from[0] |
1792 | 1788 |
1793 __ enter(); // required for proper stackwalking of RuntimeStub frame | 1789 __ enter(); // required for proper stackwalking of RuntimeStub frame |
1794 assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int. | 1790 assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int. |
1795 | 1791 |
1796 (is_oop ? disjoint_oop_copy_entry : disjoint_int_copy_entry) = __ pc(); | 1792 if (entry != NULL) { |
1797 | 1793 *entry = __ pc(); |
1798 if (is_oop) { | 1794 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) |
1799 // no registers are destroyed by this call | 1795 BLOCK_COMMENT("Entry:"); |
1800 gen_write_ref_array_pre_barrier(/* dest */ c_rarg1, /* count */ c_rarg2); | 1796 } |
1801 } | |
1802 | |
1803 BLOCK_COMMENT("Entry:"); | |
1804 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) | |
1805 | 1797 |
1806 setup_arg_regs(); // from => rdi, to => rsi, count => rdx | 1798 setup_arg_regs(); // from => rdi, to => rsi, count => rdx |
1807 // r9 and r10 may be used to save non-volatile registers | 1799 // r9 and r10 may be used to save non-volatile registers |
1808 | |
1809 if (is_oop) { | 1800 if (is_oop) { |
1810 __ movq(saved_to, to); | 1801 __ movq(saved_to, to); |
1802 gen_write_ref_array_pre_barrier(to, count); | |
1811 } | 1803 } |
1812 | 1804 |
1813 // 'from', 'to' and 'count' are now valid | 1805 // 'from', 'to' and 'count' are now valid |
1814 __ movptr(dword_count, count); | 1806 __ movptr(dword_count, count); |
1815 __ shrptr(count, 1); // count => qword_count | 1807 __ shrptr(count, 1); // count => qword_count |
1865 // | 1857 // |
1866 // If 'from' and/or 'to' are aligned on 4-byte boundaries, we let | 1858 // If 'from' and/or 'to' are aligned on 4-byte boundaries, we let |
1867 // the hardware handle it. The two dwords within qwords that span | 1859 // the hardware handle it. The two dwords within qwords that span |
1868 // cache line boundaries will still be loaded and stored atomicly. | 1860 // cache line boundaries will still be loaded and stored atomicly. |
1869 // | 1861 // |
1870 address generate_conjoint_int_oop_copy(bool aligned, bool is_oop, const char *name) { | 1862 address generate_conjoint_int_oop_copy(bool aligned, bool is_oop, address nooverlap_target, |
1863 address *entry, const char *name) { | |
1871 __ align(CodeEntryAlignment); | 1864 __ align(CodeEntryAlignment); |
1872 StubCodeMark mark(this, "StubRoutines", name); | 1865 StubCodeMark mark(this, "StubRoutines", name); |
1873 address start = __ pc(); | 1866 address start = __ pc(); |
1874 | 1867 |
1875 Label L_copy_32_bytes, L_copy_8_bytes, L_copy_2_bytes, L_exit; | 1868 Label L_copy_32_bytes, L_copy_8_bytes, L_copy_2_bytes, L_exit; |
1880 const Register qword_count = count; | 1873 const Register qword_count = count; |
1881 | 1874 |
1882 __ enter(); // required for proper stackwalking of RuntimeStub frame | 1875 __ enter(); // required for proper stackwalking of RuntimeStub frame |
1883 assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int. | 1876 assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int. |
1884 | 1877 |
1878 if (entry != NULL) { | |
1879 *entry = __ pc(); | |
1880 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) | |
1881 BLOCK_COMMENT("Entry:"); | |
1882 } | |
1883 | |
1884 array_overlap_test(nooverlap_target, Address::times_4); | |
1885 setup_arg_regs(); // from => rdi, to => rsi, count => rdx | |
1886 // r9 and r10 may be used to save non-volatile registers | |
1887 | |
1885 if (is_oop) { | 1888 if (is_oop) { |
1886 // no registers are destroyed by this call | 1889 // no registers are destroyed by this call |
1887 gen_write_ref_array_pre_barrier(/* dest */ c_rarg1, /* count */ c_rarg2); | 1890 gen_write_ref_array_pre_barrier(to, count); |
1888 } | 1891 } |
1889 | |
1890 (is_oop ? oop_copy_entry : int_copy_entry) = __ pc(); | |
1891 BLOCK_COMMENT("Entry:"); | |
1892 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) | |
1893 | |
1894 array_overlap_test(is_oop ? disjoint_oop_copy_entry : disjoint_int_copy_entry, | |
1895 Address::times_4); | |
1896 setup_arg_regs(); // from => rdi, to => rsi, count => rdx | |
1897 // r9 and r10 may be used to save non-volatile registers | |
1898 | 1892 |
1899 assert_clean_int(count, rax); // Make sure 'count' is clean int. | 1893 assert_clean_int(count, rax); // Make sure 'count' is clean int. |
1900 // 'from', 'to' and 'count' are now valid | 1894 // 'from', 'to' and 'count' are now valid |
1901 __ movptr(dword_count, count); | 1895 __ movptr(dword_count, count); |
1902 __ shrptr(count, 1); // count => qword_count | 1896 __ shrptr(count, 1); // count => qword_count |
1957 // | 1951 // |
1958 // Side Effects: | 1952 // Side Effects: |
1959 // disjoint_oop_copy_entry or disjoint_long_copy_entry is set to the | 1953 // disjoint_oop_copy_entry or disjoint_long_copy_entry is set to the |
1960 // no-overlap entry point used by generate_conjoint_long_oop_copy(). | 1954 // no-overlap entry point used by generate_conjoint_long_oop_copy(). |
1961 // | 1955 // |
1962 address generate_disjoint_long_oop_copy(bool aligned, bool is_oop, const char *name) { | 1956 address generate_disjoint_long_oop_copy(bool aligned, bool is_oop, address *entry, const char *name) { |
1963 __ align(CodeEntryAlignment); | 1957 __ align(CodeEntryAlignment); |
1964 StubCodeMark mark(this, "StubRoutines", name); | 1958 StubCodeMark mark(this, "StubRoutines", name); |
1965 address start = __ pc(); | 1959 address start = __ pc(); |
1966 | 1960 |
1967 Label L_copy_32_bytes, L_copy_8_bytes, L_exit; | 1961 Label L_copy_32_bytes, L_copy_8_bytes, L_exit; |
1976 | 1970 |
1977 __ enter(); // required for proper stackwalking of RuntimeStub frame | 1971 __ enter(); // required for proper stackwalking of RuntimeStub frame |
1978 // Save no-overlap entry point for generate_conjoint_long_oop_copy() | 1972 // Save no-overlap entry point for generate_conjoint_long_oop_copy() |
1979 assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int. | 1973 assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int. |
1980 | 1974 |
1981 if (is_oop) { | 1975 if (entry != NULL) { |
1982 disjoint_oop_copy_entry = __ pc(); | 1976 *entry = __ pc(); |
1983 // no registers are destroyed by this call | 1977 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) |
1984 gen_write_ref_array_pre_barrier(/* dest */ c_rarg1, /* count */ c_rarg2); | 1978 BLOCK_COMMENT("Entry:"); |
1985 } else { | 1979 } |
1986 disjoint_long_copy_entry = __ pc(); | |
1987 } | |
1988 BLOCK_COMMENT("Entry:"); | |
1989 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) | |
1990 | 1980 |
1991 setup_arg_regs(); // from => rdi, to => rsi, count => rdx | 1981 setup_arg_regs(); // from => rdi, to => rsi, count => rdx |
1992 // r9 and r10 may be used to save non-volatile registers | 1982 // r9 and r10 may be used to save non-volatile registers |
1993 | |
1994 // 'from', 'to' and 'qword_count' are now valid | 1983 // 'from', 'to' and 'qword_count' are now valid |
1984 if (is_oop) { | |
1985 // no registers are destroyed by this call | |
1986 gen_write_ref_array_pre_barrier(to, qword_count); | |
1987 } | |
1995 | 1988 |
1996 // Copy from low to high addresses. Use 'to' as scratch. | 1989 // Copy from low to high addresses. Use 'to' as scratch. |
1997 __ lea(end_from, Address(from, qword_count, Address::times_8, -8)); | 1990 __ lea(end_from, Address(from, qword_count, Address::times_8, -8)); |
1998 __ lea(end_to, Address(to, qword_count, Address::times_8, -8)); | 1991 __ lea(end_to, Address(to, qword_count, Address::times_8, -8)); |
1999 __ negptr(qword_count); | 1992 __ negptr(qword_count); |
2043 // Inputs: | 2036 // Inputs: |
2044 // c_rarg0 - source array address | 2037 // c_rarg0 - source array address |
2045 // c_rarg1 - destination array address | 2038 // c_rarg1 - destination array address |
2046 // c_rarg2 - element count, treated as ssize_t, can be zero | 2039 // c_rarg2 - element count, treated as ssize_t, can be zero |
2047 // | 2040 // |
2048 address generate_conjoint_long_oop_copy(bool aligned, bool is_oop, const char *name) { | 2041 address generate_conjoint_long_oop_copy(bool aligned, bool is_oop, address nooverlap_target, |
2042 address *entry, const char *name) { | |
2049 __ align(CodeEntryAlignment); | 2043 __ align(CodeEntryAlignment); |
2050 StubCodeMark mark(this, "StubRoutines", name); | 2044 StubCodeMark mark(this, "StubRoutines", name); |
2051 address start = __ pc(); | 2045 address start = __ pc(); |
2052 | 2046 |
2053 Label L_copy_32_bytes, L_copy_8_bytes, L_exit; | 2047 Label L_copy_32_bytes, L_copy_8_bytes, L_exit; |
2057 const Register saved_count = rcx; | 2051 const Register saved_count = rcx; |
2058 | 2052 |
2059 __ enter(); // required for proper stackwalking of RuntimeStub frame | 2053 __ enter(); // required for proper stackwalking of RuntimeStub frame |
2060 assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int. | 2054 assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int. |
2061 | 2055 |
2062 address disjoint_copy_entry = NULL; | 2056 if (entry != NULL) { |
2063 if (is_oop) { | 2057 *entry = __ pc(); |
2064 assert(!UseCompressedOops, "shouldn't be called for compressed oops"); | 2058 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) |
2065 disjoint_copy_entry = disjoint_oop_copy_entry; | 2059 BLOCK_COMMENT("Entry:"); |
2066 oop_copy_entry = __ pc(); | 2060 } |
2067 array_overlap_test(disjoint_oop_copy_entry, Address::times_8); | 2061 |
2068 } else { | 2062 array_overlap_test(nooverlap_target, Address::times_8); |
2069 disjoint_copy_entry = disjoint_long_copy_entry; | |
2070 long_copy_entry = __ pc(); | |
2071 array_overlap_test(disjoint_long_copy_entry, Address::times_8); | |
2072 } | |
2073 BLOCK_COMMENT("Entry:"); | |
2074 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) | |
2075 | |
2076 array_overlap_test(disjoint_copy_entry, Address::times_8); | |
2077 setup_arg_regs(); // from => rdi, to => rsi, count => rdx | 2063 setup_arg_regs(); // from => rdi, to => rsi, count => rdx |
2078 // r9 and r10 may be used to save non-volatile registers | 2064 // r9 and r10 may be used to save non-volatile registers |
2079 | |
2080 // 'from', 'to' and 'qword_count' are now valid | 2065 // 'from', 'to' and 'qword_count' are now valid |
2081 | |
2082 if (is_oop) { | 2066 if (is_oop) { |
2083 // Save to and count for store barrier | 2067 // Save to and count for store barrier |
2084 __ movptr(saved_count, qword_count); | 2068 __ movptr(saved_count, qword_count); |
2085 // No registers are destroyed by this call | 2069 // No registers are destroyed by this call |
2086 gen_write_ref_array_pre_barrier(to, saved_count); | 2070 gen_write_ref_array_pre_barrier(to, saved_count); |
2160 // | 2144 // |
2161 // Output: | 2145 // Output: |
2162 // rax == 0 - success | 2146 // rax == 0 - success |
2163 // rax == -1^K - failure, where K is partial transfer count | 2147 // rax == -1^K - failure, where K is partial transfer count |
2164 // | 2148 // |
2165 address generate_checkcast_copy(const char *name) { | 2149 address generate_checkcast_copy(const char *name, address *entry) { |
2166 | 2150 |
2167 Label L_load_element, L_store_element, L_do_card_marks, L_done; | 2151 Label L_load_element, L_store_element, L_do_card_marks, L_done; |
2168 | 2152 |
2169 // Input registers (after setup_arg_regs) | 2153 // Input registers (after setup_arg_regs) |
2170 const Register from = rdi; // source array address | 2154 const Register from = rdi; // source array address |
2214 // last argument (#4) is on stack on Win64 | 2198 // last argument (#4) is on stack on Win64 |
2215 __ movptr(ckval, Address(rsp, 6 * wordSize)); | 2199 __ movptr(ckval, Address(rsp, 6 * wordSize)); |
2216 #endif | 2200 #endif |
2217 | 2201 |
2218 // Caller of this entry point must set up the argument registers. | 2202 // Caller of this entry point must set up the argument registers. |
2219 checkcast_copy_entry = __ pc(); | 2203 if (entry != NULL) { |
2220 BLOCK_COMMENT("Entry:"); | 2204 *entry = __ pc(); |
2205 BLOCK_COMMENT("Entry:"); | |
2206 } | |
2221 | 2207 |
2222 // allocate spill slots for r13, r14 | 2208 // allocate spill slots for r13, r14 |
2223 enum { | 2209 enum { |
2224 saved_r13_offset, | 2210 saved_r13_offset, |
2225 saved_r14_offset, | 2211 saved_r14_offset, |
2332 // c_rarg2 - byte count, treated as ssize_t, can be zero | 2318 // c_rarg2 - byte count, treated as ssize_t, can be zero |
2333 // | 2319 // |
2334 // Examines the alignment of the operands and dispatches | 2320 // Examines the alignment of the operands and dispatches |
2335 // to a long, int, short, or byte copy loop. | 2321 // to a long, int, short, or byte copy loop. |
2336 // | 2322 // |
2337 address generate_unsafe_copy(const char *name) { | 2323 address generate_unsafe_copy(const char *name, |
2324 address byte_copy_entry, address short_copy_entry, | |
2325 address int_copy_entry, address long_copy_entry) { | |
2338 | 2326 |
2339 Label L_long_aligned, L_int_aligned, L_short_aligned; | 2327 Label L_long_aligned, L_int_aligned, L_short_aligned; |
2340 | 2328 |
2341 // Input registers (before setup_arg_regs) | 2329 // Input registers (before setup_arg_regs) |
2342 const Register from = c_rarg0; // source array address | 2330 const Register from = c_rarg0; // source array address |
2430 // | 2418 // |
2431 // Output: | 2419 // Output: |
2432 // rax == 0 - success | 2420 // rax == 0 - success |
2433 // rax == -1^K - failure, where K is partial transfer count | 2421 // rax == -1^K - failure, where K is partial transfer count |
2434 // | 2422 // |
2435 address generate_generic_copy(const char *name) { | 2423 address generate_generic_copy(const char *name, |
2424 address byte_copy_entry, address short_copy_entry, | |
2425 address int_copy_entry, address long_copy_entry, | |
2426 address oop_copy_entry, address checkcast_copy_entry) { | |
2436 | 2427 |
2437 Label L_failed, L_failed_0, L_objArray; | 2428 Label L_failed, L_failed_0, L_objArray; |
2438 Label L_copy_bytes, L_copy_shorts, L_copy_ints, L_copy_longs; | 2429 Label L_copy_bytes, L_copy_shorts, L_copy_ints, L_copy_longs; |
2439 | 2430 |
2440 // Input registers | 2431 // Input registers |
2723 | 2714 |
2724 return start; | 2715 return start; |
2725 } | 2716 } |
2726 | 2717 |
2727 void generate_arraycopy_stubs() { | 2718 void generate_arraycopy_stubs() { |
2728 // Call the conjoint generation methods immediately after | 2719 address entry; |
2729 // the disjoint ones so that short branches from the former | 2720 address entry_jbyte_arraycopy; |
2730 // to the latter can be generated. | 2721 address entry_jshort_arraycopy; |
2731 StubRoutines::_jbyte_disjoint_arraycopy = generate_disjoint_byte_copy(false, "jbyte_disjoint_arraycopy"); | 2722 address entry_jint_arraycopy; |
2732 StubRoutines::_jbyte_arraycopy = generate_conjoint_byte_copy(false, "jbyte_arraycopy"); | 2723 address entry_oop_arraycopy; |
2733 | 2724 address entry_jlong_arraycopy; |
2734 StubRoutines::_jshort_disjoint_arraycopy = generate_disjoint_short_copy(false, "jshort_disjoint_arraycopy"); | 2725 address entry_checkcast_arraycopy; |
2735 StubRoutines::_jshort_arraycopy = generate_conjoint_short_copy(false, "jshort_arraycopy"); | 2726 |
2736 | 2727 StubRoutines::_jbyte_disjoint_arraycopy = generate_disjoint_byte_copy(false, &entry, |
2737 StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_int_oop_copy(false, false, "jint_disjoint_arraycopy"); | 2728 "jbyte_disjoint_arraycopy"); |
2738 StubRoutines::_jint_arraycopy = generate_conjoint_int_oop_copy(false, false, "jint_arraycopy"); | 2729 StubRoutines::_jbyte_arraycopy = generate_conjoint_byte_copy(false, entry, &entry_jbyte_arraycopy, |
2739 | 2730 "jbyte_arraycopy"); |
2740 StubRoutines::_jlong_disjoint_arraycopy = generate_disjoint_long_oop_copy(false, false, "jlong_disjoint_arraycopy"); | 2731 |
2741 StubRoutines::_jlong_arraycopy = generate_conjoint_long_oop_copy(false, false, "jlong_arraycopy"); | 2732 StubRoutines::_jshort_disjoint_arraycopy = generate_disjoint_short_copy(false, &entry, |
2733 "jshort_disjoint_arraycopy"); | |
2734 StubRoutines::_jshort_arraycopy = generate_conjoint_short_copy(false, entry, &entry_jshort_arraycopy, | |
2735 "jshort_arraycopy"); | |
2736 | |
2737 StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_int_oop_copy(false, false, &entry, | |
2738 "jint_disjoint_arraycopy"); | |
2739 StubRoutines::_jint_arraycopy = generate_conjoint_int_oop_copy(false, false, entry, | |
2740 &entry_jint_arraycopy, "jint_arraycopy"); | |
2741 | |
2742 StubRoutines::_jlong_disjoint_arraycopy = generate_disjoint_long_oop_copy(false, false, &entry, | |
2743 "jlong_disjoint_arraycopy"); | |
2744 StubRoutines::_jlong_arraycopy = generate_conjoint_long_oop_copy(false, false, entry, | |
2745 &entry_jlong_arraycopy, "jlong_arraycopy"); | |
2742 | 2746 |
2743 | 2747 |
2744 if (UseCompressedOops) { | 2748 if (UseCompressedOops) { |
2745 StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_int_oop_copy(false, true, "oop_disjoint_arraycopy"); | 2749 StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_int_oop_copy(false, true, &entry, |
2746 StubRoutines::_oop_arraycopy = generate_conjoint_int_oop_copy(false, true, "oop_arraycopy"); | 2750 "oop_disjoint_arraycopy"); |
2751 StubRoutines::_oop_arraycopy = generate_conjoint_int_oop_copy(false, true, entry, | |
2752 &entry_oop_arraycopy, "oop_arraycopy"); | |
2747 } else { | 2753 } else { |
2748 StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_long_oop_copy(false, true, "oop_disjoint_arraycopy"); | 2754 StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_long_oop_copy(false, true, &entry, |
2749 StubRoutines::_oop_arraycopy = generate_conjoint_long_oop_copy(false, true, "oop_arraycopy"); | 2755 "oop_disjoint_arraycopy"); |
2750 } | 2756 StubRoutines::_oop_arraycopy = generate_conjoint_long_oop_copy(false, true, entry, |
2751 | 2757 &entry_oop_arraycopy, "oop_arraycopy"); |
2752 StubRoutines::_checkcast_arraycopy = generate_checkcast_copy("checkcast_arraycopy"); | 2758 } |
2753 StubRoutines::_unsafe_arraycopy = generate_unsafe_copy("unsafe_arraycopy"); | 2759 |
2754 StubRoutines::_generic_arraycopy = generate_generic_copy("generic_arraycopy"); | 2760 StubRoutines::_checkcast_arraycopy = generate_checkcast_copy("checkcast_arraycopy", &entry_checkcast_arraycopy); |
2761 StubRoutines::_unsafe_arraycopy = generate_unsafe_copy("unsafe_arraycopy", | |
2762 entry_jbyte_arraycopy, | |
2763 entry_jshort_arraycopy, | |
2764 entry_jint_arraycopy, | |
2765 entry_jlong_arraycopy); | |
2766 StubRoutines::_generic_arraycopy = generate_generic_copy("generic_arraycopy", | |
2767 entry_jbyte_arraycopy, | |
2768 entry_jshort_arraycopy, | |
2769 entry_jint_arraycopy, | |
2770 entry_oop_arraycopy, | |
2771 entry_jlong_arraycopy, | |
2772 entry_checkcast_arraycopy); | |
2755 | 2773 |
2756 StubRoutines::_jbyte_fill = generate_fill(T_BYTE, false, "jbyte_fill"); | 2774 StubRoutines::_jbyte_fill = generate_fill(T_BYTE, false, "jbyte_fill"); |
2757 StubRoutines::_jshort_fill = generate_fill(T_SHORT, false, "jshort_fill"); | 2775 StubRoutines::_jshort_fill = generate_fill(T_SHORT, false, "jshort_fill"); |
2758 StubRoutines::_jint_fill = generate_fill(T_INT, false, "jint_fill"); | 2776 StubRoutines::_jint_fill = generate_fill(T_INT, false, "jint_fill"); |
2759 StubRoutines::_arrayof_jbyte_fill = generate_fill(T_BYTE, true, "arrayof_jbyte_fill"); | 2777 StubRoutines::_arrayof_jbyte_fill = generate_fill(T_BYTE, true, "arrayof_jbyte_fill"); |
3067 generate_initial(); | 3085 generate_initial(); |
3068 } | 3086 } |
3069 } | 3087 } |
3070 }; // end class declaration | 3088 }; // end class declaration |
3071 | 3089 |
3072 address StubGenerator::disjoint_byte_copy_entry = NULL; | |
3073 address StubGenerator::disjoint_short_copy_entry = NULL; | |
3074 address StubGenerator::disjoint_int_copy_entry = NULL; | |
3075 address StubGenerator::disjoint_long_copy_entry = NULL; | |
3076 address StubGenerator::disjoint_oop_copy_entry = NULL; | |
3077 | |
3078 address StubGenerator::byte_copy_entry = NULL; | |
3079 address StubGenerator::short_copy_entry = NULL; | |
3080 address StubGenerator::int_copy_entry = NULL; | |
3081 address StubGenerator::long_copy_entry = NULL; | |
3082 address StubGenerator::oop_copy_entry = NULL; | |
3083 | |
3084 address StubGenerator::checkcast_copy_entry = NULL; | |
3085 | |
3086 void StubGenerator_generate(CodeBuffer* code, bool all) { | 3090 void StubGenerator_generate(CodeBuffer* code, bool all) { |
3087 StubGenerator g(code, all); | 3091 StubGenerator g(code, all); |
3088 } | 3092 } |