src/cpu/sparc/vm/c1_Runtime1_sparc.cpp

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

@@ -341,10 +341,98 @@
   __ delayed()->restore();
 
   return oop_maps;
 }
 
+inline Address layout_helper_addr(Register klass) {
+  return Address(klass, 0, (klassOopDesc::header_size() * HeapWordSize
+                            + Klass::layout_helper_offset_in_bytes()));
+}
+
+static void compute_instance_size(Register obj_size, Register klass,
+                                  Label& have_obj_size, Label& size_is_variable,
+                                  Register t1,
+                                  StubAssembler* sasm, bool hot_part) {
+  assert_different_registers(obj_size, klass, t1);
+
+  if (hot_part) {
+    __ lduw(layout_helper_addr(klass), obj_size);
+    __ andcc(obj_size, ~LayoutHelper::_size_low_mask, obj_size);
+    if (mixed_arrays) {
+      __ jcc(Assembler::negative, size_is_variable);
+      __ bind(have_obj_size);
+    }
+  } else {
+    if (MixedArrays) {
+      // Side path for fixing up the initial size of a variable object.
+      // Must round from int to object alignment, and clear high bits.
+      __ bind(size_is_variable);
+      __ add(obj_size, LayoutHelper::_header_size_odd_mask, obj_size);
+      __ set((LayoutHelper::_header_size_mask & ~MinObjAlignmentInBytesMask), t1);
+      __ and3(obj_size, t1, obj_size);
+      __ jmp(have_obj_size);
+    }
+  }
+}
+
+static void compute_array_size(Register arr_size, Register klass, Register length,
+                               Label& have_scaled_length, Label& need_multiply,
+                               Register t1, Register t2,
+                               StubAssembler* sasm, bool hot_part) {
+  assert_different_registers(arr_size, klass, length, t1, t2);
+
+  if (hot_part) {
+    // get the allocation size: round_up(hdr + length << (lh>>16 & 0x1F))
+    __ lduw(layout_helper_addr(klass), t1);
+    // int scale = (lh >> LayoutHelper::_element_size_shift);
+    __ mov(t1, t2);               // spill layout helper
+    __ srl(t1, LayoutHelper::_element_size_shift);  // lh>>16, no mask needed
+    // size_t arr_size = (array_length << scale);
+    __ sllx(length, t1, arr_size);
+    if (MixedArrays) {
+      // int sizem_ip = (scale & (LayoutHelper::_element_sizem_mask_ip));
+      __ andcc(t1, LayoutHelper::_element_sizem_mask_ip, t1);
+      __ jcc(Assembler::notZero, need_multiply);
+      __ bind(have_scaled_length);
+    }
+    // arr_size += Klass::layout_helper_header_size_in_bytes(lh);
+    assert(LayoutHelper::_header_size_shift == 0, "");
+    // sll(t2, LayoutHelper::_header_size_shift, t2);
+    __ set((LayoutHelper::_header_size_mask & ~MinObjAlignmentInBytesMask), t1);
+    __ and(t2, t1, t2);           // t2 = lh & _header_size_mask
+    __ add(arr_size, t2, arr_size);
+    __ add(arr_size, MinObjAlignmentInBytesMask, arr_size); // align up
+    __ and3(arr_size, ~MinObjAlignmentInBytesMask, arr_size);
+  } else {
+    if (MixedArrays) {
+      // Side path for scaling by a non-power-of-two array element size.
+      __ bind(need_multiply);
+      // int sizem = (sizem_ip >> LayoutHelper::_element_scale_bits);
+      __ srl(t1, LayoutHelper::_element_scale_bits, t1);
+      // arr_size = (array_length * (1+sizem)) << scale;
+      __ add(t1, 1, t1);
+      // previous value of arr_size is junk; start from length again
+      assert(wordSize == jintSize, "else use mulx");
+      __ smul(length, t1, arr_size);
+      __ srl(t2,  LayoutHelper::_element_size_shift, t1);  // lh>>16, mask needed
+      __ and3(t1, LayoutHelper::_element_scale_mask, t1);
+      __ sllx(arr_size, t1, arr_size);
+      __ jmp(have_scaled_length);
+    }
+  }
+}
+
+static void initialize_array_body(Register obj, Register arr_size, Register t1, Register t2, StubAssembler* sasm) {
+  assert_different_registers(obj, arr_size, t1, t2);
+
+  int min_header_size = arrayOopDesc::header_size(T_BYTE);
+  __ sub(arr_size, min_header_size, arr_size);  // body length
+  __ add(obj,      min_header_size, t1); // body start
+  __ initialize_body(t1, arr_size, 0, t2);
+}
+
+
 OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
 
   OopMapSet* oop_maps = NULL;
   // for better readability
   const bool must_gc_arguments = true;

@@ -411,19 +499,15 @@
             __ delayed()->nop();
           }
 #ifdef ASSERT
           // assert object can be fast path allocated
           {
-            Label ok, not_ok;
+            Label ok;
           __ ld(G5_klass, Klass::layout_helper_offset_in_bytes() + sizeof(oopDesc), G1_obj_size);
-          __ cmp(G1_obj_size, 0);  // make sure it's an instance (LH > 0)
-          __ br(Assembler::lessEqual, false, Assembler::pn, not_ok);
-          __ delayed()->nop();
-          __ btst(Klass::_lh_instance_slow_path_bit, G1_obj_size);
+          __ btst(LayoutHelper::_slow_path_low_bit, G1_obj_size);
           __ br(Assembler::zero, false, Assembler::pn, ok);
           __ delayed()->nop();
-          __ bind(not_ok);
           __ stop("assert(can be fast path allocated)");
           __ should_not_reach_here();
           __ bind(ok);
           }
 #endif // ASSERT

@@ -433,28 +517,44 @@
           __ tlab_refill(retry_tlab, try_eden, slow_path); // preserves G5_klass
 
           __ bind(retry_tlab);
 
           // get the instance size
-          __ ld(G5_klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes(), G1_obj_size);
+          Label have_obj_size, size_is_variable;
+          compute_instance_size(G1_obj_size, G5_klass,
+                                have_obj_size, size_is_variable,
+                                G3_t1, sasm, true);
           __ tlab_allocate(O0_obj, G1_obj_size, 0, G3_t1, slow_path);
           __ initialize_object(O0_obj, G5_klass, G1_obj_size, 0, G3_t1, G4_t2);
           __ verify_oop(O0_obj);
           __ mov(O0, I0);
           __ ret();
           __ delayed()->restore();
 
+          // generate side path, if any
+          compute_instance_size(G1_obj_size, G5_klass,
+                                have_obj_size, size_is_variable,
+                                G3_t1, sasm, false);
+
           __ bind(try_eden);
           // get the instance size
-          __ ld(G5_klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes(), G1_obj_size);
+          Label have_obj_size_2, size_is_variable_2;
+          compute_instance_size(G1_obj_size, G5_klass,
+                                have_obj_size_2, size_is_variable_2,
+                                G3_t1, sasm, true);
           __ eden_allocate(O0_obj, G1_obj_size, 0, G3_t1, G4_t2, slow_path);
           __ initialize_object(O0_obj, G5_klass, G1_obj_size, 0, G3_t1, G4_t2);
           __ verify_oop(O0_obj);
           __ mov(O0, I0);
           __ ret();
           __ delayed()->restore();
 
+          // generate side path, if any
+          compute_instance_size(G1_obj_size, G5_klass,
+                                have_obj_size_2, size_is_variable_2,
+                                G3_t1, sasm, false);
+
           __ bind(slow_path);
 
           // pop this frame so generate_stub_call can push it's own
           __ restore();
         }

@@ -477,18 +577,10 @@
       {
         Register G5_klass = G5; // Incoming
         Register G4_length = G4; // Incoming
         Register O0_obj   = O0; // Outgoing
 
-        Address klass_lh(G5_klass, 0, ((klassOopDesc::header_size() * HeapWordSize)
-                                       + Klass::layout_helper_offset_in_bytes()));
-        assert(Klass::_lh_header_size_shift % BitsPerByte == 0, "bytewise");
-        assert(Klass::_lh_header_size_mask == 0xFF, "bytewise");
-        // Use this offset to pick out an individual byte of the layout_helper:
-        const int klass_lh_header_size_offset = ((BytesPerInt - 1)  // 3 - 2 selects byte {0,1,0,0}
-                                                 - Klass::_lh_header_size_shift / BitsPerByte);
-
         if (id == new_type_array_id) {
           __ set_info("new_type_array", dont_gc_arguments);
         } else {
           __ set_info("new_object_array", dont_gc_arguments);
         }

@@ -496,15 +588,19 @@
 #ifdef ASSERT
         // assert object type is really an array of the proper kind
         {
           Label ok;
           Register G3_t1 = G3;
-          __ ld(klass_lh, G3_t1);
-          __ sra(G3_t1, Klass::_lh_array_tag_shift, G3_t1);
-          int tag = ((id == new_type_array_id)
-                     ? Klass::_lh_array_tag_type_value
-                     : Klass::_lh_array_tag_obj_value);
+          __ lduw(layout_helper_addr(G5_klass), G3_t1);
+          int flag_shift = LayoutHelper::_flags_shift;
+          flag_shift += LayoutHelper::_flags_low_bits; // shift out BasicType also
+          int tag = LayoutHelper::for_array((id == new_type_array_id) ? T_BYTE : T_OBJECT).as_int();
+          tag     >>= flag_shift;
+          __ sra(G3_t1, flag_shift, G3_t1);
+          assert(id == new_object_array_id ||
+                 tag == (LayoutHelper::for_array(T_DOUBLE).as_int() >> flag_shift),
+                 "same tag for all type arrays");
           __ cmp(G3_t1, tag);
           __ brx(Assembler::equal, false, Assembler::pt, ok);
           __ delayed()->nop();
           __ stop("assert(is an array klass)");
           __ should_not_reach_here();

@@ -531,50 +627,46 @@
           __ tlab_refill(retry_tlab, try_eden, slow_path); // preserves G4_length and G5_klass
 
           __ bind(retry_tlab);
 
           // get the allocation size: (length << (layout_helper & 0x1F)) + header_size
-          __ ld(klass_lh, G3_t1);
-          __ sll(G4_length, G3_t1, G1_arr_size);
-          __ srl(G3_t1, Klass::_lh_header_size_shift, G3_t1);
-          __ and3(G3_t1, Klass::_lh_header_size_mask, G3_t1);
-          __ add(G1_arr_size, G3_t1, G1_arr_size);
-          __ add(G1_arr_size, MinObjAlignmentInBytesMask, G1_arr_size);  // align up
-          __ and3(G1_arr_size, ~MinObjAlignmentInBytesMask, G1_arr_size);
-
+          Label have_scaled_length, need_multiply;
+          compute_array_size(G1_arr_size, G5_klass, G4_length,
+                             have_scaled_length, need_multiply,
+                             G3_t1, O1_t2, sasm, true);
           __ tlab_allocate(O0_obj, G1_arr_size, 0, G3_t1, slow_path);  // preserves G1_arr_size
 
           __ initialize_header(O0_obj, G5_klass, G4_length, G3_t1, O1_t2);
-          __ ldub(klass_lh, G3_t1, klass_lh_header_size_offset);
-          __ sub(G1_arr_size, G3_t1, O1_t2);  // body length
-          __ add(O0_obj, G3_t1, G3_t1);       // body start
-          __ initialize_body(G3_t1, O1_t2);
+          initialize_array_body(O0_obj, G1_arr_size, G3_t1, O1_t2, sasm);
           __ verify_oop(O0_obj);
           __ retl();
           __ delayed()->nop();
 
+          // generate side path, if any
+          compute_array_size(G1_arr_size, G5_klass, G4_length,
+                             have_scaled_length, need_multiply,
+                             G3_t1, O1_t2, sasm, false);
+
           __ bind(try_eden);
+          Label have_scaled_length_2, need_multiply_2;
           // get the allocation size: (length << (layout_helper & 0x1F)) + header_size
-          __ ld(klass_lh, G3_t1);
-          __ sll(G4_length, G3_t1, G1_arr_size);
-          __ srl(G3_t1, Klass::_lh_header_size_shift, G3_t1);
-          __ and3(G3_t1, Klass::_lh_header_size_mask, G3_t1);
-          __ add(G1_arr_size, G3_t1, G1_arr_size);
-          __ add(G1_arr_size, MinObjAlignmentInBytesMask, G1_arr_size);
-          __ and3(G1_arr_size, ~MinObjAlignmentInBytesMask, G1_arr_size);
-
+          compute_array_size(G1_arr_size, G5_klass, G4_length,
+                             have_scaled_length_2, need_multiply_2,
+                             G3_t1, O1_t2, sasm, true);
           __ eden_allocate(O0_obj, G1_arr_size, 0, G3_t1, O1_t2, slow_path);  // preserves G1_arr_size
 
           __ initialize_header(O0_obj, G5_klass, G4_length, G3_t1, O1_t2);
-          __ ldub(klass_lh, G3_t1, klass_lh_header_size_offset);
-          __ sub(G1_arr_size, G3_t1, O1_t2);  // body length
-          __ add(O0_obj, G3_t1, G3_t1);       // body start
-          __ initialize_body(G3_t1, O1_t2);
+          initialize_array_body(O0_obj, G1_arr_size, G3_t1, O1_t2, sasm);
           __ verify_oop(O0_obj);
           __ retl();
           __ delayed()->nop();
 
+          // generate side path, if any
+          compute_array_size(G1_arr_size, G5_klass, G4_length,
+                             have_scaled_length_2, need_multiply_2,
+                             G3_t1, O1_t2, sasm, false);
+
           __ bind(slow_path);
         }
 
         if (id == new_type_array_id) {
           oop_maps = generate_stub_call(sasm, I0, CAST_FROM_FN_PTR(address, new_type_array), G5_klass, G4_length);