src/cpu/sparc/vm/c1_Runtime1_sparc.cpp
Print this page
rev 146 : [mq]: mixa.layout.patch
*** 341,350 ****
--- 341,438 ----
__ 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,429 ****
__ delayed()->nop();
}
#ifdef ASSERT
// assert object can be fast path allocated
{
! Label ok, not_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);
__ 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
--- 499,513 ----
__ delayed()->nop();
}
#ifdef ASSERT
// assert object can be fast path allocated
{
! Label ok;
__ ld(G5_klass, Klass::layout_helper_offset_in_bytes() + sizeof(oopDesc), G1_obj_size);
! __ btst(LayoutHelper::_slow_path_low_bit, G1_obj_size);
__ br(Assembler::zero, false, Assembler::pn, ok);
__ delayed()->nop();
__ stop("assert(can be fast path allocated)");
__ should_not_reach_here();
__ bind(ok);
}
#endif // ASSERT
*** 433,460 ****
__ 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);
__ 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();
__ bind(try_eden);
// get the instance size
! __ ld(G5_klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes(), G1_obj_size);
__ 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();
__ bind(slow_path);
// pop this frame so generate_stub_call can push it's own
__ restore();
}
--- 517,560 ----
__ tlab_refill(retry_tlab, try_eden, slow_path); // preserves G5_klass
__ bind(retry_tlab);
// get the instance 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
! 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,494 ****
{
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);
}
--- 577,586 ----
*** 496,510 ****
#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);
__ cmp(G3_t1, tag);
__ brx(Assembler::equal, false, Assembler::pt, ok);
__ delayed()->nop();
__ stop("assert(is an array klass)");
__ should_not_reach_here();
--- 588,606 ----
#ifdef ASSERT
// assert object type is really an array of the proper kind
{
Label ok;
Register G3_t1 = G3;
! __ 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,580 ****
__ 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);
!
__ 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);
__ verify_oop(O0_obj);
__ retl();
__ delayed()->nop();
__ bind(try_eden);
// 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);
!
__ 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);
__ verify_oop(O0_obj);
__ retl();
__ delayed()->nop();
__ 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);
--- 627,672 ----
__ 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
! 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);
! 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
! 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);
! 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);