Skip to content

Commit 56360a0

Browse files
author
Adam Hrbac
committed
Get jumps working
1 parent f3a317e commit 56360a0

File tree

4 files changed

+52
-86
lines changed

4 files changed

+52
-86
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/FrameBuiltins.java

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,8 @@ public abstract static class SetLinenoNode extends PythonBuiltinNode {
174174
@Specialization(guards = "isNoValue(newLineno)")
175175
int get(VirtualFrame frame, PFrame self, Object newLineno,
176176
@Bind("this") Node inliningTarget,
177-
@Cached InlinedConditionProfile isCurrentFrameProfile,
178-
@Cached MaterializeFrameNode materializeNode) {
177+
@Cached.Shared("isCurrentFrame") @Cached InlinedConditionProfile isCurrentFrameProfile,
178+
@Cached.Shared("materialize") @Cached MaterializeFrameNode materializeNode) {
179179
// Special case because this builtin can be called without going through an invoke node:
180180
// we need to sync the location of the frame if and only if 'self' represents the
181181
// current frame. If 'self' represents another frame on the stack, the location is
@@ -190,8 +190,9 @@ int get(VirtualFrame frame, PFrame self, Object newLineno,
190190
@Specialization(guards = "!isNoValue(newLineno)")
191191
PNone set(VirtualFrame frame, PFrame self, Object newLineno,
192192
@Bind("this") Node inliningTarget,
193-
@Cached InlinedConditionProfile isCurrentFrameProfile,
194-
@Cached MaterializeFrameNode materializeNode) {
193+
@Cached.Shared("isCurrentFrame") @Cached InlinedConditionProfile isCurrentFrameProfile,
194+
@Cached.Shared("materialize") @Cached MaterializeFrameNode materializeNode,
195+
@Cached PRaiseNode.Lazy raise) {
195196
// Special case because this builtin can be called without going through an invoke node:
196197
// we need to sync the location of the frame if and only if 'self' represents the
197198
// current frame. If 'self' represents another frame on the stack, the location is
@@ -201,9 +202,13 @@ PNone set(VirtualFrame frame, PFrame self, Object newLineno,
201202
assert pyFrame == self;
202203
}
203204
if (self.isTraceArgument()) {
204-
self.setJumpDestLine((int) newLineno); // todo
205+
if (newLineno instanceof Integer x) {
206+
self.setJumpDestLine(x);
207+
} else {
208+
throw raise.get(inliningTarget).raise(PythonBuiltinClassType.ValueError, ErrorMessages.EXPECTED_S_GOT_P, "int", newLineno);
209+
}
205210
} else {
206-
throw raise(PythonBuiltinClassType.ValueError); // todo
211+
throw raise.get(inliningTarget).raise(PythonBuiltinClassType.ValueError, ErrorMessages.CANT_JUMP_FROM_S_EVENT, getContext().getThreadState(getLanguage()).getTracingWhat().pythonName);
207212
}
208213
return PNone.NONE;
209214
}
@@ -250,7 +255,8 @@ static boolean doGet(PFrame self, @SuppressWarnings("unused") PNone v) {
250255

251256
@Specialization(guards = "!isNoValue(v)")
252257
static Object doSet(PFrame self, Object v, @Bind("this") Node inliningTarget,
253-
@Cached PRaiseNode raise, @Cached CastToJavaBooleanNode cast) {
258+
@Cached PRaiseNode raise,
259+
@Cached CastToJavaBooleanNode cast) {
254260
try {
255261
self.setTraceLine(cast.execute(inliningTarget, v));
256262
} catch (CannotCastException e) {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/compiler/CodeUnit.java

Lines changed: 24 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,13 @@
4848
import java.util.List;
4949
import java.util.Objects;
5050

51+
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
5152
import com.oracle.graal.python.builtins.objects.bytes.BytesUtils;
5253
import com.oracle.graal.python.builtins.objects.code.PCode;
5354
import com.oracle.graal.python.builtins.objects.str.StringNodes;
5455
import com.oracle.graal.python.compiler.OpCodes.CollectionBits;
56+
import com.oracle.graal.python.nodes.ErrorMessages;
57+
import com.oracle.graal.python.nodes.PRaiseNode;
5558
import com.oracle.graal.python.util.PythonUtils;
5659
import com.oracle.truffle.api.CompilerDirectives;
5760
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
@@ -536,7 +539,10 @@ public int lineToBci(int line) {
536539
if (startLine == line) {
537540
return 0;
538541
}
539-
// todo look into instrumentation support
542+
if ((flags & PCode.CO_GRAALPYHON_MODULE) != 0 && line < startLine) {
543+
// allow jump to the first line of a file, even if it is a comment
544+
return 0;
545+
}
540546
int[] map = getSourceMap().startLineMap;
541547
int bestBci = -1;
542548
int lineDiff = Integer.MAX_VALUE;
@@ -584,7 +590,7 @@ private void setNextStack(ArrayDeque<Integer> todo, List<ArrayList<StackItem>> s
584590
stacks.set(target, value);
585591
todo.addLast(target);
586592
} else {
587-
assert value.equals(blocksAtTarget) : "found conflicting stacks depending on code path: " + this.name;
593+
assert value.equals(blocksAtTarget) : "found conflicting stacks depending on code path: " + this.name + "\t at " + target;
588594
}
589595
}
590596

@@ -595,22 +601,16 @@ private static ArrayList<StackItem> popStack(ArrayList<StackItem> blocks) {
595601
}
596602

597603
// returns null if the jump is fine
598-
public String checkJump(int from, int to) {
599-
List<ArrayList<StackItem>> blocks = computeStackElems();
600-
ArrayList<StackItem> blkFrom = blocks.get(from);
601-
System.out.println(this);
602-
603-
iterateBytecode(code, (bci, op, oparg, following) -> {
604-
System.out.println(bci + "\t" +
605-
op.getNumberOfProducedStackItems(oparg, following, false) + "\t" +
606-
op.getNumberOfConsumedStackItems(oparg, following, false) + "\t" + op + "\t" +
607-
blocks.get(bci));
608-
});
609-
610-
// todo these should be exceptions
611-
assert blkFrom != null : "Unreachable origin";
612-
ArrayList<StackItem> blkTo = blocks.get(to);
613-
assert blkTo != null : "Unreachable target";
604+
public String checkJump(List<ArrayList<StackItem>> stackElems, int from, int to) {
605+
ArrayList<StackItem> blkFrom = stackElems.get(from);
606+
if (blkFrom == null) {
607+
// this should not happen
608+
PRaiseNode.getUncached().raise(PythonBuiltinClassType.ValueError, ErrorMessages.LINE_D_COMES_BEFORE_THE_CURRENT_CODE_BLOCK, bciToLine(from));
609+
}
610+
ArrayList<StackItem> blkTo = stackElems.get(to);
611+
if (blkTo == null) {
612+
PRaiseNode.getUncached().raise(PythonBuiltinClassType.ValueError, ErrorMessages.LINE_D_COMES_AFTER_THE_CURRENT_CODE_BLOCK, bciToLine(from));
613+
}
614614
if (blkTo.size() > blkFrom.size()) {
615615
return blkTo.get(blkTo.size() - 1).error;
616616
}
@@ -622,7 +622,7 @@ public String checkJump(int from, int to) {
622622
return null;
623623
}
624624

625-
private List<ArrayList<StackItem>> computeStackElems() {
625+
public List<ArrayList<StackItem>> computeStackElems() {
626626
List<ArrayList<StackItem>> blocks = new ArrayList<>(Collections.nCopies(code.length + 1, null));
627627
blocks.set(0, new ArrayList<>());
628628
ArrayDeque<Integer> todo = new ArrayDeque<>();
@@ -649,8 +649,12 @@ private List<ArrayList<StackItem>> computeStackElems() {
649649
next = StackItem.Iterable.push(popStack(blocks.get(bci)));
650650
setNextStack(todo, blocks, bci + 1, next);
651651
break;
652+
case FOR_ITER:
653+
setNextStack(todo, blocks, op.getNextBci(bci, oparg, false), StackItem.Object.push(next));
654+
setNextStack(todo, blocks, op.getNextBci(bci, oparg, true), popStack(next));
655+
break;
652656
case PUSH_EXC_INFO:
653-
next = StackItem.Except.push(blocks.get(bci));
657+
next = StackItem.Except.push(StackItem.Object.push(popStack(blocks.get(bci))));
654658
setNextStack(todo, blocks, bci + 1, next);
655659
break;
656660
case MATCH_EXC_OR_JUMP:
@@ -732,56 +736,6 @@ private void handleGeneralOp(List<ArrayList<StackItem>> blocks, ArrayDeque<Integ
732736
}
733737
}
734738

735-
@CompilerDirectives.TruffleBoundary
736-
public int[] computeStackLevels() {
737-
int[] stackLevels = new int[code.length];
738-
Arrays.fill(stackLevels, -1);
739-
// stackLevels has the stack depth before the corresponding opcode executes
740-
stackLevels[0] = 0;
741-
// deque of bci
742-
ArrayDeque<Integer> todo = new ArrayDeque<>();
743-
todo.addFirst(0);
744-
for (int i = 0; i < exceptionHandlerRanges.length; i += 4) {
745-
int handler = exceptionHandlerRanges[i + 2];
746-
int stackAtHandler = exceptionHandlerRanges[i + 3];
747-
// stack at handler + the exception
748-
stackLevels[handler] = stackAtHandler + 1;
749-
todo.addFirst(handler);
750-
}
751-
while (!todo.isEmpty()) {
752-
int bci = todo.removeLast();
753-
int stackHere = stackLevels[bci];
754-
assert stackHere >= 0;
755-
opCodeAt(code, bci, (ignored, op, oparg, followingArgs) -> {
756-
assert stackHere >= op.getNumberOfConsumedStackItems(oparg, followingArgs, true) : "failed at:" + op + ":" + bci;
757-
assert stackHere >= op.getNumberOfConsumedStackItems(oparg, followingArgs, false) : "failed at:" + op + ":" + bci;
758-
int stackWJump = op.getStackEffect(oparg, followingArgs, true);
759-
int stackWOJump = op.getStackEffect(oparg, followingArgs, false);
760-
int bciWJump = op.getNextBci(bci, oparg, true);
761-
int bciWOJump = op.getNextBci(bci, oparg, false);
762-
if (bciWJump == -1) {
763-
assert bciWOJump == bciWJump;
764-
return;
765-
}
766-
if (stackLevels[bciWJump] < 0) {
767-
stackLevels[bciWJump] = stackHere + stackWJump;
768-
todo.addFirst(bciWJump);
769-
} else {
770-
assert stackLevels[bciWJump] == stackHere + stackWJump;
771-
}
772-
if (bciWJump != bciWOJump) {
773-
if (stackLevels[bciWOJump] < 0) {
774-
stackLevels[bciWOJump] = stackHere + stackWOJump;
775-
todo.addFirst(bciWOJump);
776-
} else {
777-
assert stackLevels[bciWOJump] == stackHere + stackWOJump;
778-
}
779-
}
780-
});
781-
}
782-
return stackLevels;
783-
}
784-
785739
@FunctionalInterface
786740
public interface BytecodeAction {
787741
void run(int bci, OpCodes op, int oparg, byte[] followingArgs);

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/ErrorMessages.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1615,4 +1615,10 @@ public abstract class ErrorMessages {
16151615
public static final TruffleString NOTE_MUST_BE_A_STR_NOT_P = tsLiteral("note must be a str, not '%p'");
16161616
public static final TruffleString CANNOT_ADD_NOTE_NOTES_IS_NOT_A_LIST = tsLiteral("Cannot add note: __notes__ is not a list");
16171617
public static final TruffleString CANT_GET_ATTRIBUTE_S_ON_S = tsLiteral("Can't get attribute %s on %s");
1618+
1619+
public static final TruffleString CANT_JUMP_INTO_S = tsLiteral("Can't jump into %s.");
1620+
public static final TruffleString LINE_D_COMES_AFTER_THE_CURRENT_CODE_BLOCK = tsLiteral("line %d comes after the current code block");
1621+
public static final TruffleString LINE_D_COMES_BEFORE_THE_CURRENT_CODE_BLOCK = tsLiteral("line %d comes before the current code block");
1622+
public static final TruffleString CANT_JUMP_FROM_S_EVENT = tsLiteral("Can't jump from \"%s\" event.");
1623+
16181624
}

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

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2925,7 +2925,6 @@ private int traceLine(VirtualFrame virtualFrame, MutableLoopData mutableData, by
29252925
mutableData.setPyFrame(ensurePyFrame(virtualFrame));
29262926
PFrame pyFrame = mutableData.getPyFrame();
29272927
if (pyFrame.didJump()) {
2928-
pyFrame.setJumpDestLine(-3);
29292928
mutableData.setPastBci(bci);
29302929
return bci;
29312930
}
@@ -2935,22 +2934,23 @@ private int traceLine(VirtualFrame virtualFrame, MutableLoopData mutableData, by
29352934
mutableData.getPastLine(), true);
29362935
if (pyFrame.didJump()) {
29372936
int newBci = lineToBci(pyFrame.getJumpDestLine());
2938-
String error = co.checkJump(bci, newBci);
2939-
if (error != null) {
2940-
throw PRaiseNode.getUncached().raise(ValueError, ErrorMessages.CANT_JUMP_INTO_S, error);
2941-
}
29422937
mutableData.setPastBci(bci);
29432938
if (newBci == -1) {
2944-
throw PRaiseNode.getUncached().raise(ValueError); // todo
2939+
throw PRaiseNode.getUncached().raise(ValueError, ErrorMessages.LINE_D_COMES_AFTER_THE_CURRENT_CODE_BLOCK, pyFrame.getLine());
29452940
} else if (newBci == -2) {
2946-
throw PRaiseNode.getUncached().raise(ValueError); // todo
2941+
throw PRaiseNode.getUncached().raise(ValueError, ErrorMessages.LINE_D_COMES_BEFORE_THE_CURRENT_CODE_BLOCK, pyFrame.getJumpDestLine());
29472942
} else {
2948-
int[] stacks = co.computeStackLevels();
2949-
ret = stacks[newBci] - stacks[bci];
2943+
var stacks = co.computeStackElems();
2944+
String error = co.checkJump(stacks, bci, newBci);
2945+
if (error != null) {
2946+
throw PRaiseNode.getUncached().raise(ValueError, ErrorMessages.CANT_JUMP_INTO_S, error);
2947+
}
2948+
ret = stacks.get(newBci).size() - stacks.get(bci).size();
29502949
setCurrentBci(virtualFrame, bcioffset, newBci);
29512950
}
29522951
}
29532952
}
2953+
pyFrame.setJumpDestLine(-3);
29542954
}
29552955
mutableData.setPastBci(bci);
29562956
return ret;

0 commit comments

Comments
 (0)