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