75
75
import com .oracle .graal .python .builtins .Builtin ;
76
76
import com .oracle .graal .python .builtins .CoreFunctions ;
77
77
import com .oracle .graal .python .builtins .PythonBuiltins ;
78
- import com .oracle .graal .python .builtins .PythonImmutableBuiltinType ;
79
78
import com .oracle .graal .python .builtins .objects .PNone ;
80
79
import com .oracle .graal .python .builtins .objects .PNotImplemented ;
81
80
import com .oracle .graal .python .builtins .objects .bytes .PBytes ;
@@ -634,6 +633,19 @@ public abstract static class IdNode extends PythonBuiltinNode {
634
633
* </pre>
635
634
*/
636
635
private static long KNOWN_OBJECTS_COUNT = 4L ;
636
+ // borrowed logic from pypy
637
+ // -1 - (-maxunicode-1): unichar
638
+ // 0 - 255: char
639
+ // 256: empty string
640
+ // 257: empty unicode
641
+ // 258: empty tuple
642
+ // 259: empty frozenset
643
+ private static long BASE_EMPTY_BYTES = 256 ;
644
+ private static long BASE_EMPTY_UNICODE = 257 ;
645
+ private static long BASE_EMPTY_TUPLE = 258 ;
646
+ private static long BASE_EMPTY_FROZENSET = 259 ;
647
+ private static long IDTAG_SPECIAL = 11 ;
648
+ private static int IDTAG_SHIFT = 4 ;
637
649
638
650
/**
639
651
* The next available global id. We reserve space for all integers to be their own id +
@@ -665,17 +677,6 @@ long doId(int integer) {
665
677
return integer + KNOWN_OBJECTS_COUNT ;
666
678
}
667
679
668
- /**
669
- * TODO: {@link #doId(String)} and {@link #doId(double)} are not quite right, because the
670
- * hashCode will certainly collide with integer hashes. It should be good for comparisons
671
- * between String and String id, though, it'll just look as if we interned all strings from
672
- * the Python code's perspective.
673
- */
674
- @ Specialization
675
- int doId (String value ) {
676
- return value .hashCode ();
677
- }
678
-
679
680
@ Specialization
680
681
Object doId (PInt value ) {
681
682
try {
@@ -691,26 +692,49 @@ int doId(double value) {
691
692
}
692
693
693
694
@ Specialization (guards = "isEmpty(value)" )
694
- Object doEmptyTuple (PTuple value ) {
695
- return getId (value , PythonImmutableBuiltinType .PTuple );
695
+ Object doEmptyString (@ SuppressWarnings ("unused" ) String value ) {
696
+ return (BASE_EMPTY_UNICODE << IDTAG_SHIFT ) | IDTAG_SPECIAL ;
697
+ }
698
+
699
+ @ Specialization (guards = "isEmpty(value)" )
700
+ Object doEmptyString (@ SuppressWarnings ("unused" ) PString value ) {
701
+ return (BASE_EMPTY_UNICODE << IDTAG_SHIFT ) | IDTAG_SPECIAL ;
696
702
}
697
703
698
704
@ Specialization (guards = "isEmpty(value)" )
699
- Object doEmptyBytes ( PBytes value ) {
700
- return getId ( value , PythonImmutableBuiltinType . PBytes ) ;
705
+ Object doEmptyTuple ( @ SuppressWarnings ( "unused" ) PTuple value ) {
706
+ return ( BASE_EMPTY_TUPLE << IDTAG_SHIFT ) | IDTAG_SPECIAL ;
701
707
}
702
708
703
709
@ Specialization (guards = "isEmpty(value)" )
704
- Object doEmptyFrozenSet (PFrozenSet value ) {
705
- return getId (value , PythonImmutableBuiltinType .PFrozenSet );
710
+ Object doEmptyBytes (@ SuppressWarnings ("unused" ) PBytes value ) {
711
+ return (BASE_EMPTY_BYTES << IDTAG_SHIFT ) | IDTAG_SPECIAL ;
712
+ }
713
+
714
+ @ Specialization (guards = "isEmpty(value)" )
715
+ Object doEmptyFrozenSet (@ SuppressWarnings ("unused" ) PFrozenSet value ) {
716
+ return (BASE_EMPTY_FROZENSET << IDTAG_SHIFT ) | IDTAG_SPECIAL ;
706
717
}
707
718
708
719
protected boolean isEmptyImmutableBuiltin (Object object ) {
709
720
return (object instanceof PTuple && PGuards .isEmpty ((PTuple ) object )) ||
721
+ (object instanceof String && PGuards .isEmpty ((String ) object )) ||
722
+ (object instanceof PString && PGuards .isEmpty ((PString ) object )) ||
710
723
(object instanceof PBytes && PGuards .isEmpty ((PBytes ) object )) ||
711
724
(object instanceof PFrozenSet && PGuards .isEmpty ((PFrozenSet ) object ));
712
725
}
713
726
727
+ /**
728
+ * TODO: {@link #doId(String)} and {@link #doId(double)} are not quite right, because the
729
+ * hashCode will certainly collide with integer hashes. It should be good for comparisons
730
+ * between String and String id, though, it'll just look as if we interned all strings from
731
+ * the Python code's perspective.
732
+ */
733
+ @ Specialization (guards = "!isEmpty(value)" )
734
+ int doId (String value ) {
735
+ return value .hashCode ();
736
+ }
737
+
714
738
@ Specialization (guards = {"!isPInt(obj)" , "!isPString(obj)" , "!isPFloat(obj)" , "!isEmptyImmutableBuiltin(obj)" })
715
739
Object doId (PythonObject obj ) {
716
740
return getId (obj );
@@ -722,22 +746,14 @@ Object doId(Object obj) {
722
746
}
723
747
724
748
private Object getId (PythonObject obj ) {
725
- return getId (obj , null );
726
- }
727
-
728
- private Object getId (PythonObject obj , PythonImmutableBuiltinType immutableType ) {
729
749
if (readId == null ) {
730
750
CompilerDirectives .transferToInterpreterAndInvalidate ();
731
751
readId = insert (ReadAttributeFromObjectNode .create ());
732
752
writeId = insert (WriteAttributeToObjectNode .create ());
733
753
}
734
754
Object id = readId .execute (obj , ID_KEY );
735
755
if (id == NO_VALUE ) {
736
- if (immutableType != null ) {
737
- id = getContext ().getEmptyImmutableObjectGlobalId (immutableType );
738
- } else {
739
- id = getContext ().getNextGlobalId ();
740
- }
756
+ id = getContext ().getNextGlobalId ();
741
757
writeId .execute (obj , ID_KEY , id );
742
758
}
743
759
return id ;
0 commit comments