Mercurial > hg > truffle
comparison src/cpu/sparc/vm/stubGenerator_sparc.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 | f95d63e2154a |
children | 0ac769a57c64 |
comparison
equal
deleted
inserted
replaced
2262:6bbaedb03534 | 2313:d89a22843c62 |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 1997, 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. |
966 __ verify_oop_subroutine(); | 966 __ verify_oop_subroutine(); |
967 | 967 |
968 return start; | 968 return start; |
969 } | 969 } |
970 | 970 |
971 static address disjoint_byte_copy_entry; | |
972 static address disjoint_short_copy_entry; | |
973 static address disjoint_int_copy_entry; | |
974 static address disjoint_long_copy_entry; | |
975 static address disjoint_oop_copy_entry; | |
976 | |
977 static address byte_copy_entry; | |
978 static address short_copy_entry; | |
979 static address int_copy_entry; | |
980 static address long_copy_entry; | |
981 static address oop_copy_entry; | |
982 | |
983 static address checkcast_copy_entry; | |
984 | 971 |
985 // | 972 // |
986 // Verify that a register contains clean 32-bits positive value | 973 // Verify that a register contains clean 32-bits positive value |
987 // (high 32-bits are 0) so it could be used in 64-bits shifts (sllx, srax). | 974 // (high 32-bits are 0) so it could be used in 64-bits shifts (sllx, srax). |
988 // | 975 // |
1281 // Arguments for generated stub: | 1268 // Arguments for generated stub: |
1282 // from: O0 | 1269 // from: O0 |
1283 // to: O1 | 1270 // to: O1 |
1284 // count: O2 treated as signed | 1271 // count: O2 treated as signed |
1285 // | 1272 // |
1286 address generate_disjoint_byte_copy(bool aligned, const char * name) { | 1273 address generate_disjoint_byte_copy(bool aligned, address *entry, const char *name) { |
1287 __ align(CodeEntryAlignment); | 1274 __ align(CodeEntryAlignment); |
1288 StubCodeMark mark(this, "StubRoutines", name); | 1275 StubCodeMark mark(this, "StubRoutines", name); |
1289 address start = __ pc(); | 1276 address start = __ pc(); |
1290 | 1277 |
1291 Label L_skip_alignment, L_align; | 1278 Label L_skip_alignment, L_align; |
1297 const Register offset = O5; // offset from start of arrays | 1284 const Register offset = O5; // offset from start of arrays |
1298 // O3, O4, G3, G4 are used as temp registers | 1285 // O3, O4, G3, G4 are used as temp registers |
1299 | 1286 |
1300 assert_clean_int(count, O3); // Make sure 'count' is clean int. | 1287 assert_clean_int(count, O3); // Make sure 'count' is clean int. |
1301 | 1288 |
1302 if (!aligned) disjoint_byte_copy_entry = __ pc(); | 1289 if (entry != NULL) { |
1303 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) | 1290 *entry = __ pc(); |
1304 if (!aligned) BLOCK_COMMENT("Entry:"); | 1291 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) |
1292 BLOCK_COMMENT("Entry:"); | |
1293 } | |
1305 | 1294 |
1306 // for short arrays, just do single element copy | 1295 // for short arrays, just do single element copy |
1307 __ cmp(count, 23); // 16 + 7 | 1296 __ cmp(count, 23); // 16 + 7 |
1308 __ brx(Assembler::less, false, Assembler::pn, L_copy_byte); | 1297 __ brx(Assembler::less, false, Assembler::pn, L_copy_byte); |
1309 __ delayed()->mov(G0, offset); | 1298 __ delayed()->mov(G0, offset); |
1389 // Arguments for generated stub: | 1378 // Arguments for generated stub: |
1390 // from: O0 | 1379 // from: O0 |
1391 // to: O1 | 1380 // to: O1 |
1392 // count: O2 treated as signed | 1381 // count: O2 treated as signed |
1393 // | 1382 // |
1394 address generate_conjoint_byte_copy(bool aligned, const char * name) { | 1383 address generate_conjoint_byte_copy(bool aligned, address nooverlap_target, |
1384 address *entry, const char *name) { | |
1395 // Do reverse copy. | 1385 // Do reverse copy. |
1396 | 1386 |
1397 __ align(CodeEntryAlignment); | 1387 __ align(CodeEntryAlignment); |
1398 StubCodeMark mark(this, "StubRoutines", name); | 1388 StubCodeMark mark(this, "StubRoutines", name); |
1399 address start = __ pc(); | 1389 address start = __ pc(); |
1400 address nooverlap_target = aligned ? | |
1401 StubRoutines::arrayof_jbyte_disjoint_arraycopy() : | |
1402 disjoint_byte_copy_entry; | |
1403 | 1390 |
1404 Label L_skip_alignment, L_align, L_aligned_copy; | 1391 Label L_skip_alignment, L_align, L_aligned_copy; |
1405 Label L_copy_byte, L_copy_byte_loop, L_exit; | 1392 Label L_copy_byte, L_copy_byte_loop, L_exit; |
1406 | 1393 |
1407 const Register from = O0; // source array address | 1394 const Register from = O0; // source array address |
1410 const Register end_from = from; // source array end address | 1397 const Register end_from = from; // source array end address |
1411 const Register end_to = to; // destination array end address | 1398 const Register end_to = to; // destination array end address |
1412 | 1399 |
1413 assert_clean_int(count, O3); // Make sure 'count' is clean int. | 1400 assert_clean_int(count, O3); // Make sure 'count' is clean int. |
1414 | 1401 |
1415 if (!aligned) byte_copy_entry = __ pc(); | 1402 if (entry != NULL) { |
1416 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) | 1403 *entry = __ pc(); |
1417 if (!aligned) BLOCK_COMMENT("Entry:"); | 1404 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) |
1405 BLOCK_COMMENT("Entry:"); | |
1406 } | |
1418 | 1407 |
1419 array_overlap_test(nooverlap_target, 0); | 1408 array_overlap_test(nooverlap_target, 0); |
1420 | 1409 |
1421 __ add(to, count, end_to); // offset after last copied element | 1410 __ add(to, count, end_to); // offset after last copied element |
1422 | 1411 |
1502 // Arguments for generated stub: | 1491 // Arguments for generated stub: |
1503 // from: O0 | 1492 // from: O0 |
1504 // to: O1 | 1493 // to: O1 |
1505 // count: O2 treated as signed | 1494 // count: O2 treated as signed |
1506 // | 1495 // |
1507 address generate_disjoint_short_copy(bool aligned, const char * name) { | 1496 address generate_disjoint_short_copy(bool aligned, address *entry, const char * name) { |
1508 __ align(CodeEntryAlignment); | 1497 __ align(CodeEntryAlignment); |
1509 StubCodeMark mark(this, "StubRoutines", name); | 1498 StubCodeMark mark(this, "StubRoutines", name); |
1510 address start = __ pc(); | 1499 address start = __ pc(); |
1511 | 1500 |
1512 Label L_skip_alignment, L_skip_alignment2; | 1501 Label L_skip_alignment, L_skip_alignment2; |
1518 const Register offset = O5; // offset from start of arrays | 1507 const Register offset = O5; // offset from start of arrays |
1519 // O3, O4, G3, G4 are used as temp registers | 1508 // O3, O4, G3, G4 are used as temp registers |
1520 | 1509 |
1521 assert_clean_int(count, O3); // Make sure 'count' is clean int. | 1510 assert_clean_int(count, O3); // Make sure 'count' is clean int. |
1522 | 1511 |
1523 if (!aligned) disjoint_short_copy_entry = __ pc(); | 1512 if (entry != NULL) { |
1524 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) | 1513 *entry = __ pc(); |
1525 if (!aligned) BLOCK_COMMENT("Entry:"); | 1514 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) |
1515 BLOCK_COMMENT("Entry:"); | |
1516 } | |
1526 | 1517 |
1527 // for short arrays, just do single element copy | 1518 // for short arrays, just do single element copy |
1528 __ cmp(count, 11); // 8 + 3 (22 bytes) | 1519 __ cmp(count, 11); // 8 + 3 (22 bytes) |
1529 __ brx(Assembler::less, false, Assembler::pn, L_copy_2_bytes); | 1520 __ brx(Assembler::less, false, Assembler::pn, L_copy_2_bytes); |
1530 __ delayed()->mov(G0, offset); | 1521 __ delayed()->mov(G0, offset); |
1840 // Arguments for generated stub: | 1831 // Arguments for generated stub: |
1841 // from: O0 | 1832 // from: O0 |
1842 // to: O1 | 1833 // to: O1 |
1843 // count: O2 treated as signed | 1834 // count: O2 treated as signed |
1844 // | 1835 // |
1845 address generate_conjoint_short_copy(bool aligned, const char * name) { | 1836 address generate_conjoint_short_copy(bool aligned, address nooverlap_target, |
1837 address *entry, const char *name) { | |
1846 // Do reverse copy. | 1838 // Do reverse copy. |
1847 | 1839 |
1848 __ align(CodeEntryAlignment); | 1840 __ align(CodeEntryAlignment); |
1849 StubCodeMark mark(this, "StubRoutines", name); | 1841 StubCodeMark mark(this, "StubRoutines", name); |
1850 address start = __ pc(); | 1842 address start = __ pc(); |
1851 address nooverlap_target = aligned ? | |
1852 StubRoutines::arrayof_jshort_disjoint_arraycopy() : | |
1853 disjoint_short_copy_entry; | |
1854 | 1843 |
1855 Label L_skip_alignment, L_skip_alignment2, L_aligned_copy; | 1844 Label L_skip_alignment, L_skip_alignment2, L_aligned_copy; |
1856 Label L_copy_2_bytes, L_copy_2_bytes_loop, L_exit; | 1845 Label L_copy_2_bytes, L_copy_2_bytes_loop, L_exit; |
1857 | 1846 |
1858 const Register from = O0; // source array address | 1847 const Register from = O0; // source array address |
1863 | 1852 |
1864 const Register byte_count = O3; // bytes count to copy | 1853 const Register byte_count = O3; // bytes count to copy |
1865 | 1854 |
1866 assert_clean_int(count, O3); // Make sure 'count' is clean int. | 1855 assert_clean_int(count, O3); // Make sure 'count' is clean int. |
1867 | 1856 |
1868 if (!aligned) short_copy_entry = __ pc(); | 1857 if (entry != NULL) { |
1869 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) | 1858 *entry = __ pc(); |
1870 if (!aligned) BLOCK_COMMENT("Entry:"); | 1859 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) |
1860 BLOCK_COMMENT("Entry:"); | |
1861 } | |
1871 | 1862 |
1872 array_overlap_test(nooverlap_target, 1); | 1863 array_overlap_test(nooverlap_target, 1); |
1873 | 1864 |
1874 __ sllx(count, LogBytesPerShort, byte_count); | 1865 __ sllx(count, LogBytesPerShort, byte_count); |
1875 __ add(to, byte_count, end_to); // offset after last copied element | 1866 __ add(to, byte_count, end_to); // offset after last copied element |
2070 // Arguments for generated stub: | 2061 // Arguments for generated stub: |
2071 // from: O0 | 2062 // from: O0 |
2072 // to: O1 | 2063 // to: O1 |
2073 // count: O2 treated as signed | 2064 // count: O2 treated as signed |
2074 // | 2065 // |
2075 address generate_disjoint_int_copy(bool aligned, const char * name) { | 2066 address generate_disjoint_int_copy(bool aligned, address *entry, const char *name) { |
2076 __ align(CodeEntryAlignment); | 2067 __ align(CodeEntryAlignment); |
2077 StubCodeMark mark(this, "StubRoutines", name); | 2068 StubCodeMark mark(this, "StubRoutines", name); |
2078 address start = __ pc(); | 2069 address start = __ pc(); |
2079 | 2070 |
2080 const Register count = O2; | 2071 const Register count = O2; |
2081 assert_clean_int(count, O3); // Make sure 'count' is clean int. | 2072 assert_clean_int(count, O3); // Make sure 'count' is clean int. |
2082 | 2073 |
2083 if (!aligned) disjoint_int_copy_entry = __ pc(); | 2074 if (entry != NULL) { |
2084 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) | 2075 *entry = __ pc(); |
2085 if (!aligned) BLOCK_COMMENT("Entry:"); | 2076 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) |
2077 BLOCK_COMMENT("Entry:"); | |
2078 } | |
2086 | 2079 |
2087 generate_disjoint_int_copy_core(aligned); | 2080 generate_disjoint_int_copy_core(aligned); |
2088 | 2081 |
2089 // O3, O4 are used as temp registers | 2082 // O3, O4 are used as temp registers |
2090 inc_counter_np(SharedRuntime::_jint_array_copy_ctr, O3, O4); | 2083 inc_counter_np(SharedRuntime::_jint_array_copy_ctr, O3, O4); |
2202 // Arguments for generated stub: | 2195 // Arguments for generated stub: |
2203 // from: O0 | 2196 // from: O0 |
2204 // to: O1 | 2197 // to: O1 |
2205 // count: O2 treated as signed | 2198 // count: O2 treated as signed |
2206 // | 2199 // |
2207 address generate_conjoint_int_copy(bool aligned, const char * name) { | 2200 address generate_conjoint_int_copy(bool aligned, address nooverlap_target, |
2201 address *entry, const char *name) { | |
2208 __ align(CodeEntryAlignment); | 2202 __ align(CodeEntryAlignment); |
2209 StubCodeMark mark(this, "StubRoutines", name); | 2203 StubCodeMark mark(this, "StubRoutines", name); |
2210 address start = __ pc(); | 2204 address start = __ pc(); |
2211 | 2205 |
2212 address nooverlap_target = aligned ? | |
2213 StubRoutines::arrayof_jint_disjoint_arraycopy() : | |
2214 disjoint_int_copy_entry; | |
2215 | |
2216 assert_clean_int(O2, O3); // Make sure 'count' is clean int. | 2206 assert_clean_int(O2, O3); // Make sure 'count' is clean int. |
2217 | 2207 |
2218 if (!aligned) int_copy_entry = __ pc(); | 2208 if (entry != NULL) { |
2219 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) | 2209 *entry = __ pc(); |
2220 if (!aligned) BLOCK_COMMENT("Entry:"); | 2210 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) |
2211 BLOCK_COMMENT("Entry:"); | |
2212 } | |
2221 | 2213 |
2222 array_overlap_test(nooverlap_target, 2); | 2214 array_overlap_test(nooverlap_target, 2); |
2223 | 2215 |
2224 generate_conjoint_int_copy_core(aligned); | 2216 generate_conjoint_int_copy_core(aligned); |
2225 | 2217 |
2334 // Arguments for generated stub: | 2326 // Arguments for generated stub: |
2335 // from: O0 | 2327 // from: O0 |
2336 // to: O1 | 2328 // to: O1 |
2337 // count: O2 treated as signed | 2329 // count: O2 treated as signed |
2338 // | 2330 // |
2339 address generate_disjoint_long_copy(bool aligned, const char * name) { | 2331 address generate_disjoint_long_copy(bool aligned, address *entry, const char *name) { |
2340 __ align(CodeEntryAlignment); | 2332 __ align(CodeEntryAlignment); |
2341 StubCodeMark mark(this, "StubRoutines", name); | 2333 StubCodeMark mark(this, "StubRoutines", name); |
2342 address start = __ pc(); | 2334 address start = __ pc(); |
2343 | 2335 |
2344 assert_clean_int(O2, O3); // Make sure 'count' is clean int. | 2336 assert_clean_int(O2, O3); // Make sure 'count' is clean int. |
2345 | 2337 |
2346 if (!aligned) disjoint_long_copy_entry = __ pc(); | 2338 if (entry != NULL) { |
2347 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) | 2339 *entry = __ pc(); |
2348 if (!aligned) BLOCK_COMMENT("Entry:"); | 2340 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) |
2341 BLOCK_COMMENT("Entry:"); | |
2342 } | |
2349 | 2343 |
2350 generate_disjoint_long_copy_core(aligned); | 2344 generate_disjoint_long_copy_core(aligned); |
2351 | 2345 |
2352 // O3, O4 are used as temp registers | 2346 // O3, O4 are used as temp registers |
2353 inc_counter_np(SharedRuntime::_jlong_array_copy_ctr, O3, O4); | 2347 inc_counter_np(SharedRuntime::_jlong_array_copy_ctr, O3, O4); |
2404 // Arguments for generated stub: | 2398 // Arguments for generated stub: |
2405 // from: O0 | 2399 // from: O0 |
2406 // to: O1 | 2400 // to: O1 |
2407 // count: O2 treated as signed | 2401 // count: O2 treated as signed |
2408 // | 2402 // |
2409 address generate_conjoint_long_copy(bool aligned, const char * name) { | 2403 address generate_conjoint_long_copy(bool aligned, address nooverlap_target, |
2404 address *entry, const char *name) { | |
2410 __ align(CodeEntryAlignment); | 2405 __ align(CodeEntryAlignment); |
2411 StubCodeMark mark(this, "StubRoutines", name); | 2406 StubCodeMark mark(this, "StubRoutines", name); |
2412 address start = __ pc(); | 2407 address start = __ pc(); |
2413 | 2408 |
2414 assert(!aligned, "usage"); | 2409 assert(!aligned, "usage"); |
2415 address nooverlap_target = disjoint_long_copy_entry; | |
2416 | 2410 |
2417 assert_clean_int(O2, O3); // Make sure 'count' is clean int. | 2411 assert_clean_int(O2, O3); // Make sure 'count' is clean int. |
2418 | 2412 |
2419 if (!aligned) long_copy_entry = __ pc(); | 2413 if (entry != NULL) { |
2420 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) | 2414 *entry = __ pc(); |
2421 if (!aligned) BLOCK_COMMENT("Entry:"); | 2415 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) |
2416 BLOCK_COMMENT("Entry:"); | |
2417 } | |
2422 | 2418 |
2423 array_overlap_test(nooverlap_target, 3); | 2419 array_overlap_test(nooverlap_target, 3); |
2424 | 2420 |
2425 generate_conjoint_long_copy_core(aligned); | 2421 generate_conjoint_long_copy_core(aligned); |
2426 | 2422 |
2437 // Arguments for generated stub: | 2433 // Arguments for generated stub: |
2438 // from: O0 | 2434 // from: O0 |
2439 // to: O1 | 2435 // to: O1 |
2440 // count: O2 treated as signed | 2436 // count: O2 treated as signed |
2441 // | 2437 // |
2442 address generate_disjoint_oop_copy(bool aligned, const char * name) { | 2438 address generate_disjoint_oop_copy(bool aligned, address *entry, const char *name) { |
2443 | 2439 |
2444 const Register from = O0; // source array address | 2440 const Register from = O0; // source array address |
2445 const Register to = O1; // destination array address | 2441 const Register to = O1; // destination array address |
2446 const Register count = O2; // elements count | 2442 const Register count = O2; // elements count |
2447 | 2443 |
2449 StubCodeMark mark(this, "StubRoutines", name); | 2445 StubCodeMark mark(this, "StubRoutines", name); |
2450 address start = __ pc(); | 2446 address start = __ pc(); |
2451 | 2447 |
2452 assert_clean_int(count, O3); // Make sure 'count' is clean int. | 2448 assert_clean_int(count, O3); // Make sure 'count' is clean int. |
2453 | 2449 |
2454 if (!aligned) disjoint_oop_copy_entry = __ pc(); | 2450 if (entry != NULL) { |
2455 // caller can pass a 64-bit byte count here | 2451 *entry = __ pc(); |
2456 if (!aligned) BLOCK_COMMENT("Entry:"); | 2452 // caller can pass a 64-bit byte count here |
2453 BLOCK_COMMENT("Entry:"); | |
2454 } | |
2457 | 2455 |
2458 // save arguments for barrier generation | 2456 // save arguments for barrier generation |
2459 __ mov(to, G1); | 2457 __ mov(to, G1); |
2460 __ mov(count, G5); | 2458 __ mov(count, G5); |
2461 gen_write_ref_array_pre_barrier(G1, G5); | 2459 gen_write_ref_array_pre_barrier(G1, G5); |
2485 // Arguments for generated stub: | 2483 // Arguments for generated stub: |
2486 // from: O0 | 2484 // from: O0 |
2487 // to: O1 | 2485 // to: O1 |
2488 // count: O2 treated as signed | 2486 // count: O2 treated as signed |
2489 // | 2487 // |
2490 address generate_conjoint_oop_copy(bool aligned, const char * name) { | 2488 address generate_conjoint_oop_copy(bool aligned, address nooverlap_target, |
2489 address *entry, const char *name) { | |
2491 | 2490 |
2492 const Register from = O0; // source array address | 2491 const Register from = O0; // source array address |
2493 const Register to = O1; // destination array address | 2492 const Register to = O1; // destination array address |
2494 const Register count = O2; // elements count | 2493 const Register count = O2; // elements count |
2495 | 2494 |
2497 StubCodeMark mark(this, "StubRoutines", name); | 2496 StubCodeMark mark(this, "StubRoutines", name); |
2498 address start = __ pc(); | 2497 address start = __ pc(); |
2499 | 2498 |
2500 assert_clean_int(count, O3); // Make sure 'count' is clean int. | 2499 assert_clean_int(count, O3); // Make sure 'count' is clean int. |
2501 | 2500 |
2502 if (!aligned) oop_copy_entry = __ pc(); | 2501 if (entry != NULL) { |
2503 // caller can pass a 64-bit byte count here | 2502 *entry = __ pc(); |
2504 if (!aligned) BLOCK_COMMENT("Entry:"); | 2503 // caller can pass a 64-bit byte count here |
2504 BLOCK_COMMENT("Entry:"); | |
2505 } | |
2506 | |
2507 array_overlap_test(nooverlap_target, LogBytesPerHeapOop); | |
2505 | 2508 |
2506 // save arguments for barrier generation | 2509 // save arguments for barrier generation |
2507 __ mov(to, G1); | 2510 __ mov(to, G1); |
2508 __ mov(count, G5); | 2511 __ mov(count, G5); |
2509 | |
2510 gen_write_ref_array_pre_barrier(G1, G5); | 2512 gen_write_ref_array_pre_barrier(G1, G5); |
2511 | |
2512 address nooverlap_target = aligned ? | |
2513 StubRoutines::arrayof_oop_disjoint_arraycopy() : | |
2514 disjoint_oop_copy_entry; | |
2515 | |
2516 array_overlap_test(nooverlap_target, LogBytesPerHeapOop); | |
2517 | 2513 |
2518 #ifdef _LP64 | 2514 #ifdef _LP64 |
2519 if (UseCompressedOops) { | 2515 if (UseCompressedOops) { |
2520 generate_conjoint_int_copy_core(aligned); | 2516 generate_conjoint_int_copy_core(aligned); |
2521 } else { | 2517 } else { |
2580 // count: O2 treated as signed | 2576 // count: O2 treated as signed |
2581 // ckoff: O3 (super_check_offset) | 2577 // ckoff: O3 (super_check_offset) |
2582 // ckval: O4 (super_klass) | 2578 // ckval: O4 (super_klass) |
2583 // ret: O0 zero for success; (-1^K) where K is partial transfer count | 2579 // ret: O0 zero for success; (-1^K) where K is partial transfer count |
2584 // | 2580 // |
2585 address generate_checkcast_copy(const char* name) { | 2581 address generate_checkcast_copy(const char *name, address *entry) { |
2586 | 2582 |
2587 const Register O0_from = O0; // source array address | 2583 const Register O0_from = O0; // source array address |
2588 const Register O1_to = O1; // destination array address | 2584 const Register O1_to = O1; // destination array address |
2589 const Register O2_count = O2; // elements count | 2585 const Register O2_count = O2; // elements count |
2590 const Register O3_ckoff = O3; // super_check_offset | 2586 const Register O3_ckoff = O3; // super_check_offset |
2597 const Register G5_super = G5; // oop._klass._primary_supers[ckval] | 2593 const Register G5_super = G5; // oop._klass._primary_supers[ckval] |
2598 | 2594 |
2599 __ align(CodeEntryAlignment); | 2595 __ align(CodeEntryAlignment); |
2600 StubCodeMark mark(this, "StubRoutines", name); | 2596 StubCodeMark mark(this, "StubRoutines", name); |
2601 address start = __ pc(); | 2597 address start = __ pc(); |
2602 | |
2603 gen_write_ref_array_pre_barrier(O1, O2); | |
2604 | 2598 |
2605 #ifdef ASSERT | 2599 #ifdef ASSERT |
2606 // We sometimes save a frame (see generate_type_check below). | 2600 // We sometimes save a frame (see generate_type_check below). |
2607 // If this will cause trouble, let's fail now instead of later. | 2601 // If this will cause trouble, let's fail now instead of later. |
2608 __ save_frame(0); | 2602 __ save_frame(0); |
2623 __ mov(G1, O3); | 2617 __ mov(G1, O3); |
2624 __ mov(G4, O4); | 2618 __ mov(G4, O4); |
2625 } | 2619 } |
2626 #endif //ASSERT | 2620 #endif //ASSERT |
2627 | 2621 |
2628 checkcast_copy_entry = __ pc(); | 2622 if (entry != NULL) { |
2629 // caller can pass a 64-bit byte count here (from generic stub) | 2623 *entry = __ pc(); |
2630 BLOCK_COMMENT("Entry:"); | 2624 // caller can pass a 64-bit byte count here (from generic stub) |
2625 BLOCK_COMMENT("Entry:"); | |
2626 } | |
2627 | |
2628 gen_write_ref_array_pre_barrier(O1_to, O2_count); | |
2631 | 2629 |
2632 Label load_element, store_element, do_card_marks, fail, done; | 2630 Label load_element, store_element, do_card_marks, fail, done; |
2633 __ addcc(O2_count, 0, G1_remain); // initialize loop index, and test it | 2631 __ addcc(O2_count, 0, G1_remain); // initialize loop index, and test it |
2634 __ brx(Assembler::notZero, false, Assembler::pt, load_element); | 2632 __ brx(Assembler::notZero, false, Assembler::pt, load_element); |
2635 __ delayed()->mov(G0, O5_offset); // offset from start of arrays | 2633 __ delayed()->mov(G0, O5_offset); // offset from start of arrays |
2698 // count: O2 byte count, treated as ssize_t, can be zero | 2696 // count: O2 byte count, treated as ssize_t, can be zero |
2699 // | 2697 // |
2700 // Examines the alignment of the operands and dispatches | 2698 // Examines the alignment of the operands and dispatches |
2701 // to a long, int, short, or byte copy loop. | 2699 // to a long, int, short, or byte copy loop. |
2702 // | 2700 // |
2703 address generate_unsafe_copy(const char* name) { | 2701 address generate_unsafe_copy(const char* name, |
2702 address byte_copy_entry, | |
2703 address short_copy_entry, | |
2704 address int_copy_entry, | |
2705 address long_copy_entry) { | |
2704 | 2706 |
2705 const Register O0_from = O0; // source array address | 2707 const Register O0_from = O0; // source array address |
2706 const Register O1_to = O1; // destination array address | 2708 const Register O1_to = O1; // destination array address |
2707 const Register O2_count = O2; // elements count | 2709 const Register O2_count = O2; // elements count |
2708 | 2710 |
2794 // | 2796 // |
2795 // Output: | 2797 // Output: |
2796 // O0 == 0 - success | 2798 // O0 == 0 - success |
2797 // O0 == -1 - need to call System.arraycopy | 2799 // O0 == -1 - need to call System.arraycopy |
2798 // | 2800 // |
2799 address generate_generic_copy(const char *name) { | 2801 address generate_generic_copy(const char *name, |
2800 | 2802 address entry_jbyte_arraycopy, |
2803 address entry_jshort_arraycopy, | |
2804 address entry_jint_arraycopy, | |
2805 address entry_oop_arraycopy, | |
2806 address entry_jlong_arraycopy, | |
2807 address entry_checkcast_arraycopy) { | |
2801 Label L_failed, L_objArray; | 2808 Label L_failed, L_objArray; |
2802 | 2809 |
2803 // Input registers | 2810 // Input registers |
2804 const Register src = O0; // source array oop | 2811 const Register src = O0; // source array oop |
2805 const Register src_pos = O1; // source position | 2812 const Register src_pos = O1; // source position |
2968 __ add(src, src_pos, from); // src_addr | 2975 __ add(src, src_pos, from); // src_addr |
2969 __ add(dst, dst_pos, to); // dst_addr | 2976 __ add(dst, dst_pos, to); // dst_addr |
2970 | 2977 |
2971 BLOCK_COMMENT("choose copy loop based on element size"); | 2978 BLOCK_COMMENT("choose copy loop based on element size"); |
2972 __ cmp(G3_elsize, 0); | 2979 __ cmp(G3_elsize, 0); |
2973 __ br(Assembler::equal,true,Assembler::pt,StubRoutines::_jbyte_arraycopy); | 2980 __ br(Assembler::equal, true, Assembler::pt, entry_jbyte_arraycopy); |
2974 __ delayed()->signx(length, count); // length | 2981 __ delayed()->signx(length, count); // length |
2975 | 2982 |
2976 __ cmp(G3_elsize, LogBytesPerShort); | 2983 __ cmp(G3_elsize, LogBytesPerShort); |
2977 __ br(Assembler::equal,true,Assembler::pt,StubRoutines::_jshort_arraycopy); | 2984 __ br(Assembler::equal, true, Assembler::pt, entry_jshort_arraycopy); |
2978 __ delayed()->signx(length, count); // length | 2985 __ delayed()->signx(length, count); // length |
2979 | 2986 |
2980 __ cmp(G3_elsize, LogBytesPerInt); | 2987 __ cmp(G3_elsize, LogBytesPerInt); |
2981 __ br(Assembler::equal,true,Assembler::pt,StubRoutines::_jint_arraycopy); | 2988 __ br(Assembler::equal, true, Assembler::pt, entry_jint_arraycopy); |
2982 __ delayed()->signx(length, count); // length | 2989 __ delayed()->signx(length, count); // length |
2983 #ifdef ASSERT | 2990 #ifdef ASSERT |
2984 { Label L; | 2991 { Label L; |
2985 __ cmp(G3_elsize, LogBytesPerLong); | 2992 __ cmp(G3_elsize, LogBytesPerLong); |
2986 __ br(Assembler::equal, false, Assembler::pt, L); | 2993 __ br(Assembler::equal, false, Assembler::pt, L); |
2987 __ delayed()->nop(); | 2994 __ delayed()->nop(); |
2988 __ stop("must be long copy, but elsize is wrong"); | 2995 __ stop("must be long copy, but elsize is wrong"); |
2989 __ bind(L); | 2996 __ bind(L); |
2990 } | 2997 } |
2991 #endif | 2998 #endif |
2992 __ br(Assembler::always,false,Assembler::pt,StubRoutines::_jlong_arraycopy); | 2999 __ br(Assembler::always, false, Assembler::pt, entry_jlong_arraycopy); |
2993 __ delayed()->signx(length, count); // length | 3000 __ delayed()->signx(length, count); // length |
2994 | 3001 |
2995 // objArrayKlass | 3002 // objArrayKlass |
2996 __ BIND(L_objArray); | 3003 __ BIND(L_objArray); |
2997 // live at this point: G3_src_klass, G4_dst_klass, src[_pos], dst[_pos], length | 3004 // live at this point: G3_src_klass, G4_dst_klass, src[_pos], dst[_pos], length |
3011 __ sll_ptr(src_pos, LogBytesPerHeapOop, src_pos); | 3018 __ sll_ptr(src_pos, LogBytesPerHeapOop, src_pos); |
3012 __ sll_ptr(dst_pos, LogBytesPerHeapOop, dst_pos); | 3019 __ sll_ptr(dst_pos, LogBytesPerHeapOop, dst_pos); |
3013 __ add(src, src_pos, from); // src_addr | 3020 __ add(src, src_pos, from); // src_addr |
3014 __ add(dst, dst_pos, to); // dst_addr | 3021 __ add(dst, dst_pos, to); // dst_addr |
3015 __ BIND(L_plain_copy); | 3022 __ BIND(L_plain_copy); |
3016 __ br(Assembler::always, false, Assembler::pt,StubRoutines::_oop_arraycopy); | 3023 __ br(Assembler::always, false, Assembler::pt, entry_oop_arraycopy); |
3017 __ delayed()->signx(length, count); // length | 3024 __ delayed()->signx(length, count); // length |
3018 | 3025 |
3019 __ BIND(L_checkcast_copy); | 3026 __ BIND(L_checkcast_copy); |
3020 // live at this point: G3_src_klass, G4_dst_klass | 3027 // live at this point: G3_src_klass, G4_dst_klass |
3021 { | 3028 { |
3055 | 3062 |
3056 // the checkcast_copy loop needs two extra arguments: | 3063 // the checkcast_copy loop needs two extra arguments: |
3057 __ ld_ptr(G4_dst_klass, ek_offset, O4); // dest elem klass | 3064 __ ld_ptr(G4_dst_klass, ek_offset, O4); // dest elem klass |
3058 // lduw(O4, sco_offset, O3); // sco of elem klass | 3065 // lduw(O4, sco_offset, O3); // sco of elem klass |
3059 | 3066 |
3060 __ br(Assembler::always, false, Assembler::pt, checkcast_copy_entry); | 3067 __ br(Assembler::always, false, Assembler::pt, entry_checkcast_arraycopy); |
3061 __ delayed()->lduw(O4, sco_offset, O3); | 3068 __ delayed()->lduw(O4, sco_offset, O3); |
3062 } | 3069 } |
3063 | 3070 |
3064 __ BIND(L_failed); | 3071 __ BIND(L_failed); |
3065 __ retl(); | 3072 __ retl(); |
3066 __ delayed()->sub(G0, 1, O0); // return -1 | 3073 __ delayed()->sub(G0, 1, O0); // return -1 |
3067 return start; | 3074 return start; |
3068 } | 3075 } |
3069 | 3076 |
3070 void generate_arraycopy_stubs() { | 3077 void generate_arraycopy_stubs() { |
3071 | 3078 address entry; |
3072 // Note: the disjoint stubs must be generated first, some of | 3079 address entry_jbyte_arraycopy; |
3073 // the conjoint stubs use them. | 3080 address entry_jshort_arraycopy; |
3074 StubRoutines::_jbyte_disjoint_arraycopy = generate_disjoint_byte_copy(false, "jbyte_disjoint_arraycopy"); | 3081 address entry_jint_arraycopy; |
3075 StubRoutines::_jshort_disjoint_arraycopy = generate_disjoint_short_copy(false, "jshort_disjoint_arraycopy"); | 3082 address entry_oop_arraycopy; |
3076 StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_int_copy(false, "jint_disjoint_arraycopy"); | 3083 address entry_jlong_arraycopy; |
3077 StubRoutines::_jlong_disjoint_arraycopy = generate_disjoint_long_copy(false, "jlong_disjoint_arraycopy"); | 3084 address entry_checkcast_arraycopy; |
3078 StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_oop_copy(false, "oop_disjoint_arraycopy"); | 3085 |
3079 StubRoutines::_arrayof_jbyte_disjoint_arraycopy = generate_disjoint_byte_copy(true, "arrayof_jbyte_disjoint_arraycopy"); | 3086 StubRoutines::_jbyte_disjoint_arraycopy = generate_disjoint_byte_copy(false, &entry, |
3080 StubRoutines::_arrayof_jshort_disjoint_arraycopy = generate_disjoint_short_copy(true, "arrayof_jshort_disjoint_arraycopy"); | 3087 "jbyte_disjoint_arraycopy"); |
3081 StubRoutines::_arrayof_jint_disjoint_arraycopy = generate_disjoint_int_copy(true, "arrayof_jint_disjoint_arraycopy"); | 3088 StubRoutines::_jbyte_arraycopy = generate_conjoint_byte_copy(false, entry, &entry_jbyte_arraycopy, |
3082 StubRoutines::_arrayof_jlong_disjoint_arraycopy = generate_disjoint_long_copy(true, "arrayof_jlong_disjoint_arraycopy"); | 3089 "jbyte_arraycopy"); |
3083 StubRoutines::_arrayof_oop_disjoint_arraycopy = generate_disjoint_oop_copy(true, "arrayof_oop_disjoint_arraycopy"); | 3090 StubRoutines::_jshort_disjoint_arraycopy = generate_disjoint_short_copy(false, &entry, |
3084 | 3091 "jshort_disjoint_arraycopy"); |
3085 StubRoutines::_jbyte_arraycopy = generate_conjoint_byte_copy(false, "jbyte_arraycopy"); | 3092 StubRoutines::_jshort_arraycopy = generate_conjoint_short_copy(false, entry, &entry_jshort_arraycopy, |
3086 StubRoutines::_jshort_arraycopy = generate_conjoint_short_copy(false, "jshort_arraycopy"); | 3093 "jshort_arraycopy"); |
3087 StubRoutines::_jint_arraycopy = generate_conjoint_int_copy(false, "jint_arraycopy"); | 3094 StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_int_copy(false, &entry, |
3088 StubRoutines::_jlong_arraycopy = generate_conjoint_long_copy(false, "jlong_arraycopy"); | 3095 "jint_disjoint_arraycopy"); |
3089 StubRoutines::_oop_arraycopy = generate_conjoint_oop_copy(false, "oop_arraycopy"); | 3096 StubRoutines::_jint_arraycopy = generate_conjoint_int_copy(false, entry, &entry_jint_arraycopy, |
3090 StubRoutines::_arrayof_jbyte_arraycopy = generate_conjoint_byte_copy(true, "arrayof_jbyte_arraycopy"); | 3097 "jint_arraycopy"); |
3091 StubRoutines::_arrayof_jshort_arraycopy = generate_conjoint_short_copy(true, "arrayof_jshort_arraycopy"); | 3098 StubRoutines::_jlong_disjoint_arraycopy = generate_disjoint_long_copy(false, &entry, |
3099 "jlong_disjoint_arraycopy"); | |
3100 StubRoutines::_jlong_arraycopy = generate_conjoint_long_copy(false, entry, &entry_jlong_arraycopy, | |
3101 "jlong_arraycopy"); | |
3102 StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_oop_copy(false, &entry, | |
3103 "oop_disjoint_arraycopy"); | |
3104 StubRoutines::_oop_arraycopy = generate_conjoint_oop_copy(false, entry, &entry_oop_arraycopy, | |
3105 "oop_arraycopy"); | |
3106 | |
3107 | |
3108 StubRoutines::_arrayof_jbyte_disjoint_arraycopy = generate_disjoint_byte_copy(true, &entry, | |
3109 "arrayof_jbyte_disjoint_arraycopy"); | |
3110 StubRoutines::_arrayof_jbyte_arraycopy = generate_conjoint_byte_copy(true, entry, NULL, | |
3111 "arrayof_jbyte_arraycopy"); | |
3112 | |
3113 StubRoutines::_arrayof_jshort_disjoint_arraycopy = generate_disjoint_short_copy(true, &entry, | |
3114 "arrayof_jshort_disjoint_arraycopy"); | |
3115 StubRoutines::_arrayof_jshort_arraycopy = generate_conjoint_short_copy(true, entry, NULL, | |
3116 "arrayof_jshort_arraycopy"); | |
3117 | |
3118 StubRoutines::_arrayof_jint_disjoint_arraycopy = generate_disjoint_int_copy(true, &entry, | |
3119 "arrayof_jint_disjoint_arraycopy"); | |
3092 #ifdef _LP64 | 3120 #ifdef _LP64 |
3093 // since sizeof(jint) < sizeof(HeapWord), there's a different flavor: | 3121 // since sizeof(jint) < sizeof(HeapWord), there's a different flavor: |
3094 StubRoutines::_arrayof_jint_arraycopy = generate_conjoint_int_copy(true, "arrayof_jint_arraycopy"); | 3122 StubRoutines::_arrayof_jint_arraycopy = generate_conjoint_int_copy(true, entry, NULL, "arrayof_jint_arraycopy"); |
3095 #else | 3123 #else |
3096 StubRoutines::_arrayof_jint_arraycopy = StubRoutines::_jint_arraycopy; | 3124 StubRoutines::_arrayof_jint_arraycopy = StubRoutines::_jint_arraycopy; |
3097 #endif | 3125 #endif |
3126 | |
3127 StubRoutines::_arrayof_jlong_disjoint_arraycopy = generate_disjoint_long_copy(true, NULL, | |
3128 "arrayof_jlong_disjoint_arraycopy"); | |
3129 StubRoutines::_arrayof_oop_disjoint_arraycopy = generate_disjoint_oop_copy(true, NULL, | |
3130 "arrayof_oop_disjoint_arraycopy"); | |
3131 | |
3098 StubRoutines::_arrayof_jlong_arraycopy = StubRoutines::_jlong_arraycopy; | 3132 StubRoutines::_arrayof_jlong_arraycopy = StubRoutines::_jlong_arraycopy; |
3099 StubRoutines::_arrayof_oop_arraycopy = StubRoutines::_oop_arraycopy; | 3133 StubRoutines::_arrayof_oop_arraycopy = StubRoutines::_oop_arraycopy; |
3100 | 3134 |
3101 StubRoutines::_checkcast_arraycopy = generate_checkcast_copy("checkcast_arraycopy"); | 3135 StubRoutines::_checkcast_arraycopy = generate_checkcast_copy("checkcast_arraycopy", &entry_checkcast_arraycopy); |
3102 StubRoutines::_unsafe_arraycopy = generate_unsafe_copy("unsafe_arraycopy"); | 3136 StubRoutines::_unsafe_arraycopy = generate_unsafe_copy("unsafe_arraycopy", |
3103 StubRoutines::_generic_arraycopy = generate_generic_copy("generic_arraycopy"); | 3137 entry_jbyte_arraycopy, |
3138 entry_jshort_arraycopy, | |
3139 entry_jint_arraycopy, | |
3140 entry_jlong_arraycopy); | |
3141 StubRoutines::_generic_arraycopy = generate_generic_copy("generic_arraycopy", | |
3142 entry_jbyte_arraycopy, | |
3143 entry_jshort_arraycopy, | |
3144 entry_jint_arraycopy, | |
3145 entry_oop_arraycopy, | |
3146 entry_jlong_arraycopy, | |
3147 entry_checkcast_arraycopy); | |
3104 | 3148 |
3105 StubRoutines::_jbyte_fill = generate_fill(T_BYTE, false, "jbyte_fill"); | 3149 StubRoutines::_jbyte_fill = generate_fill(T_BYTE, false, "jbyte_fill"); |
3106 StubRoutines::_jshort_fill = generate_fill(T_SHORT, false, "jshort_fill"); | 3150 StubRoutines::_jshort_fill = generate_fill(T_SHORT, false, "jshort_fill"); |
3107 StubRoutines::_jint_fill = generate_fill(T_INT, false, "jint_fill"); | 3151 StubRoutines::_jint_fill = generate_fill(T_INT, false, "jint_fill"); |
3108 StubRoutines::_arrayof_jbyte_fill = generate_fill(T_BYTE, true, "arrayof_jbyte_fill"); | 3152 StubRoutines::_arrayof_jbyte_fill = generate_fill(T_BYTE, true, "arrayof_jbyte_fill"); |
3222 } | 3266 } |
3223 } | 3267 } |
3224 | 3268 |
3225 }; // end class declaration | 3269 }; // end class declaration |
3226 | 3270 |
3227 | |
3228 address StubGenerator::disjoint_byte_copy_entry = NULL; | |
3229 address StubGenerator::disjoint_short_copy_entry = NULL; | |
3230 address StubGenerator::disjoint_int_copy_entry = NULL; | |
3231 address StubGenerator::disjoint_long_copy_entry = NULL; | |
3232 address StubGenerator::disjoint_oop_copy_entry = NULL; | |
3233 | |
3234 address StubGenerator::byte_copy_entry = NULL; | |
3235 address StubGenerator::short_copy_entry = NULL; | |
3236 address StubGenerator::int_copy_entry = NULL; | |
3237 address StubGenerator::long_copy_entry = NULL; | |
3238 address StubGenerator::oop_copy_entry = NULL; | |
3239 | |
3240 address StubGenerator::checkcast_copy_entry = NULL; | |
3241 | |
3242 void StubGenerator_generate(CodeBuffer* code, bool all) { | 3271 void StubGenerator_generate(CodeBuffer* code, bool all) { |
3243 StubGenerator g(code, all); | 3272 StubGenerator g(code, all); |
3244 } | 3273 } |