Skip to content

Commit 348bb2e

Browse files
committed
Batch up OSR back edge polls.
1 parent 8cc4b8d commit 348bb2e

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

0 commit comments

Comments
 (0)