8350642: Interpreter: Upgrade CountBytecodes to 64 bit on 64 bit platforms

Reviewed-by: lmesnik, mdoerr, shade
This commit is contained in:
David Linus Briemann 2025-03-12 10:22:44 +00:00 committed by Martin Doerr
parent 1fe45265e4
commit 4be502ea38
12 changed files with 109 additions and 22 deletions

View File

@ -2102,7 +2102,7 @@ address TemplateInterpreterGenerator::generate_trace_code(TosState state) {
void TemplateInterpreterGenerator::count_bytecode() {
__ mov(r10, (address) &BytecodeCounter::_counter_value);
__ atomic_addw(noreg, 1, r10);
__ atomic_add(noreg, 1, r10);
}
void TemplateInterpreterGenerator::histogram_bytecode(Template* t) {
@ -2150,7 +2150,7 @@ void TemplateInterpreterGenerator::stop_interpreter_at() {
__ mov(rscratch1, (address) &BytecodeCounter::_counter_value);
__ ldr(rscratch1, Address(rscratch1));
__ mov(rscratch2, StopInterpreterAt);
__ cmpw(rscratch1, rscratch2);
__ cmp(rscratch1, rscratch2);
__ br(Assembler::NE, L);
__ brk(0);
__ bind(L);

View File

@ -2328,11 +2328,11 @@ address TemplateInterpreterGenerator::generate_trace_code(TosState state) {
// Support short-cut for TraceBytecodesAt.
// Don't call into the VM if we don't want to trace to speed up things.
Label Lskip_vm_call;
if (TraceBytecodesAt > 0 && TraceBytecodesAt < max_intx) {
if (TraceBytecodesAt > 0) {
int offs1 = __ load_const_optimized(R11_scratch1, (address) &TraceBytecodesAt, R0, true);
int offs2 = __ load_const_optimized(R12_scratch2, (address) &BytecodeCounter::_counter_value, R0, true);
__ ld(R11_scratch1, offs1, R11_scratch1);
__ lwa(R12_scratch2, offs2, R12_scratch2);
__ ld(R12_scratch2, offs2, R12_scratch2);
__ cmpd(CR0, R12_scratch2, R11_scratch1);
__ blt(CR0, Lskip_vm_call);
}
@ -2346,7 +2346,7 @@ address TemplateInterpreterGenerator::generate_trace_code(TosState state) {
__ mtlr(R31);
__ pop(state);
if (TraceBytecodesAt > 0 && TraceBytecodesAt < max_intx) {
if (TraceBytecodesAt > 0) {
__ bind(Lskip_vm_call);
}
__ blr();
@ -2356,9 +2356,9 @@ address TemplateInterpreterGenerator::generate_trace_code(TosState state) {
void TemplateInterpreterGenerator::count_bytecode() {
int offs = __ load_const_optimized(R11_scratch1, (address) &BytecodeCounter::_counter_value, R12_scratch2, true);
__ lwz(R12_scratch2, offs, R11_scratch1);
__ ld(R12_scratch2, offs, R11_scratch1);
__ addi(R12_scratch2, R12_scratch2, 1);
__ stw(R12_scratch2, offs, R11_scratch1);
__ std(R12_scratch2, offs, R11_scratch1);
}
void TemplateInterpreterGenerator::histogram_bytecode(Template* t) {
@ -2407,7 +2407,7 @@ void TemplateInterpreterGenerator::stop_interpreter_at() {
int offs1 = __ load_const_optimized(R11_scratch1, (address) &StopInterpreterAt, R0, true);
int offs2 = __ load_const_optimized(R12_scratch2, (address) &BytecodeCounter::_counter_value, R0, true);
__ ld(R11_scratch1, offs1, R11_scratch1);
__ lwa(R12_scratch2, offs2, R12_scratch2);
__ ld(R12_scratch2, offs2, R12_scratch2);
__ cmpd(CR0, R12_scratch2, R11_scratch1);
__ bne(CR0, L);
__ illtrap();

View File

@ -1846,7 +1846,7 @@ address TemplateInterpreterGenerator::generate_trace_code(TosState state) {
void TemplateInterpreterGenerator::count_bytecode() {
__ mv(x7, (address) &BytecodeCounter::_counter_value);
__ atomic_addw(noreg, 1, x7);
__ atomic_add(noreg, 1, x7);
}
void TemplateInterpreterGenerator::histogram_bytecode(Template* t) {

View File

@ -2329,7 +2329,7 @@ address TemplateInterpreterGenerator::generate_trace_code(TosState state) {
// Skip runtime call, if the trace threshold is not yet reached.
__ load_absolute_address(Z_tmp_1, (address)&BytecodeCounter::_counter_value);
__ load_absolute_address(Z_tmp_2, (address)&TraceBytecodesAt);
__ load_sized_value(Z_tmp_1, Address(Z_tmp_1), 4, false /*signed*/);
__ load_sized_value(Z_tmp_1, Address(Z_tmp_1), 8, false /*signed*/);
__ load_sized_value(Z_tmp_2, Address(Z_tmp_2), 8, false /*signed*/);
__ compareU64_and_branch(Z_tmp_1, Z_tmp_2, Assembler::bcondLow, counter_below_trace_threshold);
}
@ -2359,7 +2359,7 @@ address TemplateInterpreterGenerator::generate_trace_code(TosState state) {
// Make feasible for old CPUs.
void TemplateInterpreterGenerator::count_bytecode() {
__ load_absolute_address(Z_R1_scratch, (address) &BytecodeCounter::_counter_value);
__ add2mem_32(Address(Z_R1_scratch), 1, Z_R0_scratch);
__ add2mem_64(Address(Z_R1_scratch), 1, Z_R0_scratch);
}
void TemplateInterpreterGenerator::histogram_bytecode(Template * t) {
@ -2406,7 +2406,7 @@ void TemplateInterpreterGenerator::stop_interpreter_at() {
__ load_absolute_address(Z_tmp_1, (address)&BytecodeCounter::_counter_value);
__ load_absolute_address(Z_tmp_2, (address)&StopInterpreterAt);
__ load_sized_value(Z_tmp_1, Address(Z_tmp_1), 4, false /*signed*/);
__ load_sized_value(Z_tmp_1, Address(Z_tmp_1), 8, false /*signed*/);
__ load_sized_value(Z_tmp_2, Address(Z_tmp_2), 8, false /*signed*/);
__ compareU64_and_branch(Z_tmp_1, Z_tmp_2, Assembler::bcondLow, L);
assert(Z_tmp_1->is_nonvolatile(), "must be nonvolatile to preserve Z_tos");

View File

@ -1874,7 +1874,11 @@ address TemplateInterpreterGenerator::generate_trace_code(TosState state) {
}
void TemplateInterpreterGenerator::count_bytecode() {
#ifndef _LP64
__ incrementl(ExternalAddress((address) &BytecodeCounter::_counter_value), rscratch1);
#else
__ incrementq(ExternalAddress((address) &BytecodeCounter::_counter_value), rscratch1);
#endif
}
void TemplateInterpreterGenerator::histogram_bytecode(Template* t) {
@ -1914,9 +1918,14 @@ void TemplateInterpreterGenerator::trace_bytecode(Template* t) {
void TemplateInterpreterGenerator::stop_interpreter_at() {
Label L;
#ifndef _LP64
__ cmp32(ExternalAddress((address) &BytecodeCounter::_counter_value),
StopInterpreterAt,
rscratch1);
#else
__ mov64(rscratch1, StopInterpreterAt);
__ cmp64(rscratch1, ExternalAddress((address) &BytecodeCounter::_counter_value), rscratch2);
#endif
__ jcc(Assembler::notEqual, L);
__ int3();
__ bind(L);

View File

@ -33,7 +33,7 @@
// Implementation of BytecodeCounter
int BytecodeCounter::_counter_value = 0;
uintx BytecodeCounter::_counter_value = 0;
jlong BytecodeCounter::_reset_time = 0;
@ -55,7 +55,7 @@ double BytecodeCounter::frequency() {
void BytecodeCounter::print() {
tty->print_cr(
"%d bytecodes executed in %.1fs (%.3fMHz)",
"%zu bytecodes executed in %.1fs (%.3fMHz)",
counter_value(),
elapsed_time(),
frequency() / 1000000.0

View File

@ -32,7 +32,7 @@
class BytecodeCounter: AllStatic {
private:
NOT_PRODUCT(static int _counter_value;)
NOT_PRODUCT(static uintx _counter_value;)
NOT_PRODUCT(static jlong _reset_time;)
friend class TemplateInterpreterGenerator;
@ -43,7 +43,7 @@ class BytecodeCounter: AllStatic {
static void reset() PRODUCT_RETURN;
// Counter info (all info since last reset)
static int counter_value() PRODUCT_RETURN0 NOT_PRODUCT({ return _counter_value; });
static uintx counter_value() PRODUCT_RETURN0 NOT_PRODUCT({ return _counter_value; });
static double elapsed_time() PRODUCT_RETURN0; // in seconds
static double frequency() PRODUCT_RETURN0; // bytecodes/seconds

View File

@ -129,10 +129,10 @@ class BytecodePrinter {
int bci = (int)(bcp - method->code_base());
st->print("[%zu] ", Thread::current()->osthread()->thread_id_for_printing());
if (Verbose) {
st->print("%8d %4d " INTPTR_FORMAT " " INTPTR_FORMAT " %s",
st->print("%8zu %4d " INTPTR_FORMAT " " INTPTR_FORMAT " %s",
BytecodeCounter::counter_value(), bci, tos, tos2, Bytecodes::name(code));
} else {
st->print("%8d %4d %s",
st->print("%8zu %4d %s",
BytecodeCounter::counter_value(), bci, Bytecodes::name(code));
}
print_attributes(bci, st);

View File

@ -1566,13 +1566,13 @@ const int ObjectAlignmentInBytes = 8;
"Minimal number of lookupswitch entries for rewriting to binary " \
"switch") \
\
develop(intx, StopInterpreterAt, 0, \
develop(uintx, StopInterpreterAt, 0, \
"Stop interpreter execution at specified bytecode number") \
\
develop(intx, TraceBytecodesAt, 0, \
develop(uintx, TraceBytecodesAt, 0, \
"Trace bytecodes starting with specified bytecode number") \
\
develop(intx, TraceBytecodesStopAt, 0, \
develop(uintx, TraceBytecodesStopAt, 0, \
"Stop bytecode tracing at the specified bytecode number") \
\
/* Priorities */ \

View File

@ -231,7 +231,7 @@ static void print_method_invocation_histogram() {
static void print_bytecode_count() {
if (CountBytecodes || TraceBytecodes || StopInterpreterAt) {
tty->print_cr("[BytecodeCounter::counter_value = %d]", BytecodeCounter::counter_value());
tty->print_cr("[BytecodeCounter::counter_value = %zu]", BytecodeCounter::counter_value());
}
}

View File

@ -363,6 +363,7 @@ tier1_runtime = \
-runtime/ErrorHandling/ReattemptErrorTest.java \
-runtime/ErrorHandling/TestHeapDumpOnOutOfMemoryError.java \
-runtime/ErrorHandling/TimeoutInErrorHandlingTest.java \
-runtime/interpreter/CountBytecodesTest.java \
-runtime/InvocationTests \
-runtime/logging/MonitorMismatchTest.java \
-runtime/memory/ReserveMemory.java \

View File

@ -0,0 +1,77 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2025 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8350642
* @requires vm.debug & vm.bits == "64"
* @summary Test the output for CountBytecodes and validate that the counter
* does not overflow for more than 2^32 bytecodes counted.
* @library /test/lib
* @run main/othervm/timeout=300 CountBytecodesTest
*/
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import jdk.test.lib.Asserts;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
public class CountBytecodesTest {
private final static long iterations = (1L << 32) / 9;
public static void main(String args[]) throws Exception {
if (args.length == 1 && args[0].equals("test")) {
for (long i = 0; i < iterations; i++) {
// Just iterating is enough to execute and count bytecodes.
// According to javap -c this loop translates to the following 9 bytecodes:
// 19: lload_1
// 20: ldc2_w #17
// 23: lcmp
// 24: ifge 34
// 27: lload_1
// 28: lconst_1
// 29: ladd
// 30: lstore_1
// 31: goto 19
//
// Thus we can divide the 2^32 by 9 to set the minimum number of iterations
// while maintaining execution of more than 2^32 bytecodes.
}
} else {
OutputAnalyzer output = ProcessTools.executeTestJava("-Xint", "-XX:+CountBytecodes", "CountBytecodesTest", "test");
output.shouldHaveExitValue(0);
// Output format: [BytecodeCounter::counter_value = 38676232802]
output.stdoutShouldContain("BytecodeCounter::counter_value");
String bytecodesStr = output.firstMatch("BytecodeCounter::counter_value\s*=\s*(\\d+)", 1);
long bytecodes = Long.parseLong(bytecodesStr);
System.out.println("Executed bytecodes: " + bytecodes);
Asserts.assertGTE(bytecodes, 4294967296L);
}
}
}