Skip to content

Commit

Permalink
Initial push
Browse files Browse the repository at this point in the history
  • Loading branch information
mcimadamore committed Dec 19, 2024
1 parent 8efc558 commit 0b8117d
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 1 deletion.
12 changes: 12 additions & 0 deletions src/java.base/share/classes/jdk/internal/foreign/LayoutPath.java
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,18 @@ public VarHandle dereferenceHandle(boolean adapt) {
return handle;
}

public VarHandle arrayElementHandle() {
Utils.checkElementAlignment(layout, "Element layout size is not multiple of alignment");
long[] arrayStrides = new long[strides.length + 1];
long[] arrayBounds = new long[strides.length + 1];
System.arraycopy(strides, 0, arrayStrides, 1, strides.length);
System.arraycopy(bounds, 0, arrayBounds, 1, bounds.length);
arrayStrides[0] = layout.byteSize();
arrayBounds[0] = (Long.MAX_VALUE - 1) / layout.byteSize(); // avoid overflows
LayoutPath arrayPath = nestedPath(layout, offset, arrayStrides, arrayBounds, derefAdapters, enclosing);
return arrayPath.dereferenceHandle();
}

@ForceInline
private static long addScaledOffset(long base, long index, long stride, long bound) {
Objects.checkIndex(index, bound);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,8 @@ public VarHandle varHandleInternal(PathElement... elements) {
}

public VarHandle arrayElementVarHandle(PathElement... elements) {
return MethodHandles.collectCoordinates(varHandle(elements), 1, scaleHandle());
return computePathOp(LayoutPath.rootPath((MemoryLayout) this), LayoutPath::arrayElementHandle,
Set.of(), elements);
}

public MethodHandle sliceHandle(PathElement... elements) {
Expand Down
107 changes: 107 additions & 0 deletions test/micro/org/openjdk/bench/java/lang/foreign/Alignment.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package org.openjdk.bench.java.lang.foreign;

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;

import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.util.concurrent.TimeUnit;

import static java.lang.foreign.MemoryLayout.sequenceLayout;
import static java.lang.foreign.ValueLayout.JAVA_LONG;
import static java.lang.foreign.ValueLayout.JAVA_LONG_UNALIGNED;

@BenchmarkMode(Mode.AverageTime)
@Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@State(org.openjdk.jmh.annotations.Scope.Thread)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Fork(value = 3)
public class Alignment {
// base offset = 0
static final VarHandle ALIGNED = MethodHandles.insertCoordinates(JAVA_LONG.arrayElementVarHandle(), 1, 0).withInvokeExactBehavior();
static final VarHandle UNALIGNED = MethodHandles.insertCoordinates(JAVA_LONG_UNALIGNED.arrayElementVarHandle(), 1, 0).withInvokeExactBehavior();
// base offset = 8
static final VarHandle NEXT_ALIGNED = MethodHandles.insertCoordinates(JAVA_LONG.arrayElementVarHandle(), 1, JAVA_LONG.byteSize()).withInvokeExactBehavior();
static final VarHandle NEXT_UNALIGNED = MethodHandles.insertCoordinates(JAVA_LONG_UNALIGNED.arrayElementVarHandle(), 1, JAVA_LONG.byteSize()).withInvokeExactBehavior();

static final long HAYSTACK = 30_000_000L;
static final long NEEDLE_INDEX = 934L;
static final long NEEDLE = 456L;

final MemorySegment segment = Arena.global().allocate(sequenceLayout(HAYSTACK, JAVA_LONG));

{
ALIGNED.set(segment, NEEDLE_INDEX, NEEDLE);
}

// 6 different ways to loop over segment[1, size):

@Benchmark
public void findUnaligned() {
long size = segment.byteSize() / JAVA_LONG.byteSize();
int numFound = 0;
for (long i = 1; i < size; ++i) {
if ((long) UNALIGNED.get(segment, i) == NEEDLE) ++numFound;
}
if (numFound != 1) throw new IllegalStateException();
}

@Benchmark
public void findAligned() {
long size = segment.byteSize() / JAVA_LONG.byteSize();
int numFound = 0;
for (long i = 1; i < size; ++i) {
if ((long) ALIGNED.get(segment, i) == NEEDLE) ++numFound;
}
if (numFound != 1) throw new IllegalStateException();
}

@Benchmark
public void findUnalignedPlusOne() {
long size = segment.byteSize() / JAVA_LONG.byteSize();
int numFound = 0;
for (long i = 0; i < size - 1; ++i) {
if ((long) UNALIGNED.get(segment, i + 1) == NEEDLE) ++numFound;
}
if (numFound != 1) throw new IllegalStateException();
}

@Benchmark
public void findAlignedPlusOne() {
long size = segment.byteSize() / JAVA_LONG.byteSize();
int numFound = 0;
for (long i = 0; i < size - 1; ++i) {
if ((long) ALIGNED.get(segment, i + 1) == NEEDLE) ++numFound;
}
if (numFound != 1) throw new IllegalStateException();
}

@Benchmark
public void findUnalignedNext() {
long size = segment.byteSize() / JAVA_LONG.byteSize();
int numFound = 0;
for (long i = 0; i < size - 1; ++i) {
if ((long) NEXT_UNALIGNED.get(segment, i) == NEEDLE) ++numFound;
}
if (numFound != 1) throw new IllegalStateException();
}

@Benchmark
public void findAlignedNext() {
long size = segment.byteSize() / JAVA_LONG.byteSize();
int numFound = 0;
for (long i = 0; i < size - 1; ++i) {
if ((long) NEXT_ALIGNED.get(segment, i) == NEEDLE) ++numFound;
}
if (numFound != 1) throw new IllegalStateException();
}
}

0 comments on commit 0b8117d

Please sign in to comment.