88
88
import com .oracle .graal .python .lib .PyObjectGetItem ;
89
89
import com .oracle .graal .python .lib .PyObjectSetItem ;
90
90
import com .oracle .graal .python .runtime .GilNode .UncachedAcquire ;
91
+ import com .oracle .truffle .api .dsl .Fallback ;
91
92
import org .graalvm .nativeimage .ImageInfo ;
92
93
93
94
import com .oracle .graal .python .PythonLanguage ;
296
297
import com .oracle .truffle .api .nodes .Node ;
297
298
import com .oracle .truffle .api .object .DynamicObjectLibrary ;
298
299
import com .oracle .truffle .api .object .Shape ;
299
- import com .oracle .truffle .api .profiles .ConditionProfile ;
300
300
import com .oracle .truffle .api .source .Source ;
301
301
import com .oracle .truffle .api .source .Source .SourceBuilder ;
302
302
import com .oracle .truffle .llvm .spi .NativeTypeLibrary ;
@@ -902,7 +902,7 @@ public static GraalHPyNativeSymbol getGetterFunctionName(LLVMType llvmType) {
902
902
903
903
private static final int IMMUTABLE_HANDLE_COUNT = 256 ;
904
904
905
- private Object [] hpyHandleTable = new Object []{ GraalHPyHandle . NULL_HANDLE_DELEGATE } ;
905
+ private Object [] hpyHandleTable ;
906
906
private int nextHandle = 1 ;
907
907
908
908
private GraalHPyHandle [] hpyGlobalsTable = new GraalHPyHandle []{GraalHPyHandle .NULL_HANDLE };
@@ -933,6 +933,14 @@ public static GraalHPyNativeSymbol getGetterFunctionName(LLVMType llvmType) {
933
933
934
934
@ CompilationFinal (dimensions = 1 ) private final Object [] hpyContextMembers ;
935
935
936
+ /**
937
+ * Few well known Python objects that are also HPyContext constants are guaranteed to always get
938
+ * the same handle.
939
+ */
940
+ static final int SINGLETON_HANDLE_NONE = 1 ;
941
+ static final int SINGLETON_HANDLE_NOT_IMPLEMENTED = 2 ;
942
+ static final int SINGLETON_HANDLE_ELIPSIS = 3 ;
943
+
936
944
/** the native type ID of C struct 'HPyContext' */
937
945
@ CompilationFinal private Object hpyContextNativeTypeID ;
938
946
@@ -972,20 +980,29 @@ public GraalHPyContext(PythonContext context, Object hpyLibrary) {
972
980
int traceJNISleepTime = language .getEngineOption (PythonOptions .HPyTraceUpcalls );
973
981
traceJNIUpcalls = traceJNISleepTime != 0 ;
974
982
this .slowPathFactory = context .factory ();
983
+ nextHandle = GraalHPyBoxing .SINGLETON_HANDLE_MAX + 1 ;
984
+ hpyHandleTable = new Object [IMMUTABLE_HANDLE_COUNT * 2 ];
985
+ hpyHandleTable [0 ] = GraalHPyHandle .NULL_HANDLE_DELEGATE ;
986
+ // createMembers already assigns numeric handles to "singletons"
975
987
this .hpyContextMembers = createMembers (context , T_NAME , traceJNIUpcalls );
988
+ // This will assign handles to the remaining context constants
976
989
for (Object member : hpyContextMembers ) {
977
990
if (member instanceof GraalHPyHandle ) {
978
991
GraalHPyHandle handle = (GraalHPyHandle ) member ;
979
- int id = handle .getId (this , ConditionProfile . getUncached () );
992
+ int id = handle .getIdUncached (this );
980
993
assert id > 0 && id < IMMUTABLE_HANDLE_COUNT ;
981
-
994
+ assert id > GraalHPyBoxing .SINGLETON_HANDLE_MAX ||
995
+ getHPyHandleForObject (handle .getDelegate ()) == id ;
982
996
}
983
997
}
984
- hpyHandleTable = Arrays .copyOf (hpyHandleTable , IMMUTABLE_HANDLE_COUNT * 2 );
985
998
nextHandle = IMMUTABLE_HANDLE_COUNT ;
986
999
if (traceJNIUpcalls ) {
987
1000
startUpcallsDaemon (traceJNISleepTime );
988
1001
}
1002
+
1003
+ assert getHPyHandleForObject (PNone .NONE ) == SINGLETON_HANDLE_NONE ;
1004
+ assert getHPyHandleForObject (PEllipsis .INSTANCE ) == SINGLETON_HANDLE_ELIPSIS ;
1005
+ assert getHPyHandleForObject (PNotImplemented .NOT_IMPLEMENTED ) == SINGLETON_HANDLE_NOT_IMPLEMENTED ;
989
1006
}
990
1007
991
1008
public PythonObjectSlowPathFactory getSlowPathFactory () {
@@ -1744,7 +1761,6 @@ public long ctxAsStruct(long handle) {
1744
1761
return (long ) HPyGetNativeSpacePointerNodeGen .getUncached ().execute (receiver );
1745
1762
}
1746
1763
1747
-
1748
1764
// Note: assumes that receiverHandle is not a boxed primitive value
1749
1765
@ SuppressWarnings ("try" )
1750
1766
public final int ctxSetItems (long receiverHandle , String name , long valueHandle ) {
@@ -2363,17 +2379,17 @@ Object invokeMember(String key, Object[] args,
2363
2379
return memberInvokeLib .execute (member , args );
2364
2380
}
2365
2381
2366
- private static Object [] createMembers (PythonContext context , TruffleString name , boolean traceJNIUpcalls ) {
2382
+ private Object [] createMembers (PythonContext context , TruffleString name , boolean traceJNIUpcalls ) {
2367
2383
Object [] members = new Object [HPyContextMember .VALUES .length ];
2368
2384
2369
2385
members [HPyContextMember .NAME .ordinal ()] = new CStringWrapper (name );
2370
2386
createIntConstant (members , HPyContextMember .CTX_VERSION , 1 );
2371
2387
2372
- createConstant (members , HPyContextMember .H_NONE , PNone .NONE );
2388
+ createSingletonConstant (members , HPyContextMember .H_NONE , PNone .NONE , SINGLETON_HANDLE_NONE );
2373
2389
createConstant (members , HPyContextMember .H_TRUE , context .getTrue ());
2374
2390
createConstant (members , HPyContextMember .H_FALSE , context .getFalse ());
2375
- createConstant (members , HPyContextMember .H_NOTIMPLEMENTED , PNotImplemented .NOT_IMPLEMENTED );
2376
- createConstant (members , HPyContextMember .H_ELLIPSIS , PEllipsis .INSTANCE );
2391
+ createSingletonConstant (members , HPyContextMember .H_NOTIMPLEMENTED , PNotImplemented .NOT_IMPLEMENTED , SINGLETON_HANDLE_NOT_IMPLEMENTED );
2392
+ createSingletonConstant (members , HPyContextMember .H_ELLIPSIS , PEllipsis .INSTANCE , SINGLETON_HANDLE_ELIPSIS );
2377
2393
2378
2394
createTypeConstant (members , HPyContextMember .H_BASEEXCEPTION , context , PythonBuiltinClassType .PBaseException );
2379
2395
createTypeConstant (members , HPyContextMember .H_EXCEPTION , context , PythonBuiltinClassType .Exception );
@@ -2731,6 +2747,12 @@ private static void createConstant(Object[] members, HPyContextMember member, Ob
2731
2747
members [member .ordinal ()] = GraalHPyHandle .create (value );
2732
2748
}
2733
2749
2750
+ private void createSingletonConstant (Object [] members , HPyContextMember member , Object value , int handle ) {
2751
+ GraalHPyHandle graalHandle = GraalHPyHandle .createSingleton (value , handle );
2752
+ members [member .ordinal ()] = graalHandle ;
2753
+ hpyHandleTable [handle ] = value ;
2754
+ }
2755
+
2734
2756
private static void createTypeConstant (Object [] members , HPyContextMember member , Python3Core core , PythonBuiltinClassType value ) {
2735
2757
members [member .ordinal ()] = GraalHPyHandle .create (core .lookupType (value ));
2736
2758
}
@@ -2795,6 +2817,21 @@ private int resizeHandleTable() {
2795
2817
}
2796
2818
2797
2819
public int getHPyHandleForObject (Object object ) {
2820
+ assert !(object instanceof GraalHPyHandle );
2821
+ int singletonHandle = getHPyHandleForSingleton (object );
2822
+ if (singletonHandle != -1 ) {
2823
+ return singletonHandle ;
2824
+ }
2825
+ return getHPyHandleForNonSingleton (object );
2826
+ }
2827
+
2828
+ public static int getHPyHandleForSingleton (Object object ) {
2829
+ CompilerAsserts .neverPartOfCompilation ();
2830
+ assert !(object instanceof GraalHPyHandle );
2831
+ return GraalHPyContextFactory .GetHPyHandleForSingletonNodeGen .getUncached ().execute (object );
2832
+ }
2833
+
2834
+ public int getHPyHandleForNonSingleton (Object object ) {
2798
2835
assert !(object instanceof GraalHPyHandle );
2799
2836
// find free association
2800
2837
@@ -2821,6 +2858,32 @@ public int getHPyHandleForObject(Object object) {
2821
2858
return handle ;
2822
2859
}
2823
2860
2861
+ @ GenerateUncached
2862
+ public abstract static class GetHPyHandleForSingleton extends Node {
2863
+ public abstract int execute (Object delegateObject );
2864
+
2865
+ @ Specialization
2866
+ static int doNone (PNone x ) {
2867
+ assert x == PNone .NONE ;
2868
+ return SINGLETON_HANDLE_NONE ;
2869
+ }
2870
+
2871
+ @ Specialization
2872
+ static int doElipsis (PEllipsis x ) {
2873
+ return SINGLETON_HANDLE_ELIPSIS ;
2874
+ }
2875
+
2876
+ @ Specialization
2877
+ static int doNotImplemented (PNotImplemented x ) {
2878
+ return SINGLETON_HANDLE_NOT_IMPLEMENTED ;
2879
+ }
2880
+
2881
+ @ Fallback
2882
+ static int doOthers (@ SuppressWarnings ("unused" ) Object delegate ) {
2883
+ return -1 ;
2884
+ }
2885
+ }
2886
+
2824
2887
@ TruffleBoundary
2825
2888
private void mirrorNativeSpacePointerToNative (Object delegate , int handleID ) {
2826
2889
assert isPointer ();
0 commit comments