41
41
package com .oracle .graal .python .nodes .attributes ;
42
42
43
43
import static com .oracle .graal .python .nodes .SpecialMethodNames .__GETATTRIBUTE__ ;
44
+ import static com .oracle .graal .python .nodes .SpecialMethodNames .__GETATTR__ ;
45
+ import static com .oracle .graal .python .runtime .exception .PythonErrorType .AttributeError ;
44
46
45
47
import com .oracle .graal .python .nodes .call .special .LookupAndCallBinaryNode ;
46
48
import com .oracle .graal .python .nodes .expression .ExpressionNode ;
47
49
import com .oracle .graal .python .nodes .frame .ReadNode ;
48
50
import com .oracle .graal .python .nodes .statement .StatementNode ;
51
+ import com .oracle .graal .python .runtime .exception .PException ;
52
+ import com .oracle .truffle .api .CompilerDirectives ;
53
+ import com .oracle .truffle .api .CompilerDirectives .CompilationFinal ;
49
54
import com .oracle .truffle .api .dsl .NodeChild ;
50
55
import com .oracle .truffle .api .dsl .Specialization ;
51
56
import com .oracle .truffle .api .nodes .UnexpectedResultException ;
57
+ import com .oracle .truffle .api .profiles .ConditionProfile ;
52
58
53
59
@ NodeChild (value = "object" , type = ExpressionNode .class )
54
60
public abstract class GetAttributeNode extends ExpressionNode implements ReadNode {
55
61
56
62
private final String key ;
57
63
58
64
@ Child LookupAndCallBinaryNode dispatchNode = LookupAndCallBinaryNode .create (__GETATTRIBUTE__ );
65
+ @ Child LookupAndCallBinaryNode dispatchGetAttr ;
66
+ @ CompilationFinal private ConditionProfile errorProfile = ConditionProfile .createBinaryProfile ();
59
67
60
68
protected GetAttributeNode (String key ) {
61
69
this .key = key ;
@@ -77,16 +85,39 @@ public static GetAttributeNode create(String key, ExpressionNode object) {
77
85
78
86
@ Specialization (rewriteOn = UnexpectedResultException .class )
79
87
protected int doItInt (Object object ) throws UnexpectedResultException {
80
- return dispatchNode .executeInt (object , key );
88
+ try {
89
+ return dispatchNode .executeInt (object , key );
90
+ } catch (PException pe ) {
91
+ pe .expect (AttributeError , getCore (), errorProfile );
92
+ return getDispatchGetAttr ().executeInt (object , key );
93
+ }
81
94
}
82
95
83
96
@ Specialization (rewriteOn = UnexpectedResultException .class )
84
97
protected boolean doItBoolean (Object object ) throws UnexpectedResultException {
85
- return dispatchNode .executeBool (object , key );
98
+ try {
99
+ return dispatchNode .executeBool (object , key );
100
+ } catch (PException pe ) {
101
+ pe .expect (AttributeError , getCore (), errorProfile );
102
+ return getDispatchGetAttr ().executeBool (object , key );
103
+ }
86
104
}
87
105
88
106
@ Specialization (replaces = {"doItInt" , "doItBoolean" })
89
107
protected Object doIt (Object object ) {
90
- return dispatchNode .executeObject (object , key );
108
+ try {
109
+ return dispatchNode .executeObject (object , key );
110
+ } catch (PException pe ) {
111
+ pe .expect (AttributeError , getCore (), errorProfile );
112
+ return getDispatchGetAttr ().executeObject (object , key );
113
+ }
114
+ }
115
+
116
+ private LookupAndCallBinaryNode getDispatchGetAttr () {
117
+ if (dispatchGetAttr == null ) {
118
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
119
+ dispatchGetAttr = insert (LookupAndCallBinaryNode .create (__GETATTR__ ));
120
+ }
121
+ return dispatchGetAttr ;
91
122
}
92
123
}
0 commit comments