Skip to content

Commit de82377

Browse files
committed
support reading native __dict__ from dictoffset
1 parent cfd8054 commit de82377

File tree

8 files changed

+55
-7
lines changed

8 files changed

+55
-7
lines changed

graalpython/com.oracle.graal.python.cext/src/typeobject.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ int PyType_Ready(PyTypeObject* cls) {
232232
PyDict_SetItemString(native_members, "tp_name", polyglot_from_string(cls->tp_name, SRC_CS));
233233
PyDict_SetItemString(native_members, "tp_doc", polyglot_from_string(cls->tp_doc ? cls->tp_doc : "", SRC_CS));
234234
PyDict_SetItemString(native_members, "tp_basicsize", PyLong_FromSsize_t(cls->tp_basicsize));
235+
PyDict_SetItemString(native_members, "tp_dictoffset", PyLong_FromSsize_t(cls->tp_dictoffset));
235236
const char* class_name = cls->tp_name;
236237
PyTypeObject* javacls = polyglot_invoke(PY_TRUFFLE_CEXT,
237238
"PyType_Ready",

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
import com.oracle.graal.python.builtins.objects.cext.CExtNodesFactory.MayRaiseUnaryNodeGen;
8484
import com.oracle.graal.python.builtins.objects.cext.HandleCache;
8585
import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.PrimitiveNativeWrapper;
86+
import com.oracle.graal.python.builtins.objects.cext.NativeMemberNames;
8687
import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.PySequenceArrayWrapper;
8788
import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.PythonClassInitNativeWrapper;
8889
import com.oracle.graal.python.builtins.objects.cext.NativeWrappers.PythonClassNativeWrapper;
@@ -522,13 +523,14 @@ Object run(Object typestruct, PythonClass metaClass, PTuple baseClasses, PDict n
522523
}
523524

524525
// 'tp_name' contains the fully-qualified name, i.e., 'module.A.B...'
525-
String fqname = getStringItem(nativeMembers, "tp_name");
526-
String doc = getStringItem(nativeMembers, "tp_doc");
526+
String fqname = getStringItem(nativeMembers, NativeMemberNames.TP_NAME);
527+
String doc = getStringItem(nativeMembers, NativeMemberNames.TP_DOC);
527528
// the qualified name (i.e. without module name) like 'A.B...'
528529
String qualName = getQualName(fqname);
529530
PythonNativeClass cclass = factory().createNativeClassWrapper(typestruct, metaClass, qualName, bases);
530531
writeNode.execute(cclass, SpecialAttributeNames.__DOC__, doc);
531-
writeNode.execute(cclass, SpecialAttributeNames.__BASICSIZE__, getLongItem(nativeMembers, "tp_basicsize"));
532+
writeNode.execute(cclass, SpecialAttributeNames.__BASICSIZE__, getLongItem(nativeMembers, NativeMemberNames.TP_BASICSIZE));
533+
writeNode.execute(cclass, SpecialAttributeNames.__DICTOFFSET__, getLongItem(nativeMembers, NativeMemberNames.TP_DICTOFFSET));
532534
String moduleName = getModuleName(fqname);
533535
if (moduleName != null) {
534536
writeNode.execute(cclass, SpecialAttributeNames.__MODULE__, moduleName);

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ public final class NativeMemberNames {
5757
public static final String TP_NAME = "tp_name";
5858
public static final String TP_BASE = "tp_base";
5959
public static final String TP_BASICSIZE = "tp_basicsize";
60+
public static final String TP_DICTOFFSET = "tp_dictoffset";
61+
public static final String TP_DOC = "tp_doc";
6062
public static final String TP_ALLOC = "tp_alloc";
6163
public static final String TP_AS_NUMBER = "tp_as_number";
6264
public static final String TP_HASH = "tp_hash";

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,15 @@
4141
package com.oracle.graal.python.builtins.objects.cext;
4242

4343
import com.oracle.graal.python.builtins.objects.PythonAbstractObject;
44+
import com.oracle.truffle.api.interop.TruffleObject;
4445

4546
/**
4647
* A simple wrapper around objects created through the Python C API that can be cast to PyObject*.
4748
*/
4849
public class PythonNativeObject extends PythonAbstractObject {
49-
public final Object object;
50+
public final TruffleObject object;
5051

51-
public PythonNativeObject(Object obj) {
52+
public PythonNativeObject(TruffleObject obj) {
5253
object = obj;
5354
}
5455

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

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,13 @@
6464
import com.oracle.graal.python.builtins.objects.function.PBuiltinFunction;
6565
import com.oracle.graal.python.builtins.objects.function.PKeyword;
6666
import com.oracle.graal.python.builtins.objects.function.PythonCallable;
67+
import com.oracle.graal.python.builtins.objects.ints.PInt;
6768
import com.oracle.graal.python.builtins.objects.type.LazyPythonClass;
6869
import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass;
6970
import com.oracle.graal.python.builtins.objects.type.PythonClass;
7071
import com.oracle.graal.python.nodes.SpecialMethodNames;
7172
import com.oracle.graal.python.nodes.attributes.LookupAttributeInMRONode;
73+
import com.oracle.graal.python.nodes.attributes.LookupInheritedAttributeNode;
7274
import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode;
7375
import com.oracle.graal.python.nodes.attributes.WriteAttributeToObjectNode;
7476
import com.oracle.graal.python.nodes.call.special.CallBinaryMethodNode;
@@ -93,6 +95,11 @@
9395
import com.oracle.truffle.api.dsl.NodeFactory;
9496
import com.oracle.truffle.api.dsl.Specialization;
9597
import com.oracle.truffle.api.frame.VirtualFrame;
98+
import com.oracle.truffle.api.interop.ForeignAccess;
99+
import com.oracle.truffle.api.interop.Message;
100+
import com.oracle.truffle.api.interop.UnknownIdentifierException;
101+
import com.oracle.truffle.api.interop.UnsupportedMessageException;
102+
import com.oracle.truffle.api.nodes.Node;
96103
import com.oracle.truffle.api.nodes.UnexpectedResultException;
97104
import com.oracle.truffle.api.profiles.BranchProfile;
98105
import com.oracle.truffle.api.profiles.ConditionProfile;
@@ -507,6 +514,7 @@ protected PNone doIt(Object object, Object key,
507514
static abstract class DictNode extends PythonBinaryBuiltinNode {
508515
private final IsBuiltinClassProfile exactObjInstanceProfile = IsBuiltinClassProfile.create();
509516
private final IsBuiltinClassProfile exactBuiltinInstanceProfile = IsBuiltinClassProfile.create();
517+
@Child private Node readNode;
510518

511519
protected boolean isExactObjectInstance(PythonObject self) {
512520
return exactObjInstanceProfile.profileObject(self, PythonBuiltinClassType.PythonObject);
@@ -534,6 +542,38 @@ Object dict(PythonObject self, PDict dict) {
534542
return PNone.NONE;
535543
}
536544

545+
@Specialization(guards = "isNoValue(none)")
546+
Object dict(PythonNativeObject self, @SuppressWarnings("unused") PNone none,
547+
@Cached("create(__DICTOFFSET__)") LookupInheritedAttributeNode getDictoffset,
548+
@Cached("create()") BranchProfile noOffset,
549+
@Cached("create()") BranchProfile wrongType,
550+
@Cached("create()") CExtNodes.ToJavaNode toJava) {
551+
Object dictoffset = getDictoffset.execute(self);
552+
int offset;
553+
if (dictoffset instanceof Long) {
554+
offset = ((Long) dictoffset).intValue();
555+
} else if (dictoffset instanceof Integer) {
556+
offset = (Integer) dictoffset;
557+
} else if (dictoffset instanceof PInt) {
558+
offset = ((PInt) dictoffset).intValue();
559+
} else if (dictoffset instanceof PNone) {
560+
noOffset.enter();
561+
throw raise(AttributeError, "'%p' object has no attribute '__dict__'", self);
562+
} else {
563+
wrongType.enter();
564+
throw raise(TypeError, "tp_dictoffset of native type is not an integer, got '%p'", dictoffset);
565+
}
566+
if (readNode == null) {
567+
CompilerDirectives.transferToInterpreterAndInvalidate();
568+
readNode = insert(Message.READ.createNode());
569+
}
570+
try {
571+
return toJava.execute(ForeignAccess.sendRead(readNode, self.object, offset));
572+
} catch (UnknownIdentifierException | UnsupportedMessageException e) {
573+
throw raise(AttributeError, "'%p' object has no native '__dict__'", self);
574+
}
575+
}
576+
537577
@Fallback
538578
Object dict(Object self, @SuppressWarnings("unused") Object dict) {
539579
throw raise(AttributeError, "'%p' object has no attribute '__dict__'", self);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ private Object op(VirtualFrame frame, PythonClass self, Object[] arguments, PKey
212212
// https://github.com/python/cpython/blob/2102c789035ccacbac4362589402ac68baa2cd29/Objects/typeobject.c#L3538
213213
} else {
214214
Object initMethod = lookupInit.execute(newInstanceKlass);
215-
if (newMethod != PNone.NO_VALUE) {
215+
if (initMethod != PNone.NO_VALUE) {
216216
Object[] initArgs;
217217
if (doCreateArgs) {
218218
initArgs = PositionalArgumentsNode.prependArgument(newInstance, arguments, arguments.length);

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,6 @@ public abstract class SpecialAttributeNames {
6868
public static final String __CONTEXT__ = "__context__";
6969
public static final String __BASICSIZE__ = "__basicsize__";
7070
public static final String __NEW__ = "__new__";
71+
public static final Object __SLOTS__ = "__slots__";
72+
public static final String __DICTOFFSET__ = "__dictoffset__";
7173
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/object/PythonObjectFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ public PythonObject createPythonObject(PythonClass cls) {
199199
return trace(new PythonObject(cls, cls.getInstanceShape()));
200200
}
201201

202-
public PythonNativeObject createNativeObjectWrapper(Object obj) {
202+
public PythonNativeObject createNativeObjectWrapper(TruffleObject obj) {
203203
return trace(new PythonNativeObject(obj));
204204
}
205205

0 commit comments

Comments
 (0)