Skip to content

Commit 8a0b6dc

Browse files
committed
[GR-71680] Batch up OSR back edge polls.
PullRequest: graalpython/4114
2 parents b80f03f + 348bb2e commit 8a0b6dc

File tree

2 files changed

+37
-32
lines changed

2 files changed

+37
-32
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode/OSRInterpreterState.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -46,4 +46,7 @@ final class OSRInterpreterState {
4646
public OSRInterpreterState(int stackTop) {
4747
this.stackTop = stackTop;
4848
}
49+
50+
static final int REPORT_LOOP_STRIDE = 1 << 8;
51+
static final double REPORT_LOOP_PROBABILITY = (double) 1 / (double) REPORT_LOOP_STRIDE;
4952
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode/PBytecodeRootNode.java

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2061,42 +2061,44 @@ private Object bytecodeLoop(VirtualFrame virtualFrame, Frame localFrame, Bytecod
20612061
bci -= oparg;
20622062
notifyStatement(virtualFrame, instrumentation, mutableData, bci, beginBci);
20632063
if (CompilerDirectives.hasNextTier()) {
2064-
mutableData.loopCount++;
2065-
}
2066-
if (CompilerDirectives.inInterpreter()) {
2067-
if (!useCachedNodes) {
2068-
return new InterpreterContinuation(bci, stackTop);
2064+
int counter = ++mutableData.loopCount;
2065+
if (CompilerDirectives.inInterpreter()) {
2066+
if (!useCachedNodes) {
2067+
return new InterpreterContinuation(bci, stackTop);
2068+
}
20692069
}
2070-
if (BytecodeOSRNode.pollOSRBackEdge(osrNode, 1)) {
2071-
/*
2072-
* Beware of race conditions when adding more things to the
2073-
* interpreterState argument. It gets stored already at this point,
2074-
* but the compilation runs in parallel. The compiled code may get
2075-
* entered from a different invocation of this root, using the
2076-
* interpreterState that was saved here. Don't put any data specific
2077-
* to particular invocation in there (like python-level arguments or
2078-
* variables) or it will get mixed up. To retain such state, put it
2079-
* into the frame instead.
2080-
*/
2081-
Object osrResult;
2082-
try {
2083-
osrResult = BytecodeOSRNode.tryOSR(osrNode, bci, new OSRInterpreterState(stackTop), null, virtualFrame);
2084-
} catch (AbstractTruffleException e) {
2070+
if (CompilerDirectives.injectBranchProbability(OSRInterpreterState.REPORT_LOOP_PROBABILITY, counter >= OSRInterpreterState.REPORT_LOOP_STRIDE)) {
2071+
LoopNode.reportLoopCount(this, counter);
2072+
if (CompilerDirectives.inInterpreter() && BytecodeOSRNode.pollOSRBackEdge(osrNode, counter)) {
20852073
/*
2086-
* If the OSR execution throws a python exception, it means it
2087-
* has already been processed by the bytecode exception handler
2088-
* therein. We wrap it in order to make sure it doesn't get
2089-
* processed again, which would overwrite the traceback entry
2090-
* with the location of this jump instruction.
2074+
* Beware of race conditions when adding more things to the
2075+
* interpreterState argument. It gets stored already at this
2076+
* point, but the compilation runs in parallel. The compiled
2077+
* code may get entered from a different invocation of this
2078+
* root, using the interpreterState that was saved here. Don't
2079+
* put any data specific to particular invocation in there (like
2080+
* python-level arguments or variables) or it will get mixed up.
2081+
* To retain such state, put it into the frame instead.
20912082
*/
2092-
throw new OSRException(e);
2093-
}
2094-
if (osrResult != null) {
2095-
if (CompilerDirectives.hasNextTier() && mutableData.loopCount > 0) {
2096-
LoopNode.reportLoopCount(this, mutableData.loopCount);
2083+
Object osrResult;
2084+
try {
2085+
osrResult = BytecodeOSRNode.tryOSR(osrNode, bci, new OSRInterpreterState(stackTop), null, virtualFrame);
2086+
} catch (AbstractTruffleException e) {
2087+
/*
2088+
* If the OSR execution throws a python exception, it means
2089+
* it has already been processed by the bytecode exception
2090+
* handler therein. We wrap it in order to make sure it
2091+
* doesn't get processed again, which would overwrite the
2092+
* traceback entry with the location of this jump
2093+
* instruction.
2094+
*/
2095+
throw new OSRException(e);
2096+
}
2097+
if (osrResult != null) {
2098+
return osrResult;
20972099
}
2098-
return osrResult;
20992100
}
2101+
mutableData.loopCount = 0;
21002102
}
21012103
}
21022104
PythonContext.triggerAsyncActions(this);

0 commit comments

Comments
 (0)