8290706: Remove the support for inline contiguous allocations
Reviewed-by: eosterlund, aph, rrich, fyang, thartmann
This commit is contained in:
parent
7318b22209
commit
8159a1ab70
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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; }
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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() {}
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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:
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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())
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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.
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user