On Sun, 11 Oct 2026 19:17:30 GMT, Liam Miller-Cushon <[email protected]> wrote:
>> This change adds Vector API methods that load the code units of a >> `java.lang.String` into a vector without copying, to allow processing a >> `String` with a vector loop instead of a scalar loop over `charAt`. >> >> As discussed in the [panama-dev@ thread 'String processing and Vector >> APIs'](https://mail.openjdk.org/archives/list/[email protected]/thread/YSPX3TBXZTZEFZNXWDYOZCWLUQPC62P6/), >> one motivating use-case is a regex library that wants to accelerate scans >> for character classes. Implementing these methods outside the JDK using >> scalar `charAt` loops is slower than a vectorized implementation. >> >> ### Goals >> >> * Performance - to get the full performance benefit, these APIs should avoid >> copies or re-encoding, since a copy or re-encoding would be O(n) and reduce >> the performance benefit of a vector loop >> * Encapsulation - encapsulation of `java.lang.String` internals must be >> preserved, including preventing modification of the String's backing >> storage, and also preserving encapsulation of String implementation details >> (like the exact encoding under Compact Strings) >> >> ### Design >> >> >> // ByteVector >> static boolean compatibleWith(String string, Charset charset) >> static ByteVector fromString(VectorSpecies<Byte> species, String string, >> Charset charset, int offset) >> static ByteVector fromString(VectorSpecies<Byte> species, String string, >> Charset charset, int offset, VectorMask<Byte> m) >> >> // ShortVector >> static boolean compatibleWith(String string, Charset charset) >> static ShortVector fromString(VectorSpecies<Short> species, String string, >> Charset charset, int offset) >> static ShortVector fromString(VectorSpecies<Short> species, String string, >> Charset charset, int offset, VectorMask<Short> m) >> >> >> `compatibleWith` runs in constant time. If it returns `true`, `fromString` >> loads the String's backing storage without a copy, if it returns false >> `fromString` will throw `IllegalArgumentException` and callers are expected >> to handle falling back to a scalar loop. >> >> >> if (ByteVector.compatibleWith(s, ISO_8859_1)) { >> // ... >> } else if (ShortVector.compatibleWith(s, UTF_16)) { >> // ... >> } else { >> // scalar fallback >> } >> >> >> These methods deal with strings in terms of code units, not encoded bytes. >> `ShortVector.fromString` loads the String's UTF-16 code units in native byte >> order without a BOM and any unpaired surrogates preserved, providing the >> same values as a scalar loop over `charAt`. Guaranteeing a well-formed >> encoding would... > > Liam Miller-Cushon has updated the pull request with a new target base due to > a merge or a rebase. The incremental webrev excludes the unrelated changes > brought in by the merge/rebase. The pull request contains 13 additional > commits since the last revision: > > - Clean up unused import > - Merge remote-tracking branch 'origin/master' into short-vector > - Move asReadOnlyMemorySegment to String > - Add a benchmark > > Also adjust javadoc, convert test to JUnit 5, other small adjustments > - javadoc > - Move access to jdk.internal.foreign.StringSupport > - Make test inputs longer > - Test coverage > - Move to X-Vector.java.template, update javadoc, add masked overloads > - ShortVector.compatibleWith > - ... and 3 more: https://git.openjdk.org/jdk/compare/e420793a...1c6ff6ab src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java line 497: > 495: * {@return a {@linkplain MemorySegment#isReadOnly() read-only} > {@link MemorySegment} of the given {@link String}} > 496: */ > 497: MemorySegment asReadOnlyMemorySegment(String str); I remember that, back when we started adding fast paths to bypass copying string contents into a temp byte array, we deliberately wanted not to expose the string contents directly as a memory segment, as we were afraid that this thing would get used in 100 other places in the JDK, and we'd lose a bit of control. I'm not sure how to square this circle in this new case -- because what you want is to create a vector given a segment/byte array, and vector is incubating, so references to vector API types from String are not really possible... src/java.base/share/classes/jdk/internal/foreign/SegmentFactories.java line 94: > 92: } > 93: > 94: public static OfByte fromArrayReadOnly(byte[] arr) { Why this? Is this to avoid calling "asReadOnly" ? src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java line 3858: > 3856: checkCompatibleWith(string, charset); > 3857: offset = checkFromIndexSize(offset, species.length(), > string.length()); > 3858: return fromMemorySegment(species, > StringSupport.asReadOnlyMemorySegment(string), offset, > ByteOrder.nativeOrder()); I notice here that you have two options: get a segment view and use that... or obtain the byte[] and pass that to fromArray. I'm not sure which is better -- the segment path allows you to model it as a read only segment, but it's also less direct. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/32373#discussion_r4270151629 PR Review Comment: https://git.openjdk.org/jdk/pull/32373#discussion_r4270159979 PR Review Comment: https://git.openjdk.org/jdk/pull/32373#discussion_r4270177631
