diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index eea4f225..48782553 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -38,10 +38,15 @@ jobs: uses: gradle/actions/setup-gradle@v3 - name: Execute Gradle build run: ./gradlew build --parallel + - name: Upload build reports + uses: actions/upload-artifact@v4 + with: + name: build-reports-${{ runner.os }}-jdk${{ matrix.java }} + path: | + modules/samples/build/reports/ - name: Capture build artifacts - if: ${{ runner.os == 'Linux' && matrix.java == '22' }} uses: actions/upload-artifact@v4 with: - name: artifacts + name: artifacts-${{ runner.os }}-jdk${{ matrix.java }} path: | modules/**/build/libs/ diff --git a/gradle.properties b/gradle.properties index 536f6009..f4c19593 100644 --- a/gradle.properties +++ b/gradle.properties @@ -15,3 +15,4 @@ kotlinTargetJdkVersion=21 overrunMarshalVersion=0.1.0-alpha.28-jdk22 overrunPlatformVersion=1.0.0 jomlVersion=1.10.8 +junitVersion=5.11.0 diff --git a/modules/overrungl.core/src/main/java/overrungl/util/MemoryUtil.java b/modules/overrungl.core/src/main/java/overrungl/util/MemoryUtil.java index 88cbb6cd..33c2ae87 100644 --- a/modules/overrungl.core/src/main/java/overrungl/util/MemoryUtil.java +++ b/modules/overrungl.core/src/main/java/overrungl/util/MemoryUtil.java @@ -23,7 +23,6 @@ import java.lang.foreign.*; import java.lang.invoke.MethodHandle; -import static java.lang.foreign.FunctionDescriptor.of; import static java.lang.foreign.ValueLayout.ADDRESS; import static overrungl.internal.RuntimeHelper.SIZE_T_LONG; import static overrungl.util.PlatformLayouts.SIZE_T; @@ -38,13 +37,13 @@ public final class MemoryUtil { private static final Linker LINKER = Linker.nativeLinker(); private static final SymbolLookup LOOKUP = LINKER.defaultLookup(); private static final MethodHandle - m_malloc = downcall("malloc", of(ADDRESS, SIZE_T)), - m_calloc = downcall("calloc", of(ADDRESS, SIZE_T, SIZE_T)), - m_realloc = downcall("realloc", of(ADDRESS, ADDRESS, SIZE_T)), + m_malloc = downcall("malloc", FunctionDescriptor.of(ADDRESS, SIZE_T)), + m_calloc = downcall("calloc", FunctionDescriptor.of(ADDRESS, SIZE_T, SIZE_T)), + m_realloc = downcall("realloc", FunctionDescriptor.of(ADDRESS, ADDRESS, SIZE_T)), m_free = downcall("free", FunctionDescriptor.ofVoid(ADDRESS)), - m_memcpy = downcall("memcpy", of(ADDRESS, ADDRESS, ADDRESS, SIZE_T)), - m_memmove = downcall("memmove", of(ADDRESS, ADDRESS, ADDRESS, SIZE_T)), - m_memset = downcall("memset", of(ADDRESS, ADDRESS, ValueLayout.JAVA_INT, SIZE_T)); + m_memcpy = downcall("memcpy", FunctionDescriptor.of(ADDRESS, ADDRESS, ADDRESS, SIZE_T)), + m_memmove = downcall("memmove", FunctionDescriptor.of(ADDRESS, ADDRESS, ADDRESS, SIZE_T)), + m_memset = downcall("memset", FunctionDescriptor.of(ADDRESS, ADDRESS, ValueLayout.JAVA_INT, SIZE_T)); private static final boolean DEBUG = Configurations.DEBUG_MEM_UTIL.get(); /** * The address of {@code NULL}. @@ -337,7 +336,7 @@ public static SegmentAllocator allocator(Arena arena) { return (byteSize, byteAlignment) -> { checkByteSize(byteSize); checkAlignment(byteAlignment); - return calloc(1, byteSize).reinterpret(arena, MemoryUtil::free); + return calloc(byteSize, 1).reinterpret(arena, MemoryUtil::free); }; } } diff --git a/modules/samples/build.gradle.kts b/modules/samples/build.gradle.kts index 74754b37..706dcf3a 100644 --- a/modules/samples/build.gradle.kts +++ b/modules/samples/build.gradle.kts @@ -8,6 +8,8 @@ overrunglModule { artifactName = "overrungl-samples" } +val junitVersion: String by project + dependencies { Artifact.values().forEach { implementation(project(it.subprojectName)) @@ -15,4 +17,9 @@ dependencies { implementation("io.github.over-run:timer:0.3.0") jmh("org.openjdk.jmh:jmh-core:1.37") jmhAnnotationProcessor("org.openjdk.jmh:jmh-generator-annprocess:1.37") + testImplementation("org.junit.jupiter:junit-jupiter:$junitVersion") +} + +tasks.withType { + useJUnitPlatform() } diff --git a/modules/samples/src/jmh/java/overrungl/demo/mem/MemoryUtilTest.java b/modules/samples/src/jmh/java/overrungl/demo/mem/MemoryUtilBenchmark.java similarity index 94% rename from modules/samples/src/jmh/java/overrungl/demo/mem/MemoryUtilTest.java rename to modules/samples/src/jmh/java/overrungl/demo/mem/MemoryUtilBenchmark.java index 24998f5e..8c0174ba 100644 --- a/modules/samples/src/jmh/java/overrungl/demo/mem/MemoryUtilTest.java +++ b/modules/samples/src/jmh/java/overrungl/demo/mem/MemoryUtilBenchmark.java @@ -42,7 +42,7 @@ @Measurement(iterations = 5, time = 250, timeUnit = TimeUnit.MILLISECONDS, batchSize = 100) @Threads(Threads.MAX) @Fork(1) -public class MemoryUtilTest { +public class MemoryUtilBenchmark { @Param({"0", "1", "10", "128", "1024"}) private long size; @@ -92,8 +92,8 @@ public void measureStackCalloc(Blackhole bh) { public static void main(String[] args) throws RunnerException { new Runner( new OptionsBuilder() - .include(MemoryUtilTest.class.getSimpleName()) - .result("MemoryUtilTest.json") + .include(MemoryUtilBenchmark.class.getSimpleName()) + .result("MemoryUtilBenchmark.json") .resultFormat(ResultFormatType.JSON) .build() ).run(); diff --git a/modules/samples/src/test/java/overrungl/test/MemoryUtilTest.java b/modules/samples/src/test/java/overrungl/test/MemoryUtilTest.java new file mode 100644 index 00000000..1fc0ee40 --- /dev/null +++ b/modules/samples/src/test/java/overrungl/test/MemoryUtilTest.java @@ -0,0 +1,75 @@ +/* + * MIT License + * + * Copyright (c) 2024 Overrun Organization + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + */ + +package overrungl.test; + +import org.junit.jupiter.api.Test; +import overrungl.util.MemoryUtil; + +import java.lang.foreign.Arena; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.SegmentAllocator; +import java.lang.foreign.ValueLayout; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; + +/** + * @author squid233 + * @since 0.1.0 + */ +public class MemoryUtilTest { + @Test + void test_malloc() { + MemorySegment segment = MemoryUtil.malloc(ValueLayout.JAVA_INT); + segment.set(ValueLayout.JAVA_INT, 0L, 42); + assertEquals(42, segment.get(ValueLayout.JAVA_INT, 0L)); + MemoryUtil.free(segment); + } + + @Test + void test_calloc() { + MemorySegment segment = MemoryUtil.calloc(1, ValueLayout.JAVA_INT); + assertEquals(0, segment.get(ValueLayout.JAVA_INT, 0L)); + segment.set(ValueLayout.JAVA_INT, 0L, 42); + assertEquals(42, segment.get(ValueLayout.JAVA_INT, 0L)); + MemoryUtil.free(segment); + } + + @Test + void test_realloc() { + MemorySegment segment = MemoryUtil.calloc(1, ValueLayout.JAVA_INT); + assertEquals(4L, segment.byteSize()); + segment = MemoryUtil.realloc(segment, ValueLayout.JAVA_INT.scale(0L, 2L)); + assertEquals(8L, segment.byteSize()); + MemoryUtil.free(segment); + } + + @Test + void test_allocator() { + MemorySegment.Scope scope; + try (Arena arena = Arena.ofConfined()) { + SegmentAllocator allocator = MemoryUtil.allocator(arena); + MemorySegment segment = allocator.allocate(ValueLayout.JAVA_INT); + scope = segment.scope(); + + assertEquals(0, segment.get(ValueLayout.JAVA_INT, 0L)); + segment.set(ValueLayout.JAVA_INT, 0L, 42); + assertEquals(42, segment.get(ValueLayout.JAVA_INT, 0L)); + } + assertFalse(scope.isAlive()); + } +}