1
1
package json .ext ;
2
2
3
3
import java .io .IOException ;
4
+ import javax .naming .directory .NoSuchAttributeException ;
4
5
5
6
import jdk .incubator .vector .ByteVector ;
6
7
import jdk .incubator .vector .VectorMask ;
7
8
import jdk .incubator .vector .VectorOperators ;
8
9
import jdk .incubator .vector .VectorSpecies ;
10
+ import jdk .jfr .RecordingState ;
9
11
10
12
public class VectorizedEscapeScanner implements EscapeScanner {
11
13
public static EscapeScanner .ScalarEscapeScanner FALLBACK = new EscapeScanner .ScalarEscapeScanner (StringEncoder .ESCAPE_TABLE );
12
14
13
- // private VectorMask<Byte> needsEscape = null;
14
- // private int chunkStart = 0;
15
-
16
15
@ Override
17
- public boolean scan (State state ) throws IOException {
16
+ public boolean scan (State _state ) throws IOException {
18
17
VectorSpecies <Byte > species = ByteVector .SPECIES_PREFERRED ;
19
18
20
- // if (needsEscape != null) {
21
- // if (needsEscape.anyTrue()) {
22
- // int firstEscapeIndex = needsEscape.firstTrue();
23
- // needsEscape = needsEscape.andNot(VectorMask.fromLong(species, 1L << firstEscapeIndex));
24
- // state.pos = chunkStart + firstEscapeIndex ;
25
- // return true;
26
- // } else {
27
- // needsEscape = null ;
28
- // }
29
- // }
19
+ VectorizedState state = ( VectorizedState ) _state ;
20
+
21
+ if ( state . hasMatches ) {
22
+ if ( state . mask > 0 ) {
23
+ return nextMatch ( state ) ;
24
+ } else {
25
+ state . hasMatches = false ;
26
+ state . pos = state . chunkStart + species . length () ;
27
+ }
28
+ }
30
29
31
30
while ((state .ptr + state .pos ) + species .length () < state .len ) {
32
31
ByteVector chunk = ByteVector .fromArray (species , state .ptrBytes , state .ptr + state .pos );
@@ -41,17 +40,41 @@ public boolean scan(State state) throws IOException {
41
40
42
41
VectorMask <Byte > needsEscape = chunk .eq (ByteVector .broadcast (species , '\\' )).or (tooLowOrDblQuote ).and (negative );
43
42
if (needsEscape .anyTrue ()) {
44
- // chunkStart = state.ptr + state.pos;
45
- int firstEscapeIndex = needsEscape .firstTrue ();
46
- // Clear the bit at firstEscapeIndex to avoid scanning the same byte again
47
- // needsEscape = needsEscape.andNot(VectorMask.fromLong(species, 1L << firstEscapeIndex));
48
- state .pos += firstEscapeIndex ;
49
- return true ;
43
+ state .hasMatches = true ;
44
+ state .chunkStart = state .ptr + state .pos ;
45
+ state .mask = needsEscape .toLong ();
46
+
47
+ return nextMatch (state );
50
48
}
51
49
52
50
state .pos += species .length ();
53
51
}
54
52
55
53
return FALLBACK .scan (state );
56
54
}
55
+
56
+ private boolean nextMatch (VectorizedState state ) {
57
+ int index = Long .numberOfTrailingZeros (state .mask );
58
+ state .mask &= (state .mask - 1 );
59
+ state .pos = state .chunkStart + index ;
60
+ return true ;
61
+ }
62
+
63
+ @ Override
64
+ public EscapeScanner .State createState (byte [] ptrBytes , int ptr , int len , int beg ) {
65
+ VectorizedState state = new VectorizedState ();
66
+ state .ptrBytes = ptrBytes ;
67
+ state .ptr = ptr ;
68
+ state .len = len ;
69
+ state .beg = beg ;
70
+ state .pos = 0 ;
71
+ return state ;
72
+ }
73
+
74
+ private static class VectorizedState extends State {
75
+ private long mask ;
76
+ private int chunkStart = 0 ;
77
+ // private int lastMatchingIndex;
78
+ private boolean hasMatches ;
79
+ }
57
80
}
0 commit comments