Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 17 additions & 12 deletions src/java.base/share/classes/jdk/internal/foreign/StringSupport.java
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,8 @@ public static int strlenByte(final AbstractMemorySegmentImpl segment,
final long toOffset) {
final long length = toOffset - fromOffset;
segment.checkBounds(fromOffset, length);
if (length == 0) {
// The state has to be checked explicitly for zero-length segments
if (length < Byte.BYTES) {
// There can be no null terminator present
segment.scope.checkValidState();
throw nullNotFound(segment, fromOffset, toOffset);
}
Expand Down Expand Up @@ -164,7 +164,8 @@ public static int strlenShort(final AbstractMemorySegmentImpl segment,
final long toOffset) {
final long length = toOffset - fromOffset;
segment.checkBounds(fromOffset, length);
if (length == 0) {
if (length < Short.BYTES) {
// There can be no null terminator present
segment.scope.checkValidState();
throw nullNotFound(segment, fromOffset, toOffset);
}
Expand Down Expand Up @@ -199,19 +200,23 @@ public static int strlenInt(final AbstractMemorySegmentImpl segment,
final long toOffset) {
final long length = toOffset - fromOffset;
segment.checkBounds(fromOffset, length);
if (length == 0) {
if (length < Integer.BYTES) {
// There can be no null terminator present
segment.scope.checkValidState();
throw nullNotFound(segment, fromOffset, toOffset);
}
final long longBytes = length & LONG_MASK;
final long longLimit = fromOffset + longBytes;
long offset = fromOffset;
for (; offset < longLimit; offset += Long.BYTES) {
long val = SCOPED_MEMORY_ACCESS.getLongUnaligned(segment.sessionImpl(), segment.unsafeGetBase(), segment.unsafeGetOffset() + offset, !Architecture.isLittleEndian());
if (mightContainZeroInt(val)) {
for (int j = 0; j < Long.BYTES; j += Integer.BYTES) {
if (SCOPED_MEMORY_ACCESS.getIntUnaligned(segment.sessionImpl(), segment.unsafeGetBase(), segment.unsafeGetOffset() + offset + j, !Architecture.isLittleEndian()) == 0) {
return requireWithinStringSize(offset + j - fromOffset, segment, fromOffset, toOffset);
// For quad byte strings, it does not pay off to use long scanning on x64
if (!Architecture.isX64()) {
final long longBytes = length & LONG_MASK;
final long longLimit = fromOffset + longBytes;
for (; offset < longLimit; offset += Long.BYTES) {
long val = SCOPED_MEMORY_ACCESS.getLongUnaligned(segment.sessionImpl(), segment.unsafeGetBase(), segment.unsafeGetOffset() + offset, !Architecture.isLittleEndian());
if (mightContainZeroInt(val)) {
for (int j = 0; j < Long.BYTES; j += Integer.BYTES) {
if (SCOPED_MEMORY_ACCESS.getIntUnaligned(segment.sessionImpl(), segment.unsafeGetBase(), segment.unsafeGetOffset() + offset + j, !Architecture.isLittleEndian()) == 0) {
return requireWithinStringSize(offset + j - fromOffset, segment, fromOffset, toOffset);
}
}
}
}
Expand Down
24 changes: 12 additions & 12 deletions test/micro/org/openjdk/bench/java/lang/foreign/InternalStrLen.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,20 +55,20 @@
"--enable-native-access=ALL-UNNAMED"})
public class InternalStrLen {

private AbstractMemorySegmentImpl singleByteSegment;
private AbstractMemorySegmentImpl singleByteSegmentMisaligned;
private AbstractMemorySegmentImpl doubleByteSegment;
private AbstractMemorySegmentImpl quadByteSegment;
private MemorySegment singleByteSegment;
private MemorySegment singleByteSegmentMisaligned;
private MemorySegment doubleByteSegment;
private MemorySegment quadByteSegment;

@Param({"1", "4", "16", "251", "1024"})
int size;

@Setup
public void setup() {
var arena = Arena.ofAuto();
singleByteSegment = (AbstractMemorySegmentImpl) arena.allocate((size + 1L) * Byte.BYTES);
doubleByteSegment = (AbstractMemorySegmentImpl) arena.allocate((size + 1L) * Short.BYTES);
quadByteSegment = (AbstractMemorySegmentImpl) arena.allocate((size + 1L) * Integer.BYTES);
singleByteSegment = arena.allocate((size + 1L) * Byte.BYTES);
doubleByteSegment = arena.allocate((size + 1L) * Short.BYTES);
quadByteSegment = arena.allocate((size + 1L) * Integer.BYTES);
Stream.of(singleByteSegment, doubleByteSegment, quadByteSegment)
.forEach(s -> IntStream.range(0, (int) s.byteSize() - 1)
.forEach(i -> s.set(
Expand All @@ -79,7 +79,7 @@ public void setup() {
singleByteSegment.set(ValueLayout.JAVA_BYTE, singleByteSegment.byteSize() - Byte.BYTES, (byte) 0);
doubleByteSegment.set(ValueLayout.JAVA_SHORT, doubleByteSegment.byteSize() - Short.BYTES, (short) 0);
quadByteSegment.set(ValueLayout.JAVA_INT, quadByteSegment.byteSize() - Integer.BYTES, 0);
singleByteSegmentMisaligned = (AbstractMemorySegmentImpl) arena.allocate(singleByteSegment.byteSize() + 1).
singleByteSegmentMisaligned = arena.allocate(singleByteSegment.byteSize() + 1).
asSlice(1);
MemorySegment.copy(singleByteSegment, 0, singleByteSegmentMisaligned, 0, singleByteSegment.byteSize());
}
Expand All @@ -106,22 +106,22 @@ public int elementQuad() {

@Benchmark
public int chunkedSingle() {
return StringSupport.strlenByte(singleByteSegment, 0, singleByteSegment.byteSize());
return StringSupport.strlenByte((AbstractMemorySegmentImpl) singleByteSegment, 0, singleByteSegment.byteSize());
}

@Benchmark
public int chunkedSingleMisaligned() {
return StringSupport.strlenByte(singleByteSegmentMisaligned, 0, singleByteSegment.byteSize());
return StringSupport.strlenByte((AbstractMemorySegmentImpl) singleByteSegmentMisaligned, 0, singleByteSegment.byteSize());
}

@Benchmark
public int chunkedDouble() {
return StringSupport.strlenShort(doubleByteSegment, 0, doubleByteSegment.byteSize());
return StringSupport.strlenShort((AbstractMemorySegmentImpl) doubleByteSegment, 0, doubleByteSegment.byteSize());
}

@Benchmark
public int changedElementQuad() {
return StringSupport.strlenInt(quadByteSegment, 0, quadByteSegment.byteSize());
return StringSupport.strlenInt((AbstractMemorySegmentImpl) quadByteSegment, 0, quadByteSegment.byteSize());
}

// These are the legacy methods
Expand Down