Skip to content

Commit be22a2a

Browse files
committed
Implement tp_doc, tp_repr, tp_dict, tp_traverse, and tp_clear for C API.
1 parent 846a390 commit be22a2a

File tree

2 files changed

+57
-5
lines changed

2 files changed

+57
-5
lines changed

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

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
import static com.oracle.graal.python.builtins.objects.cext.NativeMemberNames.TP_SUBCLASSES;
5252
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__BASICSIZE__;
5353
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__DICTOFFSET__;
54+
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__DICT__;
5455
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__ITEMSIZE__;
5556
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__WEAKLISTOFFSET__;
5657
import static com.oracle.graal.python.nodes.SpecialMethodNames.RICHCMP;
@@ -60,6 +61,7 @@
6061
import static com.oracle.graal.python.nodes.SpecialMethodNames.__LEN__;
6162
import static com.oracle.graal.python.nodes.SpecialMethodNames.__NEW__;
6263
import static com.oracle.graal.python.nodes.SpecialMethodNames.__NEXT__;
64+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__REPR__;
6365
import static com.oracle.graal.python.nodes.SpecialMethodNames.__SETATTR__;
6466

6567
import java.util.logging.Level;
@@ -71,6 +73,8 @@
7173
import com.oracle.graal.python.builtins.objects.PythonAbstractObject.PInteropGetAttributeNode;
7274
import com.oracle.graal.python.builtins.objects.bytes.PByteArray;
7375
import com.oracle.graal.python.builtins.objects.bytes.PBytes;
76+
import com.oracle.graal.python.builtins.objects.cext.CArrayWrappers.CStringWrapper;
77+
import com.oracle.graal.python.builtins.objects.cext.CExtNodes.GetNativeNullNode;
7478
import com.oracle.graal.python.builtins.objects.cext.CExtNodes.GetSpecialSingletonPtrNode;
7579
import com.oracle.graal.python.builtins.objects.cext.CExtNodes.IsPointerNode;
7680
import com.oracle.graal.python.builtins.objects.cext.CExtNodes.PCallCapiFunction;
@@ -299,6 +303,20 @@ Object doTpName(PythonManagedClass object, @SuppressWarnings("unused") String ke
299303
return object.getClassNativeWrapper().getNameWrapper();
300304
}
301305

306+
@Specialization(guards = "eq(TP_DOC, key)")
307+
Object doTpDoc(PythonManagedClass object, @SuppressWarnings("unused") String key,
308+
@Cached("createForceType()") ReadAttributeFromObjectNode readAttrNode,
309+
@Shared("getNativeNullNode") @Cached GetNativeNullNode getNativeNullNode) {
310+
// return a C string wrapper that really allocates 'char*' on TO_NATIVE
311+
Object docObj = readAttrNode.execute(object, SpecialAttributeNames.__DOC__);
312+
if (docObj instanceof String) {
313+
return new CStringWrapper((String) docObj);
314+
} else if (docObj instanceof PString) {
315+
return new CStringWrapper(((PString) docObj).getValue());
316+
}
317+
return getNativeNullNode.execute();
318+
}
319+
302320
@Specialization(guards = "eq(TP_BASE, key)")
303321
Object doTpBase(PythonManagedClass object, @SuppressWarnings("unused") String key,
304322
@CachedContext(PythonLanguage.class) PythonContext context,
@@ -338,7 +356,7 @@ Object doTpAsBuffer(PythonManagedClass object, @SuppressWarnings("unused") Strin
338356
@Cached BranchProfile notMemoryview,
339357
@Cached BranchProfile notBuffer,
340358
@Cached BranchProfile notMmap,
341-
@Shared("toSulongNode") @Cached CExtNodes.ToSulongNode toSulongNode) {
359+
@Shared("getNativeNullNode") @Cached GetNativeNullNode getNativeNullNode) {
342360
PythonBuiltinClass pBytes = context.getCore().lookupType(PythonBuiltinClassType.PBytes);
343361
if (isSubtype.passState().execute(object, pBytes)) {
344362
return new PyBufferProcsWrapper(pBytes);
@@ -365,7 +383,7 @@ Object doTpAsBuffer(PythonManagedClass object, @SuppressWarnings("unused") Strin
365383
}
366384
notMmap.enter();
367385
// NULL pointer
368-
return toSulongNode.execute(PNone.NO_VALUE);
386+
return getNativeNullNode.execute();
369387
}
370388

371389
@Specialization(guards = "eq(TP_AS_SEQUENCE, key)")
@@ -393,7 +411,7 @@ Object doTpHash(PythonManagedClass object, @SuppressWarnings("unused") String ke
393411
}
394412

395413
@Specialization(guards = "eq(TP_BASICSIZE, key)")
396-
Object doTpBasicsize(PythonManagedClass object, @SuppressWarnings("unused") String key,
414+
long doTpBasicsize(PythonManagedClass object, @SuppressWarnings("unused") String key,
397415
@Cached CastToIndexNode castToIntNode,
398416
@Cached PInteropGetAttributeNode getAttrNode) {
399417
Object val = getAttrNode.execute(object, __BASICSIZE__);
@@ -427,12 +445,13 @@ long doTpDictoffset(PythonManagedClass object, @SuppressWarnings("unused") Strin
427445

428446
@Specialization(guards = "eq(TP_WEAKLISTOFFSET, key)")
429447
Object doTpWeaklistoffset(PythonManagedClass object, @SuppressWarnings("unused") String key,
430-
@Cached LookupAttributeInMRONode.Dynamic getAttrNode) {
448+
@Cached LookupAttributeInMRONode.Dynamic getAttrNode,
449+
@Shared("getNativeNullNode") @Cached GetNativeNullNode getNativeNullNode) {
431450
Object val = getAttrNode.execute(object, __WEAKLISTOFFSET__);
432451
// If the attribute does not exist, this means that we take 'tp_itemsize' from the base
433452
// object which is by default 0 (see typeobject.c:PyBaseObject_Type).
434453
if (val == PNone.NO_VALUE) {
435-
return 0L;
454+
return getNativeNullNode.execute();
436455
}
437456
return val;
438457
}
@@ -485,6 +504,36 @@ Object doTpIternext(PythonManagedClass object, @SuppressWarnings("unused") Strin
485504
return toSulongNode.execute(lookupAttrNode.execute(object, __NEXT__));
486505
}
487506

507+
@Specialization(guards = "eq(TP_REPR, key)")
508+
Object doTpRepr(PythonManagedClass object, @SuppressWarnings("unused") String key,
509+
@Cached LookupAttributeInMRONode.Dynamic lookupAttrNode,
510+
@Shared("toSulongNode") @Cached CExtNodes.ToSulongNode toSulongNode) {
511+
return toSulongNode.execute(lookupAttrNode.execute(object, __REPR__));
512+
}
513+
514+
@Specialization(guards = "eq(TP_DICT, key)")
515+
Object doTpDict(PythonManagedClass object, @SuppressWarnings("unused") String key,
516+
@Cached("createForceType()") ReadAttributeFromObjectNode readAttrNode,
517+
@Shared("toSulongNode") @Cached CExtNodes.ToSulongNode toSulongNode) {
518+
return toSulongNode.execute(readAttrNode.execute(object, __DICT__));
519+
}
520+
521+
@Specialization(guards = "eq(TP_TRAVERSE, key) || eq(TP_CLEAR, key)")
522+
Object doTpTraverse(PythonManagedClass object, @SuppressWarnings("unused") String key,
523+
@Cached IsBuiltinClassProfile isTupleProfile,
524+
@Cached IsBuiltinClassProfile isDictProfile,
525+
@Cached IsBuiltinClassProfile isListProfile,
526+
@Shared("toSulongNode") @Cached CExtNodes.ToSulongNode toSulongNode,
527+
@Shared("getNativeNullNode") @Cached GetNativeNullNode getNativeNullNode) {
528+
if (isTupleProfile.profileClass(object, PythonBuiltinClassType.PTuple) || isDictProfile.profileClass(object, PythonBuiltinClassType.PDict) ||
529+
isListProfile.profileClass(object, PythonBuiltinClassType.PList)) {
530+
// We do not actually return the traverse or clear method since we will never need
531+
// it. It is just important to return something != NULL.
532+
return toSulongNode.execute(PNone.NONE);
533+
}
534+
return getNativeNullNode.execute();
535+
}
536+
488537
public static ReadTypeNativeMemberNode create() {
489538
return ReadTypeNativeMemberNodeGen.create();
490539
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ public final class NativeMemberNames {
7777
public static final String TP_ITERNEXT = "tp_iternext";
7878
public static final String TP_NEW = "tp_new";
7979
public static final String TP_DICT = "tp_dict";
80+
public static final String TP_REPR = "tp_repr";
81+
public static final String TP_TRAVERSE = "tp_traverse";
82+
public static final String TP_CLEAR = "tp_clear";
8083
public static final String _BASE = "_base";
8184
public static final String OB_ITEM = "ob_item";
8285
public static final String SQ_ITEM = "sq_item";

0 commit comments

Comments
 (0)