Skip to content

Commit fb43e41

Browse files
committed
[GR-57210] Fix failed PE-constness assert in python slot dispatchers
PullRequest: graalpython/3438
2 parents 0f99514 + d56be31 commit fb43e41

File tree

5 files changed

+67
-65
lines changed

5 files changed

+67
-65
lines changed

graalpython/com.oracle.graal.python.test/src/tests/test_repl.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ def validate_repl(stdin, python_args=(), ignore_preamble=True):
7878
index = -1
7979
whole_out = ''
8080
while True:
81-
rlist, _, _ = select.select([pty_parent], [], [], 30)
81+
rlist, _, _ = select.select([pty_parent], [], [], 60)
8282
assert pty_parent in rlist, f"Timed out waiting for REPL output. Output: {whole_out}{out}"
8383
out += os.read(pty_parent, 1024).decode('utf-8')
8484
out = out.replace('\r\n', '\n')
@@ -99,7 +99,7 @@ def validate_repl(stdin, python_args=(), ignore_preamble=True):
9999
out = out[-4:]
100100
if index >= len(input_and_output):
101101
os.write(pty_parent, b'\x04') # CTRL-D
102-
proc.wait(timeout=30)
102+
proc.wait(timeout=60)
103103
out = os.read(pty_parent, 1024).decode('utf-8')
104104
out = re.sub(r'\x1b\[\?2004[hl]', '', out)
105105
assert not out.strip(), f"Garbage after EOF:\n{out!r}"

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/PythonDispatchers.java

Lines changed: 19 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ private PythonDispatchers() {
7171
abstract static class PythonSlotDispatcherNodeBase extends PNodeWithContext {
7272
@Idempotent
7373
static boolean isSimpleSignature(PFunction callable, int positionArgsCount) {
74+
CompilerAsserts.partialEvaluationConstant(callable);
75+
CompilerAsserts.partialEvaluationConstant(positionArgsCount);
7476
Signature signature = callable.getCode().getSignature();
7577
boolean result = signature.takesPositionalOnly() && signature.getMaxNumOfPositionalArgs() == positionArgsCount;
7678
CompilerAsserts.partialEvaluationConstant(result); // should hold in single context
@@ -96,7 +98,8 @@ final Object execute(VirtualFrame frame, Node inliningTarget, Object callable, O
9698

9799
abstract Object executeImpl(VirtualFrame frame, Node inliningTarget, Object callable, Object type, Object self);
98100

99-
@Specialization(guards = {"isSingleContext()", "callee == cachedCallee", "isSimpleSignature(cachedCallee, 1)"}, limit = "getCallSiteInlineCacheMaxDepth()")
101+
@Specialization(guards = {"isSingleContext()", "callee == cachedCallee", "isSimpleSignature(cachedCallee, 1)"}, //
102+
limit = "getCallSiteInlineCacheMaxDepth()", assumptions = "cachedCallee.getCodeStableAssumption()")
100103
protected static Object doCachedPFunction(VirtualFrame frame, @SuppressWarnings("unused") PFunction callee, @SuppressWarnings("unused") Object type, Object self,
101104
@SuppressWarnings("unused") @Cached("callee") PFunction cachedCallee,
102105
@Cached("createInvokeNode(cachedCallee)") FunctionInvokeNode invoke) {
@@ -136,7 +139,8 @@ final Object execute(VirtualFrame frame, Node inliningTarget, Object callable, O
136139

137140
abstract Object executeImpl(VirtualFrame frame, Node inliningTarget, Object callable, Object type, Object self, Object arg1);
138141

139-
@Specialization(guards = {"isSingleContext()", "callee == cachedCallee", "isSimpleSignature(cachedCallee, 2)"}, limit = "getCallSiteInlineCacheMaxDepth()")
142+
@Specialization(guards = {"isSingleContext()", "callee == cachedCallee", "isSimpleSignature(cachedCallee, 2)"}, //
143+
limit = "getCallSiteInlineCacheMaxDepth()", assumptions = "cachedCallee.getCodeStableAssumption()")
140144
protected static Object doCachedPFunction(VirtualFrame frame, @SuppressWarnings("unused") PFunction callee, @SuppressWarnings("unused") Object type, Object self, Object arg1,
141145
@SuppressWarnings("unused") @Cached("callee") PFunction cachedCallee,
142146
@Cached("createInvokeNode(cachedCallee)") FunctionInvokeNode invoke) {
@@ -168,59 +172,44 @@ static Object doGeneric(VirtualFrame frame, Node inliningTarget, Object callable
168172
@GenerateUncached
169173
@GenerateInline
170174
@GenerateCached(false)
171-
abstract static class TernaryOrBinaryPythonSlotDispatcherNode extends PythonSlotDispatcherNodeBase {
172-
final Object execute(VirtualFrame frame, Node inliningTarget, boolean callTernary, Object callable, Object type, Object self, Object arg1, Object arg2) {
175+
abstract static class TernaryPythonSlotDispatcherNode extends PythonSlotDispatcherNodeBase {
176+
final Object execute(VirtualFrame frame, Node inliningTarget, Object callable, Object type, Object self, Object arg1, Object arg2) {
173177
assert !(callable instanceof TruffleWeakReference<?>);
174178
assert !(type instanceof TruffleWeakReference<?>);
175-
return executeImpl(frame, inliningTarget, callTernary, callable, type, self, arg1, arg2);
179+
return executeImpl(frame, inliningTarget, callable, type, self, arg1, arg2);
176180
}
177181

178-
abstract Object executeImpl(VirtualFrame frame, Node inliningTarget, boolean callTernary, Object callable, Object type, Object self, Object arg1, Object arg2);
182+
abstract Object executeImpl(VirtualFrame frame, Node inliningTarget, Object callable, Object type, Object self, Object arg1, Object arg2);
179183

180-
@Idempotent
181-
static int getArgsCount(boolean callTernary) {
182-
return callTernary ? 3 : 2;
183-
}
184-
185-
@Specialization(guards = {"isSingleContext()", "callee == cachedCallee", "isSimpleSignature(cachedCallee, getArgsCount(callTernary))"}, limit = "getCallSiteInlineCacheMaxDepth()")
186-
protected static Object doCachedPFunction(VirtualFrame frame, boolean callTernary, @SuppressWarnings("unused") PFunction callee, @SuppressWarnings("unused") Object type, Object self,
184+
@Specialization(guards = {"isSingleContext()", "callee == cachedCallee", "isSimpleSignature(cachedCallee, 3)"}, //
185+
limit = "getCallSiteInlineCacheMaxDepth()", assumptions = "cachedCallee.getCodeStableAssumption()")
186+
protected static Object doCachedPFunction(VirtualFrame frame, @SuppressWarnings("unused") PFunction callee, @SuppressWarnings("unused") Object type, Object self,
187187
Object arg1, Object arg2,
188188
@SuppressWarnings("unused") @Cached("callee") PFunction cachedCallee,
189189
@Cached("createInvokeNode(cachedCallee)") FunctionInvokeNode invoke) {
190-
Object[] arguments = PArguments.create(getArgsCount(callTernary));
190+
Object[] arguments = PArguments.create(3);
191191
PArguments.setArgument(arguments, 0, self);
192192
PArguments.setArgument(arguments, 1, arg1);
193-
if (callTernary) {
194-
PArguments.setArgument(arguments, 2, arg2);
195-
}
193+
PArguments.setArgument(arguments, 2, arg2);
196194
return invoke.execute(frame, arguments);
197195
}
198196

199197
@Specialization(replaces = "doCachedPFunction")
200198
@InliningCutoff
201-
static Object doGeneric(VirtualFrame frame, Node inliningTarget, boolean callTernary, Object callableObj, Object type, Object self, Object arg1, Object arg2,
199+
static Object doGeneric(VirtualFrame frame, Node inliningTarget, Object callableObj, Object type, Object self, Object arg1, Object arg2,
202200
@Cached MaybeBindDescriptorNode bindDescriptorNode,
203201
@Cached(inline = false) CallNode callNode) {
204202
Object bound = bindDescriptorNode.execute(frame, inliningTarget, callableObj, self, type);
205-
int argsCount = 1 + asInt(callTernary) + asInt(!(bound instanceof BoundDescriptor));
206-
Object[] arguments = new Object[argsCount];
207-
int argIndex = 0;
203+
Object[] arguments;
208204
Object callable;
209205
if (bound instanceof BoundDescriptor boundDescr) {
210206
callable = boundDescr.descriptor;
207+
arguments = new Object[]{arg1, arg2};
211208
} else {
212209
callable = bound;
213-
arguments[argIndex++] = self;
214-
}
215-
arguments[argIndex++] = arg1;
216-
if (callTernary) {
217-
arguments[argIndex] = arg2;
210+
arguments = new Object[]{self, arg1, arg2};
218211
}
219212
return callNode.execute(frame, callable, arguments);
220213
}
221-
222-
private static int asInt(boolean b) {
223-
return b ? 1 : 0;
224-
}
225214
}
226215
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotDescrGet.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,8 @@ static Object callGenericBuiltin(VirtualFrame frame, Node inliningTarget, TpSlot
264264
abstract static class DescrGetPythonSlotDispatcherNode extends PythonSlotDispatcherNodeBase {
265265
abstract Object execute(VirtualFrame frame, Node inliningTarget, Object callable, Object type, Object self, Object arg1, Object arg2);
266266

267-
@Specialization(guards = {"isSingleContext()", "callee == cachedCallee", "isSimpleSignature(cachedCallee, 3)"}, limit = "getCallSiteInlineCacheMaxDepth()")
267+
@Specialization(guards = {"isSingleContext()", "callee == cachedCallee", "isSimpleSignature(cachedCallee, 3)"}, //
268+
limit = "getCallSiteInlineCacheMaxDepth()", assumptions = "cachedCallee.getCodeStableAssumption()")
268269
protected static Object doCachedPFunction(VirtualFrame frame, Node inliningTarget, @SuppressWarnings("unused") PFunction callee, @SuppressWarnings("unused") Object type, Object self,
269270
Object arg1, Object arg2,
270271
@SuppressWarnings("unused") @Cached("callee") PFunction cachedCallee,

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotDescrSet.java

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@
5959
import com.oracle.graal.python.builtins.objects.function.PBuiltinFunction;
6060
import com.oracle.graal.python.builtins.objects.type.TpSlots;
6161
import com.oracle.graal.python.builtins.objects.type.slots.NodeFactoryUtils.BinaryToTernaryBuiltinNode;
62-
import com.oracle.graal.python.builtins.objects.type.slots.PythonDispatchers.TernaryOrBinaryPythonSlotDispatcherNode;
62+
import com.oracle.graal.python.builtins.objects.type.slots.PythonDispatchers.BinaryPythonSlotDispatcherNode;
63+
import com.oracle.graal.python.builtins.objects.type.slots.PythonDispatchers.TernaryPythonSlotDispatcherNode;
6364
import com.oracle.graal.python.builtins.objects.type.slots.TpSlot.TpSlotBuiltin;
6465
import com.oracle.graal.python.builtins.objects.type.slots.TpSlot.TpSlotNative;
6566
import com.oracle.graal.python.builtins.objects.type.slots.TpSlot.TpSlotPython;
@@ -76,9 +77,11 @@
7677
import com.oracle.truffle.api.HostCompilerDirectives.InliningCutoff;
7778
import com.oracle.truffle.api.RootCallTarget;
7879
import com.oracle.truffle.api.dsl.Cached;
80+
import com.oracle.truffle.api.dsl.Cached.Exclusive;
7981
import com.oracle.truffle.api.dsl.GenerateCached;
8082
import com.oracle.truffle.api.dsl.GenerateInline;
8183
import com.oracle.truffle.api.dsl.GenerateUncached;
84+
import com.oracle.truffle.api.dsl.ImportStatic;
8285
import com.oracle.truffle.api.dsl.NeverDefault;
8386
import com.oracle.truffle.api.dsl.NodeFactory;
8487
import com.oracle.truffle.api.dsl.Specialization;
@@ -214,6 +217,7 @@ private static PException raiseAttributeError(Node inliningTarget, PRaiseNode.La
214217
@GenerateInline(inlineByDefault = true)
215218
@GenerateCached
216219
@GenerateUncached
220+
@ImportStatic(PGuards.class)
217221
@SuppressWarnings("rawtypes")
218222
public abstract static class CallSlotDescrSet extends Node {
219223
@NeverDefault
@@ -234,24 +238,27 @@ static void callCachedBuiltin(VirtualFrame frame, @SuppressWarnings("unused") Tp
234238
slotNode.executeVoid(frame, self, obj, value);
235239
}
236240

237-
@Specialization
238-
static void callPython(VirtualFrame frame, Node inliningTarget, TpSlotDescrSetPython slot, Object self, Object obj, Object value,
239-
@Cached TernaryOrBinaryPythonSlotDispatcherNode dispatcherNode,
240-
@Cached PRaiseNode.Lazy raiseNode) {
241-
Object callable;
242-
boolean callDel = PGuards.isNoValue(value);
243-
TruffleString name;
244-
if (callDel) {
245-
callable = slot.getDelCallable();
246-
name = T___DEL__;
247-
} else {
248-
callable = slot.getSetCallable();
249-
name = T___SET__;
241+
@Specialization(guards = "!isNoValue(value)")
242+
static void callPythonSet(VirtualFrame frame, Node inliningTarget, TpSlotDescrSetPython slot, Object self, Object obj, Object value,
243+
@Cached TernaryPythonSlotDispatcherNode dispatcherNode,
244+
@Exclusive @Cached PRaiseNode.Lazy raiseNode) {
245+
Object callable = slot.getSetCallable();
246+
if (callable == null) {
247+
throw raiseAttributeError(inliningTarget, raiseNode, T___SET__);
250248
}
249+
dispatcherNode.execute(frame, inliningTarget, callable, slot.getType(), self, obj, value);
250+
}
251+
252+
@Specialization(guards = "isNoValue(value)")
253+
@InliningCutoff
254+
static void callPythonDel(VirtualFrame frame, Node inliningTarget, TpSlotDescrSetPython slot, Object self, Object obj, @SuppressWarnings("unused") Object value,
255+
@Cached BinaryPythonSlotDispatcherNode dispatcherNode,
256+
@Exclusive @Cached PRaiseNode.Lazy raiseNode) {
257+
Object callable = slot.getDelCallable();
251258
if (callable == null) {
252-
throw raiseAttributeError(inliningTarget, raiseNode, name);
259+
throw raiseAttributeError(inliningTarget, raiseNode, T___DEL__);
253260
}
254-
dispatcherNode.execute(frame, inliningTarget, !callDel, callable, slot.getType(), self, obj, value);
261+
dispatcherNode.execute(frame, inliningTarget, callable, slot.getType(), self, obj);
255262
}
256263

257264
@Specialization

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/slots/TpSlotSetAttr.java

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@
6161
import com.oracle.graal.python.builtins.objects.function.PBuiltinFunction;
6262
import com.oracle.graal.python.builtins.objects.type.TpSlots;
6363
import com.oracle.graal.python.builtins.objects.type.slots.NodeFactoryUtils.BinaryToTernaryBuiltinNode;
64-
import com.oracle.graal.python.builtins.objects.type.slots.PythonDispatchers.TernaryOrBinaryPythonSlotDispatcherNode;
64+
import com.oracle.graal.python.builtins.objects.type.slots.PythonDispatchers.BinaryPythonSlotDispatcherNode;
65+
import com.oracle.graal.python.builtins.objects.type.slots.PythonDispatchers.TernaryPythonSlotDispatcherNode;
6566
import com.oracle.graal.python.builtins.objects.type.slots.TpSlot.TpSlotManaged;
6667
import com.oracle.graal.python.builtins.objects.type.slots.TpSlot.TpSlotNative;
6768
import com.oracle.graal.python.builtins.objects.type.slots.TpSlot.TpSlotPython;
@@ -79,6 +80,7 @@
7980
import com.oracle.truffle.api.RootCallTarget;
8081
import com.oracle.truffle.api.dsl.Bind;
8182
import com.oracle.truffle.api.dsl.Cached;
83+
import com.oracle.truffle.api.dsl.Cached.Exclusive;
8284
import com.oracle.truffle.api.dsl.GenerateCached;
8385
import com.oracle.truffle.api.dsl.GenerateInline;
8486
import com.oracle.truffle.api.dsl.GenerateUncached;
@@ -315,24 +317,27 @@ static void callCachedBuiltin(VirtualFrame frame, @SuppressWarnings("unused") Tp
315317
slotNode.executeSetAttr(frame, self, name, value);
316318
}
317319

318-
@Specialization
319-
static void callPythonSimple(VirtualFrame frame, Node inliningTarget, TpSlotSetAttrPython slot, Object self, Object name, Object value,
320-
@Cached PRaiseNode.Lazy raiseNode,
321-
@Cached TernaryOrBinaryPythonSlotDispatcherNode callPythonFun) {
322-
Object callable;
323-
boolean callDel = PGuards.isNoValue(value);
324-
TruffleString funName;
325-
if (callDel) {
326-
callable = slot.getDelattr();
327-
funName = T___DELATTR__;
328-
} else {
329-
callable = slot.getSetattr();
330-
funName = T___SETATTR__;
320+
@Specialization(guards = "!isNoValue(value)")
321+
static void callPythonSimpleSet(VirtualFrame frame, Node inliningTarget, TpSlotSetAttrPython slot, Object self, Object name, Object value,
322+
@Exclusive @Cached PRaiseNode.Lazy raiseNode,
323+
@Cached TernaryPythonSlotDispatcherNode callPythonFun) {
324+
Object callable = slot.getSetattr();
325+
if (callable == null) {
326+
throw raiseAttributeError(inliningTarget, raiseNode, T___SETATTR__);
331327
}
328+
callPythonFun.execute(frame, inliningTarget, callable, slot.getType(), self, name, value);
329+
}
330+
331+
@Specialization(guards = "isNoValue(value)")
332+
@InliningCutoff
333+
static void callPythonSimpleDel(VirtualFrame frame, Node inliningTarget, TpSlotSetAttrPython slot, Object self, Object name, @SuppressWarnings("unused") Object value,
334+
@Exclusive @Cached PRaiseNode.Lazy raiseNode,
335+
@Cached BinaryPythonSlotDispatcherNode callPythonFun) {
336+
Object callable = slot.getDelattr();
332337
if (callable == null) {
333-
throw raiseAttributeError(inliningTarget, raiseNode, funName);
338+
throw raiseAttributeError(inliningTarget, raiseNode, T___DELATTR__);
334339
}
335-
callPythonFun.execute(frame, inliningTarget, !callDel, callable, slot.getType(), self, name, value);
340+
callPythonFun.execute(frame, inliningTarget, callable, slot.getType(), self, name);
336341
}
337342

338343
@InliningCutoff

0 commit comments

Comments
 (0)