--- old/src/cpu/sparc/vm/assembler_sparc.cpp 2010-11-12 05:55:58.614856794 -0800 +++ new/src/cpu/sparc/vm/assembler_sparc.cpp 2010-11-12 05:55:58.219777281 -0800 @@ -1427,6 +1427,45 @@ } } +int MacroAssembler::size_of_set64(jlong value) { + v9_dep(); + + int hi = (int)(value >> 32); + int lo = (int)(value & ~0); + int count = 0; + + // (Matcher::isSimpleConstant64 knows about the following optimizations.) + if (Assembler::is_simm13(lo) && value == lo) { + count++; + } else if (hi == 0) { + count++; + if (low10(lo) != 0) + count++; + } + else if (hi == -1) { + count += 2; + } + else if (lo == 0) { + if (Assembler::is_simm13(hi)) { + count++; + } else { + count++; + if (low10(hi) != 0) + count++; + } + count++; + } + else { + count += 2; + if (low10(hi) != 0) + count++; + if (low10(lo) != 0) + count++; + count += 2; + } + return count; +} + // compute size in bytes of sparc frame, given // number of extraWords int MacroAssembler::total_frame_size_in_bytes(int extraWords) { --- old/src/cpu/sparc/vm/assembler_sparc.hpp 2010-11-12 05:56:01.060715791 -0800 +++ new/src/cpu/sparc/vm/assembler_sparc.hpp 2010-11-12 05:56:00.659818915 -0800 @@ -1618,6 +1618,10 @@ void sub( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sub_op3 ) | rs1(s1) | rs2(s2) ); } void sub( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sub_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } + + // Note: offset is added to s2. + inline void sub(Register s1, RegisterOrConstant s2, Register d, int offset = 0); + void subcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sub_op3 | cc_bit_op3 ) | rs1(s1) | rs2(s2) ); } void subcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sub_op3 | cc_bit_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } void subc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(subc_op3 ) | rs1(s1) | rs2(s2) ); } @@ -1891,6 +1895,9 @@ void patchable_set(intptr_t value, Register d); void set64(jlong value, Register d, Register tmp); + // Compute size of set64. + static int size_of_set64(jlong value); + // sign-extend 32 to 64 inline void signx( Register s, Register d ) { sra( s, G0, d); } inline void signx( Register d ) { sra( d, G0, d); } --- old/src/cpu/sparc/vm/assembler_sparc.inline.hpp 2010-11-12 05:56:03.352694253 -0800 +++ new/src/cpu/sparc/vm/assembler_sparc.inline.hpp 2010-11-12 05:56:02.961018570 -0800 @@ -320,6 +320,11 @@ inline void Assembler::stdcq( int crd, Register s1, Register s2) { v8_only(); emit_long( op(ldst_op) | fcn(crd) | op3(stdcq_op3) | rs1(s1) | rs2(s2) ); } inline void Assembler::stdcq( int crd, Register s1, int simm13a) { v8_only(); emit_data( op(ldst_op) | fcn(crd) | op3(stdcq_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } +inline void Assembler::sub(Register s1, RegisterOrConstant s2, Register d, int offset) { + if (s2.is_register()) sub(s1, s2.as_register(), d); + else { sub(s1, s2.as_constant() + offset, d); offset = 0; } + if (offset != 0) sub(d, offset, d); +} // pp 231 --- old/src/cpu/sparc/vm/sparc.ad 2010-11-12 05:56:05.918737377 -0800 +++ new/src/cpu/sparc/vm/sparc.ad 2010-11-12 05:56:05.479102271 -0800 @@ -667,6 +667,20 @@ return offset; } +static inline jdouble replicate_immI(int con, int count, int width) { + // Load a constant replicated "count" times with width "width" + int bit_width = width * 8; + jlong elt_val = con; + elt_val &= (((jlong) 1) << bit_width) - 1; // mask off sign bits + jlong val = elt_val; + for (int i = 0; i < count - 1; i++) { + val <<= bit_width; + val |= elt_val; + } + jdouble dval = *((jdouble*) &val); // coerce to double type + return dval; +} + // Standard Sparc opcode form2 field breakdown static inline void emit2_19(CodeBuffer &cbuf, int f30, int f29, int f25, int f22, int f20, int f19, int f0 ) { f0 &= (1<<19)-1; // Mask displacement to 19 bits @@ -1008,6 +1022,84 @@ //============================================================================= +const RegMask& MachConstantBaseNode::_out_RegMask = PTR_REG_mask; + +void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { + emit_constant_table(cbuf); + MacroAssembler _masm(&cbuf); + + Register r = as_Register(ra_->get_encode(this)); + CodeSection* cs = __ code()->consts(); + int consts_size = cs->align_at_start(cs->size()); + + if (UseRDPCForConstantTableBase) { + int offset = __ 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))) { + set_table_base_offset(-(consts_size + 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(top_constant_offset())) { + 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"); + set_table_base_offset(-half_consts_size); // table base offset gets added to the load displacement. + disp = half_consts_size + offset; + } + } + + __ get_pc(r); + + if (disp != 0) { + assert(r != O7, "need temporary"); + __ sub(r, __ ensure_simm13_or_reg(disp, O7), r); + } + } + else { + // Materialize the constant table base. + // 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"); + set_table_base_offset(-half_consts_size); // table base offset gets added to the load displacement. + + address baseaddr = cs->start() + half_consts_size; + RelocationHolder rspec = internal_word_Relocation::spec(baseaddr); + AddressLiteral base(baseaddr, rspec); + __ set(base, r); + } +} + +uint MachConstantBaseNode::size(PhaseRegAlloc*) const { + Unimplemented(); + return 0; +} + +#ifndef PRODUCT +void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const { + char reg[128]; + ra_->dump_register(this, reg); + if (UseRDPCForConstantTableBase) { + st->print("RDPC %s\t! constant table base", reg); + } else { + st->print("SET &constanttable,%s\t! constant table base", reg); + } +} +#endif + + +//============================================================================= #ifndef PRODUCT void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { @@ -2247,25 +2339,6 @@ __ delayed()->nop(); %} - enc_class jump_enc( iRegX switch_val, o7RegI table) %{ - MacroAssembler _masm(&cbuf); - - Register switch_reg = as_Register($switch_val$$reg); - Register table_reg = O7; - - address table_base = __ address_table_constant(_index2label); - RelocationHolder rspec = internal_word_Relocation::spec(table_base); - - // Move table address into a register. - __ set(table_base, table_reg, rspec); - - // Jump to base address + switch value - __ ld_ptr(table_reg, switch_reg, table_reg); - __ jmp(table_reg, G0); - __ delayed()->nop(); - - %} - enc_class enc_ba( Label labl ) %{ MacroAssembler _masm(&cbuf); Label &L = *($labl$$label); @@ -2384,20 +2457,6 @@ cbuf.insts()->emit_int32(op); %} - // Utility encoding for loading a 64 bit Pointer into a register - // The 64 bit pointer is stored in the generated code stream - enc_class SetPtr( immP src, iRegP rd ) %{ - Register dest = reg_to_register_object($rd$$reg); - MacroAssembler _masm(&cbuf); - // [RGV] This next line should be generated from ADLC - if ( _opnds[1]->constant_is_oop() ) { - intptr_t val = $src$$constant; - __ set_oop_constant((jobject)val, dest); - } else { // non-oop pointers, e.g. card mark base, heap top - __ set($src$$constant, dest); - } - %} - enc_class Set13( immI13 src, iRegI rd ) %{ emit3_simm13( cbuf, Assembler::arith_op, $rd$$reg, Assembler::or_op3, 0, $src$$constant ); %} @@ -2411,10 +2470,6 @@ __ set($src$$constant, reg_to_register_object($rd$$reg)); %} - enc_class SetNull( iRegI rd ) %{ - emit3_simm13( cbuf, Assembler::arith_op, $rd$$reg, Assembler::or_op3, 0, 0 ); - %} - enc_class call_epilog %{ if( VerifyStackAtCalls ) { MacroAssembler _masm(&cbuf); @@ -2778,35 +2833,6 @@ __ float_cmp( $primary, -1, Fsrc1, Fsrc2, Rdst); %} - enc_class LdImmL (immL src, iRegL dst, o7RegL tmp) %{ // Load Immediate - MacroAssembler _masm(&cbuf); - Register dest = reg_to_register_object($dst$$reg); - Register temp = reg_to_register_object($tmp$$reg); - __ set64( $src$$constant, dest, temp ); - %} - - enc_class LdReplImmI(immI src, regD dst, o7RegP tmp, int count, int width) %{ - // Load a constant replicated "count" times with width "width" - int bit_width = $width$$constant * 8; - jlong elt_val = $src$$constant; - elt_val &= (((jlong)1) << bit_width) - 1; // mask off sign bits - jlong val = elt_val; - for (int i = 0; i < $count$$constant - 1; i++) { - val <<= bit_width; - val |= elt_val; - } - jdouble dval = *(jdouble*)&val; // coerce to double type - MacroAssembler _masm(&cbuf); - address double_address = __ double_constant(dval); - RelocationHolder rspec = internal_word_Relocation::spec(double_address); - AddressLiteral addrlit(double_address, rspec); - - __ sethi(addrlit, $tmp$$Register); - // XXX This is a quick fix for 6833573. - //__ ldf(FloatRegisterImpl::D, $tmp$$Register, addrlit.low10(), $dst$$FloatRegister, rspec); - __ ldf(FloatRegisterImpl::D, $tmp$$Register, addrlit.low10(), as_DoubleFloatRegister($dst$$reg), rspec); - %} - // Compiler ensures base is doubleword aligned and cnt is count of doublewords enc_class enc_Clear_Array(iRegX cnt, iRegP base, iRegX temp) %{ MacroAssembler _masm(&cbuf); @@ -3616,6 +3642,26 @@ interface(CONST_INTER); %} +// Long Immediate: cheap (materialize in <= 3 instructions) +operand immL_cheap() %{ + predicate(MacroAssembler::size_of_set64(n->get_long()) <= 3); + match(ConL); + op_cost(0); + + format %{ %} + interface(CONST_INTER); +%} + +// Long Immediate: expensive (materialize in > 3 instructions) +operand immL_expensive() %{ + predicate(MacroAssembler::size_of_set64(n->get_long()) > 3); + match(ConL); + op_cost(0); + + format %{ %} + interface(CONST_INTER); +%} + // Double Immediate operand immD() %{ match(ConD); @@ -5981,17 +6027,29 @@ ins_pipe(ialu_imm); %} -instruct loadConP(iRegP dst, immP src) %{ - match(Set dst src); +instruct loadConP(iRegP dst, immP con) %{ + match(Set dst con); +#ifndef _LP64 ins_cost(DEFAULT_COST * 3/2); - format %{ "SET $src,$dst\t!ptr" %} - // This rule does not use "expand" unlike loadConI because then - // the result type is not known to be an Oop. An ADLC - // enhancement will be needed to make that work - not worth it! - - ins_encode( SetPtr( src, dst ) ); + format %{ "SET $con,$dst\t!ptr" %} + ins_encode %{ + // [RGV] This next line should be generated from ADLC + if (_opnds[1]->constant_is_oop()) { + intptr_t val = $con$$constant; + __ set_oop_constant((jobject) val, $dst$$Register); + } else { // non-oop pointers, e.g. card mark base, heap top + __ set($con$$constant, $dst$$Register); + } + %} +#else + ins_cost(MEMORY_REF_COST); + size(4); + format %{ "LD [$constanttablebase + $constantoffset],$dst\t! load from constant table: ptr=$con" %} + ins_encode %{ + __ ld_ptr($constanttablebase, $constantoffset($con), $dst$$Register); + %} +#endif ins_pipe(loadConP); - %} instruct loadConP0(iRegP dst, immP0 src) %{ @@ -5999,7 +6057,9 @@ size(4); format %{ "CLR $dst\t!ptr" %} - ins_encode( SetNull( dst ) ); + ins_encode %{ + __ clr($dst$$Register); + %} ins_pipe(ialu_imm); %} @@ -6019,7 +6079,9 @@ size(4); format %{ "CLR $dst\t! compressed NULL ptr" %} - ins_encode( SetNull( dst ) ); + ins_encode %{ + __ clr($dst$$Register); + %} ins_pipe(ialu_imm); %} @@ -6034,13 +6096,26 @@ ins_pipe(ialu_hi_lo_reg); %} -instruct loadConL(iRegL dst, immL src, o7RegL tmp) %{ - // %%% maybe this should work like loadConD - match(Set dst src); +// Materialize long value (predicated by immL_cheap). +instruct loadConL_set64(iRegL dst, immL_cheap con, o7RegL tmp) %{ + match(Set dst con); effect(KILL tmp); - ins_cost(DEFAULT_COST * 4); - format %{ "SET64 $src,$dst KILL $tmp\t! long" %} - ins_encode( LdImmL(src, dst, tmp) ); + ins_cost(DEFAULT_COST * 3); + format %{ "SET64 $con,$dst KILL $tmp\t! long" %} + ins_encode %{ + __ set64($con$$constant, $dst$$Register, $tmp$$Register); + %} + ins_pipe(loadConL); +%} + +// Load long value from constant table (predicated by immL_expensive). +instruct loadConL_ldx(iRegL dst, immL_expensive con) %{ + match(Set dst con); + ins_cost(MEMORY_REF_COST); + format %{ "LDX [$constanttablebase + $constantoffset],$dst\t! load from constant table: long=$con" %} + ins_encode %{ + __ ldx($constanttablebase, $constantoffset($con), $dst$$Register); + %} ins_pipe(loadConL); %} @@ -6063,50 +6138,24 @@ ins_pipe(ialu_imm); %} -instruct loadConF(regF dst, immF src, o7RegP tmp) %{ - match(Set dst src); - effect(KILL tmp); - -#ifdef _LP64 - size(8*4); -#else - size(2*4); -#endif - - format %{ "SETHI hi(&$src),$tmp\t!get float $src from table\n\t" - "LDF [$tmp+lo(&$src)],$dst" %} +instruct loadConF(regF dst, immF con) %{ + match(Set dst con); + size(4); + format %{ "LDF [$constanttablebase + $constantoffset],$dst\t! load from constant table: float=$con" %} ins_encode %{ - address float_address = __ float_constant($src$$constant); - RelocationHolder rspec = internal_word_Relocation::spec(float_address); - AddressLiteral addrlit(float_address, rspec); - - __ sethi(addrlit, $tmp$$Register); - __ ldf(FloatRegisterImpl::S, $tmp$$Register, addrlit.low10(), $dst$$FloatRegister, rspec); + __ ldf(FloatRegisterImpl::S, $constanttablebase, $constantoffset($con), $dst$$FloatRegister); %} ins_pipe(loadConFD); %} -instruct loadConD(regD dst, immD src, o7RegP tmp) %{ - match(Set dst src); - effect(KILL tmp); - -#ifdef _LP64 - size(8*4); -#else - size(2*4); -#endif - - format %{ "SETHI hi(&$src),$tmp\t!get double $src from table\n\t" - "LDDF [$tmp+lo(&$src)],$dst" %} +instruct loadConD(regD dst, immD con) %{ + match(Set dst con); + size(4); + format %{ "LDDF [$constanttablebase + $constantoffset],$dst\t! load from constant table: double=$con" %} ins_encode %{ - address double_address = __ double_constant($src$$constant); - RelocationHolder rspec = internal_word_Relocation::spec(double_address); - AddressLiteral addrlit(double_address, rspec); - - __ sethi(addrlit, $tmp$$Register); // XXX This is a quick fix for 6833573. - //__ ldf(FloatRegisterImpl::D, $tmp$$Register, addrlit.low10(), $dst$$FloatRegister, rspec); - __ ldf(FloatRegisterImpl::D, $tmp$$Register, addrlit.low10(), as_DoubleFloatRegister($dst$$reg), rspec); + //__ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset($con), $dst$$FloatRegister); + __ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset($con), as_DoubleFloatRegister($dst$$reg)); %} ins_pipe(loadConFD); %} @@ -8558,16 +8607,15 @@ %} // Replicate scalar constant to packed byte values in Double register -instruct Repl8B_immI(regD dst, immI13 src, o7RegP tmp) %{ - match(Set dst (Replicate8B src)); -#ifdef _LP64 - size(36); -#else - size(8); -#endif - format %{ "SETHI hi(&Repl8($src)),$tmp\t!get Repl8B($src) from table\n\t" - "LDDF [$tmp+lo(&Repl8($src))],$dst" %} - ins_encode( LdReplImmI(src, dst, tmp, (8), (1)) ); +instruct Repl8B_immI(regD dst, immI13 con) %{ + match(Set dst (Replicate8B con)); + size(4); + format %{ "LDDF [$constanttablebase + $constantoffset],$dst\t! load from constant table: Repl8B($con)" %} + ins_encode %{ + // XXX This is a quick fix for 6833573. + //__ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset(replicate_immI($con$$constant, 8, 1)), $dst$$FloatRegister); + __ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset(replicate_immI($con$$constant, 8, 1)), as_DoubleFloatRegister($dst$$reg)); + %} ins_pipe(loadConFD); %} @@ -8594,16 +8642,15 @@ %} // Replicate scalar constant to packed char values in Double register -instruct Repl4C_immI(regD dst, immI src, o7RegP tmp) %{ - match(Set dst (Replicate4C src)); -#ifdef _LP64 - size(36); -#else - size(8); -#endif - format %{ "SETHI hi(&Repl4($src)),$tmp\t!get Repl4C($src) from table\n\t" - "LDDF [$tmp+lo(&Repl4($src))],$dst" %} - ins_encode( LdReplImmI(src, dst, tmp, (4), (2)) ); +instruct Repl4C_immI(regD dst, immI con) %{ + match(Set dst (Replicate4C con)); + size(4); + format %{ "LDDF [$constanttablebase + $constantoffset],$dst\t! load from constant table: Repl4C($con)" %} + ins_encode %{ + // XXX This is a quick fix for 6833573. + //__ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset(replicate_immI($con$$constant, 4, 2)), $dst$$FloatRegister); + __ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset(replicate_immI($con$$constant, 4, 2)), as_DoubleFloatRegister($dst$$reg)); + %} ins_pipe(loadConFD); %} @@ -8630,16 +8677,15 @@ %} // Replicate scalar constant to packed short values in Double register -instruct Repl4S_immI(regD dst, immI src, o7RegP tmp) %{ - match(Set dst (Replicate4S src)); -#ifdef _LP64 - size(36); -#else - size(8); -#endif - format %{ "SETHI hi(&Repl4($src)),$tmp\t!get Repl4S($src) from table\n\t" - "LDDF [$tmp+lo(&Repl4($src))],$dst" %} - ins_encode( LdReplImmI(src, dst, tmp, (4), (2)) ); +instruct Repl4S_immI(regD dst, immI con) %{ + match(Set dst (Replicate4S con)); + size(4); + format %{ "LDDF [$constanttablebase + $constantoffset],$dst\t! load from constant table: Repl4S($con)" %} + ins_encode %{ + // XXX This is a quick fix for 6833573. + //__ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset(replicate_immI($con$$constant, 4, 2)), $dst$$FloatRegister); + __ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset(replicate_immI($con$$constant, 4, 2)), as_DoubleFloatRegister($dst$$reg)); + %} ins_pipe(loadConFD); %} @@ -8664,16 +8710,15 @@ %} // Replicate scalar zero constant to packed int values in Double register -instruct Repl2I_immI(regD dst, immI src, o7RegP tmp) %{ - match(Set dst (Replicate2I src)); -#ifdef _LP64 - size(36); -#else - size(8); -#endif - format %{ "SETHI hi(&Repl2($src)),$tmp\t!get Repl2I($src) from table\n\t" - "LDDF [$tmp+lo(&Repl2($src))],$dst" %} - ins_encode( LdReplImmI(src, dst, tmp, (2), (4)) ); +instruct Repl2I_immI(regD dst, immI con) %{ + match(Set dst (Replicate2I con)); + size(4); + format %{ "LDDF [$constanttablebase + $constantoffset],$dst\t! load from constant table: Repl2I($con)" %} + ins_encode %{ + // XXX This is a quick fix for 6833573. + //__ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset(replicate_immI($con$$constant, 2, 4)), $dst$$FloatRegister); + __ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset(replicate_immI($con$$constant, 2, 4)), as_DoubleFloatRegister($dst$$reg)); + %} ins_pipe(loadConFD); %} @@ -8929,12 +8974,26 @@ ins_cost(350); - format %{ "SETHI [hi(table_base)],O7\n\t" - "ADD O7, lo(table_base), O7\n\t" - "LD [O7+$switch_val], O7\n\t" + format %{ "ADD $constanttablebase, $constantoffset, O7\n\t" + "LD [O7 + $switch_val], O7\n\t" "JUMP O7" %} - ins_encode( jump_enc( switch_val, table) ); + ins_encode %{ + // Calculate table address into a register. + Register table_reg; + Register label_reg = O7; + if (constant_offset() == 0) { + table_reg = $constanttablebase; + } else { + table_reg = O7; + __ add($constanttablebase, $constantoffset, table_reg); + } + + // Jump to base address + switch value + __ ld_ptr(table_reg, $switch_val$$Register, label_reg); + __ jmp(label_reg, G0); + __ delayed()->nop(); + %} ins_pc_relative(1); ins_pipe(ialu_reg_reg); %} --- old/src/cpu/x86/vm/assembler_x86.cpp 2010-11-12 05:56:08.996339492 -0800 +++ new/src/cpu/x86/vm/assembler_x86.cpp 2010-11-12 05:56:08.555487777 -0800 @@ -2633,6 +2633,37 @@ emit_byte(0xC0 | encode); } +void Assembler::sqrtsd(XMMRegister dst, Address src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + InstructionMark im(this); + emit_byte(0xF2); + prefix(src, dst); + emit_byte(0x0F); + emit_byte(0x51); + emit_operand(dst, src); +} + +void Assembler::sqrtss(XMMRegister dst, XMMRegister src) { + // HMM Table D-1 says sse2 + // NOT_LP64(assert(VM_Version::supports_sse(), "")); + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + emit_byte(0xF3); + int encode = prefix_and_encode(dst->encoding(), src->encoding()); + emit_byte(0x0F); + emit_byte(0x51); + emit_byte(0xC0 | encode); +} + +void Assembler::sqrtss(XMMRegister dst, Address src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + InstructionMark im(this); + emit_byte(0xF3); + prefix(src, dst); + emit_byte(0x0F); + emit_byte(0x51); + emit_operand(dst, src); +} + void Assembler::stmxcsr( Address dst) { NOT_LP64(assert(VM_Version::supports_sse(), "")); InstructionMark im(this); @@ -4342,16 +4373,6 @@ emit_byte(0xE8 | encode); } -void Assembler::sqrtsd(XMMRegister dst, Address src) { - NOT_LP64(assert(VM_Version::supports_sse2(), "")); - InstructionMark im(this); - emit_byte(0xF2); - prefix(src, dst); - emit_byte(0x0F); - emit_byte(0x51); - emit_operand(dst, src); -} - void Assembler::subq(Address dst, int32_t imm32) { InstructionMark im(this); prefixq(dst); @@ -4913,10 +4934,6 @@ } -void MacroAssembler::movsd(XMMRegister dst, AddressLiteral src) { - movsd(dst, as_Address(src)); -} - void MacroAssembler::pop_callee_saved_registers() { pop(rcx); pop(rdx); --- old/src/cpu/x86/vm/assembler_x86.hpp 2010-11-12 05:56:11.667294270 -0800 +++ new/src/cpu/x86/vm/assembler_x86.hpp 2010-11-12 05:56:11.246681726 -0800 @@ -1349,6 +1349,10 @@ void sqrtsd(XMMRegister dst, Address src); void sqrtsd(XMMRegister dst, XMMRegister src); + // Compute Square Root of Scalar Single-Precision Floating-Point Value + void sqrtss(XMMRegister dst, Address src); + void sqrtss(XMMRegister dst, XMMRegister src); + void std() { emit_byte(0xfd); } void stmxcsr( Address dst ); @@ -2121,6 +2125,9 @@ void comisd(XMMRegister dst, Address src) { Assembler::comisd(dst, src); } void comisd(XMMRegister dst, AddressLiteral src); + void fadd_s(Address src) { Assembler::fadd_s(src); } + void fadd_s(AddressLiteral src) { Assembler::fadd_s(as_Address(src)); } + void fldcw(Address src) { Assembler::fldcw(src); } void fldcw(AddressLiteral src); @@ -2134,6 +2141,9 @@ void fld_x(Address src) { Assembler::fld_x(src); } void fld_x(AddressLiteral src); + void fmul_s(Address src) { Assembler::fmul_s(src); } + void fmul_s(AddressLiteral src) { Assembler::fmul_s(as_Address(src)); } + void ldmxcsr(Address src) { Assembler::ldmxcsr(src); } void ldmxcsr(AddressLiteral src); @@ -2150,10 +2160,50 @@ public: - void movsd(XMMRegister dst, XMMRegister src) { Assembler::movsd(dst, src); } - void movsd(Address dst, XMMRegister src) { Assembler::movsd(dst, src); } - void movsd(XMMRegister dst, Address src) { Assembler::movsd(dst, src); } - void movsd(XMMRegister dst, AddressLiteral src); + void addsd(XMMRegister dst, XMMRegister src) { Assembler::addsd(dst, src); } + void addsd(XMMRegister dst, Address src) { Assembler::addsd(dst, src); } + void addsd(XMMRegister dst, AddressLiteral src) { Assembler::addsd(dst, as_Address(src)); } + + void addss(XMMRegister dst, XMMRegister src) { Assembler::addss(dst, src); } + void addss(XMMRegister dst, Address src) { Assembler::addss(dst, src); } + void addss(XMMRegister dst, AddressLiteral src) { Assembler::addss(dst, as_Address(src)); } + + void divsd(XMMRegister dst, XMMRegister src) { Assembler::divsd(dst, src); } + void divsd(XMMRegister dst, Address src) { Assembler::divsd(dst, src); } + void divsd(XMMRegister dst, AddressLiteral src) { Assembler::divsd(dst, as_Address(src)); } + + void divss(XMMRegister dst, XMMRegister src) { Assembler::divss(dst, src); } + void divss(XMMRegister dst, Address src) { Assembler::divss(dst, src); } + void divss(XMMRegister dst, AddressLiteral src) { Assembler::divss(dst, as_Address(src)); } + + void movsd(XMMRegister dst, XMMRegister src) { Assembler::movsd(dst, src); } + void movsd(Address dst, XMMRegister src) { Assembler::movsd(dst, src); } + void movsd(XMMRegister dst, Address src) { Assembler::movsd(dst, src); } + void movsd(XMMRegister dst, AddressLiteral src) { Assembler::movsd(dst, as_Address(src)); } + + void mulsd(XMMRegister dst, XMMRegister src) { Assembler::mulsd(dst, src); } + void mulsd(XMMRegister dst, Address src) { Assembler::mulsd(dst, src); } + void mulsd(XMMRegister dst, AddressLiteral src) { Assembler::mulsd(dst, as_Address(src)); } + + void mulss(XMMRegister dst, XMMRegister src) { Assembler::mulss(dst, src); } + void mulss(XMMRegister dst, Address src) { Assembler::mulss(dst, src); } + void mulss(XMMRegister dst, AddressLiteral src) { Assembler::mulss(dst, as_Address(src)); } + + void sqrtsd(XMMRegister dst, XMMRegister src) { Assembler::sqrtsd(dst, src); } + void sqrtsd(XMMRegister dst, Address src) { Assembler::sqrtsd(dst, src); } + void sqrtsd(XMMRegister dst, AddressLiteral src) { Assembler::sqrtsd(dst, as_Address(src)); } + + void sqrtss(XMMRegister dst, XMMRegister src) { Assembler::sqrtss(dst, src); } + void sqrtss(XMMRegister dst, Address src) { Assembler::sqrtss(dst, src); } + void sqrtss(XMMRegister dst, AddressLiteral src) { Assembler::sqrtss(dst, as_Address(src)); } + + void subsd(XMMRegister dst, XMMRegister src) { Assembler::subsd(dst, src); } + void subsd(XMMRegister dst, Address src) { Assembler::subsd(dst, src); } + void subsd(XMMRegister dst, AddressLiteral src) { Assembler::subsd(dst, as_Address(src)); } + + void subss(XMMRegister dst, XMMRegister src) { Assembler::subss(dst, src); } + void subss(XMMRegister dst, Address src) { Assembler::subss(dst, src); } + void subss(XMMRegister dst, AddressLiteral src) { Assembler::subss(dst, as_Address(src)); } void ucomiss(XMMRegister dst, XMMRegister src) { Assembler::ucomiss(dst, src); } void ucomiss(XMMRegister dst, Address src) { Assembler::ucomiss(dst, src); } --- old/src/cpu/x86/vm/x86_32.ad 2010-11-12 05:56:14.086193557 -0800 +++ new/src/cpu/x86/vm/x86_32.ad 2010-11-12 05:56:13.668624047 -0800 @@ -507,6 +507,30 @@ //============================================================================= +const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty; + +void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { + emit_constant_table(cbuf); + set_table_base_offset(0); + // Empty encoding +} + +uint MachConstantBaseNode::size(PhaseRegAlloc* ra_) const { + // Compute the size (even if it's zero) since + // Compile::Shorten_branches needs the table to be emitted (which + // happens in Compile::scratch_emit_size) to calculate the size for + // MachConstantNode's. + return MachNode::size(ra_); +} + +#ifndef PRODUCT +void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const { + st->print("# MachConstantBaseNode (empty encoding)"); +} +#endif + + +//============================================================================= #ifndef PRODUCT void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream* st ) const { Compile* C = ra_->C; @@ -1320,29 +1344,6 @@ } -static void emit_double_constant(CodeBuffer& cbuf, double x) { - int mark = cbuf.insts()->mark_off(); - MacroAssembler _masm(&cbuf); - address double_address = __ double_constant(x); - cbuf.insts()->set_mark_off(mark); // preserve mark across masm shift - emit_d32_reloc(cbuf, - (int)double_address, - internal_word_Relocation::spec(double_address), - RELOC_DISP32); -} - -static void emit_float_constant(CodeBuffer& cbuf, float x) { - int mark = cbuf.insts()->mark_off(); - MacroAssembler _masm(&cbuf); - address float_address = __ float_constant(x); - cbuf.insts()->set_mark_off(mark); // preserve mark across masm shift - emit_d32_reloc(cbuf, - (int)float_address, - internal_word_Relocation::spec(float_address), - RELOC_DISP32); -} - - const bool Matcher::match_rule_supported(int opcode) { if (!has_match_rule(opcode)) return false; @@ -1354,22 +1355,6 @@ return regnum - 32; // The FP registers are in the second chunk } -bool is_positive_zero_float(jfloat f) { - return jint_cast(f) == jint_cast(0.0F); -} - -bool is_positive_one_float(jfloat f) { - return jint_cast(f) == jint_cast(1.0F); -} - -bool is_positive_zero_double(jdouble d) { - return jlong_cast(d) == jlong_cast(0.0); -} - -bool is_positive_one_double(jdouble d) { - return jlong_cast(d) == jlong_cast(1.0); -} - // This is UltraSparc specific, true just means we have fast l2f conversion const bool Matcher::convL2FSupported(void) { return true; @@ -2036,67 +2021,6 @@ %} - enc_class LdImmD (immD src) %{ // Load Immediate - if( is_positive_zero_double($src$$constant)) { - // FLDZ - emit_opcode(cbuf,0xD9); - emit_opcode(cbuf,0xEE); - } else if( is_positive_one_double($src$$constant)) { - // FLD1 - emit_opcode(cbuf,0xD9); - emit_opcode(cbuf,0xE8); - } else { - emit_opcode(cbuf,0xDD); - emit_rm(cbuf, 0x0, 0x0, 0x5); - emit_double_constant(cbuf, $src$$constant); - } - %} - - - enc_class LdImmF (immF src) %{ // Load Immediate - if( is_positive_zero_float($src$$constant)) { - emit_opcode(cbuf,0xD9); - emit_opcode(cbuf,0xEE); - } else if( is_positive_one_float($src$$constant)) { - emit_opcode(cbuf,0xD9); - emit_opcode(cbuf,0xE8); - } else { - $$$emit8$primary; - // Load immediate does not have a zero or sign extended version - // for 8-bit immediates - // First load to TOS, then move to dst - emit_rm(cbuf, 0x0, 0x0, 0x5); - emit_float_constant(cbuf, $src$$constant); - } - %} - - enc_class LdImmX (regX dst, immXF con) %{ // Load Immediate - emit_rm(cbuf, 0x0, $dst$$reg, 0x5); - emit_float_constant(cbuf, $con$$constant); - %} - - enc_class LdImmXD (regXD dst, immXD con) %{ // Load Immediate - emit_rm(cbuf, 0x0, $dst$$reg, 0x5); - emit_double_constant(cbuf, $con$$constant); - %} - - enc_class load_conXD (regXD dst, immXD con) %{ // Load double constant - // UseXmmLoadAndClearUpper ? movsd(dst, con) : movlpd(dst, con) - emit_opcode(cbuf, UseXmmLoadAndClearUpper ? 0xF2 : 0x66); - emit_opcode(cbuf, 0x0F); - emit_opcode(cbuf, UseXmmLoadAndClearUpper ? 0x10 : 0x12); - emit_rm(cbuf, 0x0, $dst$$reg, 0x5); - emit_double_constant(cbuf, $con$$constant); - %} - - enc_class Opc_MemImm_F(immF src) %{ - cbuf.set_insts_mark(); - $$$emit8$primary; - emit_rm(cbuf, 0x0, $secondary, 0x5); - emit_float_constant(cbuf, $src$$constant); - %} - - enc_class MovI2X_reg(regX dst, eRegI src) %{ emit_opcode(cbuf, 0x66 ); // MOVD dst,src emit_opcode(cbuf, 0x0F ); @@ -4801,7 +4725,7 @@ interface(CONST_INTER); %} -// Double Immediate +// Double Immediate one operand immD1() %{ predicate( UseSSE<=1 && n->getd() == 1.0 ); match(ConD); @@ -4844,7 +4768,17 @@ // Float Immediate zero operand immF0() %{ - predicate( UseSSE == 0 && n->getf() == 0.0 ); + predicate(UseSSE == 0 && n->getf() == 0.0F); + match(ConF); + + op_cost(5); + format %{ %} + interface(CONST_INTER); +%} + +// Float Immediate one +operand immF1() %{ + predicate(UseSSE == 0 && n->getf() == 1.0F); match(ConF); op_cost(5); @@ -7215,24 +7149,53 @@ %} // The instruction usage is guarded by predicate in operand immF(). -instruct loadConF(regF dst, immF src) %{ - match(Set dst src); +instruct loadConF(regF dst, immF con) %{ + match(Set dst con); ins_cost(125); + format %{ "FLD_S ST,[$constantaddress]\t# load from constant table: float=$con\n\t" + "FSTP $dst" %} + ins_encode %{ + __ fld_s($constantaddress($con)); + __ fstp_d($dst$$reg); + %} + ins_pipe(fpu_reg_con); +%} - format %{ "FLD_S ST,$src\n\t" +// The instruction usage is guarded by predicate in operand immF0(). +instruct loadConF0(regF dst, immF0 con) %{ + match(Set dst con); + ins_cost(125); + format %{ "FLDZ ST\n\t" "FSTP $dst" %} - opcode(0xD9, 0x00); /* D9 /0 */ - ins_encode(LdImmF(src), Pop_Reg_F(dst) ); - ins_pipe( fpu_reg_con ); + ins_encode %{ + __ fldz(); + __ fstp_d($dst$$reg); + %} + ins_pipe(fpu_reg_con); +%} + +// The instruction usage is guarded by predicate in operand immF1(). +instruct loadConF1(regF dst, immF1 con) %{ + match(Set dst con); + ins_cost(125); + format %{ "FLD1 ST\n\t" + "FSTP $dst" %} + ins_encode %{ + __ fld1(); + __ fstp_d($dst$$reg); + %} + ins_pipe(fpu_reg_con); %} // The instruction usage is guarded by predicate in operand immXF(). instruct loadConX(regX dst, immXF con) %{ match(Set dst con); ins_cost(125); - format %{ "MOVSS $dst,[$con]" %} - ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x10), LdImmX(dst, con)); - ins_pipe( pipe_slow ); + format %{ "MOVSS $dst,[$constantaddress]\t# load from constant table: float=$con" %} + ins_encode %{ + __ movflt($dst$$XMMRegister, $constantaddress($con)); + %} + ins_pipe(pipe_slow); %} // The instruction usage is guarded by predicate in operand immXF0(). @@ -7240,28 +7203,63 @@ match(Set dst src); ins_cost(100); format %{ "XORPS $dst,$dst\t# float 0.0" %} - ins_encode( Opcode(0x0F), Opcode(0x57), RegReg(dst,dst)); - ins_pipe( pipe_slow ); + ins_encode %{ + __ xorps($dst$$XMMRegister, $dst$$XMMRegister); + %} + ins_pipe(pipe_slow); %} // The instruction usage is guarded by predicate in operand immD(). -instruct loadConD(regD dst, immD src) %{ - match(Set dst src); +instruct loadConD(regD dst, immD con) %{ + match(Set dst con); + ins_cost(125); + + format %{ "FLD_D ST,[$constantaddress]\t# load from constant table: double=$con\n\t" + "FSTP $dst" %} + ins_encode %{ + __ fld_d($constantaddress($con)); + __ fstp_d($dst$$reg); + %} + ins_pipe(fpu_reg_con); +%} + +// The instruction usage is guarded by predicate in operand immD0(). +instruct loadConD0(regD dst, immD0 con) %{ + match(Set dst con); + ins_cost(125); + + format %{ "FLDZ ST\n\t" + "FSTP $dst" %} + ins_encode %{ + __ fldz(); + __ fstp_d($dst$$reg); + %} + ins_pipe(fpu_reg_con); +%} + +// The instruction usage is guarded by predicate in operand immD1(). +instruct loadConD1(regD dst, immD1 con) %{ + match(Set dst con); ins_cost(125); - format %{ "FLD_D ST,$src\n\t" + format %{ "FLD1 ST\n\t" "FSTP $dst" %} - ins_encode(LdImmD(src), Pop_Reg_D(dst) ); - ins_pipe( fpu_reg_con ); + ins_encode %{ + __ fld1(); + __ fstp_d($dst$$reg); + %} + ins_pipe(fpu_reg_con); %} // The instruction usage is guarded by predicate in operand immXD(). instruct loadConXD(regXD dst, immXD con) %{ match(Set dst con); ins_cost(125); - format %{ "MOVSD $dst,[$con]" %} - ins_encode(load_conXD(dst, con)); - ins_pipe( pipe_slow ); + format %{ "MOVSD $dst,[$constantaddress]\t# load from constant table: double=$con" %} + ins_encode %{ + __ movdbl($dst$$XMMRegister, $constantaddress($con)); + %} + ins_pipe(pipe_slow); %} // The instruction usage is guarded by predicate in operand immXD0(). @@ -10303,41 +10301,45 @@ ins_pipe( fpu_reg_mem ); %} -instruct addD_reg_imm1(regD dst, immD1 src) %{ +instruct addD_reg_imm1(regD dst, immD1 con) %{ predicate(UseSSE<=1); - match(Set dst (AddD dst src)); + match(Set dst (AddD dst con)); ins_cost(125); format %{ "FLD1\n\t" "DADDp $dst,ST" %} - opcode(0xDE, 0x00); - ins_encode( LdImmD(src), - OpcP, RegOpc(dst) ); - ins_pipe( fpu_reg ); + ins_encode %{ + __ fld1(); + __ faddp($dst$$reg); + %} + ins_pipe(fpu_reg); %} -instruct addD_reg_imm(regD dst, immD src) %{ +instruct addD_reg_imm(regD dst, immD con) %{ predicate(UseSSE<=1 && _kids[1]->_leaf->getd() != 0.0 && _kids[1]->_leaf->getd() != 1.0 ); - match(Set dst (AddD dst src)); + match(Set dst (AddD dst con)); ins_cost(200); - format %{ "FLD_D [$src]\n\t" + format %{ "FLD_D [$constantaddress]\t# load from constant table: double=$con\n\t" "DADDp $dst,ST" %} - opcode(0xDE, 0x00); /* DE /0 */ - ins_encode( LdImmD(src), - OpcP, RegOpc(dst)); - ins_pipe( fpu_reg_mem ); + ins_encode %{ + __ fld_d($constantaddress($con)); + __ faddp($dst$$reg); + %} + ins_pipe(fpu_reg_mem); %} instruct addD_reg_imm_round(stackSlotD dst, regD src, immD con) %{ predicate(UseSSE<=1 && _kids[0]->_kids[1]->_leaf->getd() != 0.0 && _kids[0]->_kids[1]->_leaf->getd() != 1.0 ); match(Set dst (RoundDouble (AddD src con))); ins_cost(200); - format %{ "FLD_D [$con]\n\t" + format %{ "FLD_D [$constantaddress]\t# load from constant table: double=$con\n\t" "DADD ST,$src\n\t" "FSTP_D $dst\t# D-round" %} - opcode(0xD8, 0x00); /* D8 /0 */ - ins_encode( LdImmD(con), - OpcP, RegOpc(src), Pop_Mem_D(dst)); - ins_pipe( fpu_mem_reg_con ); + ins_encode %{ + __ fld_d($constantaddress($con)); + __ fadd($src$$reg); + __ fstp_d(Address(rsp, $dst$$disp)); + %} + ins_pipe(fpu_mem_reg_con); %} // Add two double precision floating point values in xmm @@ -10352,9 +10354,11 @@ instruct addXD_imm(regXD dst, immXD con) %{ predicate(UseSSE>=2); match(Set dst (AddD dst con)); - format %{ "ADDSD $dst,[$con]" %} - ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x58), LdImmXD(dst, con) ); - ins_pipe( pipe_slow ); + format %{ "ADDSD $dst,[$constantaddress]\t# load from constant table: double=$con" %} + ins_encode %{ + __ addsd($dst$$XMMRegister, $constantaddress($con)); + %} + ins_pipe(pipe_slow); %} instruct addXD_mem(regXD dst, memory mem) %{ @@ -10377,9 +10381,11 @@ instruct subXD_imm(regXD dst, immXD con) %{ predicate(UseSSE>=2); match(Set dst (SubD dst con)); - format %{ "SUBSD $dst,[$con]" %} - ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x5C), LdImmXD(dst, con) ); - ins_pipe( pipe_slow ); + format %{ "SUBSD $dst,[$constantaddress]\t# load from constant table: double=$con" %} + ins_encode %{ + __ subsd($dst$$XMMRegister, $constantaddress($con)); + %} + ins_pipe(pipe_slow); %} instruct subXD_mem(regXD dst, memory mem) %{ @@ -10402,9 +10408,11 @@ instruct mulXD_imm(regXD dst, immXD con) %{ predicate(UseSSE>=2); match(Set dst (MulD dst con)); - format %{ "MULSD $dst,[$con]" %} - ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x59), LdImmXD(dst, con) ); - ins_pipe( pipe_slow ); + format %{ "MULSD $dst,[$constantaddress]\t# load from constant table: double=$con" %} + ins_encode %{ + __ mulsd($dst$$XMMRegister, $constantaddress($con)); + %} + ins_pipe(pipe_slow); %} instruct mulXD_mem(regXD dst, memory mem) %{ @@ -10428,9 +10436,11 @@ instruct divXD_imm(regXD dst, immXD con) %{ predicate(UseSSE>=2); match(Set dst (DivD dst con)); - format %{ "DIVSD $dst,[$con]" %} - ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x5E), LdImmXD(dst, con)); - ins_pipe( pipe_slow ); + format %{ "DIVSD $dst,[$constantaddress]\t# load from constant table: double=$con" %} + ins_encode %{ + __ divsd($dst$$XMMRegister, $constantaddress($con)); + %} + ins_pipe(pipe_slow); %} instruct divXD_mem(regXD dst, memory mem) %{ @@ -10481,16 +10491,17 @@ ins_pipe( fpu_reg_reg ); %} -instruct mulD_reg_imm(regD dst, immD src) %{ +instruct mulD_reg_imm(regD dst, immD con) %{ predicate( UseSSE<=1 && _kids[1]->_leaf->getd() != 0.0 && _kids[1]->_leaf->getd() != 1.0 ); - match(Set dst (MulD dst src)); + match(Set dst (MulD dst con)); ins_cost(200); - format %{ "FLD_D [$src]\n\t" + format %{ "FLD_D [$constantaddress]\t# load from constant table: double=$con\n\t" "DMULp $dst,ST" %} - opcode(0xDE, 0x1); /* DE /1 */ - ins_encode( LdImmD(src), - OpcP, RegOpc(dst) ); - ins_pipe( fpu_reg_mem ); + ins_encode %{ + __ fld_d($constantaddress($con)); + __ fmulp($dst$$reg); + %} + ins_pipe(fpu_reg_mem); %} @@ -11224,9 +11235,11 @@ instruct addX_imm(regX dst, immXF con) %{ predicate(UseSSE>=1); match(Set dst (AddF dst con)); - format %{ "ADDSS $dst,[$con]" %} - ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x58), LdImmX(dst, con) ); - ins_pipe( pipe_slow ); + format %{ "ADDSS $dst,[$constantaddress]\t# load from constant table: float=$con" %} + ins_encode %{ + __ addss($dst$$XMMRegister, $constantaddress($con)); + %} + ins_pipe(pipe_slow); %} instruct addX_mem(regX dst, memory mem) %{ @@ -11249,9 +11262,11 @@ instruct subX_imm(regX dst, immXF con) %{ predicate(UseSSE>=1); match(Set dst (SubF dst con)); - format %{ "SUBSS $dst,[$con]" %} - ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x5C), LdImmX(dst, con) ); - ins_pipe( pipe_slow ); + format %{ "SUBSS $dst,[$constantaddress]\t# load from constant table: float=$con" %} + ins_encode %{ + __ subss($dst$$XMMRegister, $constantaddress($con)); + %} + ins_pipe(pipe_slow); %} instruct subX_mem(regX dst, memory mem) %{ @@ -11274,9 +11289,11 @@ instruct mulX_imm(regX dst, immXF con) %{ predicate(UseSSE>=1); match(Set dst (MulF dst con)); - format %{ "MULSS $dst,[$con]" %} - ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x59), LdImmX(dst, con) ); - ins_pipe( pipe_slow ); + format %{ "MULSS $dst,[$constantaddress]\t# load from constant table: float=$con" %} + ins_encode %{ + __ mulss($dst$$XMMRegister, $constantaddress($con)); + %} + ins_pipe(pipe_slow); %} instruct mulX_mem(regX dst, memory mem) %{ @@ -11299,9 +11316,11 @@ instruct divX_imm(regX dst, immXF con) %{ predicate(UseSSE>=1); match(Set dst (DivF dst con)); - format %{ "DIVSS $dst,[$con]" %} - ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x5E), LdImmX(dst, con) ); - ins_pipe( pipe_slow ); + format %{ "DIVSS $dst,[$constantaddress]\t# load from constant table: float=$con" %} + ins_encode %{ + __ divss($dst$$XMMRegister, $constantaddress($con)); + %} + ins_pipe(pipe_slow); %} instruct divX_mem(regX dst, memory mem) %{ @@ -11456,31 +11475,33 @@ // Spill to obtain 24-bit precision -instruct addF24_reg_imm(stackSlotF dst, regF src1, immF src2) %{ +instruct addF24_reg_imm(stackSlotF dst, regF src, immF con) %{ predicate(UseSSE==0 && Compile::current()->select_24_bit_instr()); - match(Set dst (AddF src1 src2)); - format %{ "FLD $src1\n\t" - "FADD $src2\n\t" + match(Set dst (AddF src con)); + format %{ "FLD $src\n\t" + "FADD_S [$constantaddress]\t# load from constant table: float=$con\n\t" "FSTP_S $dst" %} - opcode(0xD8, 0x00); /* D8 /0 */ - ins_encode( Push_Reg_F(src1), - Opc_MemImm_F(src2), - Pop_Mem_F(dst)); - ins_pipe( fpu_mem_reg_con ); + ins_encode %{ + __ fld_s($src$$reg - 1); // FLD ST(i-1) + __ fadd_s($constantaddress($con)); + __ fstp_s(Address(rsp, $dst$$disp)); + %} + ins_pipe(fpu_mem_reg_con); %} // // This instruction does not round to 24-bits -instruct addF_reg_imm(regF dst, regF src1, immF src2) %{ +instruct addF_reg_imm(regF dst, regF src, immF con) %{ predicate(UseSSE==0 && !Compile::current()->select_24_bit_instr()); - match(Set dst (AddF src1 src2)); - format %{ "FLD $src1\n\t" - "FADD $src2\n\t" - "FSTP_S $dst" %} - opcode(0xD8, 0x00); /* D8 /0 */ - ins_encode( Push_Reg_F(src1), - Opc_MemImm_F(src2), - Pop_Reg_F(dst)); - ins_pipe( fpu_reg_reg_con ); + match(Set dst (AddF src con)); + format %{ "FLD $src\n\t" + "FADD_S [$constantaddress]\t# load from constant table: float=$con\n\t" + "FSTP $dst" %} + ins_encode %{ + __ fld_s($src$$reg - 1); // FLD ST(i-1) + __ fadd_s($constantaddress($con)); + __ fstp_d($dst$$reg); + %} + ins_pipe(fpu_reg_reg_con); %} // Spill to obtain 24-bit precision @@ -11559,29 +11580,35 @@ %} // Spill to obtain 24-bit precision -instruct mulF24_reg_imm(stackSlotF dst, regF src1, immF src2) %{ +instruct mulF24_reg_imm(stackSlotF dst, regF src, immF con) %{ predicate(UseSSE==0 && Compile::current()->select_24_bit_instr()); - match(Set dst (MulF src1 src2)); + match(Set dst (MulF src con)); - format %{ "FMULc $dst,$src1,$src2" %} - opcode(0xD8, 0x1); /* D8 /1*/ - ins_encode( Push_Reg_F(src1), - Opc_MemImm_F(src2), - Pop_Mem_F(dst)); - ins_pipe( fpu_mem_reg_con ); + format %{ "FLD $src\n\t" + "FMUL_S [$constantaddress]\t# load from constant table: float=$con\n\t" + "FSTP_S $dst" %} + ins_encode %{ + __ fld_s($src$$reg - 1); // FLD ST(i-1) + __ fmul_s($constantaddress($con)); + __ fstp_s(Address(rsp, $dst$$disp)); + %} + ins_pipe(fpu_mem_reg_con); %} // // This instruction does not round to 24-bits -instruct mulF_reg_imm(regF dst, regF src1, immF src2) %{ +instruct mulF_reg_imm(regF dst, regF src, immF con) %{ predicate(UseSSE==0 && !Compile::current()->select_24_bit_instr()); - match(Set dst (MulF src1 src2)); + match(Set dst (MulF src con)); - format %{ "FMULc $dst. $src1, $src2" %} - opcode(0xD8, 0x1); /* D8 /1*/ - ins_encode( Push_Reg_F(src1), - Opc_MemImm_F(src2), - Pop_Reg_F(dst)); - ins_pipe( fpu_reg_reg_con ); + format %{ "FLD $src\n\t" + "FMUL_S [$constantaddress]\t# load from constant table: float=$con\n\t" + "FSTP $dst" %} + ins_encode %{ + __ fld_s($src$$reg - 1); // FLD ST(i-1) + __ fmul_s($constantaddress($con)); + __ fstp_d($dst$$reg); + %} + ins_pipe(fpu_reg_reg_con); %} @@ -12939,16 +12966,11 @@ instruct jumpXtnd(eRegI switch_val) %{ match(Jump switch_val); ins_cost(350); - - format %{ "JMP [table_base](,$switch_val,1)\n\t" %} - + format %{ "JMP [$constantaddress](,$switch_val,1)\n\t" %} ins_encode %{ - address table_base = __ address_table_constant(_index2label); - // Jump to Address(table_base + switch_reg) - InternalAddress table(table_base); Address index(noreg, $switch_val$$Register, Address::times_1); - __ jump(ArrayAddress(table, index)); + __ jump(ArrayAddress($constantaddress, index)); %} ins_pc_relative(1); ins_pipe(pipe_jmp); --- old/src/cpu/x86/vm/x86_64.ad 2010-11-12 05:56:17.111647608 -0800 +++ new/src/cpu/x86/vm/x86_64.ad 2010-11-12 05:56:16.666554612 -0800 @@ -833,6 +833,30 @@ //============================================================================= +const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty; + +void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { + emit_constant_table(cbuf); + set_table_base_offset(0); + // Empty encoding +} + +uint MachConstantBaseNode::size(PhaseRegAlloc* ra_) const { + // Compute the size (even if it's zero) since + // Compile::Shorten_branches needs the table to be emitted (which + // happens in Compile::scratch_emit_size) to calculate the size for + // MachConstantNodes. + return MachNode::size(ra_); +} + +#ifndef PRODUCT +void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const { + st->print("# MachConstantBase (empty encoding)"); +} +#endif + + +//============================================================================= #ifndef PRODUCT void MachPrologNode::format(PhaseRegAlloc* ra_, outputStream* st) const { @@ -1922,28 +1946,6 @@ return offset; } -static void emit_double_constant(CodeBuffer& cbuf, double x) { - int mark = cbuf.insts()->mark_off(); - MacroAssembler _masm(&cbuf); - address double_address = __ double_constant(x); - cbuf.insts()->set_mark_off(mark); // preserve mark across masm shift - emit_d32_reloc(cbuf, - (int) (double_address - cbuf.insts_end() - 4), - internal_word_Relocation::spec(double_address), - RELOC_DISP32); -} - -static void emit_float_constant(CodeBuffer& cbuf, float x) { - int mark = cbuf.insts()->mark_off(); - MacroAssembler _masm(&cbuf); - address float_address = __ float_constant(x); - cbuf.insts()->set_mark_off(mark); // preserve mark across masm shift - emit_d32_reloc(cbuf, - (int) (float_address - cbuf.insts_end() - 4), - internal_word_Relocation::spec(float_address), - RELOC_DISP32); -} - const bool Matcher::match_rule_supported(int opcode) { if (!has_match_rule(opcode)) @@ -2789,43 +2791,6 @@ } %} - enc_class load_immF(regF dst, immF con) - %{ - // XXX reg_mem doesn't support RIP-relative addressing yet - emit_rm(cbuf, 0x0, $dst$$reg & 7, 0x5); // 00 reg 101 - emit_float_constant(cbuf, $con$$constant); - %} - - enc_class load_immD(regD dst, immD con) - %{ - // XXX reg_mem doesn't support RIP-relative addressing yet - emit_rm(cbuf, 0x0, $dst$$reg & 7, 0x5); // 00 reg 101 - emit_double_constant(cbuf, $con$$constant); - %} - - enc_class load_conF (regF dst, immF con) %{ // Load float constant - emit_opcode(cbuf, 0xF3); - if ($dst$$reg >= 8) { - emit_opcode(cbuf, Assembler::REX_R); - } - emit_opcode(cbuf, 0x0F); - emit_opcode(cbuf, 0x10); - emit_rm(cbuf, 0x0, $dst$$reg & 7, 0x5); // 00 reg 101 - emit_float_constant(cbuf, $con$$constant); - %} - - enc_class load_conD (regD dst, immD con) %{ // Load double constant - // UseXmmLoadAndClearUpper ? movsd(dst, con) : movlpd(dst, con) - emit_opcode(cbuf, UseXmmLoadAndClearUpper ? 0xF2 : 0x66); - if ($dst$$reg >= 8) { - emit_opcode(cbuf, Assembler::REX_R); - } - emit_opcode(cbuf, 0x0F); - emit_opcode(cbuf, UseXmmLoadAndClearUpper ? 0x10 : 0x12); - emit_rm(cbuf, 0x0, $dst$$reg & 7, 0x5); // 00 reg 101 - emit_double_constant(cbuf, $con$$constant); - %} - // Encode a reg-reg copy. If it is useless, then empty encoding. enc_class enc_copy(rRegI dst, rRegI src) %{ @@ -2926,63 +2891,6 @@ emit_d32(cbuf, 0x00); %} - enc_class jump_enc(rRegL switch_val, rRegI dest) %{ - MacroAssembler masm(&cbuf); - - Register switch_reg = as_Register($switch_val$$reg); - Register dest_reg = as_Register($dest$$reg); - address table_base = masm.address_table_constant(_index2label); - - // We could use jump(ArrayAddress) except that the macro assembler needs to use r10 - // to do that and the compiler is using that register as one it can allocate. - // So we build it all by hand. - // Address index(noreg, switch_reg, Address::times_1); - // ArrayAddress dispatch(table, index); - - Address dispatch(dest_reg, switch_reg, Address::times_1); - - masm.lea(dest_reg, InternalAddress(table_base)); - masm.jmp(dispatch); - %} - - enc_class jump_enc_addr(rRegL switch_val, immI2 shift, immL32 offset, rRegI dest) %{ - MacroAssembler masm(&cbuf); - - Register switch_reg = as_Register($switch_val$$reg); - Register dest_reg = as_Register($dest$$reg); - address table_base = masm.address_table_constant(_index2label); - - // We could use jump(ArrayAddress) except that the macro assembler needs to use r10 - // to do that and the compiler is using that register as one it can allocate. - // So we build it all by hand. - // Address index(noreg, switch_reg, (Address::ScaleFactor)$shift$$constant, (int)$offset$$constant); - // ArrayAddress dispatch(table, index); - - Address dispatch(dest_reg, switch_reg, (Address::ScaleFactor)$shift$$constant, (int)$offset$$constant); - - masm.lea(dest_reg, InternalAddress(table_base)); - masm.jmp(dispatch); - %} - - enc_class jump_enc_offset(rRegL switch_val, immI2 shift, rRegI dest) %{ - MacroAssembler masm(&cbuf); - - Register switch_reg = as_Register($switch_val$$reg); - Register dest_reg = as_Register($dest$$reg); - address table_base = masm.address_table_constant(_index2label); - - // We could use jump(ArrayAddress) except that the macro assembler needs to use r10 - // to do that and the compiler is using that register as one it can allocate. - // So we build it all by hand. - // Address index(noreg, switch_reg, (Address::ScaleFactor)$shift$$constant); - // ArrayAddress dispatch(table, index); - - Address dispatch(dest_reg, switch_reg, (Address::ScaleFactor)$shift$$constant); - masm.lea(dest_reg, InternalAddress(table_base)); - masm.jmp(dispatch); - - %} - enc_class lock_prefix() %{ if (os::is_MP()) { @@ -6641,12 +6549,11 @@ ins_pipe(ialu_reg); %} -instruct loadConP(rRegP dst, immP src) -%{ - match(Set dst src); +instruct loadConP(rRegP dst, immP con) %{ + match(Set dst con); - format %{ "movq $dst, $src\t# ptr" %} - ins_encode(load_immP(dst, src)); + format %{ "movq $dst, $con\t# ptr" %} + ins_encode(load_immP(dst, con)); ins_pipe(ialu_reg_fat); // XXX %} @@ -6673,13 +6580,13 @@ ins_pipe(ialu_reg); %} -instruct loadConF(regF dst, immF src) -%{ - match(Set dst src); +instruct loadConF(regF dst, immF con) %{ + match(Set dst con); ins_cost(125); - - format %{ "movss $dst, [$src]" %} - ins_encode(load_conF(dst, src)); + format %{ "movss $dst, [$constantaddress]\t# load from constant table: float=$con" %} + ins_encode %{ + __ movflt($dst$$XMMRegister, $constantaddress($con)); + %} ins_pipe(pipe_slow); %} @@ -6721,13 +6628,13 @@ %} // Use the same format since predicate() can not be used here. -instruct loadConD(regD dst, immD src) -%{ - match(Set dst src); +instruct loadConD(regD dst, immD con) %{ + match(Set dst con); ins_cost(125); - - format %{ "movsd $dst, [$src]" %} - ins_encode(load_conD(dst, src)); + format %{ "movsd $dst, [$constantaddress]\t# load from constant table: double=$con" %} + ins_encode %{ + __ movdbl($dst$$XMMRegister, $constantaddress($con)); + %} ins_pipe(pipe_slow); %} @@ -7694,9 +7601,18 @@ predicate(false); effect(TEMP dest); - format %{ "leaq $dest, table_base\n\t" + format %{ "leaq $dest, [$constantaddress]\n\t" "jmp [$dest + $switch_val << $shift]\n\t" %} - ins_encode(jump_enc_offset(switch_val, shift, dest)); + ins_encode %{ + // We could use jump(ArrayAddress) except that the macro assembler needs to use r10 + // to do that and the compiler is using that register as one it can allocate. + // So we build it all by hand. + // Address index(noreg, switch_reg, (Address::ScaleFactor)$shift$$constant); + // ArrayAddress dispatch(table, index); + Address dispatch($dest$$Register, $switch_val$$Register, (Address::ScaleFactor) $shift$$constant); + __ lea($dest$$Register, $constantaddress); + __ jmp(dispatch); + %} ins_pipe(pipe_jmp); ins_pc_relative(1); %} @@ -7706,9 +7622,18 @@ ins_cost(350); effect(TEMP dest); - format %{ "leaq $dest, table_base\n\t" + format %{ "leaq $dest, [$constantaddress]\n\t" "jmp [$dest + $switch_val << $shift + $offset]\n\t" %} - ins_encode(jump_enc_addr(switch_val, shift, offset, dest)); + ins_encode %{ + // We could use jump(ArrayAddress) except that the macro assembler needs to use r10 + // to do that and the compiler is using that register as one it can allocate. + // So we build it all by hand. + // Address index(noreg, switch_reg, (Address::ScaleFactor) $shift$$constant, (int) $offset$$constant); + // ArrayAddress dispatch(table, index); + Address dispatch($dest$$Register, $switch_val$$Register, (Address::ScaleFactor) $shift$$constant, (int) $offset$$constant); + __ lea($dest$$Register, $constantaddress); + __ jmp(dispatch); + %} ins_pipe(pipe_jmp); ins_pc_relative(1); %} @@ -7718,9 +7643,18 @@ ins_cost(350); effect(TEMP dest); - format %{ "leaq $dest, table_base\n\t" + format %{ "leaq $dest, [$constantaddress]\n\t" "jmp [$dest + $switch_val]\n\t" %} - ins_encode(jump_enc(switch_val, dest)); + ins_encode %{ + // We could use jump(ArrayAddress) except that the macro assembler needs to use r10 + // to do that and the compiler is using that register as one it can allocate. + // So we build it all by hand. + // Address index(noreg, switch_reg, Address::times_1); + // ArrayAddress dispatch(table, index); + Address dispatch($dest$$Register, $switch_val$$Register, Address::times_1); + __ lea($dest$$Register, $constantaddress); + __ jmp(dispatch); + %} ins_pipe(pipe_jmp); ins_pc_relative(1); %} @@ -10376,30 +10310,36 @@ ins_pipe(pipe_slow); %} -instruct cmpF_cc_imm(rFlagsRegU cr, regF src1, immF src2) -%{ - match(Set cr (CmpF src1 src2)); +instruct cmpF_cc_imm(rFlagsRegU cr, regF src, immF con) %{ + match(Set cr (CmpF src con)); ins_cost(145); - format %{ "ucomiss $src1, $src2\n\t" + format %{ "ucomiss $src, [$constantaddress]\t# load from constant table: float=$con\n\t" "jnp,s exit\n\t" "pushfq\t# saw NaN, set CF\n\t" "andq [rsp], #0xffffff2b\n\t" "popfq\n" "exit: nop\t# avoid branch to branch" %} - opcode(0x0F, 0x2E); - ins_encode(REX_reg_mem(src1, src2), OpcP, OpcS, load_immF(src1, src2), - cmpfp_fixup); + ins_encode %{ + Label L_exit; + __ ucomiss($src$$XMMRegister, $constantaddress($con)); + __ jcc(Assembler::noParity, L_exit); + __ pushf(); + __ andq(rsp, 0xffffff2b); + __ popf(); + __ bind(L_exit); + __ nop(); + %} ins_pipe(pipe_slow); %} -instruct cmpF_cc_immCF(rFlagsRegUCF cr, regF src1, immF src2) %{ - match(Set cr (CmpF src1 src2)); - +instruct cmpF_cc_immCF(rFlagsRegUCF cr, regF src, immF con) %{ + match(Set cr (CmpF src con)); ins_cost(100); - format %{ "ucomiss $src1, $src2" %} - opcode(0x0F, 0x2E); - ins_encode(REX_reg_mem(src1, src2), OpcP, OpcS, load_immF(src1, src2)); + format %{ "ucomiss $src, [$constantaddress]\t# load from constant table: float=$con" %} + ins_encode %{ + __ ucomiss($src$$XMMRegister, $constantaddress($con)); + %} ins_pipe(pipe_slow); %} @@ -10458,30 +10398,36 @@ ins_pipe(pipe_slow); %} -instruct cmpD_cc_imm(rFlagsRegU cr, regD src1, immD src2) -%{ - match(Set cr (CmpD src1 src2)); +instruct cmpD_cc_imm(rFlagsRegU cr, regD src, immD con) %{ + match(Set cr (CmpD src con)); ins_cost(145); - format %{ "ucomisd $src1, [$src2]\n\t" + format %{ "ucomisd $src, [$constantaddress]\t# load from constant table: double=$con\n\t" "jnp,s exit\n\t" "pushfq\t# saw NaN, set CF\n\t" "andq [rsp], #0xffffff2b\n\t" "popfq\n" "exit: nop\t# avoid branch to branch" %} - opcode(0x66, 0x0F, 0x2E); - ins_encode(OpcP, REX_reg_mem(src1, src2), OpcS, OpcT, load_immD(src1, src2), - cmpfp_fixup); + ins_encode %{ + Label L_exit; + __ ucomisd($src$$XMMRegister, $constantaddress($con)); + __ jcc(Assembler::noParity, L_exit); + __ pushf(); + __ andq(rsp, 0xffffff2b); + __ popf(); + __ bind(L_exit); + __ nop(); + %} ins_pipe(pipe_slow); %} -instruct cmpD_cc_immCF(rFlagsRegUCF cr, regD src1, immD src2) %{ - match(Set cr (CmpD src1 src2)); - +instruct cmpD_cc_immCF(rFlagsRegUCF cr, regD src, immD con) %{ + match(Set cr (CmpD src con)); ins_cost(100); - format %{ "ucomisd $src1, [$src2]" %} - opcode(0x66, 0x0F, 0x2E); - ins_encode(OpcP, REX_reg_mem(src1, src2), OpcS, OpcT, load_immD(src1, src2)); + format %{ "ucomisd $src, [$constantaddress]\t# load from constant table: double=$con" %} + ins_encode %{ + __ ucomisd($src$$XMMRegister, $constantaddress($con)); + %} ins_pipe(pipe_slow); %} @@ -10528,23 +10474,29 @@ %} // Compare into -1,0,1 -instruct cmpF_imm(rRegI dst, regF src1, immF src2, rFlagsReg cr) -%{ - match(Set dst (CmpF3 src1 src2)); +instruct cmpF_imm(rRegI dst, regF src, immF con, rFlagsReg cr) %{ + match(Set dst (CmpF3 src con)); effect(KILL cr); ins_cost(275); - format %{ "ucomiss $src1, [$src2]\n\t" + format %{ "ucomiss $src, [$constantaddress]\t# load from constant table: float=$con\n\t" "movl $dst, #-1\n\t" "jp,s done\n\t" "jb,s done\n\t" "setne $dst\n\t" "movzbl $dst, $dst\n" "done:" %} - - opcode(0x0F, 0x2E); - ins_encode(REX_reg_mem(src1, src2), OpcP, OpcS, load_immF(src1, src2), - cmpfp3(dst)); + ins_encode %{ + Label L_done; + Register Rdst = $dst$$Register; + __ ucomiss($src$$XMMRegister, $constantaddress($con)); + __ movl(Rdst, -1); + __ jcc(Assembler::parity, L_done); + __ jcc(Assembler::below, L_done); + __ setb(Assembler::notEqual, Rdst); + __ movzbl(Rdst, Rdst); + __ bind(L_done); + %} ins_pipe(pipe_slow); %} @@ -10591,23 +10543,29 @@ %} // Compare into -1,0,1 -instruct cmpD_imm(rRegI dst, regD src1, immD src2, rFlagsReg cr) -%{ - match(Set dst (CmpD3 src1 src2)); +instruct cmpD_imm(rRegI dst, regD src, immD con, rFlagsReg cr) %{ + match(Set dst (CmpD3 src con)); effect(KILL cr); ins_cost(275); - format %{ "ucomisd $src1, [$src2]\n\t" + format %{ "ucomisd $src, [$constantaddress]\t# load from constant table: double=$con\n\t" "movl $dst, #-1\n\t" "jp,s done\n\t" "jb,s done\n\t" "setne $dst\n\t" "movzbl $dst, $dst\n" "done:" %} - - opcode(0x66, 0x0F, 0x2E); - ins_encode(OpcP, REX_reg_mem(src1, src2), OpcS, OpcT, load_immD(src1, src2), - cmpfp3(dst)); + ins_encode %{ + Register Rdst = $dst$$Register; + Label L_done; + __ ucomisd($src$$XMMRegister, $constantaddress($con)); + __ movl(Rdst, -1); + __ jcc(Assembler::parity, L_done); + __ jcc(Assembler::below, L_done); + __ setb(Assembler::notEqual, Rdst); + __ movzbl(Rdst, Rdst); + __ bind(L_done); + %} ins_pipe(pipe_slow); %} @@ -10633,14 +10591,13 @@ ins_pipe(pipe_slow); %} -instruct addF_imm(regF dst, immF src) -%{ - match(Set dst (AddF dst src)); - - format %{ "addss $dst, [$src]" %} +instruct addF_imm(regF dst, immF con) %{ + match(Set dst (AddF dst con)); + format %{ "addss $dst, [$constantaddress]\t# load from constant table: float=$con" %} ins_cost(150); // XXX - opcode(0xF3, 0x0F, 0x58); - ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immF(dst, src)); + ins_encode %{ + __ addss($dst$$XMMRegister, $constantaddress($con)); + %} ins_pipe(pipe_slow); %} @@ -10666,14 +10623,13 @@ ins_pipe(pipe_slow); %} -instruct addD_imm(regD dst, immD src) -%{ - match(Set dst (AddD dst src)); - - format %{ "addsd $dst, [$src]" %} +instruct addD_imm(regD dst, immD con) %{ + match(Set dst (AddD dst con)); + format %{ "addsd $dst, [$constantaddress]\t# load from constant table: double=$con" %} ins_cost(150); // XXX - opcode(0xF2, 0x0F, 0x58); - ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immD(dst, src)); + ins_encode %{ + __ addsd($dst$$XMMRegister, $constantaddress($con)); + %} ins_pipe(pipe_slow); %} @@ -10699,14 +10655,13 @@ ins_pipe(pipe_slow); %} -instruct subF_imm(regF dst, immF src) -%{ - match(Set dst (SubF dst src)); - - format %{ "subss $dst, [$src]" %} +instruct subF_imm(regF dst, immF con) %{ + match(Set dst (SubF dst con)); + format %{ "subss $dst, [$constantaddress]\t# load from constant table: float=$con" %} ins_cost(150); // XXX - opcode(0xF3, 0x0F, 0x5C); - ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immF(dst, src)); + ins_encode %{ + __ subss($dst$$XMMRegister, $constantaddress($con)); + %} ins_pipe(pipe_slow); %} @@ -10732,14 +10687,13 @@ ins_pipe(pipe_slow); %} -instruct subD_imm(regD dst, immD src) -%{ - match(Set dst (SubD dst src)); - - format %{ "subsd $dst, [$src]" %} +instruct subD_imm(regD dst, immD con) %{ + match(Set dst (SubD dst con)); + format %{ "subsd $dst, [$constantaddress]\t# load from constant table: double=$con" %} ins_cost(150); // XXX - opcode(0xF2, 0x0F, 0x5C); - ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immD(dst, src)); + ins_encode %{ + __ subsd($dst$$XMMRegister, $constantaddress($con)); + %} ins_pipe(pipe_slow); %} @@ -10765,14 +10719,13 @@ ins_pipe(pipe_slow); %} -instruct mulF_imm(regF dst, immF src) -%{ - match(Set dst (MulF dst src)); - - format %{ "mulss $dst, [$src]" %} +instruct mulF_imm(regF dst, immF con) %{ + match(Set dst (MulF dst con)); + format %{ "mulss $dst, [$constantaddress]\t# load from constant table: float=$con" %} ins_cost(150); // XXX - opcode(0xF3, 0x0F, 0x59); - ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immF(dst, src)); + ins_encode %{ + __ mulss($dst$$XMMRegister, $constantaddress($con)); + %} ins_pipe(pipe_slow); %} @@ -10798,14 +10751,13 @@ ins_pipe(pipe_slow); %} -instruct mulD_imm(regD dst, immD src) -%{ - match(Set dst (MulD dst src)); - - format %{ "mulsd $dst, [$src]" %} +instruct mulD_imm(regD dst, immD con) %{ + match(Set dst (MulD dst con)); + format %{ "mulsd $dst, [$constantaddress]\t# load from constant table: double=$con" %} ins_cost(150); // XXX - opcode(0xF2, 0x0F, 0x59); - ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immD(dst, src)); + ins_encode %{ + __ mulsd($dst$$XMMRegister, $constantaddress($con)); + %} ins_pipe(pipe_slow); %} @@ -10831,14 +10783,13 @@ ins_pipe(pipe_slow); %} -instruct divF_imm(regF dst, immF src) -%{ - match(Set dst (DivF dst src)); - - format %{ "divss $dst, [$src]" %} +instruct divF_imm(regF dst, immF con) %{ + match(Set dst (DivF dst con)); + format %{ "divss $dst, [$constantaddress]\t# load from constant table: float=$con" %} ins_cost(150); // XXX - opcode(0xF3, 0x0F, 0x5E); - ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immF(dst, src)); + ins_encode %{ + __ divss($dst$$XMMRegister, $constantaddress($con)); + %} ins_pipe(pipe_slow); %} @@ -10864,14 +10815,13 @@ ins_pipe(pipe_slow); %} -instruct divD_imm(regD dst, immD src) -%{ - match(Set dst (DivD dst src)); - - format %{ "divsd $dst, [$src]" %} +instruct divD_imm(regD dst, immD con) %{ + match(Set dst (DivD dst con)); + format %{ "divsd $dst, [$constantaddress]\t# load from constant table: double=$con" %} ins_cost(150); // XXX - opcode(0xF2, 0x0F, 0x5E); - ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immD(dst, src)); + ins_encode %{ + __ divsd($dst$$XMMRegister, $constantaddress($con)); + %} ins_pipe(pipe_slow); %} @@ -10897,14 +10847,13 @@ ins_pipe(pipe_slow); %} -instruct sqrtF_imm(regF dst, immF src) -%{ - match(Set dst (ConvD2F (SqrtD (ConvF2D src)))); - - format %{ "sqrtss $dst, [$src]" %} +instruct sqrtF_imm(regF dst, immF con) %{ + match(Set dst (ConvD2F (SqrtD (ConvF2D con)))); + format %{ "sqrtss $dst, [$constantaddress]\t# load from constant table: float=$con" %} ins_cost(150); // XXX - opcode(0xF3, 0x0F, 0x51); - ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immF(dst, src)); + ins_encode %{ + __ sqrtss($dst$$XMMRegister, $constantaddress($con)); + %} ins_pipe(pipe_slow); %} @@ -10930,14 +10879,13 @@ ins_pipe(pipe_slow); %} -instruct sqrtD_imm(regD dst, immD src) -%{ - match(Set dst (SqrtD src)); - - format %{ "sqrtsd $dst, [$src]" %} +instruct sqrtD_imm(regD dst, immD con) %{ + match(Set dst (SqrtD con)); + format %{ "sqrtsd $dst, [$constantaddress]\t# load from constant table: double=$con" %} ins_cost(150); // XXX - opcode(0xF2, 0x0F, 0x51); - ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immD(dst, src)); + ins_encode %{ + __ sqrtsd($dst$$XMMRegister, $constantaddress($con)); + %} ins_pipe(pipe_slow); %} --- old/src/os/linux/vm/vmError_linux.cpp 2010-11-12 05:56:20.262836058 -0800 +++ new/src/os/linux/vm/vmError_linux.cpp 2010-11-12 05:56:19.810427215 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2010, 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 @@ -41,11 +41,11 @@ jio_snprintf(p, buflen - len, "\n\n" "Do you want to debug the problem?\n\n" - "To debug, run 'gdb /proc/%d/exe %d'; then switch to thread " INTX_FORMAT "\n" + "To debug, run 'gdb /proc/%d/exe %d'; then switch to thread " INTX_FORMAT " (" INTPTR_FORMAT ")\n" "Enter 'yes' to launch gdb automatically (PATH must include gdb)\n" "Otherwise, press RETURN to abort...", os::current_process_id(), os::current_process_id(), - os::current_thread_id()); + os::current_thread_id(), os::current_thread_id()); yes = os::message_box("Unexpected Error", buf); --- old/src/share/vm/adlc/adlparse.cpp 2010-11-12 05:56:22.743671277 -0800 +++ new/src/share/vm/adlc/adlparse.cpp 2010-11-12 05:56:22.270473936 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2010, 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 @@ -95,7 +95,7 @@ if (ident == NULL) { // Empty line continue; // Get the next line } - if (!strcmp(ident, "instruct")) instr_parse(); + if (!strcmp(ident, "instruct")) instr_parse(); else if (!strcmp(ident, "operand")) oper_parse(); else if (!strcmp(ident, "opclass")) opclass_parse(); else if (!strcmp(ident, "ins_attrib")) ins_attr_parse(); @@ -216,24 +216,23 @@ else if (!strcmp(ident, "encode")) { parse_err(SYNERR, "Instructions specify ins_encode, not encode\n"); } - else if (!strcmp(ident, "ins_encode")) - instr->_insencode = ins_encode_parse(*instr); - else if (!strcmp(ident, "opcode")) instr->_opcode = opcode_parse(instr); - else if (!strcmp(ident, "size")) instr->_size = size_parse(instr); - else if (!strcmp(ident, "effect")) effect_parse(instr); - else if (!strcmp(ident, "expand")) instr->_exprule = expand_parse(instr); - else if (!strcmp(ident, "rewrite")) instr->_rewrule = rewrite_parse(); + else if (!strcmp(ident, "ins_encode")) ins_encode_parse(*instr); + else if (!strcmp(ident, "opcode")) instr->_opcode = opcode_parse(instr); + else if (!strcmp(ident, "size")) instr->_size = size_parse(instr); + else if (!strcmp(ident, "effect")) effect_parse(instr); + else if (!strcmp(ident, "expand")) instr->_exprule = expand_parse(instr); + else if (!strcmp(ident, "rewrite")) instr->_rewrule = rewrite_parse(); else if (!strcmp(ident, "constraint")) { parse_err(SYNERR, "Instructions do not specify a constraint\n"); } else if (!strcmp(ident, "construct")) { parse_err(SYNERR, "Instructions do not specify a construct\n"); } - else if (!strcmp(ident, "format")) instr->_format = format_parse(); + else if (!strcmp(ident, "format")) instr->_format = format_parse(); else if (!strcmp(ident, "interface")) { parse_err(SYNERR, "Instructions do not specify an interface\n"); } - else if (!strcmp(ident, "ins_pipe")) ins_pipe_parse(*instr); + else if (!strcmp(ident, "ins_pipe")) ins_pipe_parse(*instr); else { // Done with staticly defined parts of instruction definition // Check identifier to see if it is the name of an attribute const Form *form = _globalNames[ident]; @@ -935,9 +934,9 @@ // (2) // If we are at a replacement variable, // copy it and record in EncClass - if ( _curchar == '$' ) { + if (_curchar == '$') { // Found replacement Variable - char *rep_var = get_rep_var_ident_dup(); + char* rep_var = get_rep_var_ident_dup(); // Add flag to _strings list indicating we should check _rep_vars encoding->add_rep_var(rep_var); } @@ -2774,47 +2773,122 @@ //------------------------------ins_encode_parse_block------------------------- // Parse the block form of ins_encode. See ins_encode_parse for more details -InsEncode *ADLParser::ins_encode_parse_block(InstructForm &inst) { +void ADLParser::ins_encode_parse_block(InstructForm& inst) { // Create a new encoding name based on the name of the instruction // definition, which should be unique. - const char * prefix = "__enc_"; - char* ec_name = (char*)malloc(strlen(inst._ident) + strlen(prefix) + 1); + const char* prefix = "__ins_encode_"; + char* ec_name = (char*) malloc(strlen(inst._ident) + strlen(prefix) + 1); sprintf(ec_name, "%s%s", prefix, inst._ident); assert(_AD._encode->encClass(ec_name) == NULL, "shouldn't already exist"); - EncClass *encoding = _AD._encode->add_EncClass(ec_name); + EncClass* encoding = _AD._encode->add_EncClass(ec_name); encoding->_linenum = linenum(); // synthesize the arguments list for the enc_class from the // arguments to the instruct definition. - const char * param = NULL; + const char* param = NULL; inst._parameters.reset(); while ((param = inst._parameters.iter()) != NULL) { - OperandForm *opForm = (OperandForm*)inst._localNames[param]; + OperandForm* opForm = (OperandForm*) inst._localNames[param]; encoding->add_parameter(opForm->_ident, param); } - // Add the prologue to create the MacroAssembler - encoding->add_code("\n" - " // Define a MacroAssembler instance for use by the encoding. The\n" - " // name is chosen to match the __ idiom used for assembly in other\n" - " // parts of hotspot and assumes the existence of the standard\n" - " // #define __ _masm.\n" - " MacroAssembler _masm(&cbuf);\n"); + // Define a MacroAssembler instance for use by the encoding. The + // name is chosen to match the __ idiom used for assembly in other + // parts of hotspot and assumes the existence of the standard + // #define __ _masm. + encoding->add_code(" MacroAssembler _masm(&cbuf);\n"); // Parse the following %{ }% block - enc_class_parse_block(encoding, ec_name); + ins_encode_parse_block_impl(inst, encoding, ec_name); // Build an encoding rule which invokes the encoding rule we just // created, passing all arguments that we received. - InsEncode *encrule = new InsEncode(); // Encode class for instruction - NameAndList *params = encrule->add_encode(ec_name); + InsEncode* encrule = new InsEncode(); // Encode class for instruction + NameAndList* params = encrule->add_encode(ec_name); inst._parameters.reset(); while ((param = inst._parameters.iter()) != NULL) { params->add_entry(param); } - return encrule; + // Set encode class of this instruction. + inst._insencode = encrule; +} + + +void ADLParser::ins_encode_parse_block_impl(InstructForm& inst, EncClass* encoding, char* ec_name) { + skipws_no_preproc(); // Skip leading whitespace + // Prepend location descriptor, for debugging; cf. ADLParser::find_cpp_block + if (_AD._adlocation_debug) { + encoding->add_code(get_line_string()); + } + + // Collect the parts of the encode description + // (1) strings that are passed through to output + // (2) replacement/substitution variable, preceeded by a '$' + while ((_curchar != '%') && (*(_ptr+1) != '}')) { + + // (1) + // Check if there is a string to pass through to output + char *start = _ptr; // Record start of the next string + while ((_curchar != '$') && ((_curchar != '%') || (*(_ptr+1) != '}')) ) { + // If at the start of a comment, skip past it + if( (_curchar == '/') && ((*(_ptr+1) == '/') || (*(_ptr+1) == '*')) ) { + skipws_no_preproc(); + } else { + // ELSE advance to the next character, or start of the next line + next_char_or_line(); + } + } + // If a string was found, terminate it and record in EncClass + if (start != _ptr) { + *_ptr = '\0'; // Terminate the string + encoding->add_code(start); + } + + // (2) + // If we are at a replacement variable, + // copy it and record in EncClass + if (_curchar == '$') { + // Found replacement Variable + char* rep_var = get_rep_var_ident_dup(); + + // Add flag to _strings list indicating we should check _rep_vars + encoding->add_rep_var(rep_var); + + skipws(); + + // Check if this instruct is a MachConstantNode. + if (strcmp(rep_var, "constanttablebase") == 0) { + // This instruct is a MachConstantNode. + inst.set_is_mach_constant(true); + + if (_curchar == '(') { + parse_err(SYNERR, "constanttablebase in instruct %s cannot have an argument (only constantaddress and constantoffset)", ec_name); + return; + } + } + else if ((strcmp(rep_var, "constantaddress") == 0) || + (strcmp(rep_var, "constantoffset") == 0)) { + // This instruct is a MachConstantNode. + inst.set_is_mach_constant(true); + + // If the constant keyword has an argument, parse it. + if (_curchar == '(') constant_parse(inst); + } + } + } // end while part of format description + next_char(); // Skip '%' + next_char(); // Skip '}' + + skipws(); + + if (_AD._adlocation_debug) { + encoding->add_code(end_line_marker()); + } + + // Debug Stuff + if (_AD._adl_debug > 1) fprintf(stderr, "EncodingClass Form: %s\n", ec_name); } @@ -2838,7 +2912,7 @@ // // making it more compact to take advantage of the MacroAssembler and // placing the assembly closer to it's use by instructions. -InsEncode *ADLParser::ins_encode_parse(InstructForm &inst) { +void ADLParser::ins_encode_parse(InstructForm& inst) { // Parse encode class name skipws(); // Skip whitespace @@ -2849,11 +2923,12 @@ next_char(); // Skip '{' // Parse the block form of ins_encode - return ins_encode_parse_block(inst); + ins_encode_parse_block(inst); + return; } parse_err(SYNERR, "missing '%%{' or '(' in ins_encode definition\n"); - return NULL; + return; } next_char(); // move past '(' skipws(); @@ -2866,7 +2941,7 @@ ec_name = get_ident(); if (ec_name == NULL) { parse_err(SYNERR, "Invalid encode class name after 'ins_encode('.\n"); - return NULL; + return; } // Check that encoding is defined in the encode section EncClass *encode_class = _AD._encode->encClass(ec_name); @@ -2898,7 +2973,7 @@ (Opcode::as_opcode_type(param) == Opcode::NOT_AN_OPCODE) && ((_AD._register == NULL ) || (_AD._register->getRegDef(param) == NULL)) ) { parse_err(SYNERR, "Using non-locally defined parameter %s for encoding %s.\n", param, ec_name); - return NULL; + return; } params->add_entry(param); @@ -2915,7 +2990,7 @@ // Only ',' or ')' are valid after a parameter name parse_err(SYNERR, "expected ',' or ')' after parameter %s.\n", ec_name); - return NULL; + return; } } else { @@ -2923,11 +2998,11 @@ // Did not find a parameter if (_curchar == ',') { parse_err(SYNERR, "Expected encode parameter before ',' in encoding %s.\n", ec_name); - return NULL; + return; } if (_curchar != ')') { parse_err(SYNERR, "Expected ')' after encode parameters.\n"); - return NULL; + return; } } } // WHILE loop collecting parameters @@ -2944,7 +3019,7 @@ else if ( _curchar != ')' ) { // If not a ',' then only a ')' is allowed parse_err(SYNERR, "Expected ')' after encoding %s.\n", ec_name); - return NULL; + return; } // Check for ',' separating parameters @@ -2956,14 +3031,14 @@ } // done parsing ins_encode methods and their parameters if (_curchar != ')') { parse_err(SYNERR, "Missing ')' at end of ins_encode description.\n"); - return NULL; + return; } next_char(); // move past ')' skipws(); // Skip leading whitespace if ( _curchar != ';' ) { parse_err(SYNERR, "Missing ';' at end of ins_encode.\n"); - return NULL; + return; } next_char(); // move past ';' skipws(); // be friendly to oper_parse() @@ -2971,7 +3046,113 @@ // Debug Stuff if (_AD._adl_debug > 1) fprintf(stderr,"Instruction Encode: %s\n", ec_name); - return encrule; + // Set encode class of this instruction. + inst._insencode = encrule; +} + + +//------------------------------constant_parse--------------------------------- +// Parse a constant expression. +void ADLParser::constant_parse(InstructForm& inst) { + // Create a new encoding name based on the name of the instruction + // definition, which should be unique. + const char* prefix = "__constant_"; + char* ec_name = (char*) malloc(strlen(inst._ident) + strlen(prefix) + 1); + sprintf(ec_name, "%s%s", prefix, inst._ident); + + assert(_AD._encode->encClass(ec_name) == NULL, "shouldn't already exist"); + EncClass* encoding = _AD._encode->add_EncClass(ec_name); + encoding->_linenum = linenum(); + + // synthesize the arguments list for the enc_class from the + // arguments to the instruct definition. + const char* param = NULL; + inst._parameters.reset(); + while ((param = inst._parameters.iter()) != NULL) { + OperandForm* opForm = (OperandForm*) inst._localNames[param]; + encoding->add_parameter(opForm->_ident, param); + } + + // Parse the following ( ) expression. + constant_parse_expression(encoding, ec_name); + + // Build an encoding rule which invokes the encoding rule we just + // created, passing all arguments that we received. + InsEncode* encrule = new InsEncode(); // Encode class for instruction + NameAndList* params = encrule->add_encode(ec_name); + inst._parameters.reset(); + while ((param = inst._parameters.iter()) != NULL) { + params->add_entry(param); + } + + // Set encode class of this instruction. + inst._constant = encrule; +} + + +//------------------------------constant_parse_expression---------------------- +void ADLParser::constant_parse_expression(EncClass* encoding, char* ec_name) { + skipws(); + + // Prepend location descriptor, for debugging; cf. ADLParser::find_cpp_block + if (_AD._adlocation_debug) { + encoding->add_code(get_line_string()); + } + + // Start code line. + encoding->add_code(" add_to_constant_table"); + + // Parse everything in ( ) expression. + encoding->add_code("("); + next_char(); // Skip '(' + int parens_depth = 1; + + // Collect the parts of the constant expression. + // (1) strings that are passed through to output + // (2) replacement/substitution variable, preceeded by a '$' + while (parens_depth > 0) { + if (_curchar == '(') { + parens_depth++; + encoding->add_code("("); + next_char(); + } + else if (_curchar == ')') { + parens_depth--; + encoding->add_code(")"); + next_char(); + } + else { + // (1) + // Check if there is a string to pass through to output + char *start = _ptr; // Record start of the next string + while ((_curchar != '$') && (_curchar != '(') && (_curchar != ')')) { + next_char(); + } + // If a string was found, terminate it and record in EncClass + if (start != _ptr) { + *_ptr = '\0'; // Terminate the string + encoding->add_code(start); + } + + // (2) + // If we are at a replacement variable, copy it and record in EncClass. + if (_curchar == '$') { + // Found replacement Variable + char* rep_var = get_rep_var_ident_dup(); + encoding->add_rep_var(rep_var); + } + } + } + + // Finish code line. + encoding->add_code(";"); + + if (_AD._adlocation_debug) { + encoding->add_code(end_line_marker()); + } + + // Debug Stuff + if (_AD._adl_debug > 1) fprintf(stderr, "EncodingClass Form: %s\n", ec_name); } --- old/src/share/vm/adlc/adlparse.hpp 2010-11-12 05:56:25.406497275 -0800 +++ new/src/share/vm/adlc/adlparse.hpp 2010-11-12 05:56:24.996987011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2010, 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 @@ -153,8 +153,13 @@ Attribute *attr_parse(char *ident);// Parse instr/operand attribute rule // Parse instruction encode rule - InsEncode *ins_encode_parse(InstructForm &inst); - InsEncode *ins_encode_parse_block(InstructForm &inst); + void ins_encode_parse(InstructForm &inst); + void ins_encode_parse_block(InstructForm &inst); + void ins_encode_parse_block_impl(InstructForm& inst, EncClass* encoding, char* ec_name); + + void constant_parse(InstructForm& inst); + void constant_parse_expression(EncClass* encoding, char* ec_name); + Opcode *opcode_parse(InstructForm *insr); // Parse instruction opcode char *size_parse(InstructForm *insr); // Parse instruction size Interface *interface_parse(); // Parse operand interface rule --- old/src/share/vm/adlc/archDesc.hpp 2010-11-12 05:56:27.598817033 -0800 +++ new/src/share/vm/adlc/archDesc.hpp 2010-11-12 05:56:27.206982071 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2010, 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 @@ -123,7 +123,6 @@ void chain_rule(FILE *fp, const char *indent, const char *ideal, const Expr *icost, const char *irule, Dict &operands_chained_from, ProductionState &status); - void chain_rule_c(FILE *fp, char *indent, char *ideal, char *irule); // %%%%% TODO: remove this void expand_opclass(FILE *fp, const char *indent, const Expr *cost, const char *result_type, ProductionState &status); Expr *calc_cost(FILE *fp, const char *spaces, MatchList &mList, ProductionState &status); @@ -293,13 +292,18 @@ void buildMachNodeGenerator(FILE *fp_cpp); // Generator for Expand methods for instructions with expand rules - void defineExpand(FILE *fp, InstructForm *node); + void defineExpand (FILE *fp, InstructForm *node); // Generator for Peephole methods for instructions with peephole rules - void definePeephole(FILE *fp, InstructForm *node); + void definePeephole (FILE *fp, InstructForm *node); // Generator for Size methods for instructions - void defineSize(FILE *fp, InstructForm &node); + void defineSize (FILE *fp, InstructForm &node); + +public: + // Generator for EvalConstantValue methods for instructions + void defineEvalConstant(FILE *fp, InstructForm &node); // Generator for Emit methods for instructions - void defineEmit(FILE *fp, InstructForm &node); + void defineEmit (FILE *fp, InstructForm &node); + // Define a MachOper encode method void define_oper_interface(FILE *fp, OperandForm &oper, FormDict &globals, const char *name, const char *encoding); --- old/src/share/vm/adlc/formssel.cpp 2010-11-12 05:56:29.822065231 -0800 +++ new/src/share/vm/adlc/formssel.cpp 2010-11-12 05:56:29.409915389 -0800 @@ -30,11 +30,14 @@ InstructForm::InstructForm(const char *id, bool ideal_only) : _ident(id), _ideal_only(ideal_only), _localNames(cmpstr, hashstr, Form::arena), - _effects(cmpstr, hashstr, Form::arena) { + _effects(cmpstr, hashstr, Form::arena), + _is_mach_constant(false) +{ _ftype = Form::INS; _matrule = NULL; _insencode = NULL; + _constant = NULL; _opcode = NULL; _size = NULL; _attribs = NULL; @@ -58,11 +61,14 @@ InstructForm::InstructForm(const char *id, InstructForm *instr, MatchRule *rule) : _ident(id), _ideal_only(false), _localNames(instr->_localNames), - _effects(instr->_effects) { + _effects(instr->_effects), + _is_mach_constant(false) +{ _ftype = Form::INS; _matrule = rule; _insencode = instr->_insencode; + _constant = instr->_constant; _opcode = instr->_opcode; _size = instr->_size; _attribs = instr->_attribs; @@ -1094,6 +1100,9 @@ else if (is_ideal_nop()) { return "MachNopNode"; } + else if (is_mach_constant()) { + return "MachConstantNode"; + } else if (captures_bottom_type(globals)) { return "MachTypeNode"; } else { @@ -1190,6 +1199,21 @@ // // Generate the format call for the replacement variable void InstructForm::rep_var_format(FILE *fp, const char *rep_var) { + // Handle special constant table variables. + if (strcmp(rep_var, "constanttablebase") == 0) { + fprintf(fp, "char reg[128]; ra->dump_register(in(mach_constant_base_node_input()), reg);\n"); + fprintf(fp, "st->print(\"%%s\");\n"); + return; + } + if (strcmp(rep_var, "constantoffset") == 0) { + fprintf(fp, "st->print(\"#%%d\", constant_offset());\n"); + return; + } + if (strcmp(rep_var, "constantaddress") == 0) { + fprintf(fp, "st->print(\"constant table base + #%%d\", constant_offset());\n"); + return; + } + // Find replacement variable's type const Form *form = _localNames[rep_var]; if (form == NULL) { @@ -1348,6 +1372,7 @@ fprintf(fp,"\nInstruction: %s\n", (_ident?_ident:"")); if (_matrule) _matrule->output(fp); if (_insencode) _insencode->output(fp); + if (_constant) _constant->output(fp); if (_opcode) _opcode->output(fp); if (_attribs) _attribs->output(fp); if (_predicate) _predicate->output(fp); --- old/src/share/vm/adlc/formssel.hpp 2010-11-12 05:56:32.243351370 -0800 +++ new/src/share/vm/adlc/formssel.hpp 2010-11-12 05:56:31.827800859 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2010, 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 @@ -71,15 +71,16 @@ //------------------------------InstructForm----------------------------------- class InstructForm : public Form { private: - bool _ideal_only; // Not a user-defined instruction + bool _ideal_only; // Not a user-defined instruction // Members used for tracking CISC-spilling - uint _cisc_spill_operand;// Which operand may cisc-spill + uint _cisc_spill_operand;// Which operand may cisc-spill void set_cisc_spill_operand(uint op_index) { _cisc_spill_operand = op_index; } - bool _is_cisc_alternate; + bool _is_cisc_alternate; InstructForm *_cisc_spill_alternate;// cisc possible replacement const char *_cisc_reg_mask_name; InstructForm *_short_branch_form; bool _is_short_branch; + bool _is_mach_constant; // true if Node is a MachConstantNode uint _alignment; public: @@ -91,6 +92,7 @@ Opcode *_opcode; // Encoding of the opcode for instruction char *_size; // Size of instruction InsEncode *_insencode; // Encoding class instruction belongs to + InsEncode *_constant; // Encoding class constant value belongs to Attribute *_attribs; // List of Attribute rules Predicate *_predicate; // Predicate test for this instruction FormDict _effects; // Dictionary of effect rules @@ -248,6 +250,9 @@ bool is_short_branch() { return _is_short_branch; } void set_short_branch(bool val) { _is_short_branch = val; } + bool is_mach_constant() const { return _is_mach_constant; } + void set_is_mach_constant(bool x) { _is_mach_constant = x; } + InstructForm *short_branch_form() { return _short_branch_form; } bool has_short_branch_form() { return _short_branch_form != NULL; } // Output short branch prototypes and method bodies --- old/src/share/vm/adlc/output_c.cpp 2010-11-12 05:56:34.647153670 -0800 +++ new/src/share/vm/adlc/output_c.cpp 2010-11-12 05:56:34.240955345 -0800 @@ -1496,8 +1496,8 @@ unsigned i; // Generate Expand function header - fprintf(fp,"MachNode *%sNode::Expand(State *state, Node_List &proj_list, Node* mem) {\n", node->_ident); - fprintf(fp,"Compile* C = Compile::current();\n"); + fprintf(fp, "MachNode* %sNode::Expand(State* state, Node_List& proj_list, Node* mem) {\n", node->_ident); + fprintf(fp, " Compile* C = Compile::current();\n"); // Generate expand code if( node->expands() ) { const char *opid; @@ -1818,6 +1818,12 @@ } } + // If the node is a MachConstantNode, insert the MachConstantBaseNode edge. + // NOTE: this edge must be the last input (see MachConstantNode::mach_constant_base_node_input). + if (node->is_mach_constant()) { + fprintf(fp," add_req(C->mach_constant_base_node());\n"); + } + fprintf(fp,"\n"); if( node->expands() ) { fprintf(fp," return result;\n"); @@ -1924,7 +1930,17 @@ // No state needed. assert( _opclass == NULL, "'primary', 'secondary' and 'tertiary' don't follow operand."); - } else { + } + else if ((strcmp(rep_var, "constanttablebase") == 0) || + (strcmp(rep_var, "constantoffset") == 0) || + (strcmp(rep_var, "constantaddress") == 0)) { + if (!_inst.is_mach_constant()) { + _AD.syntax_err(_encoding._linenum, + "Replacement variable %s not allowed in instruct %s (only in MachConstantNode).\n", + rep_var, _encoding._name); + } + } + else { // Lookup its position in parameter list int param_no = _encoding.rep_var_index(rep_var); if ( param_no == -1 ) { @@ -2380,6 +2396,15 @@ rep_var, _inst._ident, _encoding._name); } } + else if (strcmp(rep_var, "constanttablebase") == 0) { + fprintf(_fp, "as_Register(ra_->get_encode(in(mach_constant_base_node_input())))"); + } + else if (strcmp(rep_var, "constantoffset") == 0) { + fprintf(_fp, "constant_offset()"); + } + else if (strcmp(rep_var, "constantaddress") == 0) { + fprintf(_fp, "InternalAddress(__ code()->consts()->start() + constant_offset())"); + } else { // Lookup its position in parameter list int param_no = _encoding.rep_var_index(rep_var); @@ -2465,37 +2490,39 @@ fprintf(fp,"}\n"); } -void ArchDesc::defineEmit(FILE *fp, InstructForm &inst) { - InsEncode *ins_encode = inst._insencode; +// defineEmit ----------------------------------------------------------------- +void ArchDesc::defineEmit(FILE* fp, InstructForm& inst) { + InsEncode* encode = inst._insencode; // (1) // Output instruction's emit prototype - fprintf(fp,"void %sNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {\n", - inst._ident); + fprintf(fp, "void %sNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {\n", inst._ident); // If user did not define an encode section, // provide stub that does not generate any machine code. - if( (_encode == NULL) || (ins_encode == NULL) ) { + if( (_encode == NULL) || (encode == NULL) ) { fprintf(fp, " // User did not define an encode section.\n"); - fprintf(fp,"}\n"); + fprintf(fp, "}\n"); return; } // Save current instruction's starting address (helps with relocation). - fprintf(fp, " cbuf.set_insts_mark();\n"); + fprintf(fp, " cbuf.set_insts_mark();\n"); - // // // idx0 is only needed for syntactic purposes and only by "storeSSI" - // fprintf( fp, " unsigned idx0 = 0;\n"); + // For MachConstantNodes which are ideal jump nodes, fill the jump table. + if (inst.is_mach_constant() && inst.is_ideal_jump()) { + fprintf(fp, " fill_jump_table_in_constant_table(cbuf, _index2label);\n"); + } // Output each operand's offset into the array of registers. - inst.index_temps( fp, _globalNames ); + inst.index_temps(fp, _globalNames); // Output this instruction's encodings const char *ec_name; bool user_defined = false; - ins_encode->reset(); - while ( (ec_name = ins_encode->encode_class_iter()) != NULL ) { - fprintf(fp, " {"); + encode->reset(); + while ((ec_name = encode->encode_class_iter()) != NULL) { + fprintf(fp, " {\n"); // Output user-defined encoding user_defined = true; @@ -2507,25 +2534,25 @@ abort(); } - if (ins_encode->current_encoding_num_args() != encoding->num_args()) { - globalAD->syntax_err(ins_encode->_linenum, "In %s: passing %d arguments to %s but expecting %d", - inst._ident, ins_encode->current_encoding_num_args(), + if (encode->current_encoding_num_args() != encoding->num_args()) { + globalAD->syntax_err(encode->_linenum, "In %s: passing %d arguments to %s but expecting %d", + inst._ident, encode->current_encoding_num_args(), ec_name, encoding->num_args()); } - DefineEmitState pending(fp, *this, *encoding, *ins_encode, inst ); + DefineEmitState pending(fp, *this, *encoding, *encode, inst); encoding->_code.reset(); encoding->_rep_vars.reset(); // Process list of user-defined strings, // and occurrences of replacement variables. // Replacement Vars are pushed into a list and then output - while ( (ec_code = encoding->_code.iter()) != NULL ) { - if ( ! encoding->_code.is_signal( ec_code ) ) { + while ((ec_code = encoding->_code.iter()) != NULL) { + if (!encoding->_code.is_signal(ec_code)) { // Emit pending code pending.emit(); pending.clear(); // Emit this code section - fprintf(fp,"%s", ec_code); + fprintf(fp, "%s", ec_code); } else { // A replacement variable or one of its subfields // Obtain replacement variable from list @@ -2536,7 +2563,7 @@ // Emit pending code pending.emit(); pending.clear(); - fprintf(fp, "}\n"); + fprintf(fp, " }\n"); } // end while instruction's encodings // Check if user stated which encoding to user @@ -2545,7 +2572,86 @@ } // (3) and (4) - fprintf(fp,"}\n"); + fprintf(fp, "}\n"); +} + +// defineEvalConstant --------------------------------------------------------- +void ArchDesc::defineEvalConstant(FILE* fp, InstructForm& inst) { + InsEncode* encode = inst._constant; + + // (1) + // Output instruction's emit prototype + fprintf(fp, "void %sNode::eval_constant() {\n", inst._ident); + + // For ideal jump nodes, allocate a jump table. + if (inst.is_ideal_jump()) { + fprintf(fp, " allocate_jump_table_in_constant_table();\n"); + } + + // If user did not define an encode section, + // provide stub that does not generate any machine code. + if ((_encode == NULL) || (encode == NULL)) { + fprintf(fp, " // User did not define an encode section.\n"); + fprintf(fp, "}\n"); + return; + } + + // Output this instruction's encodings + const char *ec_name; + bool user_defined = false; + encode->reset(); + while ((ec_name = encode->encode_class_iter()) != NULL) { + fprintf(fp, " {\n"); + // Output user-defined encoding + user_defined = true; + + const char *ec_code = NULL; + const char *ec_rep_var = NULL; + EncClass *encoding = _encode->encClass(ec_name); + if (encoding == NULL) { + fprintf(stderr, "User did not define contents of this encode_class: %s\n", ec_name); + abort(); + } + + if (encode->current_encoding_num_args() != encoding->num_args()) { + globalAD->syntax_err(encode->_linenum, "In %s: passing %d arguments to %s but expecting %d", + inst._ident, encode->current_encoding_num_args(), + ec_name, encoding->num_args()); + } + + DefineEmitState pending(fp, *this, *encoding, *encode, inst); + encoding->_code.reset(); + encoding->_rep_vars.reset(); + // Process list of user-defined strings, + // and occurrences of replacement variables. + // Replacement Vars are pushed into a list and then output + while ((ec_code = encoding->_code.iter()) != NULL) { + if (!encoding->_code.is_signal(ec_code)) { + // Emit pending code + pending.emit(); + pending.clear(); + // Emit this code section + fprintf(fp, "%s", ec_code); + } else { + // A replacement variable or one of its subfields + // Obtain replacement variable from list + ec_rep_var = encoding->_rep_vars.iter(); + pending.add_rep_var(ec_rep_var); + } + } + // Emit pending code + pending.emit(); + pending.clear(); + fprintf(fp, " }\n"); + } // end while instruction's encodings + + // Check if user stated which encoding to user + if (user_defined == false) { + fprintf(fp, " // User did not define which encode class to use.\n"); + } + + // (3) and (4) + fprintf(fp, "}\n"); } // --------------------------------------------------------------------------- @@ -2952,6 +3058,7 @@ // If there are multiple defs/kills, or an explicit expand rule, build rule if( instr->expands() || instr->needs_projections() || instr->has_temps() || + instr->is_mach_constant() || instr->_matrule != NULL && instr->num_opnds() != instr->num_unique_opnds() ) defineExpand(_CPP_EXPAND_file._fp, instr); @@ -3032,8 +3139,9 @@ // Ensure this is a machine-world instruction if ( instr->ideal_only() ) continue; - if (instr->_insencode) defineEmit(fp, *instr); - if (instr->_size) defineSize(fp, *instr); + if (instr->_insencode) defineEmit (fp, *instr); + if (instr->is_mach_constant()) defineEvalConstant(fp, *instr); + if (instr->_size) defineSize (fp, *instr); // side-call to generate output that used to be in the header file: extern void gen_inst_format(FILE *fp, FormDict &globals, InstructForm &oper, bool for_c_file); --- old/src/share/vm/adlc/output_h.cpp 2010-11-12 05:56:37.767152862 -0800 +++ new/src/share/vm/adlc/output_h.cpp 2010-11-12 05:56:37.341588176 -0800 @@ -1550,7 +1550,12 @@ } // virtual functions for encode and format - // + + // Virtual function for evaluating the constant. + if (instr->is_mach_constant()) { + fprintf(fp," virtual void eval_constant();\n"); + } + // Output the opcode function and the encode function here using the // encoding class information in the _insencode slot. if ( instr->_insencode ) { @@ -1752,6 +1757,7 @@ // Virtual methods which are only generated to override base class if( instr->expands() || instr->needs_projections() || instr->has_temps() || + instr->is_mach_constant() || instr->_matrule != NULL && instr->num_opnds() != instr->num_unique_opnds() ) { fprintf(fp," virtual MachNode *Expand(State *state, Node_List &proj_list, Node* mem);\n"); @@ -1780,24 +1786,6 @@ // Declare short branch methods, if applicable instr->declare_short_branch_methods(fp); - // Instructions containing a constant that will be entered into the - // float/double table redefine the base virtual function -#ifdef SPARC - // Sparc doubles entries in the constant table require more space for - // alignment. (expires 9/98) - int table_entries = (3 * instr->num_consts( _globalNames, Form::idealD )) - + instr->num_consts( _globalNames, Form::idealF ); -#else - int table_entries = instr->num_consts( _globalNames, Form::idealD ) - + instr->num_consts( _globalNames, Form::idealF ); -#endif - if( table_entries != 0 ) { - fprintf(fp," virtual int const_size() const {"); - fprintf(fp, " return %d;", table_entries); - fprintf(fp, " }\n"); - } - - // See if there is an "ins_pipe" declaration for this instruction if (instr->_ins_pipe) { fprintf(fp," static const Pipeline *pipeline_class();\n"); --- old/src/share/vm/asm/assembler.hpp 2010-11-12 05:56:40.071714064 -0800 +++ new/src/share/vm/asm/assembler.hpp 2010-11-12 05:56:39.670365705 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2010, 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 @@ -270,7 +270,16 @@ address start_a_const(int required_space, int required_align = sizeof(double)); void end_a_const(); - // fp constants support + // constants support + address long_constant(jlong c) { + address ptr = start_a_const(sizeof(c), sizeof(c)); + if (ptr != NULL) { + *(jlong*)ptr = c; + _code_pos = ptr + sizeof(c); + end_a_const(); + } + return ptr; + } address double_constant(jdouble c) { address ptr = start_a_const(sizeof(c), sizeof(c)); if (ptr != NULL) { @@ -289,6 +298,15 @@ } return ptr; } + address address_constant(address c) { + address ptr = start_a_const(sizeof(c), sizeof(c)); + if (ptr != NULL) { + *(address*)ptr = c; + _code_pos = ptr + sizeof(c); + end_a_const(); + } + return ptr; + } address address_constant(address c, RelocationHolder const& rspec) { address ptr = start_a_const(sizeof(c), sizeof(c)); if (ptr != NULL) { @@ -299,8 +317,6 @@ } return ptr; } - inline address address_constant(Label& L); - inline address address_table_constant(GrowableArray label); // Bootstrapping aid to cope with delayed determination of constants. // Returns a static address which will eventually contain the constant. --- old/src/share/vm/asm/assembler.inline.hpp 2010-11-12 05:56:42.288324651 -0800 +++ new/src/share/vm/asm/assembler.inline.hpp 2010-11-12 05:56:41.897378083 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2010, 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 @@ -105,31 +105,3 @@ inline void Label::bind_loc(int pos, int sect) { bind_loc(CodeBuffer::locator(pos, sect)); } - -address AbstractAssembler::address_constant(Label& L) { - address c = NULL; - address ptr = start_a_const(sizeof(c), sizeof(c)); - if (ptr != NULL) { - relocate(Relocation::spec_simple(relocInfo::internal_word_type)); - *(address*)ptr = c = code_section()->target(L, ptr); - _code_pos = ptr + sizeof(c); - end_a_const(); - } - return ptr; -} - -address AbstractAssembler::address_table_constant(GrowableArray labels) { - int addressSize = sizeof(address); - int sizeLabel = addressSize * labels.length(); - address ptr = start_a_const(sizeLabel, addressSize); - - if (ptr != NULL) { - address *labelLoc = (address*)ptr; - for (int i=0; i < labels.length(); i++) { - emit_address(code_section()->target(*labels.at(i), (address)&labelLoc[i])); - code_section()->relocate((address)&labelLoc[i], relocInfo::internal_word_type); - } - end_a_const(); - } - return ptr; -} --- old/src/share/vm/compiler/disassembler.cpp 2010-11-12 05:56:44.481936354 -0800 +++ new/src/share/vm/compiler/disassembler.cpp 2010-11-12 05:56:44.089871526 -0800 @@ -446,5 +446,18 @@ env.set_total_ticks(total_bucket_count); } + // Print constant table. + if (nm->consts_size() > 0) { + nm->print_nmethod_labels(env.output(), nm->consts_begin()); + int offset = 0; + for (address p = nm->consts_begin(); p < nm->consts_end(); p += 4, offset += 4) { + if ((offset % 8) == 0) { + env.output()->print_cr(" " INTPTR_FORMAT " (offset: %4d): " PTR32_FORMAT " " PTR64_FORMAT, (intptr_t) p, offset, *((int32_t*) p), *((int64_t*) p)); + } else { + env.output()->print_cr(" " INTPTR_FORMAT " (offset: %4d): " PTR32_FORMAT, (intptr_t) p, offset, *((int32_t*) p)); + } + } + } + env.decode_instructions(p, end); } --- old/src/share/vm/opto/c2_globals.hpp 2010-11-12 05:56:46.859485337 -0800 +++ new/src/share/vm/opto/c2_globals.hpp 2010-11-12 05:56:46.422719044 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2010, 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 @@ -264,6 +264,9 @@ develop(bool, SparcV9RegsHiBitsZero, true, \ "Assume Sparc V9 I&L registers on V8+ systems are zero-extended") \ \ + product(bool, UseRDPCForConstantTableBase, false, \ + "Use Sparc RDPC instruction for the constant table base.") \ + \ develop(intx, PrintIdealGraphLevel, 0, \ "Print ideal graph to XML file / network interface. " \ "By default attempts to connect to the visualizer on a socket.") \ --- old/src/share/vm/opto/compile.cpp 2010-11-12 05:56:49.289075661 -0800 +++ new/src/share/vm/opto/compile.cpp 2010-11-12 05:56:48.832509990 -0800 @@ -25,6 +25,18 @@ #include "incls/_precompiled.incl" #include "incls/_compile.cpp.incl" + +// -------------------- Compile::mach_constant_base_node ----------------------- +// Constant table base node singleton. +MachConstantBaseNode* Compile::mach_constant_base_node() { + if (_mach_constant_base_node == NULL) { + _mach_constant_base_node = new (C) MachConstantBaseNode(); + _mach_constant_base_node->set_req(0, C->root()); + } + return _mach_constant_base_node; +} + + /// Support for intrinsics. // Return the index at which m must be inserted (or already exists). @@ -382,13 +394,14 @@ } -void Compile::init_scratch_buffer_blob() { - if( scratch_buffer_blob() != NULL ) return; +void Compile::init_scratch_buffer_blob(int const_size) { + if (scratch_buffer_blob() != NULL) return; // Construct a temporary CodeBuffer to have it construct a BufferBlob // Cache this BufferBlob for this compile. ResourceMark rm; - int size = (MAX_inst_size + MAX_stubs_size + MAX_const_size); + _scratch_const_size = const_size; + int size = (MAX_inst_size + MAX_stubs_size + _scratch_const_size); BufferBlob* blob = BufferBlob::create("Compile::scratch_buffer", size); // Record the buffer blob for next time. set_scratch_buffer_blob(blob); @@ -405,9 +418,19 @@ } +void Compile::clear_scratch_buffer_blob() { + assert(scratch_buffer_blob(), "no BufferBlob set"); + set_scratch_buffer_blob(NULL); + set_scratch_locs_memory(NULL); +} + + //-----------------------scratch_emit_size------------------------------------- // Helper function that computes size by emitting code uint Compile::scratch_emit_size(const Node* n) { + // Start scratch_emit_size section. + set_in_scratch_emit_size(true); + // Emit into a trash buffer and count bytes emitted. // This is a pretty expensive way to compute a size, // but it works well enough if seldom used. @@ -426,13 +449,20 @@ address blob_end = (address)locs_buf; assert(blob->content_contains(blob_end), "sanity"); CodeBuffer buf(blob_begin, blob_end - blob_begin); - buf.initialize_consts_size(MAX_const_size); + buf.initialize_consts_size(_scratch_const_size); buf.initialize_stubs_size(MAX_stubs_size); assert(locs_buf != NULL, "sanity"); - int lsize = MAX_locs_size / 2; - buf.insts()->initialize_shared_locs(&locs_buf[0], lsize); - buf.stubs()->initialize_shared_locs(&locs_buf[lsize], lsize); + int lsize = MAX_locs_size / 3; + buf.consts()->initialize_shared_locs(&locs_buf[lsize * 0], lsize); + buf.insts()->initialize_shared_locs( &locs_buf[lsize * 1], lsize); + buf.stubs()->initialize_shared_locs( &locs_buf[lsize * 2], lsize); + + // Do the emission. n->emit(buf, this->regalloc()); + + // End scratch_emit_size section. + set_in_scratch_emit_size(false); + return buf.insts_size(); } @@ -466,10 +496,13 @@ _orig_pc_slot(0), _orig_pc_slot_offset_in_bytes(0), _has_method_handle_invokes(false), + _mach_constant_base_node(NULL), _node_bundling_limit(0), _node_bundling_base(NULL), _java_calls(0), _inner_loops(0), + _scratch_const_size(-1), + _in_scratch_emit_size(false), #ifndef PRODUCT _trace_opto_output(TraceOptoOutput || method()->has_option("TraceOptoOutput")), _printer(IdealGraphPrinter::printer()), @@ -733,6 +766,7 @@ _failure_reason(NULL), _code_buffer("Compile::Fill_buffer"), _has_method_handle_invokes(false), + _mach_constant_base_node(NULL), _node_bundling_limit(0), _node_bundling_base(NULL), _java_calls(0), --- old/src/share/vm/opto/compile.hpp 2010-11-12 05:56:51.694555571 -0800 +++ new/src/share/vm/opto/compile.hpp 2010-11-12 05:56:51.302209649 -0800 @@ -30,6 +30,7 @@ class InlineTree; class Int_Array; class Matcher; +class MachConstantBaseNode; class MachNode; class MachSafePointNode; class Node; @@ -194,6 +195,9 @@ Node* _recent_alloc_obj; Node* _recent_alloc_ctl; + MachConstantBaseNode* _mach_constant_base_node; // Constant table base node singleton. + + // Blocked array of debugging and profiling information, // tracked per node. enum { _log2_node_notes_block_size = 8, @@ -254,6 +258,8 @@ static int _CompiledZap_count; // counter compared against CompileZap[First/Last] BufferBlob* _scratch_buffer_blob; // For temporary code buffers. relocInfo* _scratch_locs_memory; // For temporary code buffers. + int _scratch_const_size; // For temporary code buffers. + bool _in_scratch_emit_size; // true when in scratch_emit_size. public: // Accessors @@ -436,6 +442,9 @@ _recent_alloc_obj = obj; } + MachConstantBaseNode* mach_constant_base_node(); + bool has_mach_constant_base_node() const { return _mach_constant_base_node != NULL; } + // Handy undefined Node Node* top() const { return _top; } @@ -587,13 +596,16 @@ Dependencies* dependencies() { return env()->dependencies(); } static int CompiledZap_count() { return _CompiledZap_count; } BufferBlob* scratch_buffer_blob() { return _scratch_buffer_blob; } - void init_scratch_buffer_blob(); + void init_scratch_buffer_blob(int const_size); + void clear_scratch_buffer_blob(); void set_scratch_buffer_blob(BufferBlob* b) { _scratch_buffer_blob = b; } relocInfo* scratch_locs_memory() { return _scratch_locs_memory; } void set_scratch_locs_memory(relocInfo* b) { _scratch_locs_memory = b; } // emit to scratch blob, report resulting size uint scratch_emit_size(const Node* n); + void set_in_scratch_emit_size(bool x) { _in_scratch_emit_size = x; } + bool in_scratch_emit_size() const { return _in_scratch_emit_size; } enum ScratchBufferBlob { MAX_inst_size = 1024, @@ -674,7 +686,7 @@ void Fill_buffer(); // Determine which variable sized branches can be shortened - void Shorten_branches(Label *labels, int& code_size, int& reloc_size, int& stub_size, int& const_size); + void Shorten_branches(Label *labels, int& code_size, int& reloc_size, int& stub_size); // Compute the size of first NumberOfLoopInstrToAlign instructions // at the head of a loop. --- old/src/share/vm/opto/gcm.cpp 2010-11-12 05:56:53.916790779 -0800 +++ new/src/share/vm/opto/gcm.cpp 2010-11-12 05:56:53.522710831 -0800 @@ -66,7 +66,7 @@ assert(in0 != NULL, "Only control-dependent"); const Node *p = in0->is_block_proj(); if (p != NULL && p != n) { // Control from a block projection? - assert(!n->pinned() || n->is_SafePointScalarObject(), "only SafePointScalarObject pinned node is expected here"); + //assert(!n->pinned() || n->is_SafePointScalarObject(), "only SafePointScalarObject pinned node is expected here"); // Find trailing Region Block *pb = _bbs[in0->_idx]; // Block-projection already has basic block uint j = 0; --- old/src/share/vm/opto/machnode.cpp 2010-11-12 05:56:56.188698610 -0800 +++ new/src/share/vm/opto/machnode.cpp 2010-11-12 05:56:55.779115321 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2010, 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 @@ -487,6 +487,205 @@ } #endif + +//============================================================================= +// Two Constant's are equal when the type and the value are equal. +bool MachConstantBaseNode::Constant::operator==(const Constant& other) { + if (type() != other.type() ) return false; + if (can_be_reused() != other.can_be_reused()) return false; + // For floating point values we compare the bit pattern. + switch (type()) { + case T_FLOAT: return (_value.i == other._value.i); + case T_LONG: + case T_DOUBLE: return (_value.j == other._value.j); + case T_OBJECT: + case T_ADDRESS: return (_value.l == other._value.l); + case T_VOID: return (_value.l == other._value.l); // jump-table entries + default: ShouldNotReachHere(); + } + return false; +} + +int MachConstantBaseNode::add_constant(Constant& con) { + if (con.can_be_reused()) { + int idx = _constants.find(con); + if (idx != -1 && _constants.at(idx).can_be_reused()) { + return idx; + } + } + int idx = _constants.append(con); + return idx; +} + +// 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. + case T_VOID: + case T_ADDRESS: + case T_OBJECT: return sizeof(jobject); + } + + ShouldNotReachHere(); + return -1; +} + +int MachConstantBaseNode::calculate_constant_table_size() { + int size = 0; + 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. + + // Align size for type and add type size; + int typesize = type_to_size_in_bytes(con.type()); + size = align_size_up(size, typesize) + typesize; + } + } + + // Align up to the next section start, which is insts (see + // CodeBuffer::align_at_start). + return align_size_up(size, CodeEntryAlignment); +} + +void MachConstantBaseNode::emit_constant_table(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(); + } + assert(constant_addr != NULL, "consts section too small"); + con.set_offset(constant_addr - _masm.code()->consts()->start()); + _constants.at_put(i, con); + } + } +} + +int MachConstantBaseNode::find_constant_offset(Constant& con) const { + int idx = _constants.find(con); + assert(idx != -1, "constant must be in constant table"); + int offset = _constants.at(idx).offset(); + return offset; +} + + +//============================================================================= +void MachConstantNode::add_to_constant_table(BasicType type, jvalue value) { + MachConstantBaseNode* base = Compile::current()->mach_constant_base_node(); + _constant = MachConstantBaseNode::Constant(type, value); + (void) base->add_constant(_constant); +} + +void MachConstantNode::add_to_constant_table(MachOper* oper) { + jvalue value; + BasicType type = oper->type()->basic_type(); + switch (type) { + case T_LONG: value.j = oper->constantL(); break; + case T_FLOAT: value.f = oper->constantF(); break; + case T_DOUBLE: value.d = oper->constantD(); break; + case T_OBJECT: + case T_ADDRESS: value.l = (jobject) oper->constant(); break; + default: ShouldNotReachHere(); + } + add_to_constant_table(type, value); +} + +void MachConstantNode::allocate_jump_table_in_constant_table() { + MachConstantBaseNode* base = Compile::current()->mach_constant_base_node(); + jvalue value; + // We can use the 'this' 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 table is filled (means the + // MachNode pointers do not change anymore). + value.l = (jobject) this; + _constant = MachConstantBaseNode::Constant(T_VOID, value, false); // Labels of a jump-table cannot be reused. + for (uint i = 0; i < outcnt(); i++) { + (void) base->add_constant(_constant); + } +} + +void MachConstantNode::fill_jump_table_in_constant_table(CodeBuffer& cb, GrowableArray labels) const { + // If called from Compile::scratch_emit_size do nothing. + if (Compile::current()->in_scratch_emit_size()) return; + + assert(labels.is_nonempty(), "must be"); + assert((uint) labels.length() == outcnt(), err_msg("must be equal: %d == %d", labels.length(), outcnt())); + + // Since constant_offset() also contains table_base_offset() we need + // to subtract the table_base_offset() to get the plain offset into + // the constant table. + MachConstantBaseNode* base = Compile::current()->mach_constant_base_node(); + int offset = constant_offset() - base->table_base_offset(); + + MacroAssembler _masm(&cb); + address* jump_table_base = (address*) (_masm.code()->consts()->start() + offset); + + for (int i = 0; i < labels.length(); i++) { + address* constant_addr = &jump_table_base[i]; + assert(*constant_addr == (address) this, "all jump-table entries must contain 'this' value"); + *constant_addr = cb.consts()->target(*labels.at(i), (address) constant_addr); + cb.consts()->relocate((address) constant_addr, relocInfo::internal_word_type); + } +} + +int MachConstantNode::constant_offset() { + int offset = _constant.offset(); + // Bind the offset lazily. + if (offset == -1) { + MachConstantBaseNode* base = Compile::current()->mach_constant_base_node(); + offset = base->table_base_offset() + base->find_constant_offset(_constant); + _constant.set_offset(offset); + } + return offset; +} + + //============================================================================= #ifndef PRODUCT void MachNullCheckNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { --- old/src/share/vm/opto/machnode.hpp 2010-11-12 05:56:58.414280074 -0800 +++ new/src/share/vm/opto/machnode.hpp 2010-11-12 05:56:58.021319476 -0800 @@ -222,9 +222,6 @@ // Return number of relocatable values contained in this instruction virtual int reloc() const { return 0; } - // Return number of words used for double constants in this instruction - virtual int const_size() const { return 0; } - // Hash and compare over operands. Used to do GVN on machine Nodes. virtual uint hash() const; virtual uint cmp( const Node &n ) const; @@ -339,6 +336,137 @@ #endif }; +//------------------------------MachConstantBaseNode-------------------------- +// Machine node that represents the base address of the constant +// table. +class MachConstantBaseNode : public MachIdealNode { +public: + class Constant { + private: + BasicType _type; + jvalue _value; + int _offset; // offset of this constant (in bytes) relative to the constant table base. + 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) : + _type(type), + _value(value), + _offset(-1), + _can_be_reused(can_be_reused) + {} + + bool operator==(const Constant& other); + + BasicType type() const { return _type; } + + jlong get_jlong() const { return _value.j; } + jfloat get_jfloat() const { return _value.f; } + jdouble get_jdouble() const { return _value.d; } + jobject get_jobject() const { return _value.l; } + + int offset() const { return _offset; } + void set_offset(int offset) { _offset = offset; } + + bool can_be_reused() const { return _can_be_reused; } + }; + +private: + GrowableArray _constants; // Constant table of this node. + int _table_base_offset; // Offset of the table base that gets added to the constant offsets. + static const RegMask& _out_RegMask; // We need the out_RegMask statically in MachConstantNode::in_RegMask(). + +protected: + void set_table_base_offset(int x) { _table_base_offset = x; } + // MachConstantBaseNode::emit is const but we need to modify the object. + void set_table_base_offset(int x) const { ((MachConstantBaseNode*) this)->set_table_base_offset(x); } + + void emit_constant_table(CodeBuffer& cb); + void emit_constant_table(CodeBuffer& cb) const { ((MachConstantBaseNode*) this)->emit_constant_table(cb); } + + // Returns the offset of the last entry (the top) of the constant table. + int top_constant_offset() const { assert(_constants.top().offset() != -1, "constant not yet bound"); return _constants.top().offset(); } + +public: + MachConstantBaseNode() : + MachIdealNode(), + _table_base_offset(-1) // We can use -1 here since the constant table is always bigger than 2 bytes (-(size / 2), see MachConstantBaseNode::emit). + { + init_class_id(Class_MachConstantBase); + add_req(NULL); + } + virtual const class Type* bottom_type() const { return TypeRawPtr::NOTNULL; } + virtual uint ideal_reg() const { return Op_RegP; } + virtual uint oper_input_base() const { return 1; } + + virtual void emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const; + virtual uint size(PhaseRegAlloc* ra_) const; + virtual bool pinned() const { return true; } + + static const RegMask& static_out_RegMask() { return _out_RegMask; } + virtual const RegMask& out_RegMask() const { return static_out_RegMask(); } + +#ifndef PRODUCT + virtual const char* Name() const { return "MachConstantBaseNode"; } + virtual void format(PhaseRegAlloc*, outputStream* st) const; +#endif + + int table_base_offset() const { assert(_table_base_offset != -1, "table base offset not yet set"); return _table_base_offset; } + + int add_constant(Constant& con); + int calculate_constant_table_size(); + int find_constant_offset(Constant& con) const; +}; + +//------------------------------MachConstantNode------------------------------- +// Machine node that holds a constant which is stored in the constant +// table. +class MachConstantNode : public MachNode { +private: + MachConstantBaseNode::Constant _constant; + +public: + MachConstantNode() : MachNode() { + init_class_id(Class_MachConstant); + } + + virtual void eval_constant() { +#ifdef ASSERT + tty->print("missing MachConstantNode eval_constant function: "); + dump(); +#endif + ShouldNotCallThis(); + } + + virtual const RegMask &in_RegMask(uint idx) const { + if (idx == mach_constant_base_node_input()) + return MachConstantBaseNode::static_out_RegMask(); + return MachNode::in_RegMask(idx); + } + + // Input edge of MachConstantBaseNode. + uint mach_constant_base_node_input() const { return req() - 1; } + int constant_offset(); + int constant_offset() const { return ((MachConstantNode*) this)->constant_offset(); } + +protected: + void add_to_constant_table(BasicType type, jvalue value); + void add_to_constant_table(MachOper* oper); + void add_to_constant_table(jfloat f) { + jvalue value; value.f = f; + add_to_constant_table(T_FLOAT, value); + } + void add_to_constant_table(jdouble d) { + jvalue value; value.d = d; + add_to_constant_table(T_DOUBLE, value); + } + + // Jump table + void allocate_jump_table_in_constant_table(); + void fill_jump_table_in_constant_table(CodeBuffer& cb, GrowableArray labels) const; +}; + //------------------------------MachUEPNode----------------------------------- // Machine Unvalidated Entry Point Node class MachUEPNode : public MachIdealNode { --- old/src/share/vm/opto/node.hpp 2010-11-12 05:57:00.706314770 -0800 +++ new/src/share/vm/opto/node.hpp 2010-11-12 05:57:00.266706750 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2010, 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 @@ -73,6 +73,8 @@ class MachCallNode; class MachCallRuntimeNode; class MachCallStaticJavaNode; +class MachConstantBaseNode; +class MachConstantNode; class MachIfNode; class MachNode; class MachNullCheckNode; @@ -558,10 +560,12 @@ DEFINE_CLASS_ID(MachCallDynamicJava, MachCallJava, 1) DEFINE_CLASS_ID(MachCallRuntime, MachCall, 1) DEFINE_CLASS_ID(MachCallLeaf, MachCallRuntime, 0) - DEFINE_CLASS_ID(MachSpillCopy, Mach, 1) - DEFINE_CLASS_ID(MachNullCheck, Mach, 2) - DEFINE_CLASS_ID(MachIf, Mach, 3) - DEFINE_CLASS_ID(MachTemp, Mach, 4) + DEFINE_CLASS_ID(MachSpillCopy, Mach, 1) + DEFINE_CLASS_ID(MachNullCheck, Mach, 2) + DEFINE_CLASS_ID(MachIf, Mach, 3) + DEFINE_CLASS_ID(MachTemp, Mach, 4) + DEFINE_CLASS_ID(MachConstantBase, Mach, 5) + DEFINE_CLASS_ID(MachConstant, Mach, 6) DEFINE_CLASS_ID(Proj, Node, 2) DEFINE_CLASS_ID(CatchProj, Proj, 0) @@ -726,6 +730,8 @@ DEFINE_CLASS_QUERY(MachCallLeaf) DEFINE_CLASS_QUERY(MachCallRuntime) DEFINE_CLASS_QUERY(MachCallStaticJava) + DEFINE_CLASS_QUERY(MachConstantBase) + DEFINE_CLASS_QUERY(MachConstant) DEFINE_CLASS_QUERY(MachIf) DEFINE_CLASS_QUERY(MachNullCheck) DEFINE_CLASS_QUERY(MachReturn) --- old/src/share/vm/opto/output.cpp 2010-11-12 05:57:03.166774399 -0800 +++ new/src/share/vm/opto/output.cpp 2010-11-12 05:57:02.739700640 -0800 @@ -45,11 +45,6 @@ // RootNode goes assert( _cfg->_broot->_nodes.size() == 0, "" ); - // Initialize the space for the BufferBlob used to find and verify - // instruction size in MachNode::emit_size() - init_scratch_buffer_blob(); - if (failing()) return; // Out of memory - // The number of new nodes (mostly MachNop) is proportional to // the number of java calls and inner loops which are aligned. if ( C->check_node_count((NodeLimitFudgeFactor + C->java_calls()*3 + @@ -317,7 +312,7 @@ //----------------------Shorten_branches--------------------------------------- // The architecture description provides short branch variants for some long // branch instructions. Replace eligible long branches with short branches. -void Compile::Shorten_branches(Label *labels, int& code_size, int& reloc_size, int& stub_size, int& const_size) { +void Compile::Shorten_branches(Label *labels, int& code_size, int& reloc_size, int& stub_size) { // fill in the nop array for bundling computations MachNode *_nop_list[Bundle::_nop_count]; @@ -337,12 +332,11 @@ // Size in bytes of all relocation entries, including those in local stubs. // Start with 2-bytes of reloc info for the unvalidated entry point reloc_size = 1; // Number of relocation entries - const_size = 0; // size of fp constants in words // Make three passes. The first computes pessimistic blk_starts, - // relative jmp_end, reloc_size and const_size information. - // The second performs short branch substitution using the pessimistic - // sizing. The third inserts nops where needed. + // relative jmp_end and reloc_size information. The second performs + // short branch substitution using the pessimistic sizing. The + // third inserts nops where needed. Node *nj; // tmp @@ -365,7 +359,6 @@ MachNode *mach = nj->as_Mach(); blk_size += (mach->alignment_required() - 1) * relocInfo::addr_unit(); // assume worst case padding reloc_size += mach->reloc(); - const_size += mach->const_size(); if( mach->is_MachCall() ) { MachCallNode *mcall = mach->as_MachCall(); // This destination address is NOT PC-relative @@ -382,10 +375,6 @@ if (min_offset_from_last_call == 0) { blk_size += nop_size; } - } else if (mach->ideal_Opcode() == Op_Jump) { - const_size += b->_num_succs; // Address table size - // The size is valid even for 64 bit since it is - // multiplied by 2*jintSize on this method exit. } } min_offset_from_last_call += inst_size; @@ -546,10 +535,6 @@ // a relocation index. // The CodeBuffer will expand the locs array if this estimate is too low. reloc_size *= 10 / sizeof(relocInfo); - - // Adjust const_size to number of bytes - const_size *= 2*jintSize; // both float and double take two words per entry - } //------------------------------FillLocArray----------------------------------- @@ -1086,10 +1071,42 @@ blk_labels[i].init(); } + if (has_mach_constant_base_node()) { + // Fill the constant table. + // Note: This must happen before Shorten_branches. + for (i = 0; i < _cfg->_num_blocks; i++) { + Block* b = _cfg->_blocks[i]; + + for (uint j = 0; j < b->_nodes.size(); j++) { + Node* n = b->_nodes[j]; + + if (n->is_Mach()) { + MachNode *mach = n->as_Mach(); + + // If the MachNode is a MachConstantNode evaluate the + // constant value section. + if (mach->is_MachConstant()) { + MachConstantNode* machcon = mach->as_MachConstant(); + machcon->eval_constant(); + } + } + } + } + + // Calculate the size of the constant table (including the padding + // to the next section). + const_req = mach_constant_base_node()->calculate_constant_table_size(); + } + + // Initialize the space for the BufferBlob used to find and verify + // instruction size in MachNode::emit_size() + init_scratch_buffer_blob(const_req); + if (failing()) return; // Out of memory + // If this machine supports different size branch offsets, then pre-compute // the length of the blocks if( _matcher->is_short_branch_offset(-1, 0) ) { - Shorten_branches(blk_labels, code_req, locs_req, stub_req, const_req); + Shorten_branches(blk_labels, code_req, locs_req, stub_req); labels_not_set = false; } @@ -1105,12 +1122,12 @@ code_req = const_req = stub_req = exception_handler_req = deopt_handler_req = 0x10; // force expansion int total_req = + const_req + code_req + pad_req + stub_req + exception_handler_req + - deopt_handler_req + // deopt handler - const_req; + deopt_handler_req; // deopt handler if (has_method_handle_invokes()) total_req += deopt_handler_req; // deopt MH handler @@ -1180,12 +1197,13 @@ cb->flush_bundle(true); // Define the label at the beginning of the basic block - if( labels_not_set ) - MacroAssembler(cb).bind( blk_labels[b->_pre_order] ); - - else - assert( blk_labels[b->_pre_order].loc_pos() == cb->insts_size(), - "label position does not match code offset" ); + if (labels_not_set) { + MacroAssembler(cb).bind(blk_labels[b->_pre_order]); + } else { + assert(blk_labels[b->_pre_order].loc_pos() == cb->insts_size(), + err_msg("label position does not match code offset: %d != %d", + blk_labels[b->_pre_order].loc_pos(), cb->insts_size())); + } uint last_inst = b->_nodes.size(); @@ -1702,9 +1720,17 @@ // Create a data structure for all the scheduling information Scheduling scheduling(Thread::current()->resource_area(), *this); + // Initialize the space for the BufferBlob used to find and verify + // instruction size in MachNode::emit_size() + init_scratch_buffer_blob(MAX_const_size); + if (failing()) return; // Out of memory + // Walk backwards over each basic block, computing the needed alignment // Walk over all the basic blocks scheduling.DoScheduling(); + + // Clear the BufferBlob used for scheduling. + clear_scratch_buffer_blob(); } //------------------------------ComputeLocalLatenciesForward------------------- --- old/src/share/vm/opto/postaloc.cpp 2010-11-12 05:57:05.492713397 -0800 +++ new/src/share/vm/opto/postaloc.cpp 2010-11-12 05:57:05.090365331 -0800 @@ -198,6 +198,19 @@ // then reloaded BUT survives in a register the whole way. Node *val = skip_copies(n->in(k)); + if (val == x && nk_idx != 0 && + regnd[nk_reg] != NULL && regnd[nk_reg] != x && + n2lidx(x) == n2lidx(regnd[nk_reg])) { + // When rematerialzing nodes and stretching lifetimes, the + // allocator will reuse the original def for multidef LRG instead + // of the current reaching def because it can't know it's safe to + // do so. After allocation completes if they are in the same LRG + // then it should use the current reaching def instead. + n->set_req(k, regnd[nk_reg]); + blk_adjust += yank_if_dead(val, current_block, &value, ®nd); + val = skip_copies(n->in(k)); + } + if( val == x ) return blk_adjust; // No progress? bool single = is_single_register(val->ideal_reg()); --- old/src/share/vm/utilities/debug.cpp 2010-11-12 05:57:07.703271285 -0800 +++ new/src/share/vm/utilities/debug.cpp 2010-11-12 05:57:07.311202329 -0800 @@ -361,8 +361,14 @@ extern "C" void disnm(intptr_t p) { Command c("disnm"); CodeBlob* cb = CodeCache::find_blob((address) p); - cb->print(); - Disassembler::decode(cb); + nmethod* nm = cb->as_nmethod_or_null(); + if (nm) { + nm->print(); + Disassembler::decode(nm); + } else { + cb->print(); + Disassembler::decode(cb); + } }