11/*
2- * Copyright (c) 2017, 2019 , Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 2017, 2020 , Oracle and/or its affiliates. All rights reserved.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * The Universal Permissive License (UPL), Version 1.0
4444import static com .oracle .graal .python .nodes .SpecialMethodNames .__GETATTR__ ;
4545import static com .oracle .graal .python .runtime .exception .PythonErrorType .AttributeError ;
4646
47+ import com .oracle .graal .python .builtins .objects .PNone ;
4748import com .oracle .graal .python .nodes .attributes .GetAttributeNodeGen .GetAnyAttributeNodeGen ;
4849import com .oracle .graal .python .nodes .attributes .GetAttributeNodeGen .GetFixedAttributeNodeGen ;
50+ import com .oracle .graal .python .nodes .call .special .CallBinaryMethodNode ;
4951import com .oracle .graal .python .nodes .call .special .LookupAndCallBinaryNode ;
5052import com .oracle .graal .python .nodes .expression .ExpressionNode ;
5153import com .oracle .graal .python .nodes .frame .ReadNode ;
5961import com .oracle .truffle .api .frame .VirtualFrame ;
6062import com .oracle .truffle .api .nodes .Node ;
6163import com .oracle .truffle .api .nodes .UnexpectedResultException ;
64+ import com .oracle .truffle .api .profiles .ConditionProfile ;
6265
6366@ NodeChild (value = "object" , type = ExpressionNode .class )
6467public abstract class GetAttributeNode extends ExpressionNode implements ReadNode {
@@ -108,12 +111,68 @@ public final StatementNode makeWriteNode(ExpressionNode rhs) {
108111
109112 public abstract ExpressionNode getObject ();
110113
111- public abstract static class GetFixedAttributeNode extends Node {
114+ abstract static class GetAttributeBaseNode extends Node {
115+
116+ @ Child private LookupInheritedAttributeNode lookupGetattrNode ;
117+ @ Child private CallBinaryMethodNode callBinaryMethodNode ;
118+
119+ @ CompilationFinal private ConditionProfile hasGetattrProfile ;
120+
121+ int dispatchGetAttrOrRethrowInt (VirtualFrame frame , Object object , Object key , PException pe ) throws UnexpectedResultException {
122+ return ensureCallGetattrNode ().executeInt (frame , lookupGetattrOrRethrow (object , pe ), object , key );
123+ }
124+
125+ long dispatchGetAttrOrRethrowLong (VirtualFrame frame , Object object , Object key , PException pe ) throws UnexpectedResultException {
126+ return ensureCallGetattrNode ().executeLong (frame , lookupGetattrOrRethrow (object , pe ), object , key );
127+ }
128+
129+ boolean dispatchGetAttrOrRethrowBool (VirtualFrame frame , Object object , Object key , PException pe ) throws UnexpectedResultException {
130+ return ensureCallGetattrNode ().executeBool (frame , lookupGetattrOrRethrow (object , pe ), object , key );
131+ }
132+
133+ Object dispatchGetAttrOrRethrowObject (VirtualFrame frame , Object object , Object key , PException pe ) {
134+ return ensureCallGetattrNode ().executeObject (frame , lookupGetattrOrRethrow (object , pe ), object , key );
135+ }
136+
137+ /** Lookup {@code __getattr__} or rethrow {@code pe} if it does not exist. */
138+ private Object lookupGetattrOrRethrow (Object object , PException pe ) {
139+ Object getattrAttribute = ensureLookupGetattrNode ().execute (object );
140+ if (ensureHasGetattrProfile ().profile (getattrAttribute == PNone .NO_VALUE )) {
141+ throw pe ;
142+ }
143+ return getattrAttribute ;
144+ }
145+
146+ private LookupInheritedAttributeNode ensureLookupGetattrNode () {
147+ if (lookupGetattrNode == null ) {
148+ CompilerDirectives .transferToInterpreterAndInvalidate ();
149+ lookupGetattrNode = insert (LookupInheritedAttributeNode .create (__GETATTR__ ));
150+ }
151+ return lookupGetattrNode ;
152+ }
153+
154+ private CallBinaryMethodNode ensureCallGetattrNode () {
155+ if (callBinaryMethodNode == null ) {
156+ CompilerDirectives .transferToInterpreterAndInvalidate ();
157+ callBinaryMethodNode = insert (CallBinaryMethodNode .create ());
158+ }
159+ return callBinaryMethodNode ;
160+ }
161+
162+ private ConditionProfile ensureHasGetattrProfile () {
163+ if (hasGetattrProfile == null ) {
164+ CompilerDirectives .transferToInterpreterAndInvalidate ();
165+ hasGetattrProfile = ConditionProfile .createBinaryProfile ();
166+ }
167+ return hasGetattrProfile ;
168+ }
169+ }
170+
171+ public abstract static class GetFixedAttributeNode extends GetAttributeBaseNode {
112172
113173 private final String key ;
114174
115175 @ Child private LookupAndCallBinaryNode dispatchNode = LookupAndCallBinaryNode .create (__GETATTRIBUTE__ );
116- @ Child private LookupAndCallBinaryNode dispatchGetAttr ;
117176 @ CompilationFinal private IsBuiltinClassProfile isBuiltinClassProfile = IsBuiltinClassProfile .create ();
118177
119178 public GetFixedAttributeNode (String key ) {
@@ -138,7 +197,7 @@ protected int doItInt(VirtualFrame frame, Object object) throws UnexpectedResult
138197 return dispatchNode .executeInt (frame , object , key );
139198 } catch (PException pe ) {
140199 pe .expect (AttributeError , isBuiltinClassProfile );
141- return getDispatchGetAttr (). executeInt ( frame , object , key );
200+ return dispatchGetAttrOrRethrowInt ( frame , object , key , pe );
142201 }
143202 }
144203
@@ -148,7 +207,7 @@ protected long doItLong(VirtualFrame frame, Object object) throws UnexpectedResu
148207 return dispatchNode .executeLong (frame , object , key );
149208 } catch (PException pe ) {
150209 pe .expect (AttributeError , isBuiltinClassProfile );
151- return getDispatchGetAttr (). executeInt ( frame , object , key );
210+ return dispatchGetAttrOrRethrowLong ( frame , object , key , pe );
152211 }
153212 }
154213
@@ -158,7 +217,7 @@ protected boolean doItBoolean(VirtualFrame frame, Object object) throws Unexpect
158217 return dispatchNode .executeBool (frame , object , key );
159218 } catch (PException pe ) {
160219 pe .expect (AttributeError , isBuiltinClassProfile );
161- return getDispatchGetAttr (). executeBool ( frame , object , key );
220+ return dispatchGetAttrOrRethrowBool ( frame , object , key , pe );
162221 }
163222 }
164223
@@ -168,27 +227,18 @@ protected Object doIt(VirtualFrame frame, Object object) {
168227 return dispatchNode .executeObject (frame , object , key );
169228 } catch (PException pe ) {
170229 pe .expect (AttributeError , isBuiltinClassProfile );
171- return getDispatchGetAttr (). executeObject ( frame , object , key );
230+ return dispatchGetAttrOrRethrowObject ( frame , object , key , pe );
172231 }
173232 }
174233
175- private LookupAndCallBinaryNode getDispatchGetAttr () {
176- if (dispatchGetAttr == null ) {
177- CompilerDirectives .transferToInterpreterAndInvalidate ();
178- dispatchGetAttr = insert (LookupAndCallBinaryNode .create (__GETATTR__ ));
179- }
180- return dispatchGetAttr ;
181- }
182-
183234 public static GetFixedAttributeNode create (String key ) {
184235 return GetFixedAttributeNodeGen .create (key );
185236 }
186237 }
187238
188- public abstract static class GetAnyAttributeNode extends Node {
239+ public abstract static class GetAnyAttributeNode extends GetAttributeBaseNode {
189240
190241 @ Child private LookupAndCallBinaryNode dispatchNode = LookupAndCallBinaryNode .create (__GETATTRIBUTE__ );
191- @ Child private LookupAndCallBinaryNode dispatchGetAttr ;
192242 @ CompilationFinal private IsBuiltinClassProfile isBuiltinClassProfile = IsBuiltinClassProfile .create ();
193243
194244 public abstract int executeInt (VirtualFrame frame , Object object , Object key ) throws UnexpectedResultException ;
@@ -205,7 +255,7 @@ protected int doItInt(VirtualFrame frame, Object object, String key) throws Unex
205255 return dispatchNode .executeInt (frame , object , key );
206256 } catch (PException pe ) {
207257 pe .expect (AttributeError , isBuiltinClassProfile );
208- return getDispatchGetAttr (). executeInt ( frame , object , key );
258+ return dispatchGetAttrOrRethrowInt ( frame , object , key , pe );
209259 }
210260 }
211261
@@ -215,7 +265,7 @@ protected long doItLong(VirtualFrame frame, Object object, Object key) throws Un
215265 return dispatchNode .executeLong (frame , object , key );
216266 } catch (PException pe ) {
217267 pe .expect (AttributeError , isBuiltinClassProfile );
218- return getDispatchGetAttr (). executeInt ( frame , object , key );
268+ return dispatchGetAttrOrRethrowLong ( frame , object , key , pe );
219269 }
220270 }
221271
@@ -225,7 +275,7 @@ protected boolean doItBoolean(VirtualFrame frame, Object object, Object key) thr
225275 return dispatchNode .executeBool (frame , object , key );
226276 } catch (PException pe ) {
227277 pe .expect (AttributeError , isBuiltinClassProfile );
228- return getDispatchGetAttr (). executeBool ( frame , object , key );
278+ return dispatchGetAttrOrRethrowBool ( frame , object , key , pe );
229279 }
230280 }
231281
@@ -235,16 +285,8 @@ protected Object doIt(VirtualFrame frame, Object object, Object key) {
235285 return dispatchNode .executeObject (frame , object , key );
236286 } catch (PException pe ) {
237287 pe .expect (AttributeError , isBuiltinClassProfile );
238- return getDispatchGetAttr ().executeObject (frame , object , key );
239- }
240- }
241-
242- private LookupAndCallBinaryNode getDispatchGetAttr () {
243- if (dispatchGetAttr == null ) {
244- CompilerDirectives .transferToInterpreterAndInvalidate ();
245- dispatchGetAttr = insert (LookupAndCallBinaryNode .create (__GETATTR__ ));
288+ return dispatchGetAttrOrRethrowObject (frame , object , key , pe );
246289 }
247- return dispatchGetAttr ;
248290 }
249291
250292 public static GetAnyAttributeNode create () {
0 commit comments