5151import static com .oracle .graal .python .builtins .objects .cext .NativeMemberNames .TP_SUBCLASSES ;
5252import static com .oracle .graal .python .nodes .SpecialAttributeNames .__BASICSIZE__ ;
5353import static com .oracle .graal .python .nodes .SpecialAttributeNames .__DICTOFFSET__ ;
54+ import static com .oracle .graal .python .nodes .SpecialAttributeNames .__DICT__ ;
5455import static com .oracle .graal .python .nodes .SpecialAttributeNames .__ITEMSIZE__ ;
5556import static com .oracle .graal .python .nodes .SpecialAttributeNames .__WEAKLISTOFFSET__ ;
5657import static com .oracle .graal .python .nodes .SpecialMethodNames .RICHCMP ;
6061import static com .oracle .graal .python .nodes .SpecialMethodNames .__LEN__ ;
6162import static com .oracle .graal .python .nodes .SpecialMethodNames .__NEW__ ;
6263import static com .oracle .graal .python .nodes .SpecialMethodNames .__NEXT__ ;
64+ import static com .oracle .graal .python .nodes .SpecialMethodNames .__REPR__ ;
6365import static com .oracle .graal .python .nodes .SpecialMethodNames .__SETATTR__ ;
6466
6567import java .util .logging .Level ;
7173import com .oracle .graal .python .builtins .objects .PythonAbstractObject .PInteropGetAttributeNode ;
7274import com .oracle .graal .python .builtins .objects .bytes .PByteArray ;
7375import 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 ;
7478import com .oracle .graal .python .builtins .objects .cext .CExtNodes .GetSpecialSingletonPtrNode ;
7579import com .oracle .graal .python .builtins .objects .cext .CExtNodes .IsPointerNode ;
7680import 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 }
0 commit comments