70
70
import com .oracle .graal .python .builtins .objects .cext .CExtNodesFactory .PointerCompareNodeGen ;
71
71
import com .oracle .graal .python .builtins .objects .cext .CExtNodesFactory .ToJavaNodeFactory .ToJavaCachedNodeGen ;
72
72
import com .oracle .graal .python .builtins .objects .cext .DynamicObjectNativeWrapper .PrimitiveNativeWrapper ;
73
- import com .oracle .graal .python .builtins .objects .cext .DynamicObjectNativeWrapper .PythonObjectNativeWrapper ;
74
73
import com .oracle .graal .python .builtins .objects .common .SequenceStorageNodes ;
75
74
import com .oracle .graal .python .builtins .objects .floats .PFloat ;
76
75
import com .oracle .graal .python .builtins .objects .function .PFunction ;
@@ -355,11 +354,28 @@ Object doLong(long l) {
355
354
return DynamicObjectNativeWrapper .PrimitiveNativeWrapper .createLong (l );
356
355
}
357
356
358
- @ Specialization
357
+ @ Specialization ( guards = "!isNaN(d)" )
359
358
Object doDouble (double d ) {
360
359
return DynamicObjectNativeWrapper .PrimitiveNativeWrapper .createDouble (d );
361
360
}
362
361
362
+ @ Specialization (guards = "isNaN(d)" )
363
+ Object doDouble (@ SuppressWarnings ("unused" ) double d ,
364
+ @ CachedContext (PythonLanguage .class ) PythonContext context ,
365
+ @ Cached ("createCountingProfile()" ) ConditionProfile noWrapperProfile ) {
366
+ PFloat boxed = context .getCore ().getNaN ();
367
+ DynamicObjectNativeWrapper nativeWrapper = boxed .getNativeWrapper ();
368
+ // Use a counting profile since we should enter the branch just once per context.
369
+ if (noWrapperProfile .profile (nativeWrapper == null )) {
370
+ // This deliberately uses 'CompilerDirectives.transferToInterpreter()' because this
371
+ // code will happen just once per context.
372
+ CompilerDirectives .transferToInterpreter ();
373
+ nativeWrapper = DynamicObjectNativeWrapper .PrimitiveNativeWrapper .createDouble (Double .NaN );
374
+ boxed .setNativeWrapper (nativeWrapper );
375
+ }
376
+ return nativeWrapper ;
377
+ }
378
+
363
379
@ Specialization
364
380
Object doNativeClass (PythonAbstractNativeObject nativeClass ) {
365
381
return nativeClass .getPtr ();
@@ -413,43 +429,17 @@ protected static PythonClassNativeWrapper wrapNativeClass(PythonManagedClass obj
413
429
return PythonClassNativeWrapper .wrap (object , GetNameNode .doSlowPath (object ));
414
430
}
415
431
416
- // TODO(fa): Workaround for DSL bug: did not import factory at users
432
+ protected static boolean isNaN (double d ) {
433
+ return Double .isNaN (d );
434
+ }
435
+
417
436
public static ToSulongNode create () {
418
437
return CExtNodesFactory .ToSulongNodeGen .create ();
419
438
}
420
439
421
- // TODO(fa): Workaround for DSL bug: did not import factory at users
422
440
public static ToSulongNode getUncached () {
423
441
return CExtNodesFactory .ToSulongNodeGen .getUncached ();
424
442
}
425
-
426
- @ TruffleBoundary
427
- public static Object doSlowPath (Object o ) {
428
- if (o instanceof String ) {
429
- return PythonObjectNativeWrapper .wrapSlowPath (PythonLanguage .getCore ().factory ().createString ((String ) o ));
430
- } else if (o instanceof Integer ) {
431
- return PrimitiveNativeWrapper .createInt ((Integer ) o );
432
- } else if (o instanceof Long ) {
433
- return PrimitiveNativeWrapper .createLong ((Long ) o );
434
- } else if (o instanceof Double ) {
435
- return PrimitiveNativeWrapper .createDouble ((Double ) o );
436
- } else if (PythonNativeClass .isInstance (o )) {
437
- return ((PythonNativeClass ) o ).getPtr ();
438
- } else if (PythonNativeObject .isInstance (o )) {
439
- return PythonNativeObject .cast (o ).getPtr ();
440
- } else if (o instanceof PythonNativeNull ) {
441
- return ((PythonNativeNull ) o ).getPtr ();
442
- } else if (o instanceof PythonManagedClass ) {
443
- return wrapNativeClass ((PythonManagedClass ) o );
444
- } else if (o instanceof PythonAbstractObject ) {
445
- assert !PGuards .isClass (o );
446
- return PythonObjectNativeWrapper .wrapSlowPath ((PythonAbstractObject ) o );
447
- } else if (PGuards .isForeignObject (o )) {
448
- return TruffleObjectNativeWrapper .wrap ((TruffleObject ) o );
449
- }
450
- assert o != null : "Java 'null' cannot be a Sulong value" ;
451
- return o ;
452
- }
453
443
}
454
444
455
445
// -----------------------------------------------------------------------------------------------------------------
@@ -610,9 +600,13 @@ public abstract static class MaterializeDelegateNode extends CExtBaseNode {
610
600
@ Specialization (guards = {"!isMaterialized(object)" , "object.isBool()" })
611
601
PInt doBoolNativeWrapper (DynamicObjectNativeWrapper .PrimitiveNativeWrapper object ,
612
602
@ CachedContext (PythonLanguage .class ) PythonContext context ) {
603
+ // Special case for True and False: use singletons
613
604
PythonCore core = context .getCore ();
614
605
PInt materializedInt = object .getBool () ? core .getTrue () : core .getFalse ();
615
606
object .setMaterializedObject (materializedInt );
607
+
608
+ // If the singleton already has a native wrapper, we may need to update the pointer
609
+ // of wrapper 'object' since the native could code see the same pointer.
616
610
if (materializedInt .getNativeWrapper () != null ) {
617
611
object .setNativePointer (materializedInt .getNativeWrapper ().getNativePointer ());
618
612
} else {
@@ -623,7 +617,7 @@ PInt doBoolNativeWrapper(DynamicObjectNativeWrapper.PrimitiveNativeWrapper objec
623
617
624
618
@ Specialization (guards = {"!isMaterialized(object)" , "object.isByte()" })
625
619
PInt doByteNativeWrapper (DynamicObjectNativeWrapper .PrimitiveNativeWrapper object ,
626
- @ Cached PythonObjectFactory factory ) {
620
+ @ Shared ( "factory" ) @ Cached PythonObjectFactory factory ) {
627
621
PInt materializedInt = factory .createInt (object .getByte ());
628
622
object .setMaterializedObject (materializedInt );
629
623
materializedInt .setNativeWrapper (object );
@@ -632,7 +626,7 @@ PInt doByteNativeWrapper(DynamicObjectNativeWrapper.PrimitiveNativeWrapper objec
632
626
633
627
@ Specialization (guards = {"!isMaterialized(object)" , "object.isInt()" })
634
628
PInt doIntNativeWrapper (DynamicObjectNativeWrapper .PrimitiveNativeWrapper object ,
635
- @ Cached PythonObjectFactory factory ) {
629
+ @ Shared ( "factory" ) @ Cached PythonObjectFactory factory ) {
636
630
PInt materializedInt = factory .createInt (object .getInt ());
637
631
object .setMaterializedObject (materializedInt );
638
632
materializedInt .setNativeWrapper (object );
@@ -641,22 +635,39 @@ PInt doIntNativeWrapper(DynamicObjectNativeWrapper.PrimitiveNativeWrapper object
641
635
642
636
@ Specialization (guards = {"!isMaterialized(object)" , "object.isLong()" })
643
637
PInt doLongNativeWrapper (DynamicObjectNativeWrapper .PrimitiveNativeWrapper object ,
644
- @ Cached PythonObjectFactory factory ) {
638
+ @ Shared ( "factory" ) @ Cached PythonObjectFactory factory ) {
645
639
PInt materializedInt = factory .createInt (object .getLong ());
646
640
object .setMaterializedObject (materializedInt );
647
641
materializedInt .setNativeWrapper (object );
648
642
return materializedInt ;
649
643
}
650
644
651
- @ Specialization (guards = {"!isMaterialized(object)" , "object.isDouble()" })
645
+ @ Specialization (guards = {"!isMaterialized(object)" , "object.isDouble()" , "!isNaN(object)" })
652
646
PFloat doDoubleNativeWrapper (DynamicObjectNativeWrapper .PrimitiveNativeWrapper object ,
653
- @ Cached PythonObjectFactory factory ) {
647
+ @ Shared ( "factory" ) @ Cached PythonObjectFactory factory ) {
654
648
PFloat materializedInt = factory .createFloat (object .getDouble ());
655
- object .setMaterializedObject (materializedInt );
656
649
materializedInt .setNativeWrapper (object );
650
+ object .setMaterializedObject (materializedInt );
657
651
return materializedInt ;
658
652
}
659
653
654
+ @ Specialization (guards = {"!isMaterialized(object)" , "object.isDouble()" , "isNaN(object)" })
655
+ PFloat doDoubleNativeWrapperNaN (DynamicObjectNativeWrapper .PrimitiveNativeWrapper object ,
656
+ @ CachedContext (PythonLanguage .class ) PythonContext context ) {
657
+ // Special case for double NaN: use singleton
658
+ PFloat materializedFloat = context .getCore ().getNaN ();
659
+ object .setMaterializedObject (materializedFloat );
660
+
661
+ // If the NaN singleton already has a native wrapper, we may need to update the pointer
662
+ // of wrapper 'object' since the native code should see the same pointer.
663
+ if (materializedFloat .getNativeWrapper () != null ) {
664
+ object .setNativePointer (materializedFloat .getNativeWrapper ().getNativePointer ());
665
+ } else {
666
+ materializedFloat .setNativeWrapper (object );
667
+ }
668
+ return materializedFloat ;
669
+ }
670
+
660
671
@ Specialization (guards = {"object.getClass() == cachedClass" , "isMaterialized(object)" })
661
672
Object doMaterialized (DynamicObjectNativeWrapper .PrimitiveNativeWrapper object ,
662
673
@ SuppressWarnings ("unused" ) @ Cached ("object.getClass()" ) Class <? extends DynamicObjectNativeWrapper .PrimitiveNativeWrapper > cachedClass ) {
@@ -677,6 +688,11 @@ Object doNativeWrapperGeneric(PythonNativeWrapper object) {
677
688
protected static boolean isPrimitiveNativeWrapper (PythonNativeWrapper object ) {
678
689
return object instanceof DynamicObjectNativeWrapper .PrimitiveNativeWrapper ;
679
690
}
691
+
692
+ protected static boolean isNaN (PrimitiveNativeWrapper object ) {
693
+ assert object .isDouble ();
694
+ return Double .isNaN (object .getDouble ());
695
+ }
680
696
}
681
697
682
698
// -----------------------------------------------------------------------------------------------------------------
0 commit comments