This commit is contained in:
Jiangli Zhou 2013-04-18 17:00:16 -04:00
commit a86e7e948c
35 changed files with 784 additions and 302 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -49,19 +49,13 @@ public class Method extends Metadata {
Type type = db.lookupType("Method");
constMethod = type.getAddressField("_constMethod");
methodData = type.getAddressField("_method_data");
methodCounters = type.getAddressField("_method_counters");
methodSize = new CIntField(type.getCIntegerField("_method_size"), 0);
accessFlags = new CIntField(type.getCIntegerField("_access_flags"), 0);
code = type.getAddressField("_code");
vtableIndex = new CIntField(type.getCIntegerField("_vtable_index"), 0);
if (!VM.getVM().isCore()) {
invocationCounter = new CIntField(type.getCIntegerField("_invocation_counter"), 0);
backedgeCounter = new CIntField(type.getCIntegerField("_backedge_counter"), 0);
}
bytecodeOffset = type.getSize();
interpreterThrowoutCountField = new CIntField(type.getCIntegerField("_interpreter_throwout_count"), 0);
interpreterInvocationCountField = new CIntField(type.getCIntegerField("_interpreter_invocation_count"), 0);
/*
interpreterEntry = type.getAddressField("_interpreter_entry");
fromCompiledCodeEntryPoint = type.getAddressField("_from_compiled_code_entry_point");
@ -80,18 +74,14 @@ public class Method extends Metadata {
// Fields
private static AddressField constMethod;
private static AddressField methodData;
private static AddressField methodCounters;
private static CIntField methodSize;
private static CIntField accessFlags;
private static CIntField vtableIndex;
private static CIntField invocationCounter;
private static CIntField backedgeCounter;
private static long bytecodeOffset;
private static AddressField code;
private static CIntField interpreterThrowoutCountField;
private static CIntField interpreterInvocationCountField;
// constant method names - <init>, <clinit>
// Initialized lazily to avoid initialization ordering dependencies between Method and SymbolTable
private static Symbol objectInitializerName;
@ -127,6 +117,10 @@ public class Method extends Metadata {
Address addr = methodData.getValue(getAddress());
return (MethodData) VMObjectFactory.newObject(MethodData.class, addr);
}
public MethodCounters getMethodCounters() {
Address addr = methodCounters.getValue(getAddress());
return (MethodCounters) VMObjectFactory.newObject(MethodCounters.class, addr);
}
/** WARNING: this is in words, not useful in this system; use getObjectSize() instead */
public long getMethodSize() { return methodSize.getValue(this); }
public long getMaxStack() { return getConstMethod().getMaxStack(); }
@ -139,16 +133,10 @@ public class Method extends Metadata {
public long getCodeSize() { return getConstMethod().getCodeSize(); }
public long getVtableIndex() { return vtableIndex.getValue(this); }
public long getInvocationCounter() {
if (Assert.ASSERTS_ENABLED) {
Assert.that(!VM.getVM().isCore(), "must not be used in core build");
}
return invocationCounter.getValue(this);
return getMethodCounters().getInvocationCounter();
}
public long getBackedgeCounter() {
if (Assert.ASSERTS_ENABLED) {
Assert.that(!VM.getVM().isCore(), "must not be used in core build");
}
return backedgeCounter.getValue(this);
return getMethodCounters().getBackedgeCounter();
}
// get associated compiled native method, if available, else return null.
@ -369,10 +357,10 @@ public class Method extends Metadata {
}
public int interpreterThrowoutCount() {
return (int) interpreterThrowoutCountField.getValue(this);
return getMethodCounters().interpreterThrowoutCount();
}
public int interpreterInvocationCount() {
return (int) interpreterInvocationCountField.getValue(this);
return getMethodCounters().interpreterInvocationCount();
}
}

View File

@ -0,0 +1,86 @@
/*
* Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* 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.
*
*/
package sun.jvm.hotspot.oops;
import java.io.*;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.types.*;
import sun.jvm.hotspot.utilities.*;
public class MethodCounters extends Metadata {
public MethodCounters(Address addr) {
super(addr);
}
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("MethodCounters");
interpreterInvocationCountField = new CIntField(type.getCIntegerField("_interpreter_invocation_count"), 0);
interpreterThrowoutCountField = new CIntField(type.getCIntegerField("_interpreter_throwout_count"), 0);
if (!VM.getVM().isCore()) {
invocationCounter = new CIntField(type.getCIntegerField("_invocation_counter"), 0);
backedgeCounter = new CIntField(type.getCIntegerField("_backedge_counter"), 0);
}
}
private static CIntField interpreterInvocationCountField;
private static CIntField interpreterThrowoutCountField;
private static CIntField invocationCounter;
private static CIntField backedgeCounter;
public int interpreterInvocationCount() {
return (int) interpreterInvocationCountField.getValue(this);
}
public int interpreterThrowoutCount() {
return (int) interpreterThrowoutCountField.getValue(this);
}
public long getInvocationCounter() {
if (Assert.ASSERTS_ENABLED) {
Assert.that(!VM.getVM().isCore(), "must not be used in core build");
}
return invocationCounter.getValue(this);
}
public long getBackedgeCounter() {
if (Assert.ASSERTS_ENABLED) {
Assert.that(!VM.getVM().isCore(), "must not be used in core build");
}
return backedgeCounter.getValue(this);
}
public void printValueOn(PrintStream tty) {
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -404,14 +404,20 @@ address CppInterpreter::deopt_entry(TosState state, int length) {
// ??: invocation counter
//
void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile_method, Label* profile_method_continue) {
Label done;
const Register Rcounters = G3_scratch;
__ ld_ptr(STATE(_method), G5_method);
__ get_method_counters(G5_method, Rcounters, done);
// Update standard invocation counters
__ increment_invocation_counter(O0, G3_scratch);
if (ProfileInterpreter) { // %%% Merge this into MethodData*
__ ld_ptr(STATE(_method), G3_scratch);
Address interpreter_invocation_counter(G3_scratch, 0, in_bytes(Method::interpreter_invocation_counter_offset()));
__ ld(interpreter_invocation_counter, G3_scratch);
__ inc(G3_scratch);
__ st(G3_scratch, interpreter_invocation_counter);
__ increment_invocation_counter(Rcounters, O0, G4_scratch);
if (ProfileInterpreter) {
Address interpreter_invocation_counter(Rcounters, 0,
in_bytes(MethodCounters::interpreter_invocation_counter_offset()));
__ ld(interpreter_invocation_counter, G4_scratch);
__ inc(G4_scratch);
__ st(G4_scratch, interpreter_invocation_counter);
}
Address invocation_limit(G3_scratch, (address)&InvocationCounter::InterpreterInvocationLimit);
@ -420,7 +426,7 @@ void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile
__ cmp(O0, G3_scratch);
__ br(Assembler::greaterEqualUnsigned, false, Assembler::pn, *overflow);
__ delayed()->nop();
__ bind(done);
}
address InterpreterGenerator::generate_empty_entry(void) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -30,6 +30,7 @@
#include "oops/markOop.hpp"
#include "oops/methodData.hpp"
#include "oops/method.hpp"
#include "oops/methodCounters.hpp"
#include "prims/jvmtiExport.hpp"
#include "prims/jvmtiRedefineClassesTrace.hpp"
#include "prims/jvmtiThreadState.hpp"
@ -2086,19 +2087,28 @@ void InterpreterMacroAssembler::compute_stack_base( Register Rdest ) {
#endif /* CC_INTERP */
void InterpreterMacroAssembler::increment_invocation_counter( Register Rtmp, Register Rtmp2 ) {
void InterpreterMacroAssembler::get_method_counters(Register method,
Register Rcounters,
Label& skip) {
Label has_counters;
Address method_counters(method, in_bytes(Method::method_counters_offset()));
ld_ptr(method_counters, Rcounters);
br_notnull_short(Rcounters, Assembler::pt, has_counters);
call_VM(noreg, CAST_FROM_FN_PTR(address,
InterpreterRuntime::build_method_counters), method);
ld_ptr(method_counters, Rcounters);
br_null_short(Rcounters, Assembler::pn, skip); // No MethodCounters, OutOfMemory
bind(has_counters);
}
void InterpreterMacroAssembler::increment_invocation_counter( Register Rcounters, Register Rtmp, Register Rtmp2 ) {
assert(UseCompiler, "incrementing must be useful");
#ifdef CC_INTERP
Address inv_counter(G5_method, Method::invocation_counter_offset() +
assert_different_registers(Rcounters, Rtmp, Rtmp2);
Address inv_counter(Rcounters, MethodCounters::invocation_counter_offset() +
InvocationCounter::counter_offset());
Address be_counter (G5_method, Method::backedge_counter_offset() +
Address be_counter (Rcounters, MethodCounters::backedge_counter_offset() +
InvocationCounter::counter_offset());
#else
Address inv_counter(Lmethod, Method::invocation_counter_offset() +
InvocationCounter::counter_offset());
Address be_counter (Lmethod, Method::backedge_counter_offset() +
InvocationCounter::counter_offset());
#endif /* CC_INTERP */
int delta = InvocationCounter::count_increment;
// Load each counter in a register
@ -2122,19 +2132,15 @@ void InterpreterMacroAssembler::increment_invocation_counter( Register Rtmp, Reg
// Note that this macro must leave the backedge_count + invocation_count in Rtmp!
}
void InterpreterMacroAssembler::increment_backedge_counter( Register Rtmp, Register Rtmp2 ) {
void InterpreterMacroAssembler::increment_backedge_counter( Register Rcounters, Register Rtmp, Register Rtmp2 ) {
assert(UseCompiler, "incrementing must be useful");
#ifdef CC_INTERP
Address be_counter (G5_method, Method::backedge_counter_offset() +
assert_different_registers(Rcounters, Rtmp, Rtmp2);
Address be_counter (Rcounters, MethodCounters::backedge_counter_offset() +
InvocationCounter::counter_offset());
Address inv_counter(G5_method, Method::invocation_counter_offset() +
Address inv_counter(Rcounters, MethodCounters::invocation_counter_offset() +
InvocationCounter::counter_offset());
#else
Address be_counter (Lmethod, Method::backedge_counter_offset() +
InvocationCounter::counter_offset());
Address inv_counter(Lmethod, Method::invocation_counter_offset() +
InvocationCounter::counter_offset());
#endif /* CC_INTERP */
int delta = InvocationCounter::count_increment;
// Load each counter in a register
ld( be_counter, Rtmp );

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -263,8 +263,9 @@ class InterpreterMacroAssembler: public MacroAssembler {
void compute_stack_base( Register Rdest );
#endif /* CC_INTERP */
void increment_invocation_counter( Register Rtmp, Register Rtmp2 );
void increment_backedge_counter( Register Rtmp, Register Rtmp2 );
void get_method_counters(Register method, Register Rcounters, Label& skip);
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 );

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -292,11 +292,15 @@ address TemplateInterpreterGenerator::generate_continuation_for(TosState state)
// ??: invocation counter
//
void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile_method, Label* profile_method_continue) {
// Note: In tiered we increment either counters in Method* or in MDO depending if we're profiling or not.
// Note: In tiered we increment either counters in MethodCounters* or in
// MDO depending if we're profiling or not.
const Register Rcounters = G3_scratch;
Label done;
if (TieredCompilation) {
const int increment = InvocationCounter::count_increment;
const int mask = ((1 << Tier0InvokeNotifyFreqLog) - 1) << InvocationCounter::count_shift;
Label no_mdo, done;
Label no_mdo;
if (ProfileInterpreter) {
// If no method data exists, go to profile_continue.
__ ld_ptr(Lmethod, Method::method_data_offset(), G4_scratch);
@ -311,23 +315,26 @@ void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile
__ ba_short(done);
}
// Increment counter in Method*
// Increment counter in MethodCounters*
__ bind(no_mdo);
Address invocation_counter(Lmethod,
in_bytes(Method::invocation_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
Address invocation_counter(Rcounters,
in_bytes(MethodCounters::invocation_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
__ get_method_counters(Lmethod, Rcounters, done);
__ increment_mask_and_jump(invocation_counter, increment, mask,
G3_scratch, Lscratch,
G4_scratch, Lscratch,
Assembler::zero, overflow);
__ bind(done);
} else {
// Update standard invocation counters
__ increment_invocation_counter(O0, G3_scratch);
if (ProfileInterpreter) { // %%% Merge this into MethodData*
Address interpreter_invocation_counter(Lmethod,in_bytes(Method::interpreter_invocation_counter_offset()));
__ ld(interpreter_invocation_counter, G3_scratch);
__ inc(G3_scratch);
__ st(G3_scratch, interpreter_invocation_counter);
__ get_method_counters(Lmethod, Rcounters, done);
__ increment_invocation_counter(Rcounters, O0, G4_scratch);
if (ProfileInterpreter) {
Address interpreter_invocation_counter(Rcounters,
in_bytes(MethodCounters::interpreter_invocation_counter_offset()));
__ ld(interpreter_invocation_counter, G4_scratch);
__ inc(G4_scratch);
__ st(G4_scratch, interpreter_invocation_counter);
}
if (ProfileInterpreter && profile_method != NULL) {
@ -345,6 +352,7 @@ void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile
__ cmp(O0, G3_scratch);
__ br(Assembler::greaterEqualUnsigned, false, Assembler::pn, *overflow); // Far distance
__ delayed()->nop();
__ bind(done);
}
}

View File

@ -1611,9 +1611,8 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
// Normal (non-jsr) branch handling
// Save the current Lbcp
const Register O0_cur_bcp = O0;
__ mov( Lbcp, O0_cur_bcp );
const Register l_cur_bcp = Lscratch;
__ mov( Lbcp, l_cur_bcp );
bool increment_invocation_counter_for_backward_branches = UseCompiler && UseLoopCounter;
if ( increment_invocation_counter_for_backward_branches ) {
@ -1623,6 +1622,9 @@ 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);
if (TieredCompilation) {
Label Lno_mdo, Loverflow;
int increment = InvocationCounter::count_increment;
@ -1635,21 +1637,22 @@ 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()));
__ increment_mask_and_jump(mdo_backedge_counter, increment, mask, G3_scratch, Lscratch,
__ increment_mask_and_jump(mdo_backedge_counter, increment, mask, G3_scratch, O0,
Assembler::notZero, &Lforward);
__ ba_short(Loverflow);
}
// If there's no MDO, increment counter in Method*
// If there's no MDO, increment counter in MethodCounters*
__ bind(Lno_mdo);
Address backedge_counter(Lmethod, in_bytes(Method::backedge_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
__ increment_mask_and_jump(backedge_counter, increment, mask, G3_scratch, Lscratch,
Address backedge_counter(Rcounters,
in_bytes(MethodCounters::backedge_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
__ increment_mask_and_jump(backedge_counter, increment, mask, G4_scratch, O0,
Assembler::notZero, &Lforward);
__ bind(Loverflow);
// notify point for loop, pass branch bytecode
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::frequency_counter_overflow), O0_cur_bcp);
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::frequency_counter_overflow), l_cur_bcp);
// Was an OSR adapter generated?
// O0 = osr nmethod
@ -1686,15 +1689,15 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
} else {
// Update Backedge branch separately from invocations
const Register G4_invoke_ctr = G4;
__ increment_backedge_counter(G4_invoke_ctr, G1_scratch);
__ increment_backedge_counter(Rcounters, G4_invoke_ctr, G1_scratch);
if (ProfileInterpreter) {
__ test_invocation_counter_for_mdp(G4_invoke_ctr, G3_scratch, Lforward);
if (UseOnStackReplacement) {
__ test_backedge_count_for_osr(O2_bumped_count, O0_cur_bcp, G3_scratch);
__ test_backedge_count_for_osr(O2_bumped_count, l_cur_bcp, G3_scratch);
}
} else {
if (UseOnStackReplacement) {
__ test_backedge_count_for_osr(G4_invoke_ctr, O0_cur_bcp, G3_scratch);
__ test_backedge_count_for_osr(G4_invoke_ctr, l_cur_bcp, G3_scratch);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -570,20 +570,28 @@ void CppInterpreterGenerator::generate_compute_interpreter_state(const Register
// rcx: invocation counter
//
void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile_method, Label* profile_method_continue) {
Label done;
const Address invocation_counter(rax,
MethodCounters::invocation_counter_offset() +
InvocationCounter::counter_offset());
const Address backedge_counter (rax,
MethodCounter::backedge_counter_offset() +
InvocationCounter::counter_offset());
const Address invocation_counter(rbx, Method::invocation_counter_offset() + InvocationCounter::counter_offset());
const Address backedge_counter (rbx, Method::backedge_counter_offset() + InvocationCounter::counter_offset());
__ get_method_counters(rbx, rax, done);
if (ProfileInterpreter) { // %%% Merge this into MethodData*
__ incrementl(Address(rbx,Method::interpreter_invocation_counter_offset()));
if (ProfileInterpreter) {
__ incrementl(Address(rax,
MethodCounters::interpreter_invocation_counter_offset()));
}
// Update standard invocation counters
__ movl(rax, backedge_counter); // load backedge counter
__ movl(rcx, invocation_counter);
__ increment(rcx, InvocationCounter::count_increment);
__ movl(invocation_counter, rcx); // save invocation count
__ movl(rax, backedge_counter); // load backedge counter
__ andl(rax, InvocationCounter::count_mask_value); // mask out the status bits
__ movl(invocation_counter, rcx); // save invocation count
__ addl(rcx, rax); // add both counters
// profile_method is non-null only for interpreted method so
@ -593,7 +601,7 @@ void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile
__ cmp32(rcx,
ExternalAddress((address)&InvocationCounter::InterpreterInvocationLimit));
__ jcc(Assembler::aboveEqual, *overflow);
__ bind(done);
}
void InterpreterGenerator::generate_counter_overflow(Label* do_continue) {
@ -977,7 +985,6 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
address entry_point = __ pc();
const Address constMethod (rbx, Method::const_offset());
const Address invocation_counter(rbx, Method::invocation_counter_offset() + InvocationCounter::counter_offset());
const Address access_flags (rbx, Method::access_flags_offset());
const Address size_of_parameters(rcx, ConstMethod::size_of_parameters_offset());
@ -1029,8 +1036,6 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
}
#endif
if (inc_counter) __ movl(rcx, invocation_counter); // (pre-)fetch invocation count
const Register unlock_thread = LP64_ONLY(r15_thread) NOT_LP64(rax);
NOT_LP64(__ movptr(unlock_thread, STATE(_thread));) // get thread
// Since at this point in the method invocation the exception handler

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -266,6 +266,20 @@ void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, R
addptr(cache, tmp); // construct pointer to cache entry
}
void InterpreterMacroAssembler::get_method_counters(Register method,
Register mcs, Label& skip) {
Label has_counters;
movptr(mcs, Address(method, Method::method_counters_offset()));
testptr(mcs, mcs);
jcc(Assembler::notZero, has_counters);
call_VM(noreg, CAST_FROM_FN_PTR(address,
InterpreterRuntime::build_method_counters), method);
movptr(mcs, Address(method,Method::method_counters_offset()));
testptr(mcs, mcs);
jcc(Assembler::zero, skip); // No MethodCounters allocated, OutOfMemory
bind(has_counters);
}
// Load object from cpool->resolved_references(index)
void InterpreterMacroAssembler::load_resolved_reference_at_index(
Register result, Register index) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -89,6 +89,7 @@ class InterpreterMacroAssembler: public MacroAssembler {
void get_cache_and_index_and_bytecode_at_bcp(Register cache, Register index, Register bytecode, int byte_no, int bcp_offset, size_t index_size = sizeof(u2));
void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset, size_t index_size = sizeof(u2));
void get_cache_index_at_bcp(Register index, int bcp_offset, size_t index_size = sizeof(u2));
void get_method_counters(Register method, Register mcs, Label& skip);
// load cpool->resolved_references(index);
void load_resolved_reference_at_index(Register result, Register index);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -271,6 +271,20 @@ void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache,
addptr(cache, tmp); // construct pointer to cache entry
}
void InterpreterMacroAssembler::get_method_counters(Register method,
Register mcs, Label& skip) {
Label has_counters;
movptr(mcs, Address(method, Method::method_counters_offset()));
testptr(mcs, mcs);
jcc(Assembler::notZero, has_counters);
call_VM(noreg, CAST_FROM_FN_PTR(address,
InterpreterRuntime::build_method_counters), method);
movptr(mcs, Address(method,Method::method_counters_offset()));
testptr(mcs, mcs);
jcc(Assembler::zero, skip); // No MethodCounters allocated, OutOfMemory
bind(has_counters);
}
// Load object from cpool->resolved_references(index)
void InterpreterMacroAssembler::load_resolved_reference_at_index(
Register result, Register index) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -111,6 +111,7 @@ class InterpreterMacroAssembler: public MacroAssembler {
void get_cache_and_index_and_bytecode_at_bcp(Register cache, Register index, Register bytecode, int byte_no, int bcp_offset, size_t index_size = sizeof(u2));
void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset, size_t index_size = sizeof(u2));
void get_cache_index_at_bcp(Register index, int bcp_offset, size_t index_size = sizeof(u2));
void get_method_counters(Register method, Register mcs, Label& skip);
// load cpool->resolved_references(index);
void load_resolved_reference_at_index(Register result, Register index);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -344,13 +344,13 @@ address TemplateInterpreterGenerator::generate_safept_entry_for(TosState state,
// rcx: invocation counter
//
void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile_method, Label* profile_method_continue) {
const Address invocation_counter(rbx, in_bytes(Method::invocation_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
// Note: In tiered we increment either counters in Method* or in MDO depending if we're profiling or not.
Label done;
// Note: In tiered we increment either counters in MethodCounters* 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, done;
Label no_mdo;
if (ProfileInterpreter) {
// Are we profiling?
__ movptr(rax, Address(rbx, Method::method_data_offset()));
@ -363,23 +363,38 @@ void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile
__ jmpb(done);
}
__ bind(no_mdo);
// Increment counter in Method* (we don't need to load it, it's in rcx).
__ increment_mask_and_jump(invocation_counter, increment, mask, rcx, true, Assembler::zero, overflow);
// Increment counter in MethodCounters
const Address invocation_counter(rax,
MethodCounters::invocation_counter_offset() +
InvocationCounter::counter_offset());
__ get_method_counters(rbx, rax, done);
__ increment_mask_and_jump(invocation_counter, increment, mask,
rcx, false, Assembler::zero, overflow);
__ bind(done);
} else {
const Address backedge_counter (rbx, Method::backedge_counter_offset() +
InvocationCounter::counter_offset());
const Address backedge_counter (rax,
MethodCounters::backedge_counter_offset() +
InvocationCounter::counter_offset());
const Address invocation_counter(rax,
MethodCounters::invocation_counter_offset() +
InvocationCounter::counter_offset());
if (ProfileInterpreter) { // %%% Merge this into MethodData*
__ incrementl(Address(rbx,Method::interpreter_invocation_counter_offset()));
__ get_method_counters(rbx, rax, done);
if (ProfileInterpreter) {
__ incrementl(Address(rax,
MethodCounters::interpreter_invocation_counter_offset()));
}
// Update standard invocation counters
__ movl(rax, backedge_counter); // load backedge counter
// Update standard invocation counters
__ movl(rcx, invocation_counter);
__ incrementl(rcx, InvocationCounter::count_increment);
__ movl(invocation_counter, rcx); // save invocation count
__ movl(rax, backedge_counter); // load backedge counter
__ andl(rax, InvocationCounter::count_mask_value); // mask out the status bits
__ movl(invocation_counter, rcx); // save invocation count
__ addl(rcx, rax); // add both counters
// profile_method is non-null only for interpreted method so
@ -399,6 +414,7 @@ void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile
__ cmp32(rcx,
ExternalAddress((address)&InvocationCounter::InterpreterInvocationLimit));
__ jcc(Assembler::aboveEqual, *overflow);
__ bind(done);
}
}
@ -868,7 +884,6 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
address entry_point = __ pc();
const Address constMethod (rbx, Method::const_offset());
const Address invocation_counter(rbx, Method::invocation_counter_offset() + InvocationCounter::counter_offset());
const Address access_flags (rbx, Method::access_flags_offset());
const Address size_of_parameters(rcx, ConstMethod::size_of_parameters_offset());
@ -897,9 +912,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
// NULL oop temp (mirror or jni oop result)
__ push((int32_t)NULL_WORD);
if (inc_counter) __ movl(rcx, invocation_counter); // (pre-)fetch invocation count
// initialize fixed part of activation frame
generate_fixed_frame(true);
// make sure method is native & not abstract
@ -1286,7 +1299,6 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) {
address entry_point = __ pc();
const Address constMethod (rbx, Method::const_offset());
const Address invocation_counter(rbx, Method::invocation_counter_offset() + InvocationCounter::counter_offset());
const Address access_flags (rbx, Method::access_flags_offset());
const Address size_of_parameters(rdx, ConstMethod::size_of_parameters_offset());
const Address size_of_locals (rdx, ConstMethod::size_of_locals_offset());
@ -1326,7 +1338,6 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) {
__ bind(exit);
}
if (inc_counter) __ movl(rcx, invocation_counter); // (pre-)fetch invocation count
// initialize fixed part of activation frame
generate_fixed_frame(false);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -300,13 +300,12 @@ void InterpreterGenerator::generate_counter_incr(
Label* overflow,
Label* profile_method,
Label* profile_method_continue) {
const Address invocation_counter(rbx, in_bytes(Method::invocation_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
Label done;
// 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, done;
Label no_mdo;
if (ProfileInterpreter) {
// Are we profiling?
__ movptr(rax, Address(rbx, Method::method_data_offset()));
@ -319,25 +318,36 @@ void InterpreterGenerator::generate_counter_incr(
__ jmpb(done);
}
__ bind(no_mdo);
// Increment counter in Method* (we don't need to load it, it's in ecx).
__ increment_mask_and_jump(invocation_counter, increment, mask, rcx, true, Assembler::zero, overflow);
// Increment counter in MethodCounters
const Address invocation_counter(rax,
MethodCounters::invocation_counter_offset() +
InvocationCounter::counter_offset());
__ get_method_counters(rbx, rax, done);
__ increment_mask_and_jump(invocation_counter, increment, mask, rcx,
false, Assembler::zero, overflow);
__ bind(done);
} else {
const Address backedge_counter(rbx,
Method::backedge_counter_offset() +
InvocationCounter::counter_offset());
const Address backedge_counter(rax,
MethodCounters::backedge_counter_offset() +
InvocationCounter::counter_offset());
const Address invocation_counter(rax,
MethodCounters::invocation_counter_offset() +
InvocationCounter::counter_offset());
if (ProfileInterpreter) { // %%% Merge this into MethodData*
__ incrementl(Address(rbx,
Method::interpreter_invocation_counter_offset()));
__ get_method_counters(rbx, rax, done);
if (ProfileInterpreter) {
__ incrementl(Address(rax,
MethodCounters::interpreter_invocation_counter_offset()));
}
// Update standard invocation counters
__ movl(rax, backedge_counter); // load backedge counter
__ movl(rcx, invocation_counter);
__ incrementl(rcx, InvocationCounter::count_increment);
__ movl(invocation_counter, rcx); // save invocation count
__ movl(rax, backedge_counter); // load backedge counter
__ andl(rax, InvocationCounter::count_mask_value); // mask out the status bits
__ movl(invocation_counter, rcx); // save invocation count
__ addl(rcx, rax); // add both counters
// profile_method is non-null only for interpreted method so
@ -354,6 +364,7 @@ void InterpreterGenerator::generate_counter_incr(
__ cmp32(rcx, ExternalAddress((address)&InvocationCounter::InterpreterInvocationLimit));
__ jcc(Assembler::aboveEqual, *overflow);
__ bind(done);
}
}
@ -843,9 +854,6 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
address entry_point = __ pc();
const Address constMethod (rbx, Method::const_offset());
const Address invocation_counter(rbx, Method::
invocation_counter_offset() +
InvocationCounter::counter_offset());
const Address access_flags (rbx, Method::access_flags_offset());
const Address size_of_parameters(rcx, ConstMethod::
size_of_parameters_offset());
@ -876,10 +884,6 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
// (static native method holder mirror/jni oop result)
__ push((int) NULL_WORD);
if (inc_counter) {
__ movl(rcx, invocation_counter); // (pre-)fetch invocation count
}
// initialize fixed part of activation frame
generate_fixed_frame(true);
@ -1296,9 +1300,6 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) {
address entry_point = __ pc();
const Address constMethod(rbx, Method::const_offset());
const Address invocation_counter(rbx,
Method::invocation_counter_offset() +
InvocationCounter::counter_offset());
const Address access_flags(rbx, Method::access_flags_offset());
const Address size_of_parameters(rdx,
ConstMethod::size_of_parameters_offset());
@ -1343,10 +1344,6 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) {
__ bind(exit);
}
// (pre-)fetch invocation count
if (inc_counter) {
__ movl(rcx, invocation_counter);
}
// initialize fixed part of activation frame
generate_fixed_frame(false);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -1546,9 +1546,10 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
__ get_method(rcx); // ECX holds method
__ profile_taken_branch(rax,rbx); // EAX holds updated MDP, EBX holds bumped taken count
const ByteSize be_offset = Method::backedge_counter_offset() + InvocationCounter::counter_offset();
const ByteSize inv_offset = Method::invocation_counter_offset() + InvocationCounter::counter_offset();
const int method_offset = frame::interpreter_frame_method_offset * wordSize;
const ByteSize be_offset = MethodCounters::backedge_counter_offset() +
InvocationCounter::counter_offset();
const ByteSize inv_offset = MethodCounters::invocation_counter_offset() +
InvocationCounter::counter_offset();
// Load up EDX with the branch displacement
__ movl(rdx, at_bcp(1));
@ -1596,6 +1597,22 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
__ testl(rdx, rdx); // check if forward or backward branch
__ jcc(Assembler::positive, dispatch); // count only if backward branch
// check if MethodCounters exists
Label has_counters;
__ movptr(rax, Address(rcx, Method::method_counters_offset()));
__ testptr(rax, rax);
__ jcc(Assembler::notZero, has_counters);
__ push(rdx);
__ push(rcx);
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::build_method_counters),
rcx);
__ pop(rcx);
__ pop(rdx);
__ movptr(rax, Address(rcx, Method::method_counters_offset()));
__ testptr(rax, rax);
__ jcc(Assembler::zero, dispatch);
__ bind(has_counters);
if (TieredCompilation) {
Label no_mdo;
int increment = InvocationCounter::count_increment;
@ -1613,16 +1630,19 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
__ jmp(dispatch);
}
__ bind(no_mdo);
// Increment backedge counter in Method*
// Increment backedge counter in MethodCounters*
__ movptr(rcx, Address(rcx, Method::method_counters_offset()));
__ increment_mask_and_jump(Address(rcx, be_offset), increment, mask,
rax, false, Assembler::zero, &backedge_counter_overflow);
} else {
// increment counter
__ movptr(rcx, Address(rcx, Method::method_counters_offset()));
__ movl(rax, Address(rcx, be_offset)); // load backedge counter
__ incrementl(rax, InvocationCounter::count_increment); // increment counter
__ movl(Address(rcx, be_offset), rax); // store counter
__ movl(rax, Address(rcx, inv_offset)); // load invocation counter
__ andl(rax, InvocationCounter::count_mask_value); // and the status bits
__ addl(rax, Address(rcx, be_offset)); // add both counters

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -1569,11 +1569,10 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
__ profile_taken_branch(rax, rbx); // rax holds updated MDP, rbx
// holds bumped taken count
const ByteSize be_offset = Method::backedge_counter_offset() +
const ByteSize be_offset = MethodCounters::backedge_counter_offset() +
InvocationCounter::counter_offset();
const ByteSize inv_offset = Method::invocation_counter_offset() +
const ByteSize inv_offset = MethodCounters::invocation_counter_offset() +
InvocationCounter::counter_offset();
const int method_offset = frame::interpreter_frame_method_offset * wordSize;
// Load up edx with the branch displacement
__ movl(rdx, at_bcp(1));
@ -1623,6 +1622,22 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
// r14: locals pointer
__ testl(rdx, rdx); // check if forward or backward branch
__ jcc(Assembler::positive, dispatch); // count only if backward branch
// check if MethodCounters exists
Label has_counters;
__ movptr(rax, Address(rcx, Method::method_counters_offset()));
__ testptr(rax, rax);
__ jcc(Assembler::notZero, has_counters);
__ push(rdx);
__ push(rcx);
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::build_method_counters),
rcx);
__ pop(rcx);
__ pop(rdx);
__ movptr(rax, Address(rcx, Method::method_counters_offset()));
__ jcc(Assembler::zero, dispatch);
__ bind(has_counters);
if (TieredCompilation) {
Label no_mdo;
int increment = InvocationCounter::count_increment;
@ -1640,16 +1655,19 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
__ jmp(dispatch);
}
__ bind(no_mdo);
// Increment backedge counter in Method*
// Increment backedge counter in MethodCounters*
__ movptr(rcx, Address(rcx, Method::method_counters_offset()));
__ increment_mask_and_jump(Address(rcx, be_offset), increment, mask,
rax, false, Assembler::zero, &backedge_counter_overflow);
} else {
// increment counter
__ movptr(rcx, Address(rcx, Method::method_counters_offset()));
__ movl(rax, Address(rcx, be_offset)); // load backedge counter
__ incrementl(rax, InvocationCounter::count_increment); // increment counter
__ movl(Address(rcx, be_offset), rax); // store counter
__ movl(rax, Address(rcx, inv_offset)); // load invocation counter
__ andl(rax, InvocationCounter::count_mask_value); // and the status bits
__ addl(rax, Address(rcx, be_offset)); // add both counters

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -3044,21 +3044,20 @@ void LIRGenerator::increment_event_counter_impl(CodeEmitInfo* info,
assert(level > CompLevel_simple, "Shouldn't be here");
int offset = -1;
LIR_Opr counter_holder = new_register(T_METADATA);
LIR_Opr meth;
LIR_Opr counter_holder;
if (level == CompLevel_limited_profile) {
offset = in_bytes(backedge ? Method::backedge_counter_offset() :
Method::invocation_counter_offset());
__ metadata2reg(method->constant_encoding(), counter_holder);
meth = counter_holder;
address counters_adr = method->ensure_method_counters();
counter_holder = new_pointer_register();
__ move(LIR_OprFact::intptrConst(counters_adr), counter_holder);
offset = in_bytes(backedge ? MethodCounters::backedge_counter_offset() :
MethodCounters::invocation_counter_offset());
} else if (level == CompLevel_full_profile) {
counter_holder = new_register(T_METADATA);
offset = in_bytes(backedge ? MethodData::backedge_counter_offset() :
MethodData::invocation_counter_offset());
ciMethodData* md = method->method_data_or_null();
assert(md != NULL, "Sanity");
__ metadata2reg(md->constant_encoding(), counter_holder);
meth = new_register(T_METADATA);
__ metadata2reg(method->constant_encoding(), meth);
} else {
ShouldNotReachHere();
}
@ -3069,6 +3068,8 @@ void LIRGenerator::increment_event_counter_impl(CodeEmitInfo* info,
__ store(result, counter);
if (notify) {
LIR_Opr mask = load_immediate(frequency << InvocationCounter::count_shift, T_INT);
LIR_Opr meth = new_register(T_METADATA);
__ metadata2reg(method->constant_encoding(), meth);
__ logical_and(result, mask, result);
__ cmp(lir_cond_equal, result, LIR_OprFact::intConst(0));
// The bci for info can point to cmp for if's we want the if bci

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -904,6 +904,20 @@ ciMethodData* ciMethod::method_data_or_null() {
return md;
}
// ------------------------------------------------------------------
// ciMethod::ensure_method_counters
//
address ciMethod::ensure_method_counters() {
check_is_loaded();
VM_ENTRY_MARK;
methodHandle mh(THREAD, get_Method());
MethodCounters *counter = mh->method_counters();
if (counter == NULL) {
counter = Method::build_method_counters(mh(), CHECK_AND_CLEAR_NULL);
}
return (address)counter;
}
// ------------------------------------------------------------------
// ciMethod::should_exclude
//
@ -1191,13 +1205,14 @@ void ciMethod::dump_replay_data(outputStream* st) {
ASSERT_IN_VM;
ResourceMark rm;
Method* method = get_Method();
MethodCounters* mcs = method->method_counters();
Klass* holder = method->method_holder();
st->print_cr("ciMethod %s %s %s %d %d %d %d %d",
holder->name()->as_quoted_ascii(),
method->name()->as_quoted_ascii(),
method->signature()->as_quoted_ascii(),
method->invocation_counter()->raw_counter(),
method->backedge_counter()->raw_counter(),
mcs == NULL ? 0 : mcs->invocation_counter()->raw_counter(),
mcs == NULL ? 0 : mcs->backedge_counter()->raw_counter(),
interpreter_invocation_count(),
interpreter_throwout_count(),
_instructions_size);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -262,6 +262,7 @@ class ciMethod : public ciMetadata {
bool is_klass_loaded(int refinfo_index, bool must_be_resolved) const;
bool check_call(int refinfo_index, bool is_static) const;
bool ensure_method_data(); // make sure it exists in the VM also
address ensure_method_counters();
int instructions_size();
int scale_count(int count, float prof_factor = 1.); // make MDO count commensurate with IIC

View File

@ -920,12 +920,17 @@ void ciReplay::initialize(ciMethod* m) {
method->print_name(tty);
tty->cr();
} else {
EXCEPTION_CONTEXT;
MethodCounters* mcs = method->method_counters();
// m->_instructions_size = rec->instructions_size;
m->_instructions_size = -1;
m->_interpreter_invocation_count = rec->interpreter_invocation_count;
m->_interpreter_throwout_count = rec->interpreter_throwout_count;
method->invocation_counter()->_counter = rec->invocation_counter;
method->backedge_counter()->_counter = rec->backedge_counter;
if (mcs == NULL) {
mcs = Method::build_method_counters(method, CHECK_AND_CLEAR);
}
mcs->invocation_counter()->_counter = rec->invocation_counter;
mcs->backedge_counter()->_counter = rec->backedge_counter;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -454,7 +454,7 @@ IRT_ENTRY(address, InterpreterRuntime::exception_handler_for_exception(JavaThrea
continuation = Interpreter::remove_activation_entry();
#endif
// Count this for compilation purposes
h_method->interpreter_throwout_increment();
h_method->interpreter_throwout_increment(THREAD);
} else {
// handler in this method => change bci/bcp to handler bci/bcp and continue there
handler_pc = h_method->code_base() + handler_bci;
@ -903,6 +903,15 @@ IRT_ENTRY(void, InterpreterRuntime::update_mdp_for_ret(JavaThread* thread, int r
fr.interpreter_frame_set_mdp(new_mdp);
IRT_END
IRT_ENTRY(MethodCounters*, InterpreterRuntime::build_method_counters(JavaThread* thread, Method* m))
MethodCounters* mcs = Method::build_method_counters(m, thread);
if (HAS_PENDING_EXCEPTION) {
assert((PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())), "we expect only an OOM error here");
CLEAR_PENDING_EXCEPTION;
}
return mcs;
IRT_END
IRT_ENTRY(void, InterpreterRuntime::at_safepoint(JavaThread* thread))
// We used to need an explict preserve_arguments here for invoke bytecodes. However,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -169,6 +169,7 @@ class InterpreterRuntime: AllStatic {
#ifdef ASSERT
static void verify_mdp(Method* method, address bcp, address mdp);
#endif // ASSERT
static MethodCounters* build_method_counters(JavaThread* thread, Method* m);
};

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -104,15 +104,19 @@ const char* InvocationCounter::state_as_short_string(State state) {
static address do_nothing(methodHandle method, TRAPS) {
// dummy action for inactive invocation counters
method->invocation_counter()->set_carry();
method->invocation_counter()->set_state(InvocationCounter::wait_for_nothing);
MethodCounters* mcs = method->method_counters();
assert(mcs != NULL, "");
mcs->invocation_counter()->set_carry();
mcs->invocation_counter()->set_state(InvocationCounter::wait_for_nothing);
return NULL;
}
static address do_decay(methodHandle method, TRAPS) {
// decay invocation counters so compilation gets delayed
method->invocation_counter()->decay();
MethodCounters* mcs = method->method_counters();
assert(mcs != NULL, "");
mcs->invocation_counter()->decay();
return NULL;
}

View File

@ -91,7 +91,7 @@ Method::Method(ConstMethod* xconst, AccessFlags access_flags, int size) {
set_hidden(false);
set_dont_inline(false);
set_method_data(NULL);
set_interpreter_throwout_count(0);
set_method_counters(NULL);
set_vtable_index(Method::garbage_vtable_index);
// Fix and bury in Method*
@ -105,16 +105,6 @@ Method::Method(ConstMethod* xconst, AccessFlags access_flags, int size) {
}
NOT_PRODUCT(set_compiled_invocation_count(0);)
set_interpreter_invocation_count(0);
invocation_counter()->init();
backedge_counter()->init();
clear_number_of_breakpoints();
#ifdef TIERED
set_rate(0);
set_prev_event_count(0);
set_prev_time(0);
#endif
}
// Release Method*. The nmethod will be gone when we get here because
@ -124,6 +114,8 @@ void Method::deallocate_contents(ClassLoaderData* loader_data) {
set_constMethod(NULL);
MetadataFactory::free_metadata(loader_data, method_data());
set_method_data(NULL);
MetadataFactory::free_metadata(loader_data, method_counters());
set_method_counters(NULL);
// The nmethod will be gone when we get here.
if (code() != NULL) _code = NULL;
}
@ -323,7 +315,10 @@ bool Method::was_executed_more_than(int n) {
// compiler does not bump invocation counter of compiled methods
return true;
}
else if (_invocation_counter.carry() || (method_data() != NULL && method_data()->invocation_counter()->carry())) {
else if ((method_counters() != NULL &&
method_counters()->invocation_counter()->carry()) ||
(method_data() != NULL &&
method_data()->invocation_counter()->carry())) {
// The carry bit is set when the counter overflows and causes
// a compilation to occur. We don't know how many times
// the counter has been reset, so we simply assume it has
@ -387,6 +382,18 @@ void Method::build_interpreter_method_data(methodHandle method, TRAPS) {
}
}
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, CHECK_NULL);
if (mh->method_counters() == NULL) {
mh->set_method_counters(counters);
} else {
MetadataFactory::free_metadata(loader_data, counters);
}
return mh->method_counters();
}
void Method::cleanup_inline_caches() {
// The current system doesn't use inline caches in the interpreter
// => nothing to do (keep this method around for future use)
@ -794,8 +801,6 @@ void Method::unlink_method() {
set_signature_handler(NULL);
}
NOT_PRODUCT(set_compiled_invocation_count(0);)
invocation_counter()->reset();
backedge_counter()->reset();
_adapter = NULL;
_from_compiled_entry = NULL;
@ -808,8 +813,7 @@ void Method::unlink_method() {
assert(!DumpSharedSpaces || _method_data == NULL, "unexpected method data?");
set_method_data(NULL);
set_interpreter_throwout_count(0);
set_interpreter_invocation_count(0);
set_method_counters(NULL);
}
// Called when the method_holder is getting linked. Setup entrypoints so the method
@ -1545,28 +1549,34 @@ void Method::clear_all_breakpoints() {
int Method::invocation_count() {
MethodCounters *mcs = method_counters();
if (TieredCompilation) {
MethodData* const mdo = method_data();
if (invocation_counter()->carry() || ((mdo != NULL) ? mdo->invocation_counter()->carry() : false)) {
if (((mcs != NULL) ? mcs->invocation_counter()->carry() : false) ||
((mdo != NULL) ? mdo->invocation_counter()->carry() : false)) {
return InvocationCounter::count_limit;
} else {
return invocation_counter()->count() + ((mdo != NULL) ? mdo->invocation_counter()->count() : 0);
return ((mcs != NULL) ? mcs->invocation_counter()->count() : 0) +
((mdo != NULL) ? mdo->invocation_counter()->count() : 0);
}
} else {
return invocation_counter()->count();
return (mcs == NULL) ? 0 : mcs->invocation_counter()->count();
}
}
int Method::backedge_count() {
MethodCounters *mcs = method_counters();
if (TieredCompilation) {
MethodData* const mdo = method_data();
if (backedge_counter()->carry() || ((mdo != NULL) ? mdo->backedge_counter()->carry() : false)) {
if (((mcs != NULL) ? mcs->backedge_counter()->carry() : false) ||
((mdo != NULL) ? mdo->backedge_counter()->carry() : false)) {
return InvocationCounter::count_limit;
} else {
return backedge_counter()->count() + ((mdo != NULL) ? mdo->backedge_counter()->count() : 0);
return ((mcs != NULL) ? mcs->backedge_counter()->count() : 0) +
((mdo != NULL) ? mdo->backedge_counter()->count() : 0);
}
} else {
return backedge_counter()->count();
return (mcs == NULL) ? 0 : mcs->backedge_counter()->count();
}
}
@ -1621,12 +1631,12 @@ void BreakpointInfo::set(Method* method) {
assert(orig_bytecode() == code, "original bytecode must be the same");
}
#endif
Thread *thread = Thread::current();
*method->bcp_from(_bci) = Bytecodes::_breakpoint;
method->incr_number_of_breakpoints();
method->incr_number_of_breakpoints(thread);
SystemDictionary::notice_modification();
{
// Deoptimize all dependents on this method
Thread *thread = Thread::current();
HandleMark hm(thread);
methodHandle mh(thread, method);
Universe::flush_dependents_on_method(mh);
@ -1636,7 +1646,7 @@ void BreakpointInfo::set(Method* method) {
void BreakpointInfo::clear(Method* method) {
*method->bcp_from(_bci) = orig_bytecode();
assert(method->number_of_breakpoints() > 0, "must not go negative");
method->decr_number_of_breakpoints();
method->decr_number_of_breakpoints(Thread::current());
}
// jmethodID handling

View File

@ -31,6 +31,7 @@
#include "interpreter/invocationCounter.hpp"
#include "oops/annotations.hpp"
#include "oops/constantPool.hpp"
#include "oops/methodCounters.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/oop.hpp"
#include "oops/typeArrayOop.hpp"
@ -100,6 +101,7 @@ class CheckedExceptionElement;
class LocalVariableTableElement;
class AdapterHandlerEntry;
class MethodData;
class MethodCounters;
class ConstMethod;
class InlineTableSizes;
class KlassSizeStats;
@ -109,7 +111,7 @@ class Method : public Metadata {
private:
ConstMethod* _constMethod; // Method read-only data.
MethodData* _method_data;
int _interpreter_invocation_count; // Count of times invoked (reused as prev_event_count in tiered)
MethodCounters* _method_counters;
AccessFlags _access_flags; // Access flags
int _vtable_index; // vtable index of this method (see VtableIndexFlag)
// note: can have vtables with >2**16 elements (because of inheritance)
@ -124,15 +126,6 @@ class Method : public Metadata {
_hidden : 1,
_dont_inline : 1,
: 3;
u2 _interpreter_throwout_count; // Count of times method was exited via exception while interpreting
u2 _number_of_breakpoints; // fullspeed debugging support
InvocationCounter _invocation_counter; // Incremented before each activation of the method - used to trigger frequency-based optimizations
InvocationCounter _backedge_counter; // Incremented before each backedge taken - used to trigger frequencey-based optimizations
#ifdef TIERED
float _rate; // Events (invocation and backedge counter increments) per millisecond
jlong _prev_time; // Previous time the rate was acquired
#endif
#ifndef PRODUCT
int _compiled_invocation_count; // Number of nmethod invocations so far (for perf. debugging)
@ -247,11 +240,31 @@ class Method : public Metadata {
void clear_all_breakpoints();
// Tracking number of breakpoints, for fullspeed debugging.
// Only mutated by VM thread.
u2 number_of_breakpoints() const { return _number_of_breakpoints; }
void incr_number_of_breakpoints() { ++_number_of_breakpoints; }
void decr_number_of_breakpoints() { --_number_of_breakpoints; }
u2 number_of_breakpoints() const {
if (method_counters() == NULL) {
return 0;
} else {
return method_counters()->number_of_breakpoints();
}
}
void incr_number_of_breakpoints(TRAPS) {
MethodCounters* mcs = get_method_counters(CHECK);
if (mcs != NULL) {
mcs->incr_number_of_breakpoints();
}
}
void decr_number_of_breakpoints(TRAPS) {
MethodCounters* mcs = get_method_counters(CHECK);
if (mcs != NULL) {
mcs->decr_number_of_breakpoints();
}
}
// Initialization only
void clear_number_of_breakpoints() { _number_of_breakpoints = 0; }
void clear_number_of_breakpoints() {
if (method_counters() != NULL) {
method_counters()->clear_number_of_breakpoints();
}
}
// index into InstanceKlass methods() array
// note: also used by jfr
@ -288,14 +301,20 @@ class Method : public Metadata {
void set_highest_osr_comp_level(int level);
// Count of times method was exited via exception while interpreting
void interpreter_throwout_increment() {
if (_interpreter_throwout_count < 65534) {
_interpreter_throwout_count++;
void interpreter_throwout_increment(TRAPS) {
MethodCounters* mcs = get_method_counters(CHECK);
if (mcs != NULL) {
mcs->interpreter_throwout_increment();
}
}
int interpreter_throwout_count() const { return _interpreter_throwout_count; }
void set_interpreter_throwout_count(int count) { _interpreter_throwout_count = count; }
int interpreter_throwout_count() const {
if (method_counters() == NULL) {
return 0;
} else {
return method_counters()->interpreter_throwout_count();
}
}
// size of parameters
int size_of_parameters() const { return constMethod()->size_of_parameters(); }
@ -339,23 +358,54 @@ class Method : public Metadata {
MethodData* method_data() const {
return _method_data;
}
void set_method_data(MethodData* data) {
_method_data = data;
}
// invocation counter
InvocationCounter* invocation_counter() { return &_invocation_counter; }
InvocationCounter* backedge_counter() { return &_backedge_counter; }
MethodCounters* method_counters() const {
return _method_counters;
}
void set_method_counters(MethodCounters* counters) {
_method_counters = counters;
}
#ifdef TIERED
// We are reusing interpreter_invocation_count as a holder for the previous event count!
// We can do that since interpreter_invocation_count is not used in tiered.
int prev_event_count() const { return _interpreter_invocation_count; }
void set_prev_event_count(int count) { _interpreter_invocation_count = count; }
jlong prev_time() const { return _prev_time; }
void set_prev_time(jlong time) { _prev_time = time; }
float rate() const { return _rate; }
void set_rate(float rate) { _rate = rate; }
int prev_event_count() const {
if (method_counters() == NULL) {
return 0;
} else {
return method_counters()->interpreter_invocation_count();
}
}
void set_prev_event_count(int count, TRAPS) {
MethodCounters* mcs = get_method_counters(CHECK);
if (mcs != NULL) {
mcs->set_interpreter_invocation_count(count);
}
}
jlong prev_time() const {
return method_counters() == NULL ? 0 : method_counters()->prev_time();
}
void set_prev_time(jlong time, TRAPS) {
MethodCounters* mcs = get_method_counters(CHECK);
if (mcs != NULL) {
mcs->set_prev_time(time);
}
}
float rate() const {
return method_counters() == NULL ? 0 : method_counters()->rate();
}
void set_rate(float rate, TRAPS) {
MethodCounters* mcs = get_method_counters(CHECK);
if (mcs != NULL) {
mcs->set_rate(rate);
}
}
#endif
int invocation_count();
@ -366,14 +416,17 @@ class Method : public Metadata {
static void build_interpreter_method_data(methodHandle method, TRAPS);
static MethodCounters* build_method_counters(Method* m, TRAPS);
int interpreter_invocation_count() {
if (TieredCompilation) return invocation_count();
else return _interpreter_invocation_count;
else return (method_counters() == NULL) ? 0 :
method_counters()->interpreter_invocation_count();
}
void set_interpreter_invocation_count(int count) { _interpreter_invocation_count = count; }
int increment_interpreter_invocation_count() {
int increment_interpreter_invocation_count(TRAPS) {
if (TieredCompilation) ShouldNotReachHere();
return ++_interpreter_invocation_count;
MethodCounters* mcs = get_method_counters(CHECK_0);
return (mcs == NULL) ? 0 : mcs->increment_interpreter_invocation_count();
}
#ifndef PRODUCT
@ -582,12 +635,12 @@ class Method : public Metadata {
#endif /* CC_INTERP */
static ByteSize from_compiled_offset() { return byte_offset_of(Method, _from_compiled_entry); }
static ByteSize code_offset() { return byte_offset_of(Method, _code); }
static ByteSize invocation_counter_offset() { return byte_offset_of(Method, _invocation_counter); }
static ByteSize backedge_counter_offset() { return byte_offset_of(Method, _backedge_counter); }
static ByteSize method_data_offset() {
return byte_offset_of(Method, _method_data);
}
static ByteSize interpreter_invocation_counter_offset() { return byte_offset_of(Method, _interpreter_invocation_count); }
static ByteSize method_counters_offset() {
return byte_offset_of(Method, _method_counters);
}
#ifndef PRODUCT
static ByteSize compiled_invocation_counter_offset() { return byte_offset_of(Method, _compiled_invocation_count); }
#endif // not PRODUCT
@ -598,8 +651,6 @@ class Method : public Metadata {
// for code generation
static int method_data_offset_in_bytes() { return offset_of(Method, _method_data); }
static int interpreter_invocation_counter_offset_in_bytes()
{ return offset_of(Method, _interpreter_invocation_count); }
static int intrinsic_id_offset_in_bytes() { return offset_of(Method, _intrinsic_id); }
static int intrinsic_id_size_in_bytes() { return sizeof(u1); }
@ -757,6 +808,13 @@ class Method : public Metadata {
private:
void print_made_not_compilable(int comp_level, bool is_osr, bool report, const char* reason);
MethodCounters* get_method_counters(TRAPS) {
if (_method_counters == NULL) {
build_method_counters(this, CHECK_AND_CLEAR_NULL);
}
return _method_counters;
}
public:
bool is_not_c1_compilable() const { return access_flags().is_not_c1_compilable(); }
void set_not_c1_compilable() { _access_flags.set_not_c1_compilable(); }

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* 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.
*
*/
#include "precompiled.hpp"
#include "oops/methodCounters.hpp"
#include "runtime/thread.inline.hpp"
MethodCounters* MethodCounters::allocate(ClassLoaderData* loader_data, TRAPS) {
return new(loader_data, size(), false, THREAD) MethodCounters();
}
void MethodCounters::clear_counters() {
invocation_counter()->reset();
backedge_counter()->reset();
set_interpreter_throwout_count(0);
set_interpreter_invocation_count(0);
}

View File

@ -0,0 +1,124 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* 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.
*
*/
#ifndef SHARE_VM_OOPS_METHODCOUNTERS_HPP
#define SHARE_VM_OOPS_METHODCOUNTERS_HPP
#include "oops/metadata.hpp"
#include "interpreter/invocationCounter.hpp"
class MethodCounters: public MetaspaceObj {
friend class VMStructs;
private:
int _interpreter_invocation_count; // Count of times invoked (reused as prev_event_count in tiered)
u2 _interpreter_throwout_count; // Count of times method was exited via exception while interpreting
u2 _number_of_breakpoints; // fullspeed debugging support
InvocationCounter _invocation_counter; // Incremented before each activation of the method - used to trigger frequency-based optimizations
InvocationCounter _backedge_counter; // Incremented before each backedge taken - used to trigger frequencey-based optimizations
#ifdef TIERED
float _rate; // Events (invocation and backedge counter increments) per millisecond
jlong _prev_time; // Previous time the rate was acquired
#endif
MethodCounters() : _interpreter_invocation_count(0),
_interpreter_throwout_count(0),
_number_of_breakpoints(0)
#ifdef TIERED
, _rate(0),
_prev_time(0)
#endif
{
invocation_counter()->init();
backedge_counter()->init();
}
public:
static MethodCounters* allocate(ClassLoaderData* loader_data, TRAPS);
void deallocate_contents(ClassLoaderData* loader_data) {}
DEBUG_ONLY(bool on_stack() { return false; }) // for template
static int size() { return sizeof(MethodCounters) / wordSize; }
bool is_klass() const { return false; }
void clear_counters();
int interpreter_invocation_count() {
return _interpreter_invocation_count;
}
void set_interpreter_invocation_count(int count) {
_interpreter_invocation_count = count;
}
int increment_interpreter_invocation_count() {
return ++_interpreter_invocation_count;
}
void interpreter_throwout_increment() {
if (_interpreter_throwout_count < 65534) {
_interpreter_throwout_count++;
}
}
int interpreter_throwout_count() const {
return _interpreter_throwout_count;
}
void set_interpreter_throwout_count(int count) {
_interpreter_throwout_count = count;
}
u2 number_of_breakpoints() const { return _number_of_breakpoints; }
void incr_number_of_breakpoints() { ++_number_of_breakpoints; }
void decr_number_of_breakpoints() { --_number_of_breakpoints; }
void clear_number_of_breakpoints() { _number_of_breakpoints = 0; }
#ifdef TIERED
jlong prev_time() const { return _prev_time; }
void set_prev_time(jlong time) { _prev_time = time; }
float rate() const { return _rate; }
void set_rate(float rate) { _rate = rate; }
#endif
// invocation counter
InvocationCounter* invocation_counter() { return &_invocation_counter; }
InvocationCounter* backedge_counter() { return &_backedge_counter; }
static ByteSize interpreter_invocation_counter_offset() {
return byte_offset_of(MethodCounters, _interpreter_invocation_count);
}
static ByteSize invocation_counter_offset() {
return byte_offset_of(MethodCounters, _invocation_counter);
}
static ByteSize backedge_counter_offset() {
return byte_offset_of(MethodCounters, _backedge_counter);
}
static int interpreter_invocation_counter_offset_in_bytes() {
return offset_of(MethodCounters, _interpreter_invocation_count);
}
};
#endif //SHARE_VM_OOPS_METHODCOUNTERS_HPP

View File

@ -732,14 +732,17 @@ int MethodData::mileage_of(Method* method) {
} else {
int iic = method->interpreter_invocation_count();
if (mileage < iic) mileage = iic;
InvocationCounter* ic = method->invocation_counter();
InvocationCounter* bc = method->backedge_counter();
int icval = ic->count();
if (ic->carry()) icval += CompileThreshold;
if (mileage < icval) mileage = icval;
int bcval = bc->count();
if (bc->carry()) bcval += CompileThreshold;
if (mileage < bcval) mileage = bcval;
MethodCounters* mcs = method->method_counters();
if (mcs != NULL) {
InvocationCounter* ic = mcs->invocation_counter();
InvocationCounter* bc = mcs->backedge_counter();
int icval = ic->count();
if (ic->carry()) icval += CompileThreshold;
if (mileage < icval) mileage = icval;
int bcval = bc->count();
if (bc->carry()) bcval += CompileThreshold;
if (mileage < bcval) mileage = bcval;
}
}
return mileage;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -337,19 +337,21 @@ void Parse::increment_and_test_invocation_counter(int limit) {
if (!count_invocations()) return;
// Get the Method* node.
const TypePtr* adr_type = TypeMetadataPtr::make(method());
Node *method_node = makecon(adr_type);
ciMethod* m = method();
address counters_adr = m->ensure_method_counters();
// Load the interpreter_invocation_counter from the Method*.
int offset = Method::interpreter_invocation_counter_offset_in_bytes();
Node* adr_node = basic_plus_adr(method_node, method_node, offset);
Node* cnt = make_load(NULL, adr_node, TypeInt::INT, T_INT, adr_type);
Node* ctrl = control();
const TypePtr* adr_type = TypeRawPtr::make(counters_adr);
Node *counters_node = makecon(adr_type);
Node* adr_iic_node = basic_plus_adr(counters_node, counters_node,
MethodCounters::interpreter_invocation_counter_offset_in_bytes());
Node* cnt = make_load(ctrl, adr_iic_node, TypeInt::INT, T_INT, adr_type);
test_counter_against_threshold(cnt, limit);
// Add one to the counter and store
Node* incr = _gvn.transform(new (C) AddINode(cnt, _gvn.intcon(1)));
store_to_memory( NULL, adr_node, incr, T_INT, adr_type );
store_to_memory( ctrl, adr_iic_node, incr, T_INT, adr_type );
}
//----------------------------method_data_addressing---------------------------

View File

@ -278,6 +278,7 @@ WB_ENTRY(void, WB_ClearMethodState(JNIEnv* env, jobject o, jobject method))
methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
MutexLockerEx mu(Compile_lock);
MethodData* mdo = mh->method_data();
MethodCounters* mcs = mh->method_counters();
if (mdo != NULL) {
mdo->init();
@ -288,20 +289,22 @@ WB_ENTRY(void, WB_ClearMethodState(JNIEnv* env, jobject o, jobject method))
}
}
mh->backedge_counter()->init();
mh->invocation_counter()->init();
mh->set_interpreter_invocation_count(0);
mh->set_interpreter_throwout_count(0);
mh->clear_not_c1_compilable();
mh->clear_not_c2_compilable();
mh->clear_not_c2_osr_compilable();
NOT_PRODUCT(mh->set_compiled_invocation_count(0));
if (mcs != NULL) {
mcs->backedge_counter()->init();
mcs->invocation_counter()->init();
mcs->set_interpreter_invocation_count(0);
mcs->set_interpreter_throwout_count(0);
#ifdef TIERED
mh->set_rate(0.0F);
mh->set_prev_event_count(0);
mh->set_prev_time(0);
mcs->set_rate(0.0F);
mh->set_prev_event_count(0, THREAD);
mh->set_prev_time(0, THREAD);
#endif
}
WB_END
WB_ENTRY(jboolean, WB_IsInStringTable(JNIEnv* env, jobject o, jstring javaString))

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -74,10 +74,11 @@ void AdvancedThresholdPolicy::initialize() {
// update_rate() is called from select_task() while holding a compile queue lock.
void AdvancedThresholdPolicy::update_rate(jlong t, Method* m) {
JavaThread* THREAD = JavaThread::current();
if (is_old(m)) {
// We don't remove old methods from the queue,
// so we can just zero the rate.
m->set_rate(0);
m->set_rate(0, THREAD);
return;
}
@ -93,13 +94,13 @@ void AdvancedThresholdPolicy::update_rate(jlong t, Method* m) {
if (delta_s >= TieredRateUpdateMinTime) {
// And we must've taken the previous point at least 1ms before.
if (delta_t >= TieredRateUpdateMinTime && delta_e > 0) {
m->set_prev_time(t);
m->set_prev_event_count(event_count);
m->set_rate((float)delta_e / (float)delta_t); // Rate is events per millisecond
m->set_prev_time(t, THREAD);
m->set_prev_event_count(event_count, THREAD);
m->set_rate((float)delta_e / (float)delta_t, THREAD); // Rate is events per millisecond
} else
if (delta_t > TieredRateUpdateMaxTime && delta_e == 0) {
// If nothing happened for 25ms, zero the rate. Don't modify prev values.
m->set_rate(0);
m->set_rate(0, THREAD);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -198,8 +198,10 @@ void NonTieredCompPolicy::reset_counter_for_invocation_event(methodHandle m) {
// BUT also make sure the method doesn't look like it was never executed.
// Set carry bit and reduce counter's value to min(count, CompileThreshold/2).
m->invocation_counter()->set_carry();
m->backedge_counter()->set_carry();
MethodCounters* mcs = m->method_counters();
assert(mcs != NULL, "MethodCounters cannot be NULL for profiling");
mcs->invocation_counter()->set_carry();
mcs->backedge_counter()->set_carry();
assert(!m->was_never_executed(), "don't reset to 0 -- could be mistaken for never-executed");
}
@ -207,8 +209,10 @@ void NonTieredCompPolicy::reset_counter_for_invocation_event(methodHandle m) {
void NonTieredCompPolicy::reset_counter_for_back_branch_event(methodHandle m) {
// Delay next back-branch event but pump up invocation counter to triger
// whole method compilation.
InvocationCounter* i = m->invocation_counter();
InvocationCounter* b = m->backedge_counter();
MethodCounters* mcs = m->method_counters();
assert(mcs != NULL, "MethodCounters cannot be NULL for profiling");
InvocationCounter* i = mcs->invocation_counter();
InvocationCounter* b = mcs->backedge_counter();
// Don't set invocation_counter's value too low otherwise the method will
// look like immature (ic < ~5300) which prevents the inlining based on
@ -227,7 +231,10 @@ void NonTieredCompPolicy::reset_counter_for_back_branch_event(methodHandle m) {
class CounterDecay : public AllStatic {
static jlong _last_timestamp;
static void do_method(Method* m) {
m->invocation_counter()->decay();
MethodCounters* mcs = m->method_counters();
if (mcs != NULL) {
mcs->invocation_counter()->decay();
}
}
public:
static void decay();
@ -265,30 +272,44 @@ void NonTieredCompPolicy::do_safepoint_work() {
void NonTieredCompPolicy::reprofile(ScopeDesc* trap_scope, bool is_osr) {
ScopeDesc* sd = trap_scope;
MethodCounters* mcs;
InvocationCounter* c;
for (; !sd->is_top(); sd = sd->sender()) {
// Reset ICs of inlined methods, since they can trigger compilations also.
sd->method()->invocation_counter()->reset();
mcs = sd->method()->method_counters();
if (mcs != NULL) {
// Reset ICs of inlined methods, since they can trigger compilations also.
mcs->invocation_counter()->reset();
}
}
InvocationCounter* c = sd->method()->invocation_counter();
if (is_osr) {
// It was an OSR method, so bump the count higher.
c->set(c->state(), CompileThreshold);
} else {
c->reset();
mcs = sd->method()->method_counters();
if (mcs != NULL) {
c = mcs->invocation_counter();
if (is_osr) {
// It was an OSR method, so bump the count higher.
c->set(c->state(), CompileThreshold);
} else {
c->reset();
}
mcs->backedge_counter()->reset();
}
sd->method()->backedge_counter()->reset();
}
// This method can be called by any component of the runtime to notify the policy
// that it's recommended to delay the complation of this method.
void NonTieredCompPolicy::delay_compilation(Method* method) {
method->invocation_counter()->decay();
method->backedge_counter()->decay();
MethodCounters* mcs = method->method_counters();
if (mcs != NULL) {
mcs->invocation_counter()->decay();
mcs->backedge_counter()->decay();
}
}
void NonTieredCompPolicy::disable_compilation(Method* method) {
method->invocation_counter()->set_state(InvocationCounter::wait_for_nothing);
method->backedge_counter()->set_state(InvocationCounter::wait_for_nothing);
MethodCounters* mcs = method->method_counters();
if (mcs != NULL) {
mcs->invocation_counter()->set_state(InvocationCounter::wait_for_nothing);
mcs->backedge_counter()->set_state(InvocationCounter::wait_for_nothing);
}
}
CompileTask* NonTieredCompPolicy::select_task(CompileQueue* compile_queue) {
@ -371,8 +392,10 @@ nmethod* NonTieredCompPolicy::event(methodHandle method, methodHandle inlinee, i
#ifndef PRODUCT
void NonTieredCompPolicy::trace_frequency_counter_overflow(methodHandle m, int branch_bci, int bci) {
if (TraceInvocationCounterOverflow) {
InvocationCounter* ic = m->invocation_counter();
InvocationCounter* bc = m->backedge_counter();
MethodCounters* mcs = m->method_counters();
assert(mcs != NULL, "MethodCounters cannot be NULL for profiling");
InvocationCounter* ic = mcs->invocation_counter();
InvocationCounter* bc = mcs->backedge_counter();
ResourceMark rm;
const char* msg =
bci == InvocationEntryBci

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -421,7 +421,8 @@ class interpretedNode : public ProfilerNode {
void print_method_on(outputStream* st) {
ProfilerNode::print_method_on(st);
if (Verbose) method()->invocation_counter()->print_short();
MethodCounters* mcs = method()->method_counters();
if (Verbose && mcs != NULL) mcs->invocation_counter()->print_short();
}
};

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -153,8 +153,10 @@ void SimpleThresholdPolicy::set_carry_if_necessary(InvocationCounter *counter) {
// Set carry flags on the counters if necessary
void SimpleThresholdPolicy::handle_counter_overflow(Method* method) {
set_carry_if_necessary(method->invocation_counter());
set_carry_if_necessary(method->backedge_counter());
MethodCounters *mcs = method->method_counters();
assert(mcs != NULL, "");
set_carry_if_necessary(mcs->invocation_counter());
set_carry_if_necessary(mcs->backedge_counter());
MethodData* mdo = method->method_data();
if (mdo != NULL) {
set_carry_if_necessary(mdo->invocation_counter());

View File

@ -77,6 +77,7 @@
#include "oops/klass.hpp"
#include "oops/markOop.hpp"
#include "oops/methodData.hpp"
#include "oops/methodCounters.hpp"
#include "oops/method.hpp"
#include "oops/objArrayKlass.hpp"
#include "oops/objArrayOop.hpp"
@ -348,16 +349,17 @@ typedef BinaryTreeDictionary<Metablock, FreeList> MetablockTreeDictionary;
nonstatic_field(MethodData, _arg_local, intx) \
nonstatic_field(MethodData, _arg_stack, intx) \
nonstatic_field(MethodData, _arg_returned, intx) \
nonstatic_field(Method, _constMethod, ConstMethod*) \
nonstatic_field(Method, _method_data, MethodData*) \
nonstatic_field(Method, _interpreter_invocation_count, int) \
nonstatic_field(MethodCounters, _interpreter_invocation_count, int) \
nonstatic_field(MethodCounters, _interpreter_throwout_count, u2) \
nonstatic_field(MethodCounters, _number_of_breakpoints, u2) \
nonstatic_field(MethodCounters, _invocation_counter, InvocationCounter) \
nonstatic_field(MethodCounters, _backedge_counter, InvocationCounter) \
nonstatic_field(Method, _constMethod, ConstMethod*) \
nonstatic_field(Method, _method_data, MethodData*) \
nonstatic_field(Method, _method_counters, MethodCounters*) \
nonstatic_field(Method, _access_flags, AccessFlags) \
nonstatic_field(Method, _vtable_index, int) \
nonstatic_field(Method, _method_size, u2) \
nonstatic_field(Method, _interpreter_throwout_count, u2) \
nonstatic_field(Method, _number_of_breakpoints, u2) \
nonstatic_field(Method, _invocation_counter, InvocationCounter) \
nonstatic_field(Method, _backedge_counter, InvocationCounter) \
nonproduct_nonstatic_field(Method, _compiled_invocation_count, int) \
volatile_nonstatic_field(Method, _code, nmethod*) \
nonstatic_field(Method, _i2i_entry, address) \
@ -1382,6 +1384,7 @@ typedef BinaryTreeDictionary<Metablock, FreeList> MetablockTreeDictionary;
declare_type(ConstantPoolCache, MetaspaceObj) \
declare_type(MethodData, Metadata) \
declare_type(Method, Metadata) \
declare_type(MethodCounters, MetaspaceObj) \
declare_type(ConstMethod, MetaspaceObj) \
\
declare_toplevel_type(Symbol) \