51
51
import static com .oracle .graal .python .builtins .objects .cext .NativeMemberNames .TP_SUBCLASSES ;
52
52
import static com .oracle .graal .python .nodes .SpecialAttributeNames .__BASICSIZE__ ;
53
53
import static com .oracle .graal .python .nodes .SpecialAttributeNames .__DICTOFFSET__ ;
54
+ import static com .oracle .graal .python .nodes .SpecialAttributeNames .__DICT__ ;
54
55
import static com .oracle .graal .python .nodes .SpecialAttributeNames .__ITEMSIZE__ ;
55
56
import static com .oracle .graal .python .nodes .SpecialAttributeNames .__WEAKLISTOFFSET__ ;
56
57
import static com .oracle .graal .python .nodes .SpecialMethodNames .RICHCMP ;
60
61
import static com .oracle .graal .python .nodes .SpecialMethodNames .__LEN__ ;
61
62
import static com .oracle .graal .python .nodes .SpecialMethodNames .__NEW__ ;
62
63
import static com .oracle .graal .python .nodes .SpecialMethodNames .__NEXT__ ;
64
+ import static com .oracle .graal .python .nodes .SpecialMethodNames .__REPR__ ;
63
65
import static com .oracle .graal .python .nodes .SpecialMethodNames .__SETATTR__ ;
64
66
65
67
import java .util .logging .Level ;
71
73
import com .oracle .graal .python .builtins .objects .PythonAbstractObject .PInteropGetAttributeNode ;
72
74
import com .oracle .graal .python .builtins .objects .bytes .PByteArray ;
73
75
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 ;
74
78
import com .oracle .graal .python .builtins .objects .cext .CExtNodes .GetSpecialSingletonPtrNode ;
75
79
import com .oracle .graal .python .builtins .objects .cext .CExtNodes .IsPointerNode ;
76
80
import com .oracle .graal .python .builtins .objects .cext .CExtNodes .PCallCapiFunction ;
@@ -299,6 +303,20 @@ Object doTpName(PythonManagedClass object, @SuppressWarnings("unused") String ke
299
303
return object .getClassNativeWrapper ().getNameWrapper ();
300
304
}
301
305
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
+
302
320
@ Specialization (guards = "eq(TP_BASE, key)" )
303
321
Object doTpBase (PythonManagedClass object , @ SuppressWarnings ("unused" ) String key ,
304
322
@ CachedContext (PythonLanguage .class ) PythonContext context ,
@@ -338,7 +356,7 @@ Object doTpAsBuffer(PythonManagedClass object, @SuppressWarnings("unused") Strin
338
356
@ Cached BranchProfile notMemoryview ,
339
357
@ Cached BranchProfile notBuffer ,
340
358
@ Cached BranchProfile notMmap ,
341
- @ Shared ("toSulongNode " ) @ Cached CExtNodes . ToSulongNode toSulongNode ) {
359
+ @ Shared ("getNativeNullNode " ) @ Cached GetNativeNullNode getNativeNullNode ) {
342
360
PythonBuiltinClass pBytes = context .getCore ().lookupType (PythonBuiltinClassType .PBytes );
343
361
if (isSubtype .passState ().execute (object , pBytes )) {
344
362
return new PyBufferProcsWrapper (pBytes );
@@ -365,7 +383,7 @@ Object doTpAsBuffer(PythonManagedClass object, @SuppressWarnings("unused") Strin
365
383
}
366
384
notMmap .enter ();
367
385
// NULL pointer
368
- return toSulongNode .execute (PNone . NO_VALUE );
386
+ return getNativeNullNode .execute ();
369
387
}
370
388
371
389
@ Specialization (guards = "eq(TP_AS_SEQUENCE, key)" )
@@ -393,7 +411,7 @@ Object doTpHash(PythonManagedClass object, @SuppressWarnings("unused") String ke
393
411
}
394
412
395
413
@ Specialization (guards = "eq(TP_BASICSIZE, key)" )
396
- Object doTpBasicsize (PythonManagedClass object , @ SuppressWarnings ("unused" ) String key ,
414
+ long doTpBasicsize (PythonManagedClass object , @ SuppressWarnings ("unused" ) String key ,
397
415
@ Cached CastToIndexNode castToIntNode ,
398
416
@ Cached PInteropGetAttributeNode getAttrNode ) {
399
417
Object val = getAttrNode .execute (object , __BASICSIZE__ );
@@ -427,12 +445,13 @@ long doTpDictoffset(PythonManagedClass object, @SuppressWarnings("unused") Strin
427
445
428
446
@ Specialization (guards = "eq(TP_WEAKLISTOFFSET, key)" )
429
447
Object doTpWeaklistoffset (PythonManagedClass object , @ SuppressWarnings ("unused" ) String key ,
430
- @ Cached LookupAttributeInMRONode .Dynamic getAttrNode ) {
448
+ @ Cached LookupAttributeInMRONode .Dynamic getAttrNode ,
449
+ @ Shared ("getNativeNullNode" ) @ Cached GetNativeNullNode getNativeNullNode ) {
431
450
Object val = getAttrNode .execute (object , __WEAKLISTOFFSET__ );
432
451
// If the attribute does not exist, this means that we take 'tp_itemsize' from the base
433
452
// object which is by default 0 (see typeobject.c:PyBaseObject_Type).
434
453
if (val == PNone .NO_VALUE ) {
435
- return 0L ;
454
+ return getNativeNullNode . execute () ;
436
455
}
437
456
return val ;
438
457
}
@@ -485,6 +504,36 @@ Object doTpIternext(PythonManagedClass object, @SuppressWarnings("unused") Strin
485
504
return toSulongNode .execute (lookupAttrNode .execute (object , __NEXT__ ));
486
505
}
487
506
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
+
488
537
public static ReadTypeNativeMemberNode create () {
489
538
return ReadTypeNativeMemberNodeGen .create ();
490
539
}
0 commit comments