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

Reply via email to