src/cpu/sparc/vm/stubGenerator_sparc.cpp

Print this page
rev 146 : [mq]: mixa.layout.patch


2683     }
2684 
2685 #ifdef ASSERT
2686     //  assert(src->klass() != NULL);
2687     BLOCK_COMMENT("assert klasses not null");
2688     { Label L_a, L_b;
2689       __ br_notnull(G3_src_klass, false, Assembler::pt, L_b); // it is broken if klass is NULL
2690       __ delayed()->nop();
2691       __ bind(L_a);
2692       __ stop("broken null klass");
2693       __ bind(L_b);
2694       __ load_klass(dst, G4_dst_klass);
2695       __ br_null(G4_dst_klass, false, Assembler::pn, L_a); // this would be broken also
2696       __ delayed()->mov(G0, G4_dst_klass);      // scribble the temp
2697       BLOCK_COMMENT("assert done");
2698     }
2699 #endif
2700 
2701     // Load layout helper
2702     //
2703     //  |array_tag|     | header_size | element_type |     |log2_element_size|
2704     // 32        30    24            16              8     2                 0
2705     //
2706     //   array_tag: typeArray = 0x3, objArray = 0x2, non-array = 0x0
2707     //
2708 
2709     int lh_offset = klassOopDesc::header_size() * HeapWordSize +
2710                     Klass::layout_helper_offset_in_bytes();
2711 
2712     // Load 32-bits signed value. Use br() instruction with it to check icc.
2713     __ lduw(G3_src_klass, lh_offset, G5_lh);
2714 
2715     if (UseCompressedOops) {
2716       __ load_klass(dst, G4_dst_klass);
2717     }
2718     // Handle objArrays completely differently...
2719     juint objArray_lh = Klass::array_layout_helper(T_OBJECT);



2720     __ set(objArray_lh, O5_temp);
2721     __ cmp(G5_lh,       O5_temp);
2722     __ br(Assembler::equal, false, Assembler::pt, L_objArray);
2723     if (UseCompressedOops) {
2724       __ delayed()->nop();
2725     } else {
2726       __ delayed()->ld_ptr(dst, oopDesc::klass_offset_in_bytes(), G4_dst_klass);
2727     }
2728 
2729     //  if (src->klass() != dst->klass()) return -1;
2730     __ cmp(G3_src_klass, G4_dst_klass);
2731     __ brx(Assembler::notEqual, false, Assembler::pn, L_failed);
2732     __ delayed()->nop();
2733 
2734     //  if (!src->is_Array()) return -1;
2735     __ cmp(G5_lh, Klass::_lh_neutral_value); // < 0
2736     __ br(Assembler::greaterEqual, false, Assembler::pn, L_failed);
2737 
2738     // At this point, it is known to be a typeArray (array_tag 0x3).
2739 #ifdef ASSERT
2740     __ delayed()->nop();
2741     { Label L;
2742       jint lh_prim_tag_in_place = (Klass::_lh_array_tag_type_value << Klass::_lh_array_tag_shift);
2743       __ set(lh_prim_tag_in_place, O5_temp);
2744       __ cmp(G5_lh,                O5_temp);
2745       __ br(Assembler::greaterEqual, false, Assembler::pt, L);
2746       __ delayed()->nop();
2747       __ stop("must be a primitive array");
2748       __ bind(L);
2749     }
2750 #else
2751     __ delayed();                               // match next insn to prev branch
2752 #endif
2753 
2754     arraycopy_range_checks(src, src_pos, dst, dst_pos, length,
2755                            O5_temp, G4_dst_klass, L_failed);
2756 
2757     // typeArrayKlass
2758     //
2759     // src_addr = (src + array_header_in_bytes()) + (src_pos << log2elemsize);
2760     // dst_addr = (dst + array_header_in_bytes()) + (dst_pos << log2elemsize);
2761     //
2762 
2763     const Register G4_offset = G4_dst_klass;    // array offset
2764     const Register G3_elsize = G3_src_klass;    // log2 element size
2765 
2766     __ srl(G5_lh, Klass::_lh_header_size_shift, G4_offset);
2767     __ and3(G4_offset, Klass::_lh_header_size_mask, G4_offset); // array_offset

2768     __ add(src, G4_offset, src);       // src array offset
2769     __ add(dst, G4_offset, dst);       // dst array offset
2770     __ and3(G5_lh, Klass::_lh_log2_element_size_mask, G3_elsize); // log2 element size

2771 
2772     // next registers should be set before the jump to corresponding stub
2773     const Register from     = O0;  // source array address
2774     const Register to       = O1;  // destination array address
2775     const Register count    = O2;  // elements count
2776 
2777     // 'from', 'to', 'count' registers should be set in this order
2778     // since they are the same as 'src', 'src_pos', 'dst'.
2779 
2780     BLOCK_COMMENT("scale indexes to element size");
2781     __ sll_ptr(src_pos, G3_elsize, src_pos);
2782     __ sll_ptr(dst_pos, G3_elsize, dst_pos);
2783     __ add(src, src_pos, from);       // src_addr
2784     __ add(dst, dst_pos, to);         // dst_addr
2785 
2786     BLOCK_COMMENT("choose copy loop based on element size");
2787     __ cmp(G3_elsize, 0);
2788     __ br(Assembler::equal,true,Assembler::pt,StubRoutines::_jbyte_arraycopy);
2789     __ delayed()->signx(length, count); // length
2790 
2791     __ cmp(G3_elsize, LogBytesPerShort);
2792     __ br(Assembler::equal,true,Assembler::pt,StubRoutines::_jshort_arraycopy);
2793     __ delayed()->signx(length, count); // length
2794 
2795     __ cmp(G3_elsize, LogBytesPerInt);
2796     __ br(Assembler::equal,true,Assembler::pt,StubRoutines::_jint_arraycopy);
2797     __ delayed()->signx(length, count); // length
2798 #ifdef ASSERT
2799     { Label L;
2800       __ cmp(G3_elsize, LogBytesPerLong);
2801       __ br(Assembler::equal, false, Assembler::pt, L);
2802       __ delayed()->nop();
2803       __ stop("must be long copy, but elsize is wrong");
2804       __ bind(L);
2805     }
2806 #endif
2807     __ br(Assembler::always,false,Assembler::pt,StubRoutines::_jlong_arraycopy);
2808     __ delayed()->signx(length, count); // length
2809 


2810     // objArrayKlass
2811   __ BIND(L_objArray);
2812     // live at this point:  G3_src_klass, G4_dst_klass, src[_pos], dst[_pos], length
2813 
2814     Label L_plain_copy, L_checkcast_copy;
2815     //  test array classes for subtyping
2816     __ cmp(G3_src_klass, G4_dst_klass);         // usual case is exact equality
2817     __ brx(Assembler::notEqual, true, Assembler::pn, L_checkcast_copy);
2818     __ delayed()->lduw(G4_dst_klass, lh_offset, O5_temp); // hoisted from below
2819 
2820     // Identically typed arrays can be copied without element-wise checks.
2821     arraycopy_range_checks(src, src_pos, dst, dst_pos, length,
2822                            O5_temp, G5_lh, L_failed);
2823 
2824     __ add(src, arrayOopDesc::base_offset_in_bytes(T_OBJECT), src); //src offset
2825     __ add(dst, arrayOopDesc::base_offset_in_bytes(T_OBJECT), dst); //dst offset
2826     __ sll_ptr(src_pos, LogBytesPerHeapOop, src_pos);
2827     __ sll_ptr(dst_pos, LogBytesPerHeapOop, dst_pos);
2828     __ add(src, src_pos, from);       // src_addr
2829     __ add(dst, dst_pos, to);         // dst_addr
2830   __ BIND(L_plain_copy);
2831     __ br(Assembler::always, false, Assembler::pt,StubRoutines::_oop_arraycopy);
2832     __ delayed()->signx(length, count); // length
2833 
2834   __ BIND(L_checkcast_copy);
2835     // live at this point:  G3_src_klass, G4_dst_klass
2836     {
2837       // Before looking at dst.length, make sure dst is also an objArray.
2838       // lduw(G4_dst_klass, lh_offset, O5_temp); // hoisted to delay slot
2839       __ cmp(G5_lh,                    O5_temp);
2840       __ br(Assembler::notEqual, false, Assembler::pn, L_failed);
2841 
2842       // It is safe to examine both src.length and dst.length.
2843       __ delayed();                             // match next insn to prev branch
2844       arraycopy_range_checks(src, src_pos, dst, dst_pos, length,
2845                              O5_temp, G5_lh, L_failed);
2846 
2847       // Marshal the base address arguments now, freeing registers.
2848       __ add(src, arrayOopDesc::base_offset_in_bytes(T_OBJECT), src); //src offset
2849       __ add(dst, arrayOopDesc::base_offset_in_bytes(T_OBJECT), dst); //dst offset
2850       __ sll_ptr(src_pos, LogBytesPerHeapOop, src_pos);
2851       __ sll_ptr(dst_pos, LogBytesPerHeapOop, dst_pos);
2852       __ add(src, src_pos, from);               // src_addr
2853       __ add(dst, dst_pos, to);                 // dst_addr
2854       __ signx(length, count);                  // length (reloaded)




2683     }
2684 
2685 #ifdef ASSERT
2686     //  assert(src->klass() != NULL);
2687     BLOCK_COMMENT("assert klasses not null");
2688     { Label L_a, L_b;
2689       __ br_notnull(G3_src_klass, false, Assembler::pt, L_b); // it is broken if klass is NULL
2690       __ delayed()->nop();
2691       __ bind(L_a);
2692       __ stop("broken null klass");
2693       __ bind(L_b);
2694       __ load_klass(dst, G4_dst_klass);
2695       __ br_null(G4_dst_klass, false, Assembler::pn, L_a); // this would be broken also
2696       __ delayed()->mov(G0, G4_dst_klass);      // scribble the temp
2697       BLOCK_COMMENT("assert done");
2698     }
2699 #endif
2700 
2701     // Load layout helper
2702     //
2703     //  | array_tag | element_type | log2_element_size | header_size |
2704     // 32          28             24                  16             0
2705     //
2706     //   array_tag: typeArray = 0xF, objArray = 0xD, normal instance = 0x0
2707     //
2708 
2709     int lh_offset = klassOopDesc::header_size() * HeapWordSize +
2710                     Klass::layout_helper_offset_in_bytes();
2711 
2712     // Load 32-bits signed value. Use br() instruction with it to check icc.
2713     __ lduw(G3_src_klass, lh_offset, G5_lh);
2714 
2715     if (UseCompressedOops) {
2716       __ load_klass(dst, G4_dst_klass);
2717     }
2718     // Handle objArrays completely differently...
2719     // This is necessary because they have covariant element types.
2720     // The next type check (for src.klass == dst.klass), can get a
2721     // false negative in the case of object arrays.
2722     jint objArray_lh = LayoutHelper::for_array(T_OBJECT).as_int();
2723     __ set(objArray_lh, O5_temp);
2724     __ cmp(G5_lh,       O5_temp);
2725     __ br(Assembler::equal, false, Assembler::pt, L_objArray);
2726     if (UseCompressedOops) {
2727       __ delayed()->nop();
2728     } else {
2729       __ delayed()->ld_ptr(dst, oopDesc::klass_offset_in_bytes(), G4_dst_klass);
2730     }
2731 
2732     //  if (src->klass() != dst->klass()) return -1;
2733     __ cmp(G3_src_klass, G4_dst_klass);
2734     __ brx(Assembler::notEqual, false, Assembler::pn, L_failed);
2735     __ delayed()->nop();
2736 
2737     //  if (!src->has_length_field()) return -1;
2738     __ cmp(G5_lh, LayoutHelper::_neutral_value); // < 0
2739     __ br(Assembler::greaterEqual, false, Assembler::pn, L_failed);
2740 













2741     __ delayed();                               // match next insn to prev branch

2742 
2743     arraycopy_range_checks(src, src_pos, dst, dst_pos, length,
2744                            O5_temp, G4_dst_klass, L_failed);
2745 
2746     // typeArrayKlass
2747     //
2748     // src_addr = (src + array_header_in_bytes()) + (src_pos << log2elemsize);
2749     // dst_addr = (dst + array_header_in_bytes()) + (dst_pos << log2elemsize);
2750     //
2751 
2752     const Register G4_offset = G4_dst_klass;    // array offset
2753     const Register G3_elsize = G3_src_klass;    // log2 element size
2754 
2755     assert(LayoutHelper::_header_size_shift == 0, "");
2756     __ set(LayoutHelper::_header_size_mask, G4_offset);
2757     __ and3(G5_lh, G4_offset, G4_offset); // array_offset
2758     __ add(src, G4_offset, src);       // src array offset
2759     __ add(dst, G4_offset, dst);       // dst array offset
2760     __ srl( G5_lh,     LayoutHelper::_element_size_shift, G3_elsize);
2761     __ and3(G3_elsize, LayoutHelper::_element_size_mask,  G3_elsize); // log2 element size
2762 
2763     // next registers should be set before the jump to corresponding stub
2764     const Register from     = O0;  // source array address
2765     const Register to       = O1;  // destination array address
2766     const Register count    = O2;  // elements count
2767 
2768     // 'from', 'to', 'count' registers should be set in this order
2769     // since they are the same as 'src', 'src_pos', 'dst'.
2770 
2771     BLOCK_COMMENT("scale indexes to element size");
2772     __ sll_ptr(src_pos, G3_elsize, src_pos);
2773     __ sll_ptr(dst_pos, G3_elsize, dst_pos);
2774     __ add(src, src_pos, from);       // src_addr
2775     __ add(dst, dst_pos, to);         // dst_addr
2776 
2777     BLOCK_COMMENT("choose copy loop based on element size");
2778     __ cmp(G3_elsize, 0);
2779     __ br(Assembler::equal,true,Assembler::pt,StubRoutines::_jbyte_arraycopy);
2780     __ delayed()->signx(length, count); // length
2781 
2782     __ cmp(G3_elsize, LogBytesPerShort);
2783     __ br(Assembler::equal,true,Assembler::pt,StubRoutines::_jshort_arraycopy);
2784     __ delayed()->signx(length, count); // length
2785 
2786     __ cmp(G3_elsize, LogBytesPerInt);
2787     __ br(Assembler::equal,true,Assembler::pt,StubRoutines::_jint_arraycopy);
2788     __ delayed()->signx(length, count); // length
2789 #ifdef ASSERT
2790     { Label L;
2791       __ cmp(G3_elsize, LogBytesPerLong);
2792       __ br(Assembler::equal, false, Assembler::pt, L);
2793       __ delayed()->nop();
2794       __ stop("must be long copy, but elsize is wrong");
2795       __ bind(L);
2796     }
2797 #endif
2798     __ br(Assembler::always,false,Assembler::pt,StubRoutines::_jlong_arraycopy);
2799     __ delayed()->signx(length, count); // length
2800 
2801     Label L_different_objArray, L_plain_copy, L_checkcast_copy;
2802 
2803     // objArrayKlass
2804   __ BIND(L_objArray);
2805     // live at this point:  G3_src_klass, G4_dst_klass, src[_pos], dst[_pos], length
2806 

2807     //  test array classes for subtyping
2808     __ cmp(G3_src_klass, G4_dst_klass);         // usual case is exact equality
2809     __ brx(Assembler::notEqual, true, Assembler::pn, L_different_objArray);
2810     __ delayed()->lduw(G4_dst_klass, lh_offset, O5_temp); // hoisted from below
2811 
2812     // Identically typed arrays can be copied without element-wise checks.
2813     arraycopy_range_checks(src, src_pos, dst, dst_pos, length,
2814                            O5_temp, G5_lh, L_failed);
2815 
2816     __ add(src, arrayOopDesc::base_offset_in_bytes(T_OBJECT), src); //src offset
2817     __ add(dst, arrayOopDesc::base_offset_in_bytes(T_OBJECT), dst); //dst offset
2818     __ sll_ptr(src_pos, LogBytesPerHeapOop, src_pos);
2819     __ sll_ptr(dst_pos, LogBytesPerHeapOop, dst_pos);
2820     __ add(src, src_pos, from);       // src_addr
2821     __ add(dst, dst_pos, to);         // dst_addr
2822   __ BIND(L_plain_copy);
2823     __ br(Assembler::always, false, Assembler::pt,StubRoutines::_oop_arraycopy);
2824     __ delayed()->signx(length, count); // length
2825 
2826   __ BIND(L_different_objArray);
2827     // live at this point:  G3_src_klass, G4_dst_klass
2828     {
2829       // Before looking at dst.length, make sure dst is also an objArray.
2830       // lduw(G4_dst_klass, lh_offset, O5_temp); // hoisted to delay slot
2831       __ cmp(G5_lh,                    O5_temp);
2832       __ br(Assembler::notEqual, false, Assembler::pn, L_failed);
2833 
2834       // It is safe to examine both src.length and dst.length.
2835       __ delayed();                             // match next insn to prev branch
2836       arraycopy_range_checks(src, src_pos, dst, dst_pos, length,
2837                              O5_temp, G5_lh, L_failed);
2838 
2839       // Marshal the base address arguments now, freeing registers.
2840       __ add(src, arrayOopDesc::base_offset_in_bytes(T_OBJECT), src); //src offset
2841       __ add(dst, arrayOopDesc::base_offset_in_bytes(T_OBJECT), dst); //dst offset
2842       __ sll_ptr(src_pos, LogBytesPerHeapOop, src_pos);
2843       __ sll_ptr(dst_pos, LogBytesPerHeapOop, dst_pos);
2844       __ add(src, src_pos, from);               // src_addr
2845       __ add(dst, dst_pos, to);                 // dst_addr
2846       __ signx(length, count);                  // length (reloaded)