Skip to content

Commit 5c86236

Browse files
committed
Handle self-recursion for foreign container objects
1 parent 3feef94 commit 5c86236

File tree

2 files changed

+41
-4
lines changed

2 files changed

+41
-4
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/dict/DictReprBuiltin.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,9 @@
101101
import com.oracle.truffle.api.dsl.Specialization;
102102
import com.oracle.truffle.api.frame.Frame;
103103
import com.oracle.truffle.api.frame.VirtualFrame;
104+
import com.oracle.truffle.api.interop.InteropLibrary;
105+
import com.oracle.truffle.api.interop.UnsupportedMessageException;
106+
import com.oracle.truffle.api.library.CachedLibrary;
104107
import com.oracle.truffle.api.nodes.LoopNode;
105108
import com.oracle.truffle.api.nodes.Node;
106109
import com.oracle.truffle.api.profiles.InlinedConditionProfile;
@@ -281,13 +284,27 @@ public static ReprState dict(Frame frame, @SuppressWarnings("unused") Node node,
281284
// library
282285
public static TruffleString repr(Object dict,
283286
@Bind("this") Node inliningTarget,
287+
@CachedLibrary(limit = "2") InteropLibrary interopLib,
284288
@Cached DictNodes.GetDictStorageNode getStorageNode,
285289
@Cached("create(3)") ForEachDictRepr consumerNode,
286290
@Shared @Cached HashingStorageForEach forEachNode,
287291
@Shared @Cached TruffleStringBuilder.AppendStringNode appendStringNode,
288292
@Shared @Cached TruffleStringBuilder.ToStringNode toStringNode) {
289293
PythonContext ctxt = PythonContext.get(forEachNode);
290-
if (!ctxt.reprEnter(dict)) {
294+
Object reprIdentity = dict;
295+
if (!PGuards.isAnyPythonObject(dict)) {
296+
// The interop library dispatch initialization acts as branch profile. Hash codes
297+
// may clash, but in this case the only downside is that we print an ellipsis
298+
// instead of expanding more.
299+
if (interopLib.hasIdentity(dict)) {
300+
try {
301+
reprIdentity = interopLib.identityHashCode(dict);
302+
} catch (UnsupportedMessageException e) {
303+
throw CompilerDirectives.shouldNotReachHere(e);
304+
}
305+
}
306+
}
307+
if (!ctxt.reprEnter(reprIdentity)) {
291308
return T_ELLIPSIS_IN_BRACES;
292309
}
293310
try {
@@ -298,7 +315,7 @@ public static TruffleString repr(Object dict,
298315
appendStringNode.execute(sb, T_RBRACE);
299316
return toStringNode.execute(sb);
300317
} finally {
301-
ctxt.reprLeave(dict);
318+
ctxt.reprLeave(reprIdentity);
302319
}
303320
}
304321

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/list/ListBuiltins.java

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
import com.oracle.graal.python.lib.PyObjectRichCompareBool;
9090
import com.oracle.graal.python.lib.RichCmpOp;
9191
import com.oracle.graal.python.nodes.ErrorMessages;
92+
import com.oracle.graal.python.nodes.PGuards;
9293
import com.oracle.graal.python.nodes.PRaiseNode;
9394
import com.oracle.graal.python.nodes.builtins.ListNodes;
9495
import com.oracle.graal.python.nodes.builtins.ListNodes.AppendNode;
@@ -113,6 +114,7 @@
113114
import com.oracle.graal.python.runtime.sequence.storage.IntSequenceStorage;
114115
import com.oracle.graal.python.runtime.sequence.storage.LongSequenceStorage;
115116
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
117+
import com.oracle.truffle.api.CompilerDirectives;
116118
import com.oracle.truffle.api.HostCompilerDirectives.InliningCutoff;
117119
import com.oracle.truffle.api.dsl.Bind;
118120
import com.oracle.truffle.api.dsl.Cached;
@@ -124,6 +126,9 @@
124126
import com.oracle.truffle.api.dsl.NeverDefault;
125127
import com.oracle.truffle.api.dsl.Specialization;
126128
import com.oracle.truffle.api.frame.VirtualFrame;
129+
import com.oracle.truffle.api.interop.InteropLibrary;
130+
import com.oracle.truffle.api.interop.UnsupportedMessageException;
131+
import com.oracle.truffle.api.library.CachedLibrary;
127132
import com.oracle.truffle.api.nodes.LoopNode;
128133
import com.oracle.truffle.api.nodes.Node;
129134
import com.oracle.truffle.api.profiles.InlinedBranchProfile;
@@ -184,6 +189,7 @@ abstract static class ReprNode extends PythonUnaryBuiltinNode {
184189
public TruffleString repr(VirtualFrame frame, Object self,
185190
@Bind("this") Node inliningTarget,
186191
@Cached GetListStorageNode getStorageNode,
192+
@CachedLibrary(limit = "2") InteropLibrary interopLib,
187193
@Cached SequenceStorageNodes.GetItemNode getItem,
188194
@Cached PyObjectReprAsTruffleStringNode reprNode,
189195
@Cached TruffleStringBuilder.AppendStringNode appendStringNode,
@@ -193,7 +199,21 @@ public TruffleString repr(VirtualFrame frame, Object self,
193199
if (length == 0) {
194200
return T_EMPTY_BRACKETS;
195201
}
196-
if (!PythonContext.get(this).reprEnter(self)) {
202+
Object reprIdentity = self;
203+
if (!PGuards.isAnyPythonObject(self)) {
204+
// The interop library dispatch initialization acts as branch profile. Hash codes
205+
// may clash, but in this case the only downside is that we print an ellipsis
206+
// instead of expanding more.
207+
if (interopLib.hasIdentity(self)) {
208+
try {
209+
reprIdentity = interopLib.identityHashCode(self);
210+
} catch (UnsupportedMessageException e) {
211+
throw CompilerDirectives.shouldNotReachHere(e);
212+
}
213+
}
214+
}
215+
PythonContext context = PythonContext.get(this);
216+
if (!context.reprEnter(reprIdentity)) {
197217
return T_ELLIPSIS_IN_BRACKETS;
198218
}
199219
try {
@@ -212,7 +232,7 @@ public TruffleString repr(VirtualFrame frame, Object self,
212232
appendStringNode.execute(buf, T_RBRACKET);
213233
return toStringNode.execute(buf);
214234
} finally {
215-
PythonContext.get(this).reprLeave(self);
235+
context.reprLeave(reprIdentity);
216236
}
217237
}
218238
}

0 commit comments

Comments
 (0)