Mon, 01 Feb 2010 16:49:49 -0800
6614597: Performance variability in jvm2008 xml.validation
Summary: Fix incorrect marking of methods as not compilable.
Reviewed-by: never
1.1 --- a/src/cpu/sparc/vm/interp_masm_sparc.cpp Mon Feb 01 23:18:47 2010 +0100 1.2 +++ b/src/cpu/sparc/vm/interp_masm_sparc.cpp Mon Feb 01 16:49:49 2010 -0800 1.3 @@ -1681,11 +1681,8 @@ 1.4 // If no method data exists, go to profile_continue. 1.5 test_method_data_pointer(profile_continue); 1.6 1.7 - // We are making a call. Increment the count. 1.8 - increment_mdp_data_at(in_bytes(CounterData::count_offset()), scratch); 1.9 - 1.10 // Record the receiver type. 1.11 - record_klass_in_profile(receiver, scratch); 1.12 + record_klass_in_profile(receiver, scratch, true); 1.13 1.14 // The method data pointer needs to be updated to reflect the new target. 1.15 update_mdp_by_constant(in_bytes(VirtualCallData::virtual_call_data_size())); 1.16 @@ -1695,9 +1692,13 @@ 1.17 1.18 void InterpreterMacroAssembler::record_klass_in_profile_helper( 1.19 Register receiver, Register scratch, 1.20 - int start_row, Label& done) { 1.21 - if (TypeProfileWidth == 0) 1.22 + int start_row, Label& done, bool is_virtual_call) { 1.23 + if (TypeProfileWidth == 0) { 1.24 + if (is_virtual_call) { 1.25 + increment_mdp_data_at(in_bytes(CounterData::count_offset()), scratch); 1.26 + } 1.27 return; 1.28 + } 1.29 1.30 int last_row = VirtualCallData::row_limit() - 1; 1.31 assert(start_row <= last_row, "must be work left to do"); 1.32 @@ -1714,6 +1715,7 @@ 1.33 // See if the receiver is receiver[n]. 1.34 int recvr_offset = in_bytes(VirtualCallData::receiver_offset(row)); 1.35 test_mdp_data_at(recvr_offset, receiver, next_test, scratch); 1.36 + // delayed()->tst(scratch); 1.37 1.38 // The receiver is receiver[n]. Increment count[n]. 1.39 int count_offset = in_bytes(VirtualCallData::receiver_count_offset(row)); 1.40 @@ -1723,20 +1725,31 @@ 1.41 bind(next_test); 1.42 1.43 if (test_for_null_also) { 1.44 + Label found_null; 1.45 // Failed the equality check on receiver[n]... Test for null. 1.46 if (start_row == last_row) { 1.47 // The only thing left to do is handle the null case. 1.48 - brx(Assembler::notZero, false, Assembler::pt, done); 1.49 - delayed()->nop(); 1.50 + if (is_virtual_call) { 1.51 + brx(Assembler::zero, false, Assembler::pn, found_null); 1.52 + delayed()->nop(); 1.53 + // Receiver did not match any saved receiver and there is no empty row for it. 1.54 + // Increment total counter to indicate polimorphic case. 1.55 + increment_mdp_data_at(in_bytes(CounterData::count_offset()), scratch); 1.56 + ba(false, done); 1.57 + delayed()->nop(); 1.58 + bind(found_null); 1.59 + } else { 1.60 + brx(Assembler::notZero, false, Assembler::pt, done); 1.61 + delayed()->nop(); 1.62 + } 1.63 break; 1.64 } 1.65 // Since null is rare, make it be the branch-taken case. 1.66 - Label found_null; 1.67 brx(Assembler::zero, false, Assembler::pn, found_null); 1.68 delayed()->nop(); 1.69 1.70 // Put all the "Case 3" tests here. 1.71 - record_klass_in_profile_helper(receiver, scratch, start_row + 1, done); 1.72 + record_klass_in_profile_helper(receiver, scratch, start_row + 1, done, is_virtual_call); 1.73 1.74 // Found a null. Keep searching for a matching receiver, 1.75 // but remember that this is an empty (unused) slot. 1.76 @@ -1753,16 +1766,18 @@ 1.77 int count_offset = in_bytes(VirtualCallData::receiver_count_offset(start_row)); 1.78 mov(DataLayout::counter_increment, scratch); 1.79 set_mdp_data_at(count_offset, scratch); 1.80 - ba(false, done); 1.81 - delayed()->nop(); 1.82 + if (start_row > 0) { 1.83 + ba(false, done); 1.84 + delayed()->nop(); 1.85 + } 1.86 } 1.87 1.88 void InterpreterMacroAssembler::record_klass_in_profile(Register receiver, 1.89 - Register scratch) { 1.90 + Register scratch, bool is_virtual_call) { 1.91 assert(ProfileInterpreter, "must be profiling"); 1.92 Label done; 1.93 1.94 - record_klass_in_profile_helper(receiver, scratch, 0, done); 1.95 + record_klass_in_profile_helper(receiver, scratch, 0, done, is_virtual_call); 1.96 1.97 bind (done); 1.98 } 1.99 @@ -1840,7 +1855,7 @@ 1.100 mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size()); 1.101 1.102 // Record the object type. 1.103 - record_klass_in_profile(klass, scratch); 1.104 + record_klass_in_profile(klass, scratch, false); 1.105 } 1.106 1.107 // The method data pointer needs to be updated.
2.1 --- a/src/cpu/sparc/vm/interp_masm_sparc.hpp Mon Feb 01 23:18:47 2010 +0100 2.2 +++ b/src/cpu/sparc/vm/interp_masm_sparc.hpp Mon Feb 01 16:49:49 2010 -0800 2.3 @@ -290,9 +290,9 @@ 2.4 void test_mdp_data_at(int offset, Register value, Label& not_equal_continue, 2.5 Register scratch); 2.6 2.7 - void record_klass_in_profile(Register receiver, Register scratch); 2.8 + void record_klass_in_profile(Register receiver, Register scratch, bool is_virtual_call); 2.9 void record_klass_in_profile_helper(Register receiver, Register scratch, 2.10 - int start_row, Label& done); 2.11 + int start_row, Label& done, bool is_virtual_call); 2.12 2.13 void update_mdp_by_offset(int offset_of_disp, Register scratch); 2.14 void update_mdp_by_offset(Register reg, int offset_of_disp,
3.1 --- a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Mon Feb 01 23:18:47 2010 +0100 3.2 +++ b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Mon Feb 01 16:49:49 2010 -0800 3.3 @@ -3209,7 +3209,6 @@ 3.4 Register mdo = op->mdo()->as_register(); 3.5 __ movoop(mdo, md->constant_encoding()); 3.6 Address counter_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset())); 3.7 - __ addl(counter_addr, DataLayout::counter_increment); 3.8 Bytecodes::Code bc = method->java_code_at_bci(bci); 3.9 // Perform additional virtual call profiling for invokevirtual and 3.10 // invokeinterface bytecodes 3.11 @@ -3276,14 +3275,18 @@ 3.12 __ jcc(Assembler::notEqual, next_test); 3.13 __ movptr(recv_addr, recv); 3.14 __ movl(Address(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i))), DataLayout::counter_increment); 3.15 - if (i < (VirtualCallData::row_limit() - 1)) { 3.16 - __ jmp(update_done); 3.17 - } 3.18 + __ jmp(update_done); 3.19 __ bind(next_test); 3.20 } 3.21 + // Receiver did not match any saved receiver and there is no empty row for it. 3.22 + // Increment total counter to indicate polimorphic case. 3.23 + __ addl(counter_addr, DataLayout::counter_increment); 3.24 3.25 __ bind(update_done); 3.26 } 3.27 + } else { 3.28 + // Static call 3.29 + __ addl(counter_addr, DataLayout::counter_increment); 3.30 } 3.31 } 3.32
4.1 --- a/src/cpu/x86/vm/interp_masm_x86_32.cpp Mon Feb 01 23:18:47 2010 +0100 4.2 +++ b/src/cpu/x86/vm/interp_masm_x86_32.cpp Mon Feb 01 16:49:49 2010 -0800 4.3 @@ -1239,17 +1239,19 @@ 4.4 // If no method data exists, go to profile_continue. 4.5 test_method_data_pointer(mdp, profile_continue); 4.6 4.7 - // We are making a call. Increment the count. 4.8 - increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); 4.9 - 4.10 Label skip_receiver_profile; 4.11 if (receiver_can_be_null) { 4.12 + Label not_null; 4.13 testptr(receiver, receiver); 4.14 - jcc(Assembler::zero, skip_receiver_profile); 4.15 + jccb(Assembler::notZero, not_null); 4.16 + // We are making a call. Increment the count for null receiver. 4.17 + increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); 4.18 + jmp(skip_receiver_profile); 4.19 + bind(not_null); 4.20 } 4.21 4.22 // Record the receiver type. 4.23 - record_klass_in_profile(receiver, mdp, reg2); 4.24 + record_klass_in_profile(receiver, mdp, reg2, true); 4.25 bind(skip_receiver_profile); 4.26 4.27 // The method data pointer needs to be updated to reflect the new target. 4.28 @@ -1263,10 +1265,14 @@ 4.29 4.30 void InterpreterMacroAssembler::record_klass_in_profile_helper( 4.31 Register receiver, Register mdp, 4.32 - Register reg2, 4.33 - int start_row, Label& done) { 4.34 - if (TypeProfileWidth == 0) 4.35 + Register reg2, int start_row, 4.36 + Label& done, bool is_virtual_call) { 4.37 + if (TypeProfileWidth == 0) { 4.38 + if (is_virtual_call) { 4.39 + increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); 4.40 + } 4.41 return; 4.42 + } 4.43 4.44 int last_row = VirtualCallData::row_limit() - 1; 4.45 assert(start_row <= last_row, "must be work left to do"); 4.46 @@ -1294,19 +1300,28 @@ 4.47 bind(next_test); 4.48 4.49 if (row == start_row) { 4.50 + Label found_null; 4.51 // Failed the equality check on receiver[n]... Test for null. 4.52 testptr(reg2, reg2); 4.53 if (start_row == last_row) { 4.54 // The only thing left to do is handle the null case. 4.55 - jcc(Assembler::notZero, done); 4.56 + if (is_virtual_call) { 4.57 + jccb(Assembler::zero, found_null); 4.58 + // Receiver did not match any saved receiver and there is no empty row for it. 4.59 + // Increment total counter to indicate polimorphic case. 4.60 + increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); 4.61 + jmp(done); 4.62 + bind(found_null); 4.63 + } else { 4.64 + jcc(Assembler::notZero, done); 4.65 + } 4.66 break; 4.67 } 4.68 // Since null is rare, make it be the branch-taken case. 4.69 - Label found_null; 4.70 jcc(Assembler::zero, found_null); 4.71 4.72 // Put all the "Case 3" tests here. 4.73 - record_klass_in_profile_helper(receiver, mdp, reg2, start_row + 1, done); 4.74 + record_klass_in_profile_helper(receiver, mdp, reg2, start_row + 1, done, is_virtual_call); 4.75 4.76 // Found a null. Keep searching for a matching receiver, 4.77 // but remember that this is an empty (unused) slot. 4.78 @@ -1323,16 +1338,18 @@ 4.79 int count_offset = in_bytes(VirtualCallData::receiver_count_offset(start_row)); 4.80 movptr(reg2, (int32_t)DataLayout::counter_increment); 4.81 set_mdp_data_at(mdp, count_offset, reg2); 4.82 - jmp(done); 4.83 + if (start_row > 0) { 4.84 + jmp(done); 4.85 + } 4.86 } 4.87 4.88 void InterpreterMacroAssembler::record_klass_in_profile(Register receiver, 4.89 - Register mdp, 4.90 - Register reg2) { 4.91 + Register mdp, Register reg2, 4.92 + bool is_virtual_call) { 4.93 assert(ProfileInterpreter, "must be profiling"); 4.94 Label done; 4.95 4.96 - record_klass_in_profile_helper(receiver, mdp, reg2, 0, done); 4.97 + record_klass_in_profile_helper(receiver, mdp, reg2, 0, done, is_virtual_call); 4.98 4.99 bind (done); 4.100 } 4.101 @@ -1425,7 +1442,7 @@ 4.102 mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size()); 4.103 4.104 // Record the object type. 4.105 - record_klass_in_profile(klass, mdp, reg2); 4.106 + record_klass_in_profile(klass, mdp, reg2, false); 4.107 assert(reg2 == rdi, "we know how to fix this blown reg"); 4.108 restore_locals(); // Restore EDI 4.109 }
5.1 --- a/src/cpu/x86/vm/interp_masm_x86_32.hpp Mon Feb 01 23:18:47 2010 +0100 5.2 +++ b/src/cpu/x86/vm/interp_masm_x86_32.hpp Mon Feb 01 16:49:49 2010 -0800 5.3 @@ -213,10 +213,10 @@ 5.4 Label& not_equal_continue); 5.5 5.6 void record_klass_in_profile(Register receiver, Register mdp, 5.7 - Register reg2); 5.8 + Register reg2, bool is_virtual_call); 5.9 void record_klass_in_profile_helper(Register receiver, Register mdp, 5.10 - Register reg2, 5.11 - int start_row, Label& done); 5.12 + Register reg2, int start_row, 5.13 + Label& done, bool is_virtual_call); 5.14 5.15 void update_mdp_by_offset(Register mdp_in, int offset_of_offset); 5.16 void update_mdp_by_offset(Register mdp_in, Register reg, int offset_of_disp);
6.1 --- a/src/cpu/x86/vm/interp_masm_x86_64.cpp Mon Feb 01 23:18:47 2010 +0100 6.2 +++ b/src/cpu/x86/vm/interp_masm_x86_64.cpp Mon Feb 01 16:49:49 2010 -0800 6.3 @@ -1262,17 +1262,19 @@ 6.4 // If no method data exists, go to profile_continue. 6.5 test_method_data_pointer(mdp, profile_continue); 6.6 6.7 - // We are making a call. Increment the count. 6.8 - increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); 6.9 - 6.10 Label skip_receiver_profile; 6.11 if (receiver_can_be_null) { 6.12 + Label not_null; 6.13 testptr(receiver, receiver); 6.14 - jcc(Assembler::zero, skip_receiver_profile); 6.15 + jccb(Assembler::notZero, not_null); 6.16 + // We are making a call. Increment the count for null receiver. 6.17 + increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); 6.18 + jmp(skip_receiver_profile); 6.19 + bind(not_null); 6.20 } 6.21 6.22 // Record the receiver type. 6.23 - record_klass_in_profile(receiver, mdp, reg2); 6.24 + record_klass_in_profile(receiver, mdp, reg2, true); 6.25 bind(skip_receiver_profile); 6.26 6.27 // The method data pointer needs to be updated to reflect the new target. 6.28 @@ -1296,10 +1298,14 @@ 6.29 // See below for example code. 6.30 void InterpreterMacroAssembler::record_klass_in_profile_helper( 6.31 Register receiver, Register mdp, 6.32 - Register reg2, 6.33 - int start_row, Label& done) { 6.34 - if (TypeProfileWidth == 0) 6.35 + Register reg2, int start_row, 6.36 + Label& done, bool is_virtual_call) { 6.37 + if (TypeProfileWidth == 0) { 6.38 + if (is_virtual_call) { 6.39 + increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); 6.40 + } 6.41 return; 6.42 + } 6.43 6.44 int last_row = VirtualCallData::row_limit() - 1; 6.45 assert(start_row <= last_row, "must be work left to do"); 6.46 @@ -1327,19 +1333,28 @@ 6.47 bind(next_test); 6.48 6.49 if (test_for_null_also) { 6.50 + Label found_null; 6.51 // Failed the equality check on receiver[n]... Test for null. 6.52 testptr(reg2, reg2); 6.53 if (start_row == last_row) { 6.54 // The only thing left to do is handle the null case. 6.55 - jcc(Assembler::notZero, done); 6.56 + if (is_virtual_call) { 6.57 + jccb(Assembler::zero, found_null); 6.58 + // Receiver did not match any saved receiver and there is no empty row for it. 6.59 + // Increment total counter to indicate polimorphic case. 6.60 + increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); 6.61 + jmp(done); 6.62 + bind(found_null); 6.63 + } else { 6.64 + jcc(Assembler::notZero, done); 6.65 + } 6.66 break; 6.67 } 6.68 // Since null is rare, make it be the branch-taken case. 6.69 - Label found_null; 6.70 jcc(Assembler::zero, found_null); 6.71 6.72 // Put all the "Case 3" tests here. 6.73 - record_klass_in_profile_helper(receiver, mdp, reg2, start_row + 1, done); 6.74 + record_klass_in_profile_helper(receiver, mdp, reg2, start_row + 1, done, is_virtual_call); 6.75 6.76 // Found a null. Keep searching for a matching receiver, 6.77 // but remember that this is an empty (unused) slot. 6.78 @@ -1356,7 +1371,9 @@ 6.79 int count_offset = in_bytes(VirtualCallData::receiver_count_offset(start_row)); 6.80 movl(reg2, DataLayout::counter_increment); 6.81 set_mdp_data_at(mdp, count_offset, reg2); 6.82 - jmp(done); 6.83 + if (start_row > 0) { 6.84 + jmp(done); 6.85 + } 6.86 } 6.87 6.88 // Example state machine code for three profile rows: 6.89 @@ -1368,7 +1385,7 @@ 6.90 // if (row[1].rec != NULL) { 6.91 // // degenerate decision tree, rooted at row[2] 6.92 // if (row[2].rec == rec) { row[2].incr(); goto done; } 6.93 -// if (row[2].rec != NULL) { goto done; } // overflow 6.94 +// if (row[2].rec != NULL) { count.incr(); goto done; } // overflow 6.95 // row[2].init(rec); goto done; 6.96 // } else { 6.97 // // remember row[1] is empty 6.98 @@ -1381,14 +1398,15 @@ 6.99 // if (row[2].rec == rec) { row[2].incr(); goto done; } 6.100 // row[0].init(rec); goto done; 6.101 // } 6.102 +// done: 6.103 6.104 void InterpreterMacroAssembler::record_klass_in_profile(Register receiver, 6.105 - Register mdp, 6.106 - Register reg2) { 6.107 + Register mdp, Register reg2, 6.108 + bool is_virtual_call) { 6.109 assert(ProfileInterpreter, "must be profiling"); 6.110 Label done; 6.111 6.112 - record_klass_in_profile_helper(receiver, mdp, reg2, 0, done); 6.113 + record_klass_in_profile_helper(receiver, mdp, reg2, 0, done, is_virtual_call); 6.114 6.115 bind (done); 6.116 } 6.117 @@ -1484,7 +1502,7 @@ 6.118 mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size()); 6.119 6.120 // Record the object type. 6.121 - record_klass_in_profile(klass, mdp, reg2); 6.122 + record_klass_in_profile(klass, mdp, reg2, false); 6.123 } 6.124 update_mdp_by_constant(mdp, mdp_delta); 6.125
7.1 --- a/src/cpu/x86/vm/interp_masm_x86_64.hpp Mon Feb 01 23:18:47 2010 +0100 7.2 +++ b/src/cpu/x86/vm/interp_masm_x86_64.hpp Mon Feb 01 16:49:49 2010 -0800 7.3 @@ -222,10 +222,10 @@ 7.4 Label& not_equal_continue); 7.5 7.6 void record_klass_in_profile(Register receiver, Register mdp, 7.7 - Register reg2); 7.8 + Register reg2, bool is_virtual_call); 7.9 void record_klass_in_profile_helper(Register receiver, Register mdp, 7.10 - Register reg2, 7.11 - int start_row, Label& done); 7.12 + Register reg2, int start_row, 7.13 + Label& done, bool is_virtual_call); 7.14 7.15 void update_mdp_by_offset(Register mdp_in, int offset_of_offset); 7.16 void update_mdp_by_offset(Register mdp_in, Register reg, int offset_of_disp);
8.1 --- a/src/share/vm/ci/ciMethod.cpp Mon Feb 01 23:18:47 2010 +0100 8.2 +++ b/src/share/vm/ci/ciMethod.cpp Mon Feb 01 16:49:49 2010 -0800 8.3 @@ -436,15 +436,20 @@ 8.4 // we will set result._method also. 8.5 } 8.6 // Determine call site's morphism. 8.7 - // The call site count could be == (receivers_count_total + 1) 8.8 - // not only in the case of a polymorphic call but also in the case 8.9 - // when a method data snapshot is taken after the site count was updated 8.10 - // but before receivers counters were updated. 8.11 - if (morphism == result._limit) { 8.12 - // There were no array klasses and morphism <= MorphismLimit. 8.13 - if (morphism < ciCallProfile::MorphismLimit || 8.14 - morphism == ciCallProfile::MorphismLimit && 8.15 - (receivers_count_total+1) >= count) { 8.16 + // The call site count is 0 with known morphism (onlt 1 or 2 receivers) 8.17 + // or < 0 in the case of a type check failured for checkcast, aastore, instanceof. 8.18 + // The call site count is > 0 in the case of a polymorphic virtual call. 8.19 + if (morphism > 0 && morphism == result._limit) { 8.20 + // The morphism <= MorphismLimit. 8.21 + if ((morphism < ciCallProfile::MorphismLimit) || 8.22 + (morphism == ciCallProfile::MorphismLimit && count == 0)) { 8.23 +#ifdef ASSERT 8.24 + if (count > 0) { 8.25 + tty->print_cr("bci: %d", bci); 8.26 + this->print_codes(); 8.27 + assert(false, "this call site should not be polymorphic"); 8.28 + } 8.29 +#endif 8.30 result._morphism = morphism; 8.31 } 8.32 } 8.33 @@ -452,10 +457,8 @@ 8.34 // zero or less, presume that this is a typecheck profile and 8.35 // do nothing. Otherwise, increase count to be the sum of all 8.36 // receiver's counts. 8.37 - if (count > 0) { 8.38 - if (count < receivers_count_total) { 8.39 - count = receivers_count_total; 8.40 - } 8.41 + if (count >= 0) { 8.42 + count += receivers_count_total; 8.43 } 8.44 } 8.45 result._count = count;
9.1 --- a/src/share/vm/code/dependencies.cpp Mon Feb 01 23:18:47 2010 +0100 9.2 +++ b/src/share/vm/code/dependencies.cpp Mon Feb 01 16:49:49 2010 -0800 9.3 @@ -843,13 +843,15 @@ 9.4 if (occasional_print || final_stats) { 9.5 // Every now and then dump a little info about dependency searching. 9.6 if (xtty != NULL) { 9.7 - xtty->elem("deps_find_witness calls='%d' steps='%d' recursions='%d' singles='%d'", 9.8 + ttyLocker ttyl; 9.9 + xtty->elem("deps_find_witness calls='%d' steps='%d' recursions='%d' singles='%d'", 9.10 deps_find_witness_calls, 9.11 deps_find_witness_steps, 9.12 deps_find_witness_recursions, 9.13 deps_find_witness_singles); 9.14 } 9.15 if (final_stats || (TraceDependencies && WizardMode)) { 9.16 + ttyLocker ttyl; 9.17 tty->print_cr("Dependency check (find_witness) " 9.18 "calls=%d, steps=%d (avg=%.1f), recursions=%d, singles=%d", 9.19 deps_find_witness_calls,
10.1 --- a/src/share/vm/code/nmethod.cpp Mon Feb 01 23:18:47 2010 +0100 10.2 +++ b/src/share/vm/code/nmethod.cpp Mon Feb 01 16:49:49 2010 -0800 10.3 @@ -1117,7 +1117,6 @@ 10.4 if (_method->code() == this) { 10.5 _method->clear_code(); // Break a cycle 10.6 } 10.7 - inc_decompile_count(); // Last chance to make a mark on the MDO 10.8 _method = NULL; // Clear the method of this dead nmethod 10.9 } 10.10 // Make the class unloaded - i.e., change state and notify sweeper 10.11 @@ -1177,15 +1176,17 @@ 10.12 bool nmethod::make_not_entrant_or_zombie(unsigned int state) { 10.13 assert(state == zombie || state == not_entrant, "must be zombie or not_entrant"); 10.14 10.15 - // If the method is already zombie there is nothing to do 10.16 - if (is_zombie()) { 10.17 - return false; 10.18 - } 10.19 + bool was_alive = false; 10.20 10.21 // Make sure the nmethod is not flushed in case of a safepoint in code below. 10.22 nmethodLocker nml(this); 10.23 10.24 { 10.25 + // If the method is already zombie there is nothing to do 10.26 + if (is_zombie()) { 10.27 + return false; 10.28 + } 10.29 + 10.30 // invalidate osr nmethod before acquiring the patching lock since 10.31 // they both acquire leaf locks and we don't want a deadlock. 10.32 // This logic is equivalent to the logic below for patching the 10.33 @@ -1223,6 +1224,8 @@ 10.34 assert(state == not_entrant, "other cases may need to be handled differently"); 10.35 } 10.36 10.37 + was_alive = is_in_use(); // Read state under lock 10.38 + 10.39 // Change state 10.40 flags.state = state; 10.41 10.42 @@ -1249,8 +1252,11 @@ 10.43 mark_as_seen_on_stack(); 10.44 } 10.45 10.46 - // It's a true state change, so mark the method as decompiled. 10.47 - inc_decompile_count(); 10.48 + if (was_alive) { 10.49 + // It's a true state change, so mark the method as decompiled. 10.50 + // Do it only for transition from alive. 10.51 + inc_decompile_count(); 10.52 + } 10.53 10.54 // zombie only - if a JVMTI agent has enabled the CompiledMethodUnload event 10.55 // and it hasn't already been reported for this nmethod then report it now.
11.1 --- a/src/share/vm/oops/methodDataOop.hpp Mon Feb 01 23:18:47 2010 +0100 11.2 +++ b/src/share/vm/oops/methodDataOop.hpp Mon Feb 01 16:49:49 2010 -0800 11.3 @@ -1391,6 +1391,9 @@ 11.4 } 11.5 void inc_decompile_count() { 11.6 _nof_decompiles += 1; 11.7 + if (decompile_count() > (uint)PerMethodRecompilationCutoff) { 11.8 + method()->set_not_compilable(); 11.9 + } 11.10 } 11.11 11.12 // Support for code generation
12.1 --- a/src/share/vm/oops/methodOop.cpp Mon Feb 01 23:18:47 2010 +0100 12.2 +++ b/src/share/vm/oops/methodOop.cpp Mon Feb 01 16:49:49 2010 -0800 12.3 @@ -575,12 +575,6 @@ 12.4 return true; 12.5 } 12.6 12.7 - methodDataOop mdo = method_data(); 12.8 - if (mdo != NULL 12.9 - && (uint)mdo->decompile_count() > (uint)PerMethodRecompilationCutoff) { 12.10 - // Since (uint)-1 is large, -1 really means 'no cutoff'. 12.11 - return true; 12.12 - } 12.13 #ifdef COMPILER2 12.14 if (is_tier1_compile(comp_level)) { 12.15 if (is_not_tier1_compilable()) { 12.16 @@ -594,6 +588,15 @@ 12.17 12.18 // call this when compiler finds that this method is not compilable 12.19 void methodOopDesc::set_not_compilable(int comp_level) { 12.20 + if (PrintCompilation) { 12.21 + ttyLocker ttyl; 12.22 + tty->print("made not compilable "); 12.23 + this->print_short_name(tty); 12.24 + int size = this->code_size(); 12.25 + if (size > 0) 12.26 + tty->print(" (%d bytes)", size); 12.27 + tty->cr(); 12.28 + } 12.29 if ((TraceDeoptimization || LogCompilation) && (xtty != NULL)) { 12.30 ttyLocker ttyl; 12.31 xtty->begin_elem("make_not_compilable thread='%d'", (int) os::current_thread_id());
13.1 --- a/src/share/vm/opto/doCall.cpp Mon Feb 01 23:18:47 2010 +0100 13.2 +++ b/src/share/vm/opto/doCall.cpp Mon Feb 01 16:49:49 2010 -0800 13.3 @@ -182,26 +182,16 @@ 13.4 } 13.5 } 13.6 CallGenerator* miss_cg; 13.7 + Deoptimization::DeoptReason reason = (profile.morphism() == 2) ? 13.8 + Deoptimization::Reason_bimorphic : 13.9 + Deoptimization::Reason_class_check; 13.10 if (( profile.morphism() == 1 || 13.11 (profile.morphism() == 2 && next_hit_cg != NULL) ) && 13.12 - 13.13 - !too_many_traps(Deoptimization::Reason_class_check) 13.14 - 13.15 - // Check only total number of traps per method to allow 13.16 - // the transition from monomorphic to bimorphic case between 13.17 - // compilations without falling into virtual call. 13.18 - // A monomorphic case may have the class_check trap flag is set 13.19 - // due to the time gap between the uncommon trap processing 13.20 - // when flags are set in MDO and the call site bytecode execution 13.21 - // in Interpreter when MDO counters are updated. 13.22 - // There was also class_check trap in monomorphic case due to 13.23 - // the bug 6225440. 13.24 - 13.25 + !too_many_traps(jvms->method(), jvms->bci(), reason) 13.26 ) { 13.27 // Generate uncommon trap for class check failure path 13.28 // in case of monomorphic or bimorphic virtual call site. 13.29 - miss_cg = CallGenerator::for_uncommon_trap(call_method, 13.30 - Deoptimization::Reason_class_check, 13.31 + miss_cg = CallGenerator::for_uncommon_trap(call_method, reason, 13.32 Deoptimization::Action_maybe_recompile); 13.33 } else { 13.34 // Generate virtual call for class check failure path
14.1 --- a/src/share/vm/opto/parseHelper.cpp Mon Feb 01 23:18:47 2010 +0100 14.2 +++ b/src/share/vm/opto/parseHelper.cpp Mon Feb 01 16:49:49 2010 -0800 14.3 @@ -414,8 +414,6 @@ 14.4 void Parse::profile_call(Node* receiver) { 14.5 if (!method_data_update()) return; 14.6 14.7 - profile_generic_call(); 14.8 - 14.9 switch (bc()) { 14.10 case Bytecodes::_invokevirtual: 14.11 case Bytecodes::_invokeinterface: 14.12 @@ -424,6 +422,7 @@ 14.13 case Bytecodes::_invokestatic: 14.14 case Bytecodes::_invokedynamic: 14.15 case Bytecodes::_invokespecial: 14.16 + profile_generic_call(); 14.17 break; 14.18 default: fatal("unexpected call bytecode"); 14.19 } 14.20 @@ -444,13 +443,16 @@ 14.21 void Parse::profile_receiver_type(Node* receiver) { 14.22 assert(method_data_update(), "must be generating profile code"); 14.23 14.24 - // Skip if we aren't tracking receivers 14.25 - if (TypeProfileWidth < 1) return; 14.26 - 14.27 ciMethodData* md = method()->method_data(); 14.28 assert(md != NULL, "expected valid ciMethodData"); 14.29 ciProfileData* data = md->bci_to_data(bci()); 14.30 assert(data->is_ReceiverTypeData(), "need ReceiverTypeData here"); 14.31 + 14.32 + // Skip if we aren't tracking receivers 14.33 + if (TypeProfileWidth < 1) { 14.34 + increment_md_counter_at(md, data, CounterData::count_offset()); 14.35 + return; 14.36 + } 14.37 ciReceiverTypeData* rdata = (ciReceiverTypeData*)data->as_ReceiverTypeData(); 14.38 14.39 Node* method_data = method_data_addressing(md, rdata, in_ByteSize(0));
15.1 --- a/src/share/vm/opto/runtime.cpp Mon Feb 01 23:18:47 2010 +0100 15.2 +++ b/src/share/vm/opto/runtime.cpp Mon Feb 01 16:49:49 2010 -0800 15.3 @@ -706,6 +706,11 @@ 15.4 // vc->set_receiver_count(empty_row, DataLayout::counter_increment); 15.5 int count_off = ReceiverTypeData::receiver_count_cell_index(empty_row); 15.6 *(mdp + count_off) = DataLayout::counter_increment; 15.7 + } else { 15.8 + // Receiver did not match any saved receiver and there is no empty row for it. 15.9 + // Increment total counter to indicate polimorphic case. 15.10 + intptr_t* count_p = (intptr_t*)(((byte*)(data)) + in_bytes(CounterData::count_offset())); 15.11 + *count_p += DataLayout::counter_increment; 15.12 } 15.13 JRT_END 15.14
16.1 --- a/src/share/vm/runtime/deoptimization.cpp Mon Feb 01 23:18:47 2010 +0100 16.2 +++ b/src/share/vm/runtime/deoptimization.cpp Mon Feb 01 16:49:49 2010 -0800 16.3 @@ -1338,13 +1338,14 @@ 16.4 // Whether the interpreter is producing MDO data or not, we also need 16.5 // to use the MDO to detect hot deoptimization points and control 16.6 // aggressive optimization. 16.7 + bool inc_recompile_count = false; 16.8 + ProfileData* pdata = NULL; 16.9 if (ProfileTraps && update_trap_state && trap_mdo.not_null()) { 16.10 assert(trap_mdo() == get_method_data(thread, trap_method, false), "sanity"); 16.11 uint this_trap_count = 0; 16.12 bool maybe_prior_trap = false; 16.13 bool maybe_prior_recompile = false; 16.14 - ProfileData* pdata 16.15 - = query_update_method_data(trap_mdo, trap_bci, reason, 16.16 + pdata = query_update_method_data(trap_mdo, trap_bci, reason, 16.17 //outputs: 16.18 this_trap_count, 16.19 maybe_prior_trap, 16.20 @@ -1380,18 +1381,7 @@ 16.21 // Detect repeated recompilation at the same BCI, and enforce a limit. 16.22 if (make_not_entrant && maybe_prior_recompile) { 16.23 // More than one recompile at this point. 16.24 - trap_mdo->inc_overflow_recompile_count(); 16.25 - if (maybe_prior_trap 16.26 - && ((uint)trap_mdo->overflow_recompile_count() 16.27 - > (uint)PerBytecodeRecompilationCutoff)) { 16.28 - // Give up on the method containing the bad BCI. 16.29 - if (trap_method() == nm->method()) { 16.30 - make_not_compilable = true; 16.31 - } else { 16.32 - trap_method->set_not_compilable(); 16.33 - // But give grace to the enclosing nm->method(). 16.34 - } 16.35 - } 16.36 + inc_recompile_count = maybe_prior_trap; 16.37 } 16.38 } else { 16.39 // For reasons which are not recorded per-bytecode, we simply 16.40 @@ -1418,7 +1408,17 @@ 16.41 reset_counters = true; 16.42 } 16.43 16.44 - if (make_not_entrant && pdata != NULL) { 16.45 + } 16.46 + 16.47 + // Take requested actions on the method: 16.48 + 16.49 + // Recompile 16.50 + if (make_not_entrant) { 16.51 + if (!nm->make_not_entrant()) { 16.52 + return; // the call did not change nmethod's state 16.53 + } 16.54 + 16.55 + if (pdata != NULL) { 16.56 // Record the recompilation event, if any. 16.57 int tstate0 = pdata->trap_state(); 16.58 int tstate1 = trap_state_set_recompiled(tstate0, true); 16.59 @@ -1427,7 +1427,19 @@ 16.60 } 16.61 } 16.62 16.63 - // Take requested actions on the method: 16.64 + if (inc_recompile_count) { 16.65 + trap_mdo->inc_overflow_recompile_count(); 16.66 + if ((uint)trap_mdo->overflow_recompile_count() > 16.67 + (uint)PerBytecodeRecompilationCutoff) { 16.68 + // Give up on the method containing the bad BCI. 16.69 + if (trap_method() == nm->method()) { 16.70 + make_not_compilable = true; 16.71 + } else { 16.72 + trap_method->set_not_compilable(); 16.73 + // But give grace to the enclosing nm->method(). 16.74 + } 16.75 + } 16.76 + } 16.77 16.78 // Reset invocation counters 16.79 if (reset_counters) { 16.80 @@ -1437,13 +1449,8 @@ 16.81 reset_invocation_counter(trap_scope); 16.82 } 16.83 16.84 - // Recompile 16.85 - if (make_not_entrant) { 16.86 - nm->make_not_entrant(); 16.87 - } 16.88 - 16.89 // Give up compiling 16.90 - if (make_not_compilable) { 16.91 + if (make_not_compilable && !nm->method()->is_not_compilable()) { 16.92 assert(make_not_entrant, "consistent"); 16.93 nm->method()->set_not_compilable(); 16.94 } 16.95 @@ -1516,9 +1523,11 @@ 16.96 if (tstate1 != tstate0) 16.97 pdata->set_trap_state(tstate1); 16.98 } else { 16.99 - if (LogCompilation && xtty != NULL) 16.100 + if (LogCompilation && xtty != NULL) { 16.101 + ttyLocker ttyl; 16.102 // Missing MDP? Leave a small complaint in the log. 16.103 xtty->elem("missing_mdp bci='%d'", trap_bci); 16.104 + } 16.105 } 16.106 } 16.107 16.108 @@ -1672,6 +1681,7 @@ 16.109 "class_check", 16.110 "array_check", 16.111 "intrinsic", 16.112 + "bimorphic", 16.113 "unloaded", 16.114 "uninitialized", 16.115 "unreached",
17.1 --- a/src/share/vm/runtime/deoptimization.hpp Mon Feb 01 23:18:47 2010 +0100 17.2 +++ b/src/share/vm/runtime/deoptimization.hpp Mon Feb 01 16:49:49 2010 -0800 17.3 @@ -33,12 +33,15 @@ 17.4 enum DeoptReason { 17.5 Reason_many = -1, // indicates presence of several reasons 17.6 Reason_none = 0, // indicates absence of a relevant deopt. 17.7 + // Next 7 reasons are recorded per bytecode in DataLayout::trap_bits 17.8 Reason_null_check, // saw unexpected null or zero divisor (@bci) 17.9 Reason_null_assert, // saw unexpected non-null or non-zero (@bci) 17.10 Reason_range_check, // saw unexpected array index (@bci) 17.11 Reason_class_check, // saw unexpected object class (@bci) 17.12 Reason_array_check, // saw unexpected array class (aastore @bci) 17.13 Reason_intrinsic, // saw unexpected operand to intrinsic (@bci) 17.14 + Reason_bimorphic, // saw unexpected object class in bimorphic inlining (@bci) 17.15 + 17.16 Reason_unloaded, // unloaded class or constant pool entry 17.17 Reason_uninitialized, // bad class state (uninitialized) 17.18 Reason_unreached, // code is not reached, compiler 17.19 @@ -49,7 +52,7 @@ 17.20 Reason_predicate, // compiler generated predicate failed 17.21 Reason_LIMIT, 17.22 // Note: Keep this enum in sync. with _trap_reason_name. 17.23 - Reason_RECORDED_LIMIT = Reason_unloaded // some are not recorded per bc 17.24 + Reason_RECORDED_LIMIT = Reason_bimorphic // some are not recorded per bc 17.25 // Note: Reason_RECORDED_LIMIT should be < 8 to fit into 3 bits of 17.26 // DataLayout::trap_bits. This dependency is enforced indirectly 17.27 // via asserts, to avoid excessive direct header-to-header dependencies. 17.28 @@ -279,7 +282,7 @@ 17.29 int trap_state); 17.30 17.31 static bool reason_is_recorded_per_bytecode(DeoptReason reason) { 17.32 - return reason > Reason_none && reason < Reason_RECORDED_LIMIT; 17.33 + return reason > Reason_none && reason <= Reason_RECORDED_LIMIT; 17.34 } 17.35 17.36 static DeoptReason reason_recorded_per_bytecode_if_any(DeoptReason reason) {
18.1 --- a/src/share/vm/runtime/globals.hpp Mon Feb 01 23:18:47 2010 +0100 18.2 +++ b/src/share/vm/runtime/globals.hpp Mon Feb 01 16:49:49 2010 -0800 18.3 @@ -2864,7 +2864,7 @@ 18.4 product(intx, PerMethodRecompilationCutoff, 400, \ 18.5 "After recompiling N times, stay in the interpreter (-1=>'Inf')") \ 18.6 \ 18.7 - product(intx, PerBytecodeRecompilationCutoff, 100, \ 18.8 + product(intx, PerBytecodeRecompilationCutoff, 200, \ 18.9 "Per-BCI limit on repeated recompilation (-1=>'Inf')") \ 18.10 \ 18.11 product(intx, PerMethodTrapLimit, 100, \