mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 14:24:46 +02:00
7003454: order constants in constant table by number of references in code
Reviewed-by: kvn, never, bdelsart
This commit is contained in:
parent
6b52dbceb0
commit
81c085a1e2
17 changed files with 249 additions and 189 deletions
|
@ -855,12 +855,6 @@ class Assembler : public AbstractAssembler {
|
||||||
Lookaside = 1 << 4
|
Lookaside = 1 << 4
|
||||||
};
|
};
|
||||||
|
|
||||||
// test if x is within signed immediate range for nbits
|
|
||||||
static bool is_simm(intptr_t x, int nbits) { return -( intptr_t(1) << nbits-1 ) <= x && x < ( intptr_t(1) << nbits-1 ); }
|
|
||||||
|
|
||||||
// test if -4096 <= x <= 4095
|
|
||||||
static bool is_simm13(intptr_t x) { return is_simm(x, 13); }
|
|
||||||
|
|
||||||
static bool is_in_wdisp_range(address a, address b, int nbits) {
|
static bool is_in_wdisp_range(address a, address b, int nbits) {
|
||||||
intptr_t d = intptr_t(b) - intptr_t(a);
|
intptr_t d = intptr_t(b) - intptr_t(a);
|
||||||
return is_simm(d, nbits + 2);
|
return is_simm(d, nbits + 2);
|
||||||
|
@ -1203,7 +1197,7 @@ public:
|
||||||
if (!UseCBCond || cbcond_before()) return false;
|
if (!UseCBCond || cbcond_before()) return false;
|
||||||
intptr_t x = intptr_t(target_distance(L)) - intptr_t(pc());
|
intptr_t x = intptr_t(target_distance(L)) - intptr_t(pc());
|
||||||
assert( (x & 3) == 0, "not word aligned");
|
assert( (x & 3) == 0, "not word aligned");
|
||||||
return is_simm(x, 12);
|
return is_simm12(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tells assembler you know that next instruction is delayed
|
// Tells assembler you know that next instruction is delayed
|
||||||
|
|
|
@ -765,7 +765,7 @@ void LIR_Assembler::ic_call(LIR_OpJavaCall* op) {
|
||||||
void LIR_Assembler::vtable_call(LIR_OpJavaCall* op) {
|
void LIR_Assembler::vtable_call(LIR_OpJavaCall* op) {
|
||||||
add_debug_info_for_null_check_here(op->info());
|
add_debug_info_for_null_check_here(op->info());
|
||||||
__ load_klass(O0, G3_scratch);
|
__ load_klass(O0, G3_scratch);
|
||||||
if (__ is_simm13(op->vtable_offset())) {
|
if (Assembler::is_simm13(op->vtable_offset())) {
|
||||||
__ ld_ptr(G3_scratch, op->vtable_offset(), G5_method);
|
__ ld_ptr(G3_scratch, op->vtable_offset(), G5_method);
|
||||||
} else {
|
} else {
|
||||||
// This will generate 2 instructions
|
// This will generate 2 instructions
|
||||||
|
|
|
@ -315,7 +315,7 @@ void MethodHandles::RicochetFrame::verify_clean(MacroAssembler* _masm) {
|
||||||
__ cmp_and_br_short(O7_temp, T_VOID, Assembler::equal, Assembler::pt, L_ok_4);
|
__ cmp_and_br_short(O7_temp, T_VOID, Assembler::equal, Assembler::pt, L_ok_4);
|
||||||
extract_conversion_vminfo(_masm, L5_conversion, O5_temp);
|
extract_conversion_vminfo(_masm, L5_conversion, O5_temp);
|
||||||
__ ld_ptr(L4_saved_args_base, __ argument_offset(O5_temp, O5_temp), O7_temp);
|
__ ld_ptr(L4_saved_args_base, __ argument_offset(O5_temp, O5_temp), O7_temp);
|
||||||
assert(__ is_simm13(RETURN_VALUE_PLACEHOLDER), "must be simm13");
|
assert(Assembler::is_simm13(RETURN_VALUE_PLACEHOLDER), "must be simm13");
|
||||||
__ cmp_and_brx_short(O7_temp, (int32_t) RETURN_VALUE_PLACEHOLDER, Assembler::equal, Assembler::pt, L_ok_4);
|
__ cmp_and_brx_short(O7_temp, (int32_t) RETURN_VALUE_PLACEHOLDER, Assembler::equal, Assembler::pt, L_ok_4);
|
||||||
__ stop("damaged ricochet frame: RETURN_VALUE_PLACEHOLDER not found");
|
__ stop("damaged ricochet frame: RETURN_VALUE_PLACEHOLDER not found");
|
||||||
__ BIND(L_ok_4);
|
__ BIND(L_ok_4);
|
||||||
|
|
|
@ -767,7 +767,7 @@ void AdapterGenerator::gen_c2i_adapter(
|
||||||
// In the 64bit build because of wider slots and STACKBIAS we can run
|
// In the 64bit build because of wider slots and STACKBIAS we can run
|
||||||
// out of bits in the displacement to do loads and stores. Use g3 as
|
// out of bits in the displacement to do loads and stores. Use g3 as
|
||||||
// temporary displacement.
|
// temporary displacement.
|
||||||
if (! __ is_simm13(extraspace)) {
|
if (!Assembler::is_simm13(extraspace)) {
|
||||||
__ set(extraspace, G3_scratch);
|
__ set(extraspace, G3_scratch);
|
||||||
__ sub(SP, G3_scratch, SP);
|
__ sub(SP, G3_scratch, SP);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -566,7 +566,7 @@ int MachCallDynamicJavaNode::ret_addr_offset() {
|
||||||
} else {
|
} else {
|
||||||
klass_load_size = 1*BytesPerInstWord;
|
klass_load_size = 1*BytesPerInstWord;
|
||||||
}
|
}
|
||||||
if( Assembler::is_simm13(v_off) ) {
|
if (Assembler::is_simm13(v_off)) {
|
||||||
return klass_load_size +
|
return klass_load_size +
|
||||||
(2*BytesPerInstWord + // ld_ptr, ld_ptr
|
(2*BytesPerInstWord + // ld_ptr, ld_ptr
|
||||||
NativeCall::instruction_size); // call; delay slot
|
NativeCall::instruction_size); // call; delay slot
|
||||||
|
@ -1019,17 +1019,31 @@ void emit_hi(CodeBuffer &cbuf, int val) { }
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
const bool Matcher::constant_table_absolute_addressing = false;
|
|
||||||
const RegMask& MachConstantBaseNode::_out_RegMask = PTR_REG_mask;
|
const RegMask& MachConstantBaseNode::_out_RegMask = PTR_REG_mask;
|
||||||
|
|
||||||
|
int Compile::ConstantTable::calculate_table_base_offset() const {
|
||||||
|
if (UseRDPCForConstantTableBase) {
|
||||||
|
// The table base offset might be less but then it fits into
|
||||||
|
// simm13 anyway and we are good (cf. MachConstantBaseNode::emit).
|
||||||
|
return Assembler::min_simm13();
|
||||||
|
} else {
|
||||||
|
int offset = -(size() / 2);
|
||||||
|
if (!Assembler::is_simm13(offset)) {
|
||||||
|
offset = Assembler::min_simm13();
|
||||||
|
}
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
|
void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
|
||||||
Compile* C = ra_->C;
|
Compile* C = ra_->C;
|
||||||
Compile::ConstantTable& constant_table = C->constant_table();
|
Compile::ConstantTable& constant_table = C->constant_table();
|
||||||
MacroAssembler _masm(&cbuf);
|
MacroAssembler _masm(&cbuf);
|
||||||
|
|
||||||
Register r = as_Register(ra_->get_encode(this));
|
Register r = as_Register(ra_->get_encode(this));
|
||||||
CodeSection* cs = __ code()->consts();
|
CodeSection* consts_section = __ code()->consts();
|
||||||
int consts_size = cs->align_at_start(cs->size());
|
int consts_size = consts_section->align_at_start(consts_section->size());
|
||||||
|
assert(constant_table.size() == consts_size, err_msg("must be: %d == %d", constant_table.size(), consts_size));
|
||||||
|
|
||||||
if (UseRDPCForConstantTableBase) {
|
if (UseRDPCForConstantTableBase) {
|
||||||
// For the following RDPC logic to work correctly the consts
|
// For the following RDPC logic to work correctly the consts
|
||||||
|
@ -1037,30 +1051,37 @@ void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
|
||||||
// assert checks for that. The layout and the SECT_* constants
|
// assert checks for that. The layout and the SECT_* constants
|
||||||
// are defined in src/share/vm/asm/codeBuffer.hpp.
|
// are defined in src/share/vm/asm/codeBuffer.hpp.
|
||||||
assert(CodeBuffer::SECT_CONSTS + 1 == CodeBuffer::SECT_INSTS, "must be");
|
assert(CodeBuffer::SECT_CONSTS + 1 == CodeBuffer::SECT_INSTS, "must be");
|
||||||
int offset = __ offset();
|
int insts_offset = __ offset();
|
||||||
|
|
||||||
|
// Layout:
|
||||||
|
//
|
||||||
|
// |----------- consts section ------------|----------- insts section -----------...
|
||||||
|
// |------ constant table -----|- padding -|------------------x----
|
||||||
|
// \ current PC (RDPC instruction)
|
||||||
|
// |<------------- consts_size ----------->|<- insts_offset ->|
|
||||||
|
// \ table base
|
||||||
|
// The table base offset is later added to the load displacement
|
||||||
|
// so it has to be negative.
|
||||||
|
int table_base_offset = -(consts_size + insts_offset);
|
||||||
int disp;
|
int disp;
|
||||||
|
|
||||||
// If the displacement from the current PC to the constant table
|
// If the displacement from the current PC to the constant table
|
||||||
// base fits into simm13 we set the constant table base to the
|
// base fits into simm13 we set the constant table base to the
|
||||||
// current PC.
|
// current PC.
|
||||||
if (__ is_simm13(-(consts_size + offset))) {
|
if (Assembler::is_simm13(table_base_offset)) {
|
||||||
constant_table.set_table_base_offset(-(consts_size + offset));
|
constant_table.set_table_base_offset(table_base_offset);
|
||||||
disp = 0;
|
disp = 0;
|
||||||
} else {
|
} else {
|
||||||
// If the offset of the top constant (last entry in the table)
|
// Otherwise we set the constant table base offset to the
|
||||||
// fits into simm13 we set the constant table base to the actual
|
// maximum negative displacement of load instructions to keep
|
||||||
// table base.
|
// the disp as small as possible:
|
||||||
if (__ is_simm13(constant_table.top_offset())) {
|
//
|
||||||
constant_table.set_table_base_offset(0);
|
// |<------------- consts_size ----------->|<- insts_offset ->|
|
||||||
disp = consts_size + offset;
|
// |<--------- min_simm13 --------->|<-------- disp --------->|
|
||||||
} else {
|
// \ table base
|
||||||
// Otherwise we set the constant table base in the middle of the
|
table_base_offset = Assembler::min_simm13();
|
||||||
// constant table.
|
constant_table.set_table_base_offset(table_base_offset);
|
||||||
int half_consts_size = consts_size / 2;
|
disp = (consts_size + insts_offset) + table_base_offset;
|
||||||
assert(half_consts_size * 2 == consts_size, "sanity");
|
|
||||||
constant_table.set_table_base_offset(-half_consts_size); // table base offset gets added to the load displacement.
|
|
||||||
disp = half_consts_size + offset;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__ rdpc(r);
|
__ rdpc(r);
|
||||||
|
@ -1072,8 +1093,7 @@ void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Materialize the constant table base.
|
// Materialize the constant table base.
|
||||||
assert(constant_table.size() == consts_size, err_msg("must be: %d == %d", constant_table.size(), consts_size));
|
address baseaddr = consts_section->start() + -(constant_table.table_base_offset());
|
||||||
address baseaddr = cs->start() + -(constant_table.table_base_offset());
|
|
||||||
RelocationHolder rspec = internal_word_Relocation::spec(baseaddr);
|
RelocationHolder rspec = internal_word_Relocation::spec(baseaddr);
|
||||||
AddressLiteral base(baseaddr, rspec);
|
AddressLiteral base(baseaddr, rspec);
|
||||||
__ set(base, r);
|
__ set(base, r);
|
||||||
|
@ -1169,6 +1189,13 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||||
__ save(SP, G3, SP);
|
__ save(SP, G3, SP);
|
||||||
}
|
}
|
||||||
C->set_frame_complete( __ offset() );
|
C->set_frame_complete( __ offset() );
|
||||||
|
|
||||||
|
if (!UseRDPCForConstantTableBase && C->has_mach_constant_base_node()) {
|
||||||
|
// NOTE: We set the table base offset here because users might be
|
||||||
|
// emitted before MachConstantBaseNode.
|
||||||
|
Compile::ConstantTable& constant_table = C->constant_table();
|
||||||
|
constant_table.set_table_base_offset(constant_table.calculate_table_base_offset());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint MachPrologNode::size(PhaseRegAlloc *ra_) const {
|
uint MachPrologNode::size(PhaseRegAlloc *ra_) const {
|
||||||
|
@ -1843,7 +1870,7 @@ const bool Matcher::convL2FSupported(void) {
|
||||||
bool Matcher::is_short_branch_offset(int rule, int br_size, int offset) {
|
bool Matcher::is_short_branch_offset(int rule, int br_size, int offset) {
|
||||||
// The passed offset is relative to address of the branch.
|
// The passed offset is relative to address of the branch.
|
||||||
// Don't need to adjust the offset.
|
// Don't need to adjust the offset.
|
||||||
return UseCBCond && Assembler::is_simm(offset, 12);
|
return UseCBCond && Assembler::is_simm12(offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool Matcher::isSimpleConstant64(jlong value) {
|
const bool Matcher::isSimpleConstant64(jlong value) {
|
||||||
|
@ -2072,8 +2099,8 @@ encode %{
|
||||||
%}
|
%}
|
||||||
|
|
||||||
enc_class form3_mem_reg_long_unaligned_marshal( memory mem, iRegL reg ) %{
|
enc_class form3_mem_reg_long_unaligned_marshal( memory mem, iRegL reg ) %{
|
||||||
assert( Assembler::is_simm13($mem$$disp ), "need disp and disp+4" );
|
assert(Assembler::is_simm13($mem$$disp ), "need disp and disp+4");
|
||||||
assert( Assembler::is_simm13($mem$$disp+4), "need disp and disp+4" );
|
assert(Assembler::is_simm13($mem$$disp+4), "need disp and disp+4");
|
||||||
guarantee($mem$$index == R_G0_enc, "double index?");
|
guarantee($mem$$index == R_G0_enc, "double index?");
|
||||||
emit_form3_mem_reg(cbuf, this, $primary, -1, $mem$$base, $mem$$disp+4, R_G0_enc, R_O7_enc );
|
emit_form3_mem_reg(cbuf, this, $primary, -1, $mem$$base, $mem$$disp+4, R_G0_enc, R_O7_enc );
|
||||||
emit_form3_mem_reg(cbuf, this, $primary, -1, $mem$$base, $mem$$disp, R_G0_enc, $reg$$reg );
|
emit_form3_mem_reg(cbuf, this, $primary, -1, $mem$$base, $mem$$disp, R_G0_enc, $reg$$reg );
|
||||||
|
@ -2082,8 +2109,8 @@ encode %{
|
||||||
%}
|
%}
|
||||||
|
|
||||||
enc_class form3_mem_reg_double_unaligned( memory mem, RegD_low reg ) %{
|
enc_class form3_mem_reg_double_unaligned( memory mem, RegD_low reg ) %{
|
||||||
assert( Assembler::is_simm13($mem$$disp ), "need disp and disp+4" );
|
assert(Assembler::is_simm13($mem$$disp ), "need disp and disp+4");
|
||||||
assert( Assembler::is_simm13($mem$$disp+4), "need disp and disp+4" );
|
assert(Assembler::is_simm13($mem$$disp+4), "need disp and disp+4");
|
||||||
guarantee($mem$$index == R_G0_enc, "double index?");
|
guarantee($mem$$index == R_G0_enc, "double index?");
|
||||||
// Load long with 2 instructions
|
// Load long with 2 instructions
|
||||||
emit_form3_mem_reg(cbuf, this, $primary, -1, $mem$$base, $mem$$disp, R_G0_enc, $reg$$reg+0 );
|
emit_form3_mem_reg(cbuf, this, $primary, -1, $mem$$base, $mem$$disp, R_G0_enc, $reg$$reg+0 );
|
||||||
|
@ -2563,7 +2590,7 @@ encode %{
|
||||||
}
|
}
|
||||||
int entry_offset = instanceKlass::vtable_start_offset() + vtable_index*vtableEntry::size();
|
int entry_offset = instanceKlass::vtable_start_offset() + vtable_index*vtableEntry::size();
|
||||||
int v_off = entry_offset*wordSize + vtableEntry::method_offset_in_bytes();
|
int v_off = entry_offset*wordSize + vtableEntry::method_offset_in_bytes();
|
||||||
if( __ is_simm13(v_off) ) {
|
if (Assembler::is_simm13(v_off)) {
|
||||||
__ ld_ptr(G3, v_off, G5_method);
|
__ ld_ptr(G3, v_off, G5_method);
|
||||||
} else {
|
} else {
|
||||||
// Generate 2 instructions
|
// Generate 2 instructions
|
||||||
|
@ -3336,7 +3363,7 @@ operand immI() %{
|
||||||
|
|
||||||
// Integer Immediate: 8-bit
|
// Integer Immediate: 8-bit
|
||||||
operand immI8() %{
|
operand immI8() %{
|
||||||
predicate(Assembler::is_simm(n->get_int(), 8));
|
predicate(Assembler::is_simm8(n->get_int()));
|
||||||
match(ConI);
|
match(ConI);
|
||||||
op_cost(0);
|
op_cost(0);
|
||||||
format %{ %}
|
format %{ %}
|
||||||
|
@ -3365,7 +3392,7 @@ operand immI13m7() %{
|
||||||
|
|
||||||
// Integer Immediate: 16-bit
|
// Integer Immediate: 16-bit
|
||||||
operand immI16() %{
|
operand immI16() %{
|
||||||
predicate(Assembler::is_simm(n->get_int(), 16));
|
predicate(Assembler::is_simm16(n->get_int()));
|
||||||
match(ConI);
|
match(ConI);
|
||||||
op_cost(0);
|
op_cost(0);
|
||||||
format %{ %}
|
format %{ %}
|
||||||
|
@ -3393,7 +3420,7 @@ operand immU6() %{
|
||||||
|
|
||||||
// Integer Immediate: 11-bit
|
// Integer Immediate: 11-bit
|
||||||
operand immI11() %{
|
operand immI11() %{
|
||||||
predicate(Assembler::is_simm(n->get_int(),11));
|
predicate(Assembler::is_simm11(n->get_int()));
|
||||||
match(ConI);
|
match(ConI);
|
||||||
op_cost(0);
|
op_cost(0);
|
||||||
format %{ %}
|
format %{ %}
|
||||||
|
@ -3402,7 +3429,7 @@ operand immI11() %{
|
||||||
|
|
||||||
// Integer Immediate: 5-bit
|
// Integer Immediate: 5-bit
|
||||||
operand immI5() %{
|
operand immI5() %{
|
||||||
predicate(Assembler::is_simm(n->get_int(), 5));
|
predicate(Assembler::is_simm5(n->get_int()));
|
||||||
match(ConI);
|
match(ConI);
|
||||||
op_cost(0);
|
op_cost(0);
|
||||||
format %{ %}
|
format %{ %}
|
||||||
|
@ -3634,7 +3661,7 @@ operand immL0() %{
|
||||||
|
|
||||||
// Integer Immediate: 5-bit
|
// Integer Immediate: 5-bit
|
||||||
operand immL5() %{
|
operand immL5() %{
|
||||||
predicate(n->get_long() == (int)n->get_long() && Assembler::is_simm((int)n->get_long(), 5));
|
predicate(n->get_long() == (int)n->get_long() && Assembler::is_simm5((int)n->get_long()));
|
||||||
match(ConL);
|
match(ConL);
|
||||||
op_cost(0);
|
op_cost(0);
|
||||||
format %{ %}
|
format %{ %}
|
||||||
|
@ -9251,13 +9278,16 @@ instruct jumpXtnd(iRegX switch_val, o7RegI table) %{
|
||||||
|
|
||||||
format %{ "ADD $constanttablebase, $constantoffset, O7\n\t"
|
format %{ "ADD $constanttablebase, $constantoffset, O7\n\t"
|
||||||
"LD [O7 + $switch_val], O7\n\t"
|
"LD [O7 + $switch_val], O7\n\t"
|
||||||
"JUMP O7"
|
"JUMP O7" %}
|
||||||
%}
|
|
||||||
ins_encode %{
|
ins_encode %{
|
||||||
// Calculate table address into a register.
|
// Calculate table address into a register.
|
||||||
Register table_reg;
|
Register table_reg;
|
||||||
Register label_reg = O7;
|
Register label_reg = O7;
|
||||||
if (constant_offset() == 0) {
|
// If we are calculating the size of this instruction don't trust
|
||||||
|
// zero offsets because they might change when
|
||||||
|
// MachConstantBaseNode decides to optimize the constant table
|
||||||
|
// base.
|
||||||
|
if ((constant_offset() == 0) && !Compile::current()->in_scratch_emit_size()) {
|
||||||
table_reg = $constanttablebase;
|
table_reg = $constanttablebase;
|
||||||
} else {
|
} else {
|
||||||
table_reg = O7;
|
table_reg = O7;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -83,7 +83,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
int v_off = entry_offset*wordSize + vtableEntry::method_offset_in_bytes();
|
int v_off = entry_offset*wordSize + vtableEntry::method_offset_in_bytes();
|
||||||
if( __ is_simm13(v_off) ) {
|
if (Assembler::is_simm13(v_off)) {
|
||||||
__ ld_ptr(G3, v_off, G5_method);
|
__ ld_ptr(G3, v_off, G5_method);
|
||||||
} else {
|
} else {
|
||||||
__ set(v_off,G5);
|
__ set(v_off,G5);
|
||||||
|
|
|
@ -693,17 +693,6 @@ private:
|
||||||
static address locate_next_instruction(address inst);
|
static address locate_next_instruction(address inst);
|
||||||
|
|
||||||
// Utilities
|
// Utilities
|
||||||
|
|
||||||
#ifdef _LP64
|
|
||||||
static bool is_simm(int64_t x, int nbits) { return -(CONST64(1) << (nbits-1)) <= x &&
|
|
||||||
x < (CONST64(1) << (nbits-1)); }
|
|
||||||
static bool is_simm32(int64_t x) { return x == (int64_t)(int32_t)x; }
|
|
||||||
#else
|
|
||||||
static bool is_simm(int32_t x, int nbits) { return -(1 << (nbits-1)) <= x &&
|
|
||||||
x < (1 << (nbits-1)); }
|
|
||||||
static bool is_simm32(int32_t x) { return true; }
|
|
||||||
#endif // _LP64
|
|
||||||
|
|
||||||
static bool is_polling_page_far() NOT_LP64({ return false;});
|
static bool is_polling_page_far() NOT_LP64({ return false;});
|
||||||
|
|
||||||
// Generic instructions
|
// Generic instructions
|
||||||
|
|
|
@ -1268,7 +1268,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
__ subptr(end, start); // number of bytes to copy
|
__ subptr(end, start); // number of bytes to copy
|
||||||
|
|
||||||
intptr_t disp = (intptr_t) ct->byte_map_base;
|
intptr_t disp = (intptr_t) ct->byte_map_base;
|
||||||
if (__ is_simm32(disp)) {
|
if (Assembler::is_simm32(disp)) {
|
||||||
Address cardtable(noreg, noreg, Address::no_scale, disp);
|
Address cardtable(noreg, noreg, Address::no_scale, disp);
|
||||||
__ lea(scratch, cardtable);
|
__ lea(scratch, cardtable);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -507,9 +507,12 @@ void encode_CopyXD( CodeBuffer &cbuf, int dst_encoding, int src_encoding ) {
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
const bool Matcher::constant_table_absolute_addressing = true;
|
|
||||||
const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty;
|
const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty;
|
||||||
|
|
||||||
|
int Compile::ConstantTable::calculate_table_base_offset() const {
|
||||||
|
return 0; // absolute addressing, no offset
|
||||||
|
}
|
||||||
|
|
||||||
void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
|
void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
|
||||||
// Empty encoding
|
// Empty encoding
|
||||||
}
|
}
|
||||||
|
@ -639,6 +642,12 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (C->has_mach_constant_base_node()) {
|
||||||
|
// NOTE: We set the table base offset here because users might be
|
||||||
|
// emitted before MachConstantBaseNode.
|
||||||
|
Compile::ConstantTable& constant_table = C->constant_table();
|
||||||
|
constant_table.set_table_base_offset(constant_table.calculate_table_base_offset());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint MachPrologNode::size(PhaseRegAlloc *ra_) const {
|
uint MachPrologNode::size(PhaseRegAlloc *ra_) const {
|
||||||
|
|
|
@ -843,9 +843,12 @@ void emit_cmpfp_fixup(MacroAssembler& _masm) {
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
const bool Matcher::constant_table_absolute_addressing = true;
|
|
||||||
const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty;
|
const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty;
|
||||||
|
|
||||||
|
int Compile::ConstantTable::calculate_table_base_offset() const {
|
||||||
|
return 0; // absolute addressing, no offset
|
||||||
|
}
|
||||||
|
|
||||||
void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
|
void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
|
||||||
// Empty encoding
|
// Empty encoding
|
||||||
}
|
}
|
||||||
|
@ -977,6 +980,13 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const
|
||||||
masm.bind(L);
|
masm.bind(L);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (C->has_mach_constant_base_node()) {
|
||||||
|
// NOTE: We set the table base offset here because users might be
|
||||||
|
// emitted before MachConstantBaseNode.
|
||||||
|
Compile::ConstantTable& constant_table = C->constant_table();
|
||||||
|
constant_table.set_table_base_offset(constant_table.calculate_table_base_offset());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint MachPrologNode::size(PhaseRegAlloc* ra_) const
|
uint MachPrologNode::size(PhaseRegAlloc* ra_) const
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -3115,7 +3115,7 @@ void ADLParser::constant_parse_expression(EncClass* encoding, char* ec_name) {
|
||||||
encoding->add_code(" _constant = C->constant_table().add");
|
encoding->add_code(" _constant = C->constant_table().add");
|
||||||
|
|
||||||
// Parse everything in ( ) expression.
|
// Parse everything in ( ) expression.
|
||||||
encoding->add_code("(");
|
encoding->add_code("(this, ");
|
||||||
next_char(); // Skip '('
|
next_char(); // Skip '('
|
||||||
int parens_depth = 1;
|
int parens_depth = 1;
|
||||||
|
|
||||||
|
@ -3130,6 +3130,7 @@ void ADLParser::constant_parse_expression(EncClass* encoding, char* ec_name) {
|
||||||
}
|
}
|
||||||
else if (_curchar == ')') {
|
else if (_curchar == ')') {
|
||||||
parens_depth--;
|
parens_depth--;
|
||||||
|
if (parens_depth > 0)
|
||||||
encoding->add_code(")");
|
encoding->add_code(")");
|
||||||
next_char();
|
next_char();
|
||||||
}
|
}
|
||||||
|
@ -3157,7 +3158,7 @@ void ADLParser::constant_parse_expression(EncClass* encoding, char* ec_name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finish code line.
|
// Finish code line.
|
||||||
encoding->add_code(";");
|
encoding->add_code(");");
|
||||||
|
|
||||||
if (_AD._adlocation_debug) {
|
if (_AD._adlocation_debug) {
|
||||||
encoding->add_code(end_line_marker());
|
encoding->add_code(end_line_marker());
|
||||||
|
|
|
@ -2585,9 +2585,9 @@ void ArchDesc::defineEvalConstant(FILE* fp, InstructForm& inst) {
|
||||||
// Output instruction's emit prototype
|
// Output instruction's emit prototype
|
||||||
fprintf(fp, "void %sNode::eval_constant(Compile* C) {\n", inst._ident);
|
fprintf(fp, "void %sNode::eval_constant(Compile* C) {\n", inst._ident);
|
||||||
|
|
||||||
// For ideal jump nodes, allocate a jump table.
|
// For ideal jump nodes, add a jump-table entry.
|
||||||
if (inst.is_ideal_jump()) {
|
if (inst.is_ideal_jump()) {
|
||||||
fprintf(fp, " _constant = C->constant_table().allocate_jump_table(this);\n");
|
fprintf(fp, " _constant = C->constant_table().add_jump_table(this);\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// If user did not define an encode section,
|
// If user did not define an encode section,
|
||||||
|
|
|
@ -257,6 +257,29 @@ class AbstractAssembler : public ResourceObj {
|
||||||
// ensure buf contains all code (call this before using/copying the code)
|
// ensure buf contains all code (call this before using/copying the code)
|
||||||
void flush();
|
void flush();
|
||||||
|
|
||||||
|
// min and max values for signed immediate ranges
|
||||||
|
static int min_simm(int nbits) { return -(intptr_t(1) << (nbits - 1)) ; }
|
||||||
|
static int max_simm(int nbits) { return (intptr_t(1) << (nbits - 1)) - 1; }
|
||||||
|
|
||||||
|
// Define some:
|
||||||
|
static int min_simm10() { return min_simm(10); }
|
||||||
|
static int min_simm13() { return min_simm(13); }
|
||||||
|
static int min_simm16() { return min_simm(16); }
|
||||||
|
|
||||||
|
// Test if x is within signed immediate range for nbits
|
||||||
|
static bool is_simm(intptr_t x, int nbits) { return min_simm(nbits) <= x && x <= max_simm(nbits); }
|
||||||
|
|
||||||
|
// Define some:
|
||||||
|
static bool is_simm5( intptr_t x) { return is_simm(x, 5 ); }
|
||||||
|
static bool is_simm8( intptr_t x) { return is_simm(x, 8 ); }
|
||||||
|
static bool is_simm10(intptr_t x) { return is_simm(x, 10); }
|
||||||
|
static bool is_simm11(intptr_t x) { return is_simm(x, 11); }
|
||||||
|
static bool is_simm12(intptr_t x) { return is_simm(x, 12); }
|
||||||
|
static bool is_simm13(intptr_t x) { return is_simm(x, 13); }
|
||||||
|
static bool is_simm16(intptr_t x) { return is_simm(x, 16); }
|
||||||
|
static bool is_simm26(intptr_t x) { return is_simm(x, 26); }
|
||||||
|
static bool is_simm32(intptr_t x) { return is_simm(x, 32); }
|
||||||
|
|
||||||
// Accessors
|
// Accessors
|
||||||
CodeBuffer* code() const; // _code_section->outer()
|
CodeBuffer* code() const; // _code_section->outer()
|
||||||
CodeSection* code_section() const { return _code_section; }
|
CodeSection* code_section() const { return _code_section; }
|
||||||
|
|
|
@ -3052,24 +3052,13 @@ bool Compile::Constant::operator==(const Constant& other) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit constants grouped in the following order:
|
|
||||||
static BasicType type_order[] = {
|
|
||||||
T_FLOAT, // 32-bit
|
|
||||||
T_OBJECT, // 32 or 64-bit
|
|
||||||
T_ADDRESS, // 32 or 64-bit
|
|
||||||
T_DOUBLE, // 64-bit
|
|
||||||
T_LONG, // 64-bit
|
|
||||||
T_VOID, // 32 or 64-bit (jump-tables are at the end of the constant table for code emission reasons)
|
|
||||||
T_ILLEGAL
|
|
||||||
};
|
|
||||||
|
|
||||||
static int type_to_size_in_bytes(BasicType t) {
|
static int type_to_size_in_bytes(BasicType t) {
|
||||||
switch (t) {
|
switch (t) {
|
||||||
case T_LONG: return sizeof(jlong );
|
case T_LONG: return sizeof(jlong );
|
||||||
case T_FLOAT: return sizeof(jfloat );
|
case T_FLOAT: return sizeof(jfloat );
|
||||||
case T_DOUBLE: return sizeof(jdouble);
|
case T_DOUBLE: return sizeof(jdouble);
|
||||||
// We use T_VOID as marker for jump-table entries (labels) which
|
// We use T_VOID as marker for jump-table entries (labels) which
|
||||||
// need an interal word relocation.
|
// need an internal word relocation.
|
||||||
case T_VOID:
|
case T_VOID:
|
||||||
case T_ADDRESS:
|
case T_ADDRESS:
|
||||||
case T_OBJECT: return sizeof(jobject);
|
case T_OBJECT: return sizeof(jobject);
|
||||||
|
@ -3079,57 +3068,57 @@ static int type_to_size_in_bytes(BasicType t) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compile::ConstantTable::calculate_offsets_and_size() {
|
int Compile::ConstantTable::qsort_comparator(Constant* a, Constant* b) {
|
||||||
int size = 0;
|
// sort descending
|
||||||
for (int t = 0; type_order[t] != T_ILLEGAL; t++) {
|
if (a->freq() > b->freq()) return -1;
|
||||||
BasicType type = type_order[t];
|
if (a->freq() < b->freq()) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Compile::ConstantTable::calculate_offsets_and_size() {
|
||||||
|
// First, sort the array by frequencies.
|
||||||
|
_constants.sort(qsort_comparator);
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
// Make sure all jump-table entries were sorted to the end of the
|
||||||
|
// array (they have a negative frequency).
|
||||||
|
bool found_void = false;
|
||||||
for (int i = 0; i < _constants.length(); i++) {
|
for (int i = 0; i < _constants.length(); i++) {
|
||||||
Constant con = _constants.at(i);
|
Constant con = _constants.at(i);
|
||||||
if (con.type() != type) continue; // Skip other types.
|
if (con.type() == T_VOID)
|
||||||
|
found_void = true; // jump-tables
|
||||||
|
else
|
||||||
|
assert(!found_void, "wrong sorting");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Align size for type.
|
int offset = 0;
|
||||||
int typesize = type_to_size_in_bytes(con.type());
|
for (int i = 0; i < _constants.length(); i++) {
|
||||||
size = align_size_up(size, typesize);
|
Constant* con = _constants.adr_at(i);
|
||||||
|
|
||||||
// Set offset.
|
// Align offset for type.
|
||||||
con.set_offset(size);
|
int typesize = type_to_size_in_bytes(con->type());
|
||||||
_constants.at_put(i, con);
|
offset = align_size_up(offset, typesize);
|
||||||
|
con->set_offset(offset); // set constant's offset
|
||||||
|
|
||||||
// Add type size.
|
if (con->type() == T_VOID) {
|
||||||
size = size + typesize;
|
MachConstantNode* n = (MachConstantNode*) con->get_jobject();
|
||||||
|
offset = offset + typesize * n->outcnt(); // expand jump-table
|
||||||
|
} else {
|
||||||
|
offset = offset + typesize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Align size up to the next section start (which is insts; see
|
// Align size up to the next section start (which is insts; see
|
||||||
// CodeBuffer::align_at_start).
|
// CodeBuffer::align_at_start).
|
||||||
assert(_size == -1, "already set?");
|
assert(_size == -1, "already set?");
|
||||||
_size = align_size_up(size, CodeEntryAlignment);
|
_size = align_size_up(offset, CodeEntryAlignment);
|
||||||
|
|
||||||
if (Matcher::constant_table_absolute_addressing) {
|
|
||||||
set_table_base_offset(0); // No table base offset required
|
|
||||||
} else {
|
|
||||||
if (UseRDPCForConstantTableBase) {
|
|
||||||
// table base offset is set in MachConstantBaseNode::emit
|
|
||||||
} else {
|
|
||||||
// When RDPC is not used, the table base is set into the middle of
|
|
||||||
// the constant table.
|
|
||||||
int half_size = _size / 2;
|
|
||||||
assert(half_size * 2 == _size, "sanity");
|
|
||||||
set_table_base_offset(-half_size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compile::ConstantTable::emit(CodeBuffer& cb) {
|
void Compile::ConstantTable::emit(CodeBuffer& cb) {
|
||||||
MacroAssembler _masm(&cb);
|
MacroAssembler _masm(&cb);
|
||||||
for (int t = 0; type_order[t] != T_ILLEGAL; t++) {
|
|
||||||
BasicType type = type_order[t];
|
|
||||||
|
|
||||||
for (int i = 0; i < _constants.length(); i++) {
|
for (int i = 0; i < _constants.length(); i++) {
|
||||||
Constant con = _constants.at(i);
|
Constant con = _constants.at(i);
|
||||||
if (con.type() != type) continue; // Skip other types.
|
|
||||||
|
|
||||||
address constant_addr;
|
address constant_addr;
|
||||||
switch (con.type()) {
|
switch (con.type()) {
|
||||||
case T_LONG: constant_addr = _masm.long_constant( con.get_jlong() ); break;
|
case T_LONG: constant_addr = _masm.long_constant( con.get_jlong() ); break;
|
||||||
|
@ -3147,20 +3136,25 @@ void Compile::ConstantTable::emit(CodeBuffer& cb) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// We use T_VOID as marker for jump-table entries (labels) which
|
// We use T_VOID as marker for jump-table entries (labels) which
|
||||||
// need an interal word relocation.
|
// need an internal word relocation.
|
||||||
case T_VOID: {
|
case T_VOID: {
|
||||||
// Write a dummy word. The real value is filled in later
|
MachConstantNode* n = (MachConstantNode*) con.get_jobject();
|
||||||
// in fill_jump_table_in_constant_table.
|
// Fill the jump-table with a dummy word. The real value is
|
||||||
address addr = (address) con.get_jobject();
|
// filled in later in fill_jump_table.
|
||||||
constant_addr = _masm.address_constant(addr);
|
address dummy = (address) n;
|
||||||
|
constant_addr = _masm.address_constant(dummy);
|
||||||
|
// Expand jump-table
|
||||||
|
for (uint i = 1; i < n->outcnt(); i++) {
|
||||||
|
address temp_addr = _masm.address_constant(dummy + i);
|
||||||
|
assert(temp_addr, "consts section too small");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: ShouldNotReachHere();
|
default: ShouldNotReachHere();
|
||||||
}
|
}
|
||||||
assert(constant_addr != NULL, "consts section too small");
|
assert(constant_addr, "consts section too small");
|
||||||
assert((constant_addr - _masm.code()->consts()->start()) == con.offset(), err_msg("must be: %d == %d", constant_addr - _masm.code()->consts()->start(), con.offset()));
|
assert((constant_addr - _masm.code()->consts()->start()) == con.offset(), err_msg("must be: %d == %d", constant_addr - _masm.code()->consts()->start(), con.offset()));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Compile::ConstantTable::find_offset(Constant& con) const {
|
int Compile::ConstantTable::find_offset(Constant& con) const {
|
||||||
|
@ -3175,19 +3169,21 @@ void Compile::ConstantTable::add(Constant& con) {
|
||||||
if (con.can_be_reused()) {
|
if (con.can_be_reused()) {
|
||||||
int idx = _constants.find(con);
|
int idx = _constants.find(con);
|
||||||
if (idx != -1 && _constants.at(idx).can_be_reused()) {
|
if (idx != -1 && _constants.at(idx).can_be_reused()) {
|
||||||
|
_constants.adr_at(idx)->inc_freq(con.freq()); // increase the frequency by the current value
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(void) _constants.append(con);
|
(void) _constants.append(con);
|
||||||
}
|
}
|
||||||
|
|
||||||
Compile::Constant Compile::ConstantTable::add(BasicType type, jvalue value) {
|
Compile::Constant Compile::ConstantTable::add(MachConstantNode* n, BasicType type, jvalue value) {
|
||||||
Constant con(type, value);
|
Block* b = Compile::current()->cfg()->_bbs[n->_idx];
|
||||||
|
Constant con(type, value, b->_freq);
|
||||||
add(con);
|
add(con);
|
||||||
return con;
|
return con;
|
||||||
}
|
}
|
||||||
|
|
||||||
Compile::Constant Compile::ConstantTable::add(MachOper* oper) {
|
Compile::Constant Compile::ConstantTable::add(MachConstantNode* n, MachOper* oper) {
|
||||||
jvalue value;
|
jvalue value;
|
||||||
BasicType type = oper->type()->basic_type();
|
BasicType type = oper->type()->basic_type();
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
@ -3198,20 +3194,18 @@ Compile::Constant Compile::ConstantTable::add(MachOper* oper) {
|
||||||
case T_ADDRESS: value.l = (jobject) oper->constant(); break;
|
case T_ADDRESS: value.l = (jobject) oper->constant(); break;
|
||||||
default: ShouldNotReachHere();
|
default: ShouldNotReachHere();
|
||||||
}
|
}
|
||||||
return add(type, value);
|
return add(n, type, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Compile::Constant Compile::ConstantTable::allocate_jump_table(MachConstantNode* n) {
|
Compile::Constant Compile::ConstantTable::add_jump_table(MachConstantNode* n) {
|
||||||
jvalue value;
|
jvalue value;
|
||||||
// We can use the node pointer here to identify the right jump-table
|
// We can use the node pointer here to identify the right jump-table
|
||||||
// as this method is called from Compile::Fill_buffer right before
|
// as this method is called from Compile::Fill_buffer right before
|
||||||
// the MachNodes are emitted and the jump-table is filled (means the
|
// the MachNodes are emitted and the jump-table is filled (means the
|
||||||
// MachNode pointers do not change anymore).
|
// MachNode pointers do not change anymore).
|
||||||
value.l = (jobject) n;
|
value.l = (jobject) n;
|
||||||
Constant con(T_VOID, value, false); // Labels of a jump-table cannot be reused.
|
Constant con(T_VOID, value, next_jump_table_freq(), false); // Labels of a jump-table cannot be reused.
|
||||||
for (uint i = 0; i < n->outcnt(); i++) {
|
|
||||||
add(con);
|
add(con);
|
||||||
}
|
|
||||||
return con;
|
return con;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3230,9 +3224,9 @@ void Compile::ConstantTable::fill_jump_table(CodeBuffer& cb, MachConstantNode* n
|
||||||
MacroAssembler _masm(&cb);
|
MacroAssembler _masm(&cb);
|
||||||
address* jump_table_base = (address*) (_masm.code()->consts()->start() + offset);
|
address* jump_table_base = (address*) (_masm.code()->consts()->start() + offset);
|
||||||
|
|
||||||
for (int i = 0; i < labels.length(); i++) {
|
for (uint i = 0; i < n->outcnt(); i++) {
|
||||||
address* constant_addr = &jump_table_base[i];
|
address* constant_addr = &jump_table_base[i];
|
||||||
assert(*constant_addr == (address) n, "all jump-table entries must contain node pointer");
|
assert(*constant_addr == (((address) n) + i), err_msg("all jump-table entries must contain adjusted node pointer: " INTPTR_FORMAT " == " INTPTR_FORMAT, *constant_addr, (((address) n) + i)));
|
||||||
*constant_addr = cb.consts()->target(*labels.at(i), (address) constant_addr);
|
*constant_addr = cb.consts()->target(*labels.at(i), (address) constant_addr);
|
||||||
cb.consts()->relocate((address) constant_addr, relocInfo::internal_word_type);
|
cb.consts()->relocate((address) constant_addr, relocInfo::internal_word_type);
|
||||||
}
|
}
|
||||||
|
|
|
@ -150,14 +150,16 @@ class Compile : public Phase {
|
||||||
BasicType _type;
|
BasicType _type;
|
||||||
jvalue _value;
|
jvalue _value;
|
||||||
int _offset; // offset of this constant (in bytes) relative to the constant table base.
|
int _offset; // offset of this constant (in bytes) relative to the constant table base.
|
||||||
|
float _freq;
|
||||||
bool _can_be_reused; // true (default) if the value can be shared with other users.
|
bool _can_be_reused; // true (default) if the value can be shared with other users.
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Constant() : _type(T_ILLEGAL), _offset(-1), _can_be_reused(true) { _value.l = 0; }
|
Constant() : _type(T_ILLEGAL), _offset(-1), _freq(0.0f), _can_be_reused(true) { _value.l = 0; }
|
||||||
Constant(BasicType type, jvalue value, bool can_be_reused = true) :
|
Constant(BasicType type, jvalue value, float freq = 0.0f, bool can_be_reused = true) :
|
||||||
_type(type),
|
_type(type),
|
||||||
_value(value),
|
_value(value),
|
||||||
_offset(-1),
|
_offset(-1),
|
||||||
|
_freq(freq),
|
||||||
_can_be_reused(can_be_reused)
|
_can_be_reused(can_be_reused)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -173,6 +175,9 @@ class Compile : public Phase {
|
||||||
int offset() const { return _offset; }
|
int offset() const { return _offset; }
|
||||||
void set_offset(int offset) { _offset = offset; }
|
void set_offset(int offset) { _offset = offset; }
|
||||||
|
|
||||||
|
float freq() const { return _freq; }
|
||||||
|
void inc_freq(float freq) { _freq += freq; }
|
||||||
|
|
||||||
bool can_be_reused() const { return _can_be_reused; }
|
bool can_be_reused() const { return _can_be_reused; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -182,40 +187,50 @@ class Compile : public Phase {
|
||||||
GrowableArray<Constant> _constants; // Constants of this table.
|
GrowableArray<Constant> _constants; // Constants of this table.
|
||||||
int _size; // Size in bytes the emitted constant table takes (including padding).
|
int _size; // Size in bytes the emitted constant table takes (including padding).
|
||||||
int _table_base_offset; // Offset of the table base that gets added to the constant offsets.
|
int _table_base_offset; // Offset of the table base that gets added to the constant offsets.
|
||||||
|
int _nof_jump_tables; // Number of jump-tables in this constant table.
|
||||||
|
|
||||||
|
static int qsort_comparator(Constant* a, Constant* b);
|
||||||
|
|
||||||
|
// We use negative frequencies to keep the order of the
|
||||||
|
// jump-tables in which they were added. Otherwise we get into
|
||||||
|
// trouble with relocation.
|
||||||
|
float next_jump_table_freq() { return -1.0f * (++_nof_jump_tables); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ConstantTable() :
|
ConstantTable() :
|
||||||
_size(-1),
|
_size(-1),
|
||||||
_table_base_offset(-1) // We can use -1 here since the constant table is always bigger than 2 bytes (-(size / 2), see MachConstantBaseNode::emit).
|
_table_base_offset(-1), // We can use -1 here since the constant table is always bigger than 2 bytes (-(size / 2), see MachConstantBaseNode::emit).
|
||||||
|
_nof_jump_tables(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
int size() const { assert(_size != -1, "size not yet calculated"); return _size; }
|
int size() const { assert(_size != -1, "not calculated yet"); return _size; }
|
||||||
|
|
||||||
void set_table_base_offset(int x) { assert(_table_base_offset == -1, "set only once"); _table_base_offset = x; }
|
int calculate_table_base_offset() const; // AD specific
|
||||||
int table_base_offset() const { assert(_table_base_offset != -1, "table base offset not yet set"); return _table_base_offset; }
|
void set_table_base_offset(int x) { assert(_table_base_offset == -1 || x == _table_base_offset, "can't change"); _table_base_offset = x; }
|
||||||
|
int table_base_offset() const { assert(_table_base_offset != -1, "not set yet"); return _table_base_offset; }
|
||||||
|
|
||||||
void emit(CodeBuffer& cb);
|
void emit(CodeBuffer& cb);
|
||||||
|
|
||||||
// Returns the offset of the last entry (the top) of the constant table.
|
// Returns the offset of the last entry (the top) of the constant table.
|
||||||
int top_offset() const { assert(_constants.top().offset() != -1, "constant not yet bound"); return _constants.top().offset(); }
|
int top_offset() const { assert(_constants.top().offset() != -1, "not bound yet"); return _constants.top().offset(); }
|
||||||
|
|
||||||
void calculate_offsets_and_size();
|
void calculate_offsets_and_size();
|
||||||
int find_offset(Constant& con) const;
|
int find_offset(Constant& con) const;
|
||||||
|
|
||||||
void add(Constant& con);
|
void add(Constant& con);
|
||||||
Constant add(BasicType type, jvalue value);
|
Constant add(MachConstantNode* n, BasicType type, jvalue value);
|
||||||
Constant add(MachOper* oper);
|
Constant add(MachConstantNode* n, MachOper* oper);
|
||||||
Constant add(jfloat f) {
|
Constant add(MachConstantNode* n, jfloat f) {
|
||||||
jvalue value; value.f = f;
|
jvalue value; value.f = f;
|
||||||
return add(T_FLOAT, value);
|
return add(n, T_FLOAT, value);
|
||||||
}
|
}
|
||||||
Constant add(jdouble d) {
|
Constant add(MachConstantNode* n, jdouble d) {
|
||||||
jvalue value; value.d = d;
|
jvalue value; value.d = d;
|
||||||
return add(T_DOUBLE, value);
|
return add(n, T_DOUBLE, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Jump table
|
// Jump-table
|
||||||
Constant allocate_jump_table(MachConstantNode* n);
|
Constant add_jump_table(MachConstantNode* n);
|
||||||
void fill_jump_table(CodeBuffer& cb, MachConstantNode* n, GrowableArray<Label*> labels) const;
|
void fill_jump_table(CodeBuffer& cb, MachConstantNode* n, GrowableArray<Label*> labels) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -480,21 +480,20 @@ void MachTypeNode::dump_spec(outputStream *st) const {
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
int MachConstantNode::constant_offset() {
|
int MachConstantNode::constant_offset() {
|
||||||
int offset = _constant.offset();
|
|
||||||
// Bind the offset lazily.
|
// Bind the offset lazily.
|
||||||
if (offset == -1) {
|
if (_constant.offset() == -1) {
|
||||||
Compile::ConstantTable& constant_table = Compile::current()->constant_table();
|
Compile::ConstantTable& constant_table = Compile::current()->constant_table();
|
||||||
// If called from Compile::scratch_emit_size assume the worst-case
|
int offset = constant_table.find_offset(_constant);
|
||||||
// for load offsets: half the constant table size.
|
// If called from Compile::scratch_emit_size return the
|
||||||
// NOTE: Don't return or calculate the actual offset (which might
|
// pre-calculated offset.
|
||||||
// be zero) because that leads to problems with e.g. jumpXtnd on
|
// NOTE: If the AD file does some table base offset optimizations
|
||||||
// some architectures (cf. add-optimization in SPARC jumpXtnd).
|
// later the AD file needs to take care of this fact.
|
||||||
if (Compile::current()->in_scratch_emit_size())
|
if (Compile::current()->in_scratch_emit_size()) {
|
||||||
return constant_table.size() / 2;
|
return constant_table.calculate_table_base_offset() + offset;
|
||||||
offset = constant_table.table_base_offset() + constant_table.find_offset(_constant);
|
|
||||||
_constant.set_offset(offset);
|
|
||||||
}
|
}
|
||||||
return offset;
|
_constant.set_offset(constant_table.table_base_offset() + offset);
|
||||||
|
}
|
||||||
|
return _constant.offset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -371,10 +371,6 @@ public:
|
||||||
// registers? True for Intel but false for most RISCs
|
// registers? True for Intel but false for most RISCs
|
||||||
static const bool clone_shift_expressions;
|
static const bool clone_shift_expressions;
|
||||||
|
|
||||||
// Should constant table entries be accessed with loads using
|
|
||||||
// absolute addressing? True for x86 but false for most RISCs.
|
|
||||||
static const bool constant_table_absolute_addressing;
|
|
||||||
|
|
||||||
static bool narrow_oop_use_complex_address();
|
static bool narrow_oop_use_complex_address();
|
||||||
|
|
||||||
// Generate implicit null check for narrow oops if it can fold
|
// Generate implicit null check for narrow oops if it can fold
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue