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/cardTableModRefBS.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/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
|
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::CardTableModRef:
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::CardTableModRef:
911 {
912 CardTableModRefBS* ctbs = barrier_set_cast<CardTableModRefBS>(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 BarrierSetCodeGen *bs = Universe::heap()->barrier_set()->code_gen();
2272 DecoratorSet decorators = ARRAYCOPY_DISJOINT;
2273 if (dest_uninitialized) {
2274 decorators |= AS_DEST_NOT_INITIALIZED;
2275
2276 }
2277 if (aligned) {
2278 decorators |= ARRAYCOPY_ALIGNED;
2279 }
2280 bs->arraycopy_prologue(_masm, decorators, T_OBJECT, from, to, count);
2281 assert_clean_int(count, O3); // Make sure 'count' is clean int.
2282 if (UseCompressedOops) {
2283 generate_disjoint_int_copy_core(aligned);
2284 } else {
2285 generate_disjoint_long_copy_core(aligned);
2286 }
2287 bs->arraycopy_epilogue(_masm, decorators, T_OBJECT, from, to, count);
2288
2289 // O3, O4 are used as temp registers
2290 inc_counter_np(SharedRuntime::_oop_array_copy_ctr, O3, O4);
2291 __ retl();
2292 __ delayed()->mov(G0, O0); // return 0
2293 return start;
2294 }
2295
2296 // Generate stub for conjoint oop copy. If "aligned" is true, the
2297 // "from" and "to" addresses are assumed to be heapword aligned.
2298 //
2299 // Arguments for generated stub:
2300 // from: O0
2301 // to: O1
2302 // count: O2 treated as signed
2303 //
2304 address generate_conjoint_oop_copy(bool aligned, address nooverlap_target,
2305 address *entry, const char *name,
2306 bool dest_uninitialized = false) {
2307
2308 const Register from = O0; // source array address
2309 const Register to = O1; // destination array address
2310 const Register count = O2; // elements count
2311
2312 __ align(CodeEntryAlignment);
2313 StubCodeMark mark(this, "StubRoutines", name);
2314 address start = __ pc();
2315
2316 assert_clean_int(count, O3); // Make sure 'count' is clean int.
2317
2318 if (entry != NULL) {
2319 *entry = __ pc();
2320 // caller can pass a 64-bit byte count here
2321 BLOCK_COMMENT("Entry:");
2322 }
2323
2324 array_overlap_test(nooverlap_target, LogBytesPerHeapOop);
2325
2326 BarrierSetCodeGen *bs = Universe::heap()->barrier_set()->code_gen();
2327 DecoratorSet decorators = 0;
2328 if (dest_uninitialized) {
2329 decorators |= AS_DEST_NOT_INITIALIZED;
2330 }
2331 if (aligned) {
2332 decorators |= ARRAYCOPY_ALIGNED;
2333 }
2334 bs->arraycopy_prologue(_masm, decorators, T_OBJECT, from, to, count);
2335 if (UseCompressedOops) {
2336 generate_conjoint_int_copy_core(aligned);
2337 } else {
2338 generate_conjoint_long_copy_core(aligned);
2339 }
2340 bs->arraycopy_epilogue(_masm, decorators, T_OBJECT, from, to, count);
2341
2342 // O3, O4 are used as temp registers
2343 inc_counter_np(SharedRuntime::_oop_array_copy_ctr, O3, O4);
2344 __ retl();
2345 __ delayed()->mov(G0, O0); // return 0
2346 return start;
2347 }
2348
2349
2350 // Helper for generating a dynamic type check.
2351 // Smashes only the given temp registers.
2352 void generate_type_check(Register sub_klass,
2353 Register super_check_offset,
2354 Register super_klass,
2355 Register temp,
2356 Label& L_success) {
2357 assert_different_registers(sub_klass, super_check_offset, super_klass, temp);
2358
2359 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 //
|
2422
2423 #ifdef ASSERT
2424 // caller guarantees that the arrays really are different
2425 // otherwise, we would have to make conjoint checks
2426 { Label L;
2427 __ mov(O3, G1); // spill: overlap test smashes O3
2428 __ mov(O4, G4); // spill: overlap test smashes O4
2429 array_overlap_test(L, LogBytesPerHeapOop);
2430 __ stop("checkcast_copy within a single array");
2431 __ bind(L);
2432 __ mov(G1, O3);
2433 __ mov(G4, O4);
2434 }
2435 #endif //ASSERT
2436
2437 if (entry != NULL) {
2438 *entry = __ pc();
2439 // caller can pass a 64-bit byte count here (from generic stub)
2440 BLOCK_COMMENT("Entry:");
2441 }
2442
2443 BarrierSetCodeGen *bs = Universe::heap()->barrier_set()->code_gen();
2444 DecoratorSet decorators = ARRAYCOPY_CHECKCAST;
2445 if (dest_uninitialized) {
2446 decorators |= AS_DEST_NOT_INITIALIZED;
2447 }
2448
2449 bs->arraycopy_prologue(_masm, decorators, T_OBJECT, O0_from, O1_to, O2_count);
2450
2451 Label load_element, store_element, do_epilogue, fail, done;
2452 __ addcc(O2_count, 0, G1_remain); // initialize loop index, and test it
2453 __ brx(Assembler::notZero, false, Assembler::pt, load_element);
2454 __ delayed()->mov(G0, O5_offset); // offset from start of arrays
2455
2456 // Empty array: Nothing to do.
2457 inc_counter_np(SharedRuntime::_checkcast_array_copy_ctr, O3, O4);
2458 __ retl();
2459 __ delayed()->set(0, O0); // return 0 on (trivial) success
2460
2461 // ======== begin loop ========
2462 // (Loop is rotated; its entry is load_element.)
2463 // Loop variables:
2464 // (O5 = 0; ; O5 += wordSize) --- offset from src, dest arrays
2465 // (O2 = len; O2 != 0; O2--) --- number of oops *remaining*
2466 // G3, G4, G5 --- current oop, oop.klass, oop.klass.super
2467 __ align(OptoLoopAlignment);
2468
2469 __ BIND(store_element);
2470 __ deccc(G1_remain); // decrement the count
2471 __ store_heap_oop(G3_oop, O1_to, O5_offset); // store the oop
2472 __ inc(O5_offset, heapOopSize); // step to next offset
2473 __ brx(Assembler::zero, true, Assembler::pt, do_epilogue);
2474 __ delayed()->set(0, O0); // return -1 on success
2475
2476 // ======== loop entry is here ========
2477 __ BIND(load_element);
2478 __ load_heap_oop(O0_from, O5_offset, G3_oop); // load the oop
2479 __ br_null_short(G3_oop, Assembler::pt, store_element);
2480
2481 __ load_klass(G3_oop, G4_klass); // query the object klass
2482
2483 generate_type_check(G4_klass, O3_ckoff, O4_ckval, G5_super,
2484 // branch to this on success:
2485 store_element);
2486 // ======== end loop ========
2487
2488 // It was a real error; we must depend on the caller to finish the job.
2489 // Register G1 has number of *remaining* oops, O2 number of *total* oops.
2490 // Emit GC store barriers for the oops we have copied (O2 minus G1),
2491 // and report their number to the caller.
2492 __ BIND(fail);
2493 __ subcc(O2_count, G1_remain, O2_count);
2494 __ brx(Assembler::zero, false, Assembler::pt, done);
2495 __ delayed()->not1(O2_count, O0); // report (-1^K) to caller
2496
2497 __ BIND(do_epilogue);
2498 bs->arraycopy_epilogue(_masm, decorators, T_OBJECT, O0_from, O1_to, O2_count);
2499
2500 __ BIND(done);
2501 inc_counter_np(SharedRuntime::_checkcast_array_copy_ctr, O3, O4);
2502 __ retl();
2503 __ delayed()->nop(); // return value in 00
2504
2505 return start;
2506 }
2507
2508
2509 // Generate 'unsafe' array copy stub
2510 // Though just as safe as the other stubs, it takes an unscaled
2511 // size_t argument instead of an element count.
2512 //
2513 // Arguments for generated stub:
2514 // from: O0
2515 // to: O1
2516 // count: O2 byte count, treated as ssize_t, can be zero
2517 //
|