src/cpu/x86/vm/c1_Runtime1_x86.cpp
Print this page
rev 146 : [mq]: mixa.layout.patch
@@ -784,10 +784,101 @@
return oop_maps;
}
+inline Address layout_helper_addr(Register klass) {
+ return Address(klass, (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,
+ StubAssembler* sasm, bool hot_part) {
+ assert_different_registers(obj_size, klass);
+
+ if (hot_part) {
+ __ movl(obj_size, layout_helper_addr(klass));
+ __ andl(obj_size, ~LayoutHelper::_size_low_mask);
+ if (MixedArrays) {
+ __ 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);
+ __ addl(obj_size, LayoutHelper::_header_size_odd_mask);
+ __ andl(obj_size, (LayoutHelper::_header_size_mask & ~MinObjAlignmentInBytesMask));
+ __ 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))
+ __ movl(t1, layout_helper_addr(klass));
+ __ movl(arr_size, length);
+ // int scale = (lh >> LayoutHelper::_element_size_shift);
+ __ movl(t1, t2); // spill layout helper
+ __ shrl(t1, LayoutHelper::_element_size_shift); // lh>>16, no mask needed
+ // size_t arr_size = (array_length << scale);
+ assert(t1 == rcx, "fixed register usage");
+ __ shll(arr_size /* by t1=rcx, mod 32 */);
+ if (MixedArrays) {
+ // int sizem_ip = (scale & (LayoutHelper::_element_sizem_mask_ip));
+ __ andl(t1, LayoutHelper::_element_sizem_mask_ip);
+ __ 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, "");
+ // shrl(t2, LayoutHelper::_header_size_shift);
+ __ andl(t2, LayoutHelper::_header_size_mask);
+ __ addl(arr_size, t2);
+ __ addl(arr_size, MinObjAlignmentInBytesMask); // align up
+ __ andl(arr_size, ~MinObjAlignmentInBytesMask);
+ } else {
+ if (MixedArrays) {
+ // Side path for scaling by a non-power-of-two array element size.
+ __ bind(need_multiply);
+ __ movl(arr_size, length); // reload; previous value was trash
+ // int sizem = (sizem_ip >> LayoutHelper::_element_scale_bits);
+ __ shrl(t1, LayoutHelper::_element_scale_bits);
+ // arr_size = (array_length * (1+sizem)) << scale;
+ __ addl(t1, 1);
+ assert(wordSize == jintSize, "else use imulq, shlq, etc.");
+ __ imull(arr_size, t1);
+ __ movl(t1, t2); // reload layout helper
+ __ shrl(t1, LayoutHelper::_element_size_shift); // lh>>16, mask needed
+ __ andl(t1, LayoutHelper::_element_scale_mask);
+ assert(t1 == rcx, "fixed register usage");
+ __ shll(arr_size /* by t1=rcx, mod 32 */);
+ __ 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);
+ __ subl(arr_size, min_header_size); // body length
+ __ movl(t1, obj);
+ __ addl(t1, min_header_size); // body start
+ __ initialize_body(t1, arr_size, 0, t2);
+}
+
+
OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
// for better readability
const bool must_gc_arguments = true;
const bool dont_gc_arguments = false;
@@ -867,17 +958,14 @@
}
#ifdef ASSERT
// assert object can be fast path allocated
{
- Label ok, not_ok;
- __ movl(obj_size, Address(klass, Klass::layout_helper_offset_in_bytes() + sizeof(oopDesc)));
- __ cmpl(obj_size, 0); // make sure it's an instance (LH > 0)
- __ jcc(Assembler::lessEqual, not_ok);
- __ testl(obj_size, Klass::_lh_instance_slow_path_bit);
+ Label ok;
+ __ movl(obj_size, layout_helper_addr(klass));
+ __ testl(obj_size, LayoutHelper::_slow_path_low_bit);
__ jcc(Assembler::zero, ok);
- __ bind(not_ok);
__ stop("assert(can be fast path allocated)");
__ should_not_reach_here();
__ bind(ok);
}
#endif // ASSERT
@@ -888,28 +976,44 @@
__ tlab_refill(retry_tlab, try_eden, slow_path); // does not destroy rdx (klass)
__ bind(retry_tlab);
// get the instance size
- __ movl(obj_size, Address(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes()));
+ Label have_obj_size, size_is_variable;
+ compute_instance_size(obj_size, klass,
+ have_obj_size, size_is_variable,
+ sasm, true);
__ tlab_allocate(obj, obj_size, 0, t1, t2, slow_path);
__ initialize_object(obj, klass, obj_size, 0, t1, t2);
__ verify_oop(obj);
__ popl(rbx);
__ popl(rdi);
__ ret(0);
+ // generate side path, if any
+ compute_instance_size(obj_size, klass,
+ have_obj_size, size_is_variable,
+ sasm, false);
+
__ bind(try_eden);
// get the instance size
- __ movl(obj_size, Address(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes()));
+ Label have_obj_size_2, size_is_variable_2;
+ compute_instance_size(obj_size, klass,
+ have_obj_size_2, size_is_variable_2,
+ sasm, true);
__ eden_allocate(obj, obj_size, 0, t1, slow_path);
__ initialize_object(obj, klass, obj_size, 0, t1, t2);
__ verify_oop(obj);
__ popl(rbx);
__ popl(rdi);
__ ret(0);
+ // generate side path, if any
+ compute_instance_size(obj_size, klass,
+ have_obj_size_2, size_is_variable_2,
+ sasm, false);
+
__ bind(slow_path);
__ popl(rbx);
__ popl(rdi);
}
@@ -962,15 +1066,19 @@
#ifdef ASSERT
// assert object type is really an array of the proper kind
{
Label ok;
Register t0 = obj;
- __ movl(t0, Address(klass, Klass::layout_helper_offset_in_bytes() + sizeof(oopDesc)));
- __ sarl(t0, Klass::_lh_array_tag_shift);
- int tag = ((id == new_type_array_id)
- ? Klass::_lh_array_tag_type_value
- : Klass::_lh_array_tag_obj_value);
+ __ movl(t0, layout_helper_addr(klass));
+ 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;
+ __ sarl(t0, flag_shift);
+ assert(id == new_object_array_id ||
+ tag == (LayoutHelper::for_array(T_DOUBLE).as_int() >> flag_shift),
+ "same tag for all type arrays");
__ cmpl(t0, tag);
__ jcc(Assembler::equal, ok);
__ stop("assert(is an array klass)");
__ should_not_reach_here();
__ bind(ok);
@@ -993,59 +1101,43 @@
Label retry_tlab, try_eden;
__ tlab_refill(retry_tlab, try_eden, slow_path); // preserves rbx, & rdx
__ bind(retry_tlab);
- // get the allocation size: round_up(hdr + length << (layout_helper & 0x1F))
- __ movl(t1, Address(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes()));
- __ movl(arr_size, length);
- assert(t1 == rcx, "fixed register usage");
- __ shll(arr_size /* by t1=rcx, mod 32 */);
- __ shrl(t1, Klass::_lh_header_size_shift);
- __ andl(t1, Klass::_lh_header_size_mask);
- __ addl(arr_size, t1);
- __ addl(arr_size, MinObjAlignmentInBytesMask); // align up
- __ andl(arr_size, ~MinObjAlignmentInBytesMask);
-
+ Label have_scaled_length, need_multiply;
+ compute_array_size(arr_size, klass, length,
+ have_scaled_length, need_multiply,
+ t1, t2, sasm, true);
__ tlab_allocate(obj, arr_size, 0, t1, t2, slow_path); // preserves arr_size
__ initialize_header(obj, klass, length, t1, t2);
- __ movb(t1, Address(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes() + (Klass::_lh_header_size_shift / BitsPerByte)));
- assert(Klass::_lh_header_size_shift % BitsPerByte == 0, "bytewise");
- assert(Klass::_lh_header_size_mask <= 0xFF, "bytewise");
- __ andl(t1, Klass::_lh_header_size_mask);
- __ subl(arr_size, t1); // body length
- __ addl(t1, obj); // body start
- __ initialize_body(t1, arr_size, 0, t2);
+ initialize_array_body(obj, arr_size, t1, t2, sasm);
__ verify_oop(obj);
__ ret(0);
- __ bind(try_eden);
- // get the allocation size: round_up(hdr + length << (layout_helper & 0x1F))
- __ movl(t1, Address(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes()));
- __ movl(arr_size, length);
- assert(t1 == rcx, "fixed register usage");
- __ shll(arr_size /* by t1=rcx, mod 32 */);
- __ shrl(t1, Klass::_lh_header_size_shift);
- __ andl(t1, Klass::_lh_header_size_mask);
- __ addl(arr_size, t1);
- __ addl(arr_size, MinObjAlignmentInBytesMask); // align up
- __ andl(arr_size, ~MinObjAlignmentInBytesMask);
+ // generate side path, if any
+ compute_array_size(arr_size, klass, length,
+ have_scaled_length, need_multiply,
+ t1, t2, sasm, false);
+ __ bind(try_eden);
+ Label have_scaled_length_2, need_multiply_2;
+ compute_array_size(arr_size, klass, length,
+ have_scaled_length_2, need_multiply_2,
+ t1, t2, sasm, true);
__ eden_allocate(obj, arr_size, 0, t1, slow_path); // preserves arr_size
__ initialize_header(obj, klass, length, t1, t2);
- __ movb(t1, Address(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes() + (Klass::_lh_header_size_shift / BitsPerByte)));
- assert(Klass::_lh_header_size_shift % BitsPerByte == 0, "bytewise");
- assert(Klass::_lh_header_size_mask <= 0xFF, "bytewise");
- __ andl(t1, Klass::_lh_header_size_mask);
- __ subl(arr_size, t1); // body length
- __ addl(t1, obj); // body start
- __ initialize_body(t1, arr_size, 0, t2);
+ initialize_array_body(obj, arr_size, t1, t2, sasm);
__ verify_oop(obj);
__ ret(0);
+ // generate side path, if any
+ compute_array_size(arr_size, klass, length,
+ have_scaled_length_2, need_multiply_2,
+ t1, t2, sasm, false);
+
__ bind(slow_path);
}
__ enter();
OopMap* map = save_live_registers(sasm, 3);