Skip to content

Commit

Permalink
Initial push
Browse files Browse the repository at this point in the history
  • Loading branch information
mcimadamore committed Oct 23, 2024
1 parent 7312eea commit ed4775c
Show file tree
Hide file tree
Showing 3 changed files with 201 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,6 @@ public class BindingSpecializer {
private final MethodType leafType;

private int[] leafArgSlots;
private int[] scopeSlots;
private int curScopeLocalIdx = -1;
private int returnAllocatorIdx = -1;
private int contextIdx = -1;
private int returnBufferIdx = -1;
Expand Down Expand Up @@ -266,21 +264,6 @@ private void specialize() {
// allocator passed to us for allocating the return MS (downcalls only)
if (callingSequence.forDowncall()) {
returnAllocatorIdx = 0; // first param

// for downcalls we also acquire/release scoped parameters before/after the call
// create a bunch of locals here to keep track of their scopes (to release later)
int[] initialScopeSlots = new int[callerMethodType.parameterCount()];
int numScopes = 0;
for (int i = 0; i < callerMethodType.parameterCount(); i++) {
if (shouldAcquire(i)) {
int scopeLocal = cb.allocateLocal(REFERENCE);
initialScopeSlots[numScopes++] = scopeLocal;
cb.loadConstant(null);
cb.storeLocal(REFERENCE, scopeLocal); // need to initialize all scope locals here in case an exception occurs
}
}
scopeSlots = Arrays.copyOf(initialScopeSlots, numScopes); // fit to size
curScopeLocalIdx = 0; // used from emitGetInput
}

// create a Binding.Context for this call
Expand Down Expand Up @@ -453,7 +436,13 @@ private boolean shouldAcquire(int paramIndex) {
private void emitCleanup() {
emitCloseContext();
if (callingSequence.forDowncall()) {
emitReleaseScopes();
for (int paramIndex = 0 ; paramIndex < callerMethodType.parameterCount() ; paramIndex++) {
Class<?> highLevelType = callerMethodType.parameterType(paramIndex);
if (shouldAcquire(paramIndex)) {
cb.loadLocal(TypeKind.from(highLevelType), cb.parameterSlot(paramIndex));
emitReleaseScope();
}
}
}
}

Expand Down Expand Up @@ -498,43 +487,13 @@ private void emitGetInput() {
private void emitAcquireScope() {
cb.checkcast(CD_AbstractMemorySegmentImpl);
cb.invokevirtual(CD_AbstractMemorySegmentImpl, "sessionImpl", MTD_SESSION_IMPL);
Label skipAcquire = cb.newLabel();
Label end = cb.newLabel();

// start with 1 scope to maybe acquire on the stack
assert curScopeLocalIdx != -1;
boolean hasOtherScopes = curScopeLocalIdx != 0;
for (int i = 0; i < curScopeLocalIdx; i++) {
cb.dup(); // dup for comparison
cb.loadLocal(REFERENCE, scopeSlots[i]);
cb.if_acmpeq(skipAcquire);
}

// 1 scope to acquire on the stack
cb.dup();
int nextScopeLocal = scopeSlots[curScopeLocalIdx++];
// call acquire first here. So that if it fails, we don't call release
cb.invokevirtual(CD_MemorySessionImpl, "acquire0", MTD_ACQUIRE0); // call acquire on the other
cb.storeLocal(REFERENCE, nextScopeLocal); // store off one to release later

if (hasOtherScopes) { // avoid ASM generating a bunch of nops for the dead code
cb.goto_(end);

cb.labelBinding(skipAcquire);
cb.pop(); // drop scope
}

cb.labelBinding(end);
cb.invokevirtual(CD_MemorySessionImpl, "acquire0", MTD_ACQUIRE0);
}

private void emitReleaseScopes() {
for (int scopeLocal : scopeSlots) {
cb.loadLocal(REFERENCE, scopeLocal);
cb.ifThen(Opcode.IFNONNULL, ifCb -> {
ifCb.loadLocal(REFERENCE, scopeLocal);
ifCb.invokevirtual(CD_MemorySessionImpl, "release0", MTD_RELEASE0);
});
}
private void emitReleaseScope() {
cb.checkcast(CD_AbstractMemorySegmentImpl);
cb.invokevirtual(CD_AbstractMemorySegmentImpl, "sessionImpl", MTD_SESSION_IMPL);
cb.invokevirtual(CD_MemorySessionImpl, "release0", MTD_RELEASE0);
}

private void emitSaveReturnValue(Class<?> storeType) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
package org.openjdk.bench.java.lang.foreign;

import org.openjdk.jmh.annotations.*;

import java.lang.foreign.*;
import java.lang.invoke.*;
import java.util.concurrent.TimeUnit;

/*
Windows 11, Ryzen 7950X3D, JDK 24-beta+20 (similar results on JDK 23)
Benchmark Mode Cnt Score Error Units
FFMEscapeAnalysisTest.noop_params0 avgt 3 3,133 ? 1,954 ns/op
FFMEscapeAnalysisTest.noop_params0:gc.alloc.rate avgt 3 0,007 ? 0,001 MB/sec
FFMEscapeAnalysisTest.noop_params0:gc.alloc.rate.norm avgt 3 ? 10?? B/op
FFMEscapeAnalysisTest.noop_params0:gc.count avgt 3 ? 0 counts
FFMEscapeAnalysisTest.noop_params1 avgt 3 3,051 ? 0,051 ns/op
FFMEscapeAnalysisTest.noop_params1:gc.alloc.rate avgt 3 0,007 ? 0,001 MB/sec
FFMEscapeAnalysisTest.noop_params1:gc.alloc.rate.norm avgt 3 ? 10?? B/op
FFMEscapeAnalysisTest.noop_params1:gc.count avgt 3 ? 0 counts
FFMEscapeAnalysisTest.noop_params2 avgt 3 3,048 ? 0,218 ns/op
FFMEscapeAnalysisTest.noop_params2:gc.alloc.rate avgt 3 0,007 ? 0,001 MB/sec
FFMEscapeAnalysisTest.noop_params2:gc.alloc.rate.norm avgt 3 ? 10?? B/op
FFMEscapeAnalysisTest.noop_params2:gc.count avgt 3 ? 0 counts
FFMEscapeAnalysisTest.noop_params3 avgt 3 3,110 ? 1,973 ns/op
FFMEscapeAnalysisTest.noop_params3:gc.alloc.rate avgt 3 2,368 ? 74,631 MB/sec
FFMEscapeAnalysisTest.noop_params3:gc.alloc.rate.norm avgt 3 0,008 ? 0,253 B/op
FFMEscapeAnalysisTest.noop_params3:gc.count avgt 3 ? 0 counts
FFMEscapeAnalysisTest.noop_params4 avgt 3 10,313 ? 3,615 ns/op
FFMEscapeAnalysisTest.noop_params4:gc.alloc.rate avgt 3 14796,598 ? 5131,809 MB/sec
FFMEscapeAnalysisTest.noop_params4:gc.alloc.rate.norm avgt 3 160,000 ? 0,001 B/op
FFMEscapeAnalysisTest.noop_params4:gc.count avgt 3 20,000 counts
FFMEscapeAnalysisTest.noop_params4:gc.time avgt 3 15,000 ms
FFMEscapeAnalysisTest.noop_params5 avgt 3 12,156 ? 4,828 ns/op
FFMEscapeAnalysisTest.noop_params5:gc.alloc.rate avgt 3 15692,588 ? 6152,349 MB/sec
FFMEscapeAnalysisTest.noop_params5:gc.alloc.rate.norm avgt 3 200,000 ? 0,001 B/op
FFMEscapeAnalysisTest.noop_params5:gc.count avgt 3 19,000 counts
FFMEscapeAnalysisTest.noop_params5:gc.time avgt 3 16,000 ms
*/
@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.NANOSECONDS)
@Fork(value = 3, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED", "-Djava.library.path=micro/native" })
public class FFMEscapeAnalysisTest {

static {
System.loadLibrary("eaTest");
}

// A shared library that exports the functions below
private static final SymbolLookup LOOKUP = SymbolLookup.loaderLookup();

// void noop_params0() {}
private static final MethodHandle MH_NOOP_PARAMS0 = Linker.nativeLinker()
.downcallHandle(FunctionDescriptor.ofVoid())
.bindTo(LOOKUP.find("noop_params0").orElseThrow());

// void noop_params1(void *param0) {}
private static final MethodHandle MH_NOOP_PARAMS1 = Linker.nativeLinker()
.downcallHandle(FunctionDescriptor.ofVoid(
ValueLayout.ADDRESS
))
.bindTo(LOOKUP.find("noop_params1").orElseThrow());

// void noop_params2(void *param0, void *param1) {}
private static final MethodHandle MH_NOOP_PARAMS2 = Linker.nativeLinker()
.downcallHandle(FunctionDescriptor.ofVoid(
ValueLayout.ADDRESS,
ValueLayout.ADDRESS
))
.bindTo(LOOKUP.find("noop_params2").orElseThrow());

// void noop_params3(void *param0, void *param1, void *param2) {}
private static final MethodHandle MH_NOOP_PARAMS3 = Linker.nativeLinker()
.downcallHandle(FunctionDescriptor.ofVoid(
ValueLayout.ADDRESS,
ValueLayout.ADDRESS,
ValueLayout.ADDRESS
))
.bindTo(LOOKUP.find("noop_params3").orElseThrow());

// void noop_params4(void *param0, void *param1, void *param2, void *param3) {}
private static final MethodHandle MH_NOOP_PARAMS4 = Linker.nativeLinker()
.downcallHandle(FunctionDescriptor.ofVoid(
ValueLayout.ADDRESS,
ValueLayout.ADDRESS,
ValueLayout.ADDRESS,
ValueLayout.ADDRESS
))
.bindTo(LOOKUP.find("noop_params4").orElseThrow());

// void noop_params5(int param0, int param1, void *param2, void *param3, void *param4) {}
private static final MethodHandle MH_NOOP_PARAMS5 = Linker.nativeLinker()
.downcallHandle(FunctionDescriptor.ofVoid(
ValueLayout.ADDRESS,
ValueLayout.ADDRESS,
ValueLayout.ADDRESS,
ValueLayout.ADDRESS,
ValueLayout.ADDRESS
))
.bindTo(LOOKUP.find("noop_params5").orElseThrow());

@Benchmark
public void noop_params0() {
try {
MH_NOOP_PARAMS0.invokeExact();
} catch (Throwable t) {
throw new AssertionError(t);
}
}

@Benchmark
public void noop_params1() {
try {
MH_NOOP_PARAMS1.invokeExact(
MemorySegment.ofAddress(0L)
);
} catch (Throwable t) {
throw new AssertionError(t);
}
}

@Benchmark
public void noop_params2() {
try {
MH_NOOP_PARAMS2.invokeExact(
MemorySegment.ofAddress(0L),
MemorySegment.ofAddress(0L)
);
} catch (Throwable t) {
throw new AssertionError(t);
}
}

@Benchmark
public void noop_params3() {
try {
MH_NOOP_PARAMS3.invokeExact(
MemorySegment.ofAddress(0L),
MemorySegment.ofAddress(0L),
MemorySegment.ofAddress(0L)
);
} catch (Throwable t) {
throw new AssertionError(t);
}
}

@Benchmark
public void noop_params4() {
try {
MH_NOOP_PARAMS4.invokeExact(
MemorySegment.ofAddress(0L),
MemorySegment.ofAddress(0L),
MemorySegment.ofAddress(0L),
MemorySegment.ofAddress(0L)
);
/*var p = MemorySegment.ofAddress(0L);
MH_NOOP_PARAMS4.invokeExact(p, p, p, p);*/
} catch (Throwable t) {
throw new AssertionError(t);
}
}

@Benchmark
public void noop_params5() {
try {
MH_NOOP_PARAMS5.invokeExact(
MemorySegment.ofAddress(0L),
MemorySegment.ofAddress(0L),
MemorySegment.ofAddress(0L),
MemorySegment.ofAddress(0L),
MemorySegment.ofAddress(0L)
);
/*var p = MemorySegment.ofAddress(0L);
MH_NOOP_PARAMS5.invokeExact(p, p, p, p, p);*/
} catch (Throwable t) {
throw new AssertionError(t);
}
}
}
8 changes: 8 additions & 0 deletions test/micro/org/openjdk/bench/java/lang/foreign/libeaTest.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#include "export.h"

EXPORT void noop_params0() {}
EXPORT void noop_params1(void *param0) {}
EXPORT void noop_params2(void *param0, void *param1) {}
EXPORT void noop_params3(void *param0, void *param1, void *param2) {}
EXPORT void noop_params4(void *param0, void *param1, void *param2, void *param3) {}
EXPORT void noop_params5(int param0, int param1, void *param2, void *param3, void *param4) {}

0 comments on commit ed4775c

Please sign in to comment.