--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Method.java Thu Apr 11 21:54:46 2013 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Method.java Mon Apr 15 21:25:23 2013 -0400
@@ -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 @@
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 @@
// 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 @@
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 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 int interpreterThrowoutCount() {
- return (int) interpreterThrowoutCountField.getValue(this);
+ return getMethodCounters().interpreterThrowoutCount();
}
public int interpreterInvocationCount() {
- return (int) interpreterInvocationCountField.getValue(this);
+ return getMethodCounters().interpreterInvocationCount();
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/MethodCounters.java Mon Apr 15 21:25:23 2013 -0400
@@ -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) {
+ }
+}
+
--- a/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp Thu Apr 11 21:54:46 2013 -0700
+++ b/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp Mon Apr 15 21:25:23 2013 -0400
@@ -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 @@
// ??: 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 @@
__ cmp(O0, G3_scratch);
__ br(Assembler::greaterEqualUnsigned, false, Assembler::pn, *overflow);
__ delayed()->nop();
-
+ __ bind(done);
}
address InterpreterGenerator::generate_empty_entry(void) {
--- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp Thu Apr 11 21:54:46 2013 -0700
+++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp Mon Apr 15 21:25:23 2013 -0400
@@ -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 @@
#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() +
- InvocationCounter::counter_offset());
- Address be_counter (G5_method, Method::backedge_counter_offset() +
+ assert_different_registers(Rcounters, Rtmp, Rtmp2);
+
+ Address inv_counter(Rcounters, MethodCounters::invocation_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 */
+ Address be_counter (Rcounters, MethodCounters::backedge_counter_offset() +
+ InvocationCounter::counter_offset());
int delta = InvocationCounter::count_increment;
// Load each counter in a register
@@ -2122,19 +2132,15 @@
// 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() +
- InvocationCounter::counter_offset());
- Address inv_counter(G5_method, Method::invocation_counter_offset() +
+ assert_different_registers(Rcounters, Rtmp, Rtmp2);
+
+ Address be_counter (Rcounters, MethodCounters::backedge_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 */
+ Address inv_counter(Rcounters, MethodCounters::invocation_counter_offset() +
+ InvocationCounter::counter_offset());
+
int delta = InvocationCounter::count_increment;
// Load each counter in a register
ld( be_counter, Rtmp );
--- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp Thu Apr 11 21:54:46 2013 -0700
+++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp Mon Apr 15 21:25:23 2013 -0400
@@ -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 @@
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 );
--- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Thu Apr 11 21:54:46 2013 -0700
+++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Mon Apr 15 21:25:23 2013 -0400
@@ -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 @@
// ??: 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 @@
__ 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 @@
__ cmp(O0, G3_scratch);
__ br(Assembler::greaterEqualUnsigned, false, Assembler::pn, *overflow); // Far distance
__ delayed()->nop();
+ __ bind(done);
}
}
--- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp Thu Apr 11 21:54:46 2013 -0700
+++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp Mon Apr 15 21:25:23 2013 -0400
@@ -1604,9 +1604,8 @@
// 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 ) {
@@ -1616,6 +1615,9 @@
// 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;
@@ -1628,21 +1630,22 @@
// 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
@@ -1679,15 +1682,15 @@
} 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);
}
}
}
--- a/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp Thu Apr 11 21:54:46 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp Mon Apr 15 21:25:23 2013 -0400
@@ -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 @@
// rcx: invocation counter
//
void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile_method, Label* profile_method_continue) {
-
- const Address invocation_counter(rbx, Method::invocation_counter_offset() + InvocationCounter::counter_offset());
- const Address backedge_counter (rbx, Method::backedge_counter_offset() + InvocationCounter::counter_offset());
-
- if (ProfileInterpreter) { // %%% Merge this into MethodData*
- __ incrementl(Address(rbx,Method::interpreter_invocation_counter_offset()));
+ 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());
+
+ __ 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);
__ 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 @@
__ 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 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 @@
}
#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
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp Thu Apr 11 21:54:46 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp Mon Apr 15 21:25:23 2013 -0400
@@ -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 @@
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) {
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp Thu Apr 11 21:54:46 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp Mon Apr 15 21:25:23 2013 -0400
@@ -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 @@
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);
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp Thu Apr 11 21:54:46 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp Mon Apr 15 21:25:23 2013 -0400
@@ -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 @@
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) {
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp Thu Apr 11 21:54:46 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp Mon Apr 15 21:25:23 2013 -0400
@@ -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 @@
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);
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Thu Apr 11 21:54:46 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Mon Apr 15 21:25:23 2013 -0400
@@ -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 @@
// 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 @@
__ 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());
+
+ __ 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);
+ __ incrementl(rcx, InvocationCounter::count_increment);
+ __ movl(invocation_counter, rcx); // save invocation count
- __ incrementl(rcx, InvocationCounter::count_increment);
+ __ 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 @@
__ cmp32(rcx,
ExternalAddress((address)&InvocationCounter::InterpreterInvocationLimit));
__ jcc(Assembler::aboveEqual, *overflow);
+ __ bind(done);
}
}
@@ -868,7 +884,6 @@
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 @@
// 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 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 @@
__ bind(exit);
}
- if (inc_counter) __ movl(rcx, invocation_counter); // (pre-)fetch invocation count
// initialize fixed part of activation frame
generate_fixed_frame(false);
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Thu Apr 11 21:54:46 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Mon Apr 15 21:25:23 2013 -0400
@@ -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 @@
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 @@
__ 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
- __ incrementl(rcx, InvocationCounter::count_increment);
+ __ 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 @@
__ cmp32(rcx, ExternalAddress((address)&InvocationCounter::InterpreterInvocationLimit));
__ jcc(Assembler::aboveEqual, *overflow);
+ __ bind(done);
}
}
@@ -843,9 +854,6 @@
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 @@
// (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 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 @@
__ bind(exit);
}
- // (pre-)fetch invocation count
- if (inc_counter) {
- __ movl(rcx, invocation_counter);
- }
// initialize fixed part of activation frame
generate_fixed_frame(false);
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp Thu Apr 11 21:54:46 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp Mon Apr 15 21:25:23 2013 -0400
@@ -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 @@
__ 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 @@
__ 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 @@
__ 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
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp Thu Apr 11 21:54:46 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp Mon Apr 15 21:25:23 2013 -0400
@@ -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
@@ -1564,11 +1564,10 @@
__ 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));
@@ -1618,6 +1617,22 @@
// 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;
@@ -1635,16 +1650,19 @@
__ 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
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Thu Apr 11 21:54:46 2013 -0700
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Mon Apr 15 21:25:23 2013 -0400
@@ -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 @@
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 @@
__ 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
--- a/hotspot/src/share/vm/ci/ciMethod.cpp Thu Apr 11 21:54:46 2013 -0700
+++ b/hotspot/src/share/vm/ci/ciMethod.cpp Mon Apr 15 21:25:23 2013 -0400
@@ -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
@@ -905,6 +905,20 @@
}
// ------------------------------------------------------------------
+// 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
//
// Should this method be excluded from compilation?
@@ -1191,13 +1205,14 @@
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);
--- a/hotspot/src/share/vm/ci/ciMethod.hpp Thu Apr 11 21:54:46 2013 -0700
+++ b/hotspot/src/share/vm/ci/ciMethod.hpp Mon Apr 15 21:25:23 2013 -0400
@@ -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 @@
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
--- a/hotspot/src/share/vm/ci/ciReplay.cpp Thu Apr 11 21:54:46 2013 -0700
+++ b/hotspot/src/share/vm/ci/ciReplay.cpp Mon Apr 15 21:25:23 2013 -0400
@@ -920,12 +920,17 @@
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;
}
}
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Thu Apr 11 21:54:46 2013 -0700
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Mon Apr 15 21:25:23 2013 -0400
@@ -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 @@
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 @@
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,
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp Thu Apr 11 21:54:46 2013 -0700
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp Mon Apr 15 21:25:23 2013 -0400
@@ -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 @@
#ifdef ASSERT
static void verify_mdp(Method* method, address bcp, address mdp);
#endif // ASSERT
+ static MethodCounters* build_method_counters(JavaThread* thread, Method* m);
};
--- a/hotspot/src/share/vm/interpreter/invocationCounter.cpp Thu Apr 11 21:54:46 2013 -0700
+++ b/hotspot/src/share/vm/interpreter/invocationCounter.cpp Mon Apr 15 21:25:23 2013 -0400
@@ -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 @@
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;
}
--- a/hotspot/src/share/vm/oops/method.cpp Thu Apr 11 21:54:46 2013 -0700
+++ b/hotspot/src/share/vm/oops/method.cpp Mon Apr 15 21:25:23 2013 -0400
@@ -91,7 +91,7 @@
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 @@
}
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 @@
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 @@
// 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 @@
}
}
+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 @@
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 @@
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 @@
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 @@
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::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
--- a/hotspot/src/share/vm/oops/method.hpp Thu Apr 11 21:54:46 2013 -0700
+++ b/hotspot/src/share/vm/oops/method.hpp Mon Apr 15 21:25:23 2013 -0400
@@ -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 LocalVariableTableElement;
class AdapterHandlerEntry;
class MethodData;
+class MethodCounters;
class ConstMethod;
class InlineTableSizes;
class KlassSizeStats;
@@ -109,7 +111,7 @@
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 @@
_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 @@
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 @@
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 @@
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 @@
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 @@
#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 @@
// 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 @@
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(); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/oops/methodCounters.cpp Mon Apr 15 21:25:23 2013 -0400
@@ -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);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/oops/methodCounters.hpp Mon Apr 15 21:25:23 2013 -0400
@@ -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
--- a/hotspot/src/share/vm/oops/methodData.cpp Thu Apr 11 21:54:46 2013 -0700
+++ b/hotspot/src/share/vm/oops/methodData.cpp Mon Apr 15 21:25:23 2013 -0400
@@ -732,14 +732,17 @@
} 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;
}
--- a/hotspot/src/share/vm/opto/parseHelper.cpp Thu Apr 11 21:54:46 2013 -0700
+++ b/hotspot/src/share/vm/opto/parseHelper.cpp Mon Apr 15 21:25:23 2013 -0400
@@ -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 @@
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---------------------------
--- a/hotspot/src/share/vm/prims/whitebox.cpp Thu Apr 11 21:54:46 2013 -0700
+++ b/hotspot/src/share/vm/prims/whitebox.cpp Mon Apr 15 21:25:23 2013 -0400
@@ -278,6 +278,7 @@
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 @@
}
}
- 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))
--- a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp Thu Apr 11 21:54:46 2013 -0700
+++ b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp Mon Apr 15 21:25:23 2013 -0400
@@ -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 @@
// 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 @@
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);
}
}
}
--- a/hotspot/src/share/vm/runtime/compilationPolicy.cpp Thu Apr 11 21:54:46 2013 -0700
+++ b/hotspot/src/share/vm/runtime/compilationPolicy.cpp Mon Apr 15 21:25:23 2013 -0400
@@ -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 @@
// 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_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 @@
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::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 @@
#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
--- a/hotspot/src/share/vm/runtime/fprofiler.cpp Thu Apr 11 21:54:46 2013 -0700
+++ b/hotspot/src/share/vm/runtime/fprofiler.cpp Mon Apr 15 21:25:23 2013 -0400
@@ -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 @@
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();
}
};
--- a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp Thu Apr 11 21:54:46 2013 -0700
+++ b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp Mon Apr 15 21:25:23 2013 -0400
@@ -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 @@
// 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());
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Thu Apr 11 21:54:46 2013 -0700
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Mon Apr 15 21:25:23 2013 -0400
@@ -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 @@
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 @@
declare_type(ConstantPoolCache, MetaspaceObj) \
declare_type(MethodData, Metadata) \
declare_type(Method, Metadata) \
+ declare_type(MethodCounters, MetaspaceObj) \
declare_type(ConstMethod, MetaspaceObj) \
\
declare_toplevel_type(Symbol) \