8290706: Remove the support for inline contiguous allocations

Reviewed-by: eosterlund, aph, rrich, fyang, thartmann
This commit is contained in:
Aleksey Shipilev 2022-07-26 17:19:10 +00:00
parent 7318b22209
commit 8159a1ab70
45 changed files with 44 additions and 1002 deletions

View File

@ -157,7 +157,7 @@ void C1_MacroAssembler::try_allocate(Register obj, Register var_size_in_bytes, i
if (UseTLAB) {
tlab_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case);
} else {
eden_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, slow_case);
b(slow_case);
}
}

View File

@ -656,56 +656,6 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
__ set_info("fast new_instance init check", dont_gc_arguments);
}
// If TLAB is disabled, see if there is support for inlining contiguous
// allocations.
// Otherwise, just go to the slow path.
if ((id == fast_new_instance_id || id == fast_new_instance_init_check_id) &&
!UseTLAB && Universe::heap()->supports_inline_contig_alloc()) {
Label slow_path;
Register obj_size = r19;
Register t1 = r10;
Register t2 = r11;
assert_different_registers(klass, obj, obj_size, t1, t2);
__ stp(r19, zr, Address(__ pre(sp, -2 * wordSize)));
if (id == fast_new_instance_init_check_id) {
// make sure the klass is initialized
__ ldrb(rscratch1, Address(klass, InstanceKlass::init_state_offset()));
__ cmpw(rscratch1, InstanceKlass::fully_initialized);
__ br(Assembler::NE, slow_path);
}
#ifdef ASSERT
// assert object can be fast path allocated
{
Label ok, not_ok;
__ ldrw(obj_size, Address(klass, Klass::layout_helper_offset()));
__ cmp(obj_size, (u1)0);
__ br(Assembler::LE, not_ok); // make sure it's an instance (LH > 0)
__ tstw(obj_size, Klass::_lh_instance_slow_path_bit);
__ br(Assembler::EQ, ok);
__ bind(not_ok);
__ stop("assert(can be fast path allocated)");
__ should_not_reach_here();
__ bind(ok);
}
#endif // ASSERT
// get the instance size (size is positive so movl is fine for 64bit)
__ ldrw(obj_size, Address(klass, Klass::layout_helper_offset()));
__ eden_allocate(obj, obj_size, 0, t1, slow_path);
__ initialize_object(obj, klass, obj_size, 0, t1, t2, /* is_tlab_allocated */ false);
__ verify_oop(obj);
__ ldp(r19, zr, Address(__ post(sp, 2 * wordSize)));
__ ret(lr);
__ bind(slow_path);
__ ldp(r19, zr, Address(__ post(sp, 2 * wordSize)));
}
__ enter();
OopMap* map = save_live_registers(sasm);
int call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_instance), klass);
@ -771,51 +721,6 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
}
#endif // ASSERT
// If TLAB is disabled, see if there is support for inlining contiguous
// allocations.
// Otherwise, just go to the slow path.
if (!UseTLAB && Universe::heap()->supports_inline_contig_alloc()) {
Register arr_size = r5;
Register t1 = r10;
Register t2 = r11;
Label slow_path;
assert_different_registers(length, klass, obj, arr_size, t1, t2);
// check that array length is small enough for fast path.
__ mov(rscratch1, C1_MacroAssembler::max_array_allocation_length);
__ cmpw(length, rscratch1);
__ br(Assembler::HI, slow_path);
// get the allocation size: round_up(hdr + length << (layout_helper & 0x1F))
// since size is positive ldrw does right thing on 64bit
__ ldrw(t1, Address(klass, Klass::layout_helper_offset()));
// since size is positive movw does right thing on 64bit
__ movw(arr_size, length);
__ lslvw(arr_size, length, t1);
__ ubfx(t1, t1, Klass::_lh_header_size_shift,
exact_log2(Klass::_lh_header_size_mask + 1));
__ add(arr_size, arr_size, t1);
__ add(arr_size, arr_size, MinObjAlignmentInBytesMask); // align up
__ andr(arr_size, arr_size, ~MinObjAlignmentInBytesMask);
__ eden_allocate(obj, arr_size, 0, t1, slow_path); // preserves arr_size
__ initialize_header(obj, klass, length, t1, t2);
__ ldrb(t1, Address(klass, in_bytes(Klass::layout_helper_offset()) + (Klass::_lh_header_size_shift / BitsPerByte)));
assert(Klass::_lh_header_size_shift % BitsPerByte == 0, "bytewise");
assert(Klass::_lh_header_size_mask <= 0xFF, "bytewise");
__ andr(t1, t1, Klass::_lh_header_size_mask);
__ sub(arr_size, arr_size, t1); // body length
__ add(t1, t1, obj); // body start
__ initialize_body(t1, arr_size, 0, t1, t2);
__ membar(Assembler::StoreStore);
__ verify_oop(obj);
__ ret(lr);
__ bind(slow_path);
}
__ enter();
OopMap* map = save_live_registers(sasm);
int call_offset;

View File

@ -160,63 +160,6 @@ void BarrierSetAssembler::tlab_allocate(MacroAssembler* masm, Register obj,
// verify_tlab();
}
// Defines obj, preserves var_size_in_bytes
void BarrierSetAssembler::eden_allocate(MacroAssembler* masm, Register obj,
Register var_size_in_bytes,
int con_size_in_bytes,
Register t1,
Label& slow_case) {
assert_different_registers(obj, var_size_in_bytes, t1);
if (!Universe::heap()->supports_inline_contig_alloc()) {
__ b(slow_case);
} else {
Register end = t1;
Register heap_end = rscratch2;
Label retry;
__ bind(retry);
{
uint64_t offset;
__ adrp(rscratch1, ExternalAddress((address) Universe::heap()->end_addr()), offset);
__ ldr(heap_end, Address(rscratch1, offset));
}
ExternalAddress heap_top((address) Universe::heap()->top_addr());
// Get the current top of the heap
{
uint64_t offset;
__ adrp(rscratch1, heap_top, offset);
// Use add() here after ARDP, rather than lea().
// lea() does not generate anything if its offset is zero.
// However, relocs expect to find either an ADD or a load/store
// insn after an ADRP. add() always generates an ADD insn, even
// for add(Rn, Rn, 0).
__ add(rscratch1, rscratch1, offset);
__ ldaxr(obj, rscratch1);
}
// Adjust it my the size of our new object
if (var_size_in_bytes == noreg) {
__ lea(end, Address(obj, con_size_in_bytes));
} else {
__ lea(end, Address(obj, var_size_in_bytes));
}
// if end < obj then we wrapped around high memory
__ cmp(end, obj);
__ br(Assembler::LO, slow_case);
__ cmp(end, heap_end);
__ br(Assembler::HI, slow_case);
// If heap_top hasn't been changed by some other thread, update it.
__ stlxr(rscratch2, end, rscratch1);
__ cbnzw(rscratch2, retry);
incr_allocated_bytes(masm, var_size_in_bytes, con_size_in_bytes, t1);
}
}
void BarrierSetAssembler::incr_allocated_bytes(MacroAssembler* masm,
Register var_size_in_bytes,
int con_size_in_bytes,

View File

@ -65,13 +65,6 @@ public:
Label& slow_case // continuation point if fast allocation fails
);
void eden_allocate(MacroAssembler* masm,
Register obj, // result: pointer to object after successful allocation
Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise
int con_size_in_bytes, // object size in bytes if known at compile time
Register t1, // temp register
Label& slow_case // continuation point if fast allocation fails
);
virtual void barrier_stubs_init() {}
virtual NMethodPatchingType nmethod_patching_type() { return NMethodPatchingType::stw_instruction_and_data_patch; }

View File

@ -4518,16 +4518,6 @@ void MacroAssembler::tlab_allocate(Register obj,
bs->tlab_allocate(this, obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case);
}
// Defines obj, preserves var_size_in_bytes
void MacroAssembler::eden_allocate(Register obj,
Register var_size_in_bytes,
int con_size_in_bytes,
Register t1,
Label& slow_case) {
BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
bs->eden_allocate(this, obj, var_size_in_bytes, con_size_in_bytes, t1, slow_case);
}
void MacroAssembler::verify_tlab() {
#ifdef ASSERT
if (UseTLAB && VerifyOops) {

View File

@ -909,13 +909,6 @@ public:
void java_round_float(Register dst, FloatRegister src, FloatRegister ftmp);
// allocation
void eden_allocate(
Register obj, // result: pointer to object after successful allocation
Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise
int con_size_in_bytes, // object size in bytes if known at compile time
Register t1, // temp register
Label& slow_case // continuation point if fast allocation fails
);
void tlab_allocate(
Register obj, // result: pointer to object after successful allocation
Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise

View File

@ -3468,7 +3468,6 @@ void TemplateTable::_new() {
Label slow_case;
Label done;
Label initialize_header;
Label initialize_object; // including clearing the fields
__ get_cpool_and_tags(r4, r0);
// Make sure the class we're about to instantiate has been resolved.
@ -3501,17 +3500,10 @@ void TemplateTable::_new() {
// If TLAB is enabled:
// Try to allocate in the TLAB.
// If fails, go to the slow path.
// Else If inline contiguous allocations are enabled:
// Try to allocate in eden.
// If fails due to heap end, go to slow path.
//
// If TLAB is enabled OR inline contiguous is enabled:
// Initialize the allocation.
// Exit.
//
// Go to slow path.
const bool allow_shared_alloc =
Universe::heap()->supports_inline_contig_alloc();
if (UseTLAB) {
__ tlab_allocate(r0, r3, 0, noreg, r1, slow_case);
@ -3519,25 +3511,10 @@ void TemplateTable::_new() {
if (ZeroTLAB) {
// the fields have been already cleared
__ b(initialize_header);
} else {
// initialize both the header and fields
__ b(initialize_object);
}
} else {
// Allocation in the shared Eden, if allowed.
//
// r3: instance size in bytes
if (allow_shared_alloc) {
__ eden_allocate(r0, r3, 0, r10, slow_case);
}
}
// If UseTLAB or allow_shared_alloc are true, the object is created above and
// there is an initialize need. Otherwise, skip and go to the slow path.
if (UseTLAB || allow_shared_alloc) {
// The object is initialized before the header. If the object size is
// zero, go directly to the header initialization.
__ bind(initialize_object);
__ sub(r3, r3, sizeof(oopDesc));
__ cbz(r3, initialize_header);

View File

@ -81,7 +81,7 @@ void C1_MacroAssembler::try_allocate(Register obj, Register obj_end, Register tm
if (UseTLAB) {
tlab_allocate(obj, obj_end, tmp1, size_expression, slow_case);
} else {
eden_allocate(obj, obj_end, tmp1, tmp2, size_expression, slow_case);
b(slow_case);
}
}

View File

@ -419,40 +419,6 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
const Register result = R0;
const Register klass = R1;
// If TLAB is disabled, see if there is support for inlining contiguous
// allocations.
// Otherwise, just go to the slow path.
if (!UseTLAB && Universe::heap()->supports_inline_contig_alloc() && id != new_instance_id) {
Label slow_case, slow_case_no_pop;
// Make sure the class is fully initialized
if (id == fast_new_instance_init_check_id) {
__ ldrb(result, Address(klass, InstanceKlass::init_state_offset()));
__ cmp(result, InstanceKlass::fully_initialized);
__ b(slow_case_no_pop, ne);
}
// Free some temporary registers
const Register obj_size = R4;
const Register tmp1 = R5;
const Register tmp2 = LR;
const Register obj_end = Rtemp;
__ raw_push(R4, R5, LR);
__ ldr_u32(obj_size, Address(klass, Klass::layout_helper_offset()));
__ eden_allocate(result, obj_end, tmp1, tmp2, obj_size, slow_case); // initializes result and obj_end
__ initialize_object(result, obj_end, klass, noreg /* len */, tmp1, tmp2,
instanceOopDesc::header_size() * HeapWordSize, -1,
/* is_tlab_allocated */ false);
__ raw_pop_and_ret(R4, R5);
__ bind(slow_case);
__ raw_pop(R4, R5, LR);
__ bind(slow_case_no_pop);
}
OopMap* map = save_live_registers(sasm);
int call_offset = __ call_RT(result, noreg, CAST_FROM_FN_PTR(address, new_instance), klass);
oop_maps = new OopMapSet();
@ -489,47 +455,6 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
const Register klass = R1;
const Register length = R2;
// If TLAB is disabled, see if there is support for inlining contiguous
// allocations.
// Otherwise, just go to the slow path.
if (!UseTLAB && Universe::heap()->supports_inline_contig_alloc()) {
Label slow_case, slow_case_no_pop;
__ cmp_32(length, C1_MacroAssembler::max_array_allocation_length);
__ b(slow_case_no_pop, hs);
// Free some temporary registers
const Register arr_size = R4;
const Register tmp1 = R5;
const Register tmp2 = LR;
const Register tmp3 = Rtemp;
const Register obj_end = tmp3;
__ raw_push(R4, R5, LR);
// Get the allocation size: round_up((length << (layout_helper & 0xff)) + header_size)
__ ldr_u32(tmp1, Address(klass, Klass::layout_helper_offset()));
__ mov(arr_size, MinObjAlignmentInBytesMask);
__ and_32(tmp2, tmp1, (unsigned int)(Klass::_lh_header_size_mask << Klass::_lh_header_size_shift));
__ add(arr_size, arr_size, AsmOperand(length, lsl, tmp1));
__ add(arr_size, arr_size, AsmOperand(tmp2, lsr, Klass::_lh_header_size_shift));
__ align_reg(arr_size, arr_size, MinObjAlignmentInBytes);
// eden_allocate destroys tmp2, so reload header_size after allocation
// eden_allocate initializes result and obj_end
__ eden_allocate(result, obj_end, tmp1, tmp2, arr_size, slow_case);
__ ldrb(tmp2, Address(klass, in_bytes(Klass::layout_helper_offset()) +
Klass::_lh_header_size_shift / BitsPerByte));
__ initialize_object(result, obj_end, klass, length, tmp1, tmp2, tmp2, -1, /* is_tlab_allocated */ false);
__ raw_pop_and_ret(R4, R5);
__ bind(slow_case);
__ raw_pop(R4, R5, LR);
__ bind(slow_case_no_pop);
}
OopMap* map = save_live_registers(sasm);
int call_offset;
if (id == new_type_array_id) {

View File

@ -142,50 +142,6 @@ void BarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators
}
}
// Puts address of allocated object into register `obj` and end of allocated object into register `obj_end`.
void BarrierSetAssembler::eden_allocate(MacroAssembler* masm, Register obj, Register obj_end, Register tmp1, Register tmp2,
RegisterOrConstant size_expression, Label& slow_case) {
if (!Universe::heap()->supports_inline_contig_alloc()) {
__ b(slow_case);
return;
}
CollectedHeap* ch = Universe::heap();
const Register top_addr = tmp1;
const Register heap_end = tmp2;
if (size_expression.is_register()) {
assert_different_registers(obj, obj_end, top_addr, heap_end, size_expression.as_register());
} else {
assert_different_registers(obj, obj_end, top_addr, heap_end);
}
bool load_const = VM_Version::supports_movw();
if (load_const) {
__ mov_address(top_addr, (address)Universe::heap()->top_addr());
} else {
__ ldr(top_addr, Address(Rthread, JavaThread::heap_top_addr_offset()));
}
// Calculate new heap_top by adding the size of the object
Label retry;
__ bind(retry);
__ ldr(obj, Address(top_addr));
__ ldr(heap_end, Address(top_addr, (intptr_t)ch->end_addr() - (intptr_t)ch->top_addr()));
__ add_rc(obj_end, obj, size_expression);
// Check if obj_end wrapped around, i.e., obj_end < obj. If yes, jump to the slow case.
__ cmp(obj_end, obj);
__ b(slow_case, lo);
// Update heap_top if allocation succeeded
__ cmp(obj_end, heap_end);
__ b(slow_case, hi);
__ atomic_cas_bool(obj, obj_end, top_addr, 0, heap_end/*scratched*/);
__ b(retry, ne);
incr_allocated_bytes(masm, size_expression, tmp1);
}
// Puts address of allocated object into register `obj` and end of allocated object into register `obj_end`.
void BarrierSetAssembler::tlab_allocate(MacroAssembler* masm, Register obj, Register obj_end, Register tmp1,
RegisterOrConstant size_expression, Label& slow_case) {

View File

@ -47,15 +47,6 @@ public:
virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
Address obj, Register new_val, Register tmp1, Register tmp2, Register tmp3, bool is_null);
virtual void eden_allocate(MacroAssembler* masm,
Register obj, // result: pointer to object after successful allocation
Register obj_end, // result: pointer to end of object after successful allocation
Register tmp1, // temp register
Register tmp2, // temp register
RegisterOrConstant size_expression, // size of object
Label& slow_case // continuation point if fast allocation fails
);
virtual void tlab_allocate(MacroAssembler* masm,
Register obj, // result: pointer to object after successful allocation
Register obj_end, // result: pointer to end of object after successful allocation

View File

@ -949,13 +949,6 @@ void MacroAssembler::null_check(Register reg, Register tmp, int offset) {
}
}
// Puts address of allocated object into register `obj` and end of allocated object into register `obj_end`.
void MacroAssembler::eden_allocate(Register obj, Register obj_end, Register tmp1, Register tmp2,
RegisterOrConstant size_expression, Label& slow_case) {
BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
bs->eden_allocate(this, obj, obj_end, tmp1, tmp2, size_expression, slow_case);
}
// Puts address of allocated object into register `obj` and end of allocated object into register `obj_end`.
void MacroAssembler::tlab_allocate(Register obj, Register obj_end, Register tmp1,
RegisterOrConstant size_expression, Label& slow_case) {

View File

@ -340,8 +340,6 @@ public:
inline void null_check(Register reg) { null_check(reg, noreg, -1); } // for C1 lir_null_check
// Puts address of allocated object into register `obj` and end of allocated object into register `obj_end`.
void eden_allocate(Register obj, Register obj_end, Register tmp1, Register tmp2,
RegisterOrConstant size_expression, Label& slow_case);
void tlab_allocate(Register obj, Register obj_end, Register tmp1,
RegisterOrConstant size_expression, Label& slow_case);

View File

@ -3848,13 +3848,6 @@ void TemplateTable::_new() {
Label slow_case;
Label done;
Label initialize_header;
Label initialize_object; // including clearing the fields
const bool allow_shared_alloc =
Universe::heap()->supports_inline_contig_alloc();
// Literals
InlinedAddress Lheap_top_addr(allow_shared_alloc ? (address)Universe::heap()->top_addr() : NULL);
__ get_unsigned_2_byte_index_at_bcp(Rindex, 1);
__ get_cpool_and_tags(Rcpool, Rtags);
@ -3892,11 +3885,6 @@ void TemplateTable::_new() {
// If TLAB is enabled:
// Try to allocate in the TLAB.
// If fails, go to the slow path.
// Else If inline contiguous allocations are enabled:
// Try to allocate in eden.
// If fails due to heap end, go to slow path.
//
// If TLAB is enabled OR inline contiguous is enabled:
// Initialize the allocation.
// Exit.
//
@ -3910,23 +3898,8 @@ void TemplateTable::_new() {
if (ZeroTLAB) {
// the fields have been already cleared
__ b(initialize_header);
} else {
// initialize both the header and fields
__ b(initialize_object);
}
} else {
// Allocation in the shared Eden, if allowed.
if (allow_shared_alloc) {
const Register Rheap_top_addr = R2_tmp;
const Register Rheap_top = R5_tmp;
const Register Rheap_end = Rtemp;
assert_different_registers(Robj, Rklass, Rsize, Rheap_top_addr, Rheap_top, Rheap_end, LR);
__ eden_allocate(Robj, Rheap_top, Rheap_top_addr, Rheap_end, Rsize, slow_case);
}
}
if (UseTLAB || allow_shared_alloc) {
const Register Rzero0 = R1_tmp;
const Register Rzero1 = R2_tmp;
const Register Rzero_end = R5_tmp;
@ -3935,7 +3908,6 @@ void TemplateTable::_new() {
// The object is initialized before the header. If the object size is
// zero, go directly to the header initialization.
__ bind(initialize_object);
__ subs(Rsize, Rsize, sizeof(oopDesc));
__ add(Rzero_cur, Robj, sizeof(oopDesc));
__ b(initialize_header, eq);
@ -3997,10 +3969,6 @@ void TemplateTable::_new() {
__ b(slow_case);
}
if (allow_shared_alloc) {
__ bind_literal(Lheap_top_addr);
}
// slow case
__ bind(slow_case);
__ get_constant_pool(Rcpool);

View File

@ -200,11 +200,7 @@ void C1_MacroAssembler::try_allocate(
if (UseTLAB) {
tlab_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, slow_case);
} else {
eden_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case);
RegisterOrConstant size_in_bytes = var_size_in_bytes->is_valid()
? RegisterOrConstant(var_size_in_bytes)
: RegisterOrConstant(con_size_in_bytes);
incr_allocated_bytes(size_in_bytes, t1, t2);
b(slow_case);
}
}
@ -357,11 +353,7 @@ void C1_MacroAssembler::allocate_array(
clrrdi(arr_size, arr_size, LogMinObjAlignmentInBytes); // Align array size.
// Allocate space & initialize header.
if (UseTLAB) {
tlab_allocate(obj, arr_size, 0, t2, slow_case);
} else {
eden_allocate(obj, arr_size, 0, t2, t3, slow_case);
}
try_allocate(obj, arr_size, 0, t2, t3, slow_case);
initialize_header(obj, klass, len, t2, t3);
// Initialize body.

View File

@ -2076,18 +2076,6 @@ RegisterOrConstant MacroAssembler::argument_offset(RegisterOrConstant arg_slot,
}
}
// allocation (for C1)
void MacroAssembler::eden_allocate(
Register obj, // result: pointer to object after successful allocation
Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise
int con_size_in_bytes, // object size in bytes if known at compile time
Register t1, // temp register
Register t2, // temp register
Label& slow_case // continuation point if fast allocation fails
) {
b(slow_case);
}
void MacroAssembler::tlab_allocate(
Register obj, // result: pointer to object after successful allocation
Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise

View File

@ -600,14 +600,6 @@ class MacroAssembler: public Assembler {
RegisterOrConstant argument_offset(RegisterOrConstant arg_slot, Register temp_reg, int extra_slot_offset = 0);
// allocation (for C1)
void eden_allocate(
Register obj, // result: pointer to object after successful allocation
Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise
int con_size_in_bytes, // object size in bytes if known at compile time
Register t1, // temp register
Register t2, // temp register
Label& slow_case // continuation point if fast allocation fails
);
void tlab_allocate(
Register obj, // result: pointer to object after successful allocation
Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise

View File

@ -141,7 +141,7 @@ void C1_MacroAssembler::try_allocate(Register obj, Register var_size_in_bytes, i
if (UseTLAB) {
tlab_allocate(obj, var_size_in_bytes, con_size_in_bytes, tmp1, tmp2, slow_case, /* is_far */ true);
} else {
eden_allocate(obj, var_size_in_bytes, con_size_in_bytes, tmp1, slow_case, /* is_far */ true);
j(slow_case);
}
}

View File

@ -668,66 +668,6 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
__ set_info("fast new_instance init check", dont_gc_arguments);
}
// If TLAB is disabled, see if there is support for inlining contiguous
// allocations.
// Otherwise, just go to the slow path.
if ((id == fast_new_instance_id || id == fast_new_instance_init_check_id) &&
!UseTLAB && Universe::heap()->supports_inline_contig_alloc()) {
Label slow_path;
Register obj_size = x12;
Register tmp1 = x9;
Register tmp2 = x14;
assert_different_registers(klass, obj, obj_size, tmp1, tmp2);
const int sp_offset = 2;
const int x9_offset = 1;
const int zr_offset = 0;
__ addi(sp, sp, -(sp_offset * wordSize));
__ sd(x9, Address(sp, x9_offset * wordSize));
__ sd(zr, Address(sp, zr_offset * wordSize));
if (id == fast_new_instance_init_check_id) {
// make sure the klass is initialized
__ lbu(t0, Address(klass, InstanceKlass::init_state_offset()));
__ mv(t1, InstanceKlass::fully_initialized);
__ bne(t0, t1, slow_path);
}
#ifdef ASSERT
// assert object can be fast path allocated
{
Label ok, not_ok;
__ lw(obj_size, Address(klass, Klass::layout_helper_offset()));
// make sure it's an instance. For instances, layout helper is a positive number.
// For arrays, layout helper is a negative number
__ blez(obj_size, not_ok);
__ andi(t0, obj_size, Klass::_lh_instance_slow_path_bit);
__ beqz(t0, ok);
__ bind(not_ok);
__ stop("assert(can be fast path allocated)");
__ should_not_reach_here();
__ bind(ok);
}
#endif // ASSERT
// get the instance size
__ lwu(obj_size, Address(klass, Klass::layout_helper_offset()));
__ eden_allocate(obj, obj_size, 0, tmp1, slow_path);
__ initialize_object(obj, klass, obj_size, 0, tmp1, tmp2, /* is_tlab_allocated */ false);
__ verify_oop(obj);
__ ld(x9, Address(sp, x9_offset * wordSize));
__ ld(zr, Address(sp, zr_offset * wordSize));
__ addi(sp, sp, sp_offset * wordSize);
__ ret();
__ bind(slow_path);
__ ld(x9, Address(sp, x9_offset * wordSize));
__ ld(zr, Address(sp, zr_offset * wordSize));
__ addi(sp, sp, sp_offset * wordSize);
}
__ enter();
OopMap* map = save_live_registers(sasm);
assert_cond(map != NULL);
@ -798,52 +738,6 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
}
#endif // ASSERT
// If TLAB is disabled, see if there is support for inlining contiguous
// allocations.
// Otherwise, just go to the slow path.
if (!UseTLAB && Universe::heap()->supports_inline_contig_alloc()) {
Register arr_size = x14;
Register tmp1 = x12;
Register tmp2 = x15;
Label slow_path;
assert_different_registers(length, klass, obj, arr_size, tmp1, tmp2);
// check that array length is small enough for fast path.
__ mv(t0, C1_MacroAssembler::max_array_allocation_length);
__ bgtu(length, t0, slow_path);
// get the allocation size: round_up(hdr + length << (layout_helper & 0x1F))
__ lwu(tmp1, Address(klass, Klass::layout_helper_offset()));
__ andi(t0, tmp1, 0x1f);
__ sll(arr_size, length, t0);
int lh_header_size_width = exact_log2(Klass::_lh_header_size_mask + 1);
int lh_header_size_msb = Klass::_lh_header_size_shift + lh_header_size_width;
__ slli(tmp1, tmp1, XLEN - lh_header_size_msb);
__ srli(tmp1, tmp1, XLEN - lh_header_size_width);
__ add(arr_size, arr_size, tmp1);
__ addi(arr_size, arr_size, MinObjAlignmentInBytesMask); // align up
__ andi(arr_size, arr_size, ~(uint)MinObjAlignmentInBytesMask);
__ eden_allocate(obj, arr_size, 0, tmp1, slow_path); // preserves arr_size
__ initialize_header(obj, klass, length, tmp1, tmp2);
__ lbu(tmp1, Address(klass,
in_bytes(Klass::layout_helper_offset()) +
(Klass::_lh_header_size_shift / BitsPerByte)));
assert(Klass::_lh_header_size_shift % BitsPerByte == 0, "bytewise");
assert(Klass::_lh_header_size_mask <= 0xFF, "bytewise");
__ andi(tmp1, tmp1, Klass::_lh_header_size_mask);
__ sub(arr_size, arr_size, tmp1); // body length
__ add(tmp1, tmp1, obj); // body start
__ initialize_body(tmp1, arr_size, 0, tmp2);
__ membar(MacroAssembler::StoreStore);
__ verify_oop(obj);
__ ret();
__ bind(slow_path);
}
__ enter();
OopMap* map = save_live_registers(sasm);
assert_cond(map != NULL);

View File

@ -162,59 +162,6 @@ void BarrierSetAssembler::tlab_allocate(MacroAssembler* masm, Register obj,
}
}
// Defines obj, preserves var_size_in_bytes
void BarrierSetAssembler::eden_allocate(MacroAssembler* masm, Register obj,
Register var_size_in_bytes,
int con_size_in_bytes,
Register tmp1,
Label& slow_case,
bool is_far) {
assert_cond(masm != NULL);
assert_different_registers(obj, var_size_in_bytes, tmp1);
if (!Universe::heap()->supports_inline_contig_alloc()) {
__ j(slow_case);
} else {
Register end = tmp1;
Label retry;
__ bind(retry);
// Get the current end of the heap
ExternalAddress address_end((address) Universe::heap()->end_addr());
{
int32_t offset;
__ la_patchable(t1, address_end, offset);
__ ld(t1, Address(t1, offset));
}
// Get the current top of the heap
ExternalAddress address_top((address) Universe::heap()->top_addr());
{
int32_t offset;
__ la_patchable(t0, address_top, offset);
__ addi(t0, t0, offset);
__ lr_d(obj, t0, Assembler::aqrl);
}
// Adjust it my the size of our new object
if (var_size_in_bytes == noreg) {
__ la(end, Address(obj, con_size_in_bytes));
} else {
__ add(end, obj, var_size_in_bytes);
}
// if end < obj then we wrapped around high memory
__ bltu(end, obj, slow_case, is_far);
__ bgtu(end, t1, slow_case, is_far);
// If heap_top hasn't been changed by some other thread, update it.
__ sc_d(t1, end, t0, Assembler::rl);
__ bnez(t1, retry);
incr_allocated_bytes(masm, var_size_in_bytes, con_size_in_bytes, tmp1);
}
}
void BarrierSetAssembler::incr_allocated_bytes(MacroAssembler* masm,
Register var_size_in_bytes,
int con_size_in_bytes,

View File

@ -61,14 +61,6 @@ public:
bool is_far = false
);
void eden_allocate(MacroAssembler* masm,
Register obj, // result: pointer to object after successful allocation
Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise
int con_size_in_bytes, // object size in bytes if known at compile time
Register tmp1, // temp register
Label& slow_case, // continuation point if fast allocation fails
bool is_far = false
);
virtual void barrier_stubs_init() {}
virtual void nmethod_entry_barrier(MacroAssembler* masm);

View File

@ -2687,18 +2687,6 @@ void MacroAssembler::tlab_allocate(Register obj,
bs->tlab_allocate(this, obj, var_size_in_bytes, con_size_in_bytes, tmp1, tmp2, slow_case, is_far);
}
// Defines obj, preserves var_size_in_bytes
void MacroAssembler::eden_allocate(Register obj,
Register var_size_in_bytes,
int con_size_in_bytes,
Register tmp,
Label& slow_case,
bool is_far) {
BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
bs->eden_allocate(this, obj, var_size_in_bytes, con_size_in_bytes, tmp, slow_case, is_far);
}
// get_thread() can be called anywhere inside generated code so we
// need to save whatever non-callee save context might get clobbered
// by the call to Thread::current() or, indeed, the call setup code.

View File

@ -272,15 +272,6 @@ class MacroAssembler: public Assembler {
bool is_far = false
);
void eden_allocate(
Register obj, // result: pointer to object after successful allocation
Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise
int con_size_in_bytes, // object size in bytes if known at compile time
Register tmp, // temp register
Label& slow_case, // continuation point if fast allocation fails
bool is_far = false
);
// Test sub_klass against super_klass, with fast and slow paths.
// The fast path produces a tri-state answer: yes / no / maybe-slow.

View File

@ -3474,7 +3474,6 @@ void TemplateTable::_new() {
Label slow_case;
Label done;
Label initialize_header;
Label initialize_object; // including clearing the fields
__ get_cpool_and_tags(x14, x10);
// Make sure the class we're about to instantiate has been resolved.
@ -3508,15 +3507,9 @@ void TemplateTable::_new() {
// If TLAB is enabled:
// Try to allocate in the TLAB.
// If fails, go to the slow path.
// Else If inline contiguous allocations are enabled:
// Try to allocate in eden.
// If fails due to heap end, go to slow path
//
// If TLAB is enabled OR inline contiguous is enabled:
// Initialize the allocation.
// Exit.
// Go to slow path.
const bool allow_shared_alloc = Universe::heap()->supports_inline_contig_alloc();
if (UseTLAB) {
__ tlab_allocate(x10, x13, 0, noreg, x11, slow_case);
@ -3524,25 +3517,10 @@ void TemplateTable::_new() {
if (ZeroTLAB) {
// the fields have been already cleared
__ j(initialize_header);
} else {
// initialize both the header and fields
__ j(initialize_object);
}
} else {
// Allocation in the shared Eden, if allowed.
//
// x13: instance size in bytes
if (allow_shared_alloc) {
__ eden_allocate(x10, x13, 0, x28, slow_case);
}
}
// If USETLAB or allow_shared_alloc are true, the object is created above and
// there is an initialized need. Otherwise, skip and go to the slow path.
if (UseTLAB || allow_shared_alloc) {
// The object is initialized before the header. If the object size is
// zero, go directly to the header initialization.
__ bind(initialize_object);
__ sub(x13, x13, sizeof(oopDesc));
__ beqz(x13, initialize_header);

View File

@ -138,7 +138,7 @@ void C1_MacroAssembler::try_allocate(Register obj, Register var_size_in_bytes, i
if (UseTLAB) {
tlab_allocate(noreg, obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case);
} else {
eden_allocate(noreg, obj, var_size_in_bytes, con_size_in_bytes, t1, slow_case);
jmp(slow_case);
}
}

View File

@ -1030,61 +1030,6 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
__ set_info("fast new_instance init check", dont_gc_arguments);
}
// If TLAB is disabled, see if there is support for inlining contiguous
// allocations.
// Otherwise, just go to the slow path.
if ((id == fast_new_instance_id || id == fast_new_instance_init_check_id) && !UseTLAB
&& Universe::heap()->supports_inline_contig_alloc()) {
Label slow_path;
Register obj_size = rcx;
Register t1 = rbx;
Register t2 = rsi;
assert_different_registers(klass, obj, obj_size, t1, t2);
__ push(rdi);
__ push(rbx);
if (id == fast_new_instance_init_check_id) {
// make sure the klass is initialized
__ cmpb(Address(klass, InstanceKlass::init_state_offset()), InstanceKlass::fully_initialized);
__ jcc(Assembler::notEqual, slow_path);
}
#ifdef ASSERT
// assert object can be fast path allocated
{
Label ok, not_ok;
__ movl(obj_size, Address(klass, Klass::layout_helper_offset()));
__ 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);
__ jcc(Assembler::zero, ok);
__ bind(not_ok);
__ stop("assert(can be fast path allocated)");
__ should_not_reach_here();
__ bind(ok);
}
#endif // ASSERT
const Register thread = NOT_LP64(rdi) LP64_ONLY(r15_thread);
NOT_LP64(__ get_thread(thread));
// get the instance size (size is positive so movl is fine for 64bit)
__ movl(obj_size, Address(klass, Klass::layout_helper_offset()));
__ eden_allocate(thread, obj, obj_size, 0, t1, slow_path);
__ initialize_object(obj, klass, obj_size, 0, t1, t2, /* is_tlab_allocated */ false);
__ verify_oop(obj);
__ pop(rbx);
__ pop(rdi);
__ ret(0);
__ bind(slow_path);
__ pop(rbx);
__ pop(rdi);
}
__ enter();
OopMap* map = save_live_registers(sasm, 2);
int call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_instance), klass);
@ -1149,47 +1094,6 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
}
#endif // ASSERT
// If TLAB is disabled, see if there is support for inlining contiguous
// allocations.
// Otherwise, just go to the slow path.
if (!UseTLAB && Universe::heap()->supports_inline_contig_alloc()) {
Register arr_size = rsi;
Register t1 = rcx; // must be rcx for use as shift count
Register t2 = rdi;
Label slow_path;
// get the allocation size: round_up(hdr + length << (layout_helper & 0x1F))
// since size is positive movl does right thing on 64bit
__ movl(t1, Address(klass, Klass::layout_helper_offset()));
// since size is positive movl does right thing on 64bit
__ movl(arr_size, length);
assert(t1 == rcx, "fixed register usage");
__ shlptr(arr_size /* by t1=rcx, mod 32 */);
__ shrptr(t1, Klass::_lh_header_size_shift);
__ andptr(t1, Klass::_lh_header_size_mask);
__ addptr(arr_size, t1);
__ addptr(arr_size, MinObjAlignmentInBytesMask); // align up
__ andptr(arr_size, ~MinObjAlignmentInBytesMask);
// Using t2 for non 64-bit.
const Register thread = NOT_LP64(t2) LP64_ONLY(r15_thread);
NOT_LP64(__ get_thread(thread));
__ eden_allocate(thread, obj, arr_size, 0, t1, slow_path); // preserves arr_size
__ initialize_header(obj, klass, length, t1, t2);
__ movb(t1, Address(klass, in_bytes(Klass::layout_helper_offset()) + (Klass::_lh_header_size_shift / BitsPerByte)));
assert(Klass::_lh_header_size_shift % BitsPerByte == 0, "bytewise");
assert(Klass::_lh_header_size_mask <= 0xFF, "bytewise");
__ andptr(t1, Klass::_lh_header_size_mask);
__ subptr(arr_size, t1); // body length
__ addptr(t1, obj); // body start
__ initialize_body(t1, arr_size, 0, t2);
__ verify_oop(obj);
__ ret(0);
__ bind(slow_path);
}
__ enter();
OopMap* map = save_live_registers(sasm, 3);
int call_offset;

View File

@ -242,42 +242,6 @@ void BarrierSetAssembler::tlab_allocate(MacroAssembler* masm,
__ verify_tlab();
}
// Defines obj, preserves var_size_in_bytes
void BarrierSetAssembler::eden_allocate(MacroAssembler* masm,
Register thread, Register obj,
Register var_size_in_bytes,
int con_size_in_bytes,
Register t1,
Label& slow_case) {
assert(obj == rax, "obj must be in rax, for cmpxchg");
assert_different_registers(obj, var_size_in_bytes, t1);
if (!Universe::heap()->supports_inline_contig_alloc()) {
__ jmp(slow_case);
} else {
Register end = t1;
Label retry;
__ bind(retry);
ExternalAddress heap_top((address) Universe::heap()->top_addr());
__ movptr(obj, heap_top);
if (var_size_in_bytes == noreg) {
__ lea(end, Address(obj, con_size_in_bytes));
} else {
__ lea(end, Address(obj, var_size_in_bytes, Address::times_1));
}
// if end < obj then we wrapped around => object too long => slow case
__ cmpptr(end, obj);
__ jcc(Assembler::below, slow_case);
__ cmpptr(end, ExternalAddress((address) Universe::heap()->end_addr()));
__ jcc(Assembler::above, slow_case);
// Compare obj with the top addr, and if still equal, store the new top addr in
// end at the address of the top addr pointer. Sets ZF if was equal, and clears
// it otherwise. Use lock prefix for atomicity on MPs.
__ locked_cmpxchgptr(end, heap_top);
__ jcc(Assembler::notEqual, retry);
incr_allocated_bytes(masm, thread, var_size_in_bytes, con_size_in_bytes, thread->is_valid() ? noreg : t1);
}
}
void BarrierSetAssembler::incr_allocated_bytes(MacroAssembler* masm, Register thread,
Register var_size_in_bytes,
int con_size_in_bytes,

View File

@ -59,12 +59,6 @@ public:
int con_size_in_bytes,
Register t1, Register t2,
Label& slow_case);
virtual void eden_allocate(MacroAssembler* masm,
Register thread, Register obj,
Register var_size_in_bytes,
int con_size_in_bytes,
Register t1,
Label& slow_case);
virtual void barrier_stubs_init() {}

View File

@ -3920,16 +3920,6 @@ void MacroAssembler::pop_set(RegSet set, int offset) {
}
}
// Defines obj, preserves var_size_in_bytes
void MacroAssembler::eden_allocate(Register thread, Register obj,
Register var_size_in_bytes,
int con_size_in_bytes,
Register t1,
Label& slow_case) {
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
bs->eden_allocate(this, thread, obj, var_size_in_bytes, con_size_in_bytes, t1, slow_case);
}
// Preserves the contents of address, destroys the contents length_in_bytes and temp.
void MacroAssembler::zero_memory(Register address, Register length_in_bytes, int offset_in_bytes, Register temp) {
assert(address != length_in_bytes && address != temp && temp != length_in_bytes, "registers must be different");

View File

@ -565,14 +565,6 @@ public:
}
// allocation
void eden_allocate(
Register thread, // Current thread
Register obj, // result: pointer to object after successful allocation
Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise
int con_size_in_bytes, // object size in bytes if known at compile time
Register t1, // temp register
Label& slow_case // continuation point if fast allocation fails
);
void tlab_allocate(
Register thread, // Current thread
Register obj, // result: pointer to object after successful allocation

View File

@ -3922,7 +3922,6 @@ void TemplateTable::_new() {
Label slow_case_no_pop;
Label done;
Label initialize_header;
Label initialize_object; // including clearing the fields
__ get_cpool_and_tags(rcx, rax);
@ -3952,48 +3951,23 @@ void TemplateTable::_new() {
// If TLAB is enabled:
// Try to allocate in the TLAB.
// If fails, go to the slow path.
// Else If inline contiguous allocations are enabled:
// Try to allocate in eden.
// If fails due to heap end, go to slow path.
//
// If TLAB is enabled OR inline contiguous is enabled:
// Initialize the allocation.
// Exit.
//
// Go to slow path.
const bool allow_shared_alloc =
Universe::heap()->supports_inline_contig_alloc();
const Register thread = LP64_ONLY(r15_thread) NOT_LP64(rcx);
#ifndef _LP64
if (UseTLAB || allow_shared_alloc) {
__ get_thread(thread);
}
#endif // _LP64
if (UseTLAB) {
NOT_LP64(__ get_thread(thread);)
__ tlab_allocate(thread, rax, rdx, 0, rcx, rbx, slow_case);
if (ZeroTLAB) {
// the fields have been already cleared
__ jmp(initialize_header);
} else {
// initialize both the header and fields
__ jmp(initialize_object);
}
} else if (allow_shared_alloc) {
// Allocation in the shared Eden, if allowed.
//
// rdx: instance size in bytes
__ eden_allocate(thread, rax, rdx, 0, rbx, slow_case);
}
// If UseTLAB or allow_shared_alloc are true, the object is created above and
// there is an initialize need. Otherwise, skip and go to the slow path.
if (UseTLAB || allow_shared_alloc) {
// The object is initialized before the header. If the object size is
// zero, go directly to the header initialization.
__ bind(initialize_object);
__ decrement(rdx, sizeof(oopDesc));
__ jcc(Assembler::zero, initialize_header);

View File

@ -43,15 +43,6 @@ frame JavaThread::pd_last_frame() {
void JavaThread::cache_global_variables() {
BarrierSet* bs = BarrierSet::barrier_set();
const bool allow_shared_alloc =
Universe::heap()->supports_inline_contig_alloc();
if (allow_shared_alloc) {
_heap_top_addr = (address) Universe::heap()->top_addr();
} else {
_heap_top_addr = NULL;
}
if (bs->is_a(BarrierSet::CardTableBarrierSet)) {
_card_table_base = (address) (barrier_set_cast<CardTableBarrierSet>(bs)->card_table()->byte_map_base());
} else {

View File

@ -28,7 +28,6 @@
private:
// The following thread-local variables replicate corresponding global variables.
// They are used for a quick access from compiled code via Rthread register.
address _heap_top_addr;
address _heap_lock_addr;
address _card_table_base;
@ -44,7 +43,6 @@
return byte_offset_of(JavaThread, _anchor) + JavaFrameAnchor::last_Java_fp_offset();
}
static ByteSize heap_top_addr_offset() { return byte_offset_of(JavaThread, _heap_top_addr); }
static ByteSize card_table_base_offset() { return byte_offset_of(JavaThread, _card_table_base); }
private:

View File

@ -218,11 +218,6 @@ class ParallelScavengeHeap : public CollectedHeap {
// Perform a full collection
virtual void do_full_collection(bool clear_all_soft_refs);
bool supports_inline_contig_alloc() const { return !UseNUMA; }
HeapWord* volatile* top_addr() const { return !UseNUMA ? young_gen()->top_addr() : (HeapWord* volatile*)-1; }
HeapWord** end_addr() const { return !UseNUMA ? young_gen()->end_addr() : (HeapWord**)-1; }
void ensure_parsability(bool retire_tlabs);
void resize_all_tlabs();

View File

@ -133,9 +133,6 @@ class PSYoungGen : public CHeapObj<mtGC> {
return result;
}
HeapWord* volatile* top_addr() const { return eden_space()->top_addr(); }
HeapWord** end_addr() const { return eden_space()->end_addr(); }
// Iteration.
void oop_iterate(OopIterateClosure* cl);
void object_iterate(ObjectClosure* cl);

View File

@ -458,9 +458,6 @@ size_t DefNewGeneration::contiguous_available() const {
}
HeapWord* volatile* DefNewGeneration::top_addr() const { return eden()->top_addr(); }
HeapWord** DefNewGeneration::end_addr() const { return eden()->end_addr(); }
void DefNewGeneration::object_iterate(ObjectClosure* blk) {
eden()->object_iterate(blk);
from()->object_iterate(blk);

View File

@ -223,10 +223,6 @@ protected:
size_t max_eden_size() const { return _max_eden_size; }
size_t max_survivor_size() const { return _max_survivor_size; }
bool supports_inline_contig_alloc() const { return true; }
HeapWord* volatile* top_addr() const;
HeapWord** end_addr() const;
// Thread-local allocation buffers
bool supports_tlab_allocation() const { return true; }
size_t tlab_capacity() const;

View File

@ -699,127 +699,62 @@ Node* BarrierSetC2::obj_allocate(PhaseMacroExpand* macro, Node* mem, Node* toobi
Node*& i_o, Node*& needgc_ctrl,
Node*& fast_oop_ctrl, Node*& fast_oop_rawmem,
intx prefetch_lines) const {
assert(UseTLAB, "Only for TLAB enabled allocations");
Node* eden_top_adr;
Node* eden_end_adr;
Node* thread = macro->transform_later(new ThreadLocalNode());
Node* tlab_top_adr = macro->basic_plus_adr(macro->top()/*not oop*/, thread, in_bytes(JavaThread::tlab_top_offset()));
Node* tlab_end_adr = macro->basic_plus_adr(macro->top()/*not oop*/, thread, in_bytes(JavaThread::tlab_end_offset()));
macro->set_eden_pointers(eden_top_adr, eden_end_adr);
// Load Eden::end. Loop invariant and hoisted.
// Load TLAB end.
//
// Note: We set the control input on "eden_end" and "old_eden_top" when using
// a TLAB to work around a bug where these values were being moved across
// Note: We set the control input on "tlab_end" and "old_tlab_top" to work around
// a bug where these values were being moved across
// a safepoint. These are not oops, so they cannot be include in the oop
// map, but they can be changed by a GC. The proper way to fix this would
// be to set the raw memory state when generating a SafepointNode. However
// this will require extensive changes to the loop optimization in order to
// prevent a degradation of the optimization.
// See comment in memnode.hpp, around line 227 in class LoadPNode.
Node *eden_end = macro->make_load(toobig_false, mem, eden_end_adr, 0, TypeRawPtr::BOTTOM, T_ADDRESS);
Node* tlab_end = macro->make_load(toobig_false, mem, tlab_end_adr, 0, TypeRawPtr::BOTTOM, T_ADDRESS);
// We need a Region for the loop-back contended case.
enum { fall_in_path = 1, contended_loopback_path = 2 };
Node *contended_region;
Node *contended_phi_rawmem;
if (UseTLAB) {
contended_region = toobig_false;
contended_phi_rawmem = mem;
} else {
contended_region = new RegionNode(3);
contended_phi_rawmem = new PhiNode(contended_region, Type::MEMORY, TypeRawPtr::BOTTOM);
// Now handle the passing-too-big test. We fall into the contended
// loop-back merge point.
contended_region ->init_req(fall_in_path, toobig_false);
contended_phi_rawmem->init_req(fall_in_path, mem);
macro->transform_later(contended_region);
macro->transform_later(contended_phi_rawmem);
}
// Load the TLAB top.
Node* old_tlab_top = new LoadPNode(toobig_false, mem, tlab_top_adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM, MemNode::unordered);
macro->transform_later(old_tlab_top);
// Load(-locked) the heap top.
// See note above concerning the control input when using a TLAB
Node *old_eden_top = UseTLAB
? new LoadPNode (toobig_false, contended_phi_rawmem, eden_top_adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM, MemNode::unordered)
: new LoadPLockedNode(contended_region, contended_phi_rawmem, eden_top_adr, MemNode::acquire);
// Add to heap top to get a new TLAB top
Node* new_tlab_top = new AddPNode(macro->top(), old_tlab_top, size_in_bytes);
macro->transform_later(new_tlab_top);
macro->transform_later(old_eden_top);
// Add to heap top to get a new heap top
Node *new_eden_top = new AddPNode(macro->top(), old_eden_top, size_in_bytes);
macro->transform_later(new_eden_top);
// Check for needing a GC; compare against heap end
Node *needgc_cmp = new CmpPNode(new_eden_top, eden_end);
macro->transform_later(needgc_cmp);
Node *needgc_bol = new BoolNode(needgc_cmp, BoolTest::ge);
// Check against TLAB end
Node* tlab_full = new CmpPNode(new_tlab_top, tlab_end);
macro->transform_later(tlab_full);
Node* needgc_bol = new BoolNode(tlab_full, BoolTest::ge);
macro->transform_later(needgc_bol);
IfNode *needgc_iff = new IfNode(contended_region, needgc_bol, PROB_UNLIKELY_MAG(4), COUNT_UNKNOWN);
IfNode* needgc_iff = new IfNode(toobig_false, needgc_bol, PROB_UNLIKELY_MAG(4), COUNT_UNKNOWN);
macro->transform_later(needgc_iff);
// Plug the failing-heap-space-need-gc test into the slow-path region
Node *needgc_true = new IfTrueNode(needgc_iff);
Node* needgc_true = new IfTrueNode(needgc_iff);
macro->transform_later(needgc_true);
needgc_ctrl = needgc_true;
// No need for a GC. Setup for the Store-Conditional
Node *needgc_false = new IfFalseNode(needgc_iff);
// No need for a GC.
Node* needgc_false = new IfFalseNode(needgc_iff);
macro->transform_later(needgc_false);
i_o = macro->prefetch_allocation(i_o, needgc_false, contended_phi_rawmem,
old_eden_top, new_eden_top, prefetch_lines);
// Fast path:
i_o = macro->prefetch_allocation(i_o, needgc_false, mem,
old_tlab_top, new_tlab_top, prefetch_lines);
Node* fast_oop = old_eden_top;
// Store the modified TLAB top back down.
Node* store_tlab_top = new StorePNode(needgc_false, mem, tlab_top_adr,
TypeRawPtr::BOTTOM, new_tlab_top, MemNode::unordered);
macro->transform_later(store_tlab_top);
// Store (-conditional) the modified eden top back down.
// StorePConditional produces flags for a test PLUS a modified raw
// memory state.
if (UseTLAB) {
Node* store_eden_top =
new StorePNode(needgc_false, contended_phi_rawmem, eden_top_adr,
TypeRawPtr::BOTTOM, new_eden_top, MemNode::unordered);
macro->transform_later(store_eden_top);
fast_oop_ctrl = needgc_false; // No contention, so this is the fast path
fast_oop_rawmem = store_eden_top;
} else {
Node* store_eden_top =
new StorePConditionalNode(needgc_false, contended_phi_rawmem, eden_top_adr,
new_eden_top, fast_oop/*old_eden_top*/);
macro->transform_later(store_eden_top);
Node *contention_check = new BoolNode(store_eden_top, BoolTest::ne);
macro->transform_later(contention_check);
store_eden_top = new SCMemProjNode(store_eden_top);
macro->transform_later(store_eden_top);
// If not using TLABs, check to see if there was contention.
IfNode *contention_iff = new IfNode (needgc_false, contention_check, PROB_MIN, COUNT_UNKNOWN);
macro->transform_later(contention_iff);
Node *contention_true = new IfTrueNode(contention_iff);
macro->transform_later(contention_true);
// If contention, loopback and try again.
contended_region->init_req(contended_loopback_path, contention_true);
contended_phi_rawmem->init_req(contended_loopback_path, store_eden_top);
// Fast-path succeeded with no contention!
Node *contention_false = new IfFalseNode(contention_iff);
macro->transform_later(contention_false);
fast_oop_ctrl = contention_false;
// Bump total allocated bytes for this thread
Node* thread = new ThreadLocalNode();
macro->transform_later(thread);
Node* alloc_bytes_adr = macro->basic_plus_adr(macro->top()/*not oop*/, thread,
in_bytes(JavaThread::allocated_bytes_offset()));
Node* alloc_bytes = macro->make_load(fast_oop_ctrl, store_eden_top, alloc_bytes_adr,
0, TypeLong::LONG, T_LONG);
#ifdef _LP64
Node* alloc_size = size_in_bytes;
#else
Node* alloc_size = new ConvI2LNode(size_in_bytes);
macro->transform_later(alloc_size);
#endif
Node* new_alloc_bytes = new AddLNode(alloc_bytes, alloc_size);
macro->transform_later(new_alloc_bytes);
fast_oop_rawmem = macro->make_store(fast_oop_ctrl, store_eden_top, alloc_bytes_adr,
0, new_alloc_bytes, T_LONG);
}
return fast_oop;
fast_oop_ctrl = needgc_false;
fast_oop_rawmem = store_tlab_top;
return old_tlab_top;
}
#define XTOP LP64_ONLY(COMMA phase->top())

View File

@ -320,27 +320,6 @@ class CollectedHeap : public CHeapObj<mtGC> {
return _lab_alignment_reserve;
}
// Some heaps may offer a contiguous region for shared non-blocking
// allocation, via inlined code (by exporting the address of the top and
// end fields defining the extent of the contiguous allocation region.)
// This function returns "true" iff the heap supports this kind of
// allocation. (Default is "no".)
virtual bool supports_inline_contig_alloc() const {
return false;
}
// These functions return the addresses of the fields that define the
// boundaries of the contiguous allocation area. (These fields should be
// physically near to one another.)
virtual HeapWord* volatile* top_addr() const {
guarantee(false, "inline contiguous allocation not supported");
return NULL;
}
virtual HeapWord** end_addr() const {
guarantee(false, "inline contiguous allocation not supported");
return NULL;
}
// Some heaps may be in an unparseable state at certain times between
// collections. This may be necessary for efficient implementation of
// certain allocation-related activities. Calling this function before

View File

@ -303,8 +303,6 @@ HeapWord* GenCollectedHeap::mem_allocate_work(size_t size,
// First allocation attempt is lock-free.
Generation *young = _young_gen;
assert(young->supports_inline_contig_alloc(),
"Otherwise, must do alloc within heap lock");
if (young->should_allocate(size, is_tlab)) {
result = young->par_allocate(size, is_tlab);
if (result != NULL) {
@ -817,18 +815,6 @@ bool GenCollectedHeap::no_allocs_since_save_marks() {
_old_gen->no_allocs_since_save_marks();
}
bool GenCollectedHeap::supports_inline_contig_alloc() const {
return _young_gen->supports_inline_contig_alloc();
}
HeapWord* volatile* GenCollectedHeap::top_addr() const {
return _young_gen->top_addr();
}
HeapWord** GenCollectedHeap::end_addr() const {
return _young_gen->end_addr();
}
// public collection interfaces
void GenCollectedHeap::collect(GCCause::Cause cause) {
@ -1189,8 +1175,6 @@ class GenGCEpilogueClosure: public GenCollectedHeap::GenClosure {
void GenCollectedHeap::gc_epilogue(bool full) {
#if COMPILER2_OR_JVMCI
assert(DerivedPointerTable::is_empty(), "derived pointer present");
size_t actual_gap = pointer_delta((HeapWord*) (max_uintx-3), *(end_addr()));
guarantee(!CompilerConfig::is_c2_or_jvmci_compiler_enabled() || actual_gap > (size_t)FastAllocateSizeLimit, "inline allocation wraps");
#endif // COMPILER2_OR_JVMCI
resize_all_tlabs();

View File

@ -181,12 +181,6 @@ public:
HeapWord* mem_allocate(size_t size, bool* gc_overhead_limit_was_exceeded);
// We may support a shared contiguous allocation area, if the youngest
// generation does.
bool supports_inline_contig_alloc() const;
HeapWord* volatile* top_addr() const;
HeapWord** end_addr() const;
// Perform a full collection of the heap; intended for use in implementing
// "System.gc". This implies as full a collection as the CollectedHeap
// supports. Caller does not hold the Heap_lock on entry.

View File

@ -225,24 +225,6 @@ class Generation: public CHeapObj<mtGC> {
// Like "allocate", but performs any necessary locking internally.
virtual HeapWord* par_allocate(size_t word_size, bool is_tlab) = 0;
// Some generation may offer a region for shared, contiguous allocation,
// via inlined code (by exporting the address of the top and end fields
// defining the extent of the contiguous allocation region.)
// This function returns "true" iff the heap supports this kind of
// allocation. (More precisely, this means the style of allocation that
// increments *top_addr()" with a CAS.) (Default is "no".)
// A generation that supports this allocation style must use lock-free
// allocation for *all* allocation, since there are times when lock free
// allocation will be concurrent with plain "allocate" calls.
virtual bool supports_inline_contig_alloc() const { return false; }
// These functions return the addresses of the fields that define the
// boundaries of the contiguous allocation area. (These fields should be
// physically near to one another.)
virtual HeapWord* volatile* top_addr() const { return NULL; }
virtual HeapWord** end_addr() const { return NULL; }
// Thread-local allocation buffers
virtual bool supports_tlab_allocation() const { return false; }
virtual size_t tlab_capacity() const {

View File

@ -119,9 +119,9 @@ void CompilerToVM::Data::initialize(JVMCI_TRAPS) {
Universe_verify_oop_mask = Universe::verify_oop_mask();
Universe_verify_oop_bits = Universe::verify_oop_bits();
_supports_inline_contig_alloc = Universe::heap()->supports_inline_contig_alloc();
_heap_end_addr = _supports_inline_contig_alloc ? Universe::heap()->end_addr() : (HeapWord**) -1;
_heap_top_addr = _supports_inline_contig_alloc ? Universe::heap()->top_addr() : (HeapWord* volatile*) -1;
_supports_inline_contig_alloc = false;
_heap_end_addr = (HeapWord**) -1;
_heap_top_addr = (HeapWord* volatile*) -1;
_max_oop_map_stack_offset = (OopMapValue::register_mask - VMRegImpl::stack2reg(0)->value()) * VMRegImpl::stack_slot_size;
int max_oop_map_stack_index = _max_oop_map_stack_offset / VMRegImpl::stack_slot_size;

View File

@ -1117,23 +1117,6 @@ bool PhaseMacroExpand::eliminate_boxing_node(CallStaticJavaNode *boxing) {
return true;
}
//---------------------------set_eden_pointers-------------------------
void PhaseMacroExpand::set_eden_pointers(Node* &eden_top_adr, Node* &eden_end_adr) {
if (UseTLAB) { // Private allocation: load from TLS
Node* thread = transform_later(new ThreadLocalNode());
int tlab_top_offset = in_bytes(JavaThread::tlab_top_offset());
int tlab_end_offset = in_bytes(JavaThread::tlab_end_offset());
eden_top_adr = basic_plus_adr(top()/*not oop*/, thread, tlab_top_offset);
eden_end_adr = basic_plus_adr(top()/*not oop*/, thread, tlab_end_offset);
} else { // Shared allocation: load from globals
CollectedHeap* ch = Universe::heap();
address top_adr = (address)ch->top_addr();
address end_adr = (address)ch->end_addr();
eden_top_adr = makecon(TypeRawPtr::make(top_adr));
eden_end_adr = basic_plus_adr(eden_top_adr, end_adr - top_adr);
}
}
Node* PhaseMacroExpand::make_load(Node* ctl, Node* mem, Node* base, int offset, const Type* value_type, BasicType bt) {
Node* adr = basic_plus_adr(base, offset);
@ -1244,7 +1227,7 @@ void PhaseMacroExpand::expand_allocate_common(
initial_slow_test = BoolNode::make_predicate(initial_slow_test, &_igvn);
}
if (!UseTLAB && !Universe::heap()->supports_inline_contig_alloc()) {
if (!UseTLAB) {
// Force slow-path allocation
expand_fast_path = false;
initial_slow_test = NULL;

View File

@ -58,7 +58,6 @@ public:
_igvn.register_new_node_with_optimizer(n);
return n;
}
void set_eden_pointers(Node* &eden_top_adr, Node* &eden_end_adr);
Node* make_load( Node* ctl, Node* mem, Node* base, int offset,
const Type* value_type, BasicType bt);
Node* make_store(Node* ctl, Node* mem, Node* base, int offset,