diff --git a/src/cpu/sparc/vm/assembler_sparc.hpp b/src/cpu/sparc/vm/assembler_sparc.hpp index 14a6b623660938c9a7909f59e05e693aaa8705ed..44713a005db37f3894e7eec60e788c0c19f1d971 100644 --- a/src/cpu/sparc/vm/assembler_sparc.hpp +++ b/src/cpu/sparc/vm/assembler_sparc.hpp @@ -855,12 +855,6 @@ class Assembler : public AbstractAssembler { 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) { intptr_t d = intptr_t(b) - intptr_t(a); return is_simm(d, nbits + 2); @@ -1203,7 +1197,7 @@ public: if (!UseCBCond || cbcond_before()) return false; intptr_t x = intptr_t(target_distance(L)) - intptr_t(pc()); 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 diff --git a/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp b/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp index 15be6d30b64592d629756481fb7580f5a2948807..97e86fd789fc60833195296de4b5048853d52fcc 100644 --- a/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp +++ b/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp @@ -765,7 +765,7 @@ void LIR_Assembler::ic_call(LIR_OpJavaCall* op) { void LIR_Assembler::vtable_call(LIR_OpJavaCall* op) { add_debug_info_for_null_check_here(op->info()); __ 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); } else { // This will generate 2 instructions diff --git a/src/cpu/sparc/vm/methodHandles_sparc.cpp b/src/cpu/sparc/vm/methodHandles_sparc.cpp index 3b2b5ddd12668da292808821aa3275d6d3f58eea..d2a94d17edb33a353b146a4783c609041a36c250 100644 --- a/src/cpu/sparc/vm/methodHandles_sparc.cpp +++ b/src/cpu/sparc/vm/methodHandles_sparc.cpp @@ -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); extract_conversion_vminfo(_masm, L5_conversion, O5_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); __ stop("damaged ricochet frame: RETURN_VALUE_PLACEHOLDER not found"); __ BIND(L_ok_4); diff --git a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp index cb9e429e069419eb8ba2f9c7cc9af2c86bdf4b42..560ced690893b26945e04eab49698574c4ce8eb5 100644 --- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp +++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp @@ -767,7 +767,7 @@ void AdapterGenerator::gen_c2i_adapter( // 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 // temporary displacement. - if (! __ is_simm13(extraspace)) { + if (!Assembler::is_simm13(extraspace)) { __ set(extraspace, G3_scratch); __ sub(SP, G3_scratch, SP); } else { diff --git a/src/cpu/sparc/vm/sparc.ad b/src/cpu/sparc/vm/sparc.ad index 92f3c8659a90a67eeb16a4d0134da57f8e8b39f6..19a19a1f6575c88bbc74b248d9abac272f9794d6 100644 --- a/src/cpu/sparc/vm/sparc.ad +++ b/src/cpu/sparc/vm/sparc.ad @@ -566,7 +566,7 @@ int MachCallDynamicJavaNode::ret_addr_offset() { } else { klass_load_size = 1*BytesPerInstWord; } - if( Assembler::is_simm13(v_off) ) { + if (Assembler::is_simm13(v_off)) { return klass_load_size + (2*BytesPerInstWord + // ld_ptr, ld_ptr 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; +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 { Compile* C = ra_->C; Compile::ConstantTable& constant_table = C->constant_table(); MacroAssembler _masm(&cbuf); Register r = as_Register(ra_->get_encode(this)); - CodeSection* cs = __ code()->consts(); - int consts_size = cs->align_at_start(cs->size()); + CodeSection* consts_section = __ code()->consts(); + 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) { // 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 // are defined in src/share/vm/asm/codeBuffer.hpp. 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; // If the displacement from the current PC to the constant table // base fits into simm13 we set the constant table base to the // current PC. - if (__ is_simm13(-(consts_size + offset))) { - constant_table.set_table_base_offset(-(consts_size + offset)); + if (Assembler::is_simm13(table_base_offset)) { + constant_table.set_table_base_offset(table_base_offset); disp = 0; } else { - // If the offset of the top constant (last entry in the table) - // fits into simm13 we set the constant table base to the actual - // table base. - if (__ is_simm13(constant_table.top_offset())) { - constant_table.set_table_base_offset(0); - disp = consts_size + offset; - } else { - // Otherwise we set the constant table base in the middle of the - // constant table. - int half_consts_size = consts_size / 2; - 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; - } + // Otherwise we set the constant table base offset to the + // maximum negative displacement of load instructions to keep + // the disp as small as possible: + // + // |<------------- consts_size ----------->|<- insts_offset ->| + // |<--------- min_simm13 --------->|<-------- disp --------->| + // \ table base + table_base_offset = Assembler::min_simm13(); + constant_table.set_table_base_offset(table_base_offset); + disp = (consts_size + insts_offset) + table_base_offset; } __ rdpc(r); @@ -1072,8 +1093,7 @@ void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { } else { // Materialize the constant table base. - assert(constant_table.size() == consts_size, err_msg("must be: %d == %d", constant_table.size(), consts_size)); - address baseaddr = cs->start() + -(constant_table.table_base_offset()); + address baseaddr = consts_section->start() + -(constant_table.table_base_offset()); RelocationHolder rspec = internal_word_Relocation::spec(baseaddr); AddressLiteral base(baseaddr, rspec); __ set(base, r); @@ -1169,6 +1189,13 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { __ save(SP, G3, SP); } 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 { @@ -1843,7 +1870,7 @@ const bool Matcher::convL2FSupported(void) { bool Matcher::is_short_branch_offset(int rule, int br_size, int offset) { // The passed offset is relative to address of the branch. // 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) { @@ -2072,8 +2099,8 @@ encode %{ %} 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+4), "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"); 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, R_G0_enc, $reg$$reg ); @@ -2082,8 +2109,8 @@ encode %{ %} 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+4), "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"); guarantee($mem$$index == R_G0_enc, "double index?"); // Load long with 2 instructions 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 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); } else { // Generate 2 instructions @@ -3336,7 +3363,7 @@ operand immI() %{ // Integer Immediate: 8-bit operand immI8() %{ - predicate(Assembler::is_simm(n->get_int(), 8)); + predicate(Assembler::is_simm8(n->get_int())); match(ConI); op_cost(0); format %{ %} @@ -3365,7 +3392,7 @@ operand immI13m7() %{ // Integer Immediate: 16-bit operand immI16() %{ - predicate(Assembler::is_simm(n->get_int(), 16)); + predicate(Assembler::is_simm16(n->get_int())); match(ConI); op_cost(0); format %{ %} @@ -3393,7 +3420,7 @@ operand immU6() %{ // Integer Immediate: 11-bit operand immI11() %{ - predicate(Assembler::is_simm(n->get_int(),11)); + predicate(Assembler::is_simm11(n->get_int())); match(ConI); op_cost(0); format %{ %} @@ -3402,7 +3429,7 @@ operand immI11() %{ // Integer Immediate: 5-bit operand immI5() %{ - predicate(Assembler::is_simm(n->get_int(), 5)); + predicate(Assembler::is_simm5(n->get_int())); match(ConI); op_cost(0); format %{ %} @@ -3634,7 +3661,7 @@ operand immL0() %{ // Integer Immediate: 5-bit 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); op_cost(0); format %{ %} @@ -9251,13 +9278,16 @@ instruct jumpXtnd(iRegX switch_val, o7RegI table) %{ format %{ "ADD $constanttablebase, $constantoffset, O7\n\t" "LD [O7 + $switch_val], O7\n\t" - "JUMP O7" - %} + "JUMP O7" %} ins_encode %{ // Calculate table address into a register. Register table_reg; 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; } else { table_reg = O7; diff --git a/src/cpu/sparc/vm/vtableStubs_sparc.cpp b/src/cpu/sparc/vm/vtableStubs_sparc.cpp index 4e71250c24019be3070edd07dbaa5470bda3ac33..17ef1569811142df2fa31f8f82803641a29e0daf 100644 --- a/src/cpu/sparc/vm/vtableStubs_sparc.cpp +++ b/src/cpu/sparc/vm/vtableStubs_sparc.cpp @@ -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. * * 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 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); } else { __ set(v_off,G5); diff --git a/src/cpu/x86/vm/assembler_x86.hpp b/src/cpu/x86/vm/assembler_x86.hpp index d3553e7e14f8cea9e3681de59f51896dbe6c2cdf..d5c35dfdc06aa2ebd86d4bf0ffb41ba85e248353 100644 --- a/src/cpu/x86/vm/assembler_x86.hpp +++ b/src/cpu/x86/vm/assembler_x86.hpp @@ -693,17 +693,6 @@ private: static address locate_next_instruction(address inst); // 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;}); // Generic instructions diff --git a/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/src/cpu/x86/vm/stubGenerator_x86_64.cpp index 53d9431db07aa16cfea960f07376655339cf1ed3..04eaaffe975351520f4c418c1808cd0a0055345d 100644 --- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp +++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp @@ -1268,7 +1268,7 @@ class StubGenerator: public StubCodeGenerator { __ subptr(end, start); // number of bytes to copy 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); __ lea(scratch, cardtable); } else { diff --git a/src/cpu/x86/vm/x86_32.ad b/src/cpu/x86/vm/x86_32.ad index e00df3a07bb055c594122b129cc8300d61f5ff98..42160efd0c2c84f2e8f9e43e92e8be63d7f4a2cc 100644 --- a/src/cpu/x86/vm/x86_32.ad +++ b/src/cpu/x86/vm/x86_32.ad @@ -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; +int Compile::ConstantTable::calculate_table_base_offset() const { + return 0; // absolute addressing, no offset +} + void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { // Empty encoding } @@ -639,6 +642,12 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { } #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 { diff --git a/src/cpu/x86/vm/x86_64.ad b/src/cpu/x86/vm/x86_64.ad index 3e76c4051ad44a8a67725ca1d69fb17714dcbf4f..b112c1d68d63d88415ca7538ce1df108fdd9069d 100644 --- a/src/cpu/x86/vm/x86_64.ad +++ b/src/cpu/x86/vm/x86_64.ad @@ -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; +int Compile::ConstantTable::calculate_table_base_offset() const { + return 0; // absolute addressing, no offset +} + void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { // Empty encoding } @@ -977,6 +980,13 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const masm.bind(L); } #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 diff --git a/src/share/vm/adlc/adlparse.cpp b/src/share/vm/adlc/adlparse.cpp index a730a0a8f2fd34d7187e5c3449d63fd7d6a75e01..e9b8847525058dff78835c0d790de911f0547e32 100644 --- a/src/share/vm/adlc/adlparse.cpp +++ b/src/share/vm/adlc/adlparse.cpp @@ -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. * * 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"); // Parse everything in ( ) expression. - encoding->add_code("("); + encoding->add_code("(this, "); next_char(); // Skip '(' int parens_depth = 1; @@ -3130,7 +3130,8 @@ void ADLParser::constant_parse_expression(EncClass* encoding, char* ec_name) { } else if (_curchar == ')') { parens_depth--; - encoding->add_code(")"); + if (parens_depth > 0) + encoding->add_code(")"); next_char(); } else { @@ -3157,7 +3158,7 @@ void ADLParser::constant_parse_expression(EncClass* encoding, char* ec_name) { } // Finish code line. - encoding->add_code(";"); + encoding->add_code(");"); if (_AD._adlocation_debug) { encoding->add_code(end_line_marker()); diff --git a/src/share/vm/adlc/output_c.cpp b/src/share/vm/adlc/output_c.cpp index 493c31ee0648d3113f52092e901b9d1a9f298b04..3cc65df99f1e53df46c7481f58d9ce689735e4ea 100644 --- a/src/share/vm/adlc/output_c.cpp +++ b/src/share/vm/adlc/output_c.cpp @@ -2585,9 +2585,9 @@ void ArchDesc::defineEvalConstant(FILE* fp, InstructForm& inst) { // Output instruction's emit prototype 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()) { - 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, diff --git a/src/share/vm/asm/assembler.hpp b/src/share/vm/asm/assembler.hpp index 829e56184139924317f37a1190c07487cfcb34e3..8db7eef2ea5aa316cacc6a1e96e785ce604e7bd8 100644 --- a/src/share/vm/asm/assembler.hpp +++ b/src/share/vm/asm/assembler.hpp @@ -257,6 +257,29 @@ class AbstractAssembler : public ResourceObj { // ensure buf contains all code (call this before using/copying the code) 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 CodeBuffer* code() const; // _code_section->outer() CodeSection* code_section() const { return _code_section; } diff --git a/src/share/vm/opto/compile.cpp b/src/share/vm/opto/compile.cpp index 358be6286fc23464c87ca1f4915c5d6a22a5b8f6..44383b21056988b4868913b1c79f657d47b81a5a 100644 --- a/src/share/vm/opto/compile.cpp +++ b/src/share/vm/opto/compile.cpp @@ -3052,24 +3052,13 @@ bool Compile::Constant::operator==(const Constant& other) { 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) { switch (t) { case T_LONG: return sizeof(jlong ); case T_FLOAT: return sizeof(jfloat ); case T_DOUBLE: return sizeof(jdouble); // 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_ADDRESS: case T_OBJECT: return sizeof(jobject); @@ -3079,87 +3068,92 @@ static int type_to_size_in_bytes(BasicType t) { return -1; } +int Compile::ConstantTable::qsort_comparator(Constant* a, Constant* b) { + // sort descending + if (a->freq() > b->freq()) return -1; + if (a->freq() < b->freq()) return 1; + return 0; +} + void Compile::ConstantTable::calculate_offsets_and_size() { - int size = 0; - for (int t = 0; type_order[t] != T_ILLEGAL; t++) { - BasicType type = type_order[t]; + // First, sort the array by frequencies. + _constants.sort(qsort_comparator); - for (int i = 0; i < _constants.length(); i++) { - Constant con = _constants.at(i); - if (con.type() != type) continue; // Skip other types. +#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++) { + Constant con = _constants.at(i); + if (con.type() == T_VOID) + found_void = true; // jump-tables + else + assert(!found_void, "wrong sorting"); + } +#endif - // Align size for type. - int typesize = type_to_size_in_bytes(con.type()); - size = align_size_up(size, typesize); + int offset = 0; + for (int i = 0; i < _constants.length(); i++) { + Constant* con = _constants.adr_at(i); - // Set offset. - con.set_offset(size); - _constants.at_put(i, con); + // Align offset for type. + int typesize = type_to_size_in_bytes(con->type()); + offset = align_size_up(offset, typesize); + con->set_offset(offset); // set constant's offset - // Add type size. - size = size + typesize; + if (con->type() == T_VOID) { + 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 // CodeBuffer::align_at_start). assert(_size == -1, "already set?"); - _size = align_size_up(size, 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); - } - } + _size = align_size_up(offset, CodeEntryAlignment); } void Compile::ConstantTable::emit(CodeBuffer& 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++) { - Constant con = _constants.at(i); - if (con.type() != type) continue; // Skip other types. - - address constant_addr; - switch (con.type()) { - case T_LONG: constant_addr = _masm.long_constant( con.get_jlong() ); break; - case T_FLOAT: constant_addr = _masm.float_constant( con.get_jfloat() ); break; - case T_DOUBLE: constant_addr = _masm.double_constant(con.get_jdouble()); break; - case T_OBJECT: { - jobject obj = con.get_jobject(); - int oop_index = _masm.oop_recorder()->find_index(obj); - constant_addr = _masm.address_constant((address) obj, oop_Relocation::spec(oop_index)); - break; - } - case T_ADDRESS: { - address addr = (address) con.get_jobject(); - constant_addr = _masm.address_constant(addr); - break; - } - // We use T_VOID as marker for jump-table entries (labels) which - // need an interal word relocation. - case T_VOID: { - // Write a dummy word. The real value is filled in later - // in fill_jump_table_in_constant_table. - address addr = (address) con.get_jobject(); - constant_addr = _masm.address_constant(addr); - break; - } - default: ShouldNotReachHere(); + for (int i = 0; i < _constants.length(); i++) { + Constant con = _constants.at(i); + address constant_addr; + switch (con.type()) { + case T_LONG: constant_addr = _masm.long_constant( con.get_jlong() ); break; + case T_FLOAT: constant_addr = _masm.float_constant( con.get_jfloat() ); break; + case T_DOUBLE: constant_addr = _masm.double_constant(con.get_jdouble()); break; + case T_OBJECT: { + jobject obj = con.get_jobject(); + int oop_index = _masm.oop_recorder()->find_index(obj); + constant_addr = _masm.address_constant((address) obj, oop_Relocation::spec(oop_index)); + break; + } + case T_ADDRESS: { + address addr = (address) con.get_jobject(); + constant_addr = _masm.address_constant(addr); + break; + } + // We use T_VOID as marker for jump-table entries (labels) which + // need an internal word relocation. + case T_VOID: { + MachConstantNode* n = (MachConstantNode*) con.get_jobject(); + // Fill the jump-table with a dummy word. The real value is + // filled in later in fill_jump_table. + 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"); } - assert(constant_addr != NULL, "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())); + break; + } + default: ShouldNotReachHere(); } + 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())); } } @@ -3175,19 +3169,21 @@ void Compile::ConstantTable::add(Constant& con) { if (con.can_be_reused()) { int idx = _constants.find(con); 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; } } (void) _constants.append(con); } -Compile::Constant Compile::ConstantTable::add(BasicType type, jvalue value) { - Constant con(type, value); +Compile::Constant Compile::ConstantTable::add(MachConstantNode* n, BasicType type, jvalue value) { + Block* b = Compile::current()->cfg()->_bbs[n->_idx]; + Constant con(type, value, b->_freq); add(con); return con; } -Compile::Constant Compile::ConstantTable::add(MachOper* oper) { +Compile::Constant Compile::ConstantTable::add(MachConstantNode* n, MachOper* oper) { jvalue value; BasicType type = oper->type()->basic_type(); switch (type) { @@ -3198,20 +3194,18 @@ Compile::Constant Compile::ConstantTable::add(MachOper* oper) { case T_ADDRESS: value.l = (jobject) oper->constant(); break; 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; // We can use the node pointer here to identify the right jump-table // as this method is called from Compile::Fill_buffer right before // the MachNodes are emitted and the jump-table is filled (means the // MachNode pointers do not change anymore). value.l = (jobject) n; - Constant con(T_VOID, value, false); // Labels of a jump-table cannot be reused. - for (uint i = 0; i < n->outcnt(); i++) { - add(con); - } + Constant con(T_VOID, value, next_jump_table_freq(), false); // Labels of a jump-table cannot be reused. + add(con); return con; } @@ -3230,9 +3224,9 @@ void Compile::ConstantTable::fill_jump_table(CodeBuffer& cb, MachConstantNode* n MacroAssembler _masm(&cb); 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]; - 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); cb.consts()->relocate((address) constant_addr, relocInfo::internal_word_type); } diff --git a/src/share/vm/opto/compile.hpp b/src/share/vm/opto/compile.hpp index 82e33a93ace1f5d015aa1b9242606cdc34a42f05..8254aabca103c08a65d90f64cd5ac411b5586508 100644 --- a/src/share/vm/opto/compile.hpp +++ b/src/share/vm/opto/compile.hpp @@ -150,14 +150,16 @@ class Compile : public Phase { BasicType _type; jvalue _value; 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. public: - Constant() : _type(T_ILLEGAL), _offset(-1), _can_be_reused(true) { _value.l = 0; } - Constant(BasicType type, jvalue value, bool can_be_reused = true) : + Constant() : _type(T_ILLEGAL), _offset(-1), _freq(0.0f), _can_be_reused(true) { _value.l = 0; } + Constant(BasicType type, jvalue value, float freq = 0.0f, bool can_be_reused = true) : _type(type), _value(value), _offset(-1), + _freq(freq), _can_be_reused(can_be_reused) {} @@ -173,6 +175,9 @@ class Compile : public Phase { int offset() const { return _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; } }; @@ -182,41 +187,51 @@ class Compile : public Phase { GrowableArray _constants; // Constants of this table. 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 _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: ConstantTable() : _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 table_base_offset() const { assert(_table_base_offset != -1, "table base offset not yet set"); return _table_base_offset; } + int calculate_table_base_offset() const; // AD specific + 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); // 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(); int find_offset(Constant& con) const; void add(Constant& con); - Constant add(BasicType type, jvalue value); - Constant add(MachOper* oper); - Constant add(jfloat f) { + Constant add(MachConstantNode* n, BasicType type, jvalue value); + Constant add(MachConstantNode* n, MachOper* oper); + Constant add(MachConstantNode* n, jfloat 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; - return add(T_DOUBLE, value); + return add(n, T_DOUBLE, value); } - // Jump table - Constant allocate_jump_table(MachConstantNode* n); - void fill_jump_table(CodeBuffer& cb, MachConstantNode* n, GrowableArray labels) const; + // Jump-table + Constant add_jump_table(MachConstantNode* n); + void fill_jump_table(CodeBuffer& cb, MachConstantNode* n, GrowableArray labels) const; }; private: diff --git a/src/share/vm/opto/machnode.cpp b/src/share/vm/opto/machnode.cpp index 95ee4bf82cf2ec93df7875d1eb48a5cb7b3b4b95..7bc5877854c8b7672c57b15caf12c34175c1e838 100644 --- a/src/share/vm/opto/machnode.cpp +++ b/src/share/vm/opto/machnode.cpp @@ -480,21 +480,20 @@ void MachTypeNode::dump_spec(outputStream *st) const { //============================================================================= int MachConstantNode::constant_offset() { - int offset = _constant.offset(); // Bind the offset lazily. - if (offset == -1) { + if (_constant.offset() == -1) { Compile::ConstantTable& constant_table = Compile::current()->constant_table(); - // If called from Compile::scratch_emit_size assume the worst-case - // for load offsets: half the constant table size. - // NOTE: Don't return or calculate the actual offset (which might - // be zero) because that leads to problems with e.g. jumpXtnd on - // some architectures (cf. add-optimization in SPARC jumpXtnd). - if (Compile::current()->in_scratch_emit_size()) - return constant_table.size() / 2; - offset = constant_table.table_base_offset() + constant_table.find_offset(_constant); - _constant.set_offset(offset); + int offset = constant_table.find_offset(_constant); + // If called from Compile::scratch_emit_size return the + // pre-calculated offset. + // NOTE: If the AD file does some table base offset optimizations + // later the AD file needs to take care of this fact. + if (Compile::current()->in_scratch_emit_size()) { + return constant_table.calculate_table_base_offset() + offset; + } + _constant.set_offset(constant_table.table_base_offset() + offset); } - return offset; + return _constant.offset(); } diff --git a/src/share/vm/opto/matcher.hpp b/src/share/vm/opto/matcher.hpp index 3d1a2dc5893b9ad532e73343e60dfc660086729a..fd7b0cb4c18b38fc803facddea67372b27c8ce73 100644 --- a/src/share/vm/opto/matcher.hpp +++ b/src/share/vm/opto/matcher.hpp @@ -371,10 +371,6 @@ public: // registers? True for Intel but false for most RISCs 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(); // Generate implicit null check for narrow oops if it can fold