54
54
import com .oracle .graal .python .builtins .objects .function .PArguments ;
55
55
import com .oracle .graal .python .builtins .objects .function .Signature ;
56
56
import com .oracle .graal .python .builtins .objects .traceback .PTraceback ;
57
- import com .oracle .graal .python .builtins .objects .type .PythonAbstractClass ;
58
57
import com .oracle .graal .python .builtins .objects .type .PythonClass ;
59
58
import com .oracle .graal .python .nodes .PNodeWithContext ;
60
59
import com .oracle .graal .python .nodes .PRaiseNode ;
69
68
import com .oracle .truffle .api .CompilerDirectives ;
70
69
import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
71
70
import com .oracle .truffle .api .RootCallTarget ;
71
+ import com .oracle .truffle .api .Truffle ;
72
72
import com .oracle .truffle .api .TruffleLanguage ;
73
73
import com .oracle .truffle .api .dsl .Cached ;
74
74
import com .oracle .truffle .api .dsl .Cached .Exclusive ;
77
77
import com .oracle .truffle .api .dsl .GenerateUncached ;
78
78
import com .oracle .truffle .api .dsl .ImportStatic ;
79
79
import com .oracle .truffle .api .dsl .Specialization ;
80
+ import com .oracle .truffle .api .frame .FrameInstance ;
81
+ import com .oracle .truffle .api .frame .FrameInstanceVisitor ;
80
82
import com .oracle .truffle .api .frame .VirtualFrame ;
81
83
import com .oracle .truffle .api .interop .InteropLibrary ;
82
84
import com .oracle .truffle .api .interop .UnknownIdentifierException ;
@@ -98,6 +100,7 @@ public class PThreadState extends PythonNativeWrapper {
98
100
public static final String EXC_TRACEBACK = "exc_traceback" ;
99
101
public static final String DICT = "dict" ;
100
102
public static final String PREV = "prev" ;
103
+ public static final String RECURSION_DEPTH = "recursion_depth" ;
101
104
102
105
private PDict dict ;
103
106
@@ -126,23 +129,23 @@ protected boolean isMemberReadable(String member) {
126
129
case EXC_TRACEBACK :
127
130
case DICT :
128
131
case PREV :
132
+ case RECURSION_DEPTH :
129
133
return true ;
130
134
default :
131
135
return false ;
132
136
}
133
137
}
134
138
135
139
@ 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 });
138
143
}
139
144
140
145
@ ExportMessage
141
146
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 );
146
149
}
147
150
148
151
@ ImportStatic (PThreadState .class )
@@ -154,92 +157,105 @@ abstract static class ThreadStateReadNode extends PNodeWithContext {
154
157
public abstract Object execute (Object key );
155
158
156
159
@ 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 ,
158
162
@ Shared ("context" ) @ CachedContext (PythonLanguage .class ) PythonContext context ,
159
163
@ Shared ("getClassNode" ) @ Cached GetClassNode getClassNode ) {
160
164
PException currentException = context .getCurrentException ();
165
+ Object result = null ;
161
166
if (currentException != null ) {
162
167
PBaseException exceptionObject = currentException .getExceptionObject ();
163
- return getClassNode .execute (exceptionObject );
168
+ result = getClassNode .execute (exceptionObject );
164
169
}
165
- return null ;
170
+ return toSulongNode . execute ( result != null ? result : PNone . NO_VALUE ) ;
166
171
}
167
172
168
173
@ 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 ,
170
176
@ Shared ("context" ) @ CachedContext (PythonLanguage .class ) PythonContext context ) {
171
177
PException currentException = context .getCurrentException ();
178
+ Object result = null ;
172
179
if (currentException != null ) {
173
180
PBaseException exceptionObject = currentException .getExceptionObject ();
174
- return exceptionObject ;
181
+ result = exceptionObject ;
175
182
}
176
- return null ;
183
+ return toSulongNode . execute ( result != null ? result : PNone . NO_VALUE ) ;
177
184
}
178
185
179
186
@ Specialization (guards = "eq(key, CUR_EXC_TRACEBACK)" )
180
187
Object doCurExcTraceback (@ SuppressWarnings ("unused" ) String key ,
188
+ @ Shared ("toSulong" ) @ Cached CExtNodes .ToSulongNode toSulongNode ,
181
189
@ Shared ("context" ) @ CachedContext (PythonLanguage .class ) PythonContext context ,
182
190
@ Shared ("invokeNode" ) @ Cached GenericInvokeNode invokeNode ) {
183
191
PException currentException = context .getCurrentException ();
192
+ Object result = null ;
184
193
if (currentException != null ) {
185
194
PBaseException exceptionObject = currentException .getExceptionObject ();
186
195
// we use 'GetTracebackNode' via a call to have a frame
187
196
Object [] arguments = PArguments .create (1 );
188
197
PArguments .setArgument (arguments , 0 , exceptionObject );
189
- return invokeNode .execute (null , ensureCallTarget (context .getLanguage ()), arguments );
198
+ result = invokeNode .execute (null , ensureCallTarget (context .getLanguage ()), arguments );
190
199
}
191
- return null ;
200
+ return toSulongNode . execute ( result != null ? result : PNone . NO_VALUE ) ;
192
201
}
193
202
194
203
@ 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 ,
196
206
@ Shared ("context" ) @ CachedContext (PythonLanguage .class ) PythonContext context ,
197
207
@ Shared ("getClassNode" ) @ Cached GetClassNode getClassNode ) {
198
208
PException currentException = context .getCaughtException ();
209
+ Object result = null ;
199
210
if (currentException != null ) {
200
211
PBaseException exceptionObject = currentException .getExceptionObject ();
201
- return getClassNode .execute (exceptionObject );
212
+ result = getClassNode .execute (exceptionObject );
202
213
}
203
- return null ;
214
+ return toSulongNode . execute ( result != null ? result : PNone . NO_VALUE ) ;
204
215
}
205
216
206
217
@ 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 ,
208
220
@ Shared ("context" ) @ CachedContext (PythonLanguage .class ) PythonContext context ) {
209
221
PException currentException = context .getCaughtException ();
222
+ Object result = null ;
210
223
if (currentException != null ) {
211
224
PBaseException exceptionObject = currentException .getExceptionObject ();
212
- return exceptionObject ;
225
+ result = exceptionObject ;
213
226
}
214
- return null ;
227
+ return toSulongNode . execute ( result != null ? result : PNone . NO_VALUE ) ;
215
228
}
216
229
217
230
@ Specialization (guards = "eq(key, EXC_TRACEBACK)" )
218
231
Object doExcTraceback (@ SuppressWarnings ("unused" ) String key ,
232
+ @ Shared ("toSulong" ) @ Cached CExtNodes .ToSulongNode toSulongNode ,
219
233
@ Shared ("context" ) @ CachedContext (PythonLanguage .class ) PythonContext context ,
220
234
@ Shared ("invokeNode" ) @ Cached GenericInvokeNode invokeNode ) {
221
235
PException currentException = context .getCaughtException ();
236
+ Object result = null ;
222
237
if (currentException != null ) {
223
238
PBaseException exceptionObject = currentException .getExceptionObject ();
224
239
// we use 'GetTracebackNode' via a call to have a frame
225
240
Object [] arguments = PArguments .create (1 );
226
241
PArguments .setArgument (arguments , 0 , exceptionObject );
227
- return invokeNode .execute (null , ensureCallTarget (context .getLanguage ()), arguments );
242
+ result = invokeNode .execute (null , ensureCallTarget (context .getLanguage ()), arguments );
228
243
}
229
- return null ;
244
+ return toSulongNode . execute ( result != null ? result : PNone . NO_VALUE ) ;
230
245
}
231
246
232
247
@ Specialization (guards = "eq(key, DICT)" )
233
- PDict doDict (@ SuppressWarnings ("unused" ) String key ,
248
+ Object doDict (@ SuppressWarnings ("unused" ) String key ,
234
249
@ Cached PythonObjectFactory factory ,
250
+ @ Shared ("toSulong" ) @ Cached CExtNodes .ToSulongNode toSulongNode ,
235
251
@ Shared ("context" ) @ CachedContext (PythonLanguage .class ) PythonContext context ) {
236
252
PThreadState customThreadState = context .getCustomThreadState ();
237
253
PDict threadStateDict = customThreadState .getThreadStateDict ();
238
254
if (threadStateDict == null ) {
239
255
threadStateDict = factory .createDict ();
240
256
customThreadState .setThreadStateDict (threadStateDict );
241
257
}
242
- return threadStateDict ;
258
+ return toSulongNode . execute ( threadStateDict != null ? threadStateDict : PNone . NO_VALUE ) ;
243
259
}
244
260
245
261
@ Specialization (guards = "eq(key, PREV)" )
@@ -248,6 +264,22 @@ Object doPrev(@SuppressWarnings("unused") String key,
248
264
return getNativeNullNode .execute (null );
249
265
}
250
266
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
+
251
283
protected static boolean eq (String key , String expected ) {
252
284
return expected .equals (key );
253
285
}
@@ -270,6 +302,7 @@ protected boolean isMemberModifiable(String member) {
270
302
case EXC_TYPE :
271
303
case EXC_VALUE :
272
304
case EXC_TRACEBACK :
305
+ case RECURSION_DEPTH :
273
306
return true ;
274
307
default :
275
308
return false ;
@@ -382,6 +415,13 @@ PTraceback doExcTraceback(@SuppressWarnings("unused") String key, PTraceback val
382
415
return value ;
383
416
}
384
417
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
+
385
425
private static void setCurrentException (PRaiseNode raiseNode , PythonContext context , PBaseException exceptionObject ) {
386
426
try {
387
427
throw raiseNode .raise (exceptionObject );
0 commit comments