Skip to content

Commit f54f676

Browse files
committed
replace DictNode builtin with a DictNode getset descr
1 parent c79d250 commit f54f676

File tree

8 files changed

+146
-62
lines changed

8 files changed

+146
-62
lines changed

graalpython/com.oracle.graal.python.test/src/tests/test_type.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,3 +252,48 @@ class MyDict(dict):
252252
(MyDict({"1":1, "2": 2}), TPFLAGS_DICT_SUBCLASS),
253253
]:
254254
assert type(x).__flags__ & flag, "masked __flags__ = {}, expected {}".format(type(x).__flags__ & flag, flag)
255+
256+
def test_dict():
257+
def dict_element_raises(o, err):
258+
raised = False
259+
try:
260+
o['__dict__']
261+
except err:
262+
raised = True
263+
assert raised
264+
265+
class Base:
266+
pass
267+
268+
class Sub(Base):
269+
pass
270+
271+
str(type(Base.__dict__['__dict__'])) == "<class 'get_set_desc'>"
272+
dict_element_raises(Sub.__dict__, KeyError)
273+
Base().__dict__ == {}
274+
Sub().__dict__ == {}
275+
276+
class BaseSlots:
277+
__slots__ = ['a']
278+
279+
dict_element_raises(BaseSlots.__dict__, KeyError)
280+
raised = False
281+
try:
282+
BaseSlots().__dict__
283+
except AttributeError:
284+
raised = True
285+
assert raised
286+
287+
class SubSlots(BaseSlots):
288+
pass
289+
290+
str(type(SubSlots.__dict__['__dict__'])) == "<class 'get_set_desc'>"
291+
assert SubSlots().__dict__ == {}
292+
293+
class SubSlots(BaseSlots, Base):
294+
pass
295+
296+
str(type(SubSlots.__dict__['__dict__'])) == "<class 'get_set_desc'>"
297+
assert SubSlots().__dict__ == {}
298+
299+

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

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@
138138
import com.oracle.graal.python.builtins.objects.function.PBuiltinFunction;
139139
import com.oracle.graal.python.builtins.objects.function.PFunction;
140140
import com.oracle.graal.python.builtins.objects.function.PKeyword;
141+
import com.oracle.graal.python.builtins.objects.getsetdescriptor.GetSetDescriptor;
141142
import com.oracle.graal.python.builtins.objects.getsetdescriptor.HiddenKeyDescriptor;
142143
import com.oracle.graal.python.builtins.objects.getsetdescriptor.HiddenPythonKey;
143144
import com.oracle.graal.python.builtins.objects.ints.PInt;
@@ -149,6 +150,7 @@
149150
import com.oracle.graal.python.builtins.objects.module.PythonModule;
150151
import com.oracle.graal.python.builtins.objects.object.ObjectBuiltins;
151152
import com.oracle.graal.python.builtins.objects.object.ObjectBuiltinsFactory;
153+
import com.oracle.graal.python.builtins.objects.object.ObjectBuiltinsFactory.DictNodeGen;
152154
import com.oracle.graal.python.builtins.objects.object.PythonObject;
153155
import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary;
154156
import com.oracle.graal.python.builtins.objects.range.PBigRange;
@@ -191,6 +193,8 @@
191193
import com.oracle.graal.python.nodes.classes.IsSubtypeNode;
192194
import com.oracle.graal.python.nodes.expression.CastToListExpressionNode.CastToListNode;
193195
import com.oracle.graal.python.nodes.frame.ReadCallerFrameNode;
196+
import com.oracle.graal.python.nodes.function.BuiltinFunctionRootNode;
197+
import com.oracle.graal.python.nodes.function.BuiltinFunctionRootNode.StandaloneBuiltinFactory;
194198
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
195199
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
196200
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
@@ -220,6 +224,7 @@
220224
import com.oracle.truffle.api.CompilerDirectives;
221225
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
222226
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
227+
import com.oracle.truffle.api.RootCallTarget;
223228
import com.oracle.truffle.api.Truffle;
224229
import com.oracle.truffle.api.dsl.Cached;
225230
import com.oracle.truffle.api.dsl.Cached.Shared;
@@ -2080,7 +2085,8 @@ Object typeNew(VirtualFrame frame, Object cls, Object wName, PTuple bases, PDict
20802085
@Cached CallNode callSetNameNode,
20812086
@Cached CallNode callInitSubclassNode,
20822087
@Cached CallNode callNewFuncNode,
2083-
@Cached GetBestBaseClassNode getBestBaseNode) {
2088+
@Cached GetBestBaseClassNode getBestBaseNode,
2089+
@Cached("create(__DICT__)") LookupAttributeInMRONode getDictAttrNode) {
20842090
// Determine the proper metatype to deal with this
20852091
String name = castStr.execute(wName);
20862092
Object metaclass = calculate_metaclass(frame, cls, bases, lib);
@@ -2095,7 +2101,7 @@ Object typeNew(VirtualFrame frame, Object cls, Object wName, PTuple bases, PDict
20952101
}
20962102

20972103
try {
2098-
PythonClass newType = typeMetaclass(frame, name, bases, namespace, metaclass, nslib, getBestBaseNode);
2104+
PythonClass newType = typeMetaclass(frame, name, bases, namespace, metaclass, nslib, getDictAttrNode, getBestBaseNode);
20992105

21002106
for (DictEntry entry : nslib.entries(namespace.getDictStorage())) {
21012107
Object setName = getSetNameNode.execute(entry.value);
@@ -2180,7 +2186,7 @@ private String getModuleNameFromGlobals(PythonObject globals, HashingStorageLibr
21802186
}
21812187
}
21822188

2183-
private PythonClass typeMetaclass(VirtualFrame frame, String name, PTuple bases, PDict namespace, Object metaclass, HashingStorageLibrary nslib,
2189+
private PythonClass typeMetaclass(VirtualFrame frame, String name, PTuple bases, PDict namespace, Object metaclass, HashingStorageLibrary nslib, LookupAttributeInMRONode getDictAttrNode,
21842190
GetBestBaseClassNode getBestBaseNode) {
21852191
Object[] array = ensureGetObjectArrayNode().execute(bases);
21862192

@@ -2237,6 +2243,7 @@ private PythonClass typeMetaclass(VirtualFrame frame, String name, PTuple bases,
22372243
if (slots[0] == null) {
22382244
// takes care of checking if we may_add_dict and adds it if needed
22392245
addDictIfNative(frame, pythonClass);
2246+
addDictDescrAttribute(basesArray, getDictAttrNode, pythonClass);
22402247
// TODO: tfel - also deal with weaklistoffset
22412248
} else {
22422249
// have slots
@@ -2276,6 +2283,7 @@ private PythonClass typeMetaclass(VirtualFrame frame, String name, PTuple bases,
22762283
throw raise(TypeError, ErrorMessages.SLOT_DISALLOWED_WE_GOT_ONE, "__dict__");
22772284
}
22782285
addDict = true;
2286+
addDictDescrAttribute(basesArray, getDictAttrNode, pythonClass);
22792287
} else {
22802288
// TODO: check for __weakref__
22812289
// TODO avoid if native slots are inherited
@@ -2309,6 +2317,41 @@ private PythonClass typeMetaclass(VirtualFrame frame, String name, PTuple bases,
23092317
return pythonClass;
23102318
}
23112319

2320+
private void addDictDescrAttribute(PythonAbstractClass[] basesArray, LookupAttributeInMRONode getDictAttrNode, PythonClass pythonClass) {
2321+
if ((!hasPythonClassBases(basesArray) && getDictAttrNode.execute(pythonClass) == PNone.NO_VALUE) || basesHaveSlots(basesArray)) {
2322+
CompilerDirectives.transferToInterpreterAndInvalidate();
2323+
Builtin dictBuiltin = ObjectBuiltins.DictNode.class.getAnnotation(Builtin.class);
2324+
BuiltinFunctionRootNode rootNode = new BuiltinFunctionRootNode(getCore().getLanguage(), dictBuiltin, new StandaloneBuiltinFactory<PythonBinaryBuiltinNode>(DictNodeGen.create()), true);
2325+
RootCallTarget callTarget = PythonUtils.getOrCreateCallTarget(rootNode);
2326+
PBuiltinFunction function = getCore().factory().createBuiltinFunction(__DICT__, pythonClass, 1, callTarget);
2327+
GetSetDescriptor desc = factory().createGetSetDescriptor(function, function, __DICT__, pythonClass, true);
2328+
pythonClass.setAttribute(__DICT__, desc);
2329+
}
2330+
}
2331+
2332+
private static boolean basesHaveSlots(PythonAbstractClass[] basesArray) {
2333+
// this is merely based on empirical observation
2334+
// see also test_type.py#test_dict()
2335+
for (PythonAbstractClass c : basesArray) {
2336+
// TODO: what about native?
2337+
if (c instanceof PythonClass) {
2338+
if (((PythonClass) c).getAttribute(__SLOTS__) != PNone.NO_VALUE) {
2339+
return true;
2340+
}
2341+
}
2342+
}
2343+
return false;
2344+
}
2345+
2346+
private static boolean hasPythonClassBases(PythonAbstractClass[] basesArray) {
2347+
for (PythonAbstractClass c : basesArray) {
2348+
if (c instanceof PythonClass) {
2349+
return true;
2350+
}
2351+
}
2352+
return false;
2353+
}
2354+
23122355
private void copyDictSlots(PythonClass pythonClass, PDict namespace, HashingStorageLibrary nslib, Object[] slots, boolean[] qualnameSet) {
23132356
// copy the dictionary slots over, as CPython does through PyDict_Copy
23142357
// Also check for a __slots__ sequence variable in dict

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,6 @@
115115
import com.oracle.graal.python.builtins.objects.cext.CExtNodes.GetNativeNullNode;
116116
import com.oracle.graal.python.builtins.objects.cext.CExtNodes.MayRaiseBinaryNode;
117117
import com.oracle.graal.python.builtins.objects.cext.CExtNodes.MayRaiseNode;
118-
import com.oracle.graal.python.builtins.objects.cext.CExtNodes.MayRaiseNodeFactory;
119118
import com.oracle.graal.python.builtins.objects.cext.CExtNodes.MayRaiseTernaryNode;
120119
import com.oracle.graal.python.builtins.objects.cext.CExtNodes.MayRaiseUnaryNode;
121120
import com.oracle.graal.python.builtins.objects.cext.CExtNodes.ObjectUpcallNode;
@@ -221,6 +220,7 @@
221220
import com.oracle.graal.python.nodes.expression.BinaryComparisonNode;
222221
import com.oracle.graal.python.nodes.frame.GetCurrentFrameRef;
223222
import com.oracle.graal.python.nodes.function.BuiltinFunctionRootNode;
223+
import com.oracle.graal.python.nodes.function.BuiltinFunctionRootNode.StandaloneBuiltinFactory;
224224
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
225225
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
226226
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
@@ -2325,17 +2325,17 @@ Object make(PFunction func, Object errorResult,
23252325
switch (funcSignature.getMaxNumOfPositionalArgs()) {
23262326
case 1:
23272327
rootNode = new BuiltinFunctionRootNode(lang, unaryBuiltin,
2328-
new MayRaiseNodeFactory<PythonUnaryBuiltinNode>(MayRaiseUnaryNodeGen.create(func, errorResult)),
2328+
new StandaloneBuiltinFactory<PythonUnaryBuiltinNode>(MayRaiseUnaryNodeGen.create(func, errorResult)),
23292329
true);
23302330
break;
23312331
case 2:
23322332
rootNode = new BuiltinFunctionRootNode(lang, binaryBuiltin,
2333-
new MayRaiseNodeFactory<PythonBinaryBuiltinNode>(MayRaiseBinaryNodeGen.create(func, errorResult)),
2333+
new StandaloneBuiltinFactory<PythonBinaryBuiltinNode>(MayRaiseBinaryNodeGen.create(func, errorResult)),
23342334
true);
23352335
break;
23362336
case 3:
23372337
rootNode = new BuiltinFunctionRootNode(lang, ternaryBuiltin,
2338-
new MayRaiseNodeFactory<PythonTernaryBuiltinNode>(MayRaiseTernaryNodeGen.create(func, errorResult)),
2338+
new StandaloneBuiltinFactory<PythonTernaryBuiltinNode>(MayRaiseTernaryNodeGen.create(func, errorResult)),
23392339
true);
23402340
break;
23412341
default:
@@ -2344,7 +2344,7 @@ Object make(PFunction func, Object errorResult,
23442344
}
23452345
if (rootNode == null) {
23462346
rootNode = new BuiltinFunctionRootNode(lang, varargsBuiltin,
2347-
new MayRaiseNodeFactory<PythonBuiltinNode>(new MayRaiseNode(func, errorResult)),
2347+
new StandaloneBuiltinFactory<PythonBuiltinNode>(new MayRaiseNode(func, errorResult)),
23482348
true);
23492349
}
23502350

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/CExtNodes.java

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,6 @@
5050
import static com.oracle.graal.python.nodes.SpecialMethodNames.__FLOAT__;
5151
import static com.oracle.graal.python.runtime.exception.PythonErrorType.TypeError;
5252

53-
import java.util.List;
54-
5553
import com.oracle.graal.python.PythonLanguage;
5654
import com.oracle.graal.python.builtins.Builtin;
5755
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
@@ -118,7 +116,6 @@
118116
import com.oracle.graal.python.nodes.call.special.LookupAndCallUnaryNode.LookupAndCallUnaryDynamicNode;
119117
import com.oracle.graal.python.nodes.classes.IsSubtypeNode;
120118
import com.oracle.graal.python.nodes.frame.GetCurrentFrameRef;
121-
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
122119
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
123120
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
124121
import com.oracle.graal.python.nodes.function.builtins.PythonTernaryBuiltinNode;
@@ -147,9 +144,7 @@
147144
import com.oracle.truffle.api.dsl.Cached.Shared;
148145
import com.oracle.truffle.api.dsl.CachedContext;
149146
import com.oracle.truffle.api.dsl.GenerateUncached;
150-
import com.oracle.truffle.api.dsl.GeneratedBy;
151147
import com.oracle.truffle.api.dsl.ImportStatic;
152-
import com.oracle.truffle.api.dsl.NodeFactory;
153148
import com.oracle.truffle.api.dsl.ReportPolymorphism;
154149
import com.oracle.truffle.api.dsl.Specialization;
155150
import com.oracle.truffle.api.dsl.TypeSystemReference;
@@ -165,7 +160,6 @@
165160
import com.oracle.truffle.api.nodes.ExplodeLoop;
166161
import com.oracle.truffle.api.nodes.InvalidAssumptionException;
167162
import com.oracle.truffle.api.nodes.Node;
168-
import com.oracle.truffle.api.nodes.NodeUtil;
169163
import com.oracle.truffle.api.profiles.BranchProfile;
170164
import com.oracle.truffle.api.profiles.ConditionProfile;
171165

@@ -2533,49 +2527,6 @@ public static PCallCapiFunction getUncached() {
25332527
}
25342528
}
25352529

2536-
// -----------------------------------------------------------------------------------------------------------------
2537-
public static class MayRaiseNodeFactory<T extends PythonBuiltinBaseNode> implements NodeFactory<T> {
2538-
private final T node;
2539-
private final Class<T> nodeClass;
2540-
2541-
public MayRaiseNodeFactory(T node) {
2542-
this.node = node;
2543-
this.nodeClass = determineNodeClass(node);
2544-
}
2545-
2546-
@Override
2547-
public T createNode(Object... arguments) {
2548-
return NodeUtil.cloneNode(node);
2549-
}
2550-
2551-
@Override
2552-
public Class<T> getNodeClass() {
2553-
return nodeClass;
2554-
}
2555-
2556-
@SuppressWarnings("unchecked")
2557-
private static <T> Class<T> determineNodeClass(T node) {
2558-
CompilerAsserts.neverPartOfCompilation();
2559-
Class<T> nodeClass = (Class<T>) node.getClass();
2560-
GeneratedBy genBy = nodeClass.getAnnotation(GeneratedBy.class);
2561-
if (genBy != null) {
2562-
nodeClass = (Class<T>) genBy.value();
2563-
assert nodeClass.isAssignableFrom(node.getClass());
2564-
}
2565-
return nodeClass;
2566-
}
2567-
2568-
@Override
2569-
public List<List<Class<?>>> getNodeSignatures() {
2570-
throw new IllegalAccessError();
2571-
}
2572-
2573-
@Override
2574-
public List<Class<? extends Node>> getExecutionSignature() {
2575-
throw new IllegalAccessError();
2576-
}
2577-
}
2578-
25792530
// -----------------------------------------------------------------------------------------------------------------
25802531
@Builtin(minNumOfPositionalArgs = 1)
25812532
public abstract static class MayRaiseUnaryNode extends PythonUnaryBuiltinNode {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/FrameBuiltins.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
import com.oracle.graal.python.builtins.objects.function.PArguments;
4141
import com.oracle.graal.python.builtins.objects.module.PythonModule;
4242
import com.oracle.graal.python.builtins.objects.object.ObjectBuiltins.DictNode;
43-
import com.oracle.graal.python.builtins.objects.object.ObjectBuiltinsFactory.DictNodeFactory;
43+
import com.oracle.graal.python.builtins.objects.object.ObjectBuiltinsFactory;
4444
import com.oracle.graal.python.builtins.objects.object.PythonObject;
4545
import com.oracle.graal.python.nodes.PRootNode;
4646
import com.oracle.graal.python.nodes.frame.MaterializeFrameNode;
@@ -100,7 +100,7 @@ Object get(VirtualFrame curFrame, PFrame self) {
100100
if (globals instanceof PythonModule) {
101101
if (getDictNode == null) {
102102
CompilerDirectives.transferToInterpreterAndInvalidate();
103-
getDictNode = insert(DictNodeFactory.create());
103+
getDictNode = insert(ObjectBuiltinsFactory.DictNodeGen.create());
104104
}
105105
return getDictNode.call(curFrame, globals, PNone.NO_VALUE);
106106
} else {
@@ -114,7 +114,7 @@ Object get(VirtualFrame curFrame, PFrame self) {
114114
@Builtin(name = "f_builtins", minNumOfPositionalArgs = 1, isGetter = true)
115115
@GenerateNodeFactory
116116
public abstract static class GetBuiltinsNode extends PythonBuiltinNode {
117-
@Child private DictNode dictNode = DictNodeFactory.create();
117+
@Child private DictNode dictNode = ObjectBuiltinsFactory.DictNodeGen.create();
118118

119119
@Specialization
120120
Object get(VirtualFrame frame, @SuppressWarnings("unused") PFrame self) {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,6 @@ protected PNone doIt(VirtualFrame frame, Object object, Object keyObj,
569569
}
570570

571571
@Builtin(name = __DICT__, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true)
572-
@GenerateNodeFactory
573572
public abstract static class DictNode extends PythonBinaryBuiltinNode {
574573
@Child private IsBuiltinClassProfile exactObjInstanceProfile = IsBuiltinClassProfile.create();
575574
@Child private IsBuiltinClassProfile exactBuiltinInstanceProfile = IsBuiltinClassProfile.create();

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/special/CallSpecialMethodNode.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ private <T extends PythonBuiltinBaseNode> T getBuiltin(VirtualFrame frame, PBuil
9595
if (builtinNodeFactory == null) {
9696
return null; // see for example MethodDescriptorRoot and subclasses
9797
}
98-
assert builtinNodeFactory.getNodeClass().getAnnotationsByType(Builtin.class).length > 0;
98+
assert builtinNodeFactory.getNodeClass().getAnnotationsByType(Builtin.class).length > 0 : "PBuiltinFunction " + func + " is expected to have a Builtin annotated node.";
9999
if (builtinNodeFactory.getNodeClass().getAnnotationsByType(Builtin.class)[0].needsFrame() && frame == null) {
100100
return null;
101101
}

0 commit comments

Comments
 (0)