Skip to content

Commit 5220244

Browse files
committed
add thread_state->recursion_depth
1 parent 7f0f11a commit 5220244

File tree

1 file changed

+65
-25
lines changed
  • graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext

1 file changed

+65
-25
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/PThreadState.java

Lines changed: 65 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@
5454
import com.oracle.graal.python.builtins.objects.function.PArguments;
5555
import com.oracle.graal.python.builtins.objects.function.Signature;
5656
import com.oracle.graal.python.builtins.objects.traceback.PTraceback;
57-
import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass;
5857
import com.oracle.graal.python.builtins.objects.type.PythonClass;
5958
import com.oracle.graal.python.nodes.PNodeWithContext;
6059
import com.oracle.graal.python.nodes.PRaiseNode;
@@ -69,6 +68,7 @@
6968
import com.oracle.truffle.api.CompilerDirectives;
7069
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
7170
import com.oracle.truffle.api.RootCallTarget;
71+
import com.oracle.truffle.api.Truffle;
7272
import com.oracle.truffle.api.TruffleLanguage;
7373
import com.oracle.truffle.api.dsl.Cached;
7474
import com.oracle.truffle.api.dsl.Cached.Exclusive;
@@ -77,6 +77,8 @@
7777
import com.oracle.truffle.api.dsl.GenerateUncached;
7878
import com.oracle.truffle.api.dsl.ImportStatic;
7979
import com.oracle.truffle.api.dsl.Specialization;
80+
import com.oracle.truffle.api.frame.FrameInstance;
81+
import com.oracle.truffle.api.frame.FrameInstanceVisitor;
8082
import com.oracle.truffle.api.frame.VirtualFrame;
8183
import com.oracle.truffle.api.interop.InteropLibrary;
8284
import com.oracle.truffle.api.interop.UnknownIdentifierException;
@@ -98,6 +100,7 @@ public class PThreadState extends PythonNativeWrapper {
98100
public static final String EXC_TRACEBACK = "exc_traceback";
99101
public static final String DICT = "dict";
100102
public static final String PREV = "prev";
103+
public static final String RECURSION_DEPTH = "recursion_depth";
101104

102105
private PDict dict;
103106

@@ -126,23 +129,23 @@ protected boolean isMemberReadable(String member) {
126129
case EXC_TRACEBACK:
127130
case DICT:
128131
case PREV:
132+
case RECURSION_DEPTH:
129133
return true;
130134
default:
131135
return false;
132136
}
133137
}
134138

135139
@ExportMessage
136-
protected Object getMembers(@SuppressWarnings("unused") boolean includeInternal) throws UnsupportedMessageException {
137-
throw UnsupportedMessageException.create();
140+
protected Object getMembers(@SuppressWarnings("unused") boolean includeInternal,
141+
@Exclusive @Cached PythonObjectFactory factory) {
142+
return factory.createList(new Object[] { CUR_EXC_TYPE, CUR_EXC_VALUE, CUR_EXC_TRACEBACK, EXC_TYPE, EXC_VALUE, EXC_TRACEBACK, DICT, PREV, RECURSION_DEPTH });
138143
}
139144

140145
@ExportMessage
141146
protected Object readMember(String member,
142-
@Exclusive @Cached ThreadStateReadNode readNode,
143-
@Exclusive @Cached CExtNodes.ToSulongNode toSulongNode) {
144-
Object result = readNode.execute(member);
145-
return toSulongNode.execute(result != null ? result : PNone.NO_VALUE);
147+
@Exclusive @Cached ThreadStateReadNode readNode) {
148+
return readNode.execute(member);
146149
}
147150

148151
@ImportStatic(PThreadState.class)
@@ -154,92 +157,105 @@ abstract static class ThreadStateReadNode extends PNodeWithContext {
154157
public abstract Object execute(Object key);
155158

156159
@Specialization(guards = "eq(key, CUR_EXC_TYPE)")
157-
PythonAbstractClass doCurExcType(@SuppressWarnings("unused") String key,
160+
Object doCurExcType(@SuppressWarnings("unused") String key,
161+
@Shared("toSulong") @Cached CExtNodes.ToSulongNode toSulongNode,
158162
@Shared("context") @CachedContext(PythonLanguage.class) PythonContext context,
159163
@Shared("getClassNode") @Cached GetClassNode getClassNode) {
160164
PException currentException = context.getCurrentException();
165+
Object result = null;
161166
if (currentException != null) {
162167
PBaseException exceptionObject = currentException.getExceptionObject();
163-
return getClassNode.execute(exceptionObject);
168+
result = getClassNode.execute(exceptionObject);
164169
}
165-
return null;
170+
return toSulongNode.execute(result != null ? result : PNone.NO_VALUE);
166171
}
167172

168173
@Specialization(guards = "eq(key, CUR_EXC_VALUE)")
169-
PBaseException doCurExcValue(@SuppressWarnings("unused") String key,
174+
Object doCurExcValue(@SuppressWarnings("unused") String key,
175+
@Shared("toSulong") @Cached CExtNodes.ToSulongNode toSulongNode,
170176
@Shared("context") @CachedContext(PythonLanguage.class) PythonContext context) {
171177
PException currentException = context.getCurrentException();
178+
Object result = null;
172179
if (currentException != null) {
173180
PBaseException exceptionObject = currentException.getExceptionObject();
174-
return exceptionObject;
181+
result = exceptionObject;
175182
}
176-
return null;
183+
return toSulongNode.execute(result != null ? result : PNone.NO_VALUE);
177184
}
178185

179186
@Specialization(guards = "eq(key, CUR_EXC_TRACEBACK)")
180187
Object doCurExcTraceback(@SuppressWarnings("unused") String key,
188+
@Shared("toSulong") @Cached CExtNodes.ToSulongNode toSulongNode,
181189
@Shared("context") @CachedContext(PythonLanguage.class) PythonContext context,
182190
@Shared("invokeNode") @Cached GenericInvokeNode invokeNode) {
183191
PException currentException = context.getCurrentException();
192+
Object result = null;
184193
if (currentException != null) {
185194
PBaseException exceptionObject = currentException.getExceptionObject();
186195
// we use 'GetTracebackNode' via a call to have a frame
187196
Object[] arguments = PArguments.create(1);
188197
PArguments.setArgument(arguments, 0, exceptionObject);
189-
return invokeNode.execute(null, ensureCallTarget(context.getLanguage()), arguments);
198+
result = invokeNode.execute(null, ensureCallTarget(context.getLanguage()), arguments);
190199
}
191-
return null;
200+
return toSulongNode.execute(result != null ? result : PNone.NO_VALUE);
192201
}
193202

194203
@Specialization(guards = "eq(key, EXC_TYPE)")
195-
PythonAbstractClass doExcType(@SuppressWarnings("unused") String key,
204+
Object doExcType(@SuppressWarnings("unused") String key,
205+
@Shared("toSulong") @Cached CExtNodes.ToSulongNode toSulongNode,
196206
@Shared("context") @CachedContext(PythonLanguage.class) PythonContext context,
197207
@Shared("getClassNode") @Cached GetClassNode getClassNode) {
198208
PException currentException = context.getCaughtException();
209+
Object result = null;
199210
if (currentException != null) {
200211
PBaseException exceptionObject = currentException.getExceptionObject();
201-
return getClassNode.execute(exceptionObject);
212+
result = getClassNode.execute(exceptionObject);
202213
}
203-
return null;
214+
return toSulongNode.execute(result != null ? result : PNone.NO_VALUE);
204215
}
205216

206217
@Specialization(guards = "eq(key, EXC_VALUE)")
207-
PBaseException doExcValue(@SuppressWarnings("unused") String key,
218+
Object doExcValue(@SuppressWarnings("unused") String key,
219+
@Shared("toSulong") @Cached CExtNodes.ToSulongNode toSulongNode,
208220
@Shared("context") @CachedContext(PythonLanguage.class) PythonContext context) {
209221
PException currentException = context.getCaughtException();
222+
Object result = null;
210223
if (currentException != null) {
211224
PBaseException exceptionObject = currentException.getExceptionObject();
212-
return exceptionObject;
225+
result = exceptionObject;
213226
}
214-
return null;
227+
return toSulongNode.execute(result != null ? result : PNone.NO_VALUE);
215228
}
216229

217230
@Specialization(guards = "eq(key, EXC_TRACEBACK)")
218231
Object doExcTraceback(@SuppressWarnings("unused") String key,
232+
@Shared("toSulong") @Cached CExtNodes.ToSulongNode toSulongNode,
219233
@Shared("context") @CachedContext(PythonLanguage.class) PythonContext context,
220234
@Shared("invokeNode") @Cached GenericInvokeNode invokeNode) {
221235
PException currentException = context.getCaughtException();
236+
Object result = null;
222237
if (currentException != null) {
223238
PBaseException exceptionObject = currentException.getExceptionObject();
224239
// we use 'GetTracebackNode' via a call to have a frame
225240
Object[] arguments = PArguments.create(1);
226241
PArguments.setArgument(arguments, 0, exceptionObject);
227-
return invokeNode.execute(null, ensureCallTarget(context.getLanguage()), arguments);
242+
result = invokeNode.execute(null, ensureCallTarget(context.getLanguage()), arguments);
228243
}
229-
return null;
244+
return toSulongNode.execute(result != null ? result : PNone.NO_VALUE);
230245
}
231246

232247
@Specialization(guards = "eq(key, DICT)")
233-
PDict doDict(@SuppressWarnings("unused") String key,
248+
Object doDict(@SuppressWarnings("unused") String key,
234249
@Cached PythonObjectFactory factory,
250+
@Shared("toSulong") @Cached CExtNodes.ToSulongNode toSulongNode,
235251
@Shared("context") @CachedContext(PythonLanguage.class) PythonContext context) {
236252
PThreadState customThreadState = context.getCustomThreadState();
237253
PDict threadStateDict = customThreadState.getThreadStateDict();
238254
if (threadStateDict == null) {
239255
threadStateDict = factory.createDict();
240256
customThreadState.setThreadStateDict(threadStateDict);
241257
}
242-
return threadStateDict;
258+
return toSulongNode.execute(threadStateDict != null ? threadStateDict : PNone.NO_VALUE);
243259
}
244260

245261
@Specialization(guards = "eq(key, PREV)")
@@ -248,6 +264,22 @@ Object doPrev(@SuppressWarnings("unused") String key,
248264
return getNativeNullNode.execute(null);
249265
}
250266

267+
private static class DepthCounter implements FrameInstanceVisitor<Object> {
268+
public long depth = 0;
269+
270+
public Object visitFrame(FrameInstance frameInstance) {
271+
depth++;
272+
return null;
273+
}
274+
}
275+
276+
@Specialization(guards = "eq(key, RECURSION_DEPTH)")
277+
long doRecursionDepth(@SuppressWarnings("unused") String key) {
278+
DepthCounter visitor = new DepthCounter();
279+
Truffle.getRuntime().iterateFrames(visitor);
280+
return visitor.depth;
281+
}
282+
251283
protected static boolean eq(String key, String expected) {
252284
return expected.equals(key);
253285
}
@@ -270,6 +302,7 @@ protected boolean isMemberModifiable(String member) {
270302
case EXC_TYPE:
271303
case EXC_VALUE:
272304
case EXC_TRACEBACK:
305+
case RECURSION_DEPTH:
273306
return true;
274307
default:
275308
return false;
@@ -382,6 +415,13 @@ PTraceback doExcTraceback(@SuppressWarnings("unused") String key, PTraceback val
382415
return value;
383416
}
384417

418+
@Specialization(guards = "eq(key, RECURSION_DEPTH)")
419+
@SuppressWarnings("unused")
420+
Object doRecursionDepth(String key, int value) {
421+
// TODO: (tfel) Can we not ignore this?
422+
return null;
423+
}
424+
385425
private static void setCurrentException(PRaiseNode raiseNode, PythonContext context, PBaseException exceptionObject) {
386426
try {
387427
throw raiseNode.raise(exceptionObject);

0 commit comments

Comments
 (0)