2828import static com .oracle .graal .python .runtime .PythonOptions .CatchAllExceptions ;
2929
3030import java .util .ArrayList ;
31- import java .util .List ;
3231
3332import com .oracle .graal .python .builtins .objects .PNone ;
3433import com .oracle .graal .python .builtins .objects .exception .PBaseException ;
34+ import com .oracle .graal .python .builtins .objects .function .PArguments ;
35+ import com .oracle .graal .python .builtins .objects .function .PBuiltinFunction ;
3536import com .oracle .graal .python .builtins .objects .module .PythonModule ;
37+ import com .oracle .graal .python .builtins .objects .tuple .PTuple ;
38+ import com .oracle .graal .python .nodes .BuiltinNames ;
3639import com .oracle .graal .python .nodes .PNode ;
37- import com .oracle .graal .python .nodes .attributes .ReadAttributeFromObjectNode ;
40+ import com .oracle .graal .python .nodes .attributes .GetAttributeNode ;
3841import com .oracle .graal .python .nodes .frame .ReadGlobalOrBuiltinNode ;
3942import com .oracle .graal .python .nodes .literal .TupleLiteralNode ;
43+ import com .oracle .graal .python .nodes .statement .TryExceptNode .ExceptBlockMR .CatchesFunction ;
44+ import com .oracle .graal .python .nodes .statement .TryExceptNode .ExceptBlockMR .CatchesFunction .ExceptListMR .ExecuteNode ;
4045import com .oracle .graal .python .runtime .PythonOptions ;
4146import com .oracle .graal .python .runtime .exception .ExceptionHandledException ;
4247import com .oracle .graal .python .runtime .exception .PException ;
4348import com .oracle .graal .python .runtime .exception .PythonErrorType ;
4449import com .oracle .truffle .api .CompilerDirectives ;
4550import com .oracle .truffle .api .CompilerDirectives .CompilationFinal ;
4651import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
52+ import com .oracle .truffle .api .RootCallTarget ;
4753import com .oracle .truffle .api .frame .VirtualFrame ;
4854import com .oracle .truffle .api .instrumentation .StandardTags ;
49- import com .oracle .truffle .api .instrumentation .Tag ;
5055import com .oracle .truffle .api .interop .ArityException ;
5156import com .oracle .truffle .api .interop .CanResolve ;
5257import com .oracle .truffle .api .interop .ForeignAccess ;
58+ import com .oracle .truffle .api .interop .KeyInfo ;
5359import com .oracle .truffle .api .interop .MessageResolution ;
5460import com .oracle .truffle .api .interop .Resolve ;
5561import com .oracle .truffle .api .interop .TruffleObject ;
@@ -64,10 +70,13 @@ public class TryExceptNode extends StatementNode implements TruffleObject {
6470 @ Children private final ExceptNode [] exceptNodes ;
6571 @ Child private PNode orelse ;
6672
73+ @ CompilationFinal CatchesFunction catchesFunction ;
74+
6775 @ CompilationFinal boolean seenException ;
6876
6977 public TryExceptNode (PNode body , ExceptNode [] exceptNodes , PNode orelse ) {
7078 this .body = body ;
79+ body .markAsTryBlock ();
7180 this .exceptNodes = exceptNodes ;
7281 this .orelse = orelse ;
7382 }
@@ -144,14 +153,6 @@ public PNode getOrelse() {
144153 }
145154
146155 @ Override
147- public boolean hasTag (Class <? extends Tag > tag ) {
148- return super .hasTag (tag ) || StandardTags .TryBlockTag .class == tag ;
149- }
150-
151- public Object getNodeObject () {
152- return this ;
153- }
154-
155156 public ForeignAccess getForeignAccess () {
156157 return ExceptBlockMRForeign .ACCESS ;
157158 }
@@ -172,31 +173,79 @@ Object access(TryExceptNode object) {
172173 }
173174 }
174175
176+ @ Resolve (message = "KEY_INFO" )
177+ abstract static class KeyInfoNode extends Node {
178+ Object access (@ SuppressWarnings ("unused" ) TryExceptNode object , String name ) {
179+ if (name .equals (StandardTags .TryBlockTag .CATCHES )) {
180+ return KeyInfo .INVOCABLE | KeyInfo .READABLE ;
181+ } else {
182+ return KeyInfo .NONE ;
183+ }
184+ }
185+ }
186+
175187 @ Resolve (message = "READ" )
176188 abstract static class ReadNode extends Node {
177- Object access (TryExceptNode object , String name ) {
189+ @ Child GetAttributeNode getAttr = GetAttributeNode .create ();
190+
191+ CatchesFunction access (TryExceptNode object , String name ) {
192+ return doit (object , name , getAttr );
193+ }
194+
195+ static CatchesFunction doit (TryExceptNode object , String name , GetAttributeNode getAttr ) {
178196 if (name .equals (StandardTags .TryBlockTag .CATCHES )) {
179- ExceptNode [] exceptNodes = object .getExceptNodes ();
180- List <String > literalCatches = new ArrayList <>();
181- for (ExceptNode node : exceptNodes ) {
182- PNode exceptType = node .getExceptType ();
183- if (exceptType instanceof ReadGlobalOrBuiltinNode ) {
184- literalCatches .add (((ReadGlobalOrBuiltinNode ) exceptType ).getAttributeId ());
185- } else if (exceptType instanceof TupleLiteralNode ) {
186- for (PNode tupleValue : ((TupleLiteralNode ) exceptType ).getValues ()) {
187- if (tupleValue instanceof ReadGlobalOrBuiltinNode ) {
188- literalCatches .add (((ReadGlobalOrBuiltinNode ) tupleValue ).getAttributeId ());
197+ if (object .catchesFunction == null ) {
198+ CompilerDirectives .transferToInterpreterAndInvalidate ();
199+ ArrayList <Object > literalCatches = new ArrayList <>();
200+ ExceptNode [] exceptNodes = object .getExceptNodes ();
201+ PythonModule builtins = object .getContext ().getBuiltins ();
202+
203+ for (ExceptNode node : exceptNodes ) {
204+ PNode exceptType = node .getExceptType ();
205+ if (exceptType instanceof ReadGlobalOrBuiltinNode ) {
206+ try {
207+ literalCatches .add (getAttr .execute (builtins , ((ReadGlobalOrBuiltinNode ) exceptType ).getAttributeId ()));
208+ } catch (PException e ) {
209+ }
210+ } else if (exceptType instanceof TupleLiteralNode ) {
211+ for (PNode tupleValue : ((TupleLiteralNode ) exceptType ).getValues ()) {
212+ if (tupleValue instanceof ReadGlobalOrBuiltinNode ) {
213+ try {
214+ literalCatches .add (getAttr .execute (builtins , ((ReadGlobalOrBuiltinNode ) tupleValue ).getAttributeId ()));
215+ } catch (PException e ) {
216+ }
217+ }
189218 }
190219 }
191220 }
221+
222+ Object isinstanceFunc = getAttr .execute (builtins , BuiltinNames .ISINSTANCE );
223+ PTuple caughtClasses = object .factory ().createTuple (literalCatches .toArray ());
224+
225+ if (isinstanceFunc instanceof PBuiltinFunction ) {
226+ RootCallTarget callTarget = ((PBuiltinFunction ) isinstanceFunc ).getCallTarget ();
227+ object .catchesFunction = new CatchesFunction (callTarget , caughtClasses );
228+ } else {
229+ throw new IllegalStateException ("isinstance was redefined, cannot check exceptions" );
230+ }
192231 }
193- return new CatchesFunction ( object .getContext (). getBuiltins (), literalCatches . toArray ( new String [ 0 ])) ;
232+ return object .catchesFunction ;
194233 } else {
195234 throw UnknownIdentifierException .raise (name );
196235 }
197236 }
198237 }
199238
239+ @ Resolve (message = "INVOKE" )
240+ abstract static class InvokeNode extends Node {
241+ @ Child GetAttributeNode getAttr = GetAttributeNode .create ();
242+
243+ Object access (TryExceptNode object , String name , Object [] arguments ) {
244+ CatchesFunction catchesFunction = ReadNode .doit (object , name , getAttr );
245+ return ExecuteNode .access (catchesFunction , arguments );
246+ }
247+ }
248+
200249 @ CanResolve
201250 abstract static class CheckFunction extends Node {
202251 protected static boolean test (TruffleObject receiver ) {
@@ -205,20 +254,25 @@ protected static boolean test(TruffleObject receiver) {
205254 }
206255
207256 protected static class CatchesFunction implements TruffleObject {
208- private final PythonModule builtins ;
209- @ CompilationFinal ( dimensions = 1 ) private final String [] attributes ;
210- private final ReadAttributeFromObjectNode getAttribute = ReadAttributeFromObjectNode .create ();
257+ private final RootCallTarget isInstance ;
258+ private final PTuple caughtClasses ;
259+ private final Object [] args = PArguments .create (2 );
211260
212- CatchesFunction (PythonModule builtins , String [] array ) {
213- this .builtins = builtins ;
214- this .attributes = array ;
261+ CatchesFunction (RootCallTarget callTarget , PTuple caughtClasses ) {
262+ this .isInstance = callTarget ;
263+ this .caughtClasses = caughtClasses ;
215264 }
216265
266+ @ ExplodeLoop
217267 boolean catches (Object exception ) {
218- for (String name : attributes ) {
219- Object execute = getAttribute .execute (builtins , name );
220- if (execute == exception ) {
221- return true ;
268+ if (exception instanceof PBaseException ) {
269+ PArguments .setArgument (args , 0 , exception );
270+ PArguments .setArgument (args , 1 , caughtClasses );
271+ try {
272+ if (isInstance .call (args ) == Boolean .TRUE ) {
273+ return true ;
274+ }
275+ } catch (PException e ) {
222276 }
223277 }
224278 return false ;
@@ -239,7 +293,7 @@ Object access(@SuppressWarnings("unused") CatchesFunction object) {
239293
240294 @ Resolve (message = "EXECUTE" )
241295 abstract static class ExecuteNode extends Node {
242- Object access (CatchesFunction object , Object [] arguments ) {
296+ static Object access (CatchesFunction object , Object [] arguments ) {
243297 if (arguments .length != 1 ) {
244298 throw ArityException .raise (1 , arguments .length );
245299 }
0 commit comments