28
28
import static com .oracle .graal .python .runtime .PythonOptions .CatchAllExceptions ;
29
29
30
30
import java .util .ArrayList ;
31
- import java .util .List ;
32
31
33
32
import com .oracle .graal .python .builtins .objects .PNone ;
34
33
import 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 ;
35
36
import 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 ;
36
39
import com .oracle .graal .python .nodes .PNode ;
37
- import com .oracle .graal .python .nodes .attributes .ReadAttributeFromObjectNode ;
40
+ import com .oracle .graal .python .nodes .attributes .GetAttributeNode ;
38
41
import com .oracle .graal .python .nodes .frame .ReadGlobalOrBuiltinNode ;
39
42
import 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 ;
40
45
import com .oracle .graal .python .runtime .PythonOptions ;
41
46
import com .oracle .graal .python .runtime .exception .ExceptionHandledException ;
42
47
import com .oracle .graal .python .runtime .exception .PException ;
43
48
import com .oracle .graal .python .runtime .exception .PythonErrorType ;
44
49
import com .oracle .truffle .api .CompilerDirectives ;
45
50
import com .oracle .truffle .api .CompilerDirectives .CompilationFinal ;
46
51
import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
52
+ import com .oracle .truffle .api .RootCallTarget ;
47
53
import com .oracle .truffle .api .frame .VirtualFrame ;
48
54
import com .oracle .truffle .api .instrumentation .StandardTags ;
49
- import com .oracle .truffle .api .instrumentation .Tag ;
50
55
import com .oracle .truffle .api .interop .ArityException ;
51
56
import com .oracle .truffle .api .interop .CanResolve ;
52
57
import com .oracle .truffle .api .interop .ForeignAccess ;
58
+ import com .oracle .truffle .api .interop .KeyInfo ;
53
59
import com .oracle .truffle .api .interop .MessageResolution ;
54
60
import com .oracle .truffle .api .interop .Resolve ;
55
61
import com .oracle .truffle .api .interop .TruffleObject ;
@@ -64,10 +70,13 @@ public class TryExceptNode extends StatementNode implements TruffleObject {
64
70
@ Children private final ExceptNode [] exceptNodes ;
65
71
@ Child private PNode orelse ;
66
72
73
+ @ CompilationFinal CatchesFunction catchesFunction ;
74
+
67
75
@ CompilationFinal boolean seenException ;
68
76
69
77
public TryExceptNode (PNode body , ExceptNode [] exceptNodes , PNode orelse ) {
70
78
this .body = body ;
79
+ body .markAsTryBlock ();
71
80
this .exceptNodes = exceptNodes ;
72
81
this .orelse = orelse ;
73
82
}
@@ -144,14 +153,6 @@ public PNode getOrelse() {
144
153
}
145
154
146
155
@ 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
-
155
156
public ForeignAccess getForeignAccess () {
156
157
return ExceptBlockMRForeign .ACCESS ;
157
158
}
@@ -172,31 +173,79 @@ Object access(TryExceptNode object) {
172
173
}
173
174
}
174
175
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
+
175
187
@ Resolve (message = "READ" )
176
188
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 ) {
178
196
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
+ }
189
218
}
190
219
}
191
220
}
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
+ }
192
231
}
193
- return new CatchesFunction ( object .getContext (). getBuiltins (), literalCatches . toArray ( new String [ 0 ])) ;
232
+ return object .catchesFunction ;
194
233
} else {
195
234
throw UnknownIdentifierException .raise (name );
196
235
}
197
236
}
198
237
}
199
238
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
+
200
249
@ CanResolve
201
250
abstract static class CheckFunction extends Node {
202
251
protected static boolean test (TruffleObject receiver ) {
@@ -205,20 +254,25 @@ protected static boolean test(TruffleObject receiver) {
205
254
}
206
255
207
256
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 );
211
260
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 ;
215
264
}
216
265
266
+ @ ExplodeLoop
217
267
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 ) {
222
276
}
223
277
}
224
278
return false ;
@@ -239,7 +293,7 @@ Object access(@SuppressWarnings("unused") CatchesFunction object) {
239
293
240
294
@ Resolve (message = "EXECUTE" )
241
295
abstract static class ExecuteNode extends Node {
242
- Object access (CatchesFunction object , Object [] arguments ) {
296
+ static Object access (CatchesFunction object , Object [] arguments ) {
243
297
if (arguments .length != 1 ) {
244
298
throw ArityException .raise (1 , arguments .length );
245
299
}
0 commit comments