7171import com .oracle .graal .python .builtins .objects .PythonAbstractObject .PInteropGetAttributeNode ;
7272import com .oracle .graal .python .builtins .objects .bytes .PByteArray ;
7373import com .oracle .graal .python .builtins .objects .bytes .PBytes ;
74+ import com .oracle .graal .python .builtins .objects .cext .CExtNodes .GetSpecialSingletonPtrNode ;
75+ import com .oracle .graal .python .builtins .objects .cext .CExtNodes .IsPointerNode ;
7476import com .oracle .graal .python .builtins .objects .cext .CExtNodes .PCallCapiFunction ;
77+ import com .oracle .graal .python .builtins .objects .cext .CExtNodes .SetSpecialSingletonPtrNode ;
7578import com .oracle .graal .python .builtins .objects .cext .DynamicObjectNativeWrapperFactory .ReadTypeNativeMemberNodeGen ;
7679import com .oracle .graal .python .builtins .objects .cext .UnicodeObjectNodes .UnicodeAsWideCharNode ;
7780import com .oracle .graal .python .builtins .objects .common .DynamicObjectStorage ;
106109import com .oracle .graal .python .builtins .objects .type .TypeNodes .GetSuperClassNode ;
107110import com .oracle .graal .python .builtins .objects .type .TypeNodes .GetTypeFlagsNode ;
108111import com .oracle .graal .python .nodes .PGuards ;
109- import com .oracle .graal .python .nodes .PNodeWithContext ;
110112import com .oracle .graal .python .nodes .PRaiseNode ;
111113import com .oracle .graal .python .nodes .SpecialAttributeNames ;
112114import com .oracle .graal .python .nodes .SpecialMethodNames ;
@@ -995,71 +997,78 @@ protected Object execute(Object[] arguments,
995997 // TO NATIVE, IS POINTER, AS POINTER
996998 @ GenerateUncached
997999 abstract static class ToNativeNode extends Node {
998- public abstract Object execute (PythonNativeWrapper obj );
1000+ public abstract void execute (PythonNativeWrapper obj );
9991001
10001002 protected static boolean isClassInitNativeWrapper (PythonNativeWrapper obj ) {
10011003 return obj instanceof PythonClassInitNativeWrapper ;
10021004 }
10031005
10041006 @ Specialization
1005- public Object executeClsInit (PythonClassInitNativeWrapper obj ,
1006- @ Cached . Shared ("toPyObjectNode" ) @ Cached DynamicObjectNativeWrapper . ToPyObjectNode toPyObjectNode ,
1007- @ Cached . Shared ("invalidateNode" ) @ Cached InvalidateNativeObjectsAllManagedNode invalidateNode ) {
1007+ public void executeClsInit (PythonClassInitNativeWrapper obj ,
1008+ @ Shared ("toPyObjectNode" ) @ Cached ToPyObjectNode toPyObjectNode ,
1009+ @ Shared ("invalidateNode" ) @ Cached InvalidateNativeObjectsAllManagedNode invalidateNode ) {
10081010 invalidateNode .execute ();
10091011 if (!obj .isNative ()) {
10101012 obj .setNativePointer (toPyObjectNode .execute (obj ));
10111013 }
1012- return obj ;
10131014 }
10141015
10151016 @ Specialization (guards = "!isClassInitNativeWrapper(obj)" )
1016- public Object execute (PythonNativeWrapper obj ,
1017- @ Cached .Shared ("toPyObjectNode" ) @ Cached DynamicObjectNativeWrapper .ToPyObjectNode toPyObjectNode ,
1018- @ Cached .Shared ("invalidateNode" ) @ Cached InvalidateNativeObjectsAllManagedNode invalidateNode ) {
1017+ public void execute (PythonNativeWrapper obj ,
1018+ @ Shared ("toPyObjectNode" ) @ Cached ToPyObjectNode toPyObjectNode ,
1019+ @ Cached SetSpecialSingletonPtrNode setSpecialSingletonPtrNode ,
1020+ @ Cached ("createBinaryProfile()" ) ConditionProfile profile ,
1021+ @ Shared ("invalidateNode" ) @ Cached InvalidateNativeObjectsAllManagedNode invalidateNode ,
1022+ @ Cached IsPointerNode isPointerNode ) {
10191023 invalidateNode .execute ();
1020- if (!obj .isNative ()) {
1021- obj .setNativePointer (toPyObjectNode .execute (obj ));
1024+ if (!isPointerNode .execute (obj )) {
1025+ Object ptr = toPyObjectNode .execute (obj );
1026+ Object delegate = obj .getDelegate ();
1027+ if (profile .profile (PythonLanguage .getSingletonNativePtrIdx (delegate ) != -1 )) {
1028+ setSpecialSingletonPtrNode .execute (delegate , ptr );
1029+ } else {
1030+ obj .setNativePointer (ptr );
1031+ }
10221032 }
1023- return obj ;
1024- }
1025- }
1026-
1027- abstract static class IsPointerNode extends Node {
1028- public abstract boolean execute (PythonNativeWrapper obj );
1029-
1030- @ Specialization
1031- public boolean execute (PythonNativeWrapper obj ,
1032- @ Cached .Exclusive @ Cached CExtNodes .IsPointerNode pIsPointerNode ) {
1033- return pIsPointerNode .execute (obj );
10341033 }
10351034 }
10361035
10371036 @ GenerateUncached
1038- abstract static class PAsPointerNode extends PNodeWithContext {
1037+ abstract static class PAsPointerNode extends Node {
10391038
10401039 public abstract long execute (PythonNativeWrapper o );
10411040
10421041 @ Specialization (guards = {"obj.isBool()" , "!obj.isNative()" })
1043- long doBoolNotNative (DynamicObjectNativeWrapper . PrimitiveNativeWrapper obj ,
1042+ long doBoolNotNative (PrimitiveNativeWrapper obj ,
10441043 @ Cached CExtNodes .MaterializeDelegateNode materializeNode ,
10451044 @ Shared ("interopLib" ) @ CachedLibrary (limit = "1" ) InteropLibrary interopLib ) {
10461045 // special case for True and False singletons
10471046 PInt boxed = (PInt ) materializeNode .execute (obj );
10481047 assert obj .getNativePointer () == boxed .getNativeWrapper ().getNativePointer ();
1049- return doFast ( obj , interopLib );
1048+ return ensureLong ( interopLib , obj . getNativePointer () );
10501049 }
10511050
10521051 @ Specialization (guards = {"obj.isBool()" , "obj.isNative()" })
1053- long doBoolNative (DynamicObjectNativeWrapper . PrimitiveNativeWrapper obj ,
1052+ long doBoolNative (PrimitiveNativeWrapper obj ,
10541053 @ Shared ("interopLib" ) @ CachedLibrary (limit = "1" ) InteropLibrary interopLib ) {
1055- return doFast ( obj , interopLib );
1054+ return ensureLong ( interopLib , obj . getNativePointer () );
10561055 }
10571056
10581057 @ Specialization (guards = "!isBoolNativeWrapper(obj)" )
10591058 long doFast (PythonNativeWrapper obj ,
1060- @ Shared ("interopLib" ) @ CachedLibrary (limit = "1" ) InteropLibrary interopLib ) {
1059+ @ Shared ("interopLib" ) @ CachedLibrary (limit = "1" ) InteropLibrary interopLib ,
1060+ @ Cached ("createBinaryProfile()" ) ConditionProfile profile ,
1061+ @ Cached GetSpecialSingletonPtrNode getSpecialSingletonPtrNode ) {
10611062 // the native pointer object must either be a TruffleObject or a primitive
1062- return ensureLong (interopLib , obj .getNativePointer ());
1063+ Object nativePointer = obj .getNativePointer ();
1064+ if (profile .profile (nativePointer == null )) {
1065+ // We assume that before someone calls 'asPointer' on the wrapper, 'isPointer' was
1066+ // checked and returned true. So, for this case we assume that it is one of the
1067+ // special singletons where we store the pointer in the context.
1068+ nativePointer = getSpecialSingletonPtrNode .execute (obj .getDelegate ());
1069+ assert nativePointer != null : createAssertionMessage (obj .getDelegate ());
1070+ }
1071+ return ensureLong (interopLib , nativePointer );
10631072 }
10641073
10651074 private static long ensureLong (InteropLibrary interopLib , Object nativePointer ) {
@@ -1076,8 +1085,18 @@ private static long ensureLong(InteropLibrary interopLib, Object nativePointer)
10761085 }
10771086
10781087 protected static boolean isBoolNativeWrapper (Object obj ) {
1079- return obj instanceof DynamicObjectNativeWrapper . PrimitiveNativeWrapper && ((DynamicObjectNativeWrapper . PrimitiveNativeWrapper ) obj ).isBool ();
1088+ return obj instanceof PrimitiveNativeWrapper && ((PrimitiveNativeWrapper ) obj ).isBool ();
10801089 }
1090+
1091+ private static String createAssertionMessage (Object delegate ) {
1092+ CompilerAsserts .neverPartOfCompilation ();
1093+ int singletonNativePtrIdx = PythonLanguage .getSingletonNativePtrIdx (delegate );
1094+ if (singletonNativePtrIdx == -1 ) {
1095+ return "invalid special singleton object " + delegate ;
1096+ }
1097+ return "expected special singleton '" + delegate + "' to have a native pointer" ;
1098+ }
1099+
10811100 }
10821101
10831102 @ GenerateUncached
@@ -1270,7 +1289,7 @@ protected boolean isMemberReadable(String member) {
12701289
12711290 @ ExportMessage
12721291 protected boolean isPointer (
1273- @ Cached . Exclusive @ Cached CExtNodes .IsPointerNode pIsPointerNode ) {
1292+ @ Cached CExtNodes .IsPointerNode pIsPointerNode ) {
12741293 return pIsPointerNode .execute (this );
12751294 }
12761295
0 commit comments