# HG changeset patch # User coleenp # Date 1310869299 14400 # Node ID bcc6475bc68f11d240243856d2808c29014aa1b7 # Parent 1f4f4ae84625832048500c3a0832d41496958d95# Parent 5447b2c582ad21d251a9314cc74684dd5e9a7dab Merge diff -r 5447b2c582ad -r bcc6475bc68f src/cpu/sparc/vm/assembler_sparc.hpp --- a/src/cpu/sparc/vm/assembler_sparc.hpp Thu Jul 07 22:34:34 2011 -0400 +++ b/src/cpu/sparc/vm/assembler_sparc.hpp Sat Jul 16 22:21:39 2011 -0400 @@ -716,6 +716,8 @@ casa_op3 = 0x3c, casxa_op3 = 0x3e, + mftoi_op3 = 0x36, + alt_bit_op3 = 0x10, cc_bit_op3 = 0x10 }; @@ -750,7 +752,13 @@ fitod_opf = 0xc8, fstod_opf = 0xc9, fstoi_opf = 0xd1, - fdtoi_opf = 0xd2 + fdtoi_opf = 0xd2, + + mdtox_opf = 0x110, + mstouw_opf = 0x111, + mstosw_opf = 0x113, + mxtod_opf = 0x118, + mwtos_opf = 0x119 }; enum RCondition { rc_z = 1, rc_lez = 2, rc_lz = 3, rc_nz = 5, rc_gz = 6, rc_gez = 7 }; @@ -1061,6 +1069,9 @@ return x & ((1 << 10) - 1); } + // instruction only in VIS3 + static void vis3_only() { assert( VM_Version::has_vis3(), "This instruction only works on SPARC with VIS3"); } + // instruction only in v9 static void v9_only() { assert( VM_Version::v9_instructions_work(), "This instruction only works on SPARC V9"); } @@ -1247,8 +1258,8 @@ // pp 159 - void ftox( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { v9_only(); emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x80 + w) | fs2(s, w)); } - void ftoi( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0xd0 + w) | fs2(s, w)); } + void ftox( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { v9_only(); emit_long( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(fpop1_op3) | opf(0x80 + w) | fs2(s, w)); } + void ftoi( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { emit_long( op(arith_op) | fd(d, FloatRegisterImpl::S) | op3(fpop1_op3) | opf(0xd0 + w) | fs2(s, w)); } // pp 160 @@ -1256,8 +1267,8 @@ // pp 161 - void fxtof( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { v9_only(); emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x80 + w*4) | fs2(s, w)); } - void fitof( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0xc0 + w*4) | fs2(s, w)); } + void fxtof( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { v9_only(); emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x80 + w*4) | fs2(s, FloatRegisterImpl::D)); } + void fitof( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0xc0 + w*4) | fs2(s, FloatRegisterImpl::S)); } // pp 162 @@ -1709,6 +1720,19 @@ inline void wrasi( Register d) { v9_only(); emit_long( op(arith_op) | rs1(d) | op3(wrreg_op3) | u_field(3, 29, 25)); } inline void wrfprs( Register d) { v9_only(); emit_long( op(arith_op) | rs1(d) | op3(wrreg_op3) | u_field(6, 29, 25)); } + + // VIS3 instructions + + void movstosw( FloatRegister s, Register d ) { vis3_only(); emit_long( op(arith_op) | rd(d) | op3(mftoi_op3) | opf(mstosw_opf) | fs2(s, FloatRegisterImpl::S)); } + void movstouw( FloatRegister s, Register d ) { vis3_only(); emit_long( op(arith_op) | rd(d) | op3(mftoi_op3) | opf(mstouw_opf) | fs2(s, FloatRegisterImpl::S)); } + void movdtox( FloatRegister s, Register d ) { vis3_only(); emit_long( op(arith_op) | rd(d) | op3(mftoi_op3) | opf(mdtox_opf) | fs2(s, FloatRegisterImpl::D)); } + + void movwtos( Register s, FloatRegister d ) { vis3_only(); emit_long( op(arith_op) | fd(d, FloatRegisterImpl::S) | op3(mftoi_op3) | opf(mwtos_opf) | rs2(s)); } + void movxtod( Register s, FloatRegister d ) { vis3_only(); emit_long( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(mftoi_op3) | opf(mxtod_opf) | rs2(s)); } + + + + // For a given register condition, return the appropriate condition code // Condition (the one you would use to get the same effect after "tst" on // the target register.) diff -r 5447b2c582ad -r bcc6475bc68f src/cpu/sparc/vm/sparc.ad --- a/src/cpu/sparc/vm/sparc.ad Thu Jul 07 22:34:34 2011 -0400 +++ b/src/cpu/sparc/vm/sparc.ad Sat Jul 16 22:21:39 2011 -0400 @@ -425,7 +425,7 @@ // but they are used with the "Op_RegD" type, and always occur in even/odd pairs. // This class is usable for mis-aligned loads as happen in I2C adapters. reg_class dflt_low_reg(R_F0, R_F1, R_F2, R_F3, R_F4, R_F5, R_F6, R_F7, R_F8, R_F9, R_F10,R_F11,R_F12,R_F13,R_F14,R_F15, - R_F16,R_F17,R_F18,R_F19,R_F20,R_F21,R_F22,R_F23,R_F24,R_F25,R_F26,R_F27,R_F28,R_F29,R_F30,R_F31 ); + R_F16,R_F17,R_F18,R_F19,R_F20,R_F21,R_F22,R_F23,R_F24,R_F25,R_F26,R_F27,R_F28,R_F29); %} //----------DEFINITION BLOCK--------------------------------------------------- @@ -1326,17 +1326,17 @@ // -------------------------------------- // Check for float->int copy; requires a trip through memory - if( src_first_rc == rc_float && dst_first_rc == rc_int ) { + if (src_first_rc == rc_float && dst_first_rc == rc_int && UseVIS < 3) { int offset = frame::register_save_words*wordSize; - if( cbuf ) { + if (cbuf) { emit3_simm13( *cbuf, Assembler::arith_op, R_SP_enc, Assembler::sub_op3, R_SP_enc, 16 ); impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stf_op3 ,"STF ",size, st); impl_helper(this,cbuf,ra_,do_size,true ,offset,dst_first,Assembler::lduw_op3,"LDUW",size, st); emit3_simm13( *cbuf, Assembler::arith_op, R_SP_enc, Assembler::add_op3, R_SP_enc, 16 ); } #ifndef PRODUCT - else if( !do_size ) { - if( size != 0 ) st->print("\n\t"); + else if (!do_size) { + if (size != 0) st->print("\n\t"); st->print( "SUB R_SP,16,R_SP\n"); impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stf_op3 ,"STF ",size, st); impl_helper(this,cbuf,ra_,do_size,true ,offset,dst_first,Assembler::lduw_op3,"LDUW",size, st); @@ -1346,6 +1346,21 @@ size += 16; } + // Check for float->int copy on T4 + if (src_first_rc == rc_float && dst_first_rc == rc_int && UseVIS >= 3) { + // Further check for aligned-adjacent pair, so we can use a double move + if ((src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second) + return impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::mftoi_op3,Assembler::mdtox_opf,"MOVDTOX",size, st); + size = impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::mftoi_op3,Assembler::mstouw_opf,"MOVSTOUW",size, st); + } + // Check for int->float copy on T4 + if (src_first_rc == rc_int && dst_first_rc == rc_float && UseVIS >= 3) { + // Further check for aligned-adjacent pair, so we can use a double move + if ((src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second) + return impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::mftoi_op3,Assembler::mxtod_opf,"MOVXTOD",size, st); + size = impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::mftoi_op3,Assembler::mwtos_opf,"MOVWTOS",size, st); + } + // -------------------------------------- // In the 32-bit 1-reg-longs build ONLY, I see mis-aligned long destinations. // In such cases, I have to do the big-endian swap. For aligned targets, the @@ -8164,215 +8179,58 @@ ins_pipe( cadd_cmpltmask ); %} -//----------Arithmetic Conversion Instructions--------------------------------- -// The conversions operations are all Alpha sorted. Please keep it that way! - -instruct convD2F_reg(regF dst, regD src) %{ - match(Set dst (ConvD2F src)); - size(4); - format %{ "FDTOS $src,$dst" %} - opcode(Assembler::fpop1_op3, Assembler::arith_op, Assembler::fdtos_opf); - ins_encode(form3_opf_rs2D_rdF(src, dst)); - ins_pipe(fcvtD2F); -%} - - -// Convert a double to an int in a float register. -// If the double is a NAN, stuff a zero in instead. -instruct convD2I_helper(regF dst, regD src, flagsRegF0 fcc0) %{ - effect(DEF dst, USE src, KILL fcc0); - format %{ "FCMPd fcc0,$src,$src\t! check for NAN\n\t" - "FBO,pt fcc0,skip\t! branch on ordered, predict taken\n\t" - "FDTOI $src,$dst\t! convert in delay slot\n\t" - "FITOS $dst,$dst\t! change NaN/max-int to valid float\n\t" - "FSUBs $dst,$dst,$dst\t! cleared only if nan\n" - "skip:" %} - ins_encode(form_d2i_helper(src,dst)); - ins_pipe(fcvtD2I); -%} - -instruct convD2I_reg(stackSlotI dst, regD src) %{ - match(Set dst (ConvD2I src)); - ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); - expand %{ - regF tmp; - convD2I_helper(tmp, src); - regF_to_stkI(dst, tmp); - %} -%} - -// Convert a double to a long in a double register. -// If the double is a NAN, stuff a zero in instead. -instruct convD2L_helper(regD dst, regD src, flagsRegF0 fcc0) %{ - effect(DEF dst, USE src, KILL fcc0); - format %{ "FCMPd fcc0,$src,$src\t! check for NAN\n\t" - "FBO,pt fcc0,skip\t! branch on ordered, predict taken\n\t" - "FDTOX $src,$dst\t! convert in delay slot\n\t" - "FXTOD $dst,$dst\t! change NaN/max-long to valid double\n\t" - "FSUBd $dst,$dst,$dst\t! cleared only if nan\n" - "skip:" %} - ins_encode(form_d2l_helper(src,dst)); - ins_pipe(fcvtD2L); -%} - - -// Double to Long conversion -instruct convD2L_reg(stackSlotL dst, regD src) %{ - match(Set dst (ConvD2L src)); - ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); - expand %{ - regD tmp; - convD2L_helper(tmp, src); - regD_to_stkL(dst, tmp); - %} -%} - - -instruct convF2D_reg(regD dst, regF src) %{ - match(Set dst (ConvF2D src)); - format %{ "FSTOD $src,$dst" %} - opcode(Assembler::fpop1_op3, Assembler::arith_op, Assembler::fstod_opf); - ins_encode(form3_opf_rs2F_rdD(src, dst)); - ins_pipe(fcvtF2D); -%} - - -instruct convF2I_helper(regF dst, regF src, flagsRegF0 fcc0) %{ - effect(DEF dst, USE src, KILL fcc0); - format %{ "FCMPs fcc0,$src,$src\t! check for NAN\n\t" - "FBO,pt fcc0,skip\t! branch on ordered, predict taken\n\t" - "FSTOI $src,$dst\t! convert in delay slot\n\t" - "FITOS $dst,$dst\t! change NaN/max-int to valid float\n\t" - "FSUBs $dst,$dst,$dst\t! cleared only if nan\n" - "skip:" %} - ins_encode(form_f2i_helper(src,dst)); - ins_pipe(fcvtF2I); -%} - -instruct convF2I_reg(stackSlotI dst, regF src) %{ - match(Set dst (ConvF2I src)); - ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); - expand %{ - regF tmp; - convF2I_helper(tmp, src); - regF_to_stkI(dst, tmp); - %} -%} - - -instruct convF2L_helper(regD dst, regF src, flagsRegF0 fcc0) %{ - effect(DEF dst, USE src, KILL fcc0); - format %{ "FCMPs fcc0,$src,$src\t! check for NAN\n\t" - "FBO,pt fcc0,skip\t! branch on ordered, predict taken\n\t" - "FSTOX $src,$dst\t! convert in delay slot\n\t" - "FXTOD $dst,$dst\t! change NaN/max-long to valid double\n\t" - "FSUBd $dst,$dst,$dst\t! cleared only if nan\n" - "skip:" %} - ins_encode(form_f2l_helper(src,dst)); - ins_pipe(fcvtF2L); -%} - -// Float to Long conversion -instruct convF2L_reg(stackSlotL dst, regF src) %{ - match(Set dst (ConvF2L src)); - ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); - expand %{ - regD tmp; - convF2L_helper(tmp, src); - regD_to_stkL(dst, tmp); - %} -%} - - -instruct convI2D_helper(regD dst, regF tmp) %{ - effect(USE tmp, DEF dst); - format %{ "FITOD $tmp,$dst" %} - opcode(Assembler::fpop1_op3, Assembler::arith_op, Assembler::fitod_opf); - ins_encode(form3_opf_rs2F_rdD(tmp, dst)); - ins_pipe(fcvtI2D); -%} - -instruct convI2D_reg(stackSlotI src, regD dst) %{ - match(Set dst (ConvI2D src)); - ins_cost(DEFAULT_COST + MEMORY_REF_COST); - expand %{ - regF tmp; - stkI_to_regF( tmp, src); - convI2D_helper( dst, tmp); - %} -%} - -instruct convI2D_mem( regD_low dst, memory mem ) %{ - match(Set dst (ConvI2D (LoadI mem))); - ins_cost(DEFAULT_COST + MEMORY_REF_COST); - size(8); - format %{ "LDF $mem,$dst\n\t" - "FITOD $dst,$dst" %} - opcode(Assembler::ldf_op3, Assembler::fitod_opf); - ins_encode(simple_form3_mem_reg( mem, dst ), form3_convI2F(dst, dst)); - ins_pipe(floadF_mem); -%} - - -instruct convI2F_helper(regF dst, regF tmp) %{ - effect(DEF dst, USE tmp); - format %{ "FITOS $tmp,$dst" %} - opcode(Assembler::fpop1_op3, Assembler::arith_op, Assembler::fitos_opf); - ins_encode(form3_opf_rs2F_rdF(tmp, dst)); - ins_pipe(fcvtI2F); -%} - -instruct convI2F_reg( regF dst, stackSlotI src ) %{ - match(Set dst (ConvI2F src)); - ins_cost(DEFAULT_COST + MEMORY_REF_COST); - expand %{ - regF tmp; - stkI_to_regF(tmp,src); - convI2F_helper(dst, tmp); - %} -%} - -instruct convI2F_mem( regF dst, memory mem ) %{ - match(Set dst (ConvI2F (LoadI mem))); - ins_cost(DEFAULT_COST + MEMORY_REF_COST); - size(8); - format %{ "LDF $mem,$dst\n\t" - "FITOS $dst,$dst" %} - opcode(Assembler::ldf_op3, Assembler::fitos_opf); - ins_encode(simple_form3_mem_reg( mem, dst ), form3_convI2F(dst, dst)); - ins_pipe(floadF_mem); -%} - - -instruct convI2L_reg(iRegL dst, iRegI src) %{ - match(Set dst (ConvI2L src)); - size(4); - format %{ "SRA $src,0,$dst\t! int->long" %} - opcode(Assembler::sra_op3, Assembler::arith_op); - ins_encode( form3_rs1_rs2_rd( src, R_G0, dst ) ); + +//----------------------------------------------------------------- +// Direct raw moves between float and general registers using VIS3. + +// ins_pipe(faddF_reg); +instruct MoveF2I_reg_reg(iRegI dst, regF src) %{ + predicate(UseVIS >= 3); + match(Set dst (MoveF2I src)); + + format %{ "MOVSTOUW $src,$dst\t! MoveF2I" %} + ins_encode %{ + __ movstouw($src$$FloatRegister, $dst$$Register); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct MoveI2F_reg_reg(regF dst, iRegI src) %{ + predicate(UseVIS >= 3); + match(Set dst (MoveI2F src)); + + format %{ "MOVWTOS $src,$dst\t! MoveI2F" %} + ins_encode %{ + __ movwtos($src$$Register, $dst$$FloatRegister); + %} ins_pipe(ialu_reg_reg); %} -// Zero-extend convert int to long -instruct convI2L_reg_zex(iRegL dst, iRegI src, immL_32bits mask ) %{ - match(Set dst (AndL (ConvI2L src) mask) ); - size(4); - format %{ "SRL $src,0,$dst\t! zero-extend int to long" %} - opcode(Assembler::srl_op3, Assembler::arith_op); - ins_encode( form3_rs1_rs2_rd( src, R_G0, dst ) ); +instruct MoveD2L_reg_reg(iRegL dst, regD src) %{ + predicate(UseVIS >= 3); + match(Set dst (MoveD2L src)); + + format %{ "MOVDTOX $src,$dst\t! MoveD2L" %} + ins_encode %{ + __ movdtox(as_DoubleFloatRegister($src$$reg), $dst$$Register); + %} ins_pipe(ialu_reg_reg); %} -// Zero-extend long -instruct zerox_long(iRegL dst, iRegL src, immL_32bits mask ) %{ - match(Set dst (AndL src mask) ); - size(4); - format %{ "SRL $src,0,$dst\t! zero-extend long" %} - opcode(Assembler::srl_op3, Assembler::arith_op); - ins_encode( form3_rs1_rs2_rd( src, R_G0, dst ) ); +instruct MoveL2D_reg_reg(regD dst, iRegL src) %{ + predicate(UseVIS >= 3); + match(Set dst (MoveL2D src)); + + format %{ "MOVXTOD $src,$dst\t! MoveL2D" %} + ins_encode %{ + __ movxtod($src$$Register, as_DoubleFloatRegister($dst$$reg)); + %} ins_pipe(ialu_reg_reg); %} + +// Raw moves between float and general registers using stack. + instruct MoveF2I_stack_reg(iRegI dst, stackSlotF src) %{ match(Set dst (MoveF2I src)); effect(DEF dst, USE src); @@ -8427,7 +8285,7 @@ ins_cost(MEMORY_REF_COST); size(4); - format %{ "STF $src,$dst\t!MoveF2I" %} + format %{ "STF $src,$dst\t! MoveF2I" %} opcode(Assembler::stf_op3); ins_encode(simple_form3_mem_reg(dst, src)); ins_pipe(fstoreF_stk_reg); @@ -8439,7 +8297,7 @@ ins_cost(MEMORY_REF_COST); size(4); - format %{ "STW $src,$dst\t!MoveI2F" %} + format %{ "STW $src,$dst\t! MoveI2F" %} opcode(Assembler::stw_op3); ins_encode(simple_form3_mem_reg( dst, src ) ); ins_pipe(istore_mem_reg); @@ -8451,7 +8309,7 @@ ins_cost(MEMORY_REF_COST); size(4); - format %{ "STDF $src,$dst\t!MoveD2L" %} + format %{ "STDF $src,$dst\t! MoveD2L" %} opcode(Assembler::stdf_op3); ins_encode(simple_form3_mem_reg(dst, src)); ins_pipe(fstoreD_stk_reg); @@ -8463,13 +8321,290 @@ ins_cost(MEMORY_REF_COST); size(4); - format %{ "STX $src,$dst\t!MoveL2D" %} + format %{ "STX $src,$dst\t! MoveL2D" %} opcode(Assembler::stx_op3); ins_encode(simple_form3_mem_reg( dst, src ) ); ins_pipe(istore_mem_reg); %} +//----------Arithmetic Conversion Instructions--------------------------------- +// The conversions operations are all Alpha sorted. Please keep it that way! + +instruct convD2F_reg(regF dst, regD src) %{ + match(Set dst (ConvD2F src)); + size(4); + format %{ "FDTOS $src,$dst" %} + opcode(Assembler::fpop1_op3, Assembler::arith_op, Assembler::fdtos_opf); + ins_encode(form3_opf_rs2D_rdF(src, dst)); + ins_pipe(fcvtD2F); +%} + + +// Convert a double to an int in a float register. +// If the double is a NAN, stuff a zero in instead. +instruct convD2I_helper(regF dst, regD src, flagsRegF0 fcc0) %{ + effect(DEF dst, USE src, KILL fcc0); + format %{ "FCMPd fcc0,$src,$src\t! check for NAN\n\t" + "FBO,pt fcc0,skip\t! branch on ordered, predict taken\n\t" + "FDTOI $src,$dst\t! convert in delay slot\n\t" + "FITOS $dst,$dst\t! change NaN/max-int to valid float\n\t" + "FSUBs $dst,$dst,$dst\t! cleared only if nan\n" + "skip:" %} + ins_encode(form_d2i_helper(src,dst)); + ins_pipe(fcvtD2I); +%} + +instruct convD2I_stk(stackSlotI dst, regD src) %{ + match(Set dst (ConvD2I src)); + ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); + expand %{ + regF tmp; + convD2I_helper(tmp, src); + regF_to_stkI(dst, tmp); + %} +%} + +instruct convD2I_reg(iRegI dst, regD src) %{ + predicate(UseVIS >= 3); + match(Set dst (ConvD2I src)); + ins_cost(DEFAULT_COST*2 + BRANCH_COST); + expand %{ + regF tmp; + convD2I_helper(tmp, src); + MoveF2I_reg_reg(dst, tmp); + %} +%} + + +// Convert a double to a long in a double register. +// If the double is a NAN, stuff a zero in instead. +instruct convD2L_helper(regD dst, regD src, flagsRegF0 fcc0) %{ + effect(DEF dst, USE src, KILL fcc0); + format %{ "FCMPd fcc0,$src,$src\t! check for NAN\n\t" + "FBO,pt fcc0,skip\t! branch on ordered, predict taken\n\t" + "FDTOX $src,$dst\t! convert in delay slot\n\t" + "FXTOD $dst,$dst\t! change NaN/max-long to valid double\n\t" + "FSUBd $dst,$dst,$dst\t! cleared only if nan\n" + "skip:" %} + ins_encode(form_d2l_helper(src,dst)); + ins_pipe(fcvtD2L); +%} + +instruct convD2L_stk(stackSlotL dst, regD src) %{ + match(Set dst (ConvD2L src)); + ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); + expand %{ + regD tmp; + convD2L_helper(tmp, src); + regD_to_stkL(dst, tmp); + %} +%} + +instruct convD2L_reg(iRegL dst, regD src) %{ + predicate(UseVIS >= 3); + match(Set dst (ConvD2L src)); + ins_cost(DEFAULT_COST*2 + BRANCH_COST); + expand %{ + regD tmp; + convD2L_helper(tmp, src); + MoveD2L_reg_reg(dst, tmp); + %} +%} + + +instruct convF2D_reg(regD dst, regF src) %{ + match(Set dst (ConvF2D src)); + format %{ "FSTOD $src,$dst" %} + opcode(Assembler::fpop1_op3, Assembler::arith_op, Assembler::fstod_opf); + ins_encode(form3_opf_rs2F_rdD(src, dst)); + ins_pipe(fcvtF2D); +%} + + +// Convert a float to an int in a float register. +// If the float is a NAN, stuff a zero in instead. +instruct convF2I_helper(regF dst, regF src, flagsRegF0 fcc0) %{ + effect(DEF dst, USE src, KILL fcc0); + format %{ "FCMPs fcc0,$src,$src\t! check for NAN\n\t" + "FBO,pt fcc0,skip\t! branch on ordered, predict taken\n\t" + "FSTOI $src,$dst\t! convert in delay slot\n\t" + "FITOS $dst,$dst\t! change NaN/max-int to valid float\n\t" + "FSUBs $dst,$dst,$dst\t! cleared only if nan\n" + "skip:" %} + ins_encode(form_f2i_helper(src,dst)); + ins_pipe(fcvtF2I); +%} + +instruct convF2I_stk(stackSlotI dst, regF src) %{ + match(Set dst (ConvF2I src)); + ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); + expand %{ + regF tmp; + convF2I_helper(tmp, src); + regF_to_stkI(dst, tmp); + %} +%} + +instruct convF2I_reg(iRegI dst, regF src) %{ + predicate(UseVIS >= 3); + match(Set dst (ConvF2I src)); + ins_cost(DEFAULT_COST*2 + BRANCH_COST); + expand %{ + regF tmp; + convF2I_helper(tmp, src); + MoveF2I_reg_reg(dst, tmp); + %} +%} + + +// Convert a float to a long in a float register. +// If the float is a NAN, stuff a zero in instead. +instruct convF2L_helper(regD dst, regF src, flagsRegF0 fcc0) %{ + effect(DEF dst, USE src, KILL fcc0); + format %{ "FCMPs fcc0,$src,$src\t! check for NAN\n\t" + "FBO,pt fcc0,skip\t! branch on ordered, predict taken\n\t" + "FSTOX $src,$dst\t! convert in delay slot\n\t" + "FXTOD $dst,$dst\t! change NaN/max-long to valid double\n\t" + "FSUBd $dst,$dst,$dst\t! cleared only if nan\n" + "skip:" %} + ins_encode(form_f2l_helper(src,dst)); + ins_pipe(fcvtF2L); +%} + +instruct convF2L_stk(stackSlotL dst, regF src) %{ + match(Set dst (ConvF2L src)); + ins_cost(DEFAULT_COST*2 + MEMORY_REF_COST*2 + BRANCH_COST); + expand %{ + regD tmp; + convF2L_helper(tmp, src); + regD_to_stkL(dst, tmp); + %} +%} + +instruct convF2L_reg(iRegL dst, regF src) %{ + predicate(UseVIS >= 3); + match(Set dst (ConvF2L src)); + ins_cost(DEFAULT_COST*2 + BRANCH_COST); + expand %{ + regD tmp; + convF2L_helper(tmp, src); + MoveD2L_reg_reg(dst, tmp); + %} +%} + + +instruct convI2D_helper(regD dst, regF tmp) %{ + effect(USE tmp, DEF dst); + format %{ "FITOD $tmp,$dst" %} + opcode(Assembler::fpop1_op3, Assembler::arith_op, Assembler::fitod_opf); + ins_encode(form3_opf_rs2F_rdD(tmp, dst)); + ins_pipe(fcvtI2D); +%} + +instruct convI2D_stk(stackSlotI src, regD dst) %{ + match(Set dst (ConvI2D src)); + ins_cost(DEFAULT_COST + MEMORY_REF_COST); + expand %{ + regF tmp; + stkI_to_regF(tmp, src); + convI2D_helper(dst, tmp); + %} +%} + +instruct convI2D_reg(regD_low dst, iRegI src) %{ + predicate(UseVIS >= 3); + match(Set dst (ConvI2D src)); + expand %{ + regF tmp; + MoveI2F_reg_reg(tmp, src); + convI2D_helper(dst, tmp); + %} +%} + +instruct convI2D_mem(regD_low dst, memory mem) %{ + match(Set dst (ConvI2D (LoadI mem))); + ins_cost(DEFAULT_COST + MEMORY_REF_COST); + size(8); + format %{ "LDF $mem,$dst\n\t" + "FITOD $dst,$dst" %} + opcode(Assembler::ldf_op3, Assembler::fitod_opf); + ins_encode(simple_form3_mem_reg( mem, dst ), form3_convI2F(dst, dst)); + ins_pipe(floadF_mem); +%} + + +instruct convI2F_helper(regF dst, regF tmp) %{ + effect(DEF dst, USE tmp); + format %{ "FITOS $tmp,$dst" %} + opcode(Assembler::fpop1_op3, Assembler::arith_op, Assembler::fitos_opf); + ins_encode(form3_opf_rs2F_rdF(tmp, dst)); + ins_pipe(fcvtI2F); +%} + +instruct convI2F_stk(regF dst, stackSlotI src) %{ + match(Set dst (ConvI2F src)); + ins_cost(DEFAULT_COST + MEMORY_REF_COST); + expand %{ + regF tmp; + stkI_to_regF(tmp,src); + convI2F_helper(dst, tmp); + %} +%} + +instruct convI2F_reg(regF dst, iRegI src) %{ + predicate(UseVIS >= 3); + match(Set dst (ConvI2F src)); + ins_cost(DEFAULT_COST); + expand %{ + regF tmp; + MoveI2F_reg_reg(tmp, src); + convI2F_helper(dst, tmp); + %} +%} + +instruct convI2F_mem( regF dst, memory mem ) %{ + match(Set dst (ConvI2F (LoadI mem))); + ins_cost(DEFAULT_COST + MEMORY_REF_COST); + size(8); + format %{ "LDF $mem,$dst\n\t" + "FITOS $dst,$dst" %} + opcode(Assembler::ldf_op3, Assembler::fitos_opf); + ins_encode(simple_form3_mem_reg( mem, dst ), form3_convI2F(dst, dst)); + ins_pipe(floadF_mem); +%} + + +instruct convI2L_reg(iRegL dst, iRegI src) %{ + match(Set dst (ConvI2L src)); + size(4); + format %{ "SRA $src,0,$dst\t! int->long" %} + opcode(Assembler::sra_op3, Assembler::arith_op); + ins_encode( form3_rs1_rs2_rd( src, R_G0, dst ) ); + ins_pipe(ialu_reg_reg); +%} + +// Zero-extend convert int to long +instruct convI2L_reg_zex(iRegL dst, iRegI src, immL_32bits mask ) %{ + match(Set dst (AndL (ConvI2L src) mask) ); + size(4); + format %{ "SRL $src,0,$dst\t! zero-extend int to long" %} + opcode(Assembler::srl_op3, Assembler::arith_op); + ins_encode( form3_rs1_rs2_rd( src, R_G0, dst ) ); + ins_pipe(ialu_reg_reg); +%} + +// Zero-extend long +instruct zerox_long(iRegL dst, iRegL src, immL_32bits mask ) %{ + match(Set dst (AndL src mask) ); + size(4); + format %{ "SRL $src,0,$dst\t! zero-extend long" %} + opcode(Assembler::srl_op3, Assembler::arith_op); + ins_encode( form3_rs1_rs2_rd( src, R_G0, dst ) ); + ins_pipe(ialu_reg_reg); +%} + + //----------- // Long to Double conversion using V8 opcodes. // Still useful because cheetah traps and becomes @@ -8589,7 +8724,7 @@ ins_pipe(fcvtL2D); %} -instruct convL2D_reg_fast_fxtof(regD dst, stackSlotL src) %{ +instruct convL2D_stk_fast_fxtof(regD dst, stackSlotL src) %{ predicate(VM_Version::has_fast_fxtof()); match(Set dst (ConvL2D src)); ins_cost(DEFAULT_COST + 3 * MEMORY_REF_COST); @@ -8600,10 +8735,15 @@ %} %} -//----------- -// Long to Float conversion using V8 opcodes. -// Still useful because cheetah traps and becomes -// amazingly slow for some common numbers. +instruct convL2D_reg(regD dst, iRegL src) %{ + predicate(UseVIS >= 3); + match(Set dst (ConvL2D src)); + expand %{ + regD tmp; + MoveL2D_reg_reg(tmp, src); + convL2D_helper(dst, tmp); + %} +%} // Long to Float conversion using fast fxtof instruct convL2F_helper(regF dst, regD tmp) %{ @@ -8615,7 +8755,7 @@ ins_pipe(fcvtL2F); %} -instruct convL2F_reg_fast_fxtof(regF dst, stackSlotL src) %{ +instruct convL2F_stk_fast_fxtof(regF dst, stackSlotL src) %{ match(Set dst (ConvL2F src)); ins_cost(DEFAULT_COST + MEMORY_REF_COST); expand %{ @@ -8624,6 +8764,18 @@ convL2F_helper(dst, tmp); %} %} + +instruct convL2F_reg(regF dst, iRegL src) %{ + predicate(UseVIS >= 3); + match(Set dst (ConvL2F src)); + ins_cost(DEFAULT_COST); + expand %{ + regD tmp; + MoveL2D_reg_reg(tmp, src); + convL2F_helper(dst, tmp); + %} +%} + //----------- instruct convL2I_reg(iRegI dst, iRegL src) %{ diff -r 5447b2c582ad -r bcc6475bc68f src/cpu/sparc/vm/vm_version_sparc.cpp --- a/src/cpu/sparc/vm/vm_version_sparc.cpp Thu Jul 07 22:34:34 2011 -0400 +++ b/src/cpu/sparc/vm/vm_version_sparc.cpp Sat Jul 16 22:21:39 2011 -0400 @@ -144,6 +144,18 @@ // buf is started with ", " or is empty _features_str = strdup(strlen(buf) > 2 ? buf + 2 : buf); + // UseVIS is set to the smallest of what hardware supports and what + // the command line requires. I.e., you cannot set UseVIS to 3 on + // older UltraSparc which do not support it. + if (UseVIS > 3) UseVIS=3; + if (UseVIS < 0) UseVIS=0; + if (!has_vis3()) // Drop to 2 if no VIS3 support + UseVIS = MIN2((intx)2,UseVIS); + if (!has_vis2()) // Drop to 1 if no VIS2 support + UseVIS = MIN2((intx)1,UseVIS); + if (!has_vis1()) // Drop to 0 if no VIS1 support + UseVIS = 0; + #ifndef PRODUCT if (PrintMiscellaneous && Verbose) { tty->print("Allocation: "); diff -r 5447b2c582ad -r bcc6475bc68f src/os/linux/vm/os_linux.cpp --- a/src/os/linux/vm/os_linux.cpp Thu Jul 07 22:34:34 2011 -0400 +++ b/src/os/linux/vm/os_linux.cpp Sat Jul 16 22:21:39 2011 -0400 @@ -169,7 +169,35 @@ /* Used to protect dlsym() calls */ static pthread_mutex_t dl_mutex; -//////////////////////////////////////////////////////////////////////////////// +#ifdef JAVASE_EMBEDDED +class MemNotifyThread: public Thread { + friend class VMStructs; + public: + virtual void run(); + + private: + static MemNotifyThread* _memnotify_thread; + int _fd; + + public: + + // Constructor + MemNotifyThread(int fd); + + // Tester + bool is_memnotify_thread() const { return true; } + + // Printing + char* name() const { return (char*)"Linux MemNotify Thread"; } + + // Returns the single instance of the MemNotifyThread + static MemNotifyThread* memnotify_thread() { return _memnotify_thread; } + + // Create and start the single instance of MemNotifyThread + static void start(); +}; +#endif // JAVASE_EMBEDDED + // utility functions static int SR_initialize(); @@ -2085,6 +2113,14 @@ st->cr(); } +void os::pd_print_cpu_info(outputStream* st) { + st->print("\n/proc/cpuinfo:\n"); + if (!_print_ascii_file("/proc/cpuinfo", st)) { + st->print(" "); + } + st->cr(); +} + void os::print_memory_info(outputStream* st) { st->print("Memory:"); @@ -4237,7 +4273,16 @@ } // this is called at the end of vm_initialization -void os::init_3(void) { } +void os::init_3(void) +{ +#ifdef JAVASE_EMBEDDED + // Start the MemNotifyThread + if (LowMemoryProtection) { + MemNotifyThread::start(); + } + return; +#endif +} // Mark the polling page as unreadable void os::make_polling_page_unreadable(void) { @@ -5360,3 +5405,78 @@ return true; } + +#ifdef JAVASE_EMBEDDED +// +// A thread to watch the '/dev/mem_notify' device, which will tell us when the OS is running low on memory. +// +MemNotifyThread* MemNotifyThread::_memnotify_thread = NULL; + +// ctor +// +MemNotifyThread::MemNotifyThread(int fd): Thread() { + assert(memnotify_thread() == NULL, "we can only allocate one MemNotifyThread"); + _fd = fd; + + if (os::create_thread(this, os::os_thread)) { + _memnotify_thread = this; + os::set_priority(this, NearMaxPriority); + os::start_thread(this); + } +} + +// Where all the work gets done +// +void MemNotifyThread::run() { + assert(this == memnotify_thread(), "expected the singleton MemNotifyThread"); + + // Set up the select arguments + fd_set rfds; + if (_fd != -1) { + FD_ZERO(&rfds); + FD_SET(_fd, &rfds); + } + + // Now wait for the mem_notify device to wake up + while (1) { + // Wait for the mem_notify device to signal us.. + int rc = select(_fd+1, _fd != -1 ? &rfds : NULL, NULL, NULL, NULL); + if (rc == -1) { + perror("select!\n"); + break; + } else if (rc) { + //ssize_t free_before = os::available_memory(); + //tty->print ("Notified: Free: %dK \n",os::available_memory()/1024); + + // The kernel is telling us there is not much memory left... + // try to do something about that + + // If we are not already in a GC, try one. + if (!Universe::heap()->is_gc_active()) { + Universe::heap()->collect(GCCause::_allocation_failure); + + //ssize_t free_after = os::available_memory(); + //tty->print ("Post-Notify: Free: %dK\n",free_after/1024); + //tty->print ("GC freed: %dK\n", (free_after - free_before)/1024); + } + // We might want to do something like the following if we find the GC's are not helping... + // Universe::heap()->size_policy()->set_gc_time_limit_exceeded(true); + } + } +} + +// +// See if the /dev/mem_notify device exists, and if so, start a thread to monitor it. +// +void MemNotifyThread::start() { + int fd; + fd = open ("/dev/mem_notify", O_RDONLY, 0); + if (fd < 0) { + return; + } + + if (memnotify_thread() == NULL) { + new MemNotifyThread(fd); + } +} +#endif // JAVASE_EMBEDDED diff -r 5447b2c582ad -r bcc6475bc68f src/os/solaris/vm/os_solaris.cpp --- a/src/os/solaris/vm/os_solaris.cpp Thu Jul 07 22:34:34 2011 -0400 +++ b/src/os/solaris/vm/os_solaris.cpp Sat Jul 16 22:21:39 2011 -0400 @@ -2317,6 +2317,10 @@ return status; } +void os::pd_print_cpu_info(outputStream* st) { + // Nothing to do for now. +} + void os::print_memory_info(outputStream* st) { st->print("Memory:"); st->print(" %dk page", os::vm_page_size()>>10); diff -r 5447b2c582ad -r bcc6475bc68f src/os/windows/vm/os_windows.cpp --- a/src/os/windows/vm/os_windows.cpp Thu Jul 07 22:34:34 2011 -0400 +++ b/src/os/windows/vm/os_windows.cpp Sat Jul 16 22:21:39 2011 -0400 @@ -1720,6 +1720,10 @@ st->cr(); } +void os::pd_print_cpu_info(outputStream* st) { + // Nothing to do for now. +} + void os::print_memory_info(outputStream* st) { st->print("Memory:"); st->print(" %dk page", os::vm_page_size()>>10); diff -r 5447b2c582ad -r bcc6475bc68f src/os_cpu/linux_x86/vm/assembler_linux_x86.cpp --- a/src/os_cpu/linux_x86/vm/assembler_linux_x86.cpp Thu Jul 07 22:34:34 2011 -0400 +++ b/src/os_cpu/linux_x86/vm/assembler_linux_x86.cpp Sat Jul 16 22:21:39 2011 -0400 @@ -33,6 +33,28 @@ call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); } +#ifdef MINIMIZE_RAM_USAGE + +void MacroAssembler::get_thread(Register thread) { + // call pthread_getspecific + // void * pthread_getspecific(pthread_key_t key); + if (thread != rax) push(rax); + push(rcx); + push(rdx); + + push(ThreadLocalStorage::thread_index()); + call(RuntimeAddress(CAST_FROM_FN_PTR(address, pthread_getspecific))); + increment(rsp, wordSize); + + pop(rdx); + pop(rcx); + if (thread != rax) { + mov(thread, rax); + pop(rax); + } +} + +#else void MacroAssembler::get_thread(Register thread) { movl(thread, rsp); shrl(thread, PAGE_SHIFT); @@ -43,6 +65,7 @@ movptr(thread, tls); } +#endif // MINIMIZE_RAM_USAGE #else void MacroAssembler::int3() { call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); diff -r 5447b2c582ad -r bcc6475bc68f src/os_cpu/linux_x86/vm/threadLS_linux_x86.cpp --- a/src/os_cpu/linux_x86/vm/threadLS_linux_x86.cpp Thu Jul 07 22:34:34 2011 -0400 +++ b/src/os_cpu/linux_x86/vm/threadLS_linux_x86.cpp Sat Jul 16 22:21:39 2011 -0400 @@ -52,25 +52,20 @@ // MADV_DONTNEED on Linux keeps the virtual memory mapping, but zaps the // physical memory page (i.e. similar to MADV_FREE on Solaris). -#ifndef AMD64 +#if !defined(AMD64) && !defined(MINIMIZE_RAM_USAGE) Thread* ThreadLocalStorage::_sp_map[1UL << (SP_BITLENGTH - PAGE_SHIFT)]; -#endif // !AMD64 void ThreadLocalStorage::generate_code_for_get_thread() { // nothing we can do here for user-level thread } void ThreadLocalStorage::pd_init() { -#ifndef AMD64 assert(align_size_down(os::vm_page_size(), PAGE_SIZE) == os::vm_page_size(), "page size must be multiple of PAGE_SIZE"); -#endif // !AMD64 } void ThreadLocalStorage::pd_set_thread(Thread* thread) { os::thread_local_storage_at_put(ThreadLocalStorage::thread_index(), thread); - -#ifndef AMD64 address stack_top = os::current_stack_base(); size_t stack_size = os::current_stack_size(); @@ -88,5 +83,17 @@ "thread exited without detaching from VM??"); _sp_map[(uintptr_t)p >> PAGE_SHIFT] = thread; } -#endif // !AMD64 +} +#else + +void ThreadLocalStorage::generate_code_for_get_thread() { + // nothing we can do here for user-level thread } + +void ThreadLocalStorage::pd_init() { +} + +void ThreadLocalStorage::pd_set_thread(Thread* thread) { + os::thread_local_storage_at_put(ThreadLocalStorage::thread_index(), thread); +} +#endif // !AMD64 && !MINIMIZE_RAM_USAGE diff -r 5447b2c582ad -r bcc6475bc68f src/os_cpu/linux_x86/vm/threadLS_linux_x86.hpp --- a/src/os_cpu/linux_x86/vm/threadLS_linux_x86.hpp Thu Jul 07 22:34:34 2011 -0400 +++ b/src/os_cpu/linux_x86/vm/threadLS_linux_x86.hpp Sat Jul 16 22:21:39 2011 -0400 @@ -27,28 +27,32 @@ // Processor dependent parts of ThreadLocalStorage -#ifndef AMD64 +#if !defined(AMD64) && !defined(MINIMIZE_RAM_USAGE) + // map stack pointer to thread pointer - see notes in threadLS_linux_x86.cpp #define SP_BITLENGTH 32 #define PAGE_SHIFT 12 #define PAGE_SIZE (1UL << PAGE_SHIFT) static Thread* _sp_map[1UL << (SP_BITLENGTH - PAGE_SHIFT)]; -#endif // !AMD64 public: -#ifndef AMD64 static Thread** sp_map_addr() { return _sp_map; } -#endif // !AMD64 static Thread* thread() { -#ifdef AMD64 - return (Thread*) os::thread_local_storage_at(thread_index()); -#else uintptr_t sp; __asm__ volatile ("movl %%esp, %0" : "=r" (sp)); return _sp_map[sp >> PAGE_SHIFT]; -#endif // AMD64 } +#else + +public: + + static Thread* thread() { + return (Thread*) os::thread_local_storage_at(thread_index()); + } + +#endif // AMD64 || MINIMIZE_RAM_USAGE + #endif // OS_CPU_LINUX_X86_VM_THREADLS_LINUX_X86_HPP diff -r 5447b2c582ad -r bcc6475bc68f src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Thu Jul 07 22:34:34 2011 -0400 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Sat Jul 16 22:21:39 2011 -0400 @@ -2716,6 +2716,10 @@ bitMapLock()->unlock(); releaseFreelistLocks(); + if (!CleanChunkPoolAsync) { + Chunk::clean_chunk_pool(); + } + _between_prologue_and_epilogue = false; // ready for next cycle } diff -r 5447b2c582ad -r bcc6475bc68f src/share/vm/memory/defNewGeneration.cpp --- a/src/share/vm/memory/defNewGeneration.cpp Thu Jul 07 22:34:34 2011 -0400 +++ b/src/share/vm/memory/defNewGeneration.cpp Sat Jul 16 22:21:39 2011 -0400 @@ -905,6 +905,10 @@ to()->check_mangled_unused_area_complete(); } + if (!CleanChunkPoolAsync) { + Chunk::clean_chunk_pool(); + } + // update the generation and space performance counters update_counters(); gch->collector_policy()->counters()->update_counters(); diff -r 5447b2c582ad -r bcc6475bc68f src/share/vm/memory/genCollectedHeap.cpp --- a/src/share/vm/memory/genCollectedHeap.cpp Thu Jul 07 22:34:34 2011 -0400 +++ b/src/share/vm/memory/genCollectedHeap.cpp Sat Jul 16 22:21:39 2011 -0400 @@ -1384,6 +1384,10 @@ generation_iterate(&blk, false); // not old-to-young. perm_gen()->gc_epilogue(full); + if (!CleanChunkPoolAsync) { + Chunk::clean_chunk_pool(); + } + always_do_update_barrier = UseConcMarkSweepGC; }; diff -r 5447b2c582ad -r bcc6475bc68f src/share/vm/opto/lcm.cpp --- a/src/share/vm/opto/lcm.cpp Thu Jul 07 22:34:34 2011 -0400 +++ b/src/share/vm/opto/lcm.cpp Sat Jul 16 22:21:39 2011 -0400 @@ -45,6 +45,9 @@ #ifdef TARGET_ARCH_MODEL_arm # include "adfiles/ad_arm.hpp" #endif +#ifdef TARGET_ARCH_MODEL_ppc +# include "adfiles/ad_ppc.hpp" +#endif // Optimization - Graph Style diff -r 5447b2c582ad -r bcc6475bc68f src/share/vm/opto/matcher.cpp --- a/src/share/vm/opto/matcher.cpp Thu Jul 07 22:34:34 2011 -0400 +++ b/src/share/vm/opto/matcher.cpp Sat Jul 16 22:21:39 2011 -0400 @@ -52,6 +52,9 @@ #ifdef TARGET_ARCH_MODEL_arm # include "adfiles/ad_arm.hpp" #endif +#ifdef TARGET_ARCH_MODEL_ppc +# include "adfiles/ad_ppc.hpp" +#endif OptoReg::Name OptoReg::c_frame_pointer; diff -r 5447b2c582ad -r bcc6475bc68f src/share/vm/opto/parse3.cpp --- a/src/share/vm/opto/parse3.cpp Thu Jul 07 22:34:34 2011 -0400 +++ b/src/share/vm/opto/parse3.cpp Sat Jul 16 22:21:39 2011 -0400 @@ -417,17 +417,10 @@ // Note: Array classes are always initialized; no is_initialized check. - enum { MAX_DIMENSION = 5 }; - if (ndimensions > MAX_DIMENSION || ndimensions <= 0) { - uncommon_trap(Deoptimization::Reason_unhandled, - Deoptimization::Action_none); - return; - } - kill_dead_locals(); // get the lengths from the stack (first dimension is on top) - Node* length[MAX_DIMENSION+1]; + Node** length = NEW_RESOURCE_ARRAY(Node*, ndimensions + 1); length[ndimensions] = NULL; // terminating null for make_runtime_call int j; for (j = ndimensions-1; j >= 0 ; j--) length[j] = pop(); @@ -470,20 +463,43 @@ address fun = NULL; switch (ndimensions) { - //case 1: Actually, there is no case 1. It's handled by new_array. + case 1: ShouldNotReachHere(); break; case 2: fun = OptoRuntime::multianewarray2_Java(); break; case 3: fun = OptoRuntime::multianewarray3_Java(); break; case 4: fun = OptoRuntime::multianewarray4_Java(); break; case 5: fun = OptoRuntime::multianewarray5_Java(); break; - default: ShouldNotReachHere(); }; + Node* c = NULL; - Node* c = make_runtime_call(RC_NO_LEAF | RC_NO_IO, - OptoRuntime::multianewarray_Type(ndimensions), - fun, NULL, TypeRawPtr::BOTTOM, - makecon(TypeKlassPtr::make(array_klass)), - length[0], length[1], length[2], - length[3], length[4]); + if (fun != NULL) { + c = make_runtime_call(RC_NO_LEAF | RC_NO_IO, + OptoRuntime::multianewarray_Type(ndimensions), + fun, NULL, TypeRawPtr::BOTTOM, + makecon(TypeKlassPtr::make(array_klass)), + length[0], length[1], length[2], + length[3], length[4]); + } else { + // Create a java array for dimension sizes + Node* dims = NULL; + { PreserveReexecuteState preexecs(this); + _sp += ndimensions; + Node* dims_array_klass = makecon(TypeKlassPtr::make(ciArrayKlass::make(ciType::make(T_INT)))); + dims = new_array(dims_array_klass, intcon(ndimensions), 0); + + // Fill-in it with values + for (j = 0; j < ndimensions; j++) { + Node *dims_elem = array_element_address(dims, intcon(j), T_INT); + store_to_memory(control(), dims_elem, length[j], T_INT, TypeAryPtr::INTS); + } + } + + c = make_runtime_call(RC_NO_LEAF | RC_NO_IO, + OptoRuntime::multianewarrayN_Type(), + OptoRuntime::multianewarrayN_Java(), NULL, TypeRawPtr::BOTTOM, + makecon(TypeKlassPtr::make(array_klass)), + dims); + } + Node* res = _gvn.transform(new (C, 1) ProjNode(c, TypeFunc::Parms)); const Type* type = TypeOopPtr::make_from_klass_raw(array_klass); @@ -496,7 +512,7 @@ if (ltype != NULL) type = type->is_aryptr()->cast_to_size(ltype); - // We cannot sharpen the nested sub-arrays, since the top level is mutable. + // We cannot sharpen the nested sub-arrays, since the top level is mutable. Node* cast = _gvn.transform( new (C, 2) CheckCastPPNode(control(), res, type) ); push(cast); diff -r 5447b2c582ad -r bcc6475bc68f src/share/vm/opto/runtime.cpp --- a/src/share/vm/opto/runtime.cpp Thu Jul 07 22:34:34 2011 -0400 +++ b/src/share/vm/opto/runtime.cpp Sat Jul 16 22:21:39 2011 -0400 @@ -106,6 +106,7 @@ address OptoRuntime::_multianewarray3_Java = NULL; address OptoRuntime::_multianewarray4_Java = NULL; address OptoRuntime::_multianewarray5_Java = NULL; +address OptoRuntime::_multianewarrayN_Java = NULL; address OptoRuntime::_g1_wb_pre_Java = NULL; address OptoRuntime::_g1_wb_post_Java = NULL; address OptoRuntime::_vtable_must_compile_Java = NULL; @@ -154,6 +155,7 @@ gen(env, _multianewarray3_Java , multianewarray3_Type , multianewarray3_C , 0 , true , false, false); gen(env, _multianewarray4_Java , multianewarray4_Type , multianewarray4_C , 0 , true , false, false); gen(env, _multianewarray5_Java , multianewarray5_Type , multianewarray5_C , 0 , true , false, false); + gen(env, _multianewarrayN_Java , multianewarrayN_Type , multianewarrayN_C , 0 , true , false, false); gen(env, _g1_wb_pre_Java , g1_wb_pre_Type , SharedRuntime::g1_wb_pre , 0 , false, false, false); gen(env, _g1_wb_post_Java , g1_wb_post_Type , SharedRuntime::g1_wb_post , 0 , false, false, false); gen(env, _complete_monitor_locking_Java , complete_monitor_enter_Type , SharedRuntime::complete_monitor_locking_C , 0 , false, false, false); @@ -374,6 +376,24 @@ thread->set_vm_result(obj); JRT_END +JRT_ENTRY(void, OptoRuntime::multianewarrayN_C(klassOopDesc* elem_type, arrayOopDesc* dims, JavaThread *thread)) + assert(check_compiled_frame(thread), "incorrect caller"); + assert(oop(elem_type)->is_klass(), "not a class"); + assert(oop(dims)->is_typeArray(), "not an array"); + + ResourceMark rm; + jint len = dims->length(); + assert(len > 0, "Dimensions array should contain data"); + jint *j_dims = typeArrayOop(dims)->int_at_addr(0); + jint *c_dims = NEW_RESOURCE_ARRAY(jint, len); + Copy::conjoint_jints_atomic(j_dims, c_dims, len); + + oop obj = arrayKlass::cast(elem_type)->multi_allocate(len, c_dims, THREAD); + deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION); + thread->set_vm_result(obj); +JRT_END + + const TypeFunc *OptoRuntime::new_instance_Type() { // create input type (domain) const Type **fields = TypeTuple::fields(1); @@ -454,6 +474,21 @@ return multianewarray_Type(5); } +const TypeFunc *OptoRuntime::multianewarrayN_Type() { + // create input type (domain) + const Type **fields = TypeTuple::fields(2); + fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // element klass + fields[TypeFunc::Parms+1] = TypeInstPtr::NOTNULL; // array of dim sizes + const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2, fields); + + // create result type (range) + fields = TypeTuple::fields(1); + fields[TypeFunc::Parms+0] = TypeRawPtr::NOTNULL; // Returned oop + const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+1, fields); + + return TypeFunc::make(domain, range); +} + const TypeFunc *OptoRuntime::g1_wb_pre_Type() { const Type **fields = TypeTuple::fields(2); fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // original field value diff -r 5447b2c582ad -r bcc6475bc68f src/share/vm/opto/runtime.hpp --- a/src/share/vm/opto/runtime.hpp Thu Jul 07 22:34:34 2011 -0400 +++ b/src/share/vm/opto/runtime.hpp Sat Jul 16 22:21:39 2011 -0400 @@ -118,6 +118,7 @@ static address _multianewarray3_Java; static address _multianewarray4_Java; static address _multianewarray5_Java; + static address _multianewarrayN_Java; static address _g1_wb_pre_Java; static address _g1_wb_post_Java; static address _vtable_must_compile_Java; @@ -153,6 +154,7 @@ static void multianewarray3_C(klassOopDesc* klass, int len1, int len2, int len3, JavaThread *thread); static void multianewarray4_C(klassOopDesc* klass, int len1, int len2, int len3, int len4, JavaThread *thread); static void multianewarray5_C(klassOopDesc* klass, int len1, int len2, int len3, int len4, int len5, JavaThread *thread); + static void multianewarrayN_C(klassOopDesc* klass, arrayOopDesc* dims, JavaThread *thread); static void g1_wb_pre_C(oopDesc* orig, JavaThread* thread); static void g1_wb_post_C(void* card_addr, JavaThread* thread); @@ -210,6 +212,7 @@ static address multianewarray3_Java() { return _multianewarray3_Java; } static address multianewarray4_Java() { return _multianewarray4_Java; } static address multianewarray5_Java() { return _multianewarray5_Java; } + static address multianewarrayN_Java() { return _multianewarrayN_Java; } static address g1_wb_pre_Java() { return _g1_wb_pre_Java; } static address g1_wb_post_Java() { return _g1_wb_post_Java; } static address vtable_must_compile_stub() { return _vtable_must_compile_Java; } @@ -249,6 +252,7 @@ static const TypeFunc* multianewarray3_Type(); // multianewarray static const TypeFunc* multianewarray4_Type(); // multianewarray static const TypeFunc* multianewarray5_Type(); // multianewarray + static const TypeFunc* multianewarrayN_Type(); // multianewarray static const TypeFunc* g1_wb_pre_Type(); static const TypeFunc* g1_wb_post_Type(); static const TypeFunc* complete_monitor_enter_Type(); diff -r 5447b2c582ad -r bcc6475bc68f src/share/vm/prims/jni.cpp --- a/src/share/vm/prims/jni.cpp Thu Jul 07 22:34:34 2011 -0400 +++ b/src/share/vm/prims/jni.cpp Sat Jul 16 22:21:39 2011 -0400 @@ -70,15 +70,6 @@ #include "utilities/dtrace.hpp" #include "utilities/events.hpp" #include "utilities/histogram.hpp" -#ifdef TARGET_ARCH_x86 -# include "jniTypes_x86.hpp" -#endif -#ifdef TARGET_ARCH_sparc -# include "jniTypes_sparc.hpp" -#endif -#ifdef TARGET_ARCH_zero -# include "jniTypes_zero.hpp" -#endif #ifdef TARGET_OS_FAMILY_linux # include "os_linux.inline.hpp" # include "thread_linux.inline.hpp" diff -r 5447b2c582ad -r bcc6475bc68f src/share/vm/runtime/arguments.cpp --- a/src/share/vm/runtime/arguments.cpp Thu Jul 07 22:34:34 2011 -0400 +++ b/src/share/vm/runtime/arguments.cpp Sat Jul 16 22:21:39 2011 -0400 @@ -37,15 +37,6 @@ #include "services/management.hpp" #include "utilities/defaultStream.hpp" #include "utilities/taskqueue.hpp" -#ifdef TARGET_ARCH_x86 -# include "vm_version_x86.hpp" -#endif -#ifdef TARGET_ARCH_sparc -# include "vm_version_sparc.hpp" -#endif -#ifdef TARGET_ARCH_zero -# include "vm_version_zero.hpp" -#endif #ifdef TARGET_OS_FAMILY_linux # include "os_linux.inline.hpp" #endif @@ -251,6 +242,11 @@ { "UseParallelOldGCDensePrefix", JDK_Version::jdk_update(6,27), JDK_Version::jdk(8) }, { "AllowTransitionalJSR292", JDK_Version::jdk(7), JDK_Version::jdk(8) }, + { "UseCompressedStrings", JDK_Version::jdk(7), JDK_Version::jdk(8) }, +#ifdef PRODUCT + { "DesiredMethodLimit", + JDK_Version::jdk_update(7, 2), JDK_Version::jdk(8) }, +#endif // PRODUCT { NULL, JDK_Version(0), JDK_Version(0) } }; @@ -2912,6 +2908,18 @@ } } +// Disable options not supported in this release, with a warning if they +// were explicitly requested on the command-line +#define UNSUPPORTED_OPTION(opt, description) \ +do { \ + if (opt) { \ + if (FLAG_IS_CMDLINE(opt)) { \ + warning(description " is disabled in this release."); \ + } \ + FLAG_SET_DEFAULT(opt, false); \ + } \ +} while(0) + // Parse entry point called from JNI_CreateJavaVM jint Arguments::parse(const JavaVMInitArgs* args) { @@ -3009,6 +3017,13 @@ return result; } +#ifdef JAVASE_EMBEDDED + #ifdef PPC + UNSUPPORTED_OPTION(EnableInvokeDynamic, "Invoke dynamic"); + #endif + UNSUPPORTED_OPTION(UseG1GC, "G1 GC"); +#endif + #ifndef PRODUCT if (TraceBytecodesAt != 0) { TraceBytecodes = true; diff -r 5447b2c582ad -r bcc6475bc68f src/share/vm/runtime/atomic.cpp --- a/src/share/vm/runtime/atomic.cpp Thu Jul 07 22:34:34 2011 -0400 +++ b/src/share/vm/runtime/atomic.cpp Sat Jul 16 22:21:39 2011 -0400 @@ -51,6 +51,12 @@ #ifdef TARGET_OS_ARCH_windows_x86 # include "atomic_windows_x86.inline.hpp" #endif +#ifdef TARGET_OS_ARCH_linux_arm +# include "atomic_linux_arm.inline.hpp" +#endif +#ifdef TARGET_OS_ARCH_linux_ppc +# include "atomic_linux_ppc.inline.hpp" +#endif jbyte Atomic::cmpxchg(jbyte exchange_value, volatile jbyte* dest, jbyte compare_value) { assert(sizeof(jbyte) == 1, "assumption."); diff -r 5447b2c582ad -r bcc6475bc68f src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp Thu Jul 07 22:34:34 2011 -0400 +++ b/src/share/vm/runtime/globals.hpp Sat Jul 16 22:21:39 2011 -0400 @@ -343,6 +343,12 @@ #define falseInTiered true #endif +#ifdef JAVASE_EMBEDDED +#define falseInEmbedded false +#else +#define falseInEmbedded true +#endif + // develop flags are settable / visible only during development and are constant in the PRODUCT version // product flags are always settable / visible // notproduct flags are settable / visible only during development and are not declared in the PRODUCT version @@ -438,6 +444,9 @@ product(bool, UsePPCLWSYNC, true, \ "Use lwsync instruction if true, else use slower sync") \ \ + develop(bool, CleanChunkPoolAsync, falseInEmbedded, \ + "Whether to clean the chunk pool asynchronously") \ + \ /* Temporary: See 6948537 */ \ experimental(bool, UseMemSetInBOT, true, \ "(Unstable) uses memset in BOT updates in GC code") \ @@ -492,6 +501,9 @@ product(intx, UseSSE, 99, \ "Highest supported SSE instructions set on x86/x64") \ \ + product(intx, UseVIS, 99, \ + "Highest supported VIS instructions set on Sparc") \ + \ product(uintx, LargePageSizeInBytes, 0, \ "Large page size (0 to let VM choose the page size") \ \ @@ -3611,13 +3623,9 @@ \ /* flags for performance data collection */ \ \ - NOT_EMBEDDED(product(bool, UsePerfData, true, \ + product(bool, UsePerfData, falseInEmbedded, \ "Flag to disable jvmstat instrumentation for performance testing" \ - "and problem isolation purposes.")) \ - \ - EMBEDDED_ONLY(product(bool, UsePerfData, false, \ - "Flag to disable jvmstat instrumentation for performance testing" \ - "and problem isolation purposes.")) \ + "and problem isolation purposes.") \ \ product(bool, PerfDataSaveToFile, false, \ "Save PerfData memory to hsperfdata_ file on exit") \ diff -r 5447b2c582ad -r bcc6475bc68f src/share/vm/runtime/os.cpp --- a/src/share/vm/runtime/os.cpp Thu Jul 07 22:34:34 2011 -0400 +++ b/src/share/vm/runtime/os.cpp Sat Jul 16 22:21:39 2011 -0400 @@ -761,6 +761,7 @@ // st->print("(active %d)", os::active_processor_count()); st->print(" %s", VM_Version::cpu_features()); st->cr(); + pd_print_cpu_info(st); } void os::print_date_and_time(outputStream *st) { diff -r 5447b2c582ad -r bcc6475bc68f src/share/vm/runtime/os.hpp --- a/src/share/vm/runtime/os.hpp Thu Jul 07 22:34:34 2011 -0400 +++ b/src/share/vm/runtime/os.hpp Sat Jul 16 22:21:39 2011 -0400 @@ -480,6 +480,7 @@ // Output format may be different on different platforms. static void print_os_info(outputStream* st); static void print_cpu_info(outputStream* st); + static void pd_print_cpu_info(outputStream* st); static void print_memory_info(outputStream* st); static void print_dll_info(outputStream* st); static void print_environment_variables(outputStream* st, const char** env_list, char* buffer, int len); diff -r 5447b2c582ad -r bcc6475bc68f src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Thu Jul 07 22:34:34 2011 -0400 +++ b/src/share/vm/runtime/thread.cpp Sat Jul 16 22:21:39 2011 -0400 @@ -3347,7 +3347,9 @@ // Notify JVMTI agents that VM initialization is complete - nop if no agents. JvmtiExport::post_vm_initialized(); - Chunk::start_chunk_pool_cleaner_task(); + if (CleanChunkPoolAsync) { + Chunk::start_chunk_pool_cleaner_task(); + } // initialize compiler(s) CompileBroker::compilation_init();