From 1356cd29117caa2538d80d92fbb117be5d94c350 Mon Sep 17 00:00:00 2001
Date: Sat, 23 May 2026 15:07:00 +0800
Subject: Compilecommand support dontprediction
src/hotspot/share/compiler/compilerOracle.cpp | 4 ++++
src/hotspot/share/compiler/compilerOracle.hpp | 4 ++++
src/hotspot/share/jfr/metadata/metadata.xml | 1 +
src/hotspot/share/jfr/periodic/jfrPeriodic.cpp | 3 +++
src/hotspot/share/opto/parse2.cpp | 9 +++++++++
src/hotspot/share/services/diagnosticArgument.cpp | 1 +
src/jdk.jfr/share/classes/jdk/jfr/Recording.java | 8 ++++++++
.../share/classes/jdk/jfr/consumer/RecordingStream.java | 5 +++++
.../share/classes/jdk/jfr/internal/PlatformRecorder.java | 6 +++---
.../classes/jdk/jfr/internal/PlatformRecording.java | 9 +++++++++
.../share/classes/jdk/jfr/internal/dcmd/DCmdStart.java | 9 +++++++--
.../jdk/jfr/api/consumer/recordingstream/TestStop.java | 1 +
12 files changed, 55 insertions(+), 5 deletions(-)
@@ -443,6 +443,10 @@ bool CompilerOracle::should_inline(const methodHandle& method) {
return (check_predicate(CompileCommand::Inline, method));
}
+bool CompilerOracle::should_not_prediction(const methodHandle& method) {
+ return (check_predicate(CompileCommand::Dontprediction, method));
+}
+
bool CompilerOracle::should_not_inline(const methodHandle& method) {
return check_predicate(CompileCommand::DontInline, method) || check_predicate(CompileCommand::Exclude, method);
}
@@ -51,6 +51,7 @@ class methodHandle;
option(Print, "print", Bool) \
option(Inline, "inline", Bool) \
option(DontInline, "dontinline", Bool) \
+ option(Dontprediction, "dontprediction", Bool) \
option(Blackhole, "blackhole", Bool) \
option(CompileOnly, "compileonly", Bool)\
option(Exclude, "exclude", Bool) \
@@ -157,6 +158,9 @@ class CompilerOracle : AllStatic {
// A wrapper for checking bool options
static bool has_option(const methodHandle& method, enum CompileCommand option);
+ // A wrapper for checking prediction option
+ static bool should_not_prediction(const methodHandle& method);
+
// Check if method has option and value set. If yes, overwrite value and return true,
// otherwise leave value unchanged and return false.
template<typename T>
@@ -956,6 +956,7 @@
<Field type="int" name="bailoutCount" label="Bailouts" />
<Field type="int" name="invalidatedCount" label="Invalidated Compilations" />
<Field type="int" name="osrCompileCount" label="OSR Compilations" />
+ <Field type="int" name="deoptimizationCount" label="Deoptimizations" />
<Field type="int" name="standardCompileCount" label="Standard Compilations" />
<Field type="ulong" contentType="bytes" name="osrBytesCompiled" label="OSR Bytes Compiled" />
<Field type="ulong" contentType="bytes" name="standardBytesCompiled" label="Standard Bytes Compiled" />
@@ -651,6 +651,9 @@ TRACE_REQUEST_FUNC(CompilerStatistics) {
event.set_bailoutCount(CompileBroker::get_total_bailout_count());
event.set_invalidatedCount(CompileBroker::get_total_invalidated_count());
event.set_osrCompileCount(CompileBroker::get_total_osr_compile_count());
+#ifdef COMPILER2
+ event.set_deoptimizationCount(Deoptimization::total_deoptimization_count());
+#endif
event.set_standardCompileCount(CompileBroker::get_total_standard_compile_count());
event.set_osrBytesCompiled(CompileBroker::get_sum_osr_bytes_compiled());
event.set_standardBytesCompiled(CompileBroker::get_sum_standard_bytes_compiled());
@@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "ci/ciMethodData.hpp"
+#include "ci/ciUtilities.inline.hpp"
#include "classfile/vmSymbols.hpp"
#include "compiler/compileLog.hpp"
#include "interpreter/linkResolver.hpp"
@@ -1314,6 +1315,14 @@ float Parse::branch_prediction(float& cnt,
BoolTest::mask btest,
int target_bci,
Node* test) {
+ {
+ VM_ENTRY_MARK
+ methodHandle mh(THREAD, _method->get_Method());
+ if (CompilerOracle::should_not_prediction(mh)) {
+ return PROB_FAIR;
+ }
+ }
+
float prob = dynamic_branch_prediction(cnt, btest, test);
// If prob is unknown, switch to static prediction
if (prob != PROB_UNKNOWN) return prob;
@@ -215,6 +215,7 @@ template <> void DCmdArgument<NanoTimeArgument>::parse_value(const char* str,
"Integer parsing error nanotime value: syntax error\n");
}
size_t idx = 0;
+ if (_value._time < 0) idx++;
while(idx < len && isdigit(str[idx])) {
idx++;
}
@@ -610,6 +610,14 @@ public final class Recording implements Closeable {
internal.setDuration(duration);
}
+ public void setPreRecord(long pre) {
+ internal.setPreRecord(pre);
+ }
+
+ public long getPreRecord() {
+ return internal.getPreRecord();
+ }
+
/**
* Enables the event with the specified name.
* <p>
@@ -107,6 +107,7 @@ public final class RecordingStream implements AutoCloseable, EventStream {
AccessControlContext acc = AccessController.getContext();
this.recording = new Recording();
this.creationTime = Instant.now();
+ this.recording.setPreRecord(-1);
this.recording.setName("Recording Stream: " + creationTime);
try {
PlatformRecording pr = PrivateAccess.getInstance().getPlatformRecording(recording);
@@ -239,6 +240,10 @@ public final class RecordingStream implements AutoCloseable, EventStream {
return recording.disable(eventClass);
}
+ public void setPreRecord(long pre) {
+ this.recording.setPreRecord(pre);
+ }
+
/**
* Determines how far back data is kept for the stream.
* <p>
@@ -254,7 +254,7 @@ public final class PlatformRecorder {
}
recording.setState(RecordingState.RUNNING);
updateSettings(false);
- recording.setStartTime(startTime);
+ recording.setStartTime(startTime.plusNanos(recording.getPreRecord()));
writeMetaEvents();
setRunPeriodicTask(true);
} else {
@@ -271,12 +271,12 @@ public final class PlatformRecorder {
}
startNanos = Utils.getChunkStartNanos();
startTime = Utils.epochNanosToInstant(startNanos);
- recording.setStartTime(startTime);
+ recording.setStartTime(startTime.plusNanos(recording.getPreRecord()));
recording.setState(RecordingState.RUNNING);
updateSettings(false);
writeMetaEvents();
if (currentChunk != null) {
- finishChunk(currentChunk, startTime, recording);
+ finishChunk(currentChunk, startTime, recording.getPreRecord() == 0 ? recording : null);
}
currentChunk = newChunk;
}
@@ -68,6 +68,7 @@ public final class PlatformRecording implements AutoCloseable {
private Duration duration;
private Duration maxAge;
private long maxSize;
+ private long preRecord;
private WriteableUserPath destination;
@@ -653,6 +654,14 @@ public final class PlatformRecording implements AutoCloseable {
}
}
+ public void setPreRecord(long pre) {
+ this.preRecord = pre;
+ }
+
+ public long getPreRecord() {
+ return preRecord;
+ }
+
void updateTimer() {
if (stopTask != null) {
stopTask.cancel();
@@ -117,7 +117,7 @@ final class DCmdStart extends AbstractDCmd {
}
if (delay != null) {
- if (delay < 1000L * 1000L * 1000L) {
+ if (delay >= 0 && delay < 1000L * 1000L * 1000L) {
// to avoid typo, delay shorter than 1s makes no sense.
throw new DCmdException("Could not start recording, delay must be at least 1 second.");
}
@@ -201,13 +201,18 @@ final class DCmdStart extends AbstractDCmd {
recording.setDumpOnExit(dumpOnExit);
}
- if (delay != null) {
+ if (delay != null && delay >= 0) {
Duration dDelay = Duration.ofNanos(delay);
recording.scheduleStart(dDelay);
print("Recording " + recording.getId() + " scheduled to start in ");
printTimespan(dDelay, " ");
print(".");
} else {
+ if (delay != null && delay < 0) {
+ recording.setPreRecord(delay);
+ } else {
+ recording.setPreRecord(0);
+ }
recording.start();
print("Started recording " + recording.getId() + ".");
}
@@ -120,6 +120,7 @@ public class TestStop {
try (RecordingStream inner = new RecordingStream()) {
inner.setMaxSize(100_000_000);
inner.onEvent(e -> innerCount.incrementAndGet());
+ inner.setPreRecord(0);
inner.startAsync();
MarkEvent b = new MarkEvent();
--
2.17.1