This commit is contained in:
Dean Long 2015-01-22 18:23:54 -05:00
commit eb08f7cb70
54 changed files with 614 additions and 241 deletions

View File

@ -1374,6 +1374,7 @@ void InterpreterMacroAssembler::verify_method_data_pointer() {
}
void InterpreterMacroAssembler::test_invocation_counter_for_mdp(Register invocation_count,
Register method_counters,
Register Rtmp,
Label &profile_continue) {
assert(ProfileInterpreter, "must be profiling interpreter");
@ -1386,9 +1387,8 @@ void InterpreterMacroAssembler::test_invocation_counter_for_mdp(Register invocat
br_notnull_short(ImethodDataPtr, Assembler::pn, done);
// Test to see if we should create a method data oop
AddressLiteral profile_limit((address) &InvocationCounter::InterpreterProfileLimit);
sethi(profile_limit, Rtmp);
ld(Rtmp, profile_limit.low10(), Rtmp);
Address profile_limit(method_counters, MethodCounters::interpreter_profile_limit_offset());
ld(profile_limit, Rtmp);
cmp(invocation_count, Rtmp);
// Use long branches because call_VM() code and following code generated by
// test_backedge_count_for_osr() is large in debug VM.
@ -2375,6 +2375,7 @@ void InterpreterMacroAssembler::increment_backedge_counter( Register Rcounters,
#ifndef CC_INTERP
void InterpreterMacroAssembler::test_backedge_count_for_osr( Register backedge_count,
Register method_counters,
Register branch_bcp,
Register Rtmp ) {
Label did_not_overflow;
@ -2382,8 +2383,8 @@ void InterpreterMacroAssembler::test_backedge_count_for_osr( Register backedge_c
assert_different_registers(backedge_count, Rtmp, branch_bcp);
assert(UseOnStackReplacement,"Must UseOnStackReplacement to test_backedge_count_for_osr");
AddressLiteral limit(&InvocationCounter::InterpreterBackwardBranchLimit);
load_contents(limit, Rtmp);
Address limit(method_counters, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset()));
ld(limit, Rtmp);
cmp_and_br_short(backedge_count, Rtmp, Assembler::lessUnsigned, Assembler::pt, did_not_overflow);
// When ProfileInterpreter is on, the backedge_count comes from the
@ -2500,17 +2501,13 @@ void InterpreterMacroAssembler::verify_FPU(int stack_depth, TosState state) {
// Jump if ((*counter_addr += increment) & mask) satisfies the condition.
void InterpreterMacroAssembler::increment_mask_and_jump(Address counter_addr,
int increment, int mask,
int increment, Address mask_addr,
Register scratch1, Register scratch2,
Condition cond, Label *where) {
ld(counter_addr, scratch1);
add(scratch1, increment, scratch1);
if (is_simm13(mask)) {
andcc(scratch1, mask, G0);
} else {
set(mask, scratch2);
andcc(scratch1, scratch2, G0);
}
ld(mask_addr, scratch2);
andcc(scratch1, scratch2, G0);
br(cond, false, Assembler::pn, *where);
delayed()->st(scratch1, counter_addr);
}

View File

@ -267,7 +267,7 @@ class InterpreterMacroAssembler: public MacroAssembler {
void increment_invocation_counter( Register Rcounters, Register Rtmp, Register Rtmp2 );
void increment_backedge_counter( Register Rcounters, Register Rtmp, Register Rtmp2 );
#ifndef CC_INTERP
void test_backedge_count_for_osr( Register backedge_count, Register branch_bcp, Register Rtmp );
void test_backedge_count_for_osr(Register backedge_count, Register method_counters, Register branch_bcp, Register Rtmp );
#endif /* CC_INTERP */
// Object locking
@ -280,7 +280,7 @@ class InterpreterMacroAssembler: public MacroAssembler {
void set_method_data_pointer_for_bcp();
void test_method_data_pointer(Label& zero_continue);
void verify_method_data_pointer();
void test_invocation_counter_for_mdp(Register invocation_count, Register Rtmp, Label &profile_continue);
void test_invocation_counter_for_mdp(Register invocation_count, Register method_counters, Register Rtmp, Label &profile_continue);
void set_mdp_data_at(int constant, Register value);
void increment_mdp_data_at(Address counter, Register bumped_count,
@ -291,7 +291,7 @@ class InterpreterMacroAssembler: public MacroAssembler {
Register bumped_count, Register scratch2,
bool decrement = false);
void increment_mask_and_jump(Address counter_addr,
int increment, int mask,
int increment, Address mask_addr,
Register scratch1, Register scratch2,
Condition cond, Label *where);
void set_mdp_flag_at(int flag_constant, Register scratch);

View File

@ -282,12 +282,11 @@ address TemplateInterpreterGenerator::generate_continuation_for(TosState state)
void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile_method, Label* profile_method_continue) {
// Note: In tiered we increment either counters in MethodCounters* or in
// MDO depending if we're profiling or not.
const Register Rcounters = G3_scratch;
const Register G3_method_counters = G3_scratch;
Label done;
if (TieredCompilation) {
const int increment = InvocationCounter::count_increment;
const int mask = ((1 << Tier0InvokeNotifyFreqLog) - 1) << InvocationCounter::count_shift;
Label no_mdo;
if (ProfileInterpreter) {
// If no method data exists, go to profile_continue.
@ -297,6 +296,7 @@ void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile
Address mdo_invocation_counter(G4_scratch,
in_bytes(MethodData::invocation_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
Address mask(G4_scratch, in_bytes(MethodData::invoke_mask_offset()));
__ increment_mask_and_jump(mdo_invocation_counter, increment, mask,
G3_scratch, Lscratch,
Assembler::zero, overflow);
@ -305,20 +305,21 @@ void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile
// Increment counter in MethodCounters*
__ bind(no_mdo);
Address invocation_counter(Rcounters,
Address invocation_counter(G3_method_counters,
in_bytes(MethodCounters::invocation_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
__ get_method_counters(Lmethod, Rcounters, done);
__ get_method_counters(Lmethod, G3_method_counters, done);
Address mask(G3_method_counters, in_bytes(MethodCounters::invoke_mask_offset()));
__ increment_mask_and_jump(invocation_counter, increment, mask,
G4_scratch, Lscratch,
Assembler::zero, overflow);
__ bind(done);
} else {
} else { // not TieredCompilation
// Update standard invocation counters
__ get_method_counters(Lmethod, Rcounters, done);
__ increment_invocation_counter(Rcounters, O0, G4_scratch);
__ get_method_counters(Lmethod, G3_method_counters, done);
__ increment_invocation_counter(G3_method_counters, O0, G4_scratch);
if (ProfileInterpreter) {
Address interpreter_invocation_counter(Rcounters,
Address interpreter_invocation_counter(G3_method_counters,
in_bytes(MethodCounters::interpreter_invocation_counter_offset()));
__ ld(interpreter_invocation_counter, G4_scratch);
__ inc(G4_scratch);
@ -327,16 +328,16 @@ void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile
if (ProfileInterpreter && profile_method != NULL) {
// Test to see if we should create a method data oop
AddressLiteral profile_limit((address)&InvocationCounter::InterpreterProfileLimit);
__ load_contents(profile_limit, G3_scratch);
__ cmp_and_br_short(O0, G3_scratch, Assembler::lessUnsigned, Assembler::pn, *profile_method_continue);
Address profile_limit(G3_method_counters, in_bytes(MethodCounters::interpreter_profile_limit_offset()));
__ ld(profile_limit, G1_scratch);
__ cmp_and_br_short(O0, G1_scratch, Assembler::lessUnsigned, Assembler::pn, *profile_method_continue);
// if no method data exists, go to profile_method
__ test_method_data_pointer(*profile_method);
}
AddressLiteral invocation_limit((address)&InvocationCounter::InterpreterInvocationLimit);
__ load_contents(invocation_limit, G3_scratch);
Address invocation_limit(G3_method_counters, in_bytes(MethodCounters::interpreter_invocation_limit_offset()));
__ ld(invocation_limit, G3_scratch);
__ cmp(O0, G3_scratch);
__ br(Assembler::greaterEqualUnsigned, false, Assembler::pn, *overflow); // Far distance
__ delayed()->nop();

View File

@ -1599,13 +1599,12 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
// Bump bytecode pointer by displacement (take the branch)
__ delayed()->add( O1_disp, Lbcp, Lbcp ); // add to bc addr
const Register Rcounters = G3_scratch;
__ get_method_counters(Lmethod, Rcounters, Lforward);
const Register G3_method_counters = G3_scratch;
__ get_method_counters(Lmethod, G3_method_counters, Lforward);
if (TieredCompilation) {
Label Lno_mdo, Loverflow;
int increment = InvocationCounter::count_increment;
int mask = ((1 << Tier0BackedgeNotifyFreqLog) - 1) << InvocationCounter::count_shift;
if (ProfileInterpreter) {
// If no method data exists, go to profile_continue.
__ ld_ptr(Lmethod, Method::method_data_offset(), G4_scratch);
@ -1614,6 +1613,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
// Increment backedge counter in the MDO
Address mdo_backedge_counter(G4_scratch, in_bytes(MethodData::backedge_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
Address mask(G4_scratch, in_bytes(MethodData::backedge_mask_offset()));
__ increment_mask_and_jump(mdo_backedge_counter, increment, mask, G3_scratch, O0,
Assembler::notZero, &Lforward);
__ ba_short(Loverflow);
@ -1621,9 +1621,10 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
// If there's no MDO, increment counter in MethodCounters*
__ bind(Lno_mdo);
Address backedge_counter(Rcounters,
Address backedge_counter(G3_method_counters,
in_bytes(MethodCounters::backedge_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
Address mask(G3_method_counters, in_bytes(MethodCounters::backedge_mask_offset()));
__ increment_mask_and_jump(backedge_counter, increment, mask, G4_scratch, O0,
Assembler::notZero, &Lforward);
__ bind(Loverflow);
@ -1663,18 +1664,19 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
__ jmp(O2, G0);
__ delayed()->nop();
} else {
} else { // not TieredCompilation
// Update Backedge branch separately from invocations
const Register G4_invoke_ctr = G4;
__ increment_backedge_counter(Rcounters, G4_invoke_ctr, G1_scratch);
__ increment_backedge_counter(G3_method_counters, G4_invoke_ctr, G1_scratch);
if (ProfileInterpreter) {
__ test_invocation_counter_for_mdp(G4_invoke_ctr, G3_scratch, Lforward);
__ test_invocation_counter_for_mdp(G4_invoke_ctr, G3_method_counters, G1_scratch, Lforward);
if (UseOnStackReplacement) {
__ test_backedge_count_for_osr(O2_bumped_count, l_cur_bcp, G3_scratch);
__ test_backedge_count_for_osr(O2_bumped_count, G3_method_counters, l_cur_bcp, G1_scratch);
}
} else {
if (UseOnStackReplacement) {
__ test_backedge_count_for_osr(G4_invoke_ctr, l_cur_bcp, G3_scratch);
__ test_backedge_count_for_osr(G4_invoke_ctr, G3_method_counters, l_cur_bcp, G1_scratch);
}
}
}

View File

@ -1360,7 +1360,7 @@ void InterpreterMacroAssembler::verify_FPU(int stack_depth, TosState state) {
// Jump if ((*counter_addr += increment) & mask) satisfies the condition.
void InterpreterMacroAssembler::increment_mask_and_jump(Address counter_addr,
int increment, int mask,
int increment, Address mask,
Register scratch, bool preloaded,
Condition cond, Label* where) {
if (!preloaded) {

View File

@ -182,7 +182,7 @@
void increment_mdp_data_at(Register mdp_in, Register reg, int constant,
bool decrement = false);
void increment_mask_and_jump(Address counter_addr,
int increment, int mask,
int increment, Address mask,
Register scratch, bool preloaded,
Condition cond, Label* where);
void set_mdp_flag_at(Register mdp_in, int flag_constant);

View File

@ -1426,7 +1426,7 @@ void InterpreterMacroAssembler::verify_FPU(int stack_depth, TosState state) {
// Jump if ((*counter_addr += increment) & mask) satisfies the condition.
void InterpreterMacroAssembler::increment_mask_and_jump(Address counter_addr,
int increment, int mask,
int increment, Address mask,
Register scratch, bool preloaded,
Condition cond, Label* where) {
if (!preloaded) {

View File

@ -191,7 +191,7 @@
void increment_mdp_data_at(Register mdp_in, Register reg, int constant,
bool decrement = false);
void increment_mask_and_jump(Address counter_addr,
int increment, int mask,
int increment, Address mask,
Register scratch, bool preloaded,
Condition cond, Label* where);
void set_mdp_flag_at(Register mdp_in, int flag_constant);

View File

@ -346,7 +346,6 @@ void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile
// depending if we're profiling or not.
if (TieredCompilation) {
int increment = InvocationCounter::count_increment;
int mask = ((1 << Tier0InvokeNotifyFreqLog) - 1) << InvocationCounter::count_shift;
Label no_mdo;
if (ProfileInterpreter) {
// Are we profiling?
@ -356,6 +355,7 @@ void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile
// Increment counter in the MDO
const Address mdo_invocation_counter(rax, in_bytes(MethodData::invocation_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
const Address mask(rax, in_bytes(MethodData::invoke_mask_offset()));
__ increment_mask_and_jump(mdo_invocation_counter, increment, mask, rcx, false, Assembler::zero, overflow);
__ jmp(done);
}
@ -366,11 +366,12 @@ void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile
InvocationCounter::counter_offset());
__ get_method_counters(rbx, rax, done);
const Address mask(rax, in_bytes(MethodCounters::invoke_mask_offset()));
__ increment_mask_and_jump(invocation_counter, increment, mask,
rcx, false, Assembler::zero, overflow);
__ bind(done);
} else {
const Address backedge_counter (rax,
} else { // not TieredCompilation
const Address backedge_counter(rax,
MethodCounters::backedge_counter_offset() +
InvocationCounter::counter_offset());
const Address invocation_counter(rax,
@ -400,16 +401,16 @@ void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile
if (ProfileInterpreter && profile_method != NULL) {
// Test to see if we should create a method data oop
__ cmp32(rcx,
ExternalAddress((address)&InvocationCounter::InterpreterProfileLimit));
__ movptr(rax, Address(rbx, Method::method_counters_offset()));
__ cmp32(rcx, Address(rax, in_bytes(MethodCounters::interpreter_profile_limit_offset())));
__ jcc(Assembler::less, *profile_method_continue);
// if no method data exists, go to profile_method
__ test_method_data_pointer(rax, *profile_method);
}
__ cmp32(rcx,
ExternalAddress((address)&InvocationCounter::InterpreterInvocationLimit));
__ movptr(rax, Address(rbx, Method::method_counters_offset()));
__ cmp32(rcx, Address(rax, in_bytes(MethodCounters::interpreter_invocation_limit_offset())));
__ jcc(Assembler::aboveEqual, *overflow);
__ bind(done);
}

View File

@ -299,7 +299,6 @@ void InterpreterGenerator::generate_counter_incr(
// Note: In tiered we increment either counters in Method* or in MDO depending if we're profiling or not.
if (TieredCompilation) {
int increment = InvocationCounter::count_increment;
int mask = ((1 << Tier0InvokeNotifyFreqLog) - 1) << InvocationCounter::count_shift;
Label no_mdo;
if (ProfileInterpreter) {
// Are we profiling?
@ -309,6 +308,7 @@ void InterpreterGenerator::generate_counter_incr(
// Increment counter in the MDO
const Address mdo_invocation_counter(rax, in_bytes(MethodData::invocation_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
const Address mask(rax, in_bytes(MethodData::invoke_mask_offset()));
__ increment_mask_and_jump(mdo_invocation_counter, increment, mask, rcx, false, Assembler::zero, overflow);
__ jmp(done);
}
@ -318,10 +318,11 @@ void InterpreterGenerator::generate_counter_incr(
MethodCounters::invocation_counter_offset() +
InvocationCounter::counter_offset());
__ get_method_counters(rbx, rax, done);
const Address mask(rax, in_bytes(MethodCounters::invoke_mask_offset()));
__ increment_mask_and_jump(invocation_counter, increment, mask, rcx,
false, Assembler::zero, overflow);
__ bind(done);
} else {
} else { // not TieredCompilation
const Address backedge_counter(rax,
MethodCounters::backedge_counter_offset() +
InvocationCounter::counter_offset());
@ -350,14 +351,16 @@ void InterpreterGenerator::generate_counter_incr(
if (ProfileInterpreter && profile_method != NULL) {
// Test to see if we should create a method data oop
__ cmp32(rcx, ExternalAddress((address)&InvocationCounter::InterpreterProfileLimit));
__ movptr(rax, Address(rbx, Method::method_counters_offset()));
__ cmp32(rcx, Address(rax, in_bytes(MethodCounters::interpreter_profile_limit_offset())));
__ jcc(Assembler::less, *profile_method_continue);
// if no method data exists, go to profile_method
__ test_method_data_pointer(rax, *profile_method);
}
__ cmp32(rcx, ExternalAddress((address)&InvocationCounter::InterpreterInvocationLimit));
__ movptr(rax, Address(rbx, Method::method_counters_offset()));
__ cmp32(rcx, Address(rax, in_bytes(MethodCounters::interpreter_invocation_limit_offset())));
__ jcc(Assembler::aboveEqual, *overflow);
__ bind(done);
}

View File

@ -1621,7 +1621,6 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
if (TieredCompilation) {
Label no_mdo;
int increment = InvocationCounter::count_increment;
int mask = ((1 << Tier0BackedgeNotifyFreqLog) - 1) << InvocationCounter::count_shift;
if (ProfileInterpreter) {
// Are we profiling?
__ movptr(rbx, Address(rcx, in_bytes(Method::method_data_offset())));
@ -1630,6 +1629,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
// Increment the MDO backedge counter
const Address mdo_backedge_counter(rbx, in_bytes(MethodData::backedge_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
const Address mask(rbx, in_bytes(MethodData::backedge_mask_offset()));
__ increment_mask_and_jump(mdo_backedge_counter, increment, mask,
rax, false, Assembler::zero, &backedge_counter_overflow);
__ jmp(dispatch);
@ -1637,9 +1637,10 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
__ bind(no_mdo);
// Increment backedge counter in MethodCounters*
__ movptr(rcx, Address(rcx, Method::method_counters_offset()));
const Address mask(rcx, in_bytes(MethodCounters::backedge_mask_offset()));
__ increment_mask_and_jump(Address(rcx, be_offset), increment, mask,
rax, false, Assembler::zero, &backedge_counter_overflow);
} else {
} else { // not TieredCompilation
// increment counter
__ movptr(rcx, Address(rcx, Method::method_counters_offset()));
__ movl(rax, Address(rcx, be_offset)); // load backedge counter
@ -1653,8 +1654,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
if (ProfileInterpreter) {
// Test to see if we should create a method data oop
__ cmp32(rax,
ExternalAddress((address) &InvocationCounter::InterpreterProfileLimit));
__ cmp32(rax, Address(rcx, in_bytes(MethodCounters::interpreter_profile_limit_offset())));
__ jcc(Assembler::less, dispatch);
// if no method data exists, go to profile method
@ -1662,8 +1662,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
if (UseOnStackReplacement) {
// check for overflow against rbx, which is the MDO taken count
__ cmp32(rbx,
ExternalAddress((address) &InvocationCounter::InterpreterBackwardBranchLimit));
__ cmp32(rbx, Address(rcx, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset())));
__ jcc(Assembler::below, dispatch);
// When ProfileInterpreter is on, the backedge_count comes from the
@ -1678,8 +1677,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
} else {
if (UseOnStackReplacement) {
// check for overflow against rax, which is the sum of the counters
__ cmp32(rax,
ExternalAddress((address) &InvocationCounter::InterpreterBackwardBranchLimit));
__ cmp32(rax, Address(rcx, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset())));
__ jcc(Assembler::aboveEqual, backedge_counter_overflow);
}

View File

@ -1642,7 +1642,6 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
if (TieredCompilation) {
Label no_mdo;
int increment = InvocationCounter::count_increment;
int mask = ((1 << Tier0BackedgeNotifyFreqLog) - 1) << InvocationCounter::count_shift;
if (ProfileInterpreter) {
// Are we profiling?
__ movptr(rbx, Address(rcx, in_bytes(Method::method_data_offset())));
@ -1651,6 +1650,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
// Increment the MDO backedge counter
const Address mdo_backedge_counter(rbx, in_bytes(MethodData::backedge_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
const Address mask(rbx, in_bytes(MethodData::backedge_mask_offset()));
__ increment_mask_and_jump(mdo_backedge_counter, increment, mask,
rax, false, Assembler::zero, &backedge_counter_overflow);
__ jmp(dispatch);
@ -1658,9 +1658,10 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
__ bind(no_mdo);
// Increment backedge counter in MethodCounters*
__ movptr(rcx, Address(rcx, Method::method_counters_offset()));
const Address mask(rcx, in_bytes(MethodCounters::backedge_mask_offset()));
__ increment_mask_and_jump(Address(rcx, be_offset), increment, mask,
rax, false, Assembler::zero, &backedge_counter_overflow);
} else {
} else { // not TieredCompilation
// increment counter
__ movptr(rcx, Address(rcx, Method::method_counters_offset()));
__ movl(rax, Address(rcx, be_offset)); // load backedge counter
@ -1674,8 +1675,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
if (ProfileInterpreter) {
// Test to see if we should create a method data oop
__ cmp32(rax,
ExternalAddress((address) &InvocationCounter::InterpreterProfileLimit));
__ cmp32(rax, Address(rcx, in_bytes(MethodCounters::interpreter_profile_limit_offset())));
__ jcc(Assembler::less, dispatch);
// if no method data exists, go to profile method
@ -1683,8 +1683,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
if (UseOnStackReplacement) {
// check for overflow against ebx which is the MDO taken count
__ cmp32(rbx,
ExternalAddress((address) &InvocationCounter::InterpreterBackwardBranchLimit));
__ cmp32(rbx, Address(rcx, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset())));
__ jcc(Assembler::below, dispatch);
// When ProfileInterpreter is on, the backedge_count comes
@ -1702,8 +1701,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
if (UseOnStackReplacement) {
// check for overflow against eax, which is the sum of the
// counters
__ cmp32(rax,
ExternalAddress((address) &InvocationCounter::InterpreterBackwardBranchLimit));
__ cmp32(rax, Address(rcx, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset())));
__ jcc(Assembler::aboveEqual, backedge_counter_overflow);
}

View File

@ -32,6 +32,7 @@
#include "ci/ciArrayKlass.hpp"
#include "ci/ciInstance.hpp"
#include "ci/ciObjArray.hpp"
#include "runtime/arguments.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/stubRoutines.hpp"
#include "runtime/vm_version.hpp"
@ -3351,7 +3352,12 @@ void LIRGenerator::do_ProfileInvoke(ProfileInvoke* x) {
if (!x->inlinee()->is_accessor()) {
CodeEmitInfo* info = state_for(x, x->state(), true);
// Notify the runtime very infrequently only to take care of counter overflows
increment_event_counter_impl(info, x->inlinee(), (1 << Tier23InlineeNotifyFreqLog) - 1, InvocationEntryBci, false, true);
int freq_log = Tier23InlineeNotifyFreqLog;
double scale;
if (_method->has_option_value("CompileThresholdScaling", scale)) {
freq_log = Arguments::scaled_freq_log(freq_log, scale);
}
increment_event_counter_impl(info, x->inlinee(), right_n_bits(freq_log), InvocationEntryBci, false, true);
}
}
@ -3366,7 +3372,11 @@ void LIRGenerator::increment_event_counter(CodeEmitInfo* info, int bci, bool bac
ShouldNotReachHere();
}
// Increment the appropriate invocation/backedge counter and notify the runtime.
increment_event_counter_impl(info, info->scope()->method(), (1 << freq_log) - 1, bci, backedge, true);
double scale;
if (_method->has_option_value("CompileThresholdScaling", scale)) {
freq_log = Arguments::scaled_freq_log(freq_log, scale);
}
increment_event_counter_impl(info, info->scope()->method(), right_n_bits(freq_log), bci, backedge, true);
}
void LIRGenerator::decrement_age(CodeEmitInfo* info) {

View File

@ -1470,7 +1470,9 @@ bool CompileBroker::compilation_is_prohibited(methodHandle method, int osr_bci,
// The method may be explicitly excluded by the user.
bool quietly;
if (CompilerOracle::should_exclude(method, quietly)) {
double scale;
if (CompilerOracle::should_exclude(method, quietly)
|| (CompilerOracle::has_option_value(method, "CompileThresholdScaling", scale) && scale == 0)) {
if (!quietly) {
// This does not happen quietly...
ResourceMark rm;

View File

@ -53,7 +53,7 @@
/*
* USELABELS - If using GCC, then use labels for the opcode dispatching
* rather -then a switch statement. This improves performance because it
* gives us the oportunity to have the instructions that calculate the
* gives us the opportunity to have the instructions that calculate the
* next opcode to jump to be intermixed with the rest of the instructions
* that implement the opcode (see UPDATE_PC_AND_TOS_AND_CONTINUE macro).
*/

View File

@ -36,7 +36,7 @@
// Implementation notes: For space reasons, state & counter are both encoded in one word,
// The state is encoded using some of the least significant bits, the counter is using the
// more significant bits. The counter is incremented before a method is activated and an
// action is triggered when when count() > limit().
// action is triggered when count() > limit().
class InvocationCounter VALUE_OBJ_CLASS_SPEC {
friend class VMStructs;
@ -48,7 +48,6 @@ class InvocationCounter VALUE_OBJ_CLASS_SPEC {
number_of_state_bits = 2,
number_of_carry_bits = 1,
number_of_noncount_bits = number_of_state_bits + number_of_carry_bits,
number_of_count_bits = BitsPerInt - number_of_noncount_bits,
state_limit = nth_bit(number_of_state_bits),
count_grain = nth_bit(number_of_state_bits + number_of_carry_bits),
carry_mask = right_n_bits(number_of_carry_bits) << number_of_state_bits,
@ -68,6 +67,7 @@ class InvocationCounter VALUE_OBJ_CLASS_SPEC {
count_increment = count_grain, // use this value to increment the 32bit _counter word
count_mask_value = count_mask, // use this value to mask the backedge counter
count_shift = number_of_noncount_bits,
number_of_count_bits = BitsPerInt - number_of_noncount_bits,
count_limit = nth_bit(number_of_count_bits - 1)
};

View File

@ -412,15 +412,14 @@ MethodCounters* Method::build_method_counters(Method* m, TRAPS) {
}
methodHandle mh(m);
ClassLoaderData* loader_data = mh->method_holder()->class_loader_data();
MethodCounters* counters = MethodCounters::allocate(loader_data, THREAD);
MethodCounters* counters = MethodCounters::allocate(mh, THREAD);
if (HAS_PENDING_EXCEPTION) {
CompileBroker::log_metaspace_failure();
ClassLoaderDataGraph::set_metaspace_oom(true);
return NULL; // return the exception (which is cleared)
}
if (!mh->init_method_counters(counters)) {
MetadataFactory::free_metadata(loader_data, counters);
MetadataFactory::free_metadata(mh->method_holder()->class_loader_data(), counters);
}
return mh->method_counters();
}

View File

@ -23,10 +23,11 @@
*/
#include "precompiled.hpp"
#include "oops/methodCounters.hpp"
#include "runtime/thread.inline.hpp"
#include "runtime/handles.inline.hpp"
MethodCounters* MethodCounters::allocate(ClassLoaderData* loader_data, TRAPS) {
return new(loader_data, size(), false, MetaspaceObj::MethodCountersType, THREAD) MethodCounters();
MethodCounters* MethodCounters::allocate(methodHandle mh, TRAPS) {
ClassLoaderData* loader_data = mh->method_holder()->class_loader_data();
return new(loader_data, size(), false, MetaspaceObj::MethodCountersType, THREAD) MethodCounters(mh);
}
void MethodCounters::clear_counters() {

View File

@ -26,7 +26,9 @@
#define SHARE_VM_OOPS_METHODCOUNTERS_HPP
#include "oops/metadata.hpp"
#include "compiler/compilerOracle.hpp"
#include "interpreter/invocationCounter.hpp"
#include "runtime/arguments.hpp"
class MethodCounters: public MetaspaceObj {
friend class VMStructs;
@ -45,7 +47,11 @@ class MethodCounters: public MetaspaceObj {
// 3. (INT_MIN..0] - method is hot and will deopt and get
// recompiled without the counters
int _nmethod_age;
int _interpreter_invocation_limit; // per-method InterpreterInvocationLimit
int _interpreter_backward_branch_limit; // per-method InterpreterBackwardBranchLimit
int _interpreter_profile_limit; // per-method InterpreterProfileLimit
int _invoke_mask; // per-method Tier0InvokeNotifyFreqLog
int _backedge_mask; // per-method Tier0BackedgeNotifyFreqLog
#ifdef TIERED
float _rate; // Events (invocation and backedge counter increments) per millisecond
jlong _prev_time; // Previous time the rate was acquired
@ -53,15 +59,15 @@ class MethodCounters: public MetaspaceObj {
u1 _highest_osr_comp_level; // Same for OSR level
#endif
MethodCounters() : _interpreter_invocation_count(0),
_interpreter_throwout_count(0),
_number_of_breakpoints(0),
_nmethod_age(INT_MAX)
MethodCounters(methodHandle mh) : _interpreter_invocation_count(0),
_interpreter_throwout_count(0),
_number_of_breakpoints(0),
_nmethod_age(INT_MAX)
#ifdef TIERED
, _rate(0),
_prev_time(0),
_highest_comp_level(0),
_highest_osr_comp_level(0)
, _rate(0),
_prev_time(0),
_highest_comp_level(0),
_highest_osr_comp_level(0)
#endif
{
invocation_counter()->init();
@ -70,10 +76,28 @@ class MethodCounters: public MetaspaceObj {
if (StressCodeAging) {
set_nmethod_age(HotMethodDetectionLimit);
}
// Set per-method thresholds.
double scale = 1.0;
CompilerOracle::has_option_value(mh, "CompileThresholdScaling", scale);
int compile_threshold = Arguments::scaled_compile_threshold(CompileThreshold, scale);
_interpreter_invocation_limit = compile_threshold << InvocationCounter::count_shift;
if (ProfileInterpreter) {
// If interpreter profiling is enabled, the backward branch limit
// is compared against the method data counter rather than an invocation
// counter, therefore no shifting of bits is required.
_interpreter_backward_branch_limit = (compile_threshold * (OnStackReplacePercentage - InterpreterProfilePercentage)) / 100;
} else {
_interpreter_backward_branch_limit = ((compile_threshold * OnStackReplacePercentage) / 100) << InvocationCounter::count_shift;
}
_interpreter_profile_limit = ((compile_threshold * InterpreterProfilePercentage) / 100) << InvocationCounter::count_shift;
_invoke_mask = right_n_bits(Arguments::scaled_freq_log(Tier0InvokeNotifyFreqLog, scale)) << InvocationCounter::count_shift;
_backedge_mask = right_n_bits(Arguments::scaled_freq_log(Tier0BackedgeNotifyFreqLog, scale)) << InvocationCounter::count_shift;
}
public:
static MethodCounters* allocate(ClassLoaderData* loader_data, TRAPS);
static MethodCounters* allocate(methodHandle mh, TRAPS);
void deallocate_contents(ClassLoaderData* loader_data) {}
DEBUG_ONLY(bool on_stack() { return false; }) // for template
@ -161,5 +185,24 @@ class MethodCounters: public MetaspaceObj {
return offset_of(MethodCounters, _interpreter_invocation_count);
}
static ByteSize interpreter_invocation_limit_offset() {
return byte_offset_of(MethodCounters, _interpreter_invocation_limit);
}
static ByteSize interpreter_backward_branch_limit_offset() {
return byte_offset_of(MethodCounters, _interpreter_backward_branch_limit);
}
static ByteSize interpreter_profile_limit_offset() {
return byte_offset_of(MethodCounters, _interpreter_profile_limit);
}
static ByteSize invoke_mask_offset() {
return byte_offset_of(MethodCounters, _invoke_mask);
}
static ByteSize backedge_mask_offset() {
return byte_offset_of(MethodCounters, _backedge_mask);
}
};
#endif //SHARE_VM_OOPS_METHODCOUNTERS_HPP

View File

@ -31,6 +31,7 @@
#include "memory/heapInspection.hpp"
#include "oops/methodData.hpp"
#include "prims/jvmtiRedefineClasses.hpp"
#include "runtime/arguments.hpp"
#include "runtime/compilationPolicy.hpp"
#include "runtime/deoptimization.hpp"
#include "runtime/handles.inline.hpp"
@ -1131,6 +1132,13 @@ void MethodData::init() {
_backedge_counter.init();
_invocation_counter_start = 0;
_backedge_counter_start = 0;
// Set per-method invoke- and backedge mask.
double scale = 1.0;
CompilerOracle::has_option_value(_method, "CompileThresholdScaling", scale);
_invoke_mask = right_n_bits(Arguments::scaled_freq_log(Tier0InvokeNotifyFreqLog, scale)) << InvocationCounter::count_shift;
_backedge_mask = right_n_bits(Arguments::scaled_freq_log(Tier0BackedgeNotifyFreqLog, scale)) << InvocationCounter::count_shift;
_tenure_traps = 0;
_num_loops = 0;
_num_blocks = 0;

View File

@ -2088,6 +2088,8 @@ private:
int _invocation_counter_start;
int _backedge_counter_start;
uint _tenure_traps;
int _invoke_mask; // per-method Tier0InvokeNotifyFreqLog
int _backedge_mask; // per-method Tier0BackedgeNotifyFreqLog
#if INCLUDE_RTM_OPT
// State of RTM code generation during compilation of the method
@ -2447,10 +2449,19 @@ public:
static ByteSize invocation_counter_offset() {
return byte_offset_of(MethodData, _invocation_counter);
}
static ByteSize backedge_counter_offset() {
return byte_offset_of(MethodData, _backedge_counter);
}
static ByteSize invoke_mask_offset() {
return byte_offset_of(MethodData, _invoke_mask);
}
static ByteSize backedge_mask_offset() {
return byte_offset_of(MethodData, _backedge_mask);
}
static ByteSize parameters_type_data_di_offset() {
return byte_offset_of(MethodData, _parameters_type_data_di);
}

View File

@ -582,6 +582,9 @@ void PhaseChaitin::Register_Allocate() {
// Peephole remove copies
post_allocate_copy_removal();
// Merge multidefs if multiple defs representing the same value are used in a single block.
merge_multidefs();
#ifdef ASSERT
// Veify the graph after RA.
verify(&live_arena);

View File

@ -681,6 +681,32 @@ private:
// Extend the node to LRG mapping
void add_reference( const Node *node, const Node *old_node);
// Record the first use of a def in the block for a register.
class RegDefUse {
Node* _def;
Node* _first_use;
public:
RegDefUse() : _def(NULL), _first_use(NULL) { }
Node* def() const { return _def; }
Node* first_use() const { return _first_use; }
void update(Node* def, Node* use) {
if (_def != def) {
_def = def;
_first_use = use;
}
}
void clear() {
_def = NULL;
_first_use = NULL;
}
};
typedef GrowableArray<RegDefUse> RegToDefUseMap;
int possibly_merge_multidef(Node *n, uint k, Block *block, RegToDefUseMap& reg2defuse);
// Merge nodes that are a part of a multidef lrg and produce the same value within a block.
void merge_multidefs();
private:
static int _final_loads, _final_stores, _final_copies, _final_memoves;

View File

@ -94,7 +94,7 @@ CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool
if (log != NULL) {
int rid = (receiver_count >= 0)? log->identify(profile.receiver(0)): -1;
int r2id = (rid != -1 && profile.has_receiver(1))? log->identify(profile.receiver(1)):-1;
log->begin_elem("call method='%d' count='%d' prof_factor='%g'",
log->begin_elem("call method='%d' count='%d' prof_factor='%f'",
log->identify(callee), site_count, prof_factor);
if (call_does_dispatch) log->print(" virtual='1'");
if (allow_inline) log->print(" inline='1'");

View File

@ -2010,14 +2010,9 @@ bool ConnectionGraph::is_oop_field(Node* n, int offset, bool* unsafe) {
bt = field->layout_type();
} else {
// Check for unsafe oop field access
for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
int opcode = n->fast_out(i)->Opcode();
if (opcode == Op_StoreP || opcode == Op_LoadP ||
opcode == Op_StoreN || opcode == Op_LoadN) {
bt = T_OBJECT;
(*unsafe) = true;
break;
}
if (n->has_out_with(Op_StoreP, Op_LoadP, Op_StoreN, Op_LoadN)) {
bt = T_OBJECT;
(*unsafe) = true;
}
}
} else if (adr_type->isa_aryptr()) {
@ -2031,13 +2026,8 @@ bool ConnectionGraph::is_oop_field(Node* n, int offset, bool* unsafe) {
}
} else if (adr_type->isa_rawptr() || adr_type->isa_klassptr()) {
// Allocation initialization, ThreadLocal field access, unsafe access
for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
int opcode = n->fast_out(i)->Opcode();
if (opcode == Op_StoreP || opcode == Op_LoadP ||
opcode == Op_StoreN || opcode == Op_LoadN) {
bt = T_OBJECT;
break;
}
if (n->has_out_with(Op_StoreP, Op_LoadP, Op_StoreN, Op_LoadN)) {
bt = T_OBJECT;
}
}
}
@ -3092,13 +3082,7 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist)
continue;
} else if (n->Opcode() == Op_EncodeISOArray) {
// get the memory projection
for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
Node *use = n->fast_out(i);
if (use->Opcode() == Op_SCMemProj) {
n = use;
break;
}
}
n = n->find_out_with(Op_SCMemProj);
assert(n->Opcode() == Op_SCMemProj, "memory projection required");
} else {
assert(n->is_Mem(), "memory node required.");
@ -3122,13 +3106,7 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist)
continue; // don't push users
} else if (n->is_LoadStore()) {
// get the memory projection
for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
Node *use = n->fast_out(i);
if (use->Opcode() == Op_SCMemProj) {
n = use;
break;
}
}
n = n->find_out_with(Op_SCMemProj);
assert(n->Opcode() == Op_SCMemProj, "memory projection required");
}
}

View File

@ -535,12 +535,8 @@ bool PhaseChaitin::remove_node_if_not_used(Block* b, uint location, Node* n, uin
// The method add_input_to_liveout() keeps such nodes alive (put them on liveout list)
// when it sees SCMemProj node in a block. Unfortunately SCMemProj node could be placed
// in block in such order that KILL MachProj nodes are processed first.
uint cnt = def->outcnt();
for (uint i = 0; i < cnt; i++) {
Node* proj = def->raw_out(i);
if (proj->Opcode() == Op_SCMemProj) {
return false;
}
if (def->has_out_with(Op_SCMemProj)) {
return false;
}
}
b->remove_node(location);

View File

@ -2057,10 +2057,9 @@ void PhaseIdealLoop::do_range_check( IdealLoopTree *loop, Node_List &old_new ) {
}
Node *main_cmp = main_bol->in(1);
if( main_cmp->outcnt() > 1 ) { // CmpNode shared?
_igvn.hash_delete(main_bol);
main_cmp = main_cmp->clone();// Clone a private CmpNode
register_new_node( main_cmp, main_cle->in(0) );
main_bol->set_req(1,main_cmp);
_igvn.replace_input_of(main_bol, 1, main_cmp);
}
// Hack the now-private loop bounds
_igvn.replace_input_of(main_cmp, 2, main_limit);

View File

@ -616,6 +616,29 @@ public:
#endif
};
// MachMergeNode is similar to a PhiNode in a sense it merges multiple values,
// however it doesn't have a control input and is more like a MergeMem.
// It is inserted after the register allocation is done to ensure that nodes use single
// definition of a multidef lrg in a block.
class MachMergeNode : public MachIdealNode {
public:
MachMergeNode(Node *n1) {
init_class_id(Class_MachMerge);
add_req(NULL);
add_req(n1);
}
virtual const RegMask &out_RegMask() const { return in(1)->out_RegMask(); }
virtual const RegMask &in_RegMask(uint idx) const { return in(1)->in_RegMask(idx); }
virtual const class Type *bottom_type() const { return in(1)->bottom_type(); }
virtual uint ideal_reg() const { return bottom_type()->ideal_reg(); }
virtual uint oper_input_base() const { return 1; }
virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { }
virtual uint size(PhaseRegAlloc *ra_) const { return 0; }
#ifndef PRODUCT
virtual const char *Name() const { return "MachMerge"; }
#endif
};
//------------------------------MachBranchNode--------------------------------
// Abstract machine branch Node
class MachBranchNode : public MachIdealNode {

View File

@ -258,14 +258,7 @@ void PhaseMacroExpand::eliminate_card_mark(Node* p2x) {
// Search for CastP2X->Xor->URShift->Cmp path which
// checks if the store done to a different from the value's region.
// And replace Cmp with #0 (false) to collapse G1 post barrier.
Node* xorx = NULL;
for (DUIterator_Fast imax, i = p2x->fast_outs(imax); i < imax; i++) {
Node* u = p2x->fast_out(i);
if (u->Opcode() == Op_XorX) {
xorx = u;
break;
}
}
Node* xorx = p2x->find_out_with(Op_XorX);
assert(xorx != NULL, "missing G1 post barrier");
Node* shift = xorx->unique_out();
Node* cmpx = shift->unique_out();

View File

@ -2609,7 +2609,6 @@ bool StoreNode::value_never_loaded( PhaseTransform *phase) const {
return false; // if not a distinct instance, there may be aliases of the address
for (DUIterator_Fast imax, i = adr->fast_outs(imax); i < imax; i++) {
Node *use = adr->fast_out(i);
int opc = use->Opcode();
if (use->is_Load() || use->is_LoadStore()) {
return false;
}

View File

@ -881,6 +881,34 @@ Node* Node::uncast() const {
return (Node*) this;
}
// Find out of current node that matches opcode.
Node* Node::find_out_with(int opcode) {
for (DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++) {
Node* use = fast_out(i);
if (use->Opcode() == opcode) {
return use;
}
}
return NULL;
}
// Return true if the current node has an out that matches opcode.
bool Node::has_out_with(int opcode) {
return (find_out_with(opcode) != NULL);
}
// Return true if the current node has an out that matches any of the opcodes.
bool Node::has_out_with(int opcode1, int opcode2, int opcode3, int opcode4) {
for (DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++) {
int opcode = fast_out(i)->Opcode();
if (opcode == opcode1 || opcode == opcode2 || opcode == opcode3 || opcode == opcode4) {
return true;
}
}
return false;
}
//---------------------------uncast_helper-------------------------------------
Node* Node::uncast_helper(const Node* p) {
#ifdef ASSERT

View File

@ -98,6 +98,7 @@ class MachReturnNode;
class MachSafePointNode;
class MachSpillCopyNode;
class MachTempNode;
class MachMergeNode;
class Matcher;
class MemBarNode;
class MemBarStoreStoreNode;
@ -436,6 +437,13 @@ protected:
return (this->uncast() == n->uncast());
}
// Find out of current node that matches opcode.
Node* find_out_with(int opcode);
// Return true if the current node has an out that matches opcode.
bool has_out_with(int opcode);
// Return true if the current node has an out that matches any of the opcodes.
bool has_out_with(int opcode1, int opcode2, int opcode3, int opcode4);
private:
static Node* uncast_helper(const Node* n);
@ -507,18 +515,25 @@ public:
//----------------- Other Node Properties
// Generate class id for some ideal nodes to avoid virtual query
// methods is_<Node>().
// Class id is the set of bits corresponded to the node class and all its
// super classes so that queries for super classes are also valid.
// Subclasses of the same super class have different assigned bit
// (the third parameter in the macro DEFINE_CLASS_ID).
// Classes with deeper hierarchy are declared first.
// Classes with the same hierarchy depth are sorted by usage frequency.
// Generate class IDs for (some) ideal nodes so that it is possible to determine
// the type of a node using a non-virtual method call (the method is_<Node>() below).
//
// The query method masks the bits to cut off bits of subclasses
// and then compare the result with the class id
// (see the macro DEFINE_CLASS_QUERY below).
// A class ID of an ideal node is a set of bits. In a class ID, a single bit determines
// the type of the node the ID represents; another subset of an ID's bits are reserved
// for the superclasses of the node represented by the ID.
//
// By design, if A is a supertype of B, A.is_B() returns true and B.is_A()
// returns false. A.is_A() returns true.
//
// If two classes, A and B, have the same superclass, a different bit of A's class id
// is reserved for A's type than for B's type. That bit is specified by the third
// parameter in the macro DEFINE_CLASS_ID.
//
// By convention, classes with deeper hierarchy are declared first. Moreover,
// classes with the same hierarchy depth are sorted by usage frequency.
//
// The query method masks the bits to cut off bits of subclasses and then compares
// the result with the class id (see the macro DEFINE_CLASS_QUERY below).
//
// Class_MachCall=30, ClassMask_MachCall=31
// 12 8 4 0
@ -592,6 +607,7 @@ public:
DEFINE_CLASS_ID(MachTemp, Mach, 3)
DEFINE_CLASS_ID(MachConstantBase, Mach, 4)
DEFINE_CLASS_ID(MachConstant, Mach, 5)
DEFINE_CLASS_ID(MachMerge, Mach, 6)
DEFINE_CLASS_ID(Type, Node, 2)
DEFINE_CLASS_ID(Phi, Type, 0)
@ -763,6 +779,7 @@ public:
DEFINE_CLASS_QUERY(MachSafePoint)
DEFINE_CLASS_QUERY(MachSpillCopy)
DEFINE_CLASS_QUERY(MachTemp)
DEFINE_CLASS_QUERY(MachMerge)
DEFINE_CLASS_QUERY(Mem)
DEFINE_CLASS_QUERY(MemBar)
DEFINE_CLASS_QUERY(MemBarStoreStore)

View File

@ -441,7 +441,7 @@ Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses)
CompileLog* log = C->log();
if (log != NULL) {
log->begin_head("parse method='%d' uses='%g'",
log->begin_head("parse method='%d' uses='%f'",
log->identify(parse_method), expected_uses);
if (depth() == 1 && C->is_osr_compilation()) {
log->print(" osr_bci='%d'", C->entry_bci());

View File

@ -832,7 +832,7 @@ float Parse::dynamic_branch_prediction(float &cnt) {
sprintf(prob_str_buf, "%g", prob);
prob_str = prob_str_buf;
}
C->log()->elem("branch target_bci='%d' taken='%d' not_taken='%d' cnt='%g' prob='%s'",
C->log()->elem("branch target_bci='%d' taken='%d' not_taken='%d' cnt='%f' prob='%s'",
iter().get_dest(), taken, not_taken, cnt, prob_str);
}
return prob;

View File

@ -110,6 +110,7 @@ void Phase::print_timers() {
tty->print_cr (" Compute Liveness: %7.3f s", timers[_t_computeLive].seconds());
tty->print_cr (" Regalloc Split: %7.3f s", timers[_t_regAllocSplit].seconds());
tty->print_cr (" Postalloc Copy Rem: %7.3f s", timers[_t_postAllocCopyRemoval].seconds());
tty->print_cr (" Merge multidefs: %7.3f s", timers[_t_mergeMultidefs].seconds());
tty->print_cr (" Fixup Spills: %7.3f s", timers[_t_fixupSpills].seconds());
tty->print_cr (" Compact: %7.3f s", timers[_t_chaitinCompact].seconds());
tty->print_cr (" Coalesce 1: %7.3f s", timers[_t_chaitinCoalesce1].seconds());
@ -126,6 +127,7 @@ void Phase::print_timers() {
timers[_t_computeLive].seconds() +
timers[_t_regAllocSplit].seconds() +
timers[_t_postAllocCopyRemoval].seconds() +
timers[_t_mergeMultidefs].seconds() +
timers[_t_fixupSpills].seconds() +
timers[_t_chaitinCompact].seconds() +
timers[_t_chaitinCoalesce1].seconds() +

View File

@ -88,6 +88,7 @@ public:
_t_computeLive,
_t_regAllocSplit,
_t_postAllocCopyRemoval,
_t_mergeMultidefs,
_t_fixupSpills,
_t_chaitinCompact,
_t_chaitinCoalesce1,

View File

@ -263,20 +263,6 @@ int PhaseChaitin::elide_copy( Node *n, int k, Block *current_block, Node_List &v
// intermediate copies might be illegal, i.e., value is stored down to stack
// then reloaded BUT survives in a register the whole way.
Node *val = skip_copies(n->in(k));
if (val == x && nk_idx != 0 &&
regnd[nk_reg] != NULL && regnd[nk_reg] != x &&
_lrg_map.live_range_id(x) == _lrg_map.live_range_id(regnd[nk_reg])) {
// When rematerialzing nodes and stretching lifetimes, the
// allocator will reuse the original def for multidef LRG instead
// of the current reaching def because it can't know it's safe to
// do so. After allocation completes if they are in the same LRG
// then it should use the current reaching def instead.
n->set_req(k, regnd[nk_reg]);
blk_adjust += yank_if_dead(val, current_block, &value, &regnd);
val = skip_copies(n->in(k));
}
if (val == x) return blk_adjust; // No progress?
int n_regs = RegMask::num_registers(val->ideal_reg());
@ -382,6 +368,94 @@ bool PhaseChaitin::eliminate_copy_of_constant(Node* val, Node* n,
return false;
}
// The algorithms works as follows:
// We traverse the block top to bottom. possibly_merge_multidef() is invoked for every input edge k
// of the instruction n. We check to see if the input is a multidef lrg. If it is, we record the fact that we've
// seen a definition (coming as an input) and add that fact to the reg2defuse array. The array maps registers to their
// current reaching definitions (we track only multidefs though). With each definition we also associate the first
// instruction we saw use it. If we encounter the situation when we observe an def (an input) that is a part of the
// same lrg but is different from the previous seen def we merge the two with a MachMerge node and substitute
// all the uses that we've seen so far to use the merge. After that we keep replacing the new defs in the same lrg
// as they get encountered with the merge node and keep adding these defs to the merge inputs.
void PhaseChaitin::merge_multidefs() {
Compile::TracePhase tp("mergeMultidefs", &timers[_t_mergeMultidefs]);
ResourceMark rm;
// Keep track of the defs seen in registers and collect their uses in the block.
RegToDefUseMap reg2defuse(_max_reg, _max_reg, RegDefUse());
for (uint i = 0; i < _cfg.number_of_blocks(); i++) {
Block* block = _cfg.get_block(i);
for (uint j = 1; j < block->number_of_nodes(); j++) {
Node* n = block->get_node(j);
if (n->is_Phi()) continue;
for (uint k = 1; k < n->req(); k++) {
j += possibly_merge_multidef(n, k, block, reg2defuse);
}
// Null out the value produced by the instruction itself, since we're only interested in defs
// implicitly defined by the uses. We are actually interested in tracking only redefinitions
// of the multidef lrgs in the same register. For that matter it's enough to track changes in
// the base register only and ignore other effects of multi-register lrgs and fat projections.
// It is also ok to ignore defs coming from singledefs. After an implicit overwrite by one of
// those our register is guaranteed to be used by another lrg and we won't attempt to merge it.
uint lrg = _lrg_map.live_range_id(n);
if (lrg > 0 && lrgs(lrg).is_multidef()) {
OptoReg::Name reg = lrgs(lrg).reg();
reg2defuse.at(reg).clear();
}
}
// Clear reg->def->use tracking for the next block
for (int j = 0; j < reg2defuse.length(); j++) {
reg2defuse.at(j).clear();
}
}
}
int PhaseChaitin::possibly_merge_multidef(Node *n, uint k, Block *block, RegToDefUseMap& reg2defuse) {
int blk_adjust = 0;
uint lrg = _lrg_map.live_range_id(n->in(k));
if (lrg > 0 && lrgs(lrg).is_multidef()) {
OptoReg::Name reg = lrgs(lrg).reg();
Node* def = reg2defuse.at(reg).def();
if (def != NULL && lrg == _lrg_map.live_range_id(def) && def != n->in(k)) {
// Same lrg but different node, we have to merge.
MachMergeNode* merge;
if (def->is_MachMerge()) { // is it already a merge?
merge = def->as_MachMerge();
} else {
merge = new MachMergeNode(def);
// Insert the merge node into the block before the first use.
uint use_index = block->find_node(reg2defuse.at(reg).first_use());
block->insert_node(merge, use_index++);
// Let the allocator know about the new node, use the same lrg
_lrg_map.extend(merge->_idx, lrg);
blk_adjust++;
// Fixup all the uses (there is at least one) that happened between the first
// use and before the current one.
for (; use_index < block->number_of_nodes(); use_index++) {
Node* use = block->get_node(use_index);
if (use == n) {
break;
}
use->replace_edge(def, merge);
}
}
if (merge->find_edge(n->in(k)) == -1) {
merge->add_req(n->in(k));
}
n->set_req(k, merge);
}
// update the uses
reg2defuse.at(reg).update(n->in(k), n);
}
return blk_adjust;
}
//------------------------------post_allocate_copy_removal---------------------
// Post-Allocation peephole copy removal. We do this in 1 pass over the

View File

@ -1507,10 +1507,12 @@ void PhaseStringOpts::replace_string_concat(StringConcat* sc) {
}
case StringConcat::StringMode: {
const Type* type = kit.gvn().type(arg);
Node* count = NULL;
if (type == TypePtr::NULL_PTR) {
// replace the argument with the null checked version
arg = null_string;
sc->set_argument(argi, arg);
count = kit.load_String_length(kit.control(), arg);
} else if (!type->higher_equal(TypeInstPtr::NOTNULL)) {
// s = s != null ? s : "null";
// length = length + (s.count - s.offset);
@ -1533,10 +1535,13 @@ void PhaseStringOpts::replace_string_concat(StringConcat* sc) {
// replace the argument with the null checked version
arg = phi;
sc->set_argument(argi, arg);
count = kit.load_String_length(kit.control(), arg);
} else {
// A corresponding nullcheck will be connected during IGVN MemNode::Ideal_common_DU_postCCP
// kit.control might be a different test, that can be hoisted above the actual nullcheck
// in case, that the control input is not null, Ideal_common_DU_postCCP will not look for a nullcheck.
count = kit.load_String_length(NULL, arg);
}
Node* count = kit.load_String_length(kit.control(), arg);
length = __ AddI(length, count);
string_sizes->init_req(argi, NULL);
break;

View File

@ -155,7 +155,7 @@ bool AdvancedThresholdPolicy::is_method_profiled(Method* method) {
if (mdo != NULL) {
int i = mdo->invocation_count_delta();
int b = mdo->backedge_count_delta();
return call_predicate_helper<CompLevel_full_profile>(i, b, 1);
return call_predicate_helper<CompLevel_full_profile>(i, b, 1, method);
}
return false;
}
@ -229,32 +229,32 @@ double AdvancedThresholdPolicy::threshold_scale(CompLevel level, int feedback_k)
// Tier?LoadFeedback is basically a coefficient that determines of
// how many methods per compiler thread can be in the queue before
// the threshold values double.
bool AdvancedThresholdPolicy::loop_predicate(int i, int b, CompLevel cur_level) {
bool AdvancedThresholdPolicy::loop_predicate(int i, int b, CompLevel cur_level, Method* method) {
switch(cur_level) {
case CompLevel_none:
case CompLevel_limited_profile: {
double k = threshold_scale(CompLevel_full_profile, Tier3LoadFeedback);
return loop_predicate_helper<CompLevel_none>(i, b, k);
return loop_predicate_helper<CompLevel_none>(i, b, k, method);
}
case CompLevel_full_profile: {
double k = threshold_scale(CompLevel_full_optimization, Tier4LoadFeedback);
return loop_predicate_helper<CompLevel_full_profile>(i, b, k);
return loop_predicate_helper<CompLevel_full_profile>(i, b, k, method);
}
default:
return true;
}
}
bool AdvancedThresholdPolicy::call_predicate(int i, int b, CompLevel cur_level) {
bool AdvancedThresholdPolicy::call_predicate(int i, int b, CompLevel cur_level, Method* method) {
switch(cur_level) {
case CompLevel_none:
case CompLevel_limited_profile: {
double k = threshold_scale(CompLevel_full_profile, Tier3LoadFeedback);
return call_predicate_helper<CompLevel_none>(i, b, k);
return call_predicate_helper<CompLevel_none>(i, b, k, method);
}
case CompLevel_full_profile: {
double k = threshold_scale(CompLevel_full_optimization, Tier4LoadFeedback);
return call_predicate_helper<CompLevel_full_profile>(i, b, k);
return call_predicate_helper<CompLevel_full_profile>(i, b, k, method);
}
default:
return true;
@ -271,7 +271,7 @@ bool AdvancedThresholdPolicy::should_create_mdo(Method* method, CompLevel cur_le
int i = method->invocation_count();
int b = method->backedge_count();
double k = Tier0ProfilingStartPercentage / 100.0;
return call_predicate_helper<CompLevel_none>(i, b, k) || loop_predicate_helper<CompLevel_none>(i, b, k);
return call_predicate_helper<CompLevel_none>(i, b, k, method) || loop_predicate_helper<CompLevel_none>(i, b, k, method);
}
return false;
}
@ -348,7 +348,7 @@ CompLevel AdvancedThresholdPolicy::common(Predicate p, Method* method, CompLevel
// If we were at full profile level, would we switch to full opt?
if (common(p, method, CompLevel_full_profile, disable_feedback) == CompLevel_full_optimization) {
next_level = CompLevel_full_optimization;
} else if ((this->*p)(i, b, cur_level)) {
} else if ((this->*p)(i, b, cur_level, method)) {
// C1-generated fully profiled code is about 30% slower than the limited profile
// code that has only invocation and backedge counters. The observation is that
// if C2 queue is large enough we can spend too much time in the fully profiled code
@ -374,7 +374,7 @@ CompLevel AdvancedThresholdPolicy::common(Predicate p, Method* method, CompLevel
if (mdo->would_profile()) {
if (disable_feedback || (CompileBroker::queue_size(CompLevel_full_optimization) <=
Tier3DelayOff * compiler_count(CompLevel_full_optimization) &&
(this->*p)(i, b, cur_level))) {
(this->*p)(i, b, cur_level, method))) {
next_level = CompLevel_full_profile;
}
} else {
@ -390,7 +390,7 @@ CompLevel AdvancedThresholdPolicy::common(Predicate p, Method* method, CompLevel
if (mdo->would_profile()) {
int mdo_i = mdo->invocation_count_delta();
int mdo_b = mdo->backedge_count_delta();
if ((this->*p)(mdo_i, mdo_b, cur_level)) {
if ((this->*p)(mdo_i, mdo_b, cur_level, method)) {
next_level = CompLevel_full_optimization;
}
} else {

View File

@ -84,7 +84,7 @@ class CompileQueue;
* invocation and backedge notifications. Basically every n-th invocation or backedge a mutator thread
* makes a call into the runtime.
*
* - Tier?CompileThreshold, Tier?BackEdgeThreshold, Tier?MinInvocationThreshold control
* - Tier?InvocationThreshold, Tier?CompileThreshold, Tier?BackEdgeThreshold, Tier?MinInvocationThreshold control
* compilation thresholds.
* Level 2 thresholds are not used and are provided for option-compatibility and potential future use.
* Other thresholds work as follows:
@ -100,7 +100,9 @@ class CompileQueue;
* The same predicate is used to control the transition from level 3 to level 4 (C2). It should be
* noted though that the thresholds are relative. Moreover i and b for the 0->3 transition come
* from Method* and for 3->4 transition they come from MDO (since profiled invocations are
* counted separately).
* counted separately). Finally, if a method does not contain anything worth profiling, a transition
* from level 3 to level 4 occurs without considering thresholds (e.g., with fewer invocations than
* what is specified by Tier4InvocationThreshold).
*
* OSR transitions are controlled simply with b > TierXBackEdgeThreshold * s predicates.
*
@ -164,9 +166,9 @@ class AdvancedThresholdPolicy : public SimpleThresholdPolicy {
// Call and loop predicates determine whether a transition to a higher compilation
// level should be performed (pointers to predicate functions are passed to common().
// Predicates also take compiler load into account.
typedef bool (AdvancedThresholdPolicy::*Predicate)(int i, int b, CompLevel cur_level);
bool call_predicate(int i, int b, CompLevel cur_level);
bool loop_predicate(int i, int b, CompLevel cur_level);
typedef bool (AdvancedThresholdPolicy::*Predicate)(int i, int b, CompLevel cur_level, Method* method);
bool call_predicate(int i, int b, CompLevel cur_level, Method* method);
bool loop_predicate(int i, int b, CompLevel cur_level, Method* method);
// Common transition function. Given a predicate determines if a method should transition to another level.
CompLevel common(Predicate p, Method* method, CompLevel cur_level, bool disable_feedback = false);
// Transition functions.

View File

@ -1126,16 +1126,35 @@ static void no_shared_spaces(const char* message) {
}
#endif
// Returns threshold scaled with CompileThresholdScaling
intx Arguments::get_scaled_compile_threshold(intx threshold) {
return (intx)(threshold * CompileThresholdScaling);
intx Arguments::scaled_compile_threshold(intx threshold, double scale) {
if (scale == 1.0 || scale < 0.0) {
return threshold;
} else {
return (intx)(threshold * scale);
}
}
// Returns freq_log scaled with CompileThresholdScaling
intx Arguments::get_scaled_freq_log(intx freq_log) {
intx scaled_freq = get_scaled_compile_threshold((intx)1 << freq_log);
if (scaled_freq == 0) {
return 0;
intx Arguments::scaled_freq_log(intx freq_log, double scale) {
// Check if scaling is necessary or negative value was specified.
if (scale == 1.0 || scale < 0.0) {
return freq_log;
}
// Check value to avoid calculating log2 of 0.
if (scale == 0.0) {
return 1;
}
intx scaled_freq = scaled_compile_threshold((intx)1 << freq_log, scale);
// Determine the maximum notification frequency value currently supported.
// The largest mask value that the interpreter/C1 can handle is
// of length InvocationCounter::number_of_count_bits. Mask values are always
// one bit shorter then the value of the notification frequency. Set
// max_freq_bits accordingly.
intx max_freq_bits = InvocationCounter::number_of_count_bits + 1;
if (scaled_freq > nth_bit(max_freq_bits)) {
return max_freq_bits;
} else {
return log2_intptr(scaled_freq);
}
@ -1180,31 +1199,36 @@ void Arguments::set_tiered_flags() {
Tier3InvokeNotifyFreqLog = 0;
Tier4InvocationThreshold = 0;
}
if (CompileThresholdScaling < 0) {
vm_exit_during_initialization("Negative value specified for CompileThresholdScaling", NULL);
}
// Scale tiered compilation thresholds
if (!FLAG_IS_DEFAULT(CompileThresholdScaling)) {
FLAG_SET_ERGO(intx, Tier0InvokeNotifyFreqLog, get_scaled_freq_log(Tier0InvokeNotifyFreqLog));
FLAG_SET_ERGO(intx, Tier0BackedgeNotifyFreqLog, get_scaled_freq_log(Tier0BackedgeNotifyFreqLog));
FLAG_SET_ERGO(intx, Tier0InvokeNotifyFreqLog, scaled_freq_log(Tier0InvokeNotifyFreqLog));
FLAG_SET_ERGO(intx, Tier0BackedgeNotifyFreqLog, scaled_freq_log(Tier0BackedgeNotifyFreqLog));
FLAG_SET_ERGO(intx, Tier3InvocationThreshold, get_scaled_compile_threshold(Tier3InvocationThreshold));
FLAG_SET_ERGO(intx, Tier3MinInvocationThreshold, get_scaled_compile_threshold(Tier3MinInvocationThreshold));
FLAG_SET_ERGO(intx, Tier3CompileThreshold, get_scaled_compile_threshold(Tier3CompileThreshold));
FLAG_SET_ERGO(intx, Tier3BackEdgeThreshold, get_scaled_compile_threshold(Tier3BackEdgeThreshold));
FLAG_SET_ERGO(intx, Tier3InvocationThreshold, scaled_compile_threshold(Tier3InvocationThreshold));
FLAG_SET_ERGO(intx, Tier3MinInvocationThreshold, scaled_compile_threshold(Tier3MinInvocationThreshold));
FLAG_SET_ERGO(intx, Tier3CompileThreshold, scaled_compile_threshold(Tier3CompileThreshold));
FLAG_SET_ERGO(intx, Tier3BackEdgeThreshold, scaled_compile_threshold(Tier3BackEdgeThreshold));
// Tier2{Invocation,MinInvocation,Compile,Backedge}Threshold should be scaled here
// once these thresholds become supported.
FLAG_SET_ERGO(intx, Tier2InvokeNotifyFreqLog, get_scaled_freq_log(Tier2InvokeNotifyFreqLog));
FLAG_SET_ERGO(intx, Tier2BackedgeNotifyFreqLog, get_scaled_freq_log(Tier2BackedgeNotifyFreqLog));
FLAG_SET_ERGO(intx, Tier2InvokeNotifyFreqLog, scaled_freq_log(Tier2InvokeNotifyFreqLog));
FLAG_SET_ERGO(intx, Tier2BackedgeNotifyFreqLog, scaled_freq_log(Tier2BackedgeNotifyFreqLog));
FLAG_SET_ERGO(intx, Tier3InvokeNotifyFreqLog, get_scaled_freq_log(Tier3InvokeNotifyFreqLog));
FLAG_SET_ERGO(intx, Tier3BackedgeNotifyFreqLog, get_scaled_freq_log(Tier3BackedgeNotifyFreqLog));
FLAG_SET_ERGO(intx, Tier3InvokeNotifyFreqLog, scaled_freq_log(Tier3InvokeNotifyFreqLog));
FLAG_SET_ERGO(intx, Tier3BackedgeNotifyFreqLog, scaled_freq_log(Tier3BackedgeNotifyFreqLog));
FLAG_SET_ERGO(intx, Tier23InlineeNotifyFreqLog, get_scaled_freq_log(Tier23InlineeNotifyFreqLog));
FLAG_SET_ERGO(intx, Tier23InlineeNotifyFreqLog, scaled_freq_log(Tier23InlineeNotifyFreqLog));
FLAG_SET_ERGO(intx, Tier4InvocationThreshold, get_scaled_compile_threshold(Tier4InvocationThreshold));
FLAG_SET_ERGO(intx, Tier4MinInvocationThreshold, get_scaled_compile_threshold(Tier4MinInvocationThreshold));
FLAG_SET_ERGO(intx, Tier4CompileThreshold, get_scaled_compile_threshold(Tier4CompileThreshold));
FLAG_SET_ERGO(intx, Tier4BackEdgeThreshold, get_scaled_compile_threshold(Tier4BackEdgeThreshold));
FLAG_SET_ERGO(intx, Tier4InvocationThreshold, scaled_compile_threshold(Tier4InvocationThreshold));
FLAG_SET_ERGO(intx, Tier4MinInvocationThreshold, scaled_compile_threshold(Tier4MinInvocationThreshold));
FLAG_SET_ERGO(intx, Tier4CompileThreshold, scaled_compile_threshold(Tier4CompileThreshold));
FLAG_SET_ERGO(intx, Tier4BackEdgeThreshold, scaled_compile_threshold(Tier4BackEdgeThreshold));
}
}
@ -3456,7 +3480,7 @@ jint Arguments::finalize_vm_init_args(SysClassPath* scp_p, bool scp_assembly_req
}
if ((TieredCompilation && CompileThresholdScaling == 0)
|| (!TieredCompilation && get_scaled_compile_threshold(CompileThreshold) == 0)) {
|| (!TieredCompilation && scaled_compile_threshold(CompileThreshold) == 0)) {
set_mode_flags(_int);
}
@ -3896,7 +3920,7 @@ jint Arguments::apply_ergo() {
}
// Scale CompileThreshold
if (!FLAG_IS_DEFAULT(CompileThresholdScaling)) {
FLAG_SET_ERGO(intx, CompileThreshold, get_scaled_compile_threshold(CompileThreshold));
FLAG_SET_ERGO(intx, CompileThreshold, scaled_compile_threshold(CompileThreshold));
}
}

View File

@ -328,9 +328,6 @@ class Arguments : AllStatic {
static bool _ClipInlining;
static bool _CIDynamicCompilePriority;
// Scale compile thresholds
static intx get_scaled_compile_threshold(intx threshold);
static intx get_scaled_freq_log(intx freq_log);
// Tiered
static void set_tiered_flags();
static int get_min_number_of_compiler_threads();
@ -452,6 +449,18 @@ class Arguments : AllStatic {
static char* SharedArchivePath;
public:
// Scale compile thresholds
// Returns threshold scaled with CompileThresholdScaling
static intx scaled_compile_threshold(intx threshold, double scale);
static intx scaled_compile_threshold(intx threshold) {
return scaled_compile_threshold(threshold, CompileThresholdScaling);
}
// Returns freq_log scaled with CompileThresholdScaling
static intx scaled_freq_log(intx freq_log, double scale);
static intx scaled_freq_log(intx freq_log) {
return scaled_freq_log(freq_log, CompileThresholdScaling);
}
// Parses the arguments, first phase
static jint parse(const JavaVMInitArgs* args);
// Apply ergonomics

View File

@ -2477,7 +2477,7 @@ class CommandLineFlags {
"Number of compiler threads to run") \
\
product(intx, CompilationPolicyChoice, 0, \
"which compilation policy (0/1)") \
"which compilation policy (0-3)") \
\
develop(bool, UseStackBanging, true, \
"use stack banging for stack overflow checks (required for " \
@ -3528,7 +3528,16 @@ class CommandLineFlags {
\
product(double, CompileThresholdScaling, 1.0, \
"Factor to control when first compilation happens " \
"(both with and without tiered compilation)") \
"(both with and without tiered compilation): " \
"values greater than 1.0 delay counter overflow, " \
"values between 0 and 1.0 rush counter overflow, " \
"value of 1.0 leave compilation thresholds unchanged " \
"value of 0.0 is equivalent to -Xint. " \
"" \
"Flag can be set as per-method option. " \
"If a value is specified for a method, compilation thresholds " \
"for that method are scaled by both the value of the global flag "\
"and the value of the per-method flag.") \
\
product(intx, Tier0InvokeNotifyFreqLog, 7, \
"Interpreter (tier 0) invocation notification frequency") \

View File

@ -257,28 +257,28 @@ void SimpleThresholdPolicy::submit_compile(methodHandle mh, int bci, CompLevel l
// Call and loop predicates determine whether a transition to a higher
// compilation level should be performed (pointers to predicate functions
// are passed to common() transition function).
bool SimpleThresholdPolicy::loop_predicate(int i, int b, CompLevel cur_level) {
bool SimpleThresholdPolicy::loop_predicate(int i, int b, CompLevel cur_level, Method* method) {
switch(cur_level) {
case CompLevel_none:
case CompLevel_limited_profile: {
return loop_predicate_helper<CompLevel_none>(i, b, 1.0);
return loop_predicate_helper<CompLevel_none>(i, b, 1.0, method);
}
case CompLevel_full_profile: {
return loop_predicate_helper<CompLevel_full_profile>(i, b, 1.0);
return loop_predicate_helper<CompLevel_full_profile>(i, b, 1.0, method);
}
default:
return true;
}
}
bool SimpleThresholdPolicy::call_predicate(int i, int b, CompLevel cur_level) {
bool SimpleThresholdPolicy::call_predicate(int i, int b, CompLevel cur_level, Method* method) {
switch(cur_level) {
case CompLevel_none:
case CompLevel_limited_profile: {
return call_predicate_helper<CompLevel_none>(i, b, 1.0);
return call_predicate_helper<CompLevel_none>(i, b, 1.0, method);
}
case CompLevel_full_profile: {
return call_predicate_helper<CompLevel_full_profile>(i, b, 1.0);
return call_predicate_helper<CompLevel_full_profile>(i, b, 1.0, method);
}
default:
return true;
@ -293,8 +293,8 @@ bool SimpleThresholdPolicy::is_mature(Method* method) {
int i = mdo->invocation_count();
int b = mdo->backedge_count();
double k = ProfileMaturityPercentage / 100.0;
return call_predicate_helper<CompLevel_full_profile>(i, b, k) ||
loop_predicate_helper<CompLevel_full_profile>(i, b, k);
return call_predicate_helper<CompLevel_full_profile>(i, b, k, method) ||
loop_predicate_helper<CompLevel_full_profile>(i, b, k, method);
}
return false;
}
@ -313,7 +313,7 @@ CompLevel SimpleThresholdPolicy::common(Predicate p, Method* method, CompLevel c
// If we were at full profile level, would we switch to full opt?
if (common(p, method, CompLevel_full_profile) == CompLevel_full_optimization) {
next_level = CompLevel_full_optimization;
} else if ((this->*p)(i, b, cur_level)) {
} else if ((this->*p)(i, b, cur_level, method)) {
next_level = CompLevel_full_profile;
}
break;
@ -325,7 +325,7 @@ CompLevel SimpleThresholdPolicy::common(Predicate p, Method* method, CompLevel c
if (mdo->would_profile()) {
int mdo_i = mdo->invocation_count_delta();
int mdo_b = mdo->backedge_count_delta();
if ((this->*p)(mdo_i, mdo_b, cur_level)) {
if ((this->*p)(mdo_i, mdo_b, cur_level, method)) {
next_level = CompLevel_full_optimization;
}
} else {

View File

@ -43,9 +43,9 @@ class SimpleThresholdPolicy : public CompilationPolicy {
// Call and loop predicates determine whether a transition to a higher compilation
// level should be performed (pointers to predicate functions are passed to common_TF().
// Predicates also take compiler load into account.
typedef bool (SimpleThresholdPolicy::*Predicate)(int i, int b, CompLevel cur_level);
bool call_predicate(int i, int b, CompLevel cur_level);
bool loop_predicate(int i, int b, CompLevel cur_level);
typedef bool (SimpleThresholdPolicy::*Predicate)(int i, int b, CompLevel cur_level, Method* method);
bool call_predicate(int i, int b, CompLevel cur_level, Method* method);
bool loop_predicate(int i, int b, CompLevel cur_level, Method* method);
// Common transition function. Given a predicate determines if a method should transition to another level.
CompLevel common(Predicate p, Method* method, CompLevel cur_level);
// Transition functions.
@ -76,8 +76,8 @@ protected:
// Predicate helpers are used by .*_predicate() methods as well as others.
// They check the given counter values, multiplied by the scale against the thresholds.
template<CompLevel level> static inline bool call_predicate_helper(int i, int b, double scale);
template<CompLevel level> static inline bool loop_predicate_helper(int i, int b, double scale);
template<CompLevel level> static inline bool call_predicate_helper(int i, int b, double scale, Method* method);
template<CompLevel level> static inline bool loop_predicate_helper(int i, int b, double scale, Method* method);
// Get a compilation level for a given method.
static CompLevel comp_level(Method* method) {

View File

@ -25,8 +25,14 @@
#ifndef SHARE_VM_RUNTIME_SIMPLETHRESHOLDPOLICY_INLINE_HPP
#define SHARE_VM_RUNTIME_SIMPLETHRESHOLDPOLICY_INLINE_HPP
#include "compiler/compilerOracle.hpp"
template<CompLevel level>
bool SimpleThresholdPolicy::call_predicate_helper(int i, int b, double scale) {
bool SimpleThresholdPolicy::call_predicate_helper(int i, int b, double scale, Method* method) {
double threshold_scaling;
if (CompilerOracle::has_option_value(method, "CompileThresholdScaling", threshold_scaling)) {
scale *= threshold_scaling;
}
switch(level) {
case CompLevel_none:
case CompLevel_limited_profile:
@ -40,7 +46,11 @@ bool SimpleThresholdPolicy::call_predicate_helper(int i, int b, double scale) {
}
template<CompLevel level>
bool SimpleThresholdPolicy::loop_predicate_helper(int i, int b, double scale) {
bool SimpleThresholdPolicy::loop_predicate_helper(int i, int b, double scale, Method* method) {
double threshold_scaling;
if (CompilerOracle::has_option_value(method, "CompileThresholdScaling", threshold_scaling)) {
scale *= threshold_scaling;
}
switch(level) {
case CompLevel_none:
case CompLevel_limited_profile:

View File

@ -351,11 +351,18 @@ typedef TwoOopHashtable<Symbol*, mtClass> SymbolTwoOopHashtable;
nonstatic_field(MethodData, _arg_stack, intx) \
nonstatic_field(MethodData, _arg_returned, intx) \
nonstatic_field(MethodData, _tenure_traps, uint) \
nonstatic_field(MethodData, _invoke_mask, int) \
nonstatic_field(MethodData, _backedge_mask, int) \
nonstatic_field(DataLayout, _header._struct._tag, u1) \
nonstatic_field(DataLayout, _header._struct._flags, u1) \
nonstatic_field(DataLayout, _header._struct._bci, u2) \
nonstatic_field(DataLayout, _cells[0], intptr_t) \
nonstatic_field(MethodCounters, _nmethod_age, int) \
nonstatic_field(MethodCounters, _interpreter_invocation_limit, int) \
nonstatic_field(MethodCounters, _interpreter_backward_branch_limit, int) \
nonstatic_field(MethodCounters, _interpreter_profile_limit, int) \
nonstatic_field(MethodCounters, _invoke_mask, int) \
nonstatic_field(MethodCounters, _backedge_mask, int) \
nonstatic_field(MethodCounters, _interpreter_invocation_count, int) \
nonstatic_field(MethodCounters, _interpreter_throwout_count, u2) \
nonstatic_field(MethodCounters, _number_of_breakpoints, u2) \

View File

@ -1142,17 +1142,18 @@ inline bool is_power_of_2_long(jlong x) {
return ((x != NoLongBits) && (mask_long_bits(x, x - 1) == NoLongBits));
}
//* largest i such that 2^i <= x
// A negative value of 'x' will return '31'
// Returns largest i such that 2^i <= x.
// If x < 0, the function returns 31 on a 32-bit machine and 63 on a 64-bit machine.
// If x == 0, the function returns -1.
inline int log2_intptr(intptr_t x) {
int i = -1;
uintptr_t p = 1;
uintptr_t p = 1;
while (p != 0 && p <= (uintptr_t)x) {
// p = 2^(i+1) && p <= x (i.e., 2^(i+1) <= x)
i++; p *= 2;
}
// p = 2^(i+1) && x < p (i.e., 2^i <= x < 2^(i+1))
// (if p = 0 then overflow occurred and i = 31)
// If p = 0, overflow has occurred and i = 31 or i = 63 (depending on the machine word size).
return i;
}

View File

@ -54,7 +54,7 @@ public class CheckCompileThresholdScaling {
//
// Tier0InvokeNotifyFreqLog, Tier0BackedgeNotifyFreqLog,
// Tier3InvocationThreshold, Tier3MinInvocationThreshold,
// Tier3CompileThreshold, and Tier3BackEdgeThreshold,
// Tier3CompileThreshold, Tier3BackEdgeThreshold,
// Tier2InvokeNotifyFreqLog, Tier2BackedgeNotifyFreqLog,
// Tier3InvokeNotifyFreqLog, Tier3BackedgeNotifyFreqLog,
// Tier23InlineeNotifyFreqLog, Tier4InvocationThreshold,

View File

@ -98,11 +98,13 @@ public class PoolsIndependenceTest implements NotificationListener {
return false;
});
for (BlobType bt : BlobType.getAvailable()) {
int expectedNotificationsAmount = bt.equals(btype) ? 1 : 0;
Asserts.assertEQ(counters.get(bt.getMemoryPool().getName()).get(),
expectedNotificationsAmount, String.format("Unexpected "
+ "amount of notifications for pool: %s",
bt.getMemoryPool().getName()));
if (CodeCacheUtils.isCodeHeapPredictable(bt)) {
int expectedNotificationsAmount = bt.equals(btype) ? 1 : 0;
Asserts.assertEQ(counters.get(bt.getMemoryPool().getName()).get(),
expectedNotificationsAmount, String.format("Unexpected "
+ "amount of notifications for pool: %s",
bt.getMemoryPool().getName()));
}
}
try {
((NotificationEmitter) ManagementFactory.getMemoryMXBean()).

View File

@ -52,7 +52,9 @@ public class ThresholdNotificationsTest implements NotificationListener {
public static void main(String[] args) {
for (BlobType bt : BlobType.getAvailable()) {
new ThresholdNotificationsTest(bt).runTest();
if (CodeCacheUtils.isCodeHeapPredictable(bt)) {
new ThresholdNotificationsTest(bt).runTest();
}
}
}

View File

@ -25,7 +25,6 @@
/**
* @test
* @bug 7052494
* @ignore 7154567
* @summary Eclipse test fails on JDK 7 b142
*
* @run main/othervm -Xbatch Test7052494

View File

@ -0,0 +1,89 @@
/*
* Copyright 2015 SAP AG. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8068909
* @key regression
* @summary test that string optimizations produce code, that doesn't lead to a crash.
* @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestOptimizeStringConcat
* @author axel.siebenborn@sap.com
*/
public class TestOptimizeStringConcat {
static boolean checkArgumentSyntax(String value, String allowedchars, String notallowedchars, String logmsg) {
String rc = null;
int maxchar = 99999;
int minchar = 1;
if ((allowedchars != null && notallowedchars != null) || minchar > maxchar) {
rc = "internal error";
} else {
if (value == null) {
rc = "the value null is not allowed, it is missing";
} else if (value != null && minchar > 0 && value.trim().equals("")) {
rc = "the value must not be empty";
} else if (value != null) {
if (value.length() < minchar || value.length() > maxchar) {
if (rc == null) {
rc = "the value length must be between +minchar+ and +maxchar";
}
}
char[] _value = value.toCharArray();
boolean dotfound = false;
int i = 1;
if (_value[i] == '.' && !dotfound) {
dotfound = true;
} else if (allowedchars != null && allowedchars.indexOf(_value[i]) == -1) {
if (rc == null) {
rc = "the value contains an illegal character: '" + _value[i] + "', only following characters are allowed: '+allowedchars+'";
} else {
rc += " / the value contains an illegal character: '" + _value[i] + "', only following characters are allowed: '+allowedchars+'";
}
} else if (notallowedchars != null && notallowedchars.indexOf(_value[i]) != -1) {
if (rc == null) {
rc = "the value contains an illegal character: '" + _value[i] + "', following characters are not allowed '+notallowedchars+'";
} else {
rc += " / the value contains an illegal character: '" + _value[i] + "', following characters are not allowed '+notallowedchars+'";
}
}
}
}
if (rc != null) {
System.out.println(logmsg + " ==> " + rc);
return false;
}
return true;
}
public static void main(String[] args) {
boolean failed = false;
for (int i = 0; i < 10000; i++) {
failed |= !checkArgumentSyntax("theName", null, "\"<&", "Error consistencyCheck: name in component definition");
failed |= !checkArgumentSyntax(null, null, "\"<&", "Error consistencyCheck: name in component definition");
failed |= !checkArgumentSyntax("42", "0123456789.", null, "Error consistencyCheck: counter in component definition");
}
System.out.println(failed);
}
}

View File

@ -25,6 +25,7 @@
* @test CompilerQueueTest
* @bug 8054889
* @library ..
* @ignore 8069160
* @build DcmdUtil CompilerQueueTest
* @run main CompilerQueueTest
* @run main/othervm -XX:-TieredCompilation CompilerQueueTest