7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "asm/macroAssembler.inline.hpp"
27 #include "interpreter/interpreter.hpp"
28 #include "nativeInst_sparc.hpp"
29 #include "oops/instanceOop.hpp"
30 #include "oops/method.hpp"
31 #include "oops/objArrayKlass.hpp"
32 #include "oops/oop.inline.hpp"
33 #include "prims/methodHandles.hpp"
34 #include "runtime/frame.inline.hpp"
35 #include "runtime/handles.inline.hpp"
36 #include "runtime/sharedRuntime.hpp"
37 #include "runtime/stubCodeGenerator.hpp"
38 #include "runtime/stubRoutines.hpp"
39 #include "runtime/thread.inline.hpp"
40 #ifdef COMPILER2
41 #include "opto/runtime.hpp"
42 #endif
43
44 // Declaration and definition of StubGenerator (no .hpp file).
45 // For a more detailed description of the stub routine structure
46 // see the comment in stubRoutines.hpp.
806 const Register to = O1;
807 const Register count = O2;
808 const Register to_from = O3; // to - from
809 const Register byte_count = O4; // count << log2_elem_size
810
811 __ subcc(to, from, to_from);
812 __ sll_ptr(count, log2_elem_size, byte_count);
813 if (NOLp == NULL)
814 __ brx(Assembler::lessEqualUnsigned, false, Assembler::pt, no_overlap_target);
815 else
816 __ brx(Assembler::lessEqualUnsigned, false, Assembler::pt, (*NOLp));
817 __ delayed()->cmp(to_from, byte_count);
818 if (NOLp == NULL)
819 __ brx(Assembler::greaterEqualUnsigned, false, Assembler::pt, no_overlap_target);
820 else
821 __ brx(Assembler::greaterEqualUnsigned, false, Assembler::pt, (*NOLp));
822 __ delayed()->nop();
823 }
824
825 //
826 // Generate pre-write barrier for array.
827 //
828 // Input:
829 // addr - register containing starting address
830 // count - register containing element count
831 // tmp - scratch register
832 //
833 // The input registers are overwritten.
834 //
835 void gen_write_ref_array_pre_barrier(Register addr, Register count, bool dest_uninitialized) {
836 BarrierSet* bs = Universe::heap()->barrier_set();
837 switch (bs->kind()) {
838 case BarrierSet::G1SATBCTLogging:
839 // With G1, don't generate the call if we statically know that the target in uninitialized
840 if (!dest_uninitialized) {
841 __ save_frame(0);
842 // Save the necessary global regs... will be used after.
843 if (addr->is_global()) {
844 __ mov(addr, L0);
845 }
846 if (count->is_global()) {
847 __ mov(count, L1);
848 }
849 __ mov(addr->after_save(), O0);
850 // Get the count into O1
851 __ call(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre));
852 __ delayed()->mov(count->after_save(), O1);
853 if (addr->is_global()) {
854 __ mov(L0, addr);
855 }
856 if (count->is_global()) {
857 __ mov(L1, count);
858 }
859 __ restore();
860 }
861 break;
862 case BarrierSet::CardTableForRS:
863 case BarrierSet::CardTableExtension:
864 case BarrierSet::ModRef:
865 break;
866 default:
867 ShouldNotReachHere();
868 }
869 }
870 //
871 // Generate post-write barrier for array.
872 //
873 // Input:
874 // addr - register containing starting address
875 // count - register containing element count
876 // tmp - scratch register
877 //
878 // The input registers are overwritten.
879 //
880 void gen_write_ref_array_post_barrier(Register addr, Register count,
881 Register tmp) {
882 BarrierSet* bs = Universe::heap()->barrier_set();
883
884 switch (bs->kind()) {
885 case BarrierSet::G1SATBCTLogging:
886 {
887 // Get some new fresh output registers.
888 __ save_frame(0);
889 __ mov(addr->after_save(), O0);
890 __ call(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post));
891 __ delayed()->mov(count->after_save(), O1);
892 __ restore();
893 }
894 break;
895 case BarrierSet::CardTableForRS:
896 case BarrierSet::CardTableExtension:
897 {
898 CardTableModRefBS* ct = barrier_set_cast<CardTableModRefBS>(bs);
899 assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
900 assert_different_registers(addr, count, tmp);
901
902 Label L_loop;
903
904 __ sll_ptr(count, LogBytesPerHeapOop, count);
905 __ sub(count, BytesPerHeapOop, count);
906 __ add(count, addr, count);
907 // Use two shifts to clear out those low order two bits! (Cannot opt. into 1.)
908 __ srl_ptr(addr, CardTableModRefBS::card_shift, addr);
909 __ srl_ptr(count, CardTableModRefBS::card_shift, count);
910 __ sub(count, addr, count);
911 AddressLiteral rs(ct->byte_map_base);
912 __ set(rs, tmp);
913 __ BIND(L_loop);
914 __ stb(G0, tmp, addr);
915 __ subcc(count, 1, count);
916 __ brx(Assembler::greaterEqual, false, Assembler::pt, L_loop);
917 __ delayed()->add(addr, 1, addr);
918 }
919 break;
920 case BarrierSet::ModRef:
921 break;
922 default:
923 ShouldNotReachHere();
924 }
925 }
926
927 //
928 // Generate main code for disjoint arraycopy
929 //
930 typedef void (StubGenerator::*CopyLoopFunc)(Register from, Register to, Register count, int count_dec,
931 Label& L_loop, bool use_prefetch, bool use_bis);
932
933 void disjoint_copy_core(Register from, Register to, Register count, int log2_elem_size,
934 int iter_size, StubGenerator::CopyLoopFunc copy_loop_func) {
935 Label L_copy;
936
937 assert(log2_elem_size <= 3, "the following code should be changed");
938 int count_dec = 16>>log2_elem_size;
939
940 int prefetch_dist = MAX2(ArraycopySrcPrefetchDistance, ArraycopyDstPrefetchDistance);
941 assert(prefetch_dist < 4096, "invalid value");
942 prefetch_dist = (prefetch_dist + (iter_size-1)) & (-iter_size); // round up to one iteration copy size
943 int prefetch_count = (prefetch_dist >> log2_elem_size); // elements count
944
945 if (UseBlockCopy) {
946 Label L_block_copy, L_block_copy_prefetch, L_skip_block_copy;
947
2355 //
2356 address generate_disjoint_oop_copy(bool aligned, address *entry, const char *name,
2357 bool dest_uninitialized = false) {
2358
2359 const Register from = O0; // source array address
2360 const Register to = O1; // destination array address
2361 const Register count = O2; // elements count
2362
2363 __ align(CodeEntryAlignment);
2364 StubCodeMark mark(this, "StubRoutines", name);
2365 address start = __ pc();
2366
2367 assert_clean_int(count, O3); // Make sure 'count' is clean int.
2368
2369 if (entry != NULL) {
2370 *entry = __ pc();
2371 // caller can pass a 64-bit byte count here
2372 BLOCK_COMMENT("Entry:");
2373 }
2374
2375 // save arguments for barrier generation
2376 __ mov(to, G1);
2377 __ mov(count, G5);
2378 gen_write_ref_array_pre_barrier(G1, G5, dest_uninitialized);
2379 assert_clean_int(count, O3); // Make sure 'count' is clean int.
2380 if (UseCompressedOops) {
2381 generate_disjoint_int_copy_core(aligned);
2382 } else {
2383 generate_disjoint_long_copy_core(aligned);
2384 }
2385 // O0 is used as temp register
2386 gen_write_ref_array_post_barrier(G1, G5, O0);
2387
2388 // O3, O4 are used as temp registers
2389 inc_counter_np(SharedRuntime::_oop_array_copy_ctr, O3, O4);
2390 __ retl();
2391 __ delayed()->mov(G0, O0); // return 0
2392 return start;
2393 }
2394
2395 // Generate stub for conjoint oop copy. If "aligned" is true, the
2396 // "from" and "to" addresses are assumed to be heapword aligned.
2397 //
2398 // Arguments for generated stub:
2399 // from: O0
2400 // to: O1
2401 // count: O2 treated as signed
2402 //
2403 address generate_conjoint_oop_copy(bool aligned, address nooverlap_target,
2404 address *entry, const char *name,
2405 bool dest_uninitialized = false) {
2406
2407 const Register from = O0; // source array address
2408 const Register to = O1; // destination array address
2409 const Register count = O2; // elements count
2410
2411 __ align(CodeEntryAlignment);
2412 StubCodeMark mark(this, "StubRoutines", name);
2413 address start = __ pc();
2414
2415 assert_clean_int(count, O3); // Make sure 'count' is clean int.
2416
2417 if (entry != NULL) {
2418 *entry = __ pc();
2419 // caller can pass a 64-bit byte count here
2420 BLOCK_COMMENT("Entry:");
2421 }
2422
2423 array_overlap_test(nooverlap_target, LogBytesPerHeapOop);
2424
2425 // save arguments for barrier generation
2426 __ mov(to, G1);
2427 __ mov(count, G5);
2428 gen_write_ref_array_pre_barrier(G1, G5, dest_uninitialized);
2429
2430 if (UseCompressedOops) {
2431 generate_conjoint_int_copy_core(aligned);
2432 } else {
2433 generate_conjoint_long_copy_core(aligned);
2434 }
2435
2436 // O0 is used as temp register
2437 gen_write_ref_array_post_barrier(G1, G5, O0);
2438
2439 // O3, O4 are used as temp registers
2440 inc_counter_np(SharedRuntime::_oop_array_copy_ctr, O3, O4);
2441 __ retl();
2442 __ delayed()->mov(G0, O0); // return 0
2443 return start;
2444 }
2445
2446
2447 // Helper for generating a dynamic type check.
2448 // Smashes only the given temp registers.
2449 void generate_type_check(Register sub_klass,
2450 Register super_check_offset,
2451 Register super_klass,
2452 Register temp,
2453 Label& L_success) {
2454 assert_different_registers(sub_klass, super_check_offset, super_klass, temp);
2455
2456 BLOCK_COMMENT("type_check:");
2457
2519
2520 #ifdef ASSERT
2521 // caller guarantees that the arrays really are different
2522 // otherwise, we would have to make conjoint checks
2523 { Label L;
2524 __ mov(O3, G1); // spill: overlap test smashes O3
2525 __ mov(O4, G4); // spill: overlap test smashes O4
2526 array_overlap_test(L, LogBytesPerHeapOop);
2527 __ stop("checkcast_copy within a single array");
2528 __ bind(L);
2529 __ mov(G1, O3);
2530 __ mov(G4, O4);
2531 }
2532 #endif //ASSERT
2533
2534 if (entry != NULL) {
2535 *entry = __ pc();
2536 // caller can pass a 64-bit byte count here (from generic stub)
2537 BLOCK_COMMENT("Entry:");
2538 }
2539 gen_write_ref_array_pre_barrier(O1_to, O2_count, dest_uninitialized);
2540
2541 Label load_element, store_element, do_card_marks, fail, done;
2542 __ addcc(O2_count, 0, G1_remain); // initialize loop index, and test it
2543 __ brx(Assembler::notZero, false, Assembler::pt, load_element);
2544 __ delayed()->mov(G0, O5_offset); // offset from start of arrays
2545
2546 // Empty array: Nothing to do.
2547 inc_counter_np(SharedRuntime::_checkcast_array_copy_ctr, O3, O4);
2548 __ retl();
2549 __ delayed()->set(0, O0); // return 0 on (trivial) success
2550
2551 // ======== begin loop ========
2552 // (Loop is rotated; its entry is load_element.)
2553 // Loop variables:
2554 // (O5 = 0; ; O5 += wordSize) --- offset from src, dest arrays
2555 // (O2 = len; O2 != 0; O2--) --- number of oops *remaining*
2556 // G3, G4, G5 --- current oop, oop.klass, oop.klass.super
2557 __ align(OptoLoopAlignment);
2558
2559 __ BIND(store_element);
2560 __ deccc(G1_remain); // decrement the count
2561 __ store_heap_oop(G3_oop, O1_to, O5_offset); // store the oop
2562 __ inc(O5_offset, heapOopSize); // step to next offset
2563 __ brx(Assembler::zero, true, Assembler::pt, do_card_marks);
2564 __ delayed()->set(0, O0); // return -1 on success
2565
2566 // ======== loop entry is here ========
2567 __ BIND(load_element);
2568 __ load_heap_oop(O0_from, O5_offset, G3_oop); // load the oop
2569 __ br_null_short(G3_oop, Assembler::pt, store_element);
2570
2571 __ load_klass(G3_oop, G4_klass); // query the object klass
2572
2573 generate_type_check(G4_klass, O3_ckoff, O4_ckval, G5_super,
2574 // branch to this on success:
2575 store_element);
2576 // ======== end loop ========
2577
2578 // It was a real error; we must depend on the caller to finish the job.
2579 // Register G1 has number of *remaining* oops, O2 number of *total* oops.
2580 // Emit GC store barriers for the oops we have copied (O2 minus G1),
2581 // and report their number to the caller.
2582 __ BIND(fail);
2583 __ subcc(O2_count, G1_remain, O2_count);
2584 __ brx(Assembler::zero, false, Assembler::pt, done);
2585 __ delayed()->not1(O2_count, O0); // report (-1^K) to caller
2586
2587 __ BIND(do_card_marks);
2588 gen_write_ref_array_post_barrier(O1_to, O2_count, O3); // store check on O1[0..O2]
2589
2590 __ BIND(done);
2591 inc_counter_np(SharedRuntime::_checkcast_array_copy_ctr, O3, O4);
2592 __ retl();
2593 __ delayed()->nop(); // return value in 00
2594
2595 return start;
2596 }
2597
2598
2599 // Generate 'unsafe' array copy stub
2600 // Though just as safe as the other stubs, it takes an unscaled
2601 // size_t argument instead of an element count.
2602 //
2603 // Arguments for generated stub:
2604 // from: O0
2605 // to: O1
2606 // count: O2 byte count, treated as ssize_t, can be zero
2607 //
2608 // Examines the alignment of the operands and dispatches
|
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "asm/macroAssembler.inline.hpp"
27 #include "gc/shared/barrierSetCodeGen.hpp"
28 #include "interpreter/interpreter.hpp"
29 #include "nativeInst_sparc.hpp"
30 #include "oops/instanceOop.hpp"
31 #include "oops/method.hpp"
32 #include "oops/objArrayKlass.hpp"
33 #include "oops/oop.inline.hpp"
34 #include "prims/methodHandles.hpp"
35 #include "runtime/frame.inline.hpp"
36 #include "runtime/handles.inline.hpp"
37 #include "runtime/sharedRuntime.hpp"
38 #include "runtime/stubCodeGenerator.hpp"
39 #include "runtime/stubRoutines.hpp"
40 #include "runtime/thread.inline.hpp"
41 #ifdef COMPILER2
42 #include "opto/runtime.hpp"
43 #endif
44
45 // Declaration and definition of StubGenerator (no .hpp file).
46 // For a more detailed description of the stub routine structure
47 // see the comment in stubRoutines.hpp.
807 const Register to = O1;
808 const Register count = O2;
809 const Register to_from = O3; // to - from
810 const Register byte_count = O4; // count << log2_elem_size
811
812 __ subcc(to, from, to_from);
813 __ sll_ptr(count, log2_elem_size, byte_count);
814 if (NOLp == NULL)
815 __ brx(Assembler::lessEqualUnsigned, false, Assembler::pt, no_overlap_target);
816 else
817 __ brx(Assembler::lessEqualUnsigned, false, Assembler::pt, (*NOLp));
818 __ delayed()->cmp(to_from, byte_count);
819 if (NOLp == NULL)
820 __ brx(Assembler::greaterEqualUnsigned, false, Assembler::pt, no_overlap_target);
821 else
822 __ brx(Assembler::greaterEqualUnsigned, false, Assembler::pt, (*NOLp));
823 __ delayed()->nop();
824 }
825
826 //
827 // Generate main code for disjoint arraycopy
828 //
829 typedef void (StubGenerator::*CopyLoopFunc)(Register from, Register to, Register count, int count_dec,
830 Label& L_loop, bool use_prefetch, bool use_bis);
831
832 void disjoint_copy_core(Register from, Register to, Register count, int log2_elem_size,
833 int iter_size, StubGenerator::CopyLoopFunc copy_loop_func) {
834 Label L_copy;
835
836 assert(log2_elem_size <= 3, "the following code should be changed");
837 int count_dec = 16>>log2_elem_size;
838
839 int prefetch_dist = MAX2(ArraycopySrcPrefetchDistance, ArraycopyDstPrefetchDistance);
840 assert(prefetch_dist < 4096, "invalid value");
841 prefetch_dist = (prefetch_dist + (iter_size-1)) & (-iter_size); // round up to one iteration copy size
842 int prefetch_count = (prefetch_dist >> log2_elem_size); // elements count
843
844 if (UseBlockCopy) {
845 Label L_block_copy, L_block_copy_prefetch, L_skip_block_copy;
846
2254 //
2255 address generate_disjoint_oop_copy(bool aligned, address *entry, const char *name,
2256 bool dest_uninitialized = false) {
2257
2258 const Register from = O0; // source array address
2259 const Register to = O1; // destination array address
2260 const Register count = O2; // elements count
2261
2262 __ align(CodeEntryAlignment);
2263 StubCodeMark mark(this, "StubRoutines", name);
2264 address start = __ pc();
2265
2266 assert_clean_int(count, O3); // Make sure 'count' is clean int.
2267
2268 if (entry != NULL) {
2269 *entry = __ pc();
2270 // caller can pass a 64-bit byte count here
2271 BLOCK_COMMENT("Entry:");
2272 }
2273
2274 BarrierSetCodeGen *bs = Universe::heap()->barrier_set()->code_gen();
2275 DecoratorSet decorators = DEST_COVARIANT | DEST_DISJOINT;
2276 if (dest_uninitialized) {
2277 decorators |= DEST_NOT_INITIALIZED;
2278
2279 }
2280 if (aligned) {
2281 decorators |= ACCESS_ALIGNED;
2282 }
2283 bs->arraycopy_prologue(_masm, decorators, T_OBJECT, from, to, count);
2284 assert_clean_int(count, O3); // Make sure 'count' is clean int.
2285 if (UseCompressedOops) {
2286 generate_disjoint_int_copy_core(aligned);
2287 } else {
2288 generate_disjoint_long_copy_core(aligned);
2289 }
2290 bs->arraycopy_epilogue(_masm, decorators, T_OBJECT, from, to, count);
2291
2292 // O3, O4 are used as temp registers
2293 inc_counter_np(SharedRuntime::_oop_array_copy_ctr, O3, O4);
2294 __ retl();
2295 __ delayed()->mov(G0, O0); // return 0
2296 return start;
2297 }
2298
2299 // Generate stub for conjoint oop copy. If "aligned" is true, the
2300 // "from" and "to" addresses are assumed to be heapword aligned.
2301 //
2302 // Arguments for generated stub:
2303 // from: O0
2304 // to: O1
2305 // count: O2 treated as signed
2306 //
2307 address generate_conjoint_oop_copy(bool aligned, address nooverlap_target,
2308 address *entry, const char *name,
2309 bool dest_uninitialized = false) {
2310
2311 const Register from = O0; // source array address
2312 const Register to = O1; // destination array address
2313 const Register count = O2; // elements count
2314
2315 __ align(CodeEntryAlignment);
2316 StubCodeMark mark(this, "StubRoutines", name);
2317 address start = __ pc();
2318
2319 assert_clean_int(count, O3); // Make sure 'count' is clean int.
2320
2321 if (entry != NULL) {
2322 *entry = __ pc();
2323 // caller can pass a 64-bit byte count here
2324 BLOCK_COMMENT("Entry:");
2325 }
2326
2327 array_overlap_test(nooverlap_target, LogBytesPerHeapOop);
2328
2329 BarrierSetCodeGen *bs = Universe::heap()->barrier_set()->code_gen();
2330 DecoratorSet decorators = DEST_COVARIANT | DEST_CONJOINT;
2331 if (dest_uninitialized) {
2332 decorators |= DEST_NOT_INITIALIZED;
2333 }
2334 if (aligned) {
2335 decorators |= ACCESS_ALIGNED;
2336 }
2337 bs->arraycopy_prologue(_masm, decorators, T_OBJECT, from, to, count);
2338 if (UseCompressedOops) {
2339 generate_conjoint_int_copy_core(aligned);
2340 } else {
2341 generate_conjoint_long_copy_core(aligned);
2342 }
2343 bs->arraycopy_epilogue(_masm, decorators, T_OBJECT, from, to, count);
2344
2345 // O3, O4 are used as temp registers
2346 inc_counter_np(SharedRuntime::_oop_array_copy_ctr, O3, O4);
2347 __ retl();
2348 __ delayed()->mov(G0, O0); // return 0
2349 return start;
2350 }
2351
2352
2353 // Helper for generating a dynamic type check.
2354 // Smashes only the given temp registers.
2355 void generate_type_check(Register sub_klass,
2356 Register super_check_offset,
2357 Register super_klass,
2358 Register temp,
2359 Label& L_success) {
2360 assert_different_registers(sub_klass, super_check_offset, super_klass, temp);
2361
2362 BLOCK_COMMENT("type_check:");
2363
2425
2426 #ifdef ASSERT
2427 // caller guarantees that the arrays really are different
2428 // otherwise, we would have to make conjoint checks
2429 { Label L;
2430 __ mov(O3, G1); // spill: overlap test smashes O3
2431 __ mov(O4, G4); // spill: overlap test smashes O4
2432 array_overlap_test(L, LogBytesPerHeapOop);
2433 __ stop("checkcast_copy within a single array");
2434 __ bind(L);
2435 __ mov(G1, O3);
2436 __ mov(G4, O4);
2437 }
2438 #endif //ASSERT
2439
2440 if (entry != NULL) {
2441 *entry = __ pc();
2442 // caller can pass a 64-bit byte count here (from generic stub)
2443 BLOCK_COMMENT("Entry:");
2444 }
2445
2446 BarrierSetCodeGen *bs = Universe::heap()->barrier_set()->code_gen();
2447 DecoratorSet decorators = DEST_DISJOINT;
2448 if (dest_uninitialized) {
2449 decorators |= DEST_NOT_INITIALIZED;
2450 }
2451
2452 bs->arraycopy_prologue(_masm, decorators, T_OBJECT, O0_from, O1_to, O2_count);
2453
2454 Label load_element, store_element, do_epilogue, fail, done;
2455 __ addcc(O2_count, 0, G1_remain); // initialize loop index, and test it
2456 __ brx(Assembler::notZero, false, Assembler::pt, load_element);
2457 __ delayed()->mov(G0, O5_offset); // offset from start of arrays
2458
2459 // Empty array: Nothing to do.
2460 inc_counter_np(SharedRuntime::_checkcast_array_copy_ctr, O3, O4);
2461 __ retl();
2462 __ delayed()->set(0, O0); // return 0 on (trivial) success
2463
2464 // ======== begin loop ========
2465 // (Loop is rotated; its entry is load_element.)
2466 // Loop variables:
2467 // (O5 = 0; ; O5 += wordSize) --- offset from src, dest arrays
2468 // (O2 = len; O2 != 0; O2--) --- number of oops *remaining*
2469 // G3, G4, G5 --- current oop, oop.klass, oop.klass.super
2470 __ align(OptoLoopAlignment);
2471
2472 __ BIND(store_element);
2473 __ deccc(G1_remain); // decrement the count
2474 __ store_heap_oop(G3_oop, O1_to, O5_offset); // store the oop
2475 __ inc(O5_offset, heapOopSize); // step to next offset
2476 __ brx(Assembler::zero, true, Assembler::pt, do_epilogue);
2477 __ delayed()->set(0, O0); // return -1 on success
2478
2479 // ======== loop entry is here ========
2480 __ BIND(load_element);
2481 __ load_heap_oop(O0_from, O5_offset, G3_oop); // load the oop
2482 __ br_null_short(G3_oop, Assembler::pt, store_element);
2483
2484 __ load_klass(G3_oop, G4_klass); // query the object klass
2485
2486 generate_type_check(G4_klass, O3_ckoff, O4_ckval, G5_super,
2487 // branch to this on success:
2488 store_element);
2489 // ======== end loop ========
2490
2491 // It was a real error; we must depend on the caller to finish the job.
2492 // Register G1 has number of *remaining* oops, O2 number of *total* oops.
2493 // Emit GC store barriers for the oops we have copied (O2 minus G1),
2494 // and report their number to the caller.
2495 __ BIND(fail);
2496 __ subcc(O2_count, G1_remain, O2_count);
2497 __ brx(Assembler::zero, false, Assembler::pt, done);
2498 __ delayed()->not1(O2_count, O0); // report (-1^K) to caller
2499
2500 __ BIND(do_epilogue);
2501 bs->arraycopy_epilogue(_masm, decorators, T_OBJECT, O0_from, O1_to, O2_count);
2502
2503 __ BIND(done);
2504 inc_counter_np(SharedRuntime::_checkcast_array_copy_ctr, O3, O4);
2505 __ retl();
2506 __ delayed()->nop(); // return value in 00
2507
2508 return start;
2509 }
2510
2511
2512 // Generate 'unsafe' array copy stub
2513 // Though just as safe as the other stubs, it takes an unscaled
2514 // size_t argument instead of an element count.
2515 //
2516 // Arguments for generated stub:
2517 // from: O0
2518 // to: O1
2519 // count: O2 byte count, treated as ssize_t, can be zero
2520 //
2521 // Examines the alignment of the operands and dispatches
|