95
95
import com .oracle .graal .python .builtins .objects .common .SequenceNodes ;
96
96
import com .oracle .graal .python .builtins .objects .common .SequenceNodes .GetObjectArrayNode ;
97
97
import com .oracle .graal .python .builtins .objects .common .SequenceNodesFactory .GetObjectArrayNodeGen ;
98
+ import com .oracle .graal .python .builtins .objects .complex .PComplex ;
98
99
import com .oracle .graal .python .builtins .objects .common .SequenceStorageNodes ;
99
100
import com .oracle .graal .python .builtins .objects .dict .PDict ;
101
+ import com .oracle .graal .python .builtins .objects .floats .PFloat ;
100
102
import com .oracle .graal .python .builtins .objects .frame .PFrame ;
101
103
import com .oracle .graal .python .builtins .objects .function .PArguments ;
102
104
import com .oracle .graal .python .builtins .objects .function .PKeyword ;
108
110
import com .oracle .graal .python .builtins .objects .str .PString ;
109
111
import com .oracle .graal .python .builtins .objects .tuple .PTuple ;
110
112
import com .oracle .graal .python .builtins .objects .type .PythonAbstractClass ;
113
+ import com .oracle .graal .python .builtins .objects .type .PythonBuiltinClass ;
111
114
import com .oracle .graal .python .builtins .objects .type .TypeBuiltins ;
112
115
import com .oracle .graal .python .builtins .objects .type .TypeNodes ;
113
116
import com .oracle .graal .python .nodes .BuiltinNames ;
172
175
import com .oracle .truffle .api .TruffleLanguage ;
173
176
import com .oracle .truffle .api .debug .Debugger ;
174
177
import com .oracle .truffle .api .dsl .Cached ;
178
+ import com .oracle .truffle .api .dsl .CachedContext ;
175
179
import com .oracle .truffle .api .dsl .Cached .Shared ;
176
180
import com .oracle .truffle .api .dsl .Fallback ;
177
181
import com .oracle .truffle .api .dsl .GenerateNodeFactory ;
182
+ import com .oracle .truffle .api .dsl .GenerateUncached ;
178
183
import com .oracle .truffle .api .dsl .ImportStatic ;
179
184
import com .oracle .truffle .api .dsl .ReportPolymorphism ;
180
185
import com .oracle .truffle .api .dsl .Specialization ;
@@ -909,15 +914,16 @@ Object getAttrGeneric(VirtualFrame frame, Object primary, Object name, Object de
909
914
// id(object)
910
915
@ Builtin (name = ID , minNumOfPositionalArgs = 1 )
911
916
@ GenerateNodeFactory
912
- public abstract static class IdNode extends PythonBuiltinNode {
913
- /**
914
- * The reserved ids at the beginning.
915
- *
916
- * <pre>
917
- * None, NotImplemented, True, False
918
- * </pre>
919
- */
920
- private static final long KNOWN_OBJECTS_COUNT = 4L ;
917
+ public abstract static class IdNode extends PythonUnaryBuiltinNode {
918
+ @ Specialization
919
+ long doObject (Object value ,
920
+ @ Cached IdExpressionNode idNode ) {
921
+ return idNode .executeLong (value );
922
+ }
923
+ }
924
+
925
+ @ GenerateUncached
926
+ public abstract static class IdExpressionNode extends Node {
921
927
// borrowed logic from pypy
922
928
// -1 - (-maxunicode-1): unichar
923
929
// 0 - 255: char
@@ -929,97 +935,124 @@ public abstract static class IdNode extends PythonBuiltinNode {
929
935
private static final long BASE_EMPTY_UNICODE = 257 ;
930
936
private static final long BASE_EMPTY_TUPLE = 258 ;
931
937
private static final long BASE_EMPTY_FROZENSET = 259 ;
932
- private static final long IDTAG_SPECIAL = 11 ;
933
- private static final int IDTAG_SHIFT = 4 ;
938
+ private static final int IDTAG_INT = 1 ;
939
+ private static final int IDTAG_FLOAT = 5 ;
940
+ private static final int IDTAG_COMPLEX = 7 ;
941
+ private static final int IDTAG_SPECIAL = 11 ;
942
+ private static final int IDTAG_SHIFT = 4 ;
934
943
935
- /**
936
- * The next available global id. We reserve space for all integers to be their own id +
937
- * offset.
938
- */
944
+ public abstract long executeLong (Object value );
939
945
940
- @ Child private ReadAttributeFromObjectNode readId = null ;
941
- @ Child private WriteAttributeToObjectNode writeId = null ;
942
- @ Child private SequenceNodes .LenNode lenNode = null ;
943
- @ Child private HashingCollectionNodes .LenNode setLenNode = null ;
944
-
945
- @ SuppressWarnings ("unused" )
946
946
@ Specialization
947
- int doId (PNone none ) {
948
- return 0 ;
947
+ long doId (boolean value ,
948
+ @ CachedContext (PythonLanguage .class ) PythonContext ctx ) {
949
+ return value ? doGeneric (ctx .getCore ().getTrue ()) : doGeneric (ctx .getCore ().getFalse ());
949
950
}
950
951
951
- @ SuppressWarnings ("unused" )
952
952
@ Specialization
953
- int doId (PNotImplemented none ) {
954
- return 1 ;
953
+ long doId (int integer ) {
954
+ return (( long ) integer ) << IDTAG_SHIFT | IDTAG_INT ;
955
955
}
956
956
957
957
@ Specialization
958
- int doId (boolean value ) {
959
- return value ? 2 : 3 ;
958
+ long doId (PInt value ,
959
+ @ Shared ("isBuiltin" ) @ Cached IsBuiltinClassProfile isBuiltin ) {
960
+ if (isBuiltin .profileIsAnyBuiltinObject (value )) {
961
+ try {
962
+ return doId (value .intValueExact ());
963
+ } catch (ArithmeticException e ) {
964
+ // fall through
965
+ }
966
+ }
967
+ return doGeneric (value );
960
968
}
961
969
962
970
@ Specialization
963
- long doId (int integer ) {
964
- return integer + KNOWN_OBJECTS_COUNT ;
971
+ long doString (String s ) {
972
+ if (s .length () == 0 ) {
973
+ return (BASE_EMPTY_UNICODE << IDTAG_SHIFT ) | IDTAG_SPECIAL ;
974
+ } else if (s .length () == 1 ) {
975
+ return (~s .codePointAt (0 ) << IDTAG_SHIFT ) | IDTAG_SPECIAL ;
976
+ } else {
977
+ return doGeneric (s );
978
+ }
965
979
}
966
980
967
981
@ Specialization
968
- Object doId (PInt value ) {
969
- try {
970
- return value .intValueExact () + KNOWN_OBJECTS_COUNT ;
971
- } catch (ArithmeticException e ) {
972
- return getId (value );
982
+ long doPString (PString s ,
983
+ @ Shared ("isBuiltin" ) @ Cached IsBuiltinClassProfile isBuiltin ,
984
+ @ Cached CastToJavaStringNode castStr ) {
985
+ if (isBuiltin .profileIsAnyBuiltinObject (s )) {
986
+ String jS = castStr .execute (s );
987
+ return doString (jS );
988
+ } else {
989
+ return doGeneric (s );
973
990
}
974
991
}
975
992
976
993
@ Specialization
977
- int doId (double value ) {
978
- return Double .hashCode (value );
979
- }
980
-
981
- @ Specialization (guards = "isEmpty(value)" )
982
- Object doEmptyString (@ SuppressWarnings ("unused" ) String value ) {
983
- return (BASE_EMPTY_UNICODE << IDTAG_SHIFT ) | IDTAG_SPECIAL ;
994
+ long doTuple (@ SuppressWarnings ("unused" ) PTuple value ,
995
+ @ Shared ("isBuiltin" ) @ Cached IsBuiltinClassProfile isBuiltin ,
996
+ @ Shared ("lenNode" ) @ Cached SequenceNodes .LenNode lenNode ) {
997
+ if (isBuiltin .profileIsAnyBuiltinObject (value ) && lenNode .execute (value ) == 0 ) {
998
+ return (BASE_EMPTY_TUPLE << IDTAG_SHIFT ) | IDTAG_SPECIAL ;
999
+ } else {
1000
+ return doGeneric (value );
1001
+ }
984
1002
}
985
1003
986
- @ Specialization (guards = "isEmpty(value)" )
987
- Object doEmptyString (@ SuppressWarnings ("unused" ) PString value ) {
988
- return (BASE_EMPTY_UNICODE << IDTAG_SHIFT ) | IDTAG_SPECIAL ;
1004
+ @ Specialization
1005
+ long doBytes (PBytes value ,
1006
+ @ Shared ("isBuiltin" ) @ Cached IsBuiltinClassProfile isBuiltin ,
1007
+ @ Shared ("lenNode" ) @ Cached SequenceNodes .LenNode lenNode ) {
1008
+ if (isBuiltin .profileIsAnyBuiltinObject (value ) && lenNode .execute (value ) == 0 ) {
1009
+ return (BASE_EMPTY_BYTES << IDTAG_SHIFT ) | IDTAG_SPECIAL ;
1010
+ } else {
1011
+ return doGeneric (value );
1012
+ }
989
1013
}
990
1014
991
- @ Specialization (guards = "isEmpty(value)" )
992
- Object doEmptyTuple (@ SuppressWarnings ("unused" ) PTuple value ) {
993
- return (BASE_EMPTY_TUPLE << IDTAG_SHIFT ) | IDTAG_SPECIAL ;
1015
+ @ Specialization
1016
+ long doFrozenSet (PFrozenSet value ,
1017
+ @ Shared ("isBuiltin" ) @ Cached IsBuiltinClassProfile isBuiltin ,
1018
+ @ Cached HashingCollectionNodes .LenNode lenNode ) {
1019
+ if (isBuiltin .profileIsAnyBuiltinObject (value ) && lenNode .execute (value ) == 0 ) {
1020
+ return (BASE_EMPTY_FROZENSET << IDTAG_SHIFT ) | IDTAG_SPECIAL ;
1021
+ } else {
1022
+ return doGeneric (value );
1023
+ }
994
1024
}
995
1025
996
- @ Specialization ( guards = "isEmpty(value)" )
997
- Object doEmptyBytes ( @ SuppressWarnings ( "unused" ) PBytes value ) {
998
- return ( BASE_EMPTY_BYTES << IDTAG_SHIFT ) | IDTAG_SPECIAL ;
1026
+ @ Specialization
1027
+ long doDouble ( double value ) {
1028
+ return Double . doubleToLongBits ( value ) << IDTAG_SHIFT | IDTAG_FLOAT ;
999
1029
}
1000
1030
1001
- @ Specialization (guards = "isEmpty(value)" )
1002
- Object doEmptyFrozenSet (@ SuppressWarnings ("unused" ) PFrozenSet value ) {
1003
- return (BASE_EMPTY_FROZENSET << IDTAG_SHIFT ) | IDTAG_SPECIAL ;
1031
+ @ Specialization
1032
+ long doPFloat (PFloat value ,
1033
+ @ Shared ("isBuiltin" ) @ Cached IsBuiltinClassProfile isBuiltin ) {
1034
+ if (isBuiltin .profileIsAnyBuiltinObject (value )) {
1035
+ return doDouble (value .getValue ());
1036
+ } else {
1037
+ return doGeneric (value );
1038
+ }
1004
1039
}
1005
1040
1006
- protected boolean isEmptyImmutableBuiltin (Object object ) {
1007
- return (object instanceof PTuple && isEmpty ((PTuple ) object )) ||
1008
- (object instanceof String && PGuards .isEmpty ((String ) object )) ||
1009
- (object instanceof PString && isEmpty ((PString ) object )) ||
1010
- (object instanceof PBytes && isEmpty ((PBytes ) object )) ||
1011
- (object instanceof PFrozenSet && isEmpty ((PFrozenSet ) object ));
1041
+ @ Specialization
1042
+ long doComplex (PComplex value ,
1043
+ @ Shared ("isBuiltin" ) @ Cached IsBuiltinClassProfile isBuiltin ) {
1044
+ if (isBuiltin .profileIsAnyBuiltinObject (value )) {
1045
+ int imag = Double .hashCode (value .getImag ());
1046
+ int real = Double .hashCode (value .getReal ());
1047
+ return (((real << 32 ) | imag ) << IDTAG_SHIFT ) | IDTAG_COMPLEX ;
1048
+ } else {
1049
+ return doGeneric (value );
1050
+ }
1012
1051
}
1013
1052
1014
- /**
1015
- * TODO: {@link #doId(String)} and {@link #doId(double)} are not quite right, because the
1016
- * hashCode will certainly collide with integer hashes. It should be good for comparisons
1017
- * between String and String id, though, it'll just look as if we interned all strings from
1018
- * the Python code's perspective.
1019
- */
1020
- @ Specialization (guards = "!isEmpty(value)" )
1021
- int doId (String value ) {
1022
- return value .hashCode ();
1053
+ @ Specialization
1054
+ long doPythonBuiltinClass (PythonBuiltinClass value ) {
1055
+ return doGeneric (value .getType ());
1023
1056
}
1024
1057
1025
1058
/**
@@ -1031,55 +1064,16 @@ int doId(String value) {
1031
1064
long doId (PCode obj ) {
1032
1065
RootCallTarget ct = obj .getRootCallTarget ();
1033
1066
if (ct != null ) {
1034
- return ct . hashCode ( );
1067
+ return doGeneric ( ct );
1035
1068
} else {
1036
- return obj . hashCode ( );
1069
+ return doGeneric ( obj );
1037
1070
}
1038
1071
}
1039
1072
1040
- @ Specialization (guards = {"!isPCode(obj)" , "!isPInt(obj)" , "!isPString(obj)" , "!isPFloat(obj)" , "!isEmptyImmutableBuiltin(obj)" })
1041
- long doId (PythonObject obj ) {
1042
- return getId (obj );
1043
- }
1044
-
1045
1073
@ Fallback
1046
1074
@ TruffleBoundary (allowInlining = true )
1047
- Object doId (Object obj ) {
1048
- return obj .hashCode ();
1049
- }
1050
-
1051
- protected boolean isEmpty (PSequence s ) {
1052
- if (lenNode == null ) {
1053
- CompilerDirectives .transferToInterpreterAndInvalidate ();
1054
- lenNode = insert (SequenceNodes .LenNode .create ());
1055
- }
1056
- return lenNode .execute (s ) == 0 ;
1057
- }
1058
-
1059
- protected boolean isEmpty (PHashingCollection s ) {
1060
- if (setLenNode == null ) {
1061
- CompilerDirectives .transferToInterpreterAndInvalidate ();
1062
- setLenNode = insert (HashingCollectionNodes .LenNode .create ());
1063
- }
1064
- return setLenNode .execute (s ) == 0 ;
1065
- }
1066
-
1067
- private long getId (PythonObject obj ) {
1068
- if (readId == null ) {
1069
- CompilerDirectives .transferToInterpreterAndInvalidate ();
1070
- readId = insert (ReadAttributeFromObjectNode .create ());
1071
- }
1072
- Object id = readId .execute (obj , ID_KEY );
1073
- if (id == NO_VALUE ) {
1074
- if (writeId == null ) {
1075
- CompilerDirectives .transferToInterpreterAndInvalidate ();
1076
- writeId = insert (WriteAttributeToObjectNode .create ());
1077
- }
1078
- id = getContext ().getNextGlobalId ();
1079
- writeId .execute (obj , ID_KEY , id );
1080
- }
1081
- assert id instanceof Long : "invalid object ID stored" ;
1082
- return (long ) id ;
1075
+ long doGeneric (Object obj ) {
1076
+ return System .identityHashCode (obj );
1083
1077
}
1084
1078
}
1085
1079
0 commit comments