< prev index next >

src/cpu/sparc/vm/stubGenerator_sparc.cpp

Print this page
rev 12906 : [mq]: gc_interface


   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


< prev index next >