Skip to content

Commit 7db76ad

Browse files
committed
[GR-33179] More bytecode interpreter cleanups
PullRequest: graalpython/1964
2 parents c7e1845 + 3598680 commit 7db76ad

File tree

12 files changed

+420
-91
lines changed

12 files changed

+420
-91
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinFunctions.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@
102102
import com.oracle.graal.python.builtins.objects.bytes.PBytesLike;
103103
import com.oracle.graal.python.builtins.objects.code.CodeNodes;
104104
import com.oracle.graal.python.builtins.objects.code.PCode;
105+
import com.oracle.graal.python.builtins.objects.common.DynamicObjectStorage;
105106
import com.oracle.graal.python.builtins.objects.common.HashingCollectionNodes;
106107
import com.oracle.graal.python.builtins.objects.common.HashingStorageLibrary;
107108
import com.oracle.graal.python.builtins.objects.common.SequenceNodes.GetObjectArrayNode;
@@ -2204,7 +2205,7 @@ class InitializeBuildClass {
22042205
ns = callPrep.execute(frame, prep, new Object[]{name, init.bases}, init.mkw);
22052206
} catch (PException p) {
22062207
p.expectAttributeError(noAttributeProfile);
2207-
ns = factory.createDict();
2208+
ns = factory().createDict(new DynamicObjectStorage(PythonLanguage.get(this)));
22082209
}
22092210
if (PGuards.isNoValue(getGetItem.execute(getGetItemClass.execute(ns)))) {
22102211
if (init.isClass) {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
import java.util.List;
6363
import java.util.Set;
6464

65+
import com.oracle.graal.python.PythonLanguage;
6566
import com.oracle.graal.python.builtins.Builtin;
6667
import com.oracle.graal.python.builtins.CoreFunctions;
6768
import com.oracle.graal.python.builtins.Python3Core;
@@ -74,6 +75,7 @@
7475
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes;
7576
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes.GetTypeMemberNode;
7677
import com.oracle.graal.python.builtins.objects.cext.capi.NativeMember;
78+
import com.oracle.graal.python.builtins.objects.common.DynamicObjectStorage;
7779
import com.oracle.graal.python.builtins.objects.common.SequenceNodes.GetObjectArrayNode;
7880
import com.oracle.graal.python.builtins.objects.dict.PDict;
7981
import com.oracle.graal.python.builtins.objects.function.PBuiltinFunction;
@@ -689,7 +691,7 @@ public abstract static class PrepareNode extends PythonBuiltinNode {
689691
@SuppressWarnings("unused")
690692
@Specialization
691693
Object doIt(Object args, Object kwargs) {
692-
return factory().createDict();
694+
return factory().createDict(new DynamicObjectStorage(PythonLanguage.get(this)));
693695
}
694696
}
695697

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
package com.oracle.graal.python.lib;
42+
43+
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.TypeError;
44+
45+
import com.oracle.graal.python.builtins.objects.PNone;
46+
import com.oracle.graal.python.builtins.objects.type.SpecialMethodSlot;
47+
import com.oracle.graal.python.nodes.ErrorMessages;
48+
import com.oracle.graal.python.nodes.PRaiseNode;
49+
import com.oracle.graal.python.nodes.attributes.LookupCallableSlotInMRONode;
50+
import com.oracle.graal.python.nodes.call.special.CallBinaryMethodNode;
51+
import com.oracle.graal.python.nodes.call.special.LookupSpecialMethodSlotNode;
52+
import com.oracle.graal.python.nodes.object.GetClassNode;
53+
import com.oracle.truffle.api.dsl.Cached;
54+
import com.oracle.truffle.api.dsl.Cached.Shared;
55+
import com.oracle.truffle.api.dsl.GenerateUncached;
56+
import com.oracle.truffle.api.dsl.ImportStatic;
57+
import com.oracle.truffle.api.dsl.Specialization;
58+
import com.oracle.truffle.api.frame.Frame;
59+
import com.oracle.truffle.api.frame.VirtualFrame;
60+
import com.oracle.truffle.api.nodes.Node;
61+
62+
/**
63+
* Equivalent to use for PyObject_DelItem.
64+
*/
65+
@GenerateUncached
66+
@ImportStatic(SpecialMethodSlot.class)
67+
public abstract class PyObjectDelItem extends Node {
68+
public abstract void execute(Frame frame, Object container, Object index);
69+
70+
@Specialization
71+
static void doWithFrame(VirtualFrame frame, Object primary, Object index,
72+
@Shared("getclass") @Cached GetClassNode getClassNode,
73+
@Cached("create(DelItem)") LookupSpecialMethodSlotNode lookupDelitem,
74+
@Shared("raiseNode") @Cached PRaiseNode raise,
75+
@Shared("callNode") @Cached CallBinaryMethodNode callDelitem) {
76+
Object delitem = lookupDelitem.execute(frame, getClassNode.execute(primary), primary);
77+
if (delitem == PNone.NO_VALUE) {
78+
throw raise.raise(TypeError, ErrorMessages.OBJ_DOESNT_SUPPORT_DELETION, primary);
79+
}
80+
callDelitem.executeObject(frame, delitem, primary, index);
81+
}
82+
83+
@Specialization(replaces = "doWithFrame")
84+
static void doGeneric(Object primary, Object index,
85+
@Shared("getclass") @Cached GetClassNode getClassNode,
86+
@Cached(parameters = "DelItem") LookupCallableSlotInMRONode lookupDelitem,
87+
@Shared("raiseNode") @Cached PRaiseNode raise,
88+
@Shared("callNode") @Cached CallBinaryMethodNode callDelitem) {
89+
Object setitem = lookupDelitem.execute(getClassNode.execute(primary));
90+
if (setitem == PNone.NO_VALUE) {
91+
throw raise.raise(TypeError, ErrorMessages.OBJ_DOESNT_SUPPORT_DELETION, primary);
92+
}
93+
callDelitem.executeObject(null, setitem, primary, index);
94+
}
95+
96+
public static PyObjectDelItem create() {
97+
return PyObjectDelItemNodeGen.create();
98+
}
99+
100+
public static PyObjectDelItem getUncached() {
101+
return PyObjectDelItemNodeGen.getUncached();
102+
}
103+
}
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
/*
2+
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
package com.oracle.graal.python.lib;
42+
43+
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.TypeError;
44+
import static com.oracle.graal.python.nodes.ErrorMessages.P_HAS_NO_ATTRS_S_TO_ASSIGN;
45+
import static com.oracle.graal.python.nodes.ErrorMessages.P_HAS_NO_ATTRS_S_TO_DELETE;
46+
import static com.oracle.graal.python.nodes.ErrorMessages.P_HAS_RO_ATTRS_S_TO_ASSIGN;
47+
import static com.oracle.graal.python.nodes.ErrorMessages.P_HAS_RO_ATTRS_S_TO_DELETE;
48+
49+
import com.oracle.graal.python.builtins.objects.PNone;
50+
import com.oracle.graal.python.builtins.objects.type.SpecialMethodSlot;
51+
import com.oracle.graal.python.nodes.PRaiseNode;
52+
import com.oracle.graal.python.nodes.call.special.CallBinaryMethodNode;
53+
import com.oracle.graal.python.nodes.call.special.CallTernaryMethodNode;
54+
import com.oracle.graal.python.nodes.call.special.LookupSpecialMethodSlotNode;
55+
import com.oracle.graal.python.nodes.object.GetClassNode;
56+
import com.oracle.truffle.api.dsl.Cached.Shared;
57+
import com.oracle.truffle.api.dsl.Cached;
58+
import com.oracle.truffle.api.dsl.GenerateUncached;
59+
import com.oracle.truffle.api.dsl.ImportStatic;
60+
import com.oracle.truffle.api.dsl.Specialization;
61+
import com.oracle.truffle.api.frame.Frame;
62+
import com.oracle.truffle.api.nodes.Node;
63+
64+
/**
65+
* Equivalent PyObject_SetAttr*. Like Python, this method raises when the attribute doesn't exist.
66+
*/
67+
@GenerateUncached
68+
@ImportStatic(SpecialMethodSlot.class)
69+
public abstract class PyObjectSetAttr extends Node {
70+
public abstract void execute(Frame frame, Object receiver, Object name, Object value);
71+
72+
public final void delete(Frame frame, Object receiver, Object name) {
73+
execute(frame, receiver, name, null);
74+
}
75+
76+
@Specialization(guards = {"name == cachedName", "value != null"}, limit = "1")
77+
static void setFixedAttr(Frame frame, Object self, @SuppressWarnings("unused") String name, Object value,
78+
@SuppressWarnings("unused") @Cached("name") String cachedName,
79+
@Shared("getClass") @Cached GetClassNode getClass,
80+
@Shared("lookup") @Cached(parameters = "SetAttr") LookupSpecialMethodSlotNode lookupSetattr,
81+
@Shared("lookupGet") @Cached(parameters = "GetAttribute") LookupSpecialMethodSlotNode lookupGetattr,
82+
@Shared("raise") @Cached PRaiseNode raise,
83+
@Shared("call") @Cached CallTernaryMethodNode callSetattr) {
84+
Object type = getClass.execute(self);
85+
Object setattr = lookupSetattr.execute(frame, type, self);
86+
if (setattr == PNone.NO_VALUE) {
87+
if (lookupGetattr.execute(frame, type, self) == PNone.NO_VALUE) {
88+
throw raise.raise(TypeError, P_HAS_NO_ATTRS_S_TO_ASSIGN, self, name);
89+
} else {
90+
throw raise.raise(TypeError, P_HAS_RO_ATTRS_S_TO_ASSIGN, self, name);
91+
}
92+
}
93+
callSetattr.execute(frame, setattr, self, name, value);
94+
}
95+
96+
@Specialization(guards = {"name == cachedName", "value == null"}, limit = "1")
97+
static void delFixedAttr(Frame frame, Object self, @SuppressWarnings("unused") String name, @SuppressWarnings("unused") Object value,
98+
@SuppressWarnings("unused") @Cached("name") String cachedName,
99+
@Shared("getClass") @Cached GetClassNode getClass,
100+
@Shared("lookupDel") @Cached(parameters = "DelAttr") LookupSpecialMethodSlotNode lookupDelattr,
101+
@Shared("lookupGet") @Cached(parameters = "GetAttribute") LookupSpecialMethodSlotNode lookupGetattr,
102+
@Shared("raise") @Cached PRaiseNode raise,
103+
@Shared("callDel") @Cached CallBinaryMethodNode callDelattr) {
104+
Object type = getClass.execute(self);
105+
Object delattr = lookupDelattr.execute(frame, type, self);
106+
if (delattr == PNone.NO_VALUE) {
107+
if (lookupGetattr.execute(frame, type, self) == PNone.NO_VALUE) {
108+
throw raise.raise(TypeError, P_HAS_NO_ATTRS_S_TO_DELETE, self, name);
109+
} else {
110+
throw raise.raise(TypeError, P_HAS_RO_ATTRS_S_TO_DELETE, self, name);
111+
}
112+
}
113+
callDelattr.executeObject(frame, delattr, self, name);
114+
}
115+
116+
@Specialization(replaces = {"setFixedAttr", "delFixedAttr"})
117+
static void doDynamicAttr(Frame frame, Object self, String name, Object value,
118+
@Shared("getClass") @Cached GetClassNode getClass,
119+
@Shared("lookup") @Cached(parameters = "SetAttr") LookupSpecialMethodSlotNode lookupSetattr,
120+
@Shared("lookupDel") @Cached(parameters = "DelAttr") LookupSpecialMethodSlotNode lookupDelattr,
121+
@Shared("lookupGet") @Cached(parameters = "GetAttribute") LookupSpecialMethodSlotNode lookupGetattr,
122+
@Shared("raise") @Cached PRaiseNode raise,
123+
@Shared("call") @Cached CallTernaryMethodNode callSetattr,
124+
@Shared("callDel") @Cached CallBinaryMethodNode callDelattr) {
125+
if (value == null) {
126+
delFixedAttr(frame, self, name, value, name, getClass, lookupDelattr, lookupGetattr, raise, callDelattr);
127+
} else {
128+
setFixedAttr(frame, self, name, value, name, getClass, lookupSetattr, lookupGetattr, raise, callSetattr);
129+
}
130+
}
131+
132+
public static PyObjectSetAttr create() {
133+
return PyObjectSetAttrNodeGen.create();
134+
}
135+
136+
public static PyObjectSetAttr getUncached() {
137+
return PyObjectSetAttrNodeGen.getUncached();
138+
}
139+
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/ErrorMessages.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,10 @@ public abstract class ErrorMessages {
286286
public static final String GOT_UNEXPECTED_KEYWORD_ARG = "%s() got an unexpected keyword argument '%s'";
287287
public static final String HANDLER_MUST_BE_CALLABLE = "handler must be callable";
288288
public static final String HAS_NO_ATTR = "%s has no attribute %s";
289+
public static final String P_HAS_NO_ATTRS_S_TO_ASSIGN = "'%p' object has no attributes (assign to .%s)";
290+
public static final String P_HAS_NO_ATTRS_S_TO_DELETE = "'%p' object has no attributes (del .%s)";
291+
public static final String P_HAS_RO_ATTRS_S_TO_ASSIGN = "'%p' object has only read-only attributes (assign to .%s)";
292+
public static final String P_HAS_RO_ATTRS_S_TO_DELETE = "'%p' object has only read-only attributes (del .%s)";
289293
public static final String HASH_SHOULD_RETURN_INTEGER = "__hash__ method should return an integer";
290294
public static final String HEX_VALUE_TOO_LARGE_AS_FLOAT = "hexadecimal value too large to represent as a float";
291295
public static final String HOST_ACCESS_NOT_ALLOWED = "host access is not allowed";

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PGuards.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
9191
import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass;
9292
import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass;
93+
import com.oracle.graal.python.builtins.objects.type.PythonClass;
9394
import com.oracle.graal.python.builtins.objects.type.PythonManagedClass;
9495
import com.oracle.graal.python.nodes.object.GetClassNode;
9596
import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile;
@@ -310,7 +311,7 @@ public static boolean isIndexNegative(long idx) {
310311
}
311312

312313
public static boolean isPythonUserClass(Object klass) {
313-
return !isPythonBuiltinClass(klass);
314+
return klass instanceof PythonClass || PythonNativeClass.isInstance(klass);
314315
}
315316

316317
public static boolean isPythonBuiltinClassType(Object klass) {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/CallNode.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,25 @@ protected Object builtinFunctionCall(VirtualFrame frame, PBuiltinFunction callab
121121
return dispatch.executeCall(frame, callable, createArgs.execute(callable, arguments, keywords));
122122
}
123123

124-
@Specialization(guards = "!isCallable(callableObject)")
124+
@Specialization
125+
protected Object doType(VirtualFrame frame, PythonBuiltinClassType callableObject, Object[] arguments, PKeyword[] keywords,
126+
@Shared("raise") @Cached PRaiseNode raise,
127+
@Shared("lookupCall") @Cached("create(__CALL__)") LookupInheritedAttributeNode callAttrGetterNode,
128+
@Shared("callCall") @Cached CallVarargsMethodNode callCallNode) {
129+
Object call = callAttrGetterNode.execute(callableObject);
130+
return callCall(frame, callableObject, arguments, keywords, raise, callCallNode, call);
131+
}
132+
133+
@Specialization(guards = "isPythonClass(callableObject)", replaces = "doType")
134+
protected Object doPythonClass(VirtualFrame frame, Object callableObject, Object[] arguments, PKeyword[] keywords,
135+
@Shared("raise") @Cached PRaiseNode raise,
136+
@Shared("lookupCall") @Cached("create(__CALL__)") LookupInheritedAttributeNode callAttrGetterNode,
137+
@Shared("callCall") @Cached CallVarargsMethodNode callCallNode) {
138+
Object call = callAttrGetterNode.execute(callableObject);
139+
return callCall(frame, callableObject, arguments, keywords, raise, callCallNode, call);
140+
}
141+
142+
@Specialization(guards = "!isCallable(callableObject)", replaces = {"doType", "doPythonClass"})
125143
protected Object doObjectAndType(VirtualFrame frame, Object callableObject, Object[] arguments, PKeyword[] keywords,
126144
@Shared("raise") @Cached PRaiseNode raise,
127145
@Shared("lookupCall") @Cached("create(__CALL__)") LookupInheritedAttributeNode callAttrGetterNode,

0 commit comments

Comments
 (0)