Skip to content

Commit a3b178c

Browse files
committed
if available, then delegate to type/-s getset descr in object.dict
1 parent b6fc315 commit a3b178c

File tree

2 files changed

+166
-54
lines changed

2 files changed

+166
-54
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/getsetdescriptor/GetSetDescriptorTypeBuiltins.java

Lines changed: 89 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,6 @@
4444
import static com.oracle.graal.python.nodes.SpecialMethodNames.__GET__;
4545
import static com.oracle.graal.python.nodes.SpecialMethodNames.__REPR__;
4646
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;
4947

5048
import java.util.List;
5149

@@ -73,6 +71,8 @@
7371
import com.oracle.graal.python.nodes.function.builtins.PythonTernaryBuiltinNode;
7472
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
7573
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;
7676
import com.oracle.truffle.api.CompilerDirectives;
7777
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
7878
import com.oracle.truffle.api.dsl.Cached;
@@ -81,6 +81,7 @@
8181
import com.oracle.truffle.api.dsl.Specialization;
8282
import com.oracle.truffle.api.frame.VirtualFrame;
8383
import com.oracle.truffle.api.library.CachedLibrary;
84+
import com.oracle.truffle.api.nodes.Node;
8485
import com.oracle.truffle.api.profiles.BranchProfile;
8586
import com.oracle.truffle.api.profiles.ConditionProfile;
8687

@@ -186,131 +187,171 @@ private PRaiseNode getRaiseNode() {
186187
@Builtin(name = __GET__, minNumOfPositionalArgs = 2, maxNumOfPositionalArgs = 3)
187188
@GenerateNodeFactory
188189
abstract static class GetSetGetNode extends PythonTernaryBuiltinNode {
189-
@Child private GetNameNode getNameNode;
190-
private final BranchProfile branchProfile = BranchProfile.create();
191-
192190
// https://github.com/python/cpython/blob/e8b19656396381407ad91473af5da8b0d4346e88/Objects/descrobject.c#L149
193191
@Specialization
194192
Object get(VirtualFrame frame, GetSetDescriptor descr, Object obj, @SuppressWarnings("unused") Object type,
195193
@Cached DescriptorCheckNode descriptorCheckNode,
196-
@Cached CallUnaryMethodNode callNode) {
194+
@Cached DescrGetNode getNode) {
197195
if (descriptorCheckNode.execute(descr.getType(), descr.getName(), obj)) {
198196
return descr;
199197
}
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) {
200219
if (descr.getGet() != null) {
201220
return callNode.executeObject(frame, descr.getGet(), obj);
202221
} else {
203222
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()));
205224
}
206225
}
207226

208227
@Specialization
209-
Object getSlot(HiddenKeyDescriptor descr, Object obj, @SuppressWarnings("unused") Object type,
210-
@Cached DescriptorCheckNode descriptorCheckNode,
228+
Object getSlot(HiddenKeyDescriptor descr, Object obj,
211229
@Cached ReadAttributeFromObjectNode readNode,
212230
@Cached ConditionProfile profile) {
213-
if (descriptorCheckNode.execute(descr.getType(), descr.getKey().getName(), obj)) {
214-
return descr;
215-
}
216231
Object val = readNode.execute(obj, descr.getKey());
217232
if (profile.profile(val != PNone.NO_VALUE)) {
218233
return val;
219234
}
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());
229236
}
230237
}
231238

232239
@Builtin(name = __SET__, minNumOfPositionalArgs = 3)
233240
@GenerateNodeFactory
234241
abstract static class GetSetSetNode extends PythonTernaryBuiltinNode {
235-
@Child private GetNameNode getNameNode;
236-
private final BranchProfile branchProfile = BranchProfile.create();
237-
238242
@Specialization
239243
Object set(VirtualFrame frame, GetSetDescriptor descr, Object obj, Object value,
240244
@Cached DescriptorCheckNode descriptorCheckNode,
241-
@Cached CallBinaryMethodNode callNode) {
245+
@Cached DescrSetNode setNode) {
242246
if (descriptorCheckNode.execute(descr.getType(), descr.getName(), obj)) {
243247
return descr;
244248
}
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) {
245270
if (descr.getSet() != null) {
246271
return callNode.executeObject(frame, descr.getSet(), obj, value);
247272
} else {
248273
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()));
250275
}
251276
}
252277

253278
@Specialization
254279
Object setSlot(HiddenKeyDescriptor descr, Object obj, Object value,
255-
@Cached DescriptorCheckNode descriptorCheckNode,
256280
@Cached WriteAttributeToObjectNode writeNode) {
257-
if (descriptorCheckNode.execute(descr.getType(), descr.getKey().getName(), obj)) {
258-
return descr;
259-
}
260281
return writeNode.execute(obj, descr.getKey(), value);
261282
}
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-
}
270283
}
271284

272285
@Builtin(name = __DELETE__, minNumOfPositionalArgs = 2)
273286
@GenerateNodeFactory
274287
abstract static class GetSetDeleteNode extends PythonBinaryBuiltinNode {
275-
@Child private GetNameNode getNameNode;
276-
private final BranchProfile branchProfile = BranchProfile.create();
277288

278289
@Specialization
279290
Object delete(VirtualFrame frame, GetSetDescriptor descr, Object obj,
280291
@Cached DescriptorCheckNode descriptorCheckNode,
281-
@Cached CallBinaryMethodNode callNode) {
292+
@Cached DescrDeleteNode deleteNode) {
282293
if (descriptorCheckNode.execute(descr.getType(), descr.getName(), obj)) {
283294
return descr;
284295
}
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) {
285317
if (descr.allowsDelete()) {
286318
return callNode.executeObject(frame, descr.getSet(), obj, DescriptorDeleteMarker.INSTANCE);
287319
} else {
288320
branchProfile.enter();
289321
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());
291323
} else {
292-
throw raise(AttributeError, ErrorMessages.READONLY_ATTRIBUTE);
324+
throw getRaiseNode().raise(AttributeError, ErrorMessages.READONLY_ATTRIBUTE);
293325
}
294326
}
295327
}
296328

297329
@Specialization
298330
Object deleteSlot(HiddenKeyDescriptor descr, Object obj,
299-
@Cached DescriptorCheckNode descriptorCheckNode,
300331
@Cached WriteAttributeToObjectNode writeNode) {
301-
if (descriptorCheckNode.execute(descr.getType(), descr.getKey().getName(), obj)) {
302-
return descr;
303-
}
304332
writeNode.execute(obj, descr.getKey(), PNone.NO_VALUE);
305333
return PNone.NONE;
306334
}
335+
}
307336

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) {
309342
if (getNameNode == null) {
310343
CompilerDirectives.transferToInterpreterAndInvalidate();
311344
getNameNode = insert(GetNameNode.create());
312345
}
313346
return getNameNode.execute(descrType);
314347
}
348+
349+
protected PRaiseNode getRaiseNode() {
350+
if (raiseNode == null) {
351+
CompilerDirectives.transferToInterpreterAndInvalidate();
352+
raiseNode = insert(PRaiseNode.create());
353+
}
354+
return raiseNode;
355+
}
315356
}
316357
}

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

Lines changed: 77 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,14 @@
6969
import com.oracle.graal.python.builtins.objects.function.PBuiltinFunction;
7070
import com.oracle.graal.python.builtins.objects.function.PKeyword;
7171
import com.oracle.graal.python.builtins.objects.object.ObjectBuiltinsClinicProviders.FormatNodeClinicProviderGen;
72+
import com.oracle.graal.python.builtins.objects.getsetdescriptor.DescriptorDeleteMarker;
73+
import com.oracle.graal.python.builtins.objects.getsetdescriptor.GetSetDescriptorTypeBuiltins.DescrDeleteNode;
74+
import com.oracle.graal.python.builtins.objects.getsetdescriptor.GetSetDescriptorTypeBuiltins.DescrGetNode;
75+
import com.oracle.graal.python.builtins.objects.getsetdescriptor.GetSetDescriptorTypeBuiltins.DescrSetNode;
7276
import com.oracle.graal.python.builtins.objects.object.ObjectBuiltinsFactory.GetAttributeNodeFactory;
7377
import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass;
7478
import com.oracle.graal.python.builtins.objects.type.TypeNodes.CheckCompatibleForAssigmentNode;
79+
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetBaseClassNode;
7580
import com.oracle.graal.python.builtins.objects.type.TypeNodesFactory.CheckCompatibleForAssigmentNodeGen;
7681
import com.oracle.graal.python.nodes.BuiltinNames;
7782
import com.oracle.graal.python.nodes.ErrorMessages;
@@ -582,10 +587,22 @@ protected boolean isBuiltinObjectExact(PythonObject self) {
582587
return exactBuiltinInstanceProfile.profileIsOtherBuiltinObject(self, PythonBuiltinClassType.PythonModule);
583588
}
584589

585-
@Specialization(guards = {"!isBuiltinObjectExact(self)", "!isClass(self, iLib)", "!isExactObjectInstance(self)", "isNoValue(none)"})
586-
Object dict(PythonObject self, @SuppressWarnings("unused") PNone none,
590+
@Specialization(guards = {"!isBuiltinObjectExact(self)", "!isExactObjectInstance(self)", "isNoValue(none)"})
591+
Object dict(VirtualFrame frame, PythonObject self, @SuppressWarnings("unused") PNone none,
592+
@Cached GetClassNode getClassNode,
593+
@Cached GetBaseClassNode getBaseNode,
594+
@Cached("createForLookupOfUnmanagedClasses(__DICT__)") LookupAttributeInMRONode getDescrNode,
595+
@Cached DescrGetNode getNode,
587596
@CachedLibrary(limit = "3") PythonObjectLibrary lib,
588-
@SuppressWarnings("unused") @CachedLibrary(limit = "3") InteropLibrary iLib) {
597+
@SuppressWarnings("unused") @CachedLibrary(limit = "3") InteropLibrary iLib,
598+
@Cached BranchProfile branchProfile) {
599+
// typeobject.c#subtype_getdict()
600+
Object func = getDescrFromBuiltinBase(getClassNode.execute(self), getBaseNode, getDescrNode);
601+
if (func != null) {
602+
branchProfile.enter();
603+
return getNode.execute(frame, func, self);
604+
}
605+
589606
PDict dict = lib.getDict(self);
590607
if (dict == null) {
591608
dict = factory().createDictFixedStorage(self);
@@ -599,10 +616,22 @@ Object dict(PythonObject self, @SuppressWarnings("unused") PNone none,
599616
return dict;
600617
}
601618

602-
@Specialization(guards = {"!isBuiltinObjectExact(self)", "!isClass(self, iLib)", "!isExactObjectInstance(self)"})
603-
Object dict(PythonObject self, PDict dict,
619+
@Specialization(guards = {"!isBuiltinObjectExact(self)", "!isExactObjectInstance(self)", "!isPythonModule(self)"})
620+
Object dict(VirtualFrame frame, PythonObject self, PDict dict,
621+
@Cached GetClassNode getClassNode,
622+
@Cached GetBaseClassNode getBaseNode,
623+
@Cached("createForLookupOfUnmanagedClasses(__DICT__)") LookupAttributeInMRONode getDescrNode,
624+
@Cached DescrSetNode setNode,
604625
@CachedLibrary(limit = "3") PythonObjectLibrary lib,
605-
@SuppressWarnings("unused") @CachedLibrary(limit = "3") InteropLibrary iLib) {
626+
@SuppressWarnings("unused") @CachedLibrary(limit = "3") InteropLibrary iLib,
627+
@Cached BranchProfile branchProfile) {
628+
// typeobject.c#subtype_setdict()
629+
Object func = getDescrFromBuiltinBase(getClassNode.execute(self), getBaseNode, getDescrNode);
630+
if (func != null) {
631+
branchProfile.enter();
632+
return setNode.execute(frame, func, self, dict);
633+
}
634+
606635
try {
607636
lib.setDict(self, dict);
608637
} catch (UnsupportedMessageException e) {
@@ -622,6 +651,48 @@ Object dict(PythonAbstractNativeObject self, @SuppressWarnings("unused") PNone n
622651
return dict;
623652
}
624653

654+
@Specialization(limit = "1")
655+
Object dict(VirtualFrame frame, @SuppressWarnings("unused") PythonObject self, @SuppressWarnings("unused") DescriptorDeleteMarker marker,
656+
@Cached GetClassNode getClassNode,
657+
@Cached GetBaseClassNode getBaseNode,
658+
@Cached("createForLookupOfUnmanagedClasses(__DICT__)") LookupAttributeInMRONode getDescrNode,
659+
@Cached DescrDeleteNode deleteNode,
660+
@CachedLibrary("self") PythonObjectLibrary lib,
661+
@Cached BranchProfile branchProfile) {
662+
// typeobject.c#subtype_setdict()
663+
Object func = getDescrFromBuiltinBase(getClassNode.execute(self), getBaseNode, getDescrNode);
664+
if (func != null) {
665+
branchProfile.enter();
666+
return deleteNode.execute(frame, func, self);
667+
}
668+
try {
669+
lib.deleteDict(self);
670+
} catch (UnsupportedMessageException e) {
671+
CompilerDirectives.transferToInterpreterAndInvalidate();
672+
throw new IllegalStateException(e);
673+
}
674+
return PNone.NONE;
675+
}
676+
677+
/**
678+
* see typeobject.c#get_builtin_base_with_dict()
679+
*/
680+
private static Object getDescrFromBuiltinBase(Object type, GetBaseClassNode getBaseNode, LookupAttributeInMRONode getDescrNode) {
681+
Object t = type;
682+
Object base = getBaseNode.execute(t);
683+
while (base != null) {
684+
if (t instanceof PythonBuiltinClass) {
685+
Object func = getDescrNode.execute(t);
686+
if (func != PNone.NO_VALUE) {
687+
return func;
688+
}
689+
}
690+
t = base;
691+
base = getBaseNode.execute(t);
692+
}
693+
return null;
694+
}
695+
625696
@Specialization(guards = {"!isNoValue(mapping)", "!isDict(mapping)"})
626697
Object dict(@SuppressWarnings("unused") Object self, Object mapping) {
627698
throw raise(TypeError, ErrorMessages.DICT_MUST_BE_SET_TO_DICT, mapping);

0 commit comments

Comments
 (0)