47
47
import com .oracle .graal .python .builtins .objects .PNone ;
48
48
import com .oracle .graal .python .builtins .objects .common .SequenceNodes ;
49
49
import com .oracle .graal .python .builtins .objects .tuple .PTuple ;
50
- import com .oracle .graal .python .builtins .objects .type .TypeNodes ;
50
+ import com .oracle .graal .python .builtins .objects .type .TypeNodes . IsTypeNode ;
51
51
import com .oracle .graal .python .nodes .ErrorMessages ;
52
52
import com .oracle .graal .python .nodes .PGuards ;
53
53
import com .oracle .graal .python .nodes .PRaiseNode ;
54
- import com .oracle .graal .python .nodes .SpecialMethodNames ;
55
54
import com .oracle .graal .python .nodes .call .CallNode ;
56
55
import com .oracle .graal .python .nodes .classes .IsSubtypeNode ;
57
56
import com .oracle .graal .python .runtime .object .PythonObjectFactory ;
58
- import com .oracle .truffle .api .CompilerDirectives ;
59
57
import com .oracle .truffle .api .dsl .Bind ;
60
58
import com .oracle .truffle .api .dsl .Cached ;
59
+ import com .oracle .truffle .api .dsl .Cached .Shared ;
61
60
import com .oracle .truffle .api .dsl .Fallback ;
62
61
import com .oracle .truffle .api .dsl .ImportStatic ;
63
62
import com .oracle .truffle .api .dsl .Specialization ;
69
68
* Creates an exception out of type and value, similarly to CPython's
70
69
* {@code PyErr_NormalizeException}. Returns the normalized exception.
71
70
*/
72
- @ ImportStatic ({ PGuards .class , SpecialMethodNames . class } )
71
+ @ ImportStatic (PGuards .class )
73
72
public abstract class PrepareExceptionNode extends Node {
74
73
public abstract PBaseException execute (VirtualFrame frame , Object type , Object value );
75
74
76
- private PRaiseNode raiseNode ;
77
- private IsSubtypeNode isSubtypeNode ;
78
-
79
75
@ Specialization
80
76
static PBaseException doException (PBaseException exc , @ SuppressWarnings ("unused" ) PNone value ) {
81
77
return exc ;
82
78
}
83
79
84
80
@ Specialization (guards = "!isPNone(value)" )
85
- PBaseException doException (@ SuppressWarnings ("unused" ) PBaseException exc , @ SuppressWarnings ("unused" ) Object value ) {
86
- throw raise ().raise (PythonBuiltinClassType .TypeError , ErrorMessages .INSTANCE_EX_MAY_NOT_HAVE_SEP_VALUE );
81
+ static PBaseException doException (@ SuppressWarnings ("unused" ) PBaseException exc , @ SuppressWarnings ("unused" ) Object value ,
82
+ @ Shared @ Cached PRaiseNode raiseNode ) {
83
+ throw raiseNode .raise (TypeError , ErrorMessages .INSTANCE_EX_MAY_NOT_HAVE_SEP_VALUE );
87
84
}
88
85
89
86
@ Specialization (guards = "isTypeNode.execute(type)" , limit = "1" )
90
- PBaseException doException (VirtualFrame frame , Object type , PBaseException value ,
87
+ static PBaseException doException (VirtualFrame frame , Object type , PBaseException value ,
91
88
@ Bind ("this" ) Node inliningTarget ,
92
- @ SuppressWarnings ("unused" ) @ Cached . Shared ("isType" ) @ Cached TypeNodes . IsTypeNode isTypeNode ,
89
+ @ SuppressWarnings ("unused" ) @ Shared ("isType" ) @ Cached IsTypeNode isTypeNode ,
93
90
@ Cached BuiltinFunctions .IsInstanceNode isInstanceNode ,
94
91
@ Cached InlinedBranchProfile isNotInstanceProfile ,
95
- @ Cached .Shared ("callCtor" ) @ Cached CallNode callConstructor ) {
92
+ @ Shared @ Cached IsSubtypeNode isSubtypeNode ,
93
+ @ Shared @ Cached PRaiseNode raiseNode ,
94
+ @ Shared ("callCtor" ) @ Cached CallNode callConstructor ) {
96
95
if (isInstanceNode .executeWith (frame , value , type )) {
97
- checkExceptionClass (type );
96
+ checkExceptionClass (type , isSubtypeNode , raiseNode );
98
97
return value ;
99
98
} else {
100
99
isNotInstanceProfile .enter (inliningTarget );
101
- return doCreateObject (frame , type , value , isTypeNode , callConstructor );
100
+ return doCreateObject (frame , type , value , isTypeNode , isSubtypeNode , raiseNode , callConstructor );
102
101
}
103
102
}
104
103
105
104
@ Specialization (guards = "isTypeNode.execute(type)" , limit = "1" )
106
- PBaseException doCreate (VirtualFrame frame , Object type , @ SuppressWarnings ("unused" ) PNone value ,
107
- @ SuppressWarnings ("unused" ) @ Cached .Shared ("isType" ) @ Cached TypeNodes .IsTypeNode isTypeNode ,
108
- @ Cached .Shared ("callCtor" ) @ Cached CallNode callConstructor ) {
109
- checkExceptionClass (type );
105
+ static PBaseException doCreate (VirtualFrame frame , Object type , @ SuppressWarnings ("unused" ) PNone value ,
106
+ @ SuppressWarnings ("unused" ) @ Shared ("isType" ) @ Cached IsTypeNode isTypeNode ,
107
+ @ Shared @ Cached IsSubtypeNode isSubtypeNode ,
108
+ @ Shared @ Cached PRaiseNode raiseNode ,
109
+ @ Shared ("callCtor" ) @ Cached CallNode callConstructor ) {
110
+ checkExceptionClass (type , isSubtypeNode , raiseNode );
110
111
Object instance = callConstructor .execute (frame , type );
111
112
if (instance instanceof PBaseException ) {
112
113
return (PBaseException ) instance ;
@@ -116,12 +117,14 @@ PBaseException doCreate(VirtualFrame frame, Object type, @SuppressWarnings("unus
116
117
}
117
118
118
119
@ Specialization (guards = "isTypeNode.execute(type)" , limit = "1" )
119
- PBaseException doCreateTuple (VirtualFrame frame , Object type , PTuple value ,
120
+ static PBaseException doCreateTuple (VirtualFrame frame , Object type , PTuple value ,
120
121
@ Bind ("this" ) Node inliningTarget ,
121
- @ SuppressWarnings ("unused" ) @ Cached . Shared ("isType" ) @ Cached TypeNodes . IsTypeNode isTypeNode ,
122
+ @ SuppressWarnings ("unused" ) @ Shared ("isType" ) @ Cached IsTypeNode isTypeNode ,
122
123
@ Cached SequenceNodes .GetObjectArrayNode getObjectArrayNode ,
123
- @ Cached .Shared ("callCtor" ) @ Cached CallNode callConstructor ) {
124
- checkExceptionClass (type );
124
+ @ Shared @ Cached IsSubtypeNode isSubtypeNode ,
125
+ @ Shared @ Cached PRaiseNode raiseNode ,
126
+ @ Shared ("callCtor" ) @ Cached CallNode callConstructor ) {
127
+ checkExceptionClass (type , isSubtypeNode , raiseNode );
125
128
Object [] args = getObjectArrayNode .execute (inliningTarget , value );
126
129
Object instance = callConstructor .execute (frame , type , args );
127
130
if (instance instanceof PBaseException ) {
@@ -132,10 +135,12 @@ PBaseException doCreateTuple(VirtualFrame frame, Object type, PTuple value,
132
135
}
133
136
134
137
@ Specialization (guards = {"isTypeNode.execute(type)" , "!isPNone(value)" , "!isPTuple(value)" , "!isPBaseException(value)" }, limit = "1" )
135
- PBaseException doCreateObject (VirtualFrame frame , Object type , Object value ,
136
- @ SuppressWarnings ("unused" ) @ Cached .Shared ("isType" ) @ Cached TypeNodes .IsTypeNode isTypeNode ,
137
- @ Cached .Shared ("callCtor" ) @ Cached CallNode callConstructor ) {
138
- checkExceptionClass (type );
138
+ static PBaseException doCreateObject (VirtualFrame frame , Object type , Object value ,
139
+ @ SuppressWarnings ("unused" ) @ Shared ("isType" ) @ Cached IsTypeNode isTypeNode ,
140
+ @ Shared @ Cached IsSubtypeNode isSubtypeNode ,
141
+ @ Shared @ Cached PRaiseNode raiseNode ,
142
+ @ Shared ("callCtor" ) @ Cached CallNode callConstructor ) {
143
+ checkExceptionClass (type , isSubtypeNode , raiseNode );
139
144
Object instance = callConstructor .execute (frame , type , value );
140
145
if (instance instanceof PBaseException ) {
141
146
return (PBaseException ) instance ;
@@ -144,34 +149,23 @@ PBaseException doCreateObject(VirtualFrame frame, Object type, Object value,
144
149
}
145
150
}
146
151
152
+ @ Fallback
153
+ static PBaseException doError (Object type , @ SuppressWarnings ("unused" ) Object value ,
154
+ @ Shared @ Cached PRaiseNode raiseNode ) {
155
+ throw raiseNode .raise (TypeError , ErrorMessages .EXCEPTIONS_MUST_BE_CLASSES_OR_INSTANCES_DERIVING_FROM_BASE_EX , type );
156
+ }
157
+
147
158
private static PBaseException handleInstanceNotAnException (Object type , Object instance ) {
148
159
/*
149
- * Instead of throwing the exception here, we throw it into the generator. That's what
150
- * CPython does
160
+ * Instead of throwing the exception here, we replace the created exception with it. This is
161
+ * done to match CPython's behavior of `generator.throw`
151
162
*/
152
163
return PythonObjectFactory .getUncached ().createBaseException (TypeError , ErrorMessages .CALLING_N_SHOULD_HAVE_RETURNED_AN_INSTANCE_OF_BASE_EXCEPTION_NOT_P , new Object []{type , instance });
153
164
}
154
165
155
- @ Fallback
156
- PBaseException doError (Object type , @ SuppressWarnings ("unused" ) Object value ) {
157
- throw raise ().raise (TypeError , ErrorMessages .EXCEPTIONS_MUST_BE_CLASSES_OR_INSTANCES_DERIVING_FROM_BASE_EX , type );
158
- }
159
-
160
- private PRaiseNode raise () {
161
- if (raiseNode == null ) {
162
- CompilerDirectives .transferToInterpreterAndInvalidate ();
163
- raiseNode = insert (PRaiseNode .create ());
164
- }
165
- return raiseNode ;
166
- }
167
-
168
- private void checkExceptionClass (Object type ) {
169
- if (isSubtypeNode == null ) {
170
- CompilerDirectives .transferToInterpreterAndInvalidate ();
171
- isSubtypeNode = insert (IsSubtypeNode .create ());
172
- }
166
+ private static void checkExceptionClass (Object type , IsSubtypeNode isSubtypeNode , PRaiseNode raiseNode ) {
173
167
if (!isSubtypeNode .execute (type , PythonBuiltinClassType .PBaseException )) {
174
- throw raise () .raise (TypeError , ErrorMessages .EXCEPTIONS_MUST_BE_CLASSES_OR_INSTANCES_DERIVING_FROM_BASE_EX , type );
168
+ throw raiseNode .raise (TypeError , ErrorMessages .EXCEPTIONS_MUST_BE_CLASSES_OR_INSTANCES_DERIVING_FROM_BASE_EX , type );
175
169
}
176
170
}
177
171
}
0 commit comments