|
44 | 44 | import static com.oracle.graal.python.nodes.SpecialMethodNames.__GET__;
|
45 | 45 | import static com.oracle.graal.python.nodes.SpecialMethodNames.__REPR__;
|
46 | 46 | import static com.oracle.graal.python.nodes.SpecialMethodNames.__SET__;
|
47 |
| -import static com.oracle.graal.python.runtime.exception.PythonErrorType.AttributeError; |
48 |
| -import static com.oracle.graal.python.runtime.exception.PythonErrorType.TypeError; |
49 | 47 |
|
50 | 48 | import java.util.List;
|
51 | 49 |
|
|
73 | 71 | import com.oracle.graal.python.nodes.function.builtins.PythonTernaryBuiltinNode;
|
74 | 72 | import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
|
75 | 73 | import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile;
|
| 74 | +import static com.oracle.graal.python.runtime.exception.PythonErrorType.AttributeError; |
| 75 | +import static com.oracle.graal.python.runtime.exception.PythonErrorType.TypeError; |
76 | 76 | import com.oracle.truffle.api.CompilerDirectives;
|
77 | 77 | import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
|
78 | 78 | import com.oracle.truffle.api.dsl.Cached;
|
|
81 | 81 | import com.oracle.truffle.api.dsl.Specialization;
|
82 | 82 | import com.oracle.truffle.api.frame.VirtualFrame;
|
83 | 83 | import com.oracle.truffle.api.library.CachedLibrary;
|
| 84 | +import com.oracle.truffle.api.nodes.Node; |
84 | 85 | import com.oracle.truffle.api.profiles.BranchProfile;
|
85 | 86 | import com.oracle.truffle.api.profiles.ConditionProfile;
|
86 | 87 |
|
@@ -186,131 +187,171 @@ private PRaiseNode getRaiseNode() {
|
186 | 187 | @Builtin(name = __GET__, minNumOfPositionalArgs = 2, maxNumOfPositionalArgs = 3)
|
187 | 188 | @GenerateNodeFactory
|
188 | 189 | abstract static class GetSetGetNode extends PythonTernaryBuiltinNode {
|
189 |
| - @Child private GetNameNode getNameNode; |
190 |
| - private final BranchProfile branchProfile = BranchProfile.create(); |
191 |
| - |
192 | 190 | // https://github.com/python/cpython/blob/e8b19656396381407ad91473af5da8b0d4346e88/Objects/descrobject.c#L149
|
193 | 191 | @Specialization
|
194 | 192 | Object get(VirtualFrame frame, GetSetDescriptor descr, Object obj, @SuppressWarnings("unused") Object type,
|
195 | 193 | @Cached DescriptorCheckNode descriptorCheckNode,
|
196 |
| - @Cached CallUnaryMethodNode callNode) { |
| 194 | + @Cached DescrGetNode getNode) { |
197 | 195 | if (descriptorCheckNode.execute(descr.getType(), descr.getName(), obj)) {
|
198 | 196 | return descr;
|
199 | 197 | }
|
| 198 | + return getNode.execute(frame, descr, obj); |
| 199 | + } |
| 200 | + |
| 201 | + @Specialization |
| 202 | + Object getSlot(VirtualFrame frame, HiddenKeyDescriptor descr, Object obj, @SuppressWarnings("unused") Object type, |
| 203 | + @Cached DescriptorCheckNode descriptorCheckNode, |
| 204 | + @Cached DescrGetNode getNode) { |
| 205 | + if (descriptorCheckNode.execute(descr.getType(), descr.getKey().getName(), obj)) { |
| 206 | + return descr; |
| 207 | + } |
| 208 | + return getNode.execute(frame, descr, obj); |
| 209 | + } |
| 210 | + } |
| 211 | + |
| 212 | + public abstract static class DescrGetNode extends AbstractDescrNode { |
| 213 | + public abstract Object execute(VirtualFrame frame, Object descr, Object obj); |
| 214 | + |
| 215 | + @Specialization |
| 216 | + Object get(VirtualFrame frame, GetSetDescriptor descr, Object obj, |
| 217 | + @Cached CallUnaryMethodNode callNode, |
| 218 | + @Cached BranchProfile branchProfile) { |
200 | 219 | if (descr.getGet() != null) {
|
201 | 220 | return callNode.executeObject(frame, descr.getGet(), obj);
|
202 | 221 | } else {
|
203 | 222 | branchProfile.enter();
|
204 |
| - throw raise(AttributeError, ErrorMessages.ATTR_S_OF_S_IS_NOT_READABLE, descr.getName(), getTypeName(descr.getType())); |
| 223 | + throw getRaiseNode().raise(AttributeError, ErrorMessages.ATTR_S_OF_S_IS_NOT_READABLE, descr.getName(), getTypeName(descr.getType())); |
205 | 224 | }
|
206 | 225 | }
|
207 | 226 |
|
208 | 227 | @Specialization
|
209 |
| - Object getSlot(HiddenKeyDescriptor descr, Object obj, @SuppressWarnings("unused") Object type, |
210 |
| - @Cached DescriptorCheckNode descriptorCheckNode, |
| 228 | + Object getSlot(HiddenKeyDescriptor descr, Object obj, |
211 | 229 | @Cached ReadAttributeFromObjectNode readNode,
|
212 | 230 | @Cached ConditionProfile profile) {
|
213 |
| - if (descriptorCheckNode.execute(descr.getType(), descr.getKey().getName(), obj)) { |
214 |
| - return descr; |
215 |
| - } |
216 | 231 | Object val = readNode.execute(obj, descr.getKey());
|
217 | 232 | if (profile.profile(val != PNone.NO_VALUE)) {
|
218 | 233 | return val;
|
219 | 234 | }
|
220 |
| - throw raise(AttributeError, descr.getKey().getName()); |
221 |
| - } |
222 |
| - |
223 |
| - private Object getTypeName(Object descrType) { |
224 |
| - if (getNameNode == null) { |
225 |
| - CompilerDirectives.transferToInterpreterAndInvalidate(); |
226 |
| - getNameNode = insert(GetNameNode.create()); |
227 |
| - } |
228 |
| - return getNameNode.execute(descrType); |
| 235 | + throw getRaiseNode().raise(AttributeError, descr.getKey().getName()); |
229 | 236 | }
|
230 | 237 | }
|
231 | 238 |
|
232 | 239 | @Builtin(name = __SET__, minNumOfPositionalArgs = 3)
|
233 | 240 | @GenerateNodeFactory
|
234 | 241 | abstract static class GetSetSetNode extends PythonTernaryBuiltinNode {
|
235 |
| - @Child private GetNameNode getNameNode; |
236 |
| - private final BranchProfile branchProfile = BranchProfile.create(); |
237 |
| - |
238 | 242 | @Specialization
|
239 | 243 | Object set(VirtualFrame frame, GetSetDescriptor descr, Object obj, Object value,
|
240 | 244 | @Cached DescriptorCheckNode descriptorCheckNode,
|
241 |
| - @Cached CallBinaryMethodNode callNode) { |
| 245 | + @Cached DescrSetNode setNode) { |
242 | 246 | if (descriptorCheckNode.execute(descr.getType(), descr.getName(), obj)) {
|
243 | 247 | return descr;
|
244 | 248 | }
|
| 249 | + return setNode.execute(frame, descr, obj, value); |
| 250 | + } |
| 251 | + |
| 252 | + @Specialization |
| 253 | + Object setSlot(VirtualFrame frame, HiddenKeyDescriptor descr, Object obj, Object value, |
| 254 | + @Cached DescriptorCheckNode descriptorCheckNode, |
| 255 | + @Cached DescrSetNode setNode) { |
| 256 | + if (descriptorCheckNode.execute(descr.getType(), descr.getKey().getName(), obj)) { |
| 257 | + return descr; |
| 258 | + } |
| 259 | + return setNode.execute(frame, descr, obj, value); |
| 260 | + } |
| 261 | + } |
| 262 | + |
| 263 | + public abstract static class DescrSetNode extends AbstractDescrNode { |
| 264 | + public abstract Object execute(VirtualFrame frame, Object descr, Object obj, Object value); |
| 265 | + |
| 266 | + @Specialization |
| 267 | + Object set(VirtualFrame frame, GetSetDescriptor descr, Object obj, Object value, |
| 268 | + @Cached CallBinaryMethodNode callNode, |
| 269 | + @Cached BranchProfile branchProfile) { |
245 | 270 | if (descr.getSet() != null) {
|
246 | 271 | return callNode.executeObject(frame, descr.getSet(), obj, value);
|
247 | 272 | } else {
|
248 | 273 | branchProfile.enter();
|
249 |
| - throw raise(AttributeError, ErrorMessages.ATTR_S_OF_S_OBJ_IS_NOT_WRITABLE, descr.getName(), getTypeName(descr.getType())); |
| 274 | + throw getRaiseNode().raise(AttributeError, ErrorMessages.ATTR_S_OF_S_OBJ_IS_NOT_WRITABLE, descr.getName(), getTypeName(descr.getType())); |
250 | 275 | }
|
251 | 276 | }
|
252 | 277 |
|
253 | 278 | @Specialization
|
254 | 279 | Object setSlot(HiddenKeyDescriptor descr, Object obj, Object value,
|
255 |
| - @Cached DescriptorCheckNode descriptorCheckNode, |
256 | 280 | @Cached WriteAttributeToObjectNode writeNode) {
|
257 |
| - if (descriptorCheckNode.execute(descr.getType(), descr.getKey().getName(), obj)) { |
258 |
| - return descr; |
259 |
| - } |
260 | 281 | return writeNode.execute(obj, descr.getKey(), value);
|
261 | 282 | }
|
262 |
| - |
263 |
| - private Object getTypeName(Object descrType) { |
264 |
| - if (getNameNode == null) { |
265 |
| - CompilerDirectives.transferToInterpreterAndInvalidate(); |
266 |
| - getNameNode = insert(GetNameNode.create()); |
267 |
| - } |
268 |
| - return getNameNode.execute(descrType); |
269 |
| - } |
270 | 283 | }
|
271 | 284 |
|
272 | 285 | @Builtin(name = __DELETE__, minNumOfPositionalArgs = 2)
|
273 | 286 | @GenerateNodeFactory
|
274 | 287 | abstract static class GetSetDeleteNode extends PythonBinaryBuiltinNode {
|
275 |
| - @Child private GetNameNode getNameNode; |
276 |
| - private final BranchProfile branchProfile = BranchProfile.create(); |
277 | 288 |
|
278 | 289 | @Specialization
|
279 | 290 | Object delete(VirtualFrame frame, GetSetDescriptor descr, Object obj,
|
280 | 291 | @Cached DescriptorCheckNode descriptorCheckNode,
|
281 |
| - @Cached CallBinaryMethodNode callNode) { |
| 292 | + @Cached DescrDeleteNode deleteNode) { |
282 | 293 | if (descriptorCheckNode.execute(descr.getType(), descr.getName(), obj)) {
|
283 | 294 | return descr;
|
284 | 295 | }
|
| 296 | + return deleteNode.execute(frame, descr, obj); |
| 297 | + } |
| 298 | + |
| 299 | + @Specialization |
| 300 | + Object deleteSlot(VirtualFrame frame, HiddenKeyDescriptor descr, Object obj, |
| 301 | + @Cached DescriptorCheckNode descriptorCheckNode, |
| 302 | + @Cached DescrDeleteNode deleteNode) { |
| 303 | + if (descriptorCheckNode.execute(descr.getType(), descr.getKey().getName(), obj)) { |
| 304 | + return descr; |
| 305 | + } |
| 306 | + return deleteNode.execute(frame, descr, obj); |
| 307 | + } |
| 308 | + } |
| 309 | + |
| 310 | + public abstract static class DescrDeleteNode extends AbstractDescrNode { |
| 311 | + public abstract Object execute(VirtualFrame frame, Object descr, Object obj); |
| 312 | + |
| 313 | + @Specialization |
| 314 | + Object delete(VirtualFrame frame, GetSetDescriptor descr, Object obj, |
| 315 | + @Cached CallBinaryMethodNode callNode, |
| 316 | + @Cached BranchProfile branchProfile) { |
285 | 317 | if (descr.allowsDelete()) {
|
286 | 318 | return callNode.executeObject(frame, descr.getSet(), obj, DescriptorDeleteMarker.INSTANCE);
|
287 | 319 | } else {
|
288 | 320 | branchProfile.enter();
|
289 | 321 | if (descr.getSet() != null) {
|
290 |
| - throw raise(TypeError, ErrorMessages.CANNOT_DELETE_ATTRIBUTE, getTypeName(descr.getType()), descr.getName()); |
| 322 | + throw getRaiseNode().raise(TypeError, ErrorMessages.CANNOT_DELETE_ATTRIBUTE, getTypeName(descr.getType()), descr.getName()); |
291 | 323 | } else {
|
292 |
| - throw raise(AttributeError, ErrorMessages.READONLY_ATTRIBUTE); |
| 324 | + throw getRaiseNode().raise(AttributeError, ErrorMessages.READONLY_ATTRIBUTE); |
293 | 325 | }
|
294 | 326 | }
|
295 | 327 | }
|
296 | 328 |
|
297 | 329 | @Specialization
|
298 | 330 | Object deleteSlot(HiddenKeyDescriptor descr, Object obj,
|
299 |
| - @Cached DescriptorCheckNode descriptorCheckNode, |
300 | 331 | @Cached WriteAttributeToObjectNode writeNode) {
|
301 |
| - if (descriptorCheckNode.execute(descr.getType(), descr.getKey().getName(), obj)) { |
302 |
| - return descr; |
303 |
| - } |
304 | 332 | writeNode.execute(obj, descr.getKey(), PNone.NO_VALUE);
|
305 | 333 | return PNone.NONE;
|
306 | 334 | }
|
| 335 | + } |
307 | 336 |
|
308 |
| - private Object getTypeName(Object descrType) { |
| 337 | + private abstract static class AbstractDescrNode extends Node { |
| 338 | + @Node.Child private GetNameNode getNameNode; |
| 339 | + @Node.Child private PRaiseNode raiseNode; |
| 340 | + |
| 341 | + protected Object getTypeName(Object descrType) { |
309 | 342 | if (getNameNode == null) {
|
310 | 343 | CompilerDirectives.transferToInterpreterAndInvalidate();
|
311 | 344 | getNameNode = insert(GetNameNode.create());
|
312 | 345 | }
|
313 | 346 | return getNameNode.execute(descrType);
|
314 | 347 | }
|
| 348 | + |
| 349 | + protected PRaiseNode getRaiseNode() { |
| 350 | + if (raiseNode == null) { |
| 351 | + CompilerDirectives.transferToInterpreterAndInvalidate(); |
| 352 | + raiseNode = insert(PRaiseNode.create()); |
| 353 | + } |
| 354 | + return raiseNode; |
| 355 | + } |
315 | 356 | }
|
316 | 357 | }
|
0 commit comments