Thu, 08 Dec 2011 10:27:33 -0800
Merge
make/jprt.properties | file | annotate | diff | comparison | revisions | |
src/share/vm/runtime/globals.hpp | file | annotate | diff | comparison | revisions |
1.1 --- a/make/jprt.properties Wed Dec 07 07:27:09 2011 -0800 1.2 +++ b/make/jprt.properties Thu Dec 08 10:27:33 2011 -0800 1.3 @@ -248,7 +248,7 @@ 1.4 1.5 jprt.my.solaris.sparc.test.targets= \ 1.6 ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jvm98, \ 1.7 - ${jprt.my.solaris.sparc}-{product|fastdebug}-c2-jvm98_tiered, \ 1.8 + ${jprt.my.solaris.sparc}-{product|fastdebug}-c2-jvm98_nontiered, \ 1.9 ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-scimark, \ 1.10 ${jprt.my.solaris.sparc}-product-{c1|c2}-runThese, \ 1.11 ${jprt.my.solaris.sparc}-fastdebug-c1-runThese_Xshare, \ 1.12 @@ -267,7 +267,7 @@ 1.13 ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCOld_G1, \ 1.14 ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCOld_ParOldGC, \ 1.15 ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_default, \ 1.16 - ${jprt.my.solaris.sparc}-{product|fastdebug}-c2-jbb_default_tiered, \ 1.17 + ${jprt.my.solaris.sparc}-{product|fastdebug}-c2-jbb_default_nontiered, \ 1.18 ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_SerialGC, \ 1.19 ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_ParallelGC, \ 1.20 ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_CMS, \ 1.21 @@ -276,7 +276,7 @@ 1.22 1.23 jprt.my.solaris.sparcv9.test.targets= \ 1.24 ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jvm98, \ 1.25 - ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jvm98_tiered, \ 1.26 + ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jvm98_nontiered, \ 1.27 ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-scimark, \ 1.28 ${jprt.my.solaris.sparcv9}-product-c2-runThese, \ 1.29 ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_default, \ 1.30 @@ -294,7 +294,7 @@ 1.31 ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCOld_G1, \ 1.32 ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCOld_ParOldGC, \ 1.33 ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_default, \ 1.34 - ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_default_tiered, \ 1.35 + ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_default_nontiered, \ 1.36 ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_SerialGC, \ 1.37 ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_ParallelGC, \ 1.38 ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_CMS, \ 1.39 @@ -303,7 +303,7 @@ 1.40 1.41 jprt.my.solaris.x64.test.targets= \ 1.42 ${jprt.my.solaris.x64}-{product|fastdebug}-c2-jvm98, \ 1.43 - ${jprt.my.solaris.x64}-{product|fastdebug}-c2-jvm98_tiered, \ 1.44 + ${jprt.my.solaris.x64}-{product|fastdebug}-c2-jvm98_nontiered, \ 1.45 ${jprt.my.solaris.x64}-{product|fastdebug}-c2-scimark, \ 1.46 ${jprt.my.solaris.x64}-product-c2-runThese, \ 1.47 ${jprt.my.solaris.x64}-product-c2-runThese_Xcomp, \ 1.48 @@ -322,7 +322,7 @@ 1.49 ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_G1, \ 1.50 ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_ParOldGC, \ 1.51 ${jprt.my.solaris.x64}-{product|fastdebug}-c2-jbb_default, \ 1.52 - ${jprt.my.solaris.x64}-{product|fastdebug}-c2-jbb_default_tiered, \ 1.53 + ${jprt.my.solaris.x64}-{product|fastdebug}-c2-jbb_default_nontiered, \ 1.54 ${jprt.my.solaris.x64}-{product|fastdebug}-c2-jbb_SerialGC, \ 1.55 ${jprt.my.solaris.x64}-{product|fastdebug}-c2-jbb_ParallelGC, \ 1.56 ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_CMS, \ 1.57 @@ -331,7 +331,7 @@ 1.58 1.59 jprt.my.solaris.i586.test.targets= \ 1.60 ${jprt.my.solaris.i586}-{product|fastdebug}-{c1|c2}-jvm98, \ 1.61 - ${jprt.my.solaris.i586}-{product|fastdebug}-c2-jvm98_tiered, \ 1.62 + ${jprt.my.solaris.i586}-{product|fastdebug}-c2-jvm98_nontiered, \ 1.63 ${jprt.my.solaris.i586}-{product|fastdebug}-{c1|c2}-scimark, \ 1.64 ${jprt.my.solaris.i586}-product-{c1|c2}-runThese_Xcomp, \ 1.65 ${jprt.my.solaris.i586}-fastdebug-c1-runThese_Xcomp, \ 1.66 @@ -358,7 +358,7 @@ 1.67 ${jprt.my.solaris.i586}-product-c1-GCOld_G1, \ 1.68 ${jprt.my.solaris.i586}-product-c1-GCOld_ParOldGC, \ 1.69 ${jprt.my.solaris.i586}-fastdebug-c2-jbb_default, \ 1.70 - ${jprt.my.solaris.i586}-fastdebug-c2-jbb_default_tiered, \ 1.71 + ${jprt.my.solaris.i586}-fastdebug-c2-jbb_default_nontiered, \ 1.72 ${jprt.my.solaris.i586}-fastdebug-c2-jbb_ParallelGC, \ 1.73 ${jprt.my.solaris.i586}-fastdebug-c2-jbb_CMS, \ 1.74 ${jprt.my.solaris.i586}-fastdebug-c2-jbb_G1, \ 1.75 @@ -366,7 +366,7 @@ 1.76 1.77 jprt.my.linux.i586.test.targets = \ 1.78 ${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-jvm98, \ 1.79 - ${jprt.my.linux.i586}-{product|fastdebug}-c2-jvm98_tiered, \ 1.80 + ${jprt.my.linux.i586}-{product|fastdebug}-c2-jvm98_nontiered, \ 1.81 ${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-scimark, \ 1.82 ${jprt.my.linux.i586}-product-c1-runThese_Xcomp, \ 1.83 ${jprt.my.linux.i586}-fastdebug-c1-runThese_Xshare, \ 1.84 @@ -386,7 +386,7 @@ 1.85 ${jprt.my.linux.i586}-product-{c1|c2}-GCOld_G1, \ 1.86 ${jprt.my.linux.i586}-product-{c1|c2}-GCOld_ParOldGC, \ 1.87 ${jprt.my.linux.i586}-{product|fastdebug}-c1-jbb_default, \ 1.88 - ${jprt.my.linux.i586}-{product|fastdebug}-c2-jbb_default_tiered, \ 1.89 + ${jprt.my.linux.i586}-{product|fastdebug}-c2-jbb_default_nontiered, \ 1.90 ${jprt.my.linux.i586}-{product|fastdebug}-c1-jbb_ParallelGC, \ 1.91 ${jprt.my.linux.i586}-{product|fastdebug}-c1-jbb_CMS, \ 1.92 ${jprt.my.linux.i586}-{product|fastdebug}-c1-jbb_G1, \ 1.93 @@ -394,7 +394,7 @@ 1.94 1.95 jprt.my.linux.x64.test.targets = \ 1.96 ${jprt.my.linux.x64}-{product|fastdebug}-c2-jvm98, \ 1.97 - ${jprt.my.linux.x64}-{product|fastdebug}-c2-jvm98_tiered, \ 1.98 + ${jprt.my.linux.x64}-{product|fastdebug}-c2-jvm98_nontiered, \ 1.99 ${jprt.my.linux.x64}-{product|fastdebug}-c2-scimark, \ 1.100 ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCBasher_default, \ 1.101 ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCBasher_SerialGC, \ 1.102 @@ -411,14 +411,14 @@ 1.103 ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCOld_G1, \ 1.104 ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCOld_ParOldGC, \ 1.105 ${jprt.my.linux.x64}-{product|fastdebug}-c2-jbb_default, \ 1.106 - ${jprt.my.linux.x64}-{product|fastdebug}-c2-jbb_default_tiered, \ 1.107 + ${jprt.my.linux.x64}-{product|fastdebug}-c2-jbb_default_nontiered, \ 1.108 ${jprt.my.linux.x64}-{product|fastdebug}-c2-jbb_ParallelGC, \ 1.109 ${jprt.my.linux.x64}-{product|fastdebug}-c2-jbb_G1, \ 1.110 ${jprt.my.linux.x64}-{product|fastdebug}-c2-jbb_ParOldGC 1.111 1.112 jprt.my.windows.i586.test.targets = \ 1.113 ${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-jvm98, \ 1.114 - ${jprt.my.windows.i586}-{product|fastdebug}-c2-jvm98_tiered, \ 1.115 + ${jprt.my.windows.i586}-{product|fastdebug}-c2-jvm98_nontiered, \ 1.116 ${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-scimark, \ 1.117 ${jprt.my.windows.i586}-product-{c1|c2}-runThese, \ 1.118 ${jprt.my.windows.i586}-product-{c1|c2}-runThese_Xcomp, \ 1.119 @@ -438,7 +438,7 @@ 1.120 ${jprt.my.windows.i586}-product-{c1|c2}-GCOld_G1, \ 1.121 ${jprt.my.windows.i586}-product-{c1|c2}-GCOld_ParOldGC, \ 1.122 ${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-jbb_default, \ 1.123 - ${jprt.my.windows.i586}-{product|fastdebug}-c2-jbb_default_tiered, \ 1.124 + ${jprt.my.windows.i586}-{product|fastdebug}-c2-jbb_default_nontiered, \ 1.125 ${jprt.my.windows.i586}-product-{c1|c2}-jbb_ParallelGC, \ 1.126 ${jprt.my.windows.i586}-product-{c1|c2}-jbb_CMS, \ 1.127 ${jprt.my.windows.i586}-product-{c1|c2}-jbb_G1, \ 1.128 @@ -446,7 +446,7 @@ 1.129 1.130 jprt.my.windows.x64.test.targets = \ 1.131 ${jprt.my.windows.x64}-{product|fastdebug}-c2-jvm98, \ 1.132 - ${jprt.my.windows.x64}-{product|fastdebug}-c2-jvm98_tiered, \ 1.133 + ${jprt.my.windows.x64}-{product|fastdebug}-c2-jvm98_nontiered, \ 1.134 ${jprt.my.windows.x64}-{product|fastdebug}-c2-scimark, \ 1.135 ${jprt.my.windows.x64}-product-c2-runThese, \ 1.136 ${jprt.my.windows.x64}-product-c2-runThese_Xcomp, \ 1.137 @@ -465,7 +465,7 @@ 1.138 ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCOld_G1, \ 1.139 ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCOld_ParOldGC, \ 1.140 ${jprt.my.windows.x64}-{product|fastdebug}-c2-jbb_default, \ 1.141 - ${jprt.my.windows.x64}-{product|fastdebug}-c2-jbb_default_tiered, \ 1.142 + ${jprt.my.windows.x64}-{product|fastdebug}-c2-jbb_default_nontiered, \ 1.143 ${jprt.my.windows.x64}-product-c2-jbb_CMS, \ 1.144 ${jprt.my.windows.x64}-product-c2-jbb_ParallelGC, \ 1.145 ${jprt.my.windows.x64}-product-c2-jbb_G1, \ 1.146 @@ -473,9 +473,9 @@ 1.147 1.148 # Some basic "smoke" tests for OpenJDK builds 1.149 jprt.test.targets.open = \ 1.150 - ${jprt.my.solaris.x64}-{productOpen|debugOpen|fastdebugOpen}-c2-jvm98_tiered, \ 1.151 - ${jprt.my.solaris.i586}-{productOpen|fastdebugOpen}-c2-jvm98_tiered, \ 1.152 - ${jprt.my.linux.x64}-{productOpen|fastdebugOpen}-c2-jvm98_tiered 1.153 + ${jprt.my.solaris.x64}-{productOpen|debugOpen|fastdebugOpen}-c2-jvm98, \ 1.154 + ${jprt.my.solaris.i586}-{productOpen|fastdebugOpen}-c2-jvm98, \ 1.155 + ${jprt.my.linux.x64}-{productOpen|fastdebugOpen}-c2-jvm98 1.156 1.157 # Testing for actual embedded builds is different to standard 1.158 jprt.my.linux.i586.test.targets.embedded = \
2.1 --- a/src/cpu/sparc/vm/assembler_sparc.hpp Wed Dec 07 07:27:09 2011 -0800 2.2 +++ b/src/cpu/sparc/vm/assembler_sparc.hpp Thu Dec 08 10:27:33 2011 -0800 2.3 @@ -855,12 +855,6 @@ 2.4 Lookaside = 1 << 4 2.5 }; 2.6 2.7 - // test if x is within signed immediate range for nbits 2.8 - static bool is_simm(intptr_t x, int nbits) { return -( intptr_t(1) << nbits-1 ) <= x && x < ( intptr_t(1) << nbits-1 ); } 2.9 - 2.10 - // test if -4096 <= x <= 4095 2.11 - static bool is_simm13(intptr_t x) { return is_simm(x, 13); } 2.12 - 2.13 static bool is_in_wdisp_range(address a, address b, int nbits) { 2.14 intptr_t d = intptr_t(b) - intptr_t(a); 2.15 return is_simm(d, nbits + 2); 2.16 @@ -1203,7 +1197,7 @@ 2.17 if (!UseCBCond || cbcond_before()) return false; 2.18 intptr_t x = intptr_t(target_distance(L)) - intptr_t(pc()); 2.19 assert( (x & 3) == 0, "not word aligned"); 2.20 - return is_simm(x, 12); 2.21 + return is_simm12(x); 2.22 } 2.23 2.24 // Tells assembler you know that next instruction is delayed
3.1 --- a/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Wed Dec 07 07:27:09 2011 -0800 3.2 +++ b/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Thu Dec 08 10:27:33 2011 -0800 3.3 @@ -765,7 +765,7 @@ 3.4 void LIR_Assembler::vtable_call(LIR_OpJavaCall* op) { 3.5 add_debug_info_for_null_check_here(op->info()); 3.6 __ load_klass(O0, G3_scratch); 3.7 - if (__ is_simm13(op->vtable_offset())) { 3.8 + if (Assembler::is_simm13(op->vtable_offset())) { 3.9 __ ld_ptr(G3_scratch, op->vtable_offset(), G5_method); 3.10 } else { 3.11 // This will generate 2 instructions
4.1 --- a/src/cpu/sparc/vm/c2_globals_sparc.hpp Wed Dec 07 07:27:09 2011 -0800 4.2 +++ b/src/cpu/sparc/vm/c2_globals_sparc.hpp Thu Dec 08 10:27:33 2011 -0800 4.3 @@ -42,7 +42,7 @@ 4.4 #else 4.5 define_pd_global(bool, ProfileInterpreter, true); 4.6 #endif // CC_INTERP 4.7 -define_pd_global(bool, TieredCompilation, false); 4.8 +define_pd_global(bool, TieredCompilation, true); 4.9 define_pd_global(intx, CompileThreshold, 10000); 4.10 define_pd_global(intx, BackEdgeThreshold, 140000); 4.11
5.1 --- a/src/cpu/sparc/vm/methodHandles_sparc.cpp Wed Dec 07 07:27:09 2011 -0800 5.2 +++ b/src/cpu/sparc/vm/methodHandles_sparc.cpp Thu Dec 08 10:27:33 2011 -0800 5.3 @@ -315,7 +315,7 @@ 5.4 __ cmp_and_br_short(O7_temp, T_VOID, Assembler::equal, Assembler::pt, L_ok_4); 5.5 extract_conversion_vminfo(_masm, L5_conversion, O5_temp); 5.6 __ ld_ptr(L4_saved_args_base, __ argument_offset(O5_temp, O5_temp), O7_temp); 5.7 - assert(__ is_simm13(RETURN_VALUE_PLACEHOLDER), "must be simm13"); 5.8 + assert(Assembler::is_simm13(RETURN_VALUE_PLACEHOLDER), "must be simm13"); 5.9 __ cmp_and_brx_short(O7_temp, (int32_t) RETURN_VALUE_PLACEHOLDER, Assembler::equal, Assembler::pt, L_ok_4); 5.10 __ stop("damaged ricochet frame: RETURN_VALUE_PLACEHOLDER not found"); 5.11 __ BIND(L_ok_4);
6.1 --- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Wed Dec 07 07:27:09 2011 -0800 6.2 +++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Thu Dec 08 10:27:33 2011 -0800 6.3 @@ -767,7 +767,7 @@ 6.4 // In the 64bit build because of wider slots and STACKBIAS we can run 6.5 // out of bits in the displacement to do loads and stores. Use g3 as 6.6 // temporary displacement. 6.7 - if (! __ is_simm13(extraspace)) { 6.8 + if (!Assembler::is_simm13(extraspace)) { 6.9 __ set(extraspace, G3_scratch); 6.10 __ sub(SP, G3_scratch, SP); 6.11 } else {
7.1 --- a/src/cpu/sparc/vm/sparc.ad Wed Dec 07 07:27:09 2011 -0800 7.2 +++ b/src/cpu/sparc/vm/sparc.ad Thu Dec 08 10:27:33 2011 -0800 7.3 @@ -566,7 +566,7 @@ 7.4 } else { 7.5 klass_load_size = 1*BytesPerInstWord; 7.6 } 7.7 - if( Assembler::is_simm13(v_off) ) { 7.8 + if (Assembler::is_simm13(v_off)) { 7.9 return klass_load_size + 7.10 (2*BytesPerInstWord + // ld_ptr, ld_ptr 7.11 NativeCall::instruction_size); // call; delay slot 7.12 @@ -1019,8 +1019,21 @@ 7.13 7.14 7.15 //============================================================================= 7.16 -const bool Matcher::constant_table_absolute_addressing = false; 7.17 -const RegMask& MachConstantBaseNode::_out_RegMask = PTR_REG_mask; 7.18 +const RegMask& MachConstantBaseNode::_out_RegMask = PTR_REG_mask(); 7.19 + 7.20 +int Compile::ConstantTable::calculate_table_base_offset() const { 7.21 + if (UseRDPCForConstantTableBase) { 7.22 + // The table base offset might be less but then it fits into 7.23 + // simm13 anyway and we are good (cf. MachConstantBaseNode::emit). 7.24 + return Assembler::min_simm13(); 7.25 + } else { 7.26 + int offset = -(size() / 2); 7.27 + if (!Assembler::is_simm13(offset)) { 7.28 + offset = Assembler::min_simm13(); 7.29 + } 7.30 + return offset; 7.31 + } 7.32 +} 7.33 7.34 void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { 7.35 Compile* C = ra_->C; 7.36 @@ -1028,8 +1041,9 @@ 7.37 MacroAssembler _masm(&cbuf); 7.38 7.39 Register r = as_Register(ra_->get_encode(this)); 7.40 - CodeSection* cs = __ code()->consts(); 7.41 - int consts_size = cs->align_at_start(cs->size()); 7.42 + CodeSection* consts_section = __ code()->consts(); 7.43 + int consts_size = consts_section->align_at_start(consts_section->size()); 7.44 + assert(constant_table.size() == consts_size, err_msg("must be: %d == %d", constant_table.size(), consts_size)); 7.45 7.46 if (UseRDPCForConstantTableBase) { 7.47 // For the following RDPC logic to work correctly the consts 7.48 @@ -1037,30 +1051,37 @@ 7.49 // assert checks for that. The layout and the SECT_* constants 7.50 // are defined in src/share/vm/asm/codeBuffer.hpp. 7.51 assert(CodeBuffer::SECT_CONSTS + 1 == CodeBuffer::SECT_INSTS, "must be"); 7.52 - int offset = __ offset(); 7.53 + int insts_offset = __ offset(); 7.54 + 7.55 + // Layout: 7.56 + // 7.57 + // |----------- consts section ------------|----------- insts section -----------... 7.58 + // |------ constant table -----|- padding -|------------------x---- 7.59 + // \ current PC (RDPC instruction) 7.60 + // |<------------- consts_size ----------->|<- insts_offset ->| 7.61 + // \ table base 7.62 + // The table base offset is later added to the load displacement 7.63 + // so it has to be negative. 7.64 + int table_base_offset = -(consts_size + insts_offset); 7.65 int disp; 7.66 7.67 // If the displacement from the current PC to the constant table 7.68 // base fits into simm13 we set the constant table base to the 7.69 // current PC. 7.70 - if (__ is_simm13(-(consts_size + offset))) { 7.71 - constant_table.set_table_base_offset(-(consts_size + offset)); 7.72 + if (Assembler::is_simm13(table_base_offset)) { 7.73 + constant_table.set_table_base_offset(table_base_offset); 7.74 disp = 0; 7.75 } else { 7.76 - // If the offset of the top constant (last entry in the table) 7.77 - // fits into simm13 we set the constant table base to the actual 7.78 - // table base. 7.79 - if (__ is_simm13(constant_table.top_offset())) { 7.80 - constant_table.set_table_base_offset(0); 7.81 - disp = consts_size + offset; 7.82 - } else { 7.83 - // Otherwise we set the constant table base in the middle of the 7.84 - // constant table. 7.85 - int half_consts_size = consts_size / 2; 7.86 - assert(half_consts_size * 2 == consts_size, "sanity"); 7.87 - constant_table.set_table_base_offset(-half_consts_size); // table base offset gets added to the load displacement. 7.88 - disp = half_consts_size + offset; 7.89 - } 7.90 + // Otherwise we set the constant table base offset to the 7.91 + // maximum negative displacement of load instructions to keep 7.92 + // the disp as small as possible: 7.93 + // 7.94 + // |<------------- consts_size ----------->|<- insts_offset ->| 7.95 + // |<--------- min_simm13 --------->|<-------- disp --------->| 7.96 + // \ table base 7.97 + table_base_offset = Assembler::min_simm13(); 7.98 + constant_table.set_table_base_offset(table_base_offset); 7.99 + disp = (consts_size + insts_offset) + table_base_offset; 7.100 } 7.101 7.102 __ rdpc(r); 7.103 @@ -1072,8 +1093,7 @@ 7.104 } 7.105 else { 7.106 // Materialize the constant table base. 7.107 - assert(constant_table.size() == consts_size, err_msg("must be: %d == %d", constant_table.size(), consts_size)); 7.108 - address baseaddr = cs->start() + -(constant_table.table_base_offset()); 7.109 + address baseaddr = consts_section->start() + -(constant_table.table_base_offset()); 7.110 RelocationHolder rspec = internal_word_Relocation::spec(baseaddr); 7.111 AddressLiteral base(baseaddr, rspec); 7.112 __ set(base, r); 7.113 @@ -1169,6 +1189,13 @@ 7.114 __ save(SP, G3, SP); 7.115 } 7.116 C->set_frame_complete( __ offset() ); 7.117 + 7.118 + if (!UseRDPCForConstantTableBase && C->has_mach_constant_base_node()) { 7.119 + // NOTE: We set the table base offset here because users might be 7.120 + // emitted before MachConstantBaseNode. 7.121 + Compile::ConstantTable& constant_table = C->constant_table(); 7.122 + constant_table.set_table_base_offset(constant_table.calculate_table_base_offset()); 7.123 + } 7.124 } 7.125 7.126 uint MachPrologNode::size(PhaseRegAlloc *ra_) const { 7.127 @@ -1843,7 +1870,7 @@ 7.128 bool Matcher::is_short_branch_offset(int rule, int br_size, int offset) { 7.129 // The passed offset is relative to address of the branch. 7.130 // Don't need to adjust the offset. 7.131 - return UseCBCond && Assembler::is_simm(offset, 12); 7.132 + return UseCBCond && Assembler::is_simm12(offset); 7.133 } 7.134 7.135 const bool Matcher::isSimpleConstant64(jlong value) { 7.136 @@ -1997,7 +2024,7 @@ 7.137 } 7.138 7.139 const RegMask Matcher::method_handle_invoke_SP_save_mask() { 7.140 - return L7_REGP_mask; 7.141 + return L7_REGP_mask(); 7.142 } 7.143 7.144 %} 7.145 @@ -2072,8 +2099,8 @@ 7.146 %} 7.147 7.148 enc_class form3_mem_reg_long_unaligned_marshal( memory mem, iRegL reg ) %{ 7.149 - assert( Assembler::is_simm13($mem$$disp ), "need disp and disp+4" ); 7.150 - assert( Assembler::is_simm13($mem$$disp+4), "need disp and disp+4" ); 7.151 + assert(Assembler::is_simm13($mem$$disp ), "need disp and disp+4"); 7.152 + assert(Assembler::is_simm13($mem$$disp+4), "need disp and disp+4"); 7.153 guarantee($mem$$index == R_G0_enc, "double index?"); 7.154 emit_form3_mem_reg(cbuf, this, $primary, -1, $mem$$base, $mem$$disp+4, R_G0_enc, R_O7_enc ); 7.155 emit_form3_mem_reg(cbuf, this, $primary, -1, $mem$$base, $mem$$disp, R_G0_enc, $reg$$reg ); 7.156 @@ -2082,8 +2109,8 @@ 7.157 %} 7.158 7.159 enc_class form3_mem_reg_double_unaligned( memory mem, RegD_low reg ) %{ 7.160 - assert( Assembler::is_simm13($mem$$disp ), "need disp and disp+4" ); 7.161 - assert( Assembler::is_simm13($mem$$disp+4), "need disp and disp+4" ); 7.162 + assert(Assembler::is_simm13($mem$$disp ), "need disp and disp+4"); 7.163 + assert(Assembler::is_simm13($mem$$disp+4), "need disp and disp+4"); 7.164 guarantee($mem$$index == R_G0_enc, "double index?"); 7.165 // Load long with 2 instructions 7.166 emit_form3_mem_reg(cbuf, this, $primary, -1, $mem$$base, $mem$$disp, R_G0_enc, $reg$$reg+0 ); 7.167 @@ -2563,7 +2590,7 @@ 7.168 } 7.169 int entry_offset = instanceKlass::vtable_start_offset() + vtable_index*vtableEntry::size(); 7.170 int v_off = entry_offset*wordSize + vtableEntry::method_offset_in_bytes(); 7.171 - if( __ is_simm13(v_off) ) { 7.172 + if (Assembler::is_simm13(v_off)) { 7.173 __ ld_ptr(G3, v_off, G5_method); 7.174 } else { 7.175 // Generate 2 instructions 7.176 @@ -3336,7 +3363,7 @@ 7.177 7.178 // Integer Immediate: 8-bit 7.179 operand immI8() %{ 7.180 - predicate(Assembler::is_simm(n->get_int(), 8)); 7.181 + predicate(Assembler::is_simm8(n->get_int())); 7.182 match(ConI); 7.183 op_cost(0); 7.184 format %{ %} 7.185 @@ -3365,7 +3392,7 @@ 7.186 7.187 // Integer Immediate: 16-bit 7.188 operand immI16() %{ 7.189 - predicate(Assembler::is_simm(n->get_int(), 16)); 7.190 + predicate(Assembler::is_simm16(n->get_int())); 7.191 match(ConI); 7.192 op_cost(0); 7.193 format %{ %} 7.194 @@ -3393,7 +3420,7 @@ 7.195 7.196 // Integer Immediate: 11-bit 7.197 operand immI11() %{ 7.198 - predicate(Assembler::is_simm(n->get_int(),11)); 7.199 + predicate(Assembler::is_simm11(n->get_int())); 7.200 match(ConI); 7.201 op_cost(0); 7.202 format %{ %} 7.203 @@ -3402,7 +3429,7 @@ 7.204 7.205 // Integer Immediate: 5-bit 7.206 operand immI5() %{ 7.207 - predicate(Assembler::is_simm(n->get_int(), 5)); 7.208 + predicate(Assembler::is_simm5(n->get_int())); 7.209 match(ConI); 7.210 op_cost(0); 7.211 format %{ %} 7.212 @@ -3634,7 +3661,7 @@ 7.213 7.214 // Integer Immediate: 5-bit 7.215 operand immL5() %{ 7.216 - predicate(n->get_long() == (int)n->get_long() && Assembler::is_simm((int)n->get_long(), 5)); 7.217 + predicate(n->get_long() == (int)n->get_long() && Assembler::is_simm5((int)n->get_long())); 7.218 match(ConL); 7.219 op_cost(0); 7.220 format %{ %} 7.221 @@ -9251,13 +9278,16 @@ 7.222 7.223 format %{ "ADD $constanttablebase, $constantoffset, O7\n\t" 7.224 "LD [O7 + $switch_val], O7\n\t" 7.225 - "JUMP O7" 7.226 - %} 7.227 + "JUMP O7" %} 7.228 ins_encode %{ 7.229 // Calculate table address into a register. 7.230 Register table_reg; 7.231 Register label_reg = O7; 7.232 - if (constant_offset() == 0) { 7.233 + // If we are calculating the size of this instruction don't trust 7.234 + // zero offsets because they might change when 7.235 + // MachConstantBaseNode decides to optimize the constant table 7.236 + // base. 7.237 + if ((constant_offset() == 0) && !Compile::current()->in_scratch_emit_size()) { 7.238 table_reg = $constanttablebase; 7.239 } else { 7.240 table_reg = O7;
8.1 --- a/src/cpu/sparc/vm/vtableStubs_sparc.cpp Wed Dec 07 07:27:09 2011 -0800 8.2 +++ b/src/cpu/sparc/vm/vtableStubs_sparc.cpp Thu Dec 08 10:27:33 2011 -0800 8.3 @@ -1,5 +1,5 @@ 8.4 /* 8.5 - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. 8.6 + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. 8.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 8.8 * 8.9 * This code is free software; you can redistribute it and/or modify it 8.10 @@ -83,7 +83,7 @@ 8.11 } 8.12 #endif 8.13 int v_off = entry_offset*wordSize + vtableEntry::method_offset_in_bytes(); 8.14 - if( __ is_simm13(v_off) ) { 8.15 + if (Assembler::is_simm13(v_off)) { 8.16 __ ld_ptr(G3, v_off, G5_method); 8.17 } else { 8.18 __ set(v_off,G5);
9.1 --- a/src/cpu/x86/vm/assembler_x86.cpp Wed Dec 07 07:27:09 2011 -0800 9.2 +++ b/src/cpu/x86/vm/assembler_x86.cpp Thu Dec 08 10:27:33 2011 -0800 9.3 @@ -3535,7 +3535,8 @@ 9.4 // addressing. 9.5 bool Assembler::is_polling_page_far() { 9.6 intptr_t addr = (intptr_t)os::get_polling_page(); 9.7 - return !is_simm32(addr - (intptr_t)CodeCache::low_bound()) || 9.8 + return ForceUnreachable || 9.9 + !is_simm32(addr - (intptr_t)CodeCache::low_bound()) || 9.10 !is_simm32(addr - (intptr_t)CodeCache::high_bound()); 9.11 } 9.12
10.1 --- a/src/cpu/x86/vm/assembler_x86.hpp Wed Dec 07 07:27:09 2011 -0800 10.2 +++ b/src/cpu/x86/vm/assembler_x86.hpp Thu Dec 08 10:27:33 2011 -0800 10.3 @@ -693,17 +693,6 @@ 10.4 static address locate_next_instruction(address inst); 10.5 10.6 // Utilities 10.7 - 10.8 -#ifdef _LP64 10.9 - static bool is_simm(int64_t x, int nbits) { return -(CONST64(1) << (nbits-1)) <= x && 10.10 - x < (CONST64(1) << (nbits-1)); } 10.11 - static bool is_simm32(int64_t x) { return x == (int64_t)(int32_t)x; } 10.12 -#else 10.13 - static bool is_simm(int32_t x, int nbits) { return -(1 << (nbits-1)) <= x && 10.14 - x < (1 << (nbits-1)); } 10.15 - static bool is_simm32(int32_t x) { return true; } 10.16 -#endif // _LP64 10.17 - 10.18 static bool is_polling_page_far() NOT_LP64({ return false;}); 10.19 10.20 // Generic instructions
11.1 --- a/src/cpu/x86/vm/c2_globals_x86.hpp Wed Dec 07 07:27:09 2011 -0800 11.2 +++ b/src/cpu/x86/vm/c2_globals_x86.hpp Thu Dec 08 10:27:33 2011 -0800 11.3 @@ -44,7 +44,7 @@ 11.4 #else 11.5 define_pd_global(bool, ProfileInterpreter, true); 11.6 #endif // CC_INTERP 11.7 -define_pd_global(bool, TieredCompilation, false); 11.8 +define_pd_global(bool, TieredCompilation, true); 11.9 define_pd_global(intx, CompileThreshold, 10000); 11.10 define_pd_global(intx, BackEdgeThreshold, 100000); 11.11
12.1 --- a/src/cpu/x86/vm/methodHandles_x86.hpp Wed Dec 07 07:27:09 2011 -0800 12.2 +++ b/src/cpu/x86/vm/methodHandles_x86.hpp Thu Dec 08 10:27:33 2011 -0800 12.3 @@ -27,7 +27,7 @@ 12.4 12.5 // Adapters 12.6 enum /* platform_dependent_constants */ { 12.7 - adapter_code_size = NOT_LP64(16000 DEBUG_ONLY(+ 15000)) LP64_ONLY(32000 DEBUG_ONLY(+ 80000)) 12.8 + adapter_code_size = NOT_LP64(16000 DEBUG_ONLY(+ 15000)) LP64_ONLY(32000 DEBUG_ONLY(+ 120000)) 12.9 }; 12.10 12.11 public:
13.1 --- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp Wed Dec 07 07:27:09 2011 -0800 13.2 +++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp Thu Dec 08 10:27:33 2011 -0800 13.3 @@ -95,6 +95,7 @@ 13.4 #define inc_counter_np(counter) (0) 13.5 #else 13.6 void inc_counter_np_(int& counter) { 13.7 + // This can destroy rscratch1 if counter is far from the code cache 13.8 __ incrementl(ExternalAddress((address)&counter)); 13.9 } 13.10 #define inc_counter_np(counter) \ 13.11 @@ -1268,7 +1269,7 @@ 13.12 __ subptr(end, start); // number of bytes to copy 13.13 13.14 intptr_t disp = (intptr_t) ct->byte_map_base; 13.15 - if (__ is_simm32(disp)) { 13.16 + if (Assembler::is_simm32(disp)) { 13.17 Address cardtable(noreg, noreg, Address::no_scale, disp); 13.18 __ lea(scratch, cardtable); 13.19 } else { 13.20 @@ -1466,8 +1467,8 @@ 13.21 __ movb(Address(end_to, 8), rax); 13.22 13.23 __ BIND(L_exit); 13.24 - inc_counter_np(SharedRuntime::_jbyte_array_copy_ctr); 13.25 restore_arg_regs(); 13.26 + inc_counter_np(SharedRuntime::_jbyte_array_copy_ctr); // Update counter after rscratch1 is free 13.27 __ xorptr(rax, rax); // return 0 13.28 __ leave(); // required for proper stackwalking of RuntimeStub frame 13.29 __ ret(0); 13.30 @@ -1555,8 +1556,8 @@ 13.31 __ decrement(qword_count); 13.32 __ jcc(Assembler::notZero, L_copy_8_bytes); 13.33 13.34 - inc_counter_np(SharedRuntime::_jbyte_array_copy_ctr); 13.35 restore_arg_regs(); 13.36 + inc_counter_np(SharedRuntime::_jbyte_array_copy_ctr); // Update counter after rscratch1 is free 13.37 __ xorptr(rax, rax); // return 0 13.38 __ leave(); // required for proper stackwalking of RuntimeStub frame 13.39 __ ret(0); 13.40 @@ -1564,8 +1565,8 @@ 13.41 // Copy in 32-bytes chunks 13.42 copy_32_bytes_backward(from, to, qword_count, rax, L_copy_32_bytes, L_copy_8_bytes); 13.43 13.44 - inc_counter_np(SharedRuntime::_jbyte_array_copy_ctr); 13.45 restore_arg_regs(); 13.46 + inc_counter_np(SharedRuntime::_jbyte_array_copy_ctr); // Update counter after rscratch1 is free 13.47 __ xorptr(rax, rax); // return 0 13.48 __ leave(); // required for proper stackwalking of RuntimeStub frame 13.49 __ ret(0); 13.50 @@ -1658,8 +1659,8 @@ 13.51 __ movw(Address(end_to, 8), rax); 13.52 13.53 __ BIND(L_exit); 13.54 - inc_counter_np(SharedRuntime::_jshort_array_copy_ctr); 13.55 restore_arg_regs(); 13.56 + inc_counter_np(SharedRuntime::_jshort_array_copy_ctr); // Update counter after rscratch1 is free 13.57 __ xorptr(rax, rax); // return 0 13.58 __ leave(); // required for proper stackwalking of RuntimeStub frame 13.59 __ ret(0); 13.60 @@ -1759,8 +1760,8 @@ 13.61 __ decrement(qword_count); 13.62 __ jcc(Assembler::notZero, L_copy_8_bytes); 13.63 13.64 - inc_counter_np(SharedRuntime::_jshort_array_copy_ctr); 13.65 restore_arg_regs(); 13.66 + inc_counter_np(SharedRuntime::_jshort_array_copy_ctr); // Update counter after rscratch1 is free 13.67 __ xorptr(rax, rax); // return 0 13.68 __ leave(); // required for proper stackwalking of RuntimeStub frame 13.69 __ ret(0); 13.70 @@ -1768,8 +1769,8 @@ 13.71 // Copy in 32-bytes chunks 13.72 copy_32_bytes_backward(from, to, qword_count, rax, L_copy_32_bytes, L_copy_8_bytes); 13.73 13.74 - inc_counter_np(SharedRuntime::_jshort_array_copy_ctr); 13.75 restore_arg_regs(); 13.76 + inc_counter_np(SharedRuntime::_jshort_array_copy_ctr); // Update counter after rscratch1 is free 13.77 __ xorptr(rax, rax); // return 0 13.78 __ leave(); // required for proper stackwalking of RuntimeStub frame 13.79 __ ret(0); 13.80 @@ -1859,8 +1860,8 @@ 13.81 __ leaq(end_to, Address(saved_to, dword_count, Address::times_4, -4)); 13.82 gen_write_ref_array_post_barrier(saved_to, end_to, rax); 13.83 } 13.84 - inc_counter_np(SharedRuntime::_jint_array_copy_ctr); 13.85 restore_arg_regs(); 13.86 + inc_counter_np(SharedRuntime::_jint_array_copy_ctr); // Update counter after rscratch1 is free 13.87 __ xorptr(rax, rax); // return 0 13.88 __ leave(); // required for proper stackwalking of RuntimeStub frame 13.89 __ ret(0); 13.90 @@ -1940,11 +1941,11 @@ 13.91 __ decrement(qword_count); 13.92 __ jcc(Assembler::notZero, L_copy_8_bytes); 13.93 13.94 - inc_counter_np(SharedRuntime::_jint_array_copy_ctr); 13.95 if (is_oop) { 13.96 __ jmp(L_exit); 13.97 } 13.98 restore_arg_regs(); 13.99 + inc_counter_np(SharedRuntime::_jint_array_copy_ctr); // Update counter after rscratch1 is free 13.100 __ xorptr(rax, rax); // return 0 13.101 __ leave(); // required for proper stackwalking of RuntimeStub frame 13.102 __ ret(0); 13.103 @@ -1952,7 +1953,6 @@ 13.104 // Copy in 32-bytes chunks 13.105 copy_32_bytes_backward(from, to, qword_count, rax, L_copy_32_bytes, L_copy_8_bytes); 13.106 13.107 - inc_counter_np(SharedRuntime::_jint_array_copy_ctr); 13.108 __ bind(L_exit); 13.109 if (is_oop) { 13.110 Register end_to = rdx; 13.111 @@ -1960,6 +1960,7 @@ 13.112 gen_write_ref_array_post_barrier(to, end_to, rax); 13.113 } 13.114 restore_arg_regs(); 13.115 + inc_counter_np(SharedRuntime::_jint_array_copy_ctr); // Update counter after rscratch1 is free 13.116 __ xorptr(rax, rax); // return 0 13.117 __ leave(); // required for proper stackwalking of RuntimeStub frame 13.118 __ ret(0); 13.119 @@ -2032,8 +2033,8 @@ 13.120 if (is_oop) { 13.121 __ jmp(L_exit); 13.122 } else { 13.123 - inc_counter_np(SharedRuntime::_jlong_array_copy_ctr); 13.124 restore_arg_regs(); 13.125 + inc_counter_np(SharedRuntime::_jlong_array_copy_ctr); // Update counter after rscratch1 is free 13.126 __ xorptr(rax, rax); // return 0 13.127 __ leave(); // required for proper stackwalking of RuntimeStub frame 13.128 __ ret(0); 13.129 @@ -2045,11 +2046,13 @@ 13.130 if (is_oop) { 13.131 __ BIND(L_exit); 13.132 gen_write_ref_array_post_barrier(saved_to, end_to, rax); 13.133 - inc_counter_np(SharedRuntime::_oop_array_copy_ctr); 13.134 - } else { 13.135 - inc_counter_np(SharedRuntime::_jlong_array_copy_ctr); 13.136 } 13.137 restore_arg_regs(); 13.138 + if (is_oop) { 13.139 + inc_counter_np(SharedRuntime::_oop_array_copy_ctr); // Update counter after rscratch1 is free 13.140 + } else { 13.141 + inc_counter_np(SharedRuntime::_jlong_array_copy_ctr); // Update counter after rscratch1 is free 13.142 + } 13.143 __ xorptr(rax, rax); // return 0 13.144 __ leave(); // required for proper stackwalking of RuntimeStub frame 13.145 __ ret(0); 13.146 @@ -2113,8 +2116,8 @@ 13.147 if (is_oop) { 13.148 __ jmp(L_exit); 13.149 } else { 13.150 - inc_counter_np(SharedRuntime::_jlong_array_copy_ctr); 13.151 restore_arg_regs(); 13.152 + inc_counter_np(SharedRuntime::_jlong_array_copy_ctr); // Update counter after rscratch1 is free 13.153 __ xorptr(rax, rax); // return 0 13.154 __ leave(); // required for proper stackwalking of RuntimeStub frame 13.155 __ ret(0); 13.156 @@ -2127,11 +2130,13 @@ 13.157 __ BIND(L_exit); 13.158 __ lea(rcx, Address(to, saved_count, Address::times_8, -8)); 13.159 gen_write_ref_array_post_barrier(to, rcx, rax); 13.160 - inc_counter_np(SharedRuntime::_oop_array_copy_ctr); 13.161 - } else { 13.162 - inc_counter_np(SharedRuntime::_jlong_array_copy_ctr); 13.163 } 13.164 restore_arg_regs(); 13.165 + if (is_oop) { 13.166 + inc_counter_np(SharedRuntime::_oop_array_copy_ctr); // Update counter after rscratch1 is free 13.167 + } else { 13.168 + inc_counter_np(SharedRuntime::_jlong_array_copy_ctr); // Update counter after rscratch1 is free 13.169 + } 13.170 __ xorptr(rax, rax); // return 0 13.171 __ leave(); // required for proper stackwalking of RuntimeStub frame 13.172 __ ret(0); 13.173 @@ -2331,8 +2336,8 @@ 13.174 __ BIND(L_done); 13.175 __ movptr(r13, Address(rsp, saved_r13_offset * wordSize)); 13.176 __ movptr(r14, Address(rsp, saved_r14_offset * wordSize)); 13.177 - inc_counter_np(SharedRuntime::_checkcast_array_copy_ctr); 13.178 restore_arg_regs(); 13.179 + inc_counter_np(SharedRuntime::_checkcast_array_copy_ctr); // Update counter after rscratch1 is free 13.180 __ leave(); // required for proper stackwalking of RuntimeStub frame 13.181 __ ret(0); 13.182
14.1 --- a/src/cpu/x86/vm/x86_32.ad Wed Dec 07 07:27:09 2011 -0800 14.2 +++ b/src/cpu/x86/vm/x86_32.ad Thu Dec 08 10:27:33 2011 -0800 14.3 @@ -507,9 +507,12 @@ 14.4 14.5 14.6 //============================================================================= 14.7 -const bool Matcher::constant_table_absolute_addressing = true; 14.8 const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty; 14.9 14.10 +int Compile::ConstantTable::calculate_table_base_offset() const { 14.11 + return 0; // absolute addressing, no offset 14.12 +} 14.13 + 14.14 void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { 14.15 // Empty encoding 14.16 } 14.17 @@ -639,6 +642,12 @@ 14.18 } 14.19 #endif 14.20 14.21 + if (C->has_mach_constant_base_node()) { 14.22 + // NOTE: We set the table base offset here because users might be 14.23 + // emitted before MachConstantBaseNode. 14.24 + Compile::ConstantTable& constant_table = C->constant_table(); 14.25 + constant_table.set_table_base_offset(constant_table.calculate_table_base_offset()); 14.26 + } 14.27 } 14.28 14.29 uint MachPrologNode::size(PhaseRegAlloc *ra_) const { 14.30 @@ -1515,12 +1524,12 @@ 14.31 14.32 // Register for DIVI projection of divmodI 14.33 RegMask Matcher::divI_proj_mask() { 14.34 - return EAX_REG_mask; 14.35 + return EAX_REG_mask(); 14.36 } 14.37 14.38 // Register for MODI projection of divmodI 14.39 RegMask Matcher::modI_proj_mask() { 14.40 - return EDX_REG_mask; 14.41 + return EDX_REG_mask(); 14.42 } 14.43 14.44 // Register for DIVL projection of divmodL 14.45 @@ -1536,7 +1545,7 @@ 14.46 } 14.47 14.48 const RegMask Matcher::method_handle_invoke_SP_save_mask() { 14.49 - return EBP_REG_mask; 14.50 + return EBP_REG_mask(); 14.51 } 14.52 14.53 // Returns true if the high 32 bits of the value is known to be zero.
15.1 --- a/src/cpu/x86/vm/x86_64.ad Wed Dec 07 07:27:09 2011 -0800 15.2 +++ b/src/cpu/x86/vm/x86_64.ad Thu Dec 08 10:27:33 2011 -0800 15.3 @@ -843,9 +843,12 @@ 15.4 15.5 15.6 //============================================================================= 15.7 -const bool Matcher::constant_table_absolute_addressing = true; 15.8 const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty; 15.9 15.10 +int Compile::ConstantTable::calculate_table_base_offset() const { 15.11 + return 0; // absolute addressing, no offset 15.12 +} 15.13 + 15.14 void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { 15.15 // Empty encoding 15.16 } 15.17 @@ -977,6 +980,13 @@ 15.18 masm.bind(L); 15.19 } 15.20 #endif 15.21 + 15.22 + if (C->has_mach_constant_base_node()) { 15.23 + // NOTE: We set the table base offset here because users might be 15.24 + // emitted before MachConstantBaseNode. 15.25 + Compile::ConstantTable& constant_table = C->constant_table(); 15.26 + constant_table.set_table_base_offset(constant_table.calculate_table_base_offset()); 15.27 + } 15.28 } 15.29 15.30 uint MachPrologNode::size(PhaseRegAlloc* ra_) const 15.31 @@ -2079,26 +2089,26 @@ 15.32 15.33 // Register for DIVI projection of divmodI 15.34 RegMask Matcher::divI_proj_mask() { 15.35 - return INT_RAX_REG_mask; 15.36 + return INT_RAX_REG_mask(); 15.37 } 15.38 15.39 // Register for MODI projection of divmodI 15.40 RegMask Matcher::modI_proj_mask() { 15.41 - return INT_RDX_REG_mask; 15.42 + return INT_RDX_REG_mask(); 15.43 } 15.44 15.45 // Register for DIVL projection of divmodL 15.46 RegMask Matcher::divL_proj_mask() { 15.47 - return LONG_RAX_REG_mask; 15.48 + return LONG_RAX_REG_mask(); 15.49 } 15.50 15.51 // Register for MODL projection of divmodL 15.52 RegMask Matcher::modL_proj_mask() { 15.53 - return LONG_RDX_REG_mask; 15.54 + return LONG_RDX_REG_mask(); 15.55 } 15.56 15.57 const RegMask Matcher::method_handle_invoke_SP_save_mask() { 15.58 - return PTR_RBP_REG_mask; 15.59 + return PTR_RBP_REG_mask(); 15.60 } 15.61 15.62 static Address build_address(int b, int i, int s, int d) {
16.1 --- a/src/share/vm/adlc/adlparse.cpp Wed Dec 07 07:27:09 2011 -0800 16.2 +++ b/src/share/vm/adlc/adlparse.cpp Thu Dec 08 10:27:33 2011 -0800 16.3 @@ -1,5 +1,5 @@ 16.4 /* 16.5 - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. 16.6 + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. 16.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 16.8 * 16.9 * This code is free software; you can redistribute it and/or modify it 16.10 @@ -982,27 +982,9 @@ 16.11 } 16.12 if (strcmp(token,"interpreter_frame_pointer")==0) { 16.13 interpreter_frame_pointer_parse(frame, false); 16.14 - // Add reg_class interpreter_frame_pointer_reg 16.15 - if( _AD._register != NULL ) { 16.16 - RegClass *reg_class = _AD._register->addRegClass("interpreter_frame_pointer_reg"); 16.17 - char *interpreter_frame_pointer_reg = frame->_interpreter_frame_pointer_reg; 16.18 - if( interpreter_frame_pointer_reg != NULL ) { 16.19 - RegDef *regDef = _AD._register->getRegDef(interpreter_frame_pointer_reg); 16.20 - reg_class->addReg(regDef); // add regDef to regClass 16.21 - } 16.22 - } 16.23 } 16.24 if (strcmp(token,"inline_cache_reg")==0) { 16.25 inline_cache_parse(frame, false); 16.26 - // Add reg_class inline_cache_reg 16.27 - if( _AD._register != NULL ) { 16.28 - RegClass *reg_class = _AD._register->addRegClass("inline_cache_reg"); 16.29 - char *inline_cache_reg = frame->_inline_cache_reg; 16.30 - if( inline_cache_reg != NULL ) { 16.31 - RegDef *regDef = _AD._register->getRegDef(inline_cache_reg); 16.32 - reg_class->addReg(regDef); // add regDef to regClass 16.33 - } 16.34 - } 16.35 } 16.36 if (strcmp(token,"compiler_method_oop_reg")==0) { 16.37 parse_err(WARN, "Using obsolete Token, compiler_method_oop_reg"); 16.38 @@ -1010,15 +992,6 @@ 16.39 } 16.40 if (strcmp(token,"interpreter_method_oop_reg")==0) { 16.41 interpreter_method_oop_parse(frame, false); 16.42 - // Add reg_class interpreter_method_oop_reg 16.43 - if( _AD._register != NULL ) { 16.44 - RegClass *reg_class = _AD._register->addRegClass("interpreter_method_oop_reg"); 16.45 - char *method_oop_reg = frame->_interpreter_method_oop_reg; 16.46 - if( method_oop_reg != NULL ) { 16.47 - RegDef *regDef = _AD._register->getRegDef(method_oop_reg); 16.48 - reg_class->addReg(regDef); // add regDef to regClass 16.49 - } 16.50 - } 16.51 } 16.52 if (strcmp(token,"cisc_spilling_operand_name")==0) { 16.53 cisc_spilling_operand_name_parse(frame, false); 16.54 @@ -2363,6 +2336,14 @@ 16.55 } 16.56 } 16.57 next_char(); // Skip closing ')' 16.58 + } else if (_curchar == '%') { 16.59 + char *code = find_cpp_block("reg class"); 16.60 + if (code == NULL) { 16.61 + parse_err(SYNERR, "missing code declaration for reg class.\n"); 16.62 + return; 16.63 + } 16.64 + reg_class->_user_defined = code; 16.65 + return; 16.66 } 16.67 16.68 // Check for terminating ';' 16.69 @@ -3115,7 +3096,7 @@ 16.70 encoding->add_code(" _constant = C->constant_table().add"); 16.71 16.72 // Parse everything in ( ) expression. 16.73 - encoding->add_code("("); 16.74 + encoding->add_code("(this, "); 16.75 next_char(); // Skip '(' 16.76 int parens_depth = 1; 16.77 16.78 @@ -3130,7 +3111,8 @@ 16.79 } 16.80 else if (_curchar == ')') { 16.81 parens_depth--; 16.82 - encoding->add_code(")"); 16.83 + if (parens_depth > 0) 16.84 + encoding->add_code(")"); 16.85 next_char(); 16.86 } 16.87 else { 16.88 @@ -3157,7 +3139,7 @@ 16.89 } 16.90 16.91 // Finish code line. 16.92 - encoding->add_code(";"); 16.93 + encoding->add_code(");"); 16.94 16.95 if (_AD._adlocation_debug) { 16.96 encoding->add_code(end_line_marker()); 16.97 @@ -3817,7 +3799,7 @@ 16.98 return; 16.99 } 16.100 // Get list of effect-operand pairs and insert into dictionary 16.101 - else get_effectlist(instr->_effects, instr->_localNames); 16.102 + else get_effectlist(instr->_effects, instr->_localNames, instr->_has_call); 16.103 16.104 // Debug Stuff 16.105 if (_AD._adl_debug > 1) fprintf(stderr,"Effect description: %s\n", desc); 16.106 @@ -4595,7 +4577,7 @@ 16.107 // effect, and the second must be the name of an operand defined in the 16.108 // operand list of this instruction. Stores the names with a pointer to the 16.109 // effect form in a local effects table. 16.110 -void ADLParser::get_effectlist(FormDict &effects, FormDict &operands) { 16.111 +void ADLParser::get_effectlist(FormDict &effects, FormDict &operands, bool& has_call) { 16.112 OperandForm *opForm; 16.113 Effect *eForm; 16.114 char *ident; 16.115 @@ -4628,26 +4610,31 @@ 16.116 // Debugging Stuff 16.117 if (_AD._adl_debug > 1) fprintf(stderr, "\tEffect Type: %s\t", ident); 16.118 skipws(); 16.119 - // Get name of operand and check that it is in the local name table 16.120 - if( (ident = get_unique_ident(effects, "effect")) == NULL) { 16.121 - parse_err(SYNERR, "missing operand identifier in effect list\n"); 16.122 - return; 16.123 + if (eForm->is(Component::CALL)) { 16.124 + if (_AD._adl_debug > 1) fprintf(stderr, "\n"); 16.125 + has_call = true; 16.126 + } else { 16.127 + // Get name of operand and check that it is in the local name table 16.128 + if( (ident = get_unique_ident(effects, "effect")) == NULL) { 16.129 + parse_err(SYNERR, "missing operand identifier in effect list\n"); 16.130 + return; 16.131 + } 16.132 + const Form *form = operands[ident]; 16.133 + opForm = form ? form->is_operand() : NULL; 16.134 + if( opForm == NULL ) { 16.135 + if( form && form->is_opclass() ) { 16.136 + const char* cname = form->is_opclass()->_ident; 16.137 + parse_err(SYNERR, "operand classes are illegal in effect lists (found %s %s)\n", cname, ident); 16.138 + } else { 16.139 + parse_err(SYNERR, "undefined operand %s in effect list\n", ident); 16.140 + } 16.141 + return; 16.142 + } 16.143 + // Add the pair to the effects table 16.144 + effects.Insert(ident, eForm); 16.145 + // Debugging Stuff 16.146 + if (_AD._adl_debug > 1) fprintf(stderr, "\tOperand Name: %s\n", ident); 16.147 } 16.148 - const Form *form = operands[ident]; 16.149 - opForm = form ? form->is_operand() : NULL; 16.150 - if( opForm == NULL ) { 16.151 - if( form && form->is_opclass() ) { 16.152 - const char* cname = form->is_opclass()->_ident; 16.153 - parse_err(SYNERR, "operand classes are illegal in effect lists (found %s %s)\n", cname, ident); 16.154 - } else { 16.155 - parse_err(SYNERR, "undefined operand %s in effect list\n", ident); 16.156 - } 16.157 - return; 16.158 - } 16.159 - // Add the pair to the effects table 16.160 - effects.Insert(ident, eForm); 16.161 - // Debugging Stuff 16.162 - if (_AD._adl_debug > 1) fprintf(stderr, "\tOperand Name: %s\n", ident); 16.163 skipws(); 16.164 } while(_curchar == ','); 16.165
17.1 --- a/src/share/vm/adlc/adlparse.hpp Wed Dec 07 07:27:09 2011 -0800 17.2 +++ b/src/share/vm/adlc/adlparse.hpp Thu Dec 08 10:27:33 2011 -0800 17.3 @@ -232,7 +232,7 @@ 17.4 char *get_relation_dup(void); 17.5 17.6 void get_oplist(NameList ¶meters, FormDict &operands);// Parse type-operand pairs 17.7 - void get_effectlist(FormDict &effects, FormDict &operands); // Parse effect-operand pairs 17.8 + void get_effectlist(FormDict &effects, FormDict &operands, bool& has_call); // Parse effect-operand pairs 17.9 // Return the contents of a parenthesized expression. 17.10 // Requires initial '(' and consumes final ')', which is replaced by '\0'. 17.11 char *get_paren_expr(const char *description, bool include_location = false);
18.1 --- a/src/share/vm/adlc/archDesc.cpp Wed Dec 07 07:27:09 2011 -0800 18.2 +++ b/src/share/vm/adlc/archDesc.cpp Thu Dec 08 10:27:33 2011 -0800 18.3 @@ -823,9 +823,9 @@ 18.4 } else { 18.5 char *rc_name = toUpper(reg_class_name); 18.6 const char *mask = "_mask"; 18.7 - int length = (int)strlen(rc_name) + (int)strlen(mask) + 3; 18.8 + int length = (int)strlen(rc_name) + (int)strlen(mask) + 5; 18.9 char *regMask = new char[length]; 18.10 - sprintf(regMask,"%s%s", rc_name, mask); 18.11 + sprintf(regMask,"%s%s()", rc_name, mask); 18.12 return regMask; 18.13 } 18.14 } 18.15 @@ -1018,6 +1018,9 @@ 18.16 ident = "TEMP"; 18.17 eForm = new Effect(ident); 18.18 _globalNames.Insert(ident, eForm); 18.19 + ident = "CALL"; 18.20 + eForm = new Effect(ident); 18.21 + _globalNames.Insert(ident, eForm); 18.22 } 18.23 18.24 //
19.1 --- a/src/share/vm/adlc/formsopt.cpp Wed Dec 07 07:27:09 2011 -0800 19.2 +++ b/src/share/vm/adlc/formsopt.cpp Thu Dec 08 10:27:33 2011 -0800 19.3 @@ -219,7 +219,9 @@ 19.4 19.5 //------------------------------RegClass--------------------------------------- 19.6 // Construct a register class into which registers will be inserted 19.7 -RegClass::RegClass(const char *classid) : _stack_or_reg(false), _classid(classid), _regDef(cmpstr,hashstr, Form::arena) { 19.8 +RegClass::RegClass(const char *classid) : _stack_or_reg(false), _classid(classid), _regDef(cmpstr,hashstr, Form::arena), 19.9 + _user_defined(NULL) 19.10 +{ 19.11 } 19.12 19.13 // record a register in this class
20.1 --- a/src/share/vm/adlc/formsopt.hpp Wed Dec 07 07:27:09 2011 -0800 20.2 +++ b/src/share/vm/adlc/formsopt.hpp Thu Dec 08 10:27:33 2011 -0800 20.3 @@ -161,6 +161,7 @@ 20.4 NameList _regDefs; // List of registers in class 20.5 Dict _regDef; // Dictionary of registers in class 20.6 bool _stack_or_reg; // Allowed on any stack slot 20.7 + char* _user_defined; 20.8 20.9 // Public Methods 20.10 RegClass(const char *classid);// Constructor
21.1 --- a/src/share/vm/adlc/formssel.cpp Wed Dec 07 07:27:09 2011 -0800 21.2 +++ b/src/share/vm/adlc/formssel.cpp Thu Dec 08 10:27:33 2011 -0800 21.3 @@ -31,7 +31,8 @@ 21.4 : _ident(id), _ideal_only(ideal_only), 21.5 _localNames(cmpstr, hashstr, Form::arena), 21.6 _effects(cmpstr, hashstr, Form::arena), 21.7 - _is_mach_constant(false) 21.8 + _is_mach_constant(false), 21.9 + _has_call(false) 21.10 { 21.11 _ftype = Form::INS; 21.12 21.13 @@ -62,7 +63,8 @@ 21.14 : _ident(id), _ideal_only(false), 21.15 _localNames(instr->_localNames), 21.16 _effects(instr->_effects), 21.17 - _is_mach_constant(false) 21.18 + _is_mach_constant(false), 21.19 + _has_call(false) 21.20 { 21.21 _ftype = Form::INS; 21.22 21.23 @@ -1754,6 +1756,7 @@ 21.24 if(!strcmp(name, "USE_KILL")) return Component::USE_KILL; 21.25 if(!strcmp(name, "TEMP")) return Component::TEMP; 21.26 if(!strcmp(name, "INVALID")) return Component::INVALID; 21.27 + if(!strcmp(name, "CALL")) return Component::CALL; 21.28 assert( false,"Invalid effect name specified\n"); 21.29 return Component::INVALID; 21.30 }
22.1 --- a/src/share/vm/adlc/formssel.hpp Wed Dec 07 07:27:09 2011 -0800 22.2 +++ b/src/share/vm/adlc/formssel.hpp Thu Dec 08 10:27:33 2011 -0800 22.3 @@ -111,6 +111,8 @@ 22.4 ComponentList _components; // List of Components matches MachNode's 22.5 // operand structure 22.6 22.7 + bool _has_call; // contain a call and caller save registers should be saved? 22.8 + 22.9 // Public Methods 22.10 InstructForm(const char *id, bool ideal_only = false); 22.11 InstructForm(const char *id, InstructForm *instr, MatchRule *rule); 22.12 @@ -895,7 +897,8 @@ 22.13 DEF = 0x2, USE_DEF = 0x3, 22.14 KILL = 0x4, USE_KILL = 0x5, 22.15 SYNTHETIC = 0x8, 22.16 - TEMP = USE | SYNTHETIC 22.17 + TEMP = USE | SYNTHETIC, 22.18 + CALL = 0x10 22.19 }; 22.20 }; 22.21
23.1 --- a/src/share/vm/adlc/output_c.cpp Wed Dec 07 07:27:09 2011 -0800 23.2 +++ b/src/share/vm/adlc/output_c.cpp Thu Dec 08 10:27:33 2011 -0800 23.3 @@ -162,11 +162,17 @@ 23.4 RegClass *reg_class = _register->getRegClass(rc_name); 23.5 assert( reg_class, "Using an undefined register class"); 23.6 23.7 - int len = RegisterForm::RegMask_Size(); 23.8 - fprintf(fp_hpp, "extern const RegMask %s%s_mask;\n", prefix, toUpper( rc_name ) ); 23.9 + if (reg_class->_user_defined == NULL) { 23.10 + fprintf(fp_hpp, "extern const RegMask _%s%s_mask;\n", prefix, toUpper( rc_name ) ); 23.11 + fprintf(fp_hpp, "inline const RegMask &%s%s_mask() { return _%s%s_mask; }\n", prefix, toUpper( rc_name ), prefix, toUpper( rc_name )); 23.12 + } else { 23.13 + fprintf(fp_hpp, "inline const RegMask &%s%s_mask() { %s }\n", prefix, toUpper( rc_name ), reg_class->_user_defined); 23.14 + } 23.15 23.16 if( reg_class->_stack_or_reg ) { 23.17 - fprintf(fp_hpp, "extern const RegMask %sSTACK_OR_%s_mask;\n", prefix, toUpper( rc_name ) ); 23.18 + assert(reg_class->_user_defined == NULL, "no user defined reg class here"); 23.19 + fprintf(fp_hpp, "extern const RegMask _%sSTACK_OR_%s_mask;\n", prefix, toUpper( rc_name ) ); 23.20 + fprintf(fp_hpp, "inline const RegMask &%sSTACK_OR_%s_mask() { return _%sSTACK_OR_%s_mask; }\n", prefix, toUpper( rc_name ), prefix, toUpper( rc_name ) ); 23.21 } 23.22 } 23.23 } 23.24 @@ -188,8 +194,10 @@ 23.25 RegClass *reg_class = _register->getRegClass(rc_name); 23.26 assert( reg_class, "Using an undefined register class"); 23.27 23.28 + if (reg_class->_user_defined != NULL) continue; 23.29 + 23.30 int len = RegisterForm::RegMask_Size(); 23.31 - fprintf(fp_cpp, "const RegMask %s%s_mask(", prefix, toUpper( rc_name ) ); 23.32 + fprintf(fp_cpp, "const RegMask _%s%s_mask(", prefix, toUpper( rc_name ) ); 23.33 { int i; 23.34 for( i = 0; i < len-1; i++ ) 23.35 fprintf(fp_cpp," 0x%x,",reg_class->regs_in_word(i,false)); 23.36 @@ -198,7 +206,7 @@ 23.37 23.38 if( reg_class->_stack_or_reg ) { 23.39 int i; 23.40 - fprintf(fp_cpp, "const RegMask %sSTACK_OR_%s_mask(", prefix, toUpper( rc_name ) ); 23.41 + fprintf(fp_cpp, "const RegMask _%sSTACK_OR_%s_mask(", prefix, toUpper( rc_name ) ); 23.42 for( i = 0; i < len-1; i++ ) 23.43 fprintf(fp_cpp," 0x%x,",reg_class->regs_in_word(i,true)); 23.44 fprintf(fp_cpp," 0x%x );\n",reg_class->regs_in_word(i,true)); 23.45 @@ -2585,9 +2593,9 @@ 23.46 // Output instruction's emit prototype 23.47 fprintf(fp, "void %sNode::eval_constant(Compile* C) {\n", inst._ident); 23.48 23.49 - // For ideal jump nodes, allocate a jump table. 23.50 + // For ideal jump nodes, add a jump-table entry. 23.51 if (inst.is_ideal_jump()) { 23.52 - fprintf(fp, " _constant = C->constant_table().allocate_jump_table(this);\n"); 23.53 + fprintf(fp, " _constant = C->constant_table().add_jump_table(this);\n"); 23.54 } 23.55 23.56 // If user did not define an encode section, 23.57 @@ -2690,7 +2698,7 @@ 23.58 if (strcmp(first_reg_class, "stack_slots") == 0) { 23.59 fprintf(fp," return &(Compile::current()->FIRST_STACK_mask());\n"); 23.60 } else { 23.61 - fprintf(fp," return &%s_mask;\n", toUpper(first_reg_class)); 23.62 + fprintf(fp," return &%s_mask();\n", toUpper(first_reg_class)); 23.63 } 23.64 } else { 23.65 // Build a switch statement to return the desired mask. 23.66 @@ -2702,7 +2710,7 @@ 23.67 if( !strcmp(reg_class, "stack_slots") ) { 23.68 fprintf(fp, " case %d: return &(Compile::current()->FIRST_STACK_mask());\n", index); 23.69 } else { 23.70 - fprintf(fp, " case %d: return &%s_mask;\n", index, toUpper(reg_class)); 23.71 + fprintf(fp, " case %d: return &%s_mask();\n", index, toUpper(reg_class)); 23.72 } 23.73 } 23.74 fprintf(fp," }\n"); 23.75 @@ -4080,8 +4088,6 @@ 23.76 fprintf(fp_cpp,"OptoReg::Name Matcher::inline_cache_reg() {"); 23.77 fprintf(fp_cpp," return OptoReg::Name(%s_num); }\n\n", 23.78 _frame->_inline_cache_reg); 23.79 - fprintf(fp_cpp,"const RegMask &Matcher::inline_cache_reg_mask() {"); 23.80 - fprintf(fp_cpp," return INLINE_CACHE_REG_mask; }\n\n"); 23.81 fprintf(fp_cpp,"int Matcher::inline_cache_reg_encode() {"); 23.82 fprintf(fp_cpp," return _regEncode[inline_cache_reg()]; }\n\n"); 23.83 23.84 @@ -4089,8 +4095,6 @@ 23.85 fprintf(fp_cpp,"OptoReg::Name Matcher::interpreter_method_oop_reg() {"); 23.86 fprintf(fp_cpp," return OptoReg::Name(%s_num); }\n\n", 23.87 _frame->_interpreter_method_oop_reg); 23.88 - fprintf(fp_cpp,"const RegMask &Matcher::interpreter_method_oop_reg_mask() {"); 23.89 - fprintf(fp_cpp," return INTERPRETER_METHOD_OOP_REG_mask; }\n\n"); 23.90 fprintf(fp_cpp,"int Matcher::interpreter_method_oop_reg_encode() {"); 23.91 fprintf(fp_cpp," return _regEncode[interpreter_method_oop_reg()]; }\n\n"); 23.92 23.93 @@ -4101,11 +4105,6 @@ 23.94 else 23.95 fprintf(fp_cpp," return OptoReg::Name(%s_num); }\n\n", 23.96 _frame->_interpreter_frame_pointer_reg); 23.97 - fprintf(fp_cpp,"const RegMask &Matcher::interpreter_frame_pointer_reg_mask() {"); 23.98 - if (_frame->_interpreter_frame_pointer_reg == NULL) 23.99 - fprintf(fp_cpp," static RegMask dummy; return dummy; }\n\n"); 23.100 - else 23.101 - fprintf(fp_cpp," return INTERPRETER_FRAME_POINTER_REG_mask; }\n\n"); 23.102 23.103 // Frame Pointer definition 23.104 /* CNC - I can not contemplate having a different frame pointer between
24.1 --- a/src/share/vm/adlc/output_h.cpp Wed Dec 07 07:27:09 2011 -0800 24.2 +++ b/src/share/vm/adlc/output_h.cpp Thu Dec 08 10:27:33 2011 -0800 24.3 @@ -1720,6 +1720,16 @@ 24.4 } 24.5 } 24.6 24.7 + // flag: if this instruction is implemented with a call 24.8 + if ( instr->_has_call ) { 24.9 + if ( node_flags_set ) { 24.10 + fprintf(fp," | Flag_has_call"); 24.11 + } else { 24.12 + fprintf(fp,"init_flags(Flag_has_call"); 24.13 + node_flags_set = true; 24.14 + } 24.15 + } 24.16 + 24.17 if ( node_flags_set ) { 24.18 fprintf(fp,"); "); 24.19 }
25.1 --- a/src/share/vm/asm/assembler.hpp Wed Dec 07 07:27:09 2011 -0800 25.2 +++ b/src/share/vm/asm/assembler.hpp Thu Dec 08 10:27:33 2011 -0800 25.3 @@ -257,6 +257,29 @@ 25.4 // ensure buf contains all code (call this before using/copying the code) 25.5 void flush(); 25.6 25.7 + // min and max values for signed immediate ranges 25.8 + static int min_simm(int nbits) { return -(intptr_t(1) << (nbits - 1)) ; } 25.9 + static int max_simm(int nbits) { return (intptr_t(1) << (nbits - 1)) - 1; } 25.10 + 25.11 + // Define some: 25.12 + static int min_simm10() { return min_simm(10); } 25.13 + static int min_simm13() { return min_simm(13); } 25.14 + static int min_simm16() { return min_simm(16); } 25.15 + 25.16 + // Test if x is within signed immediate range for nbits 25.17 + static bool is_simm(intptr_t x, int nbits) { return min_simm(nbits) <= x && x <= max_simm(nbits); } 25.18 + 25.19 + // Define some: 25.20 + static bool is_simm5( intptr_t x) { return is_simm(x, 5 ); } 25.21 + static bool is_simm8( intptr_t x) { return is_simm(x, 8 ); } 25.22 + static bool is_simm10(intptr_t x) { return is_simm(x, 10); } 25.23 + static bool is_simm11(intptr_t x) { return is_simm(x, 11); } 25.24 + static bool is_simm12(intptr_t x) { return is_simm(x, 12); } 25.25 + static bool is_simm13(intptr_t x) { return is_simm(x, 13); } 25.26 + static bool is_simm16(intptr_t x) { return is_simm(x, 16); } 25.27 + static bool is_simm26(intptr_t x) { return is_simm(x, 26); } 25.28 + static bool is_simm32(intptr_t x) { return is_simm(x, 32); } 25.29 + 25.30 // Accessors 25.31 CodeBuffer* code() const; // _code_section->outer() 25.32 CodeSection* code_section() const { return _code_section; }
26.1 --- a/src/share/vm/c1/c1_GraphBuilder.cpp Wed Dec 07 07:27:09 2011 -0800 26.2 +++ b/src/share/vm/c1/c1_GraphBuilder.cpp Thu Dec 08 10:27:33 2011 -0800 26.3 @@ -3495,9 +3495,6 @@ 26.4 if (profile_calls()) { 26.5 profile_call(recv, holder_known ? callee->holder() : NULL); 26.6 } 26.7 - if (profile_inlined_calls()) { 26.8 - profile_invocation(callee, copy_state_before()); 26.9 - } 26.10 } 26.11 26.12 // Introduce a new callee continuation point - if the callee has 26.13 @@ -3571,6 +3568,10 @@ 26.14 append(new RuntimeCall(voidType, "dtrace_method_entry", CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry), args)); 26.15 } 26.16 26.17 + if (profile_inlined_calls()) { 26.18 + profile_invocation(callee, copy_state_before_with_bci(SynchronizationEntryBCI)); 26.19 + } 26.20 + 26.21 BlockBegin* callee_start_block = block_at(0); 26.22 if (callee_start_block != NULL) { 26.23 assert(callee_start_block->is_set(BlockBegin::parser_loop_header_flag), "must be loop header");
27.1 --- a/src/share/vm/c1/c1_Instruction.hpp Wed Dec 07 07:27:09 2011 -0800 27.2 +++ b/src/share/vm/c1/c1_Instruction.hpp Thu Dec 08 10:27:33 2011 -0800 27.3 @@ -501,6 +501,7 @@ 27.4 virtual RoundFP* as_RoundFP() { return NULL; } 27.5 virtual ExceptionObject* as_ExceptionObject() { return NULL; } 27.6 virtual UnsafeOp* as_UnsafeOp() { return NULL; } 27.7 + virtual ProfileInvoke* as_ProfileInvoke() { return NULL; } 27.8 27.9 virtual void visit(InstructionVisitor* v) = 0; 27.10
28.1 --- a/src/share/vm/c1/c1_LIRGenerator.cpp Wed Dec 07 07:27:09 2011 -0800 28.2 +++ b/src/share/vm/c1/c1_LIRGenerator.cpp Thu Dec 08 10:27:33 2011 -0800 28.3 @@ -429,7 +429,7 @@ 28.4 // all locals are dead on exit from the synthetic unlocker 28.5 liveness.clear(); 28.6 } else { 28.7 - assert(x->as_MonitorEnter(), "only other case is MonitorEnter"); 28.8 + assert(x->as_MonitorEnter() || x->as_ProfileInvoke(), "only other cases are MonitorEnter and ProfileInvoke"); 28.9 } 28.10 } 28.11 if (!liveness.is_valid()) {
29.1 --- a/src/share/vm/ci/bcEscapeAnalyzer.cpp Wed Dec 07 07:27:09 2011 -0800 29.2 +++ b/src/share/vm/ci/bcEscapeAnalyzer.cpp Thu Dec 08 10:27:33 2011 -0800 29.3 @@ -150,11 +150,23 @@ 29.4 clear_bits(vars, _arg_local); 29.5 } 29.6 29.7 -void BCEscapeAnalyzer::set_global_escape(ArgumentMap vars) { 29.8 +void BCEscapeAnalyzer::set_global_escape(ArgumentMap vars, bool merge) { 29.9 clear_bits(vars, _arg_local); 29.10 clear_bits(vars, _arg_stack); 29.11 if (vars.contains_allocated()) 29.12 _allocated_escapes = true; 29.13 + 29.14 + if (merge && !vars.is_empty()) { 29.15 + // Merge new state into already processed block. 29.16 + // New state is not taken into account and 29.17 + // it may invalidate set_returned() result. 29.18 + if (vars.contains_unknown() || vars.contains_allocated()) { 29.19 + _return_local = false; 29.20 + } 29.21 + if (vars.contains_unknown() || vars.contains_vars()) { 29.22 + _return_allocated = false; 29.23 + } 29.24 + } 29.25 } 29.26 29.27 void BCEscapeAnalyzer::set_dirty(ArgumentMap vars) { 29.28 @@ -999,7 +1011,7 @@ 29.29 t.set_difference(d_state->_stack[i]); 29.30 extra_vars.set_union(t); 29.31 } 29.32 - set_global_escape(extra_vars); 29.33 + set_global_escape(extra_vars, true); 29.34 } 29.35 } 29.36
30.1 --- a/src/share/vm/ci/bcEscapeAnalyzer.hpp Wed Dec 07 07:27:09 2011 -0800 30.2 +++ b/src/share/vm/ci/bcEscapeAnalyzer.hpp Thu Dec 08 10:27:33 2011 -0800 30.3 @@ -81,7 +81,7 @@ 30.4 bool is_arg_stack(ArgumentMap vars); 30.5 void clear_bits(ArgumentMap vars, VectorSet &bs); 30.6 void set_method_escape(ArgumentMap vars); 30.7 - void set_global_escape(ArgumentMap vars); 30.8 + void set_global_escape(ArgumentMap vars, bool merge = false); 30.9 void set_dirty(ArgumentMap vars); 30.10 void set_modified(ArgumentMap vars, int offs, int size); 30.11
31.1 --- a/src/share/vm/ci/ciMethod.hpp Wed Dec 07 07:27:09 2011 -0800 31.2 +++ b/src/share/vm/ci/ciMethod.hpp Thu Dec 08 10:27:33 2011 -0800 31.3 @@ -295,12 +295,6 @@ 31.4 // Print the name of this method in various incarnations. 31.5 void print_name(outputStream* st = tty); 31.6 void print_short_name(outputStream* st = tty); 31.7 - 31.8 - methodOop get_method_handle_target() { 31.9 - KlassHandle receiver_limit; int flags = 0; 31.10 - methodHandle m = MethodHandles::decode_method(get_oop(), receiver_limit, flags); 31.11 - return m(); 31.12 - } 31.13 }; 31.14 31.15 #endif // SHARE_VM_CI_CIMETHOD_HPP
32.1 --- a/src/share/vm/compiler/compileBroker.cpp Wed Dec 07 07:27:09 2011 -0800 32.2 +++ b/src/share/vm/compiler/compileBroker.cpp Thu Dec 08 10:27:33 2011 -0800 32.3 @@ -1748,7 +1748,7 @@ 32.4 tty->print("%4d ", compile_id); // print compilation number 32.5 tty->print("%s ", (is_osr ? "%" : " ")); 32.6 int code_size = (task->code() == NULL) ? 0 : task->code()->total_size(); 32.7 - tty->print_cr("size: %d time: %d inlined: %d bytes", code_size, time.milliseconds(), task->num_inlined_bytecodes()); 32.8 + tty->print_cr("size: %d time: %d inlined: %d bytes", code_size, (int)time.milliseconds(), task->num_inlined_bytecodes()); 32.9 } 32.10 32.11 if (compilable == ciEnv::MethodCompilable_never) {
33.1 --- a/src/share/vm/opto/block.cpp Wed Dec 07 07:27:09 2011 -0800 33.2 +++ b/src/share/vm/opto/block.cpp Thu Dec 08 10:27:33 2011 -0800 33.3 @@ -898,45 +898,41 @@ 33.4 void PhaseCFG::verify( ) const { 33.5 #ifdef ASSERT 33.6 // Verify sane CFG 33.7 - for( uint i = 0; i < _num_blocks; i++ ) { 33.8 + for (uint i = 0; i < _num_blocks; i++) { 33.9 Block *b = _blocks[i]; 33.10 uint cnt = b->_nodes.size(); 33.11 uint j; 33.12 - for( j = 0; j < cnt; j++ ) { 33.13 + for (j = 0; j < cnt; j++) { 33.14 Node *n = b->_nodes[j]; 33.15 assert( _bbs[n->_idx] == b, "" ); 33.16 - if( j >= 1 && n->is_Mach() && 33.17 - n->as_Mach()->ideal_Opcode() == Op_CreateEx ) { 33.18 - assert( j == 1 || b->_nodes[j-1]->is_Phi(), 33.19 - "CreateEx must be first instruction in block" ); 33.20 + if (j >= 1 && n->is_Mach() && 33.21 + n->as_Mach()->ideal_Opcode() == Op_CreateEx) { 33.22 + assert(j == 1 || b->_nodes[j-1]->is_Phi(), 33.23 + "CreateEx must be first instruction in block"); 33.24 } 33.25 - for( uint k = 0; k < n->req(); k++ ) { 33.26 + for (uint k = 0; k < n->req(); k++) { 33.27 Node *def = n->in(k); 33.28 - if( def && def != n ) { 33.29 - assert( _bbs[def->_idx] || def->is_Con(), 33.30 - "must have block; constants for debug info ok" ); 33.31 + if (def && def != n) { 33.32 + assert(_bbs[def->_idx] || def->is_Con(), 33.33 + "must have block; constants for debug info ok"); 33.34 // Verify that instructions in the block is in correct order. 33.35 // Uses must follow their definition if they are at the same block. 33.36 // Mostly done to check that MachSpillCopy nodes are placed correctly 33.37 // when CreateEx node is moved in build_ifg_physical(). 33.38 - if( _bbs[def->_idx] == b && 33.39 + if (_bbs[def->_idx] == b && 33.40 !(b->head()->is_Loop() && n->is_Phi()) && 33.41 // See (+++) comment in reg_split.cpp 33.42 - !(n->jvms() != NULL && n->jvms()->is_monitor_use(k)) ) { 33.43 + !(n->jvms() != NULL && n->jvms()->is_monitor_use(k))) { 33.44 bool is_loop = false; 33.45 if (n->is_Phi()) { 33.46 - for( uint l = 1; l < def->req(); l++ ) { 33.47 + for (uint l = 1; l < def->req(); l++) { 33.48 if (n == def->in(l)) { 33.49 is_loop = true; 33.50 break; // Some kind of loop 33.51 } 33.52 } 33.53 } 33.54 - assert( is_loop || b->find_node(def) < j, "uses must follow definitions" ); 33.55 - } 33.56 - if( def->is_SafePointScalarObject() ) { 33.57 - assert(_bbs[def->_idx] == b, "SafePointScalarObject Node should be at the same block as its SafePoint node"); 33.58 - assert(_bbs[def->_idx] == _bbs[def->in(0)->_idx], "SafePointScalarObject Node should be at the same block as its control edge"); 33.59 + assert(is_loop || b->find_node(def) < j, "uses must follow definitions"); 33.60 } 33.61 } 33.62 } 33.63 @@ -946,12 +942,11 @@ 33.64 Node *bp = (Node*)b->_nodes[b->_nodes.size()-1]->is_block_proj(); 33.65 assert( bp, "last instruction must be a block proj" ); 33.66 assert( bp == b->_nodes[j], "wrong number of successors for this block" ); 33.67 - if( bp->is_Catch() ) { 33.68 - while( b->_nodes[--j]->is_MachProj() ) ; 33.69 - assert( b->_nodes[j]->is_MachCall(), "CatchProj must follow call" ); 33.70 - } 33.71 - else if( bp->is_Mach() && bp->as_Mach()->ideal_Opcode() == Op_If ) { 33.72 - assert( b->_num_succs == 2, "Conditional branch must have two targets"); 33.73 + if (bp->is_Catch()) { 33.74 + while (b->_nodes[--j]->is_MachProj()) ; 33.75 + assert(b->_nodes[j]->is_MachCall(), "CatchProj must follow call"); 33.76 + } else if (bp->is_Mach() && bp->as_Mach()->ideal_Opcode() == Op_If) { 33.77 + assert(b->_num_succs == 2, "Conditional branch must have two targets"); 33.78 } 33.79 } 33.80 #endif
34.1 --- a/src/share/vm/opto/block.hpp Wed Dec 07 07:27:09 2011 -0800 34.2 +++ b/src/share/vm/opto/block.hpp Thu Dec 08 10:27:33 2011 -0800 34.3 @@ -281,6 +281,8 @@ 34.4 // Find and remove n from block list 34.5 void find_remove( const Node *n ); 34.6 34.7 + // helper function that adds caller save registers to MachProjNode 34.8 + void add_call_kills(MachProjNode *proj, RegMask& regs, const char* save_policy, bool exclude_soe); 34.9 // Schedule a call next in the block 34.10 uint sched_call(Matcher &matcher, Block_Array &bbs, uint node_cnt, Node_List &worklist, int *ready_cnt, MachCallNode *mcall, VectorSet &next_call); 34.11
35.1 --- a/src/share/vm/opto/c2_globals.hpp Wed Dec 07 07:27:09 2011 -0800 35.2 +++ b/src/share/vm/opto/c2_globals.hpp Thu Dec 08 10:27:33 2011 -0800 35.3 @@ -456,6 +456,12 @@ 35.4 product(intx, EliminateAllocationArraySizeLimit, 64, \ 35.5 "Array size (number of elements) limit for scalar replacement") \ 35.6 \ 35.7 + product(bool, OptimizePtrCompare, true, \ 35.8 + "Use escape analysis to optimize pointers compare") \ 35.9 + \ 35.10 + notproduct(bool, PrintOptimizePtrCompare, false, \ 35.11 + "Print information about optimized pointers compare") \ 35.12 + \ 35.13 product(bool, UseOptoBiasInlining, true, \ 35.14 "Generate biased locking code in C2 ideal graph") \ 35.15 \
36.1 --- a/src/share/vm/opto/callGenerator.cpp Wed Dec 07 07:27:09 2011 -0800 36.2 +++ b/src/share/vm/opto/callGenerator.cpp Thu Dec 08 10:27:33 2011 -0800 36.3 @@ -318,17 +318,17 @@ 36.4 return new DirectCallGenerator(m, separate_io_proj); 36.5 } 36.6 36.7 -CallGenerator* CallGenerator::for_dynamic_call(ciMethod* m) { 36.8 - assert(m->is_method_handle_invoke() || m->is_method_handle_adapter(), "for_dynamic_call mismatch"); 36.9 - return new DynamicCallGenerator(m); 36.10 -} 36.11 - 36.12 CallGenerator* CallGenerator::for_virtual_call(ciMethod* m, int vtable_index) { 36.13 assert(!m->is_static(), "for_virtual_call mismatch"); 36.14 assert(!m->is_method_handle_invoke(), "should be a direct call"); 36.15 return new VirtualCallGenerator(m, vtable_index); 36.16 } 36.17 36.18 +CallGenerator* CallGenerator::for_dynamic_call(ciMethod* m) { 36.19 + assert(m->is_method_handle_invoke() || m->is_method_handle_adapter(), "for_dynamic_call mismatch"); 36.20 + return new DynamicCallGenerator(m); 36.21 +} 36.22 + 36.23 // Allow inlining decisions to be delayed 36.24 class LateInlineCallGenerator : public DirectCallGenerator { 36.25 CallGenerator* _inline_cg; 36.26 @@ -576,7 +576,9 @@ 36.27 kit.set_control(slow_ctl); 36.28 if (!kit.stopped()) { 36.29 slow_jvms = _if_missed->generate(kit.sync_jvms()); 36.30 - assert(slow_jvms != NULL, "miss path must not fail to generate"); 36.31 + if (kit.failing()) 36.32 + return NULL; // might happen because of NodeCountInliningCutoff 36.33 + assert(slow_jvms != NULL, "must be"); 36.34 kit.add_exception_states_from(slow_jvms); 36.35 kit.set_map(slow_jvms->map()); 36.36 if (!kit.stopped()) 36.37 @@ -682,6 +684,15 @@ 36.38 } 36.39 36.40 36.41 +CallGenerator* CallGenerator::for_method_handle_call(Node* method_handle, JVMState* jvms, 36.42 + ciMethod* caller, ciMethod* callee, ciCallProfile profile) { 36.43 + assert(callee->is_method_handle_invoke() || callee->is_method_handle_adapter(), "for_method_handle_call mismatch"); 36.44 + CallGenerator* cg = CallGenerator::for_method_handle_inline(method_handle, jvms, caller, callee, profile); 36.45 + if (cg != NULL) 36.46 + return cg; 36.47 + return CallGenerator::for_direct_call(callee); 36.48 +} 36.49 + 36.50 CallGenerator* CallGenerator::for_method_handle_inline(Node* method_handle, JVMState* jvms, 36.51 ciMethod* caller, ciMethod* callee, ciCallProfile profile) { 36.52 if (method_handle->Opcode() == Op_ConP) { 36.53 @@ -721,8 +732,8 @@ 36.54 // Generate a guard so that each can be inlined. We might want to 36.55 // do more inputs at later point but this gets the most common 36.56 // case. 36.57 - CallGenerator* cg1 = for_method_handle_inline(method_handle->in(1), jvms, caller, callee, profile.rescale(1.0 - prob)); 36.58 - CallGenerator* cg2 = for_method_handle_inline(method_handle->in(2), jvms, caller, callee, profile.rescale(prob)); 36.59 + CallGenerator* cg1 = for_method_handle_call(method_handle->in(1), jvms, caller, callee, profile.rescale(1.0 - prob)); 36.60 + CallGenerator* cg2 = for_method_handle_call(method_handle->in(2), jvms, caller, callee, profile.rescale(prob)); 36.61 if (cg1 != NULL && cg2 != NULL) { 36.62 const TypeOopPtr* oop_ptr = method_handle->in(1)->bottom_type()->is_oopptr(); 36.63 ciObject* const_oop = oop_ptr->const_oop(); 36.64 @@ -733,6 +744,17 @@ 36.65 return NULL; 36.66 } 36.67 36.68 +CallGenerator* CallGenerator::for_invokedynamic_call(JVMState* jvms, ciMethod* caller, ciMethod* callee, ciCallProfile profile) { 36.69 + assert(callee->is_method_handle_invoke() || callee->is_method_handle_adapter(), "for_invokedynamic_call mismatch"); 36.70 + // Get the CallSite object. 36.71 + ciBytecodeStream str(caller); 36.72 + str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci. 36.73 + ciCallSite* call_site = str.get_call_site(); 36.74 + CallGenerator* cg = CallGenerator::for_invokedynamic_inline(call_site, jvms, caller, callee, profile); 36.75 + if (cg != NULL) 36.76 + return cg; 36.77 + return CallGenerator::for_dynamic_call(callee); 36.78 +} 36.79 36.80 CallGenerator* CallGenerator::for_invokedynamic_inline(ciCallSite* call_site, JVMState* jvms, 36.81 ciMethod* caller, ciMethod* callee, ciCallProfile profile) { 36.82 @@ -819,7 +841,9 @@ 36.83 kit.set_control(slow_ctl); 36.84 if (!kit.stopped()) { 36.85 slow_jvms = _if_missed->generate(kit.sync_jvms()); 36.86 - assert(slow_jvms != NULL, "miss path must not fail to generate"); 36.87 + if (kit.failing()) 36.88 + return NULL; // might happen because of NodeCountInliningCutoff 36.89 + assert(slow_jvms != NULL, "must be"); 36.90 kit.add_exception_states_from(slow_jvms); 36.91 kit.set_map(slow_jvms->map()); 36.92 if (!kit.stopped())
37.1 --- a/src/share/vm/opto/callGenerator.hpp Wed Dec 07 07:27:09 2011 -0800 37.2 +++ b/src/share/vm/opto/callGenerator.hpp Thu Dec 08 10:27:33 2011 -0800 37.3 @@ -108,8 +108,11 @@ 37.4 37.5 // How to generate vanilla out-of-line call sites: 37.6 static CallGenerator* for_direct_call(ciMethod* m, bool separate_io_projs = false); // static, special 37.7 + static CallGenerator* for_virtual_call(ciMethod* m, int vtable_index); // virtual, interface 37.8 static CallGenerator* for_dynamic_call(ciMethod* m); // invokedynamic 37.9 - static CallGenerator* for_virtual_call(ciMethod* m, int vtable_index); // virtual, interface 37.10 + 37.11 + static CallGenerator* for_method_handle_call(Node* method_handle, JVMState* jvms, ciMethod* caller, ciMethod* callee, ciCallProfile profile); 37.12 + static CallGenerator* for_invokedynamic_call( JVMState* jvms, ciMethod* caller, ciMethod* callee, ciCallProfile profile); 37.13 37.14 static CallGenerator* for_method_handle_inline(Node* method_handle, JVMState* jvms, ciMethod* caller, ciMethod* callee, ciCallProfile profile); 37.15 static CallGenerator* for_invokedynamic_inline(ciCallSite* call_site, JVMState* jvms, ciMethod* caller, ciMethod* callee, ciCallProfile profile);
38.1 --- a/src/share/vm/opto/callnode.cpp Wed Dec 07 07:27:09 2011 -0800 38.2 +++ b/src/share/vm/opto/callnode.cpp Thu Dec 08 10:27:33 2011 -0800 38.3 @@ -1071,8 +1071,11 @@ 38.4 init_class_id(Class_SafePointScalarObject); 38.5 } 38.6 38.7 -bool SafePointScalarObjectNode::pinned() const { return true; } 38.8 -bool SafePointScalarObjectNode::depends_only_on_test() const { return false; } 38.9 +// Do not allow value-numbering for SafePointScalarObject node. 38.10 +uint SafePointScalarObjectNode::hash() const { return NO_HASH; } 38.11 +uint SafePointScalarObjectNode::cmp( const Node &n ) const { 38.12 + return (&n == this); // Always fail except on self 38.13 +} 38.14 38.15 uint SafePointScalarObjectNode::ideal_reg() const { 38.16 return 0; // No matching to machine instruction 38.17 @@ -1096,7 +1099,6 @@ 38.18 if (cached != NULL) { 38.19 return (SafePointScalarObjectNode*)cached; 38.20 } 38.21 - Compile* C = Compile::current(); 38.22 SafePointScalarObjectNode* res = (SafePointScalarObjectNode*)Node::clone(); 38.23 res->_first_index += jvms_adj; 38.24 sosn_map->Insert((void*)this, (void*)res); 38.25 @@ -1142,6 +1144,8 @@ 38.26 38.27 Node* AllocateArrayNode::Ideal(PhaseGVN *phase, bool can_reshape) { 38.28 if (remove_dead_region(phase, can_reshape)) return this; 38.29 + // Don't bother trying to transform a dead node 38.30 + if (in(0) && in(0)->is_top()) return NULL; 38.31 38.32 const Type* type = phase->type(Ideal_length()); 38.33 if (type->isa_int() && type->is_int()->_hi < 0) { 38.34 @@ -1522,13 +1526,16 @@ 38.35 38.36 // perform any generic optimizations first (returns 'this' or NULL) 38.37 Node *result = SafePointNode::Ideal(phase, can_reshape); 38.38 + if (result != NULL) return result; 38.39 + // Don't bother trying to transform a dead node 38.40 + if (in(0) && in(0)->is_top()) return NULL; 38.41 38.42 // Now see if we can optimize away this lock. We don't actually 38.43 // remove the locking here, we simply set the _eliminate flag which 38.44 // prevents macro expansion from expanding the lock. Since we don't 38.45 // modify the graph, the value returned from this function is the 38.46 // one computed above. 38.47 - if (result == NULL && can_reshape && EliminateLocks && !is_eliminated()) { 38.48 + if (can_reshape && EliminateLocks && (!is_eliminated() || is_coarsened())) { 38.49 // 38.50 // If we are locking an unescaped object, the lock/unlock is unnecessary 38.51 // 38.52 @@ -1537,8 +1544,16 @@ 38.53 if (cgr != NULL) 38.54 es = cgr->escape_state(obj_node()); 38.55 if (es != PointsToNode::UnknownEscape && es != PointsToNode::GlobalEscape) { 38.56 - // Mark it eliminated to update any counters 38.57 - this->set_eliminated(); 38.58 + if (!is_eliminated()) { 38.59 + // Mark it eliminated to update any counters 38.60 + this->set_eliminated(); 38.61 + } else { 38.62 + assert(is_coarsened(), "sanity"); 38.63 + // The lock could be marked eliminated by lock coarsening 38.64 + // code during first IGVN before EA. Clear coarsened flag 38.65 + // to eliminate all associated locks/unlocks. 38.66 + this->clear_coarsened(); 38.67 + } 38.68 return result; 38.69 } 38.70 38.71 @@ -1546,7 +1561,7 @@ 38.72 // Try lock coarsening 38.73 // 38.74 PhaseIterGVN* iter = phase->is_IterGVN(); 38.75 - if (iter != NULL) { 38.76 + if (iter != NULL && !is_eliminated()) { 38.77 38.78 GrowableArray<AbstractLockNode*> lock_ops; 38.79 38.80 @@ -1602,7 +1617,7 @@ 38.81 lock->set_eliminated(); 38.82 lock->set_coarsened(); 38.83 } 38.84 - } else if (result != NULL && ctrl->is_Region() && 38.85 + } else if (ctrl->is_Region() && 38.86 iter->_worklist.member(ctrl)) { 38.87 // We weren't able to find any opportunities but the region this 38.88 // lock is control dependent on hasn't been processed yet so put 38.89 @@ -1623,7 +1638,10 @@ 38.90 Node *UnlockNode::Ideal(PhaseGVN *phase, bool can_reshape) { 38.91 38.92 // perform any generic optimizations first (returns 'this' or NULL) 38.93 - Node * result = SafePointNode::Ideal(phase, can_reshape); 38.94 + Node *result = SafePointNode::Ideal(phase, can_reshape); 38.95 + if (result != NULL) return result; 38.96 + // Don't bother trying to transform a dead node 38.97 + if (in(0) && in(0)->is_top()) return NULL; 38.98 38.99 // Now see if we can optimize away this unlock. We don't actually 38.100 // remove the unlocking here, we simply set the _eliminate flag which 38.101 @@ -1631,7 +1649,7 @@ 38.102 // modify the graph, the value returned from this function is the 38.103 // one computed above. 38.104 // Escape state is defined after Parse phase. 38.105 - if (result == NULL && can_reshape && EliminateLocks && !is_eliminated()) { 38.106 + if (can_reshape && EliminateLocks && (!is_eliminated() || is_coarsened())) { 38.107 // 38.108 // If we are unlocking an unescaped object, the lock/unlock is unnecessary. 38.109 // 38.110 @@ -1640,8 +1658,16 @@ 38.111 if (cgr != NULL) 38.112 es = cgr->escape_state(obj_node()); 38.113 if (es != PointsToNode::UnknownEscape && es != PointsToNode::GlobalEscape) { 38.114 - // Mark it eliminated to update any counters 38.115 - this->set_eliminated(); 38.116 + if (!is_eliminated()) { 38.117 + // Mark it eliminated to update any counters 38.118 + this->set_eliminated(); 38.119 + } else { 38.120 + assert(is_coarsened(), "sanity"); 38.121 + // The lock could be marked eliminated by lock coarsening 38.122 + // code during first IGVN before EA. Clear coarsened flag 38.123 + // to eliminate all associated locks/unlocks. 38.124 + this->clear_coarsened(); 38.125 + } 38.126 } 38.127 } 38.128 return result;
39.1 --- a/src/share/vm/opto/callnode.hpp Wed Dec 07 07:27:09 2011 -0800 39.2 +++ b/src/share/vm/opto/callnode.hpp Thu Dec 08 10:27:33 2011 -0800 39.3 @@ -440,6 +440,10 @@ 39.4 // states of the scalarized object fields are collected. 39.5 uint _n_fields; // Number of non-static fields of the scalarized object. 39.6 DEBUG_ONLY(AllocateNode* _alloc;) 39.7 + 39.8 + virtual uint hash() const ; // { return NO_HASH; } 39.9 + virtual uint cmp( const Node &n ) const; 39.10 + 39.11 public: 39.12 SafePointScalarObjectNode(const TypeOopPtr* tp, 39.13 #ifdef ASSERT 39.14 @@ -454,15 +458,10 @@ 39.15 39.16 uint first_index() const { return _first_index; } 39.17 uint n_fields() const { return _n_fields; } 39.18 - DEBUG_ONLY(AllocateNode* alloc() const { return _alloc; }) 39.19 39.20 - // SafePointScalarObject should be always pinned to the control edge 39.21 - // of the SafePoint node for which it was generated. 39.22 - virtual bool pinned() const; // { return true; } 39.23 - 39.24 - // SafePointScalarObject depends on the SafePoint node 39.25 - // for which it was generated. 39.26 - virtual bool depends_only_on_test() const; // { return false; } 39.27 +#ifdef ASSERT 39.28 + AllocateNode* alloc() const { return _alloc; } 39.29 +#endif 39.30 39.31 virtual uint size_of() const { return sizeof(*this); } 39.32 39.33 @@ -880,6 +879,7 @@ 39.34 39.35 bool is_coarsened() { return _coarsened; } 39.36 void set_coarsened() { _coarsened = true; } 39.37 + void clear_coarsened() { _coarsened = false; } 39.38 39.39 // locking does not modify its arguments 39.40 virtual bool may_modify(const TypePtr *addr_t, PhaseTransform *phase){ return false;}
40.1 --- a/src/share/vm/opto/cfgnode.cpp Wed Dec 07 07:27:09 2011 -0800 40.2 +++ b/src/share/vm/opto/cfgnode.cpp Thu Dec 08 10:27:33 2011 -0800 40.3 @@ -460,8 +460,11 @@ 40.4 // Is it dead loop? 40.5 // If it is LoopNopde it had 2 (+1 itself) inputs and 40.6 // one of them was cut. The loop is dead if it was EntryContol. 40.7 - assert(!this->is_Loop() || cnt_orig == 3, "Loop node should have 3 inputs"); 40.8 - if (this->is_Loop() && del_it == LoopNode::EntryControl || 40.9 + // Loop node may have only one input because entry path 40.10 + // is removed in PhaseIdealLoop::Dominators(). 40.11 + assert(!this->is_Loop() || cnt_orig <= 3, "Loop node should have 3 or less inputs"); 40.12 + if (this->is_Loop() && (del_it == LoopNode::EntryControl || 40.13 + del_it == 0 && is_unreachable_region(phase)) || 40.14 !this->is_Loop() && has_phis && is_unreachable_region(phase)) { 40.15 // Yes, the region will be removed during the next step below. 40.16 // Cut the backedge input and remove phis since no data paths left. 40.17 @@ -1585,14 +1588,17 @@ 40.18 // Only one not-NULL unique input path is left. 40.19 // Determine if this input is backedge of a loop. 40.20 // (Skip new phis which have no uses and dead regions). 40.21 - if( outcnt() > 0 && r->in(0) != NULL ) { 40.22 + if (outcnt() > 0 && r->in(0) != NULL) { 40.23 // First, take the short cut when we know it is a loop and 40.24 // the EntryControl data path is dead. 40.25 - assert(!r->is_Loop() || r->req() == 3, "Loop node should have 3 inputs"); 40.26 + // Loop node may have only one input because entry path 40.27 + // is removed in PhaseIdealLoop::Dominators(). 40.28 + assert(!r->is_Loop() || r->req() <= 3, "Loop node should have 3 or less inputs"); 40.29 + bool is_loop = (r->is_Loop() && r->req() == 3); 40.30 // Then, check if there is a data loop when phi references itself directly 40.31 // or through other data nodes. 40.32 - if( r->is_Loop() && !phase->eqv_uncast(uin, in(LoopNode::EntryControl)) || 40.33 - !r->is_Loop() && is_unsafe_data_reference(uin) ) { 40.34 + if (is_loop && !phase->eqv_uncast(uin, in(LoopNode::EntryControl)) || 40.35 + !is_loop && is_unsafe_data_reference(uin)) { 40.36 // Break this data loop to avoid creation of a dead loop. 40.37 if (can_reshape) { 40.38 return top;
41.1 --- a/src/share/vm/opto/compile.cpp Wed Dec 07 07:27:09 2011 -0800 41.2 +++ b/src/share/vm/opto/compile.cpp Thu Dec 08 10:27:33 2011 -0800 41.3 @@ -1711,11 +1711,22 @@ 41.4 41.5 if (failing()) return; 41.6 41.7 + // Optimize out fields loads from scalar replaceable allocations. 41.8 igvn.optimize(); 41.9 print_method("Iter GVN after EA", 2); 41.10 41.11 if (failing()) return; 41.12 41.13 + if (congraph() != NULL && macro_count() > 0) { 41.14 + PhaseMacroExpand mexp(igvn); 41.15 + mexp.eliminate_macro_nodes(); 41.16 + igvn.set_delay_transform(false); 41.17 + 41.18 + igvn.optimize(); 41.19 + print_method("Iter GVN after eliminating allocations and locks", 2); 41.20 + 41.21 + if (failing()) return; 41.22 + } 41.23 } 41.24 41.25 // Loop transforms on the ideal graph. Range Check Elimination, 41.26 @@ -3052,24 +3063,13 @@ 41.27 return false; 41.28 } 41.29 41.30 -// Emit constants grouped in the following order: 41.31 -static BasicType type_order[] = { 41.32 - T_FLOAT, // 32-bit 41.33 - T_OBJECT, // 32 or 64-bit 41.34 - T_ADDRESS, // 32 or 64-bit 41.35 - T_DOUBLE, // 64-bit 41.36 - T_LONG, // 64-bit 41.37 - T_VOID, // 32 or 64-bit (jump-tables are at the end of the constant table for code emission reasons) 41.38 - T_ILLEGAL 41.39 -}; 41.40 - 41.41 static int type_to_size_in_bytes(BasicType t) { 41.42 switch (t) { 41.43 case T_LONG: return sizeof(jlong ); 41.44 case T_FLOAT: return sizeof(jfloat ); 41.45 case T_DOUBLE: return sizeof(jdouble); 41.46 // We use T_VOID as marker for jump-table entries (labels) which 41.47 - // need an interal word relocation. 41.48 + // need an internal word relocation. 41.49 case T_VOID: 41.50 case T_ADDRESS: 41.51 case T_OBJECT: return sizeof(jobject); 41.52 @@ -3079,87 +3079,92 @@ 41.53 return -1; 41.54 } 41.55 41.56 +int Compile::ConstantTable::qsort_comparator(Constant* a, Constant* b) { 41.57 + // sort descending 41.58 + if (a->freq() > b->freq()) return -1; 41.59 + if (a->freq() < b->freq()) return 1; 41.60 + return 0; 41.61 +} 41.62 + 41.63 void Compile::ConstantTable::calculate_offsets_and_size() { 41.64 - int size = 0; 41.65 - for (int t = 0; type_order[t] != T_ILLEGAL; t++) { 41.66 - BasicType type = type_order[t]; 41.67 - 41.68 - for (int i = 0; i < _constants.length(); i++) { 41.69 - Constant con = _constants.at(i); 41.70 - if (con.type() != type) continue; // Skip other types. 41.71 - 41.72 - // Align size for type. 41.73 - int typesize = type_to_size_in_bytes(con.type()); 41.74 - size = align_size_up(size, typesize); 41.75 - 41.76 - // Set offset. 41.77 - con.set_offset(size); 41.78 - _constants.at_put(i, con); 41.79 - 41.80 - // Add type size. 41.81 - size = size + typesize; 41.82 + // First, sort the array by frequencies. 41.83 + _constants.sort(qsort_comparator); 41.84 + 41.85 +#ifdef ASSERT 41.86 + // Make sure all jump-table entries were sorted to the end of the 41.87 + // array (they have a negative frequency). 41.88 + bool found_void = false; 41.89 + for (int i = 0; i < _constants.length(); i++) { 41.90 + Constant con = _constants.at(i); 41.91 + if (con.type() == T_VOID) 41.92 + found_void = true; // jump-tables 41.93 + else 41.94 + assert(!found_void, "wrong sorting"); 41.95 + } 41.96 +#endif 41.97 + 41.98 + int offset = 0; 41.99 + for (int i = 0; i < _constants.length(); i++) { 41.100 + Constant* con = _constants.adr_at(i); 41.101 + 41.102 + // Align offset for type. 41.103 + int typesize = type_to_size_in_bytes(con->type()); 41.104 + offset = align_size_up(offset, typesize); 41.105 + con->set_offset(offset); // set constant's offset 41.106 + 41.107 + if (con->type() == T_VOID) { 41.108 + MachConstantNode* n = (MachConstantNode*) con->get_jobject(); 41.109 + offset = offset + typesize * n->outcnt(); // expand jump-table 41.110 + } else { 41.111 + offset = offset + typesize; 41.112 } 41.113 } 41.114 41.115 // Align size up to the next section start (which is insts; see 41.116 // CodeBuffer::align_at_start). 41.117 assert(_size == -1, "already set?"); 41.118 - _size = align_size_up(size, CodeEntryAlignment); 41.119 - 41.120 - if (Matcher::constant_table_absolute_addressing) { 41.121 - set_table_base_offset(0); // No table base offset required 41.122 - } else { 41.123 - if (UseRDPCForConstantTableBase) { 41.124 - // table base offset is set in MachConstantBaseNode::emit 41.125 - } else { 41.126 - // When RDPC is not used, the table base is set into the middle of 41.127 - // the constant table. 41.128 - int half_size = _size / 2; 41.129 - assert(half_size * 2 == _size, "sanity"); 41.130 - set_table_base_offset(-half_size); 41.131 - } 41.132 - } 41.133 + _size = align_size_up(offset, CodeEntryAlignment); 41.134 } 41.135 41.136 void Compile::ConstantTable::emit(CodeBuffer& cb) { 41.137 MacroAssembler _masm(&cb); 41.138 - for (int t = 0; type_order[t] != T_ILLEGAL; t++) { 41.139 - BasicType type = type_order[t]; 41.140 - 41.141 - for (int i = 0; i < _constants.length(); i++) { 41.142 - Constant con = _constants.at(i); 41.143 - if (con.type() != type) continue; // Skip other types. 41.144 - 41.145 - address constant_addr; 41.146 - switch (con.type()) { 41.147 - case T_LONG: constant_addr = _masm.long_constant( con.get_jlong() ); break; 41.148 - case T_FLOAT: constant_addr = _masm.float_constant( con.get_jfloat() ); break; 41.149 - case T_DOUBLE: constant_addr = _masm.double_constant(con.get_jdouble()); break; 41.150 - case T_OBJECT: { 41.151 - jobject obj = con.get_jobject(); 41.152 - int oop_index = _masm.oop_recorder()->find_index(obj); 41.153 - constant_addr = _masm.address_constant((address) obj, oop_Relocation::spec(oop_index)); 41.154 - break; 41.155 + for (int i = 0; i < _constants.length(); i++) { 41.156 + Constant con = _constants.at(i); 41.157 + address constant_addr; 41.158 + switch (con.type()) { 41.159 + case T_LONG: constant_addr = _masm.long_constant( con.get_jlong() ); break; 41.160 + case T_FLOAT: constant_addr = _masm.float_constant( con.get_jfloat() ); break; 41.161 + case T_DOUBLE: constant_addr = _masm.double_constant(con.get_jdouble()); break; 41.162 + case T_OBJECT: { 41.163 + jobject obj = con.get_jobject(); 41.164 + int oop_index = _masm.oop_recorder()->find_index(obj); 41.165 + constant_addr = _masm.address_constant((address) obj, oop_Relocation::spec(oop_index)); 41.166 + break; 41.167 + } 41.168 + case T_ADDRESS: { 41.169 + address addr = (address) con.get_jobject(); 41.170 + constant_addr = _masm.address_constant(addr); 41.171 + break; 41.172 + } 41.173 + // We use T_VOID as marker for jump-table entries (labels) which 41.174 + // need an internal word relocation. 41.175 + case T_VOID: { 41.176 + MachConstantNode* n = (MachConstantNode*) con.get_jobject(); 41.177 + // Fill the jump-table with a dummy word. The real value is 41.178 + // filled in later in fill_jump_table. 41.179 + address dummy = (address) n; 41.180 + constant_addr = _masm.address_constant(dummy); 41.181 + // Expand jump-table 41.182 + for (uint i = 1; i < n->outcnt(); i++) { 41.183 + address temp_addr = _masm.address_constant(dummy + i); 41.184 + assert(temp_addr, "consts section too small"); 41.185 } 41.186 - case T_ADDRESS: { 41.187 - address addr = (address) con.get_jobject(); 41.188 - constant_addr = _masm.address_constant(addr); 41.189 - break; 41.190 - } 41.191 - // We use T_VOID as marker for jump-table entries (labels) which 41.192 - // need an interal word relocation. 41.193 - case T_VOID: { 41.194 - // Write a dummy word. The real value is filled in later 41.195 - // in fill_jump_table_in_constant_table. 41.196 - address addr = (address) con.get_jobject(); 41.197 - constant_addr = _masm.address_constant(addr); 41.198 - break; 41.199 - } 41.200 - default: ShouldNotReachHere(); 41.201 - } 41.202 - assert(constant_addr != NULL, "consts section too small"); 41.203 - assert((constant_addr - _masm.code()->consts()->start()) == con.offset(), err_msg("must be: %d == %d", constant_addr - _masm.code()->consts()->start(), con.offset())); 41.204 + break; 41.205 } 41.206 + default: ShouldNotReachHere(); 41.207 + } 41.208 + assert(constant_addr, "consts section too small"); 41.209 + assert((constant_addr - _masm.code()->consts()->start()) == con.offset(), err_msg("must be: %d == %d", constant_addr - _masm.code()->consts()->start(), con.offset())); 41.210 } 41.211 } 41.212 41.213 @@ -3175,19 +3180,21 @@ 41.214 if (con.can_be_reused()) { 41.215 int idx = _constants.find(con); 41.216 if (idx != -1 && _constants.at(idx).can_be_reused()) { 41.217 + _constants.adr_at(idx)->inc_freq(con.freq()); // increase the frequency by the current value 41.218 return; 41.219 } 41.220 } 41.221 (void) _constants.append(con); 41.222 } 41.223 41.224 -Compile::Constant Compile::ConstantTable::add(BasicType type, jvalue value) { 41.225 - Constant con(type, value); 41.226 +Compile::Constant Compile::ConstantTable::add(MachConstantNode* n, BasicType type, jvalue value) { 41.227 + Block* b = Compile::current()->cfg()->_bbs[n->_idx]; 41.228 + Constant con(type, value, b->_freq); 41.229 add(con); 41.230 return con; 41.231 } 41.232 41.233 -Compile::Constant Compile::ConstantTable::add(MachOper* oper) { 41.234 +Compile::Constant Compile::ConstantTable::add(MachConstantNode* n, MachOper* oper) { 41.235 jvalue value; 41.236 BasicType type = oper->type()->basic_type(); 41.237 switch (type) { 41.238 @@ -3198,20 +3205,18 @@ 41.239 case T_ADDRESS: value.l = (jobject) oper->constant(); break; 41.240 default: ShouldNotReachHere(); 41.241 } 41.242 - return add(type, value); 41.243 + return add(n, type, value); 41.244 } 41.245 41.246 -Compile::Constant Compile::ConstantTable::allocate_jump_table(MachConstantNode* n) { 41.247 +Compile::Constant Compile::ConstantTable::add_jump_table(MachConstantNode* n) { 41.248 jvalue value; 41.249 // We can use the node pointer here to identify the right jump-table 41.250 // as this method is called from Compile::Fill_buffer right before 41.251 // the MachNodes are emitted and the jump-table is filled (means the 41.252 // MachNode pointers do not change anymore). 41.253 value.l = (jobject) n; 41.254 - Constant con(T_VOID, value, false); // Labels of a jump-table cannot be reused. 41.255 - for (uint i = 0; i < n->outcnt(); i++) { 41.256 - add(con); 41.257 - } 41.258 + Constant con(T_VOID, value, next_jump_table_freq(), false); // Labels of a jump-table cannot be reused. 41.259 + add(con); 41.260 return con; 41.261 } 41.262 41.263 @@ -3230,9 +3235,9 @@ 41.264 MacroAssembler _masm(&cb); 41.265 address* jump_table_base = (address*) (_masm.code()->consts()->start() + offset); 41.266 41.267 - for (int i = 0; i < labels.length(); i++) { 41.268 + for (uint i = 0; i < n->outcnt(); i++) { 41.269 address* constant_addr = &jump_table_base[i]; 41.270 - assert(*constant_addr == (address) n, "all jump-table entries must contain node pointer"); 41.271 + assert(*constant_addr == (((address) n) + i), err_msg("all jump-table entries must contain adjusted node pointer: " INTPTR_FORMAT " == " INTPTR_FORMAT, *constant_addr, (((address) n) + i))); 41.272 *constant_addr = cb.consts()->target(*labels.at(i), (address) constant_addr); 41.273 cb.consts()->relocate((address) constant_addr, relocInfo::internal_word_type); 41.274 }
42.1 --- a/src/share/vm/opto/compile.hpp Wed Dec 07 07:27:09 2011 -0800 42.2 +++ b/src/share/vm/opto/compile.hpp Thu Dec 08 10:27:33 2011 -0800 42.3 @@ -150,14 +150,16 @@ 42.4 BasicType _type; 42.5 jvalue _value; 42.6 int _offset; // offset of this constant (in bytes) relative to the constant table base. 42.7 + float _freq; 42.8 bool _can_be_reused; // true (default) if the value can be shared with other users. 42.9 42.10 public: 42.11 - Constant() : _type(T_ILLEGAL), _offset(-1), _can_be_reused(true) { _value.l = 0; } 42.12 - Constant(BasicType type, jvalue value, bool can_be_reused = true) : 42.13 + Constant() : _type(T_ILLEGAL), _offset(-1), _freq(0.0f), _can_be_reused(true) { _value.l = 0; } 42.14 + Constant(BasicType type, jvalue value, float freq = 0.0f, bool can_be_reused = true) : 42.15 _type(type), 42.16 _value(value), 42.17 _offset(-1), 42.18 + _freq(freq), 42.19 _can_be_reused(can_be_reused) 42.20 {} 42.21 42.22 @@ -173,6 +175,9 @@ 42.23 int offset() const { return _offset; } 42.24 void set_offset(int offset) { _offset = offset; } 42.25 42.26 + float freq() const { return _freq; } 42.27 + void inc_freq(float freq) { _freq += freq; } 42.28 + 42.29 bool can_be_reused() const { return _can_be_reused; } 42.30 }; 42.31 42.32 @@ -182,41 +187,51 @@ 42.33 GrowableArray<Constant> _constants; // Constants of this table. 42.34 int _size; // Size in bytes the emitted constant table takes (including padding). 42.35 int _table_base_offset; // Offset of the table base that gets added to the constant offsets. 42.36 + int _nof_jump_tables; // Number of jump-tables in this constant table. 42.37 + 42.38 + static int qsort_comparator(Constant* a, Constant* b); 42.39 + 42.40 + // We use negative frequencies to keep the order of the 42.41 + // jump-tables in which they were added. Otherwise we get into 42.42 + // trouble with relocation. 42.43 + float next_jump_table_freq() { return -1.0f * (++_nof_jump_tables); } 42.44 42.45 public: 42.46 ConstantTable() : 42.47 _size(-1), 42.48 - _table_base_offset(-1) // We can use -1 here since the constant table is always bigger than 2 bytes (-(size / 2), see MachConstantBaseNode::emit). 42.49 + _table_base_offset(-1), // We can use -1 here since the constant table is always bigger than 2 bytes (-(size / 2), see MachConstantBaseNode::emit). 42.50 + _nof_jump_tables(0) 42.51 {} 42.52 42.53 - int size() const { assert(_size != -1, "size not yet calculated"); return _size; } 42.54 + int size() const { assert(_size != -1, "not calculated yet"); return _size; } 42.55 42.56 - void set_table_base_offset(int x) { assert(_table_base_offset == -1, "set only once"); _table_base_offset = x; } 42.57 - int table_base_offset() const { assert(_table_base_offset != -1, "table base offset not yet set"); return _table_base_offset; } 42.58 + int calculate_table_base_offset() const; // AD specific 42.59 + void set_table_base_offset(int x) { assert(_table_base_offset == -1 || x == _table_base_offset, "can't change"); _table_base_offset = x; } 42.60 + int table_base_offset() const { assert(_table_base_offset != -1, "not set yet"); return _table_base_offset; } 42.61 42.62 void emit(CodeBuffer& cb); 42.63 42.64 // Returns the offset of the last entry (the top) of the constant table. 42.65 - int top_offset() const { assert(_constants.top().offset() != -1, "constant not yet bound"); return _constants.top().offset(); } 42.66 + int top_offset() const { assert(_constants.top().offset() != -1, "not bound yet"); return _constants.top().offset(); } 42.67 42.68 void calculate_offsets_and_size(); 42.69 int find_offset(Constant& con) const; 42.70 42.71 void add(Constant& con); 42.72 - Constant add(BasicType type, jvalue value); 42.73 - Constant add(MachOper* oper); 42.74 - Constant add(jfloat f) { 42.75 + Constant add(MachConstantNode* n, BasicType type, jvalue value); 42.76 + Constant add(MachConstantNode* n, MachOper* oper); 42.77 + Constant add(MachConstantNode* n, jfloat f) { 42.78 jvalue value; value.f = f; 42.79 - return add(T_FLOAT, value); 42.80 + return add(n, T_FLOAT, value); 42.81 } 42.82 - Constant add(jdouble d) { 42.83 + Constant add(MachConstantNode* n, jdouble d) { 42.84 jvalue value; value.d = d; 42.85 - return add(T_DOUBLE, value); 42.86 + return add(n, T_DOUBLE, value); 42.87 } 42.88 42.89 - // Jump table 42.90 - Constant allocate_jump_table(MachConstantNode* n); 42.91 - void fill_jump_table(CodeBuffer& cb, MachConstantNode* n, GrowableArray<Label*> labels) const; 42.92 + // Jump-table 42.93 + Constant add_jump_table(MachConstantNode* n); 42.94 + void fill_jump_table(CodeBuffer& cb, MachConstantNode* n, GrowableArray<Label*> labels) const; 42.95 }; 42.96 42.97 private:
43.1 --- a/src/share/vm/opto/doCall.cpp Wed Dec 07 07:27:09 2011 -0800 43.2 +++ b/src/share/vm/opto/doCall.cpp Thu Dec 08 10:27:33 2011 -0800 43.3 @@ -62,7 +62,6 @@ 43.4 CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index, bool call_is_virtual, 43.5 JVMState* jvms, bool allow_inline, 43.6 float prof_factor) { 43.7 - CallGenerator* cg; 43.8 ciMethod* caller = jvms->method(); 43.9 int bci = jvms->bci(); 43.10 Bytecodes::Code bytecode = caller->java_code_at_bci(bci); 43.11 @@ -110,7 +109,7 @@ 43.12 // We do this before the strict f.p. check below because the 43.13 // intrinsics handle strict f.p. correctly. 43.14 if (allow_inline) { 43.15 - cg = find_intrinsic(call_method, call_is_virtual); 43.16 + CallGenerator* cg = find_intrinsic(call_method, call_is_virtual); 43.17 if (cg != NULL) return cg; 43.18 } 43.19 43.20 @@ -121,33 +120,16 @@ 43.21 if (call_method->is_method_handle_invoke()) { 43.22 if (bytecode != Bytecodes::_invokedynamic) { 43.23 GraphKit kit(jvms); 43.24 - Node* n = kit.argument(0); 43.25 - 43.26 - CallGenerator* cg = CallGenerator::for_method_handle_inline(n, jvms, caller, call_method, profile); 43.27 - if (cg != NULL) { 43.28 - return cg; 43.29 - } 43.30 - return CallGenerator::for_direct_call(call_method); 43.31 + Node* method_handle = kit.argument(0); 43.32 + return CallGenerator::for_method_handle_call(method_handle, jvms, caller, call_method, profile); 43.33 } 43.34 else { 43.35 - // Get the CallSite object. 43.36 - ciMethod* caller_method = jvms->method(); 43.37 - ciBytecodeStream str(caller_method); 43.38 - str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci. 43.39 - ciCallSite* call_site = str.get_call_site(); 43.40 - 43.41 - CallGenerator* cg = CallGenerator::for_invokedynamic_inline(call_site, jvms, caller, call_method, profile); 43.42 - if (cg != NULL) { 43.43 - return cg; 43.44 - } 43.45 - // If something failed, generate a normal dynamic call. 43.46 - return CallGenerator::for_dynamic_call(call_method); 43.47 + return CallGenerator::for_invokedynamic_call(jvms, caller, call_method, profile); 43.48 } 43.49 } 43.50 43.51 // Do not inline strict fp into non-strict code, or the reverse 43.52 - bool caller_method_is_strict = jvms->method()->is_strict(); 43.53 - if( caller_method_is_strict ^ call_method->is_strict() ) { 43.54 + if (caller->is_strict() ^ call_method->is_strict()) { 43.55 allow_inline = false; 43.56 } 43.57 43.58 @@ -258,7 +240,7 @@ 43.59 } 43.60 if (miss_cg != NULL) { 43.61 NOT_PRODUCT(trace_type_profile(jvms->method(), jvms->depth() - 1, jvms->bci(), receiver_method, profile.receiver(0), site_count, receiver_count)); 43.62 - cg = CallGenerator::for_predicted_call(profile.receiver(0), miss_cg, hit_cg, profile.receiver_prob(0)); 43.63 + CallGenerator* cg = CallGenerator::for_predicted_call(profile.receiver(0), miss_cg, hit_cg, profile.receiver_prob(0)); 43.64 if (cg != NULL) return cg; 43.65 } 43.66 }
44.1 --- a/src/share/vm/opto/escape.cpp Wed Dec 07 07:27:09 2011 -0800 44.2 +++ b/src/share/vm/opto/escape.cpp Thu Dec 08 10:27:33 2011 -0800 44.3 @@ -119,6 +119,8 @@ 44.4 } else { 44.5 _noop_null = _oop_null; // Should be initialized 44.6 } 44.7 + _pcmp_neq = NULL; // Should be initialized 44.8 + _pcmp_eq = NULL; 44.9 } 44.10 44.11 void ConnectionGraph::add_pointsto_edge(uint from_i, uint to_i) { 44.12 @@ -128,6 +130,13 @@ 44.13 assert(f->node_type() != PointsToNode::UnknownType && t->node_type() != PointsToNode::UnknownType, "node types must be set"); 44.14 assert(f->node_type() == PointsToNode::LocalVar || f->node_type() == PointsToNode::Field, "invalid source of PointsTo edge"); 44.15 assert(t->node_type() == PointsToNode::JavaObject, "invalid destination of PointsTo edge"); 44.16 + if (to_i == _phantom_object) { // Quick test for most common object 44.17 + if (f->has_unknown_ptr()) { 44.18 + return; 44.19 + } else { 44.20 + f->set_has_unknown_ptr(); 44.21 + } 44.22 + } 44.23 add_edge(f, to_i, PointsToNode::PointsToEdge); 44.24 } 44.25 44.26 @@ -163,6 +172,9 @@ 44.27 } 44.28 44.29 void ConnectionGraph::add_field_edge(uint from_i, uint to_i, int offset) { 44.30 + // Don't add fields to NULL pointer. 44.31 + if (is_null_ptr(from_i)) 44.32 + return; 44.33 PointsToNode *f = ptnode_adr(from_i); 44.34 PointsToNode *t = ptnode_adr(to_i); 44.35 44.36 @@ -177,7 +189,7 @@ 44.37 44.38 void ConnectionGraph::set_escape_state(uint ni, PointsToNode::EscapeState es) { 44.39 // Don't change non-escaping state of NULL pointer. 44.40 - if (ni == _noop_null || ni == _oop_null) 44.41 + if (is_null_ptr(ni)) 44.42 return; 44.43 PointsToNode *npt = ptnode_adr(ni); 44.44 PointsToNode::EscapeState old_es = npt->escape_state(); 44.45 @@ -309,6 +321,9 @@ 44.46 44.47 visited->set(ni); 44.48 PointsToNode *ptn = ptnode_adr(ni); 44.49 + assert(ptn->node_type() == PointsToNode::LocalVar || 44.50 + ptn->node_type() == PointsToNode::Field, "sanity"); 44.51 + assert(ptn->edge_count() != 0, "should have at least phantom_object"); 44.52 44.53 // Mark current edges as visited and move deferred edges to separate array. 44.54 for (uint i = 0; i < ptn->edge_count(); ) { 44.55 @@ -329,6 +344,7 @@ 44.56 uint t = deferred_edges->at(next); 44.57 PointsToNode *ptt = ptnode_adr(t); 44.58 uint e_cnt = ptt->edge_count(); 44.59 + assert(e_cnt != 0, "should have at least phantom_object"); 44.60 for (uint e = 0; e < e_cnt; e++) { 44.61 uint etgt = ptt->edge_target(e); 44.62 if (visited->test_set(etgt)) 44.63 @@ -337,10 +353,6 @@ 44.64 PointsToNode::EdgeType et = ptt->edge_type(e); 44.65 if (et == PointsToNode::PointsToEdge) { 44.66 add_pointsto_edge(ni, etgt); 44.67 - if(etgt == _phantom_object) { 44.68 - // Special case - field set outside (globally escaping). 44.69 - set_escape_state(ni, PointsToNode::GlobalEscape); 44.70 - } 44.71 } else if (et == PointsToNode::DeferredEdge) { 44.72 deferred_edges->append(etgt); 44.73 } else { 44.74 @@ -348,6 +360,20 @@ 44.75 } 44.76 } 44.77 } 44.78 + if (ptn->edge_count() == 0) { 44.79 + // No pointsto edges found after deferred edges are removed. 44.80 + // For example, in the next case where call is replaced 44.81 + // with uncommon trap and as result array's load references 44.82 + // itself through deferred edges: 44.83 + // 44.84 + // A a = b[i]; 44.85 + // if (c!=null) a = c.foo(); 44.86 + // b[i] = a; 44.87 + // 44.88 + // Assume the value was set outside this method and 44.89 + // add edge to phantom object. 44.90 + add_pointsto_edge(ni, _phantom_object); 44.91 + } 44.92 } 44.93 44.94 44.95 @@ -356,13 +382,25 @@ 44.96 // a pointsto edge is added if it is a JavaObject 44.97 44.98 void ConnectionGraph::add_edge_from_fields(uint adr_i, uint to_i, int offs) { 44.99 + // No fields for NULL pointer. 44.100 + if (is_null_ptr(adr_i)) { 44.101 + return; 44.102 + } 44.103 PointsToNode* an = ptnode_adr(adr_i); 44.104 PointsToNode* to = ptnode_adr(to_i); 44.105 bool deferred = (to->node_type() == PointsToNode::LocalVar); 44.106 - 44.107 + bool escaped = (to_i == _phantom_object) && (offs == Type::OffsetTop); 44.108 + if (escaped) { 44.109 + // Values in fields escaped during call. 44.110 + assert(an->escape_state() >= PointsToNode::ArgEscape, "sanity"); 44.111 + offs = Type::OffsetBot; 44.112 + } 44.113 for (uint fe = 0; fe < an->edge_count(); fe++) { 44.114 assert(an->edge_type(fe) == PointsToNode::FieldEdge, "expecting a field edge"); 44.115 int fi = an->edge_target(fe); 44.116 + if (escaped) { 44.117 + set_escape_state(fi, PointsToNode::GlobalEscape); 44.118 + } 44.119 PointsToNode* pf = ptnode_adr(fi); 44.120 int po = pf->offset(); 44.121 if (po == offs || po == Type::OffsetBot || offs == Type::OffsetBot) { 44.122 @@ -377,6 +415,15 @@ 44.123 // Add a deferred edge from node given by "from_i" to any field of adr_i 44.124 // whose offset matches "offset". 44.125 void ConnectionGraph::add_deferred_edge_to_fields(uint from_i, uint adr_i, int offs) { 44.126 + // No fields for NULL pointer. 44.127 + if (is_null_ptr(adr_i)) { 44.128 + return; 44.129 + } 44.130 + if (adr_i == _phantom_object) { 44.131 + // Add only one edge for unknown object. 44.132 + add_pointsto_edge(from_i, _phantom_object); 44.133 + return; 44.134 + } 44.135 PointsToNode* an = ptnode_adr(adr_i); 44.136 bool is_alloc = an->_node->is_Allocate(); 44.137 for (uint fe = 0; fe < an->edge_count(); fe++) { 44.138 @@ -392,6 +439,13 @@ 44.139 add_deferred_edge(from_i, fi); 44.140 } 44.141 } 44.142 + // Some fields references (AddP) may still be missing 44.143 + // until Connection Graph construction is complete. 44.144 + // For example, loads from RAW pointers with offset 0 44.145 + // which don't have AddP. 44.146 + // A reference to phantom_object will be added if 44.147 + // a field reference is still missing after completing 44.148 + // Connection Graph (see remove_deferred()). 44.149 } 44.150 44.151 // Helper functions 44.152 @@ -1540,8 +1594,8 @@ 44.153 44.154 GrowableArray<Node*> alloc_worklist; 44.155 GrowableArray<Node*> addp_worklist; 44.156 + GrowableArray<Node*> ptr_cmp_worklist; 44.157 PhaseGVN* igvn = _igvn; 44.158 - bool has_allocations = false; 44.159 44.160 // Push all useful nodes onto CG list and set their type. 44.161 for( uint next = 0; next < worklist_init.size(); ++next ) { 44.162 @@ -1551,11 +1605,8 @@ 44.163 // for an escape status. See process_call_result() below. 44.164 if (n->is_Allocate() || n->is_CallStaticJava() && 44.165 ptnode_adr(n->_idx)->node_type() == PointsToNode::JavaObject) { 44.166 - has_allocations = true; 44.167 - if (n->is_Allocate()) 44.168 - alloc_worklist.append(n); 44.169 - } 44.170 - if(n->is_AddP()) { 44.171 + alloc_worklist.append(n); 44.172 + } else if(n->is_AddP()) { 44.173 // Collect address nodes. Use them during stage 3 below 44.174 // to build initial connection graph field edges. 44.175 addp_worklist.append(n); 44.176 @@ -1563,6 +1614,10 @@ 44.177 // Collect all MergeMem nodes to add memory slices for 44.178 // scalar replaceable objects in split_unique_types(). 44.179 _mergemem_worklist.append(n->as_MergeMem()); 44.180 + } else if (OptimizePtrCompare && n->is_Cmp() && 44.181 + (n->Opcode() == Op_CmpP || n->Opcode() == Op_CmpN)) { 44.182 + // Compare pointers nodes 44.183 + ptr_cmp_worklist.append(n); 44.184 } 44.185 for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { 44.186 Node* m = n->fast_out(i); // Get user 44.187 @@ -1570,7 +1625,7 @@ 44.188 } 44.189 } 44.190 44.191 - if (!has_allocations) { 44.192 + if (alloc_worklist.length() == 0) { 44.193 _collecting = false; 44.194 return false; // Nothing to do. 44.195 } 44.196 @@ -1588,7 +1643,7 @@ 44.197 for( uint next = 0; next < addp_length; ++next ) { 44.198 Node* n = addp_worklist.at(next); 44.199 Node* base = get_addp_base(n); 44.200 - if (base->is_Proj()) 44.201 + if (base->is_Proj() && base->in(0)->is_Call()) 44.202 base = base->in(0); 44.203 PointsToNode::NodeType nt = ptnode_adr(base->_idx)->node_type(); 44.204 if (nt == PointsToNode::JavaObject) { 44.205 @@ -1653,39 +1708,7 @@ 44.206 } 44.207 #undef CG_BUILD_ITER_LIMIT 44.208 44.209 - Arena* arena = Thread::current()->resource_area(); 44.210 - VectorSet visited(arena); 44.211 - 44.212 - // 5. Find fields initializing values for not escaped allocations 44.213 - uint alloc_length = alloc_worklist.length(); 44.214 - for (uint next = 0; next < alloc_length; ++next) { 44.215 - Node* n = alloc_worklist.at(next); 44.216 - if (ptnode_adr(n->_idx)->escape_state() == PointsToNode::NoEscape) { 44.217 - find_init_values(n, &visited, igvn); 44.218 - } 44.219 - } 44.220 - 44.221 - worklist.clear(); 44.222 - 44.223 - // 6. Remove deferred edges from the graph. 44.224 - uint cg_length = cg_worklist.length(); 44.225 - for (uint next = 0; next < cg_length; ++next) { 44.226 - int ni = cg_worklist.at(next); 44.227 - PointsToNode* ptn = ptnode_adr(ni); 44.228 - PointsToNode::NodeType nt = ptn->node_type(); 44.229 - if (nt == PointsToNode::LocalVar || nt == PointsToNode::Field) { 44.230 - remove_deferred(ni, &worklist, &visited); 44.231 - Node *n = ptn->_node; 44.232 - } 44.233 - } 44.234 - 44.235 - // 7. Adjust escape state of nonescaping objects. 44.236 - for (uint next = 0; next < addp_length; ++next) { 44.237 - Node* n = addp_worklist.at(next); 44.238 - adjust_escape_state(n); 44.239 - } 44.240 - 44.241 - // 8. Propagate escape states. 44.242 + // 5. Propagate escaped states. 44.243 worklist.clear(); 44.244 44.245 // mark all nodes reachable from GlobalEscape nodes 44.246 @@ -1694,20 +1717,72 @@ 44.247 // mark all nodes reachable from ArgEscape nodes 44.248 bool has_non_escaping_obj = propagate_escape_state(&cg_worklist, &worklist, PointsToNode::ArgEscape); 44.249 44.250 + Arena* arena = Thread::current()->resource_area(); 44.251 + VectorSet visited(arena); 44.252 + 44.253 + // 6. Find fields initializing values for not escaped allocations 44.254 + uint alloc_length = alloc_worklist.length(); 44.255 + for (uint next = 0; next < alloc_length; ++next) { 44.256 + Node* n = alloc_worklist.at(next); 44.257 + if (ptnode_adr(n->_idx)->escape_state() == PointsToNode::NoEscape) { 44.258 + has_non_escaping_obj = true; 44.259 + if (n->is_Allocate()) { 44.260 + find_init_values(n, &visited, igvn); 44.261 + } 44.262 + } 44.263 + } 44.264 + 44.265 + uint cg_length = cg_worklist.length(); 44.266 + 44.267 + // Skip the rest of code if all objects escaped. 44.268 + if (!has_non_escaping_obj) { 44.269 + cg_length = 0; 44.270 + addp_length = 0; 44.271 + } 44.272 + 44.273 + for (uint next = 0; next < cg_length; ++next) { 44.274 + int ni = cg_worklist.at(next); 44.275 + PointsToNode* ptn = ptnode_adr(ni); 44.276 + PointsToNode::NodeType nt = ptn->node_type(); 44.277 + if (nt == PointsToNode::LocalVar || nt == PointsToNode::Field) { 44.278 + if (ptn->edge_count() == 0) { 44.279 + // No values were found. Assume the value was set 44.280 + // outside this method - add edge to phantom object. 44.281 + add_pointsto_edge(ni, _phantom_object); 44.282 + } 44.283 + } 44.284 + } 44.285 + 44.286 + // 7. Remove deferred edges from the graph. 44.287 + for (uint next = 0; next < cg_length; ++next) { 44.288 + int ni = cg_worklist.at(next); 44.289 + PointsToNode* ptn = ptnode_adr(ni); 44.290 + PointsToNode::NodeType nt = ptn->node_type(); 44.291 + if (nt == PointsToNode::LocalVar || nt == PointsToNode::Field) { 44.292 + remove_deferred(ni, &worklist, &visited); 44.293 + } 44.294 + } 44.295 + 44.296 + // 8. Adjust escape state of nonescaping objects. 44.297 + for (uint next = 0; next < addp_length; ++next) { 44.298 + Node* n = addp_worklist.at(next); 44.299 + adjust_escape_state(n); 44.300 + } 44.301 + 44.302 // push all NoEscape nodes on the worklist 44.303 + worklist.clear(); 44.304 for( uint next = 0; next < cg_length; ++next ) { 44.305 int nk = cg_worklist.at(next); 44.306 - if (ptnode_adr(nk)->escape_state() == PointsToNode::NoEscape) 44.307 + if (ptnode_adr(nk)->escape_state() == PointsToNode::NoEscape && 44.308 + !is_null_ptr(nk)) 44.309 worklist.push(nk); 44.310 } 44.311 + 44.312 alloc_worklist.clear(); 44.313 - // mark all nodes reachable from NoEscape nodes 44.314 + // Propagate scalar_replaceable value. 44.315 while(worklist.length() > 0) { 44.316 uint nk = worklist.pop(); 44.317 PointsToNode* ptn = ptnode_adr(nk); 44.318 - if (ptn->node_type() == PointsToNode::JavaObject && 44.319 - !(nk == _noop_null || nk == _oop_null)) 44.320 - has_non_escaping_obj = true; // Non Escape 44.321 Node* n = ptn->_node; 44.322 bool scalar_replaceable = ptn->scalar_replaceable(); 44.323 if (n->is_Allocate() && scalar_replaceable) { 44.324 @@ -1719,6 +1794,8 @@ 44.325 uint e_cnt = ptn->edge_count(); 44.326 for (uint ei = 0; ei < e_cnt; ei++) { 44.327 uint npi = ptn->edge_target(ei); 44.328 + if (is_null_ptr(npi)) 44.329 + continue; 44.330 PointsToNode *np = ptnode_adr(npi); 44.331 if (np->escape_state() < PointsToNode::NoEscape) { 44.332 set_escape_state(npi, PointsToNode::NoEscape); 44.333 @@ -1727,7 +1804,6 @@ 44.334 } 44.335 worklist.push(npi); 44.336 } else if (np->scalar_replaceable() && !scalar_replaceable) { 44.337 - // Propagate scalar_replaceable value. 44.338 np->set_scalar_replaceable(false); 44.339 worklist.push(npi); 44.340 } 44.341 @@ -1737,9 +1813,11 @@ 44.342 _collecting = false; 44.343 assert(C->unique() == nodes_size(), "there should be no new ideal nodes during ConnectionGraph build"); 44.344 44.345 - assert(ptnode_adr(_oop_null)->escape_state() == PointsToNode::NoEscape, "sanity"); 44.346 + assert(ptnode_adr(_oop_null)->escape_state() == PointsToNode::NoEscape && 44.347 + ptnode_adr(_oop_null)->edge_count() == 0, "sanity"); 44.348 if (UseCompressedOops) { 44.349 - assert(ptnode_adr(_noop_null)->escape_state() == PointsToNode::NoEscape, "sanity"); 44.350 + assert(ptnode_adr(_noop_null)->escape_state() == PointsToNode::NoEscape && 44.351 + ptnode_adr(_noop_null)->edge_count() == 0, "sanity"); 44.352 } 44.353 44.354 if (EliminateLocks && has_non_escaping_obj) { 44.355 @@ -1749,18 +1827,53 @@ 44.356 Node *n = C->macro_node(i); 44.357 if (n->is_AbstractLock()) { // Lock and Unlock nodes 44.358 AbstractLockNode* alock = n->as_AbstractLock(); 44.359 - if (!alock->is_eliminated()) { 44.360 + if (!alock->is_eliminated() || alock->is_coarsened()) { 44.361 PointsToNode::EscapeState es = escape_state(alock->obj_node()); 44.362 assert(es != PointsToNode::UnknownEscape, "should know"); 44.363 if (es != PointsToNode::UnknownEscape && es != PointsToNode::GlobalEscape) { 44.364 - // Mark it eliminated 44.365 - alock->set_eliminated(); 44.366 + if (!alock->is_eliminated()) { 44.367 + // Mark it eliminated to update any counters 44.368 + alock->set_eliminated(); 44.369 + } else { 44.370 + // The lock could be marked eliminated by lock coarsening 44.371 + // code during first IGVN before EA. Clear coarsened flag 44.372 + // to eliminate all associated locks/unlocks and relock 44.373 + // during deoptimization. 44.374 + alock->clear_coarsened(); 44.375 + } 44.376 } 44.377 } 44.378 } 44.379 } 44.380 } 44.381 44.382 + if (OptimizePtrCompare && has_non_escaping_obj) { 44.383 + // Add ConI(#CC_GT) and ConI(#CC_EQ). 44.384 + _pcmp_neq = igvn->makecon(TypeInt::CC_GT); 44.385 + _pcmp_eq = igvn->makecon(TypeInt::CC_EQ); 44.386 + // Optimize objects compare. 44.387 + while (ptr_cmp_worklist.length() != 0) { 44.388 + Node *n = ptr_cmp_worklist.pop(); 44.389 + Node *res = optimize_ptr_compare(n); 44.390 + if (res != NULL) { 44.391 +#ifndef PRODUCT 44.392 + if (PrintOptimizePtrCompare) { 44.393 + tty->print_cr("++++ Replaced: %d %s(%d,%d) --> %s", n->_idx, (n->Opcode() == Op_CmpP ? "CmpP" : "CmpN"), n->in(1)->_idx, n->in(2)->_idx, (res == _pcmp_eq ? "EQ" : "NotEQ")); 44.394 + if (Verbose) { 44.395 + n->dump(1); 44.396 + } 44.397 + } 44.398 +#endif 44.399 + _igvn->replace_node(n, res); 44.400 + } 44.401 + } 44.402 + // cleanup 44.403 + if (_pcmp_neq->outcnt() == 0) 44.404 + igvn->hash_delete(_pcmp_neq); 44.405 + if (_pcmp_eq->outcnt() == 0) 44.406 + igvn->hash_delete(_pcmp_eq); 44.407 + } 44.408 + 44.409 #ifndef PRODUCT 44.410 if (PrintEscapeAnalysis) { 44.411 dump(); // Dump ConnectionGraph 44.412 @@ -1821,15 +1934,30 @@ 44.413 // Connection Graph does not record a default initialization by NULL 44.414 // captured by Initialize node. 44.415 // 44.416 + uint null_idx = UseCompressedOops ? _noop_null : _oop_null; 44.417 uint ae_cnt = pta->edge_count(); 44.418 + bool visited_bottom_offset = false; 44.419 for (uint ei = 0; ei < ae_cnt; ei++) { 44.420 uint nidx = pta->edge_target(ei); // Field (AddP) 44.421 PointsToNode* ptn = ptnode_adr(nidx); 44.422 assert(ptn->_node->is_AddP(), "Should be AddP nodes only"); 44.423 int offset = ptn->offset(); 44.424 - if (offset != Type::OffsetBot && 44.425 - offset != oopDesc::klass_offset_in_bytes() && 44.426 - !visited->test_set(offset)) { 44.427 + if (offset == Type::OffsetBot) { 44.428 + if (!visited_bottom_offset) { 44.429 + visited_bottom_offset = true; 44.430 + // Check only oop fields. 44.431 + const Type* adr_type = ptn->_node->as_AddP()->bottom_type(); 44.432 + if (!adr_type->isa_aryptr() || 44.433 + (adr_type->isa_aryptr()->klass() == NULL) || 44.434 + adr_type->isa_aryptr()->klass()->is_obj_array_klass()) { 44.435 + // OffsetBot is used to reference array's element, 44.436 + // always add reference to NULL since we don't 44.437 + // known which element is referenced. 44.438 + add_edge_from_fields(alloc->_idx, null_idx, offset); 44.439 + } 44.440 + } 44.441 + } else if (offset != oopDesc::klass_offset_in_bytes() && 44.442 + !visited->test_set(offset)) { 44.443 44.444 // Check only oop fields. 44.445 const Type* adr_type = ptn->_node->as_AddP()->bottom_type(); 44.446 @@ -1904,7 +2032,6 @@ 44.447 } 44.448 if (value == NULL || value != ptnode_adr(value->_idx)->_node) { 44.449 // A field's initializing value was not recorded. Add NULL. 44.450 - uint null_idx = UseCompressedOops ? _noop_null : _oop_null; 44.451 add_edge_from_fields(alloc->_idx, null_idx, offset); 44.452 } 44.453 } 44.454 @@ -1990,13 +2117,21 @@ 44.455 } 44.456 // mark all reachable nodes 44.457 while (worklist->length() > 0) { 44.458 - PointsToNode* ptn = ptnode_adr(worklist->pop()); 44.459 - if (ptn->node_type() == PointsToNode::JavaObject) { 44.460 + int pt = worklist->pop(); 44.461 + PointsToNode* ptn = ptnode_adr(pt); 44.462 + if (ptn->node_type() == PointsToNode::JavaObject && 44.463 + !is_null_ptr(pt)) { 44.464 has_java_obj = true; 44.465 + if (esc_state > PointsToNode::NoEscape) { 44.466 + // fields values are unknown if object escapes 44.467 + add_edge_from_fields(pt, _phantom_object, Type::OffsetBot); 44.468 + } 44.469 } 44.470 uint e_cnt = ptn->edge_count(); 44.471 for (uint ei = 0; ei < e_cnt; ei++) { 44.472 uint npi = ptn->edge_target(ei); 44.473 + if (is_null_ptr(npi)) 44.474 + continue; 44.475 PointsToNode *np = ptnode_adr(npi); 44.476 if (np->escape_state() < esc_state) { 44.477 set_escape_state(npi, esc_state); 44.478 @@ -2008,8 +2143,100 @@ 44.479 return has_java_obj && (esc_state < PointsToNode::GlobalEscape); 44.480 } 44.481 44.482 +// Optimize objects compare. 44.483 +Node* ConnectionGraph::optimize_ptr_compare(Node* n) { 44.484 + assert(OptimizePtrCompare, "sanity"); 44.485 + // Clone returned Set since PointsTo() returns pointer 44.486 + // to the same structure ConnectionGraph.pt_ptset. 44.487 + VectorSet ptset1 = *PointsTo(n->in(1)); 44.488 + VectorSet ptset2 = *PointsTo(n->in(2)); 44.489 + 44.490 + // Check simple cases first. 44.491 + if (ptset1.Size() == 1) { 44.492 + uint pt1 = ptset1.getelem(); 44.493 + PointsToNode* ptn1 = ptnode_adr(pt1); 44.494 + if (ptn1->escape_state() == PointsToNode::NoEscape) { 44.495 + if (ptset2.Size() == 1 && ptset2.getelem() == pt1) { 44.496 + // Comparing the same not escaping object. 44.497 + return _pcmp_eq; 44.498 + } 44.499 + Node* obj = ptn1->_node; 44.500 + // Comparing not escaping allocation. 44.501 + if ((obj->is_Allocate() || obj->is_CallStaticJava()) && 44.502 + !ptset2.test(pt1)) { 44.503 + return _pcmp_neq; // This includes nullness check. 44.504 + } 44.505 + } 44.506 + } else if (ptset2.Size() == 1) { 44.507 + uint pt2 = ptset2.getelem(); 44.508 + PointsToNode* ptn2 = ptnode_adr(pt2); 44.509 + if (ptn2->escape_state() == PointsToNode::NoEscape) { 44.510 + Node* obj = ptn2->_node; 44.511 + // Comparing not escaping allocation. 44.512 + if ((obj->is_Allocate() || obj->is_CallStaticJava()) && 44.513 + !ptset1.test(pt2)) { 44.514 + return _pcmp_neq; // This includes nullness check. 44.515 + } 44.516 + } 44.517 + } 44.518 + 44.519 + if (!ptset1.disjoint(ptset2)) { 44.520 + return NULL; // Sets are not disjoint 44.521 + } 44.522 + 44.523 + // Sets are disjoint. 44.524 + bool set1_has_unknown_ptr = ptset1.test(_phantom_object) != 0; 44.525 + bool set2_has_unknown_ptr = ptset2.test(_phantom_object) != 0; 44.526 + bool set1_has_null_ptr = (ptset1.test(_oop_null) | ptset1.test(_noop_null)) != 0; 44.527 + bool set2_has_null_ptr = (ptset2.test(_oop_null) | ptset2.test(_noop_null)) != 0; 44.528 + 44.529 + if (set1_has_unknown_ptr && set2_has_null_ptr || 44.530 + set2_has_unknown_ptr && set1_has_null_ptr) { 44.531 + // Check nullness of unknown object. 44.532 + return NULL; 44.533 + } 44.534 + 44.535 + // Disjointness by itself is not sufficient since 44.536 + // alias analysis is not complete for escaped objects. 44.537 + // Disjoint sets are definitely unrelated only when 44.538 + // at least one set has only not escaping objects. 44.539 + if (!set1_has_unknown_ptr && !set1_has_null_ptr) { 44.540 + bool has_only_non_escaping_alloc = true; 44.541 + for (VectorSetI i(&ptset1); i.test(); ++i) { 44.542 + uint pt = i.elem; 44.543 + PointsToNode* ptn = ptnode_adr(pt); 44.544 + Node* obj = ptn->_node; 44.545 + if (ptn->escape_state() != PointsToNode::NoEscape || 44.546 + !(obj->is_Allocate() || obj->is_CallStaticJava())) { 44.547 + has_only_non_escaping_alloc = false; 44.548 + break; 44.549 + } 44.550 + } 44.551 + if (has_only_non_escaping_alloc) { 44.552 + return _pcmp_neq; 44.553 + } 44.554 + } 44.555 + if (!set2_has_unknown_ptr && !set2_has_null_ptr) { 44.556 + bool has_only_non_escaping_alloc = true; 44.557 + for (VectorSetI i(&ptset2); i.test(); ++i) { 44.558 + uint pt = i.elem; 44.559 + PointsToNode* ptn = ptnode_adr(pt); 44.560 + Node* obj = ptn->_node; 44.561 + if (ptn->escape_state() != PointsToNode::NoEscape || 44.562 + !(obj->is_Allocate() || obj->is_CallStaticJava())) { 44.563 + has_only_non_escaping_alloc = false; 44.564 + break; 44.565 + } 44.566 + } 44.567 + if (has_only_non_escaping_alloc) { 44.568 + return _pcmp_neq; 44.569 + } 44.570 + } 44.571 + return NULL; 44.572 +} 44.573 + 44.574 void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *phase) { 44.575 - 44.576 + bool is_arraycopy = false; 44.577 switch (call->Opcode()) { 44.578 #ifdef ASSERT 44.579 case Op_Allocate: 44.580 @@ -2019,25 +2246,44 @@ 44.581 assert(false, "should be done already"); 44.582 break; 44.583 #endif 44.584 + case Op_CallLeafNoFP: 44.585 + is_arraycopy = (call->as_CallLeaf()->_name != NULL && 44.586 + strstr(call->as_CallLeaf()->_name, "arraycopy") != 0); 44.587 + // fall through 44.588 case Op_CallLeaf: 44.589 - case Op_CallLeafNoFP: 44.590 { 44.591 // Stub calls, objects do not escape but they are not scale replaceable. 44.592 // Adjust escape state for outgoing arguments. 44.593 const TypeTuple * d = call->tf()->domain(); 44.594 + bool src_has_oops = false; 44.595 for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { 44.596 const Type* at = d->field_at(i); 44.597 Node *arg = call->in(i)->uncast(); 44.598 const Type *aat = phase->type(arg); 44.599 + PointsToNode::EscapeState arg_esc = ptnode_adr(arg->_idx)->escape_state(); 44.600 if (!arg->is_top() && at->isa_ptr() && aat->isa_ptr() && 44.601 - ptnode_adr(arg->_idx)->escape_state() < PointsToNode::ArgEscape) { 44.602 + (is_arraycopy || arg_esc < PointsToNode::ArgEscape)) { 44.603 44.604 assert(aat == Type::TOP || aat == TypePtr::NULL_PTR || 44.605 aat->isa_ptr() != NULL, "expecting an Ptr"); 44.606 + bool arg_has_oops = aat->isa_oopptr() && 44.607 + (aat->isa_oopptr()->klass() == NULL || aat->isa_instptr() || 44.608 + (aat->isa_aryptr() && aat->isa_aryptr()->klass()->is_obj_array_klass())); 44.609 + if (i == TypeFunc::Parms) { 44.610 + src_has_oops = arg_has_oops; 44.611 + } 44.612 + // 44.613 + // src or dst could be j.l.Object when other is basic type array: 44.614 + // 44.615 + // arraycopy(char[],0,Object*,0,size); 44.616 + // arraycopy(Object*,0,char[],0,size); 44.617 + // 44.618 + // Don't add edges from dst's fields in such cases. 44.619 + // 44.620 + bool arg_is_arraycopy_dest = src_has_oops && is_arraycopy && 44.621 + arg_has_oops && (i > TypeFunc::Parms); 44.622 #ifdef ASSERT 44.623 - if (!(call->Opcode() == Op_CallLeafNoFP && 44.624 - call->as_CallLeaf()->_name != NULL && 44.625 - (strstr(call->as_CallLeaf()->_name, "arraycopy") != 0) || 44.626 + if (!(is_arraycopy || 44.627 call->as_CallLeaf()->_name != NULL && 44.628 (strcmp(call->as_CallLeaf()->_name, "g1_wb_pre") == 0 || 44.629 strcmp(call->as_CallLeaf()->_name, "g1_wb_post") == 0 )) 44.630 @@ -2046,20 +2292,72 @@ 44.631 assert(false, "EA: unexpected CallLeaf"); 44.632 } 44.633 #endif 44.634 + // Always process arraycopy's destination object since 44.635 + // we need to add all possible edges to references in 44.636 + // source object. 44.637 + if (arg_esc >= PointsToNode::ArgEscape && 44.638 + !arg_is_arraycopy_dest) { 44.639 + continue; 44.640 + } 44.641 set_escape_state(arg->_idx, PointsToNode::ArgEscape); 44.642 + Node* arg_base = arg; 44.643 if (arg->is_AddP()) { 44.644 // 44.645 // The inline_native_clone() case when the arraycopy stub is called 44.646 // after the allocation before Initialize and CheckCastPP nodes. 44.647 + // Or normal arraycopy for object arrays case. 44.648 // 44.649 // Set AddP's base (Allocate) as not scalar replaceable since 44.650 // pointer to the base (with offset) is passed as argument. 44.651 // 44.652 - arg = get_addp_base(arg); 44.653 + arg_base = get_addp_base(arg); 44.654 } 44.655 - for( VectorSetI j(PointsTo(arg)); j.test(); ++j ) { 44.656 - uint pt = j.elem; 44.657 - set_escape_state(pt, PointsToNode::ArgEscape); 44.658 + VectorSet argset = *PointsTo(arg_base); // Clone set 44.659 + for( VectorSetI j(&argset); j.test(); ++j ) { 44.660 + uint pd = j.elem; // Destination object 44.661 + set_escape_state(pd, PointsToNode::ArgEscape); 44.662 + 44.663 + if (arg_is_arraycopy_dest) { 44.664 + PointsToNode* ptd = ptnode_adr(pd); 44.665 + // Conservatively reference an unknown object since 44.666 + // not all source's fields/elements may be known. 44.667 + add_edge_from_fields(pd, _phantom_object, Type::OffsetBot); 44.668 + 44.669 + Node *src = call->in(TypeFunc::Parms)->uncast(); 44.670 + Node* src_base = src; 44.671 + if (src->is_AddP()) { 44.672 + src_base = get_addp_base(src); 44.673 + } 44.674 + // Create edges from destination's fields to 44.675 + // everything known source's fields could point to. 44.676 + for( VectorSetI s(PointsTo(src_base)); s.test(); ++s ) { 44.677 + uint ps = s.elem; 44.678 + bool has_bottom_offset = false; 44.679 + for (uint fd = 0; fd < ptd->edge_count(); fd++) { 44.680 + assert(ptd->edge_type(fd) == PointsToNode::FieldEdge, "expecting a field edge"); 44.681 + int fdi = ptd->edge_target(fd); 44.682 + PointsToNode* pfd = ptnode_adr(fdi); 44.683 + int offset = pfd->offset(); 44.684 + if (offset == Type::OffsetBot) 44.685 + has_bottom_offset = true; 44.686 + assert(offset != -1, "offset should be set"); 44.687 + add_deferred_edge_to_fields(fdi, ps, offset); 44.688 + } 44.689 + // Destination object may not have access (no field edge) 44.690 + // to fields which are accessed in source object. 44.691 + // As result no edges will be created to those source's 44.692 + // fields and escape state of destination object will 44.693 + // not be propagated to those fields. 44.694 + // 44.695 + // Mark source object as global escape except in 44.696 + // the case with Type::OffsetBot field (which is 44.697 + // common case for array elements access) when 44.698 + // edges are created to all source's fields. 44.699 + if (!has_bottom_offset) { 44.700 + set_escape_state(ps, PointsToNode::GlobalEscape); 44.701 + } 44.702 + } 44.703 + } 44.704 } 44.705 } 44.706 } 44.707 @@ -2102,14 +2400,16 @@ 44.708 for( VectorSetI j(PointsTo(arg)); j.test(); ++j ) { 44.709 uint pt = j.elem; 44.710 if (global_escapes) { 44.711 - //The argument global escapes, mark everything it could point to 44.712 + // The argument global escapes, mark everything it could point to 44.713 set_escape_state(pt, PointsToNode::GlobalEscape); 44.714 + add_edge_from_fields(pt, _phantom_object, Type::OffsetBot); 44.715 } else { 44.716 + set_escape_state(pt, PointsToNode::ArgEscape); 44.717 if (fields_escapes) { 44.718 - // The argument itself doesn't escape, but any fields might 44.719 - add_edge_from_fields(pt, _phantom_object, Type::OffsetBot); 44.720 + // The argument itself doesn't escape, but any fields might. 44.721 + // Use OffsetTop to indicate such case. 44.722 + add_edge_from_fields(pt, _phantom_object, Type::OffsetTop); 44.723 } 44.724 - set_escape_state(pt, PointsToNode::ArgEscape); 44.725 } 44.726 } 44.727 } 44.728 @@ -2135,6 +2435,7 @@ 44.729 for( VectorSetI j(PointsTo(arg)); j.test(); ++j ) { 44.730 uint pt = j.elem; 44.731 set_escape_state(pt, PointsToNode::GlobalEscape); 44.732 + add_edge_from_fields(pt, _phantom_object, Type::OffsetBot); 44.733 } 44.734 } 44.735 } 44.736 @@ -2235,15 +2536,16 @@ 44.737 // it's fields will be marked as NoEscape at least. 44.738 set_escape_state(call_idx, PointsToNode::NoEscape); 44.739 ptnode_adr(call_idx)->set_scalar_replaceable(false); 44.740 + // Fields values are unknown 44.741 + add_edge_from_fields(call_idx, _phantom_object, Type::OffsetBot); 44.742 add_pointsto_edge(resproj_idx, call_idx); 44.743 copy_dependencies = true; 44.744 - } else if (call_analyzer->is_return_local()) { 44.745 + } else { 44.746 // determine whether any arguments are returned 44.747 set_escape_state(call_idx, PointsToNode::ArgEscape); 44.748 bool ret_arg = false; 44.749 for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { 44.750 const Type* at = d->field_at(i); 44.751 - 44.752 if (at->isa_oopptr() != NULL) { 44.753 Node *arg = call->in(i)->uncast(); 44.754 44.755 @@ -2259,17 +2561,14 @@ 44.756 } 44.757 } 44.758 } 44.759 - if (done && !ret_arg) { 44.760 - // Returns unknown object. 44.761 - set_escape_state(call_idx, PointsToNode::GlobalEscape); 44.762 - add_pointsto_edge(resproj_idx, _phantom_object); 44.763 - } 44.764 if (done) { 44.765 copy_dependencies = true; 44.766 + // is_return_local() is true when only arguments are returned. 44.767 + if (!ret_arg || !call_analyzer->is_return_local()) { 44.768 + // Returns unknown object. 44.769 + add_pointsto_edge(resproj_idx, _phantom_object); 44.770 + } 44.771 } 44.772 - } else { 44.773 - set_escape_state(call_idx, PointsToNode::GlobalEscape); 44.774 - add_pointsto_edge(resproj_idx, _phantom_object); 44.775 } 44.776 if (copy_dependencies) 44.777 call_analyzer->copy_dependencies(_compile->dependencies()); 44.778 @@ -2431,6 +2730,11 @@ 44.779 add_node(n, PointsToNode::JavaObject, PointsToNode::GlobalEscape, false); 44.780 break; 44.781 } 44.782 + case Op_PartialSubtypeCheck: 44.783 + { // Produces Null or notNull and is used in CmpP. 44.784 + add_node(n, PointsToNode::JavaObject, PointsToNode::ArgEscape, true); 44.785 + break; 44.786 + } 44.787 case Op_Phi: 44.788 { 44.789 const Type *t = n->as_Phi()->type(); 44.790 @@ -2589,10 +2893,11 @@ 44.791 case Op_AddP: 44.792 { 44.793 Node *base = get_addp_base(n); 44.794 + int offset = address_offset(n, phase); 44.795 // Create a field edge to this node from everything base could point to. 44.796 for( VectorSetI i(PointsTo(base)); i.test(); ++i ) { 44.797 uint pt = i.elem; 44.798 - add_field_edge(pt, n_idx, address_offset(n, phase)); 44.799 + add_field_edge(pt, n_idx, offset); 44.800 } 44.801 break; 44.802 } 44.803 @@ -2659,6 +2964,10 @@ 44.804 int offset = address_offset(adr, phase); 44.805 for( VectorSetI i(PointsTo(adr_base)); i.test(); ++i ) { 44.806 uint pt = i.elem; 44.807 + if (adr->is_AddP()) { 44.808 + // Add field edge if it is missing. 44.809 + add_field_edge(pt, adr->_idx, offset); 44.810 + } 44.811 add_deferred_edge_to_fields(n_idx, pt, offset); 44.812 } 44.813 break; 44.814 @@ -2668,6 +2977,11 @@ 44.815 assert(false, "Op_Parm"); 44.816 break; 44.817 } 44.818 + case Op_PartialSubtypeCheck: 44.819 + { 44.820 + assert(false, "Op_PartialSubtypeCheck"); 44.821 + break; 44.822 + } 44.823 case Op_Phi: 44.824 { 44.825 #ifdef ASSERT 44.826 @@ -2745,11 +3059,14 @@ 44.827 assert(adr->is_AddP(), "expecting an AddP"); 44.828 Node *adr_base = get_addp_base(adr); 44.829 Node *val = n->in(MemNode::ValueIn)->uncast(); 44.830 + int offset = address_offset(adr, phase); 44.831 // For everything "adr_base" could point to, create a deferred edge 44.832 // to "val" from each field with the same offset. 44.833 for( VectorSetI i(PointsTo(adr_base)); i.test(); ++i ) { 44.834 uint pt = i.elem; 44.835 - add_edge_from_fields(pt, val->_idx, address_offset(adr, phase)); 44.836 + // Add field edge if it is missing. 44.837 + add_field_edge(pt, adr->_idx, offset); 44.838 + add_edge_from_fields(pt, val->_idx, offset); 44.839 } 44.840 break; 44.841 }
45.1 --- a/src/share/vm/opto/escape.hpp Wed Dec 07 07:27:09 2011 -0800 45.2 +++ b/src/share/vm/opto/escape.hpp Thu Dec 08 10:27:33 2011 -0800 45.3 @@ -160,6 +160,7 @@ 45.4 Node* _node; // Ideal node corresponding to this PointsTo node. 45.5 int _offset; // Object fields offsets. 45.6 bool _scalar_replaceable; // Not escaped object could be replaced with scalar 45.7 + bool _has_unknown_ptr; // Has edge to phantom_object 45.8 45.9 public: 45.10 PointsToNode(): 45.11 @@ -168,6 +169,7 @@ 45.12 _edges(NULL), 45.13 _node(NULL), 45.14 _offset(-1), 45.15 + _has_unknown_ptr(false), 45.16 _scalar_replaceable(true) {} 45.17 45.18 45.19 @@ -175,6 +177,7 @@ 45.20 NodeType node_type() const { return _type;} 45.21 int offset() { return _offset;} 45.22 bool scalar_replaceable() { return _scalar_replaceable;} 45.23 + bool has_unknown_ptr() { return _has_unknown_ptr;} 45.24 45.25 void set_offset(int offs) { _offset = offs;} 45.26 void set_escape_state(EscapeState state) { _escape = state; } 45.27 @@ -183,6 +186,7 @@ 45.28 _type = ntype; 45.29 } 45.30 void set_scalar_replaceable(bool v) { _scalar_replaceable = v; } 45.31 + void set_has_unknown_ptr() { _has_unknown_ptr = true; } 45.32 45.33 // count of outgoing edges 45.34 uint edge_count() const { return (_edges == NULL) ? 0 : _edges->length(); } 45.35 @@ -236,6 +240,8 @@ 45.36 // are assumed to point to. 45.37 uint _oop_null; // ConP(#NULL)->_idx 45.38 uint _noop_null; // ConN(#NULL)->_idx 45.39 + Node* _pcmp_neq; // ConI(#CC_GT) 45.40 + Node* _pcmp_eq; // ConI(#CC_EQ) 45.41 45.42 Compile * _compile; // Compile object for current compilation 45.43 PhaseIterGVN * _igvn; // Value numbering 45.44 @@ -248,6 +254,8 @@ 45.45 } 45.46 uint nodes_size() const { return _nodes.length(); } 45.47 45.48 + bool is_null_ptr(uint idx) const { return (idx == _noop_null || idx == _oop_null); } 45.49 + 45.50 // Add node to ConnectionGraph. 45.51 void add_node(Node *n, PointsToNode::NodeType nt, PointsToNode::EscapeState es, bool done); 45.52 45.53 @@ -331,10 +339,9 @@ 45.54 } 45.55 45.56 // Notify optimizer that a node has been modified 45.57 - // Node: This assumes that escape analysis is run before 45.58 - // PhaseIterGVN creation 45.59 void record_for_optimizer(Node *n) { 45.60 _igvn->_worklist.push(n); 45.61 + _igvn->add_users_to_worklist(n); 45.62 } 45.63 45.64 // Set the escape state of a node 45.65 @@ -351,6 +358,9 @@ 45.66 GrowableArray<uint>* worklist, 45.67 PointsToNode::EscapeState esc_state); 45.68 45.69 + // Optimize objects compare. 45.70 + Node* optimize_ptr_compare(Node* n); 45.71 + 45.72 // Compute the escape information 45.73 bool compute_escape(); 45.74
46.1 --- a/src/share/vm/opto/gcm.cpp Wed Dec 07 07:27:09 2011 -0800 46.2 +++ b/src/share/vm/opto/gcm.cpp Thu Dec 08 10:27:33 2011 -0800 46.3 @@ -95,7 +95,7 @@ 46.4 assert(in0 != NULL, "Only control-dependent"); 46.5 const Node *p = in0->is_block_proj(); 46.6 if (p != NULL && p != n) { // Control from a block projection? 46.7 - assert(!n->pinned() || n->is_MachConstantBase() || n->is_SafePointScalarObject(), "only pinned MachConstantBase or SafePointScalarObject node is expected here"); 46.8 + assert(!n->pinned() || n->is_MachConstantBase(), "only pinned MachConstantBase node is expected here"); 46.9 // Find trailing Region 46.10 Block *pb = _bbs[in0->_idx]; // Block-projection already has basic block 46.11 uint j = 0;
47.1 --- a/src/share/vm/opto/idealGraphPrinter.cpp Wed Dec 07 07:27:09 2011 -0800 47.2 +++ b/src/share/vm/opto/idealGraphPrinter.cpp Thu Dec 08 10:27:33 2011 -0800 47.3 @@ -447,6 +447,9 @@ 47.4 if (flags & Node::Flag_may_be_short_branch) { 47.5 print_prop("may_be_short_branch", "true"); 47.6 } 47.7 + if (flags & Node::Flag_has_call) { 47.8 + print_prop("has_call", "true"); 47.9 + } 47.10 47.11 if (C->matcher() != NULL) { 47.12 if (C->matcher()->is_shared(node)) {
48.1 --- a/src/share/vm/opto/lcm.cpp Wed Dec 07 07:27:09 2011 -0800 48.2 +++ b/src/share/vm/opto/lcm.cpp Thu Dec 08 10:27:33 2011 -0800 48.3 @@ -548,6 +548,22 @@ 48.4 set_next_call(call, next_call, bbs); 48.5 } 48.6 48.7 +//------------------------------add_call_kills------------------------------------- 48.8 +void Block::add_call_kills(MachProjNode *proj, RegMask& regs, const char* save_policy, bool exclude_soe) { 48.9 + // Fill in the kill mask for the call 48.10 + for( OptoReg::Name r = OptoReg::Name(0); r < _last_Mach_Reg; r=OptoReg::add(r,1) ) { 48.11 + if( !regs.Member(r) ) { // Not already defined by the call 48.12 + // Save-on-call register? 48.13 + if ((save_policy[r] == 'C') || 48.14 + (save_policy[r] == 'A') || 48.15 + ((save_policy[r] == 'E') && exclude_soe)) { 48.16 + proj->_rout.Insert(r); 48.17 + } 48.18 + } 48.19 + } 48.20 +} 48.21 + 48.22 + 48.23 //------------------------------sched_call------------------------------------- 48.24 uint Block::sched_call( Matcher &matcher, Block_Array &bbs, uint node_cnt, Node_List &worklist, int *ready_cnt, MachCallNode *mcall, VectorSet &next_call ) { 48.25 RegMask regs; 48.26 @@ -631,17 +647,7 @@ 48.27 proj->_rout.OR(Matcher::method_handle_invoke_SP_save_mask()); 48.28 } 48.29 48.30 - // Fill in the kill mask for the call 48.31 - for( OptoReg::Name r = OptoReg::Name(0); r < _last_Mach_Reg; r=OptoReg::add(r,1) ) { 48.32 - if( !regs.Member(r) ) { // Not already defined by the call 48.33 - // Save-on-call register? 48.34 - if ((save_policy[r] == 'C') || 48.35 - (save_policy[r] == 'A') || 48.36 - ((save_policy[r] == 'E') && exclude_soe)) { 48.37 - proj->_rout.Insert(r); 48.38 - } 48.39 - } 48.40 - } 48.41 + add_call_kills(proj, regs, save_policy, exclude_soe); 48.42 48.43 return node_cnt; 48.44 } 48.45 @@ -776,6 +782,7 @@ 48.46 } 48.47 #endif 48.48 48.49 + uint max_idx = matcher.C->unique(); 48.50 // Pull from worklist and schedule 48.51 while( worklist.size() ) { // Worklist is not ready 48.52 48.53 @@ -815,11 +822,28 @@ 48.54 phi_cnt = sched_call(matcher, cfg->_bbs, phi_cnt, worklist, ready_cnt, mcall, next_call); 48.55 continue; 48.56 } 48.57 + 48.58 + if (n->is_Mach() && n->as_Mach()->has_call()) { 48.59 + RegMask regs; 48.60 + regs.Insert(matcher.c_frame_pointer()); 48.61 + regs.OR(n->out_RegMask()); 48.62 + 48.63 + MachProjNode *proj = new (matcher.C, 1) MachProjNode( n, 1, RegMask::Empty, MachProjNode::fat_proj ); 48.64 + cfg->_bbs.map(proj->_idx,this); 48.65 + _nodes.insert(phi_cnt++, proj); 48.66 + 48.67 + add_call_kills(proj, regs, matcher._c_reg_save_policy, false); 48.68 + } 48.69 + 48.70 // Children are now all ready 48.71 for (DUIterator_Fast i5max, i5 = n->fast_outs(i5max); i5 < i5max; i5++) { 48.72 Node* m = n->fast_out(i5); // Get user 48.73 if( cfg->_bbs[m->_idx] != this ) continue; 48.74 if( m->is_Phi() ) continue; 48.75 + if (m->_idx > max_idx) { // new node, skip it 48.76 + assert(m->is_MachProj() && n->is_Mach() && n->as_Mach()->has_call(), "unexpected node types"); 48.77 + continue; 48.78 + } 48.79 if( !--ready_cnt[m->_idx] ) 48.80 worklist.push(m); 48.81 }
49.1 --- a/src/share/vm/opto/loopnode.cpp Wed Dec 07 07:27:09 2011 -0800 49.2 +++ b/src/share/vm/opto/loopnode.cpp Thu Dec 08 10:27:33 2011 -0800 49.3 @@ -715,7 +715,6 @@ 49.4 long limit_con = cl->limit()->get_int(); 49.5 julong trip_cnt = cl->trip_count(); 49.6 long final_con = init_con + trip_cnt*stride_con; 49.7 - final_con -= stride_con; 49.8 int final_int = (int)final_con; 49.9 // The final value should be in integer range since the loop 49.10 // is counted and the limit was checked for overflow. 49.11 @@ -1947,7 +1946,7 @@ 49.12 } 49.13 49.14 // Nothing to do, so get out 49.15 - if( !C->has_loops() && !do_split_ifs && !_verify_me && !_verify_only ) { 49.16 + if( !C->has_loops() && !skip_loop_opts && !do_split_ifs && !_verify_me && !_verify_only ) { 49.17 _igvn.optimize(); // Cleanup NeverBranches 49.18 return; 49.19 }
50.1 --- a/src/share/vm/opto/machnode.cpp Wed Dec 07 07:27:09 2011 -0800 50.2 +++ b/src/share/vm/opto/machnode.cpp Thu Dec 08 10:27:33 2011 -0800 50.3 @@ -480,21 +480,20 @@ 50.4 50.5 //============================================================================= 50.6 int MachConstantNode::constant_offset() { 50.7 - int offset = _constant.offset(); 50.8 // Bind the offset lazily. 50.9 - if (offset == -1) { 50.10 + if (_constant.offset() == -1) { 50.11 Compile::ConstantTable& constant_table = Compile::current()->constant_table(); 50.12 - // If called from Compile::scratch_emit_size assume the worst-case 50.13 - // for load offsets: half the constant table size. 50.14 - // NOTE: Don't return or calculate the actual offset (which might 50.15 - // be zero) because that leads to problems with e.g. jumpXtnd on 50.16 - // some architectures (cf. add-optimization in SPARC jumpXtnd). 50.17 - if (Compile::current()->in_scratch_emit_size()) 50.18 - return constant_table.size() / 2; 50.19 - offset = constant_table.table_base_offset() + constant_table.find_offset(_constant); 50.20 - _constant.set_offset(offset); 50.21 + int offset = constant_table.find_offset(_constant); 50.22 + // If called from Compile::scratch_emit_size return the 50.23 + // pre-calculated offset. 50.24 + // NOTE: If the AD file does some table base offset optimizations 50.25 + // later the AD file needs to take care of this fact. 50.26 + if (Compile::current()->in_scratch_emit_size()) { 50.27 + return constant_table.calculate_table_base_offset() + offset; 50.28 + } 50.29 + _constant.set_offset(constant_table.table_base_offset() + offset); 50.30 } 50.31 - return offset; 50.32 + return _constant.offset(); 50.33 } 50.34 50.35
51.1 --- a/src/share/vm/opto/machnode.hpp Wed Dec 07 07:27:09 2011 -0800 51.2 +++ b/src/share/vm/opto/machnode.hpp Thu Dec 08 10:27:33 2011 -0800 51.3 @@ -190,6 +190,9 @@ 51.4 // Avoid back to back some instructions on some CPUs. 51.5 bool avoid_back_to_back() const { return (flags() & Flag_avoid_back_to_back) != 0; } 51.6 51.7 + // instruction implemented with a call 51.8 + bool has_call() const { return (flags() & Flag_has_call) != 0; } 51.9 + 51.10 // First index in _in[] corresponding to operand, or -1 if there is none 51.11 int operand_index(uint operand) const; 51.12
52.1 --- a/src/share/vm/opto/macro.cpp Wed Dec 07 07:27:09 2011 -0800 52.2 +++ b/src/share/vm/opto/macro.cpp Thu Dec 08 10:27:33 2011 -0800 52.3 @@ -81,7 +81,7 @@ 52.4 uint old_unique = C->unique(); 52.5 Node* new_in = old_sosn->clone(jvms_adj, sosn_map); 52.6 if (old_unique != C->unique()) { 52.7 - new_in->set_req(0, newcall->in(0)); // reset control edge 52.8 + new_in->set_req(0, C->root()); // reset control edge 52.9 new_in = transform_later(new_in); // Register new node. 52.10 } 52.11 old_in = new_in; 52.12 @@ -565,7 +565,6 @@ 52.13 if (res == NULL) { 52.14 // All users were eliminated. 52.15 } else if (!res->is_CheckCastPP()) { 52.16 - alloc->_is_scalar_replaceable = false; // don't try again 52.17 NOT_PRODUCT(fail_eliminate = "Allocation does not have unique CheckCastPP";) 52.18 can_eliminate = false; 52.19 } else { 52.20 @@ -719,7 +718,7 @@ 52.21 alloc, 52.22 #endif 52.23 first_ind, nfields); 52.24 - sobj->init_req(0, sfpt->in(TypeFunc::Control)); 52.25 + sobj->init_req(0, C->root()); 52.26 transform_later(sobj); 52.27 52.28 // Scan object's fields adding an input to the safepoint for each field. 52.29 @@ -762,10 +761,10 @@ 52.30 52.31 Node *field_val = value_from_mem(mem, basic_elem_type, field_type, field_addr_type, alloc); 52.32 if (field_val == NULL) { 52.33 - // we weren't able to find a value for this field, 52.34 - // give up on eliminating this allocation 52.35 - alloc->_is_scalar_replaceable = false; // don't try again 52.36 - // remove any extra entries we added to the safepoint 52.37 + // We weren't able to find a value for this field, 52.38 + // give up on eliminating this allocation. 52.39 + 52.40 + // Remove any extra entries we added to the safepoint. 52.41 uint last = sfpt->req() - 1; 52.42 for (int k = 0; k < j; k++) { 52.43 sfpt->del_req(last--); 52.44 @@ -1804,9 +1803,9 @@ 52.45 #ifndef PRODUCT 52.46 if (PrintEliminateLocks) { 52.47 if (alock->is_Lock()) { 52.48 - tty->print_cr("++++ Eliminating: %d Lock", alock->_idx); 52.49 + tty->print_cr("++++ Eliminated: %d Lock", alock->_idx); 52.50 } else { 52.51 - tty->print_cr("++++ Eliminating: %d Unlock", alock->_idx); 52.52 + tty->print_cr("++++ Eliminated: %d Unlock", alock->_idx); 52.53 } 52.54 } 52.55 #endif 52.56 @@ -2165,11 +2164,12 @@ 52.57 _igvn.replace_node(_memproj_fallthrough, mem_phi); 52.58 } 52.59 52.60 -//------------------------------expand_macro_nodes---------------------- 52.61 -// Returns true if a failure occurred. 52.62 -bool PhaseMacroExpand::expand_macro_nodes() { 52.63 +//---------------------------eliminate_macro_nodes---------------------- 52.64 +// Eliminate scalar replaced allocations and associated locks. 52.65 +void PhaseMacroExpand::eliminate_macro_nodes() { 52.66 if (C->macro_count() == 0) 52.67 - return false; 52.68 + return; 52.69 + 52.70 // First, attempt to eliminate locks 52.71 int cnt = C->macro_count(); 52.72 for (int i=0; i < cnt; i++) { 52.73 @@ -2189,14 +2189,6 @@ 52.74 debug_only(int old_macro_count = C->macro_count();); 52.75 if (n->is_AbstractLock()) { 52.76 success = eliminate_locking_node(n->as_AbstractLock()); 52.77 - } else if (n->Opcode() == Op_LoopLimit) { 52.78 - // Remove it from macro list and put on IGVN worklist to optimize. 52.79 - C->remove_macro_node(n); 52.80 - _igvn._worklist.push(n); 52.81 - success = true; 52.82 - } else if (n->Opcode() == Op_Opaque1 || n->Opcode() == Op_Opaque2) { 52.83 - _igvn.replace_node(n, n->in(1)); 52.84 - success = true; 52.85 } 52.86 assert(success == (C->macro_count() < old_macro_count), "elimination reduces macro count"); 52.87 progress = progress || success; 52.88 @@ -2220,18 +2212,50 @@ 52.89 assert(!n->as_AbstractLock()->is_eliminated(), "sanity"); 52.90 break; 52.91 default: 52.92 - assert(false, "unknown node type in macro list"); 52.93 + assert(n->Opcode() == Op_LoopLimit || 52.94 + n->Opcode() == Op_Opaque1 || 52.95 + n->Opcode() == Op_Opaque2, "unknown node type in macro list"); 52.96 } 52.97 assert(success == (C->macro_count() < old_macro_count), "elimination reduces macro count"); 52.98 progress = progress || success; 52.99 } 52.100 } 52.101 +} 52.102 + 52.103 +//------------------------------expand_macro_nodes---------------------- 52.104 +// Returns true if a failure occurred. 52.105 +bool PhaseMacroExpand::expand_macro_nodes() { 52.106 + // Last attempt to eliminate macro nodes. 52.107 + eliminate_macro_nodes(); 52.108 + 52.109 // Make sure expansion will not cause node limit to be exceeded. 52.110 // Worst case is a macro node gets expanded into about 50 nodes. 52.111 // Allow 50% more for optimization. 52.112 if (C->check_node_count(C->macro_count() * 75, "out of nodes before macro expansion" ) ) 52.113 return true; 52.114 52.115 + // Eliminate Opaque and LoopLimit nodes. Do it after all loop optimizations. 52.116 + bool progress = true; 52.117 + while (progress) { 52.118 + progress = false; 52.119 + for (int i = C->macro_count(); i > 0; i--) { 52.120 + Node * n = C->macro_node(i-1); 52.121 + bool success = false; 52.122 + debug_only(int old_macro_count = C->macro_count();); 52.123 + if (n->Opcode() == Op_LoopLimit) { 52.124 + // Remove it from macro list and put on IGVN worklist to optimize. 52.125 + C->remove_macro_node(n); 52.126 + _igvn._worklist.push(n); 52.127 + success = true; 52.128 + } else if (n->Opcode() == Op_Opaque1 || n->Opcode() == Op_Opaque2) { 52.129 + _igvn.replace_node(n, n->in(1)); 52.130 + success = true; 52.131 + } 52.132 + assert(success == (C->macro_count() < old_macro_count), "elimination reduces macro count"); 52.133 + progress = progress || success; 52.134 + } 52.135 + } 52.136 + 52.137 // expand "macro" nodes 52.138 // nodes are removed from the macro list as they are processed 52.139 while (C->macro_count() > 0) { 52.140 @@ -2265,5 +2289,6 @@ 52.141 52.142 _igvn.set_delay_transform(false); 52.143 _igvn.optimize(); 52.144 + if (C->failing()) return true; 52.145 return false; 52.146 }
53.1 --- a/src/share/vm/opto/macro.hpp Wed Dec 07 07:27:09 2011 -0800 53.2 +++ b/src/share/vm/opto/macro.hpp Thu Dec 08 10:27:33 2011 -0800 53.3 @@ -119,6 +119,7 @@ 53.4 PhaseMacroExpand(PhaseIterGVN &igvn) : Phase(Macro_Expand), _igvn(igvn) { 53.5 _igvn.set_delay_transform(true); 53.6 } 53.7 + void eliminate_macro_nodes(); 53.8 bool expand_macro_nodes(); 53.9 53.10 };
54.1 --- a/src/share/vm/opto/matcher.hpp Wed Dec 07 07:27:09 2011 -0800 54.2 +++ b/src/share/vm/opto/matcher.hpp Thu Dec 08 10:27:33 2011 -0800 54.3 @@ -294,7 +294,6 @@ 54.4 RegMask _return_value_mask; 54.5 // Inline Cache Register 54.6 static OptoReg::Name inline_cache_reg(); 54.7 - static const RegMask &inline_cache_reg_mask(); 54.8 static int inline_cache_reg_encode(); 54.9 54.10 // Register for DIVI projection of divmodI 54.11 @@ -324,7 +323,6 @@ 54.12 // and then expanded into the inline_cache_reg and a method_oop register 54.13 54.14 static OptoReg::Name interpreter_method_oop_reg(); 54.15 - static const RegMask &interpreter_method_oop_reg_mask(); 54.16 static int interpreter_method_oop_reg_encode(); 54.17 54.18 static OptoReg::Name compiler_method_oop_reg(); 54.19 @@ -333,7 +331,6 @@ 54.20 54.21 // Interpreter's Frame Pointer Register 54.22 static OptoReg::Name interpreter_frame_pointer_reg(); 54.23 - static const RegMask &interpreter_frame_pointer_reg_mask(); 54.24 54.25 // Java-Native calling convention 54.26 // (what you use when intercalling between Java and C++ code) 54.27 @@ -371,10 +368,6 @@ 54.28 // registers? True for Intel but false for most RISCs 54.29 static const bool clone_shift_expressions; 54.30 54.31 - // Should constant table entries be accessed with loads using 54.32 - // absolute addressing? True for x86 but false for most RISCs. 54.33 - static const bool constant_table_absolute_addressing; 54.34 - 54.35 static bool narrow_oop_use_complex_address(); 54.36 54.37 // Generate implicit null check for narrow oops if it can fold
55.1 --- a/src/share/vm/opto/memnode.cpp Wed Dec 07 07:27:09 2011 -0800 55.2 +++ b/src/share/vm/opto/memnode.cpp Thu Dec 08 10:27:33 2011 -0800 55.3 @@ -265,6 +265,13 @@ 55.4 if( phase->type( mem ) == Type::TOP ) return NodeSentinel; // caller will return NULL 55.5 assert( mem != this, "dead loop in MemNode::Ideal" ); 55.6 55.7 + if (can_reshape && igvn != NULL && igvn->_worklist.member(mem)) { 55.8 + // This memory slice may be dead. 55.9 + // Delay this mem node transformation until the memory is processed. 55.10 + phase->is_IterGVN()->_worklist.push(this); 55.11 + return NodeSentinel; // caller will return NULL 55.12 + } 55.13 + 55.14 Node *address = in(MemNode::Address); 55.15 const Type *t_adr = phase->type( address ); 55.16 if( t_adr == Type::TOP ) return NodeSentinel; // caller will return NULL 55.17 @@ -2661,6 +2668,8 @@ 55.18 // control copies 55.19 Node *StrIntrinsicNode::Ideal(PhaseGVN *phase, bool can_reshape) { 55.20 if (remove_dead_region(phase, can_reshape)) return this; 55.21 + // Don't bother trying to transform a dead node 55.22 + if (in(0) && in(0)->is_top()) return NULL; 55.23 55.24 if (can_reshape) { 55.25 Node* mem = phase->transform(in(MemNode::Memory)); 55.26 @@ -2675,6 +2684,12 @@ 55.27 return NULL; 55.28 } 55.29 55.30 +//------------------------------Value------------------------------------------ 55.31 +const Type *StrIntrinsicNode::Value( PhaseTransform *phase ) const { 55.32 + if (in(0) && phase->type(in(0)) == Type::TOP) return Type::TOP; 55.33 + return bottom_type(); 55.34 +} 55.35 + 55.36 //============================================================================= 55.37 MemBarNode::MemBarNode(Compile* C, int alias_idx, Node* precedent) 55.38 : MultiNode(TypeFunc::Parms + (precedent == NULL? 0: 1)), 55.39 @@ -2715,6 +2730,8 @@ 55.40 // control copies 55.41 Node *MemBarNode::Ideal(PhaseGVN *phase, bool can_reshape) { 55.42 if (remove_dead_region(phase, can_reshape)) return this; 55.43 + // Don't bother trying to transform a dead node 55.44 + if (in(0) && in(0)->is_top()) return NULL; 55.45 55.46 // Eliminate volatile MemBars for scalar replaced objects. 55.47 if (can_reshape && req() == (Precedent+1) &&
56.1 --- a/src/share/vm/opto/memnode.hpp Wed Dec 07 07:27:09 2011 -0800 56.2 +++ b/src/share/vm/opto/memnode.hpp Thu Dec 08 10:27:33 2011 -0800 56.3 @@ -800,6 +800,7 @@ 56.4 virtual uint match_edge(uint idx) const; 56.5 virtual uint ideal_reg() const { return Op_RegI; } 56.6 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 56.7 + virtual const Type *Value(PhaseTransform *phase) const; 56.8 }; 56.9 56.10 //------------------------------StrComp-------------------------------------
57.1 --- a/src/share/vm/opto/node.hpp Wed Dec 07 07:27:09 2011 -0800 57.2 +++ b/src/share/vm/opto/node.hpp Thu Dec 08 10:27:33 2011 -0800 57.3 @@ -641,7 +641,8 @@ 57.4 Flag_is_dead_loop_safe = Flag_is_cisc_alternate << 1, 57.5 Flag_may_be_short_branch = Flag_is_dead_loop_safe << 1, 57.6 Flag_avoid_back_to_back = Flag_may_be_short_branch << 1, 57.7 - _max_flags = (Flag_avoid_back_to_back << 1) - 1 // allow flags combination 57.8 + Flag_has_call = Flag_avoid_back_to_back << 1, 57.9 + _max_flags = (Flag_has_call << 1) - 1 // allow flags combination 57.10 }; 57.11 57.12 private:
58.1 --- a/src/share/vm/runtime/globals.hpp Wed Dec 07 07:27:09 2011 -0800 58.2 +++ b/src/share/vm/runtime/globals.hpp Thu Dec 08 10:27:33 2011 -0800 58.3 @@ -890,7 +890,7 @@ 58.4 diagnostic(bool, TraceNMethodInstalls, false, \ 58.5 "Trace nmethod intallation") \ 58.6 \ 58.7 - diagnostic(intx, ScavengeRootsInCode, 1, \ 58.8 + diagnostic(intx, ScavengeRootsInCode, 2, \ 58.9 "0: do not allow scavengable oops in the code cache; " \ 58.10 "1: allow scavenging from the code cache; " \ 58.11 "2: emit as many constants as the compiler can see") \
59.1 --- a/src/share/vm/runtime/simpleThresholdPolicy.cpp Wed Dec 07 07:27:09 2011 -0800 59.2 +++ b/src/share/vm/runtime/simpleThresholdPolicy.cpp Thu Dec 08 10:27:33 2011 -0800 59.3 @@ -30,6 +30,27 @@ 59.4 #include "runtime/simpleThresholdPolicy.inline.hpp" 59.5 #include "code/scopeDesc.hpp" 59.6 59.7 + 59.8 +void SimpleThresholdPolicy::print_counters(const char* prefix, methodHandle mh) { 59.9 + int invocation_count = mh->invocation_count(); 59.10 + int backedge_count = mh->backedge_count(); 59.11 + methodDataHandle mdh = mh->method_data(); 59.12 + int mdo_invocations = 0, mdo_backedges = 0; 59.13 + int mdo_invocations_start = 0, mdo_backedges_start = 0; 59.14 + if (mdh() != NULL) { 59.15 + mdo_invocations = mdh->invocation_count(); 59.16 + mdo_backedges = mdh->backedge_count(); 59.17 + mdo_invocations_start = mdh->invocation_count_start(); 59.18 + mdo_backedges_start = mdh->backedge_count_start(); 59.19 + } 59.20 + tty->print(" %stotal: %d,%d %smdo: %d(%d),%d(%d)", prefix, 59.21 + invocation_count, backedge_count, prefix, 59.22 + mdo_invocations, mdo_invocations_start, 59.23 + mdo_backedges, mdo_backedges_start); 59.24 + tty->print(" %smax levels: %d,%d", prefix, 59.25 + mh->highest_comp_level(), mh->highest_osr_comp_level()); 59.26 +} 59.27 + 59.28 // Print an event. 59.29 void SimpleThresholdPolicy::print_event(EventType type, methodHandle mh, methodHandle imh, 59.30 int bci, CompLevel level) { 59.31 @@ -38,8 +59,6 @@ 59.32 ttyLocker tty_lock; 59.33 tty->print("%lf: [", os::elapsedTime()); 59.34 59.35 - int invocation_count = mh->invocation_count(); 59.36 - int backedge_count = mh->backedge_count(); 59.37 switch(type) { 59.38 case CALL: 59.39 tty->print("call"); 59.40 @@ -82,23 +101,9 @@ 59.41 print_specific(type, mh, imh, bci, level); 59.42 59.43 if (type != COMPILE) { 59.44 - methodDataHandle mdh = mh->method_data(); 59.45 - int mdo_invocations = 0, mdo_backedges = 0; 59.46 - int mdo_invocations_start = 0, mdo_backedges_start = 0; 59.47 - if (mdh() != NULL) { 59.48 - mdo_invocations = mdh->invocation_count(); 59.49 - mdo_backedges = mdh->backedge_count(); 59.50 - mdo_invocations_start = mdh->invocation_count_start(); 59.51 - mdo_backedges_start = mdh->backedge_count_start(); 59.52 - } 59.53 - tty->print(" total: %d,%d mdo: %d(%d),%d(%d)", 59.54 - invocation_count, backedge_count, 59.55 - mdo_invocations, mdo_invocations_start, 59.56 - mdo_backedges, mdo_backedges_start); 59.57 - tty->print(" max levels: %d,%d", 59.58 - mh->highest_comp_level(), mh->highest_osr_comp_level()); 59.59 + print_counters("", mh); 59.60 if (inlinee_event) { 59.61 - tty->print(" inlinee max levels: %d,%d", imh->highest_comp_level(), imh->highest_osr_comp_level()); 59.62 + print_counters("inlinee ", imh); 59.63 } 59.64 tty->print(" compilable: "); 59.65 bool need_comma = false;
60.1 --- a/src/share/vm/runtime/simpleThresholdPolicy.hpp Wed Dec 07 07:27:09 2011 -0800 60.2 +++ b/src/share/vm/runtime/simpleThresholdPolicy.hpp Thu Dec 08 10:27:33 2011 -0800 60.3 @@ -55,7 +55,7 @@ 60.4 // loop_event checks if a method should be OSR compiled at a different 60.5 // level. 60.6 CompLevel loop_event(methodOop method, CompLevel cur_level); 60.7 - 60.8 + void print_counters(const char* prefix, methodHandle mh); 60.9 protected: 60.10 int c1_count() const { return _c1_count; } 60.11 int c2_count() const { return _c2_count; }
61.1 --- a/test/compiler/6792161/Test6792161.java Wed Dec 07 07:27:09 2011 -0800 61.2 +++ b/test/compiler/6792161/Test6792161.java Thu Dec 08 10:27:33 2011 -0800 61.3 @@ -27,7 +27,7 @@ 61.4 * @bug 6792161 61.5 * @summary assert("No dead instructions after post-alloc") 61.6 * 61.7 - * @run main/othervm -Xcomp -XX:MaxInlineSize=120 Test6792161 61.8 + * @run main/othervm/timeout=300 -Xcomp -XX:MaxInlineSize=120 Test6792161 61.9 */ 61.10 61.11 import java.lang.reflect.Constructor;
62.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 62.2 +++ b/test/compiler/7110586/Test7110586.java Thu Dec 08 10:27:33 2011 -0800 62.3 @@ -0,0 +1,132 @@ 62.4 +/* 62.5 + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 62.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 62.7 + * 62.8 + * This code is free software; you can redistribute it and/or modify it 62.9 + * under the terms of the GNU General Public License version 2 only, as 62.10 + * published by the Free Software Foundation. 62.11 + * 62.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 62.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 62.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 62.15 + * version 2 for more details (a copy is included in the LICENSE file that 62.16 + * accompanied this code). 62.17 + * 62.18 + * You should have received a copy of the GNU General Public License version 62.19 + * 2 along with this work; if not, write to the Free Software Foundation, 62.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 62.21 + * 62.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 62.23 + * or visit www.oracle.com if you need additional information or have any 62.24 + * questions. 62.25 + * 62.26 + */ 62.27 + 62.28 +/** 62.29 + * @test 62.30 + * @bug 7110586 62.31 + * @summary C2 generates icorrect results 62.32 + * 62.33 + * @run main/othervm -Xbatch Test7110586 62.34 + */ 62.35 + 62.36 +public class Test7110586 { 62.37 + static int test1() { 62.38 + int i = 0; 62.39 + for ( ; i < 11; i+=1) {} 62.40 + return i; 62.41 + } 62.42 + static int test2() { 62.43 + int i = 0; 62.44 + for ( ; i < 11; i+=2) {} 62.45 + return i; 62.46 + } 62.47 + static int test3() { 62.48 + int i = 0; 62.49 + for ( ; i < 11; i+=3) {} 62.50 + return i; 62.51 + } 62.52 + static int test11() { 62.53 + int i = 0; 62.54 + for ( ; i < 11; i+=11) {} 62.55 + return i; 62.56 + } 62.57 + 62.58 + static int testm1() { 62.59 + int i = 0; 62.60 + for ( ; i > -11; i-=1) {} 62.61 + return i; 62.62 + } 62.63 + static int testm2() { 62.64 + int i = 0; 62.65 + for ( ; i > -11; i-=2) {} 62.66 + return i; 62.67 + } 62.68 + static int testm3() { 62.69 + int i = 0; 62.70 + for ( ; i > -11; i-=3) {} 62.71 + return i; 62.72 + } 62.73 + static int testm11() { 62.74 + int i = 0; 62.75 + for ( ; i > -11; i-=11) {} 62.76 + return i; 62.77 + } 62.78 + 62.79 + public static void main(String args[]) { 62.80 + int x1 = 0; 62.81 + int x2 = 0; 62.82 + int x3 = 0; 62.83 + int x11 = 0; 62.84 + int m1 = 0; 62.85 + int m2 = 0; 62.86 + int m3 = 0; 62.87 + int m11 = 0; 62.88 + for (int i=0; i<10000; i++) { 62.89 + x1 = test1(); 62.90 + x2 = test2(); 62.91 + x3 = test3(); 62.92 + x11 = test11(); 62.93 + m1 = testm1(); 62.94 + m2 = testm2(); 62.95 + m3 = testm3(); 62.96 + m11 = testm11(); 62.97 + } 62.98 + boolean failed = false; 62.99 + if (x1 != 11) { 62.100 + System.out.println("ERROR (incr = +1): " + x1 + " != 11"); 62.101 + failed = true; 62.102 + } 62.103 + if (x2 != 12) { 62.104 + System.out.println("ERROR (incr = +2): " + x2 + " != 12"); 62.105 + failed = true; 62.106 + } 62.107 + if (x3 != 12) { 62.108 + System.out.println("ERROR (incr = +3): " + x3 + " != 12"); 62.109 + failed = true; 62.110 + } 62.111 + if (x11 != 11) { 62.112 + System.out.println("ERROR (incr = +11): " + x11 + " != 11"); 62.113 + failed = true; 62.114 + } 62.115 + if (m1 != -11) { 62.116 + System.out.println("ERROR (incr = -1): " + m1 + " != -11"); 62.117 + failed = true; 62.118 + } 62.119 + if (m2 != -12) { 62.120 + System.out.println("ERROR (incr = -2): " + m2 + " != -12"); 62.121 + failed = true; 62.122 + } 62.123 + if (m3 != -12) { 62.124 + System.out.println("ERROR (incr = -3): " + m3 + " != -12"); 62.125 + failed = true; 62.126 + } 62.127 + if (m11 != -11) { 62.128 + System.out.println("ERROR (incr = -11): " + m11 + " != -11"); 62.129 + failed = true; 62.130 + } 62.131 + if (failed) { 62.132 + System.exit(97); 62.133 + } 62.134 + } 62.135 +}