mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-15 18:33:41 +00:00
8350642: Interpreter: Upgrade CountBytecodes to 64 bit on 64 bit platforms
Reviewed-by: lmesnik, mdoerr, shade
This commit is contained in:
parent
1fe45265e4
commit
4be502ea38
@ -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);
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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 */ \
|
||||
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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 \
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user