Merge
This commit is contained in:
commit
a86e7e948c
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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 );
|
||||
|
@ -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 );
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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(); }
|
||||
|
37
hotspot/src/share/vm/oops/methodCounters.cpp
Normal file
37
hotspot/src/share/vm/oops/methodCounters.cpp
Normal 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);
|
||||
}
|
124
hotspot/src/share/vm/oops/methodCounters.hpp
Normal file
124
hotspot/src/share/vm/oops/methodCounters.hpp
Normal 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
|
@ -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;
|
||||
}
|
||||
|
@ -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---------------------------
|
||||
|
@ -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))
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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) \
|
||||
|
Loading…
Reference in New Issue
Block a user