107
107
import com .oracle .truffle .api .dsl .Specialization ;
108
108
import com .oracle .truffle .api .dsl .TypeSystemReference ;
109
109
import com .oracle .truffle .api .frame .VirtualFrame ;
110
+ import com .oracle .truffle .api .interop .UnsupportedMessageException ;
110
111
import com .oracle .truffle .api .library .CachedLibrary ;
111
112
import com .oracle .truffle .api .nodes .Node ;
112
113
import com .oracle .truffle .api .profiles .BranchProfile ;
@@ -570,90 +571,96 @@ abstract static class PrefixSuffixBaseNode extends PythonQuaternaryBuiltinNode {
570
571
@ Child private CastToSliceComponentNode castSliceComponentNode ;
571
572
@ Child private GetObjectArrayNode getObjectArrayNode ;
572
573
574
+ private static final String INVALID_RECEIVER = "Method requires a 'bytes' object, got '%p'" ;
575
+ private static final String INVALID_FIRST_ARG = "first arg must be bytes or a tuple of bytes, not %p" ;
576
+ private static final String INVALID_ELEMENT_TYPE = "a bytes-like object is required, not '%p'" ;
577
+
573
578
// common and specialized cases --------------------
574
579
575
- @ Specialization
576
- boolean doPrefixStartEnd (PIBytesLike self , PIBytesLike substr , int start , int end ,
577
- @ Shared ("toByteArrayNode" ) @ Cached SequenceStorageNodes .ToByteArrayNode toByteArrayNode ) {
578
- byte [] bytes = toByteArrayNode .execute (self .getSequenceStorage ());
579
- byte [] substrBytes = toByteArrayNode .execute (substr .getSequenceStorage ());
580
+ @ Specialization (guards = "!isPTuple(substr)" , limit = "2" )
581
+ boolean doPrefixStartEnd (PIBytesLike self , Object substr , int start , int end ,
582
+ @ CachedLibrary ("self" ) PythonObjectLibrary lib ,
583
+ @ CachedLibrary ("substr" ) PythonObjectLibrary substrLib ) {
584
+ byte [] bytes = getBytes (lib , self );
585
+ byte [] substrBytes = getBytes (substrLib , substr , INVALID_FIRST_ARG );
580
586
int len = bytes .length ;
581
587
return doIt (bytes , substrBytes , adjustStart (start , len ), adjustStart (end , len ));
582
588
}
583
589
584
- @ Specialization
585
- boolean doPrefixStart (PIBytesLike self , PIBytesLike substr , int start , @ SuppressWarnings ("unused" ) PNone end ,
586
- @ Shared ("toByteArrayNode" ) @ Cached SequenceStorageNodes .ToByteArrayNode toByteArrayNode ) {
587
- byte [] bytes = toByteArrayNode .execute (self .getSequenceStorage ());
588
- byte [] substrBytes = toByteArrayNode .execute (substr .getSequenceStorage ());
590
+ @ Specialization (guards = "!isPTuple(substr)" , limit = "2" )
591
+ boolean doPrefixStart (PIBytesLike self , Object substr , int start , @ SuppressWarnings ("unused" ) PNone end ,
592
+ @ CachedLibrary ("self" ) PythonObjectLibrary lib ,
593
+ @ CachedLibrary ("substr" ) PythonObjectLibrary substrLib ) {
594
+ byte [] bytes = getBytes (lib , self );
595
+ byte [] substrBytes = getBytes (substrLib , substr , INVALID_FIRST_ARG );
589
596
int len = bytes .length ;
590
597
return doIt (bytes , substrBytes , adjustStart (start , len ), len );
591
598
}
592
599
593
- @ Specialization
594
- boolean doPrefix (PIBytesLike self , PIBytesLike substr , @ SuppressWarnings ("unused" ) PNone start , @ SuppressWarnings ("unused" ) PNone end ,
595
- @ Shared ("toByteArrayNode" ) @ Cached SequenceStorageNodes .ToByteArrayNode toByteArrayNode ) {
596
- byte [] bytes = toByteArrayNode .execute (self .getSequenceStorage ());
597
- byte [] substrBytes = toByteArrayNode .execute (substr .getSequenceStorage ());
600
+ @ Specialization (guards = "!isPTuple(substr)" , limit = "2" )
601
+ boolean doPrefix (PIBytesLike self , Object substr , @ SuppressWarnings ("unused" ) PNone start , @ SuppressWarnings ("unused" ) PNone end ,
602
+ @ CachedLibrary ("self" ) PythonObjectLibrary lib ,
603
+ @ CachedLibrary ("substr" ) PythonObjectLibrary substrLib ) {
604
+ byte [] bytes = getBytes (lib , self );
605
+ byte [] substrBytes = getBytes (substrLib , substr , INVALID_FIRST_ARG );
598
606
return doIt (bytes , substrBytes , 0 , bytes .length );
599
607
}
600
608
601
- @ Specialization
609
+ @ Specialization ( limit = "2" )
602
610
boolean doTuplePrefixStartEnd (PIBytesLike self , PTuple substrs , int start , int end ,
603
- @ Shared ("toByteArrayNode" ) @ Cached SequenceStorageNodes .ToByteArrayNode toByteArrayNode ) {
604
- byte [] bytes = toByteArrayNode .execute (self .getSequenceStorage ());
611
+ @ CachedLibrary ("self" ) PythonObjectLibrary lib ,
612
+ @ CachedLibrary (limit = "16" ) PythonObjectLibrary substrLib ) {
613
+ byte [] bytes = getBytes (lib , self );
605
614
int len = bytes .length ;
606
- return doIt (bytes , substrs , adjustStart (start , len ), adjustStart (end , len ), toByteArrayNode );
615
+ return doIt (bytes , substrs , adjustStart (start , len ), adjustStart (end , len ), substrLib );
607
616
}
608
617
609
- @ Specialization
618
+ @ Specialization ( limit = "2" )
610
619
boolean doTuplePrefixStart (PIBytesLike self , PTuple substrs , int start , @ SuppressWarnings ("unused" ) PNone end ,
611
- @ Shared ("toByteArrayNode" ) @ Cached SequenceStorageNodes .ToByteArrayNode toByteArrayNode ) {
612
- byte [] bytes = toByteArrayNode .execute (self .getSequenceStorage ());
620
+ @ CachedLibrary ("self" ) PythonObjectLibrary lib ,
621
+ @ CachedLibrary (limit = "16" ) PythonObjectLibrary substrLib ) {
622
+ byte [] bytes = getBytes (lib , self );
613
623
int len = bytes .length ;
614
- return doIt (bytes , substrs , adjustStart (start , len ), len , toByteArrayNode );
624
+ return doIt (bytes , substrs , adjustStart (start , len ), len , substrLib );
615
625
}
616
626
617
- @ Specialization
627
+ @ Specialization ( limit = "2" )
618
628
boolean doTuplePrefix (PIBytesLike self , PTuple substrs , @ SuppressWarnings ("unused" ) PNone start , @ SuppressWarnings ("unused" ) PNone end ,
619
- @ Shared ("toByteArrayNode" ) @ Cached SequenceStorageNodes .ToByteArrayNode toByteArrayNode ) {
620
- byte [] bytes = toByteArrayNode .execute (self .getSequenceStorage ());
621
- return doIt (bytes , substrs , 0 , bytes .length , toByteArrayNode );
629
+ @ CachedLibrary ("self" ) PythonObjectLibrary lib ,
630
+ @ CachedLibrary (limit = "16" ) PythonObjectLibrary substrLib ) {
631
+ byte [] bytes = getBytes (lib , self );
632
+ return doIt (bytes , substrs , 0 , bytes .length , substrLib );
622
633
}
623
634
624
635
// generic cases --------------------
625
636
626
- @ Specialization (replaces = {"doPrefixStartEnd" , "doPrefixStart" , "doPrefix" })
627
- boolean doPrefixGeneric (VirtualFrame frame , PIBytesLike self , PIBytesLike substr , Object start , Object end ,
628
- @ Shared ("toByteArrayNode" ) @ Cached SequenceStorageNodes .ToByteArrayNode toByteArrayNode ) {
629
- byte [] bytes = toByteArrayNode .execute (self .getSequenceStorage ());
630
- byte [] substrBytes = toByteArrayNode .execute (substr .getSequenceStorage ());
637
+ @ Specialization (guards = "!isPTuple(substr)" , replaces = {"doPrefixStartEnd" , "doPrefixStart" , "doPrefix" }, limit = "200" )
638
+ boolean doPrefixGeneric (VirtualFrame frame , PIBytesLike self , Object substr , Object start , Object end ,
639
+ @ CachedLibrary ("self" ) PythonObjectLibrary lib ,
640
+ @ CachedLibrary ("substr" ) PythonObjectLibrary substrLib ) {
641
+ byte [] bytes = getBytes (lib , self );
642
+ byte [] substrBytes = getBytes (substrLib , substr , INVALID_FIRST_ARG );
631
643
int len = bytes .length ;
632
644
int istart = PGuards .isPNone (start ) ? 0 : castSlicePart (frame , start );
633
645
int iend = PGuards .isPNone (end ) ? len : adjustEnd (castSlicePart (frame , end ), len );
634
646
return doIt (bytes , substrBytes , adjustStart (istart , len ), adjustStart (iend , len ));
635
647
}
636
648
637
- @ Specialization (replaces = {"doTuplePrefixStartEnd" , "doTuplePrefixStart" , "doTuplePrefix" })
649
+ @ Specialization (replaces = {"doTuplePrefixStartEnd" , "doTuplePrefixStart" , "doTuplePrefix" }, limit = "2" )
638
650
boolean doTuplePrefixGeneric (VirtualFrame frame , PIBytesLike self , PTuple substrs , Object start , Object end ,
639
- @ Shared ("toByteArrayNode" ) @ Cached SequenceStorageNodes .ToByteArrayNode toByteArrayNode ) {
640
- byte [] bytes = toByteArrayNode .execute (self .getSequenceStorage ());
651
+ @ CachedLibrary ("self" ) PythonObjectLibrary lib ,
652
+ @ CachedLibrary (limit = "16" ) PythonObjectLibrary substrLib ) {
653
+ byte [] bytes = getBytes (lib , self );
641
654
int len = bytes .length ;
642
655
int istart = PGuards .isPNone (start ) ? 0 : castSlicePart (frame , start );
643
656
int iend = PGuards .isPNone (end ) ? len : adjustEnd (castSlicePart (frame , end ), len );
644
- return doIt (bytes , substrs , adjustStart (istart , len ), adjustStart (iend , len ), toByteArrayNode );
645
- }
646
-
647
- @ Specialization (guards = {"!isBytes(substr)" , "!isPTuple(substr)" })
648
- boolean doGeneric (@ SuppressWarnings ("unused" ) PIBytesLike self , Object substr , @ SuppressWarnings ("unused" ) Object start ,
649
- @ SuppressWarnings ("unused" ) Object end ) {
650
- throw raise (TypeError , "first arg must be bytes or a tuple of bytes, not %p" , substr );
657
+ return doIt (bytes , substrs , adjustStart (istart , len ), adjustStart (iend , len ), substrLib );
651
658
}
652
659
653
660
@ Specialization (guards = "!isBytes(self)" )
654
661
boolean doGeneric (@ SuppressWarnings ("unused" ) Object self , @ SuppressWarnings ("unused" ) Object substr ,
655
662
@ SuppressWarnings ("unused" ) Object start , @ SuppressWarnings ("unused" ) Object end ) {
656
- throw raise (TypeError , "Method requires a 'bytes' object, got '%p'" , self );
663
+ throw raise (TypeError , INVALID_RECEIVER , self );
657
664
}
658
665
659
666
// the actual operation; will be overridden by subclasses
@@ -662,22 +669,30 @@ protected boolean doIt(byte[] bytes, byte[] prefix, int start, int end) {
662
669
throw new IllegalStateException ("should not reach" );
663
670
}
664
671
665
- private boolean doIt (byte [] self , PTuple substrs , int start , int stop , SequenceStorageNodes . ToByteArrayNode toByteArrayNode ) {
672
+ private boolean doIt (byte [] self , PTuple substrs , int start , int stop , PythonObjectLibrary lib ) {
666
673
for (Object element : ensureGetObjectArrayNode ().execute (substrs )) {
667
- if (element instanceof PIBytesLike ) {
668
- if (doIt (self , toByteArrayNode .execute (((PIBytesLike ) element ).getSequenceStorage ()), start , stop )) {
669
- return true ;
670
- }
671
- } else {
672
- throw raise (TypeError , getErrorMessage (), element );
674
+ byte [] bytes = getBytes (lib , element , INVALID_ELEMENT_TYPE );
675
+ if (doIt (self , bytes , start , stop )) {
676
+ return true ;
673
677
}
674
678
}
675
679
return false ;
676
680
}
677
681
678
- protected String getErrorMessage () {
679
- CompilerDirectives .transferToInterpreter ();
680
- throw new IllegalStateException ("should not reach" );
682
+ private byte [] getBytes (PythonObjectLibrary lib , Object object ) {
683
+ try {
684
+ return lib .getBufferBytes (object );
685
+ } catch (UnsupportedMessageException e ) {
686
+ CompilerDirectives .transferToInterpreter ();
687
+ throw new IllegalStateException (e );
688
+ }
689
+ }
690
+
691
+ private byte [] getBytes (PythonObjectLibrary lib , Object object , String errorMessage ) {
692
+ if (!lib .isBuffer (object )) {
693
+ throw raise (TypeError , errorMessage , object );
694
+ }
695
+ return getBytes (lib , object );
681
696
}
682
697
683
698
// helper methods --------------------
@@ -723,8 +738,6 @@ private GetObjectArrayNode ensureGetObjectArrayNode() {
723
738
@ GenerateNodeFactory
724
739
public abstract static class StartsWithNode extends PrefixSuffixBaseNode {
725
740
726
- private static final String INVALID_ELEMENT_TYPE = "a bytes-like object is required, not '%p'" ;
727
-
728
741
@ Override
729
742
protected boolean doIt (byte [] bytes , byte [] prefix , int start , int end ) {
730
743
// start and end must be normalized indices for 'bytes'
@@ -741,11 +754,6 @@ protected boolean doIt(byte[] bytes, byte[] prefix, int start, int end) {
741
754
}
742
755
return true ;
743
756
}
744
-
745
- @ Override
746
- protected String getErrorMessage () {
747
- return INVALID_ELEMENT_TYPE ;
748
- }
749
757
}
750
758
751
759
// bytes.endswith(suffix[, start[, end]])
@@ -754,8 +762,6 @@ protected String getErrorMessage() {
754
762
@ GenerateNodeFactory
755
763
public abstract static class EndsWithNode extends PrefixSuffixBaseNode {
756
764
757
- private static final String INVALID_ELEMENT_TYPE = "a bytes-like object is required, not '%p'" ;
758
-
759
765
@ Override
760
766
protected boolean doIt (byte [] bytes , byte [] suffix , int start , int end ) {
761
767
// start and end must be normalized indices for 'bytes'
@@ -773,11 +779,6 @@ protected boolean doIt(byte[] bytes, byte[] suffix, int start, int end) {
773
779
}
774
780
return true ;
775
781
}
776
-
777
- @ Override
778
- protected String getErrorMessage () {
779
- return INVALID_ELEMENT_TYPE ;
780
- }
781
782
}
782
783
783
784
// bytes.index(x)
0 commit comments