5454import com .oracle .graal .python .builtins .objects .function .PArguments ;
5555import com .oracle .graal .python .builtins .objects .function .Signature ;
5656import com .oracle .graal .python .builtins .objects .traceback .PTraceback ;
57- import com .oracle .graal .python .builtins .objects .type .PythonAbstractClass ;
5857import com .oracle .graal .python .builtins .objects .type .PythonClass ;
5958import com .oracle .graal .python .nodes .PNodeWithContext ;
6059import com .oracle .graal .python .nodes .PRaiseNode ;
6968import com .oracle .truffle .api .CompilerDirectives ;
7069import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
7170import com .oracle .truffle .api .RootCallTarget ;
71+ import com .oracle .truffle .api .Truffle ;
7272import com .oracle .truffle .api .TruffleLanguage ;
7373import com .oracle .truffle .api .dsl .Cached ;
7474import com .oracle .truffle .api .dsl .Cached .Exclusive ;
7777import com .oracle .truffle .api .dsl .GenerateUncached ;
7878import com .oracle .truffle .api .dsl .ImportStatic ;
7979import com .oracle .truffle .api .dsl .Specialization ;
80+ import com .oracle .truffle .api .frame .FrameInstance ;
81+ import com .oracle .truffle .api .frame .FrameInstanceVisitor ;
8082import com .oracle .truffle .api .frame .VirtualFrame ;
8183import com .oracle .truffle .api .interop .InteropLibrary ;
8284import 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