diff --git a/.github/actions/prepare_env/action.yml b/.github/actions/prepare_env/action.yml index 33fa1f76..c63b87cf 100644 --- a/.github/actions/prepare_env/action.yml +++ b/.github/actions/prepare_env/action.yml @@ -11,6 +11,7 @@ runs: java-version: | 24 21 + 19 cache: 'gradle' - name: Set JAVA_HOME_{N} shell: bash diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index b55e0489..9a0b59b8 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -31,10 +31,14 @@ jobs: - uses: actions/checkout@v4 - name: Prepare CI Environment uses: ./.github/actions/prepare_env - - name: Gradle :SwiftKit:build - run: ./gradlew build -x test - - name: Gradle :SwiftKit:check - run: ./gradlew :SwiftKit:check --info + - name: Gradle :SwiftKitCore:build + run: ./gradlew :SwiftKitCore:build -x test + - name: Gradle :SwiftKitCore:check + run: ./gradlew :SwiftKitCore:check --info + - name: Gradle :SwiftKitFFM:build + run: ./gradlew :SwiftKitFFM:build -x test + - name: Gradle :SwiftKitFFM:check + run: ./gradlew :SwiftKitFFM:check --info test-java-macos: name: Test (Java) (${{ matrix.os_version }} swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}}) @@ -51,10 +55,14 @@ jobs: - uses: actions/checkout@v4 - name: Prepare CI Environment uses: ./.github/actions/prepare_env - - name: Gradle :SwiftKit:build - run: ./gradlew build -x test - - name: Gradle :SwiftKit:check - run: ./gradlew :SwiftKit:check --debug + - name: Gradle :SwiftKitCore:build + run: ./gradlew :SwiftKitCore:build -x test + - name: Gradle :SwiftKitCore:check + run: ./gradlew :SwiftKitCore:check --debug + - name: Gradle :SwiftKitFFM:build + run: ./gradlew :SwiftKitFFM:build -x test + - name: Gradle :SwiftKitFFM:check + run: ./gradlew :SwiftKitFFM:check --debug benchmark-java: name: Benchmark (JMH) (${{ matrix.os_version }} swift:${{ matrix.swift_version }} jdk:${{matrix.jdk_vendor}}) diff --git a/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts b/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts index fb10bee0..df0a6633 100644 --- a/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts +++ b/BuildLogic/src/main/kotlin/build-logic.java-common-conventions.gradle.kts @@ -31,21 +31,6 @@ repositories { mavenCentral() } -testing { - suites { - val test by getting(JvmTestSuite::class) { - useJUnitJupiter("5.10.3") - } - } -} - -/// Enable access to preview APIs, e.g. java.lang.foreign.* (Panama) -tasks.withType(JavaCompile::class).forEach { - it.options.compilerArgs.add("--enable-preview") - it.options.compilerArgs.add("-Xlint:preview") -} - - fun getSwiftRuntimeLibraryPaths(): List { val process = ProcessBuilder("swiftc", "-print-target-info") .redirectError(ProcessBuilder.Redirect.INHERIT) diff --git a/Samples/JExtractJNISampleApp/build.gradle b/Samples/JExtractJNISampleApp/build.gradle index 03794ff7..54bd725a 100644 --- a/Samples/JExtractJNISampleApp/build.gradle +++ b/Samples/JExtractJNISampleApp/build.gradle @@ -148,7 +148,7 @@ tasks.clean { } dependencies { - implementation(project(':SwiftKit')) + implementation(project(':SwiftKitCore')) testImplementation(platform("org.junit:junit-bom:5.10.0")) testImplementation("org.junit.jupiter:junit-jupiter") diff --git a/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java b/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java index 7d0d77e1..66366a19 100644 --- a/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java +++ b/Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java @@ -18,12 +18,12 @@ // Import javakit/swiftkit support libraries -import org.swift.swiftkit.SwiftKit; +import org.swift.swiftkit.core.SwiftLibraries; public class HelloJava2SwiftJNI { public static void main(String[] args) { - System.out.print("Property: java.library.path = " + SwiftKit.getJavaLibraryPath()); + System.out.print("Property: java.library.path = " + SwiftLibraries.getJavaLibraryPath()); examples(); } @@ -35,10 +35,8 @@ static void examples() { MySwiftLibrary.globalTakeIntInt(1337, 42); long cnt = MySwiftLibrary.globalWriteString("String from Java"); - SwiftKit.trace("count = " + cnt); long i = MySwiftLibrary.globalMakeInt(); - SwiftKit.trace("globalMakeInt() = " + i); MySwiftClass.method(); diff --git a/Samples/SwiftAndJavaJarSampleLib/build.gradle b/Samples/SwiftAndJavaJarSampleLib/build.gradle index cc4c79d4..96b25e22 100644 --- a/Samples/SwiftAndJavaJarSampleLib/build.gradle +++ b/Samples/SwiftAndJavaJarSampleLib/build.gradle @@ -43,7 +43,8 @@ java { } dependencies { - implementation(project(':SwiftKit')) + implementation(project(':SwiftKitCore')) + implementation(project(':SwiftKitFFM')) testImplementation(platform("org.junit:junit-bom:5.10.0")) testImplementation("org.junit.jupiter:junit-jupiter") diff --git a/Samples/SwiftAndJavaJarSampleLib/ci-validate.sh b/Samples/SwiftAndJavaJarSampleLib/ci-validate.sh index f56b611e..4fde0ef0 100755 --- a/Samples/SwiftAndJavaJarSampleLib/ci-validate.sh +++ b/Samples/SwiftAndJavaJarSampleLib/ci-validate.sh @@ -27,9 +27,10 @@ fi # check if we can compile a plain Example file that uses the generated Java bindings that should be in the generated jar # The classpath MUST end with a * if it contains jar files, and must not if it directly contains class files. -SWIFTKIT_CLASSPATH="$(pwd)/../../SwiftKit/build/libs/*" +SWIFTKIT_CORE_CLASSPATH="$(pwd)/../../SwiftKitCore/build/libs/*" +SWIFTKIT_FFM_CLASSPATH="$(pwd)/../../SwiftKitFFM/build/libs/*" MYLIB_CLASSPATH="$(pwd)/build/libs/*" -CLASSPATH="$(pwd)/:${SWIFTKIT_CLASSPATH}:${MYLIB_CLASSPATH}" +CLASSPATH="$(pwd)/:${SWIFTKIT_FFM_CLASSPATH}:${SWIFTKIT_CORE_CLASSPATH}:${MYLIB_CLASSPATH}" echo "CLASSPATH = ${CLASSPATH}" $JAVAC -cp "${CLASSPATH}" Example.java diff --git a/Samples/SwiftAndJavaJarSampleLib/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java b/Samples/SwiftAndJavaJarSampleLib/src/jmh/java/org/swift/swiftkit/ffm/JavaToSwiftBenchmark.java similarity index 98% rename from Samples/SwiftAndJavaJarSampleLib/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java rename to Samples/SwiftAndJavaJarSampleLib/src/jmh/java/org/swift/swiftkit/ffm/JavaToSwiftBenchmark.java index 4e3edf03..7d6b92dc 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/jmh/java/org/swift/swiftkit/ffm/JavaToSwiftBenchmark.java @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.ffm; import java.util.concurrent.TimeUnit; diff --git a/Samples/SwiftAndJavaJarSampleLib/src/main/java/com/example/swift/HelloJava2Swift.java b/Samples/SwiftAndJavaJarSampleLib/src/main/java/com/example/swift/HelloJava2Swift.java index cd8af700..e41547bd 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/main/java/com/example/swift/HelloJava2Swift.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/main/java/com/example/swift/HelloJava2Swift.java @@ -16,15 +16,10 @@ // Import swift-extract generated sources -import com.example.swift.MySwiftLibrary; -import com.example.swift.MySwiftClass; - // Import javakit/swiftkit support libraries -import org.swift.swiftkit.SwiftArena; -import org.swift.swiftkit.SwiftKit; -import org.swift.swiftkit.SwiftValueWitnessTable; - -import java.util.Arrays; +import org.swift.swiftkit.core.SwiftLibraries; +import org.swift.swiftkit.ffm.AllocatingSwiftArena; +import org.swift.swiftkit.ffm.SwiftRuntime; public class HelloJava2Swift { @@ -32,7 +27,7 @@ public static void main(String[] args) { boolean traceDowncalls = Boolean.getBoolean("jextract.trace.downcalls"); System.out.println("Property: jextract.trace.downcalls = " + traceDowncalls); - System.out.print("Property: java.library.path = " +SwiftKit.getJavaLibraryPath()); + System.out.print("Property: java.library.path = " + SwiftLibraries.getJavaLibraryPath()); examples(); } @@ -43,12 +38,12 @@ static void examples() { MySwiftLibrary.globalTakeInt(1337); // Example of using an arena; MyClass.deinit is run at end of scope - try (var arena = SwiftArena.ofConfined()) { + try (var arena = AllocatingSwiftArena.ofConfined()) { MySwiftClass obj = MySwiftClass.init(2222, 7777, arena); // just checking retains/releases work - SwiftKit.retain(obj); - SwiftKit.release(obj); + SwiftRuntime.retain(obj); + SwiftRuntime.release(obj); obj.voidMethod(); obj.takeIntMethod(42); diff --git a/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftClassTest.java b/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftClassTest.java index bb46ef3d..6fb7651c 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftClassTest.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftClassTest.java @@ -16,8 +16,8 @@ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import org.swift.swiftkit.SwiftArena; -import org.swift.swiftkit.SwiftKit; +import org.swift.swiftkit.core.SwiftLibraries; +import org.swift.swiftkit.ffm.AllocatingSwiftArena; import java.io.File; import java.util.stream.Stream; @@ -27,7 +27,7 @@ public class MySwiftClassTest { void checkPaths(Throwable throwable) { - var paths = SwiftKit.getJavaLibraryPath().split(":"); + var paths = SwiftLibraries.getJavaLibraryPath().split(":"); for (var path : paths) { System.out.println("CHECKING PATH: " + path); Stream.of(new File(path).listFiles()) @@ -42,7 +42,7 @@ void checkPaths(Throwable throwable) { @Test void test_MySwiftClass_voidMethod() { - try(var arena = SwiftArena.ofConfined()) { + try(var arena = AllocatingSwiftArena.ofConfined()) { MySwiftClass o = MySwiftClass.init(12, 42, arena); o.voidMethod(); } catch (Throwable throwable) { @@ -52,7 +52,7 @@ void test_MySwiftClass_voidMethod() { @Test void test_MySwiftClass_makeIntMethod() { - try(var arena = SwiftArena.ofConfined()) { + try(var arena = AllocatingSwiftArena.ofConfined()) { MySwiftClass o = MySwiftClass.init(12, 42, arena); var got = o.makeIntMethod(); assertEquals(12, got); @@ -62,7 +62,7 @@ void test_MySwiftClass_makeIntMethod() { @Test @Disabled // TODO: Need var mangled names in interfaces void test_MySwiftClass_property_len() { - try(var arena = SwiftArena.ofConfined()) { + try(var arena = AllocatingSwiftArena.ofConfined()) { MySwiftClass o = MySwiftClass.init(12, 42, arena); var got = o.getLen(); assertEquals(12, got); diff --git a/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftLibraryTest.java b/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftLibraryTest.java index 74df5da8..13ebb1b0 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftLibraryTest.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/test/java/com/example/swift/MySwiftLibraryTest.java @@ -14,14 +14,10 @@ package com.example.swift; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import org.swift.swiftkit.SwiftKit; -import java.util.Arrays; import java.util.concurrent.CountDownLatch; -import java.util.stream.Collectors; import static org.junit.jupiter.api.Assertions.*; diff --git a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java b/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/ffm/MySwiftClassTest.java similarity index 72% rename from Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java rename to Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/ffm/MySwiftClassTest.java index 78da5a64..fb1c5d1a 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/ffm/MySwiftClassTest.java @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.ffm; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -24,16 +24,16 @@ public class MySwiftClassTest { @Test void call_retain_retainCount_release() { - var arena = SwiftArena.ofConfined(); + var arena = AllocatingSwiftArena.ofConfined(); var obj = MySwiftClass.init(1, 2, arena); - assertEquals(1, SwiftKit.retainCount(obj)); + assertEquals(1, SwiftRuntime.retainCount(obj)); // TODO: test directly on SwiftHeapObject inheriting obj - SwiftKit.retain(obj); - assertEquals(2, SwiftKit.retainCount(obj)); + SwiftRuntime.retain(obj); + assertEquals(2, SwiftRuntime.retainCount(obj)); - SwiftKit.release(obj); - assertEquals(1, SwiftKit.retainCount(obj)); + SwiftRuntime.release(obj); + assertEquals(1, SwiftRuntime.retainCount(obj)); } } diff --git a/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/SwiftArenaTest.java b/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/ffm/SwiftArenaTest.java similarity index 77% rename from Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/SwiftArenaTest.java rename to Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/ffm/SwiftArenaTest.java index e8b1ac04..8d786d95 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/SwiftArenaTest.java +++ b/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/ffm/SwiftArenaTest.java @@ -12,20 +12,15 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.ffm; import com.example.swift.MySwiftClass; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledIf; -import org.swift.swiftkit.util.PlatformUtils; +import org.swift.swiftkit.core.util.PlatformUtils; -import java.util.Arrays; -import java.util.stream.Collectors; - -import static org.junit.jupiter.api.Assertions.*; -import static org.swift.swiftkit.SwiftKit.*; -import static org.swift.swiftkit.SwiftKit.retainCount; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.swift.swiftkit.ffm.SwiftRuntime.*; public class SwiftArenaTest { @@ -38,7 +33,7 @@ static boolean isAmd64() { @Test @DisabledIf("isAmd64") public void arena_releaseClassOnClose_class_ok() { - try (var arena = SwiftArena.ofConfined()) { + try (var arena = AllocatingSwiftArena.ofConfined()) { var obj = MySwiftClass.init(1, 2, arena); retain(obj); diff --git a/Samples/SwiftKitSampleApp/build.gradle b/Samples/SwiftKitSampleApp/build.gradle index 647eaba9..048c984d 100644 --- a/Samples/SwiftKitSampleApp/build.gradle +++ b/Samples/SwiftKitSampleApp/build.gradle @@ -16,7 +16,6 @@ import groovy.json.JsonSlurper import org.swift.swiftkit.gradle.BuildUtils import java.nio.file.* -import kotlinx.serialization.json.* plugins { id("build-logic.java-application-conventions") @@ -148,7 +147,8 @@ tasks.clean { } dependencies { - implementation(project(':SwiftKit')) + implementation(project(':SwiftKitCore')) + implementation(project(':SwiftKitFFM')) testImplementation(platform("org.junit:junit-bom:5.10.0")) testImplementation("org.junit.jupiter:junit-jupiter") diff --git a/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java b/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/ffm/JavaToSwiftBenchmark.java similarity index 92% rename from Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java rename to Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/ffm/JavaToSwiftBenchmark.java index ff313fc6..dffbd090 100644 --- a/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/JavaToSwiftBenchmark.java +++ b/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/ffm/JavaToSwiftBenchmark.java @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.ffm; import com.example.swift.HelloJava2Swift; import com.example.swift.MySwiftLibrary; @@ -31,12 +31,12 @@ public class JavaToSwiftBenchmark { @State(Scope.Benchmark) public static class BenchmarkState { - ClosableSwiftArena arena; + ClosableAllocatingSwiftArena arena; MySwiftClass obj; @Setup(Level.Trial) public void beforeAll() { - arena = SwiftArena.ofConfined(); + arena = AllocatingSwiftArena.ofConfined(); obj = MySwiftClass.init(1, 2, arena); } diff --git a/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/StringPassingBenchmark.java b/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/ffm/StringPassingBenchmark.java similarity index 94% rename from Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/StringPassingBenchmark.java rename to Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/ffm/StringPassingBenchmark.java index 0e686fb4..25855842 100644 --- a/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/StringPassingBenchmark.java +++ b/Samples/SwiftKitSampleApp/src/jmh/java/org/swift/swiftkit/ffm/StringPassingBenchmark.java @@ -12,15 +12,14 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.ffm; import com.example.swift.HelloJava2Swift; import com.example.swift.MySwiftClass; import com.example.swift.MySwiftLibrary; import org.openjdk.jmh.annotations.*; +import org.swift.swiftkit.core.ClosableSwiftArena; -import java.lang.foreign.Arena; -import java.nio.charset.StandardCharsets; import java.util.concurrent.TimeUnit; @BenchmarkMode(Mode.AverageTime) @@ -40,12 +39,12 @@ public class StringPassingBenchmark { public int stringLen; public String string; - ClosableSwiftArena arena; + ClosableAllocatingSwiftArena arena; MySwiftClass obj; @Setup(Level.Trial) public void beforeAll() { - arena = SwiftArena.ofConfined(); + arena = AllocatingSwiftArena.ofConfined(); obj = MySwiftClass.init(1, 2, arena); string = makeString(stringLen); } diff --git a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java index c12d82dd..668140b2 100644 --- a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java +++ b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java @@ -18,8 +18,9 @@ // Import javakit/swiftkit support libraries -import org.swift.swiftkit.SwiftArena; -import org.swift.swiftkit.SwiftKit; +import org.swift.swiftkit.core.SwiftLibraries; +import org.swift.swiftkit.ffm.AllocatingSwiftArena; +import org.swift.swiftkit.ffm.SwiftRuntime; public class HelloJava2Swift { @@ -27,7 +28,7 @@ public static void main(String[] args) { boolean traceDowncalls = Boolean.getBoolean("jextract.trace.downcalls"); System.out.println("Property: jextract.trace.downcalls = " + traceDowncalls); - System.out.print("Property: java.library.path = " + SwiftKit.getJavaLibraryPath()); + System.out.print("Property: java.library.path = " + SwiftLibraries.getJavaLibraryPath()); examples(); } @@ -39,30 +40,30 @@ static void examples() { long cnt = MySwiftLibrary.globalWriteString("String from Java"); - SwiftKit.trace("count = " + cnt); + SwiftRuntime.trace("count = " + cnt); MySwiftLibrary.globalCallMeRunnable(() -> { - SwiftKit.trace("running runnable"); + SwiftRuntime.trace("running runnable"); }); - SwiftKit.trace("getGlobalBuffer().byteSize()=" + MySwiftLibrary.getGlobalBuffer().byteSize()); + SwiftRuntime.trace("getGlobalBuffer().byteSize()=" + MySwiftLibrary.getGlobalBuffer().byteSize()); MySwiftLibrary.withBuffer((buf) -> { - SwiftKit.trace("withBuffer{$0.byteSize()}=" + buf.byteSize()); + SwiftRuntime.trace("withBuffer{$0.byteSize()}=" + buf.byteSize()); }); // Example of using an arena; MyClass.deinit is run at end of scope - try (var arena = SwiftArena.ofConfined()) { + try (var arena = AllocatingSwiftArena.ofConfined()) { MySwiftClass obj = MySwiftClass.init(2222, 7777, arena); // just checking retains/releases work - SwiftKit.trace("retainCount = " + SwiftKit.retainCount(obj)); - SwiftKit.retain(obj); - SwiftKit.trace("retainCount = " + SwiftKit.retainCount(obj)); - SwiftKit.release(obj); - SwiftKit.trace("retainCount = " + SwiftKit.retainCount(obj)); + SwiftRuntime.trace("retainCount = " + SwiftRuntime.retainCount(obj)); + SwiftRuntime.retain(obj); + SwiftRuntime.trace("retainCount = " + SwiftRuntime.retainCount(obj)); + SwiftRuntime.release(obj); + SwiftRuntime.trace("retainCount = " + SwiftRuntime.retainCount(obj)); obj.setCounter(12); - SwiftKit.trace("obj.counter = " + obj.getCounter()); + SwiftRuntime.trace("obj.counter = " + obj.getCounter()); obj.voidMethod(); obj.takeIntMethod(42); @@ -71,9 +72,9 @@ static void examples() { otherObj.voidMethod(); MySwiftStruct swiftValue = MySwiftStruct.init(2222, 1111, arena); - SwiftKit.trace("swiftValue.capacity = " + swiftValue.getCapacity()); + SwiftRuntime.trace("swiftValue.capacity = " + swiftValue.getCapacity()); swiftValue.withCapLen((cap, len) -> { - SwiftKit.trace("withCapLenCallback: cap=" + cap + ", len=" + len); + SwiftRuntime.trace("withCapLenCallback: cap=" + cap + ", len=" + len); }); } diff --git a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java index 6c0ceb1e..1f0464eb 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftClassTest.java @@ -16,8 +16,8 @@ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import org.swift.swiftkit.SwiftArena; -import org.swift.swiftkit.SwiftKit; +import org.swift.swiftkit.core.SwiftLibraries; +import org.swift.swiftkit.ffm.AllocatingSwiftArena; import java.io.File; import java.util.stream.Stream; @@ -27,7 +27,7 @@ public class MySwiftClassTest { void checkPaths(Throwable throwable) { - var paths = SwiftKit.getJavaLibraryPath().split(":"); + var paths = SwiftLibraries.getJavaLibraryPath().split(":"); for (var path : paths) { Stream.of(new File(path).listFiles()) .filter(file -> !file.isDirectory()) @@ -41,7 +41,7 @@ void checkPaths(Throwable throwable) { @Test void test_MySwiftClass_voidMethod() { - try(var arena = SwiftArena.ofConfined()) { + try(var arena = AllocatingSwiftArena.ofConfined()) { MySwiftClass o = MySwiftClass.init(12, 42, arena); o.voidMethod(); } catch (Throwable throwable) { @@ -51,7 +51,7 @@ void test_MySwiftClass_voidMethod() { @Test void test_MySwiftClass_makeIntMethod() { - try(var arena = SwiftArena.ofConfined()) { + try(var arena = AllocatingSwiftArena.ofConfined()) { MySwiftClass o = MySwiftClass.init(12, 42, arena); var got = o.makeIntMethod(); assertEquals(12, got); @@ -61,7 +61,7 @@ void test_MySwiftClass_makeIntMethod() { @Test @Disabled // TODO: Need var mangled names in interfaces void test_MySwiftClass_property_len() { - try(var arena = SwiftArena.ofConfined()) { + try(var arena = AllocatingSwiftArena.ofConfined()) { MySwiftClass o = MySwiftClass.init(12, 42, arena); var got = o.getLen(); assertEquals(12, got); diff --git a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java index 2df53843..a6c34b57 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java @@ -14,15 +14,10 @@ package com.example.swift; -import com.example.swift.MySwiftLibrary; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import org.swift.swiftkit.SwiftKit; -import java.util.Arrays; import java.util.concurrent.CountDownLatch; -import java.util.stream.Collectors; import static org.junit.jupiter.api.Assertions.*; diff --git a/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/MySwiftClassTest.java b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkitffm/MySwiftClassTest.java similarity index 66% rename from Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/MySwiftClassTest.java rename to Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkitffm/MySwiftClassTest.java index 78da5a64..17db4c41 100644 --- a/Samples/SwiftAndJavaJarSampleLib/src/test/java/org/swift/swiftkit/MySwiftClassTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkitffm/MySwiftClassTest.java @@ -12,28 +12,30 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkitffm; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; import com.example.swift.MySwiftClass; +import org.swift.swiftkit.ffm.AllocatingSwiftArena; +import org.swift.swiftkit.ffm.SwiftRuntime; public class MySwiftClassTest { @Test void call_retain_retainCount_release() { - var arena = SwiftArena.ofConfined(); + var arena = AllocatingSwiftArena.ofConfined(); var obj = MySwiftClass.init(1, 2, arena); - assertEquals(1, SwiftKit.retainCount(obj)); + assertEquals(1, SwiftRuntime.retainCount(obj)); // TODO: test directly on SwiftHeapObject inheriting obj - SwiftKit.retain(obj); - assertEquals(2, SwiftKit.retainCount(obj)); + SwiftRuntime.retain(obj); + assertEquals(2, SwiftRuntime.retainCount(obj)); - SwiftKit.release(obj); - assertEquals(1, SwiftKit.retainCount(obj)); + SwiftRuntime.release(obj); + assertEquals(1, SwiftRuntime.retainCount(obj)); } } diff --git a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftStructTest.java b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkitffm/MySwiftStructTest.java similarity index 86% rename from Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftStructTest.java rename to Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkitffm/MySwiftStructTest.java index 843551a5..6b994137 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftStructTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkitffm/MySwiftStructTest.java @@ -12,10 +12,11 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkitffm; import com.example.swift.MySwiftStruct; import org.junit.jupiter.api.Test; +import org.swift.swiftkit.ffm.AllocatingSwiftArena; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -23,7 +24,7 @@ public class MySwiftStructTest { @Test void create_struct() { - try (var arena = SwiftArena.ofConfined()) { + try (var arena = AllocatingSwiftArena.ofConfined()) { long cap = 12; long len = 34; var struct = MySwiftStruct.init(cap, len, arena); diff --git a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkitffm/SwiftArenaTest.java similarity index 84% rename from Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java rename to Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkitffm/SwiftArenaTest.java index 52d791a1..08dd9b1b 100644 --- a/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/SwiftArenaTest.java +++ b/Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkitffm/SwiftArenaTest.java @@ -12,21 +12,18 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkitffm; import com.example.swift.MySwiftClass; import com.example.swift.MySwiftStruct; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledIf; -import org.swift.swiftkit.util.PlatformUtils; - -import java.util.Arrays; -import java.util.stream.Collectors; +import org.swift.swiftkit.core.util.PlatformUtils; +import org.swift.swiftkit.ffm.AllocatingSwiftArena; +import org.swift.swiftkit.ffm.SwiftRuntime; import static org.junit.jupiter.api.Assertions.*; -import static org.swift.swiftkit.SwiftKit.*; -import static org.swift.swiftkit.SwiftKit.retainCount; +import static org.swift.swiftkit.ffm.SwiftRuntime.retainCount; public class SwiftArenaTest { @@ -39,13 +36,13 @@ static boolean isAmd64() { @Test @DisabledIf("isAmd64") public void arena_releaseClassOnClose_class_ok() { - try (var arena = SwiftArena.ofConfined()) { + try (var arena = AllocatingSwiftArena.ofConfined()) { var obj = MySwiftClass.init(1, 2, arena); - retain(obj); + SwiftRuntime.retain(obj); assertEquals(2, retainCount(obj)); - release(obj); + SwiftRuntime.release(obj); assertEquals(1, retainCount(obj)); } } @@ -56,7 +53,7 @@ public void arena_releaseClassOnClose_class_ok() { public void arena_markAsDestroyed_preventUseAfterFree_class() { MySwiftClass unsafelyEscapedOutsideArenaScope = null; - try (var arena = SwiftArena.ofConfined()) { + try (var arena = AllocatingSwiftArena.ofConfined()) { var obj = MySwiftClass.init(1, 2, arena); unsafelyEscapedOutsideArenaScope = obj; } @@ -75,7 +72,7 @@ public void arena_markAsDestroyed_preventUseAfterFree_class() { public void arena_markAsDestroyed_preventUseAfterFree_struct() { MySwiftStruct unsafelyEscapedOutsideArenaScope = null; - try (var arena = SwiftArena.ofConfined()) { + try (var arena = AllocatingSwiftArena.ofConfined()) { var s = MySwiftStruct.init(1, 2, arena); unsafelyEscapedOutsideArenaScope = s; } diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift index 364fd270..13230a32 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift @@ -116,8 +116,8 @@ extension FFMSwift2JavaGenerator { """ public static \(returnTy) call(\(paramsStr)) { try { - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(\(argsStr)); + if (SwiftRuntime.TRACE_DOWNCALLS) { + SwiftRuntime.traceDowncall(\(argsStr)); } \(maybeReturn)HANDLE.invokeExact(\(argsStr)); } catch (Throwable ex$) { @@ -156,7 +156,7 @@ extension FFMSwift2JavaGenerator { /// apply(); /// } /// static final MethodDescriptor DESC = FunctionDescriptor.of(...); - /// static final MethodHandle HANDLE = SwiftKit.upcallHandle(Function.class, "apply", DESC); + /// static final MethodHandle HANDLE = SwiftRuntime.upcallHandle(Function.class, "apply", DESC); /// static MemorySegment toUpcallStub(Function fi, Arena arena) { /// return Linker.nativeLinker().upcallStub(HANDLE.bindTo(fi), DESC, arena); /// } @@ -197,7 +197,7 @@ extension FFMSwift2JavaGenerator { printFunctionDescriptorDefinition(&printer, cResultType, cParams) printer.print( """ - private static final MethodHandle HANDLE = SwiftKit.upcallHandle(Function.class, "apply", DESC); + private static final MethodHandle HANDLE = SwiftRuntime.upcallHandle(Function.class, "apply", DESC); private static MemorySegment toUpcallStub(Function fi, Arena arena) { return Linker.nativeLinker().upcallStub(HANDLE.bindTo(fi), DESC, arena); } @@ -320,7 +320,7 @@ extension FFMSwift2JavaGenerator { .flatMap(\.javaParameters) .map { "\($0.type) \($0.name)" } if translatedSignature.requiresSwiftArena { - paramDecls.append("SwiftArena swiftArena$") + paramDecls.append("AllocatingSwiftArena swiftArena$") } // TODO: we could copy the Swift method's documentation over here, that'd be great UX diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift index 16efddea..d29f6b96 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift @@ -313,7 +313,7 @@ extension FFMSwift2JavaGenerator { return TranslatedParameter( javaParameters: [ JavaParameter( - name: parameterName, type: JavaType.class(package: "org.swift.swiftkit", name: "SwiftAnyType")) + name: parameterName, type: JavaType.class(package: "org.swift.swiftkit.ffm", name: "SwiftAnyType")) ], conversion: .swiftValueSelfSegment(.placeholder) ) @@ -350,7 +350,7 @@ extension FFMSwift2JavaGenerator { name: parameterName, type: .javaLangString ) ], - conversion: .call(.placeholder, function: "SwiftKit.toCString", withArena: true) + conversion: .call(.placeholder, function: "SwiftRuntime.toCString", withArena: true) ) default: @@ -411,7 +411,7 @@ extension FFMSwift2JavaGenerator { switch swiftType { case .metatype(_): // Metatype are expressed as 'org.swift.swiftkit.SwiftAnyType' - let javaType = JavaType.class(package: "org.swift.swiftkit", name: "SwiftAnyType") + let javaType = JavaType.class(package: "org.swift.swiftkit.ffm", name: "SwiftAnyType") return TranslatedResult( javaResultType: javaType, outParameters: [], diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift index 09fcf858..9a140b94 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift @@ -92,9 +92,10 @@ extension FFMSwift2JavaGenerator { /// Default set Java imports for every generated file static let defaultJavaImports: Array = [ - "org.swift.swiftkit.*", - "org.swift.swiftkit.SwiftKit", - "org.swift.swiftkit.util.*", + "org.swift.swiftkit.core.*", + "org.swift.swiftkit.core.util.*", + "org.swift.swiftkit.ffm.*", + "org.swift.swiftkit.ffm.SwiftRuntime", // Necessary for native calls and type mapping "java.lang.foreign.*", @@ -188,7 +189,7 @@ extension FFMSwift2JavaGenerator { @SuppressWarnings("unused") private static final boolean INITIALIZED_LIBS = initializeLibs(); static boolean initializeLibs() { - System.loadLibrary(SwiftKit.STDLIB_DYLIB_NAME); + System.loadLibrary(SwiftLibraries.STDLIB_DYLIB_NAME); System.loadLibrary("SwiftKitSwift"); System.loadLibrary(LIB_NAME); return true; @@ -210,7 +211,7 @@ extension FFMSwift2JavaGenerator { printer.print( """ - public \(decl.swiftNominal.name)(MemorySegment segment, SwiftArena arena) { + public \(decl.swiftNominal.name)(MemorySegment segment, AllocatingSwiftArena arena) { super(segment, arena); } """ @@ -272,7 +273,7 @@ extension FFMSwift2JavaGenerator { parentProtocol = "SwiftValue" } - printer.printBraceBlock("public final class \(decl.swiftNominal.name) extends SwiftInstance implements \(parentProtocol)") { + printer.printBraceBlock("public final class \(decl.swiftNominal.name) extends FFMSwiftInstance implements \(parentProtocol)") { printer in // Constants printClassConstants(printer: &printer) @@ -322,9 +323,9 @@ extension FFMSwift2JavaGenerator { static final SymbolLookup SYMBOL_LOOKUP = getSymbolLookup(); private static SymbolLookup getSymbolLookup() { // Ensure Swift and our Lib are loaded during static initialization of the class. - SwiftKit.loadLibrary("swiftCore"); - SwiftKit.loadLibrary("SwiftKitSwift"); - SwiftKit.loadLibrary(LIB_NAME); + SwiftLibraries.loadLibrary("swiftCore"); + SwiftLibraries.loadLibrary("SwiftKitSwift"); + SwiftLibraries.loadLibrary(LIB_NAME); if (PlatformUtils.isMacOS()) { return SymbolLookup.libraryLookup(System.mapLibraryName(LIB_NAME), LIBRARY_ARENA) @@ -386,7 +387,7 @@ extension FFMSwift2JavaGenerator { public String toString() { return getClass().getSimpleName() + "(" - + SwiftKit.nameOfSwiftType($swiftType().$memorySegment(), true) + + SwiftRuntime.nameOfSwiftType($swiftType().$memorySegment(), true) + ")@" + $memorySegment(); } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift index c61dd929..b4d73873 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift @@ -130,7 +130,7 @@ extension JNISwift2JavaGenerator { _ decl: ImportedFunc ) { let translatedDecl = self.translatedDecl(for: decl) - let parentName = translatedDecl.parentName ?? swiftModuleName + let parentName = translatedDecl.parentName let swiftReturnType = decl.functionSignature.result.type printCDecl(&printer, decl) { printer in diff --git a/Sources/JExtractSwiftLib/SwiftKit+Printing.swift b/Sources/JExtractSwiftLib/SwiftKit+Printing.swift index aa01502d..0afc9645 100644 --- a/Sources/JExtractSwiftLib/SwiftKit+Printing.swift +++ b/Sources/JExtractSwiftLib/SwiftKit+Printing.swift @@ -23,7 +23,7 @@ package struct SwiftKitPrinting { /// Forms syntax for a Java call to a swiftkit exposed function. static func renderCallGetSwiftType(module: String, nominal: ImportedNominalType) -> String { """ - SwiftKit.swiftjava.getType("\(module)", "\(nominal.swiftNominal.qualifiedName)") + SwiftRuntime.swiftjava.getType("\(module)", "\(nominal.swiftNominal.qualifiedName)") """ } } diff --git a/SwiftKit/build.gradle b/SwiftKitCore/build.gradle similarity index 87% rename from SwiftKit/build.gradle rename to SwiftKitCore/build.gradle index 8f3b6c51..3d5907f2 100644 --- a/SwiftKit/build.gradle +++ b/SwiftKitCore/build.gradle @@ -25,13 +25,15 @@ repositories { java { toolchain { - languageVersion.set(JavaLanguageVersion.of(24)) + // JDK 19 is the last JDK to support Java 7 + languageVersion.set(JavaLanguageVersion.of(19)) } + // Support Android 6+ (Java 7) + sourceCompatibility = JavaVersion.VERSION_1_7 } dependencies { - testImplementation(platform("org.junit:junit-bom:5.10.0")) - testImplementation("org.junit.jupiter:junit-jupiter") + testImplementation 'junit:junit:4.13.2' } tasks.test { diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/ClosableSwiftArena.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ClosableSwiftArena.java similarity index 96% rename from SwiftKit/src/main/java/org/swift/swiftkit/ClosableSwiftArena.java rename to SwiftKitCore/src/main/java/org/swift/swiftkit/core/ClosableSwiftArena.java index c257ae57..1a089069 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/ClosableSwiftArena.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ClosableSwiftArena.java @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.core; /** * Auto-closable version of {@link SwiftArena}. @@ -24,5 +24,4 @@ public interface ClosableSwiftArena extends SwiftArena, AutoCloseable { * Throws if unable to verify all resources have been release (e.g. over retained Swift classes) */ void close(); - } diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/ConfinedSwiftMemorySession.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ConfinedSwiftMemorySession.java similarity index 68% rename from SwiftKit/src/main/java/org/swift/swiftkit/ConfinedSwiftMemorySession.java rename to SwiftKitCore/src/main/java/org/swift/swiftkit/core/ConfinedSwiftMemorySession.java index 86725ae8..cd8f2dd1 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/ConfinedSwiftMemorySession.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ConfinedSwiftMemorySession.java @@ -12,15 +12,13 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.core; -import java.lang.foreign.Arena; -import java.lang.foreign.MemorySegment; import java.util.LinkedList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; -final class ConfinedSwiftMemorySession implements ClosableSwiftArena { +public class ConfinedSwiftMemorySession implements ClosableSwiftArena { final static int CLOSED = 0; final static int ACTIVE = 1; @@ -28,21 +26,17 @@ final class ConfinedSwiftMemorySession implements ClosableSwiftArena { final Thread owner; final AtomicInteger state; - final Arena arena; final ConfinedResourceList resources; public ConfinedSwiftMemorySession(Thread owner) { this.owner = owner; this.state = new AtomicInteger(ACTIVE); this.resources = new ConfinedResourceList(); - - this.arena = Arena.ofConfined(); } public void checkValid() throws RuntimeException { if (this.owner != null && this.owner != Thread.currentThread()) { - throw new WrongThreadException("ConfinedSwift arena is confined to %s but was closed from %s!" - .formatted(this.owner, Thread.currentThread())); + throw new WrongThreadException(String.format("ConfinedSwift arena is confined to %s but was closed from %s!", this.owner, Thread.currentThread())); } else if (this.state.get() < ACTIVE) { throw new RuntimeException("SwiftArena is already closed!"); } @@ -53,32 +47,19 @@ public void close() { checkValid(); // Cleanup all resources - if (this.state.compareAndExchange(ACTIVE, CLOSED) == ACTIVE) { + if (this.state.compareAndSet(ACTIVE, CLOSED)) { this.resources.runCleanup(); } // else, was already closed; do nothing - - this.arena.close(); } @Override public void register(SwiftInstance instance) { checkValid(); - var statusDestroyedFlag = instance.$statusDestroyedFlag(); - Runnable markAsDestroyed = () -> statusDestroyedFlag.set(true); - - var cleanup = new SwiftInstanceCleanup( - instance.$memorySegment(), - instance.$swiftType(), - markAsDestroyed); + SwiftInstanceCleanup cleanup = instance.createCleanupAction(); this.resources.add(cleanup); } - @Override - public MemorySegment allocate(long byteSize, long byteAlignment) { - return arena.allocate(byteSize, byteAlignment); - } - static final class ConfinedResourceList implements SwiftResourceList { // TODO: Could use intrusive linked list to avoid one indirection here final List resourceCleanups = new LinkedList<>(); diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java new file mode 100644 index 00000000..891745a2 --- /dev/null +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java @@ -0,0 +1,56 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit.core; + +import java.util.concurrent.atomic.AtomicBoolean; + +public abstract class JNISwiftInstance extends SwiftInstance { + /** + * The designated constructor of any imported Swift types. + * + * @param pointer a pointer to the memory containing the value + * @param arena the arena this object belongs to. When the arena goes out of scope, this value is destroyed. + */ + protected JNISwiftInstance(long pointer, SwiftArena arena) { + super(pointer, arena); + } + + /** + * Creates a function that will be called when the value should be destroyed. + * This will be code-generated to call a native method to do deinitialization and deallocation. + *

+ * The reason for this "indirection" is that we cannot have static methods on abstract classes, + * and we can't define the destroy method as a member method, because we assume that the wrapper + * has been released, when we destroy. + *

+ * Warning: The function must not capture {@code this}. + * + * @return a function that is called when the value should be destroyed. + */ + abstract Runnable $createDestroyFunction(); + + @Override + public SwiftInstanceCleanup createCleanupAction() { + final AtomicBoolean statusDestroyedFlag = $statusDestroyedFlag(); + Runnable markAsDestroyed = new Runnable() { + @Override + public void run() { + statusDestroyedFlag.set(true); + } + }; + + return new JNISwiftInstanceCleanup(this.$createDestroyFunction(), markAsDestroyed); + } +} diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstanceCleanup.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstanceCleanup.java new file mode 100644 index 00000000..08ddcdab --- /dev/null +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstanceCleanup.java @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit.core; + +class JNISwiftInstanceCleanup implements SwiftInstanceCleanup { + private final Runnable destroyFunction; + private final Runnable markAsDestroyed; + + public JNISwiftInstanceCleanup(Runnable destroyFunction, Runnable markAsDestroyed) { + this.destroyFunction = destroyFunction; + this.markAsDestroyed = markAsDestroyed; + } + + @Override + public void run() { + markAsDestroyed.run(); + destroyFunction.run(); + } +} diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftArena.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftArena.java similarity index 54% rename from SwiftKit/src/main/java/org/swift/swiftkit/SwiftArena.java rename to SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftArena.java index f50025cc..ed16d250 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftArena.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftArena.java @@ -12,10 +12,7 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; - -import java.lang.foreign.SegmentAllocator; -import java.util.concurrent.ThreadFactory; +package org.swift.swiftkit.core; /** * A Swift arena manages Swift allocated memory for classes, structs, enums etc. @@ -24,39 +21,17 @@ *

A confined arena has an associated owner thread that confines some operations to * associated owner thread such as {@link ClosableSwiftArena#close()}. */ -public interface SwiftArena extends SegmentAllocator { - - static ClosableSwiftArena ofConfined() { - return new ConfinedSwiftMemorySession(Thread.currentThread()); - } - - static SwiftArena ofAuto() { - ThreadFactory cleanerThreadFactory = r -> new Thread(r, "AutoSwiftArenaCleanerThread"); - return new AutoSwiftMemorySession(cleanerThreadFactory); - } - +public interface SwiftArena { /** * Register a Swift object. * Its memory should be considered managed by this arena, and be destroyed when the arena is closed. */ void register(SwiftInstance instance); - } /** * Represents a list of resources that need a cleanup, e.g. allocated classes/structs. */ interface SwiftResourceList { - void runCleanup(); - -} - - -final class UnexpectedRetainCountException extends RuntimeException { - public UnexpectedRetainCountException(Object resource, long retainCount, int expectedRetainCount) { - super(("Attempting to cleanup managed memory segment %s, but it's retain count was different than [%d] (was %d)! " + - "This would result in destroying a swift object that is still retained by other code somewhere." - ).formatted(resource, expectedRetainCount, retainCount)); - } } diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstance.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstance.java similarity index 70% rename from SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstance.java rename to SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstance.java index 5b8ff700..638cb8be 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstance.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstance.java @@ -12,24 +12,28 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.core; -import java.lang.foreign.GroupLayout; -import java.lang.foreign.MemorySegment; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Supplier; public abstract class SwiftInstance { /// Pointer to the "self". - private final MemorySegment selfMemorySegment; + private final long selfPointer; /** * The pointer to the instance in memory. I.e. the {@code self} of the Swift object or value. */ - public final MemorySegment $memorySegment() { - return this.selfMemorySegment; + public final long pointer() { + return this.selfPointer; } + /** + * Called when the arena has decided the value should be destroyed. + *

+ * Warning: The cleanup action must not capture {@code this}. + */ + public abstract SwiftInstanceCleanup createCleanupAction(); + // TODO: make this a flagset integer and/or use a field updater /** Used to track additional state of the underlying object, e.g. if it was explicitly destroyed. */ private final AtomicBoolean $state$destroyed = new AtomicBoolean(false); @@ -45,24 +49,14 @@ public abstract class SwiftInstance { return this.$state$destroyed; } - /** - * The in memory layout of an instance of this Swift type. - */ - public abstract GroupLayout $layout(); - - /** - * The Swift type metadata of this type. - */ - public abstract SwiftAnyType $swiftType(); - /** * The designated constructor of any imported Swift types. * - * @param segment the memory segment. + * @param pointer a pointer to the memory containing the value * @param arena the arena this object belongs to. When the arena goes out of scope, this value is destroyed. */ - protected SwiftInstance(MemorySegment segment, SwiftArena arena) { - this.selfMemorySegment = segment; + protected SwiftInstance(long pointer, SwiftArena arena) { + this.selfPointer = pointer; arena.register(this); } @@ -78,13 +72,4 @@ protected SwiftInstance(MemorySegment segment, SwiftArena arena) { throw new IllegalStateException("Attempted to call method on already destroyed instance of " + getClass().getSimpleName() + "!"); } } - - /** - * Returns `true` if this swift instance is a reference type, i.e. a `class` or (`distributed`) `actor`. - * - * @return `true` if this instance is a reference type, `false` otherwise. - */ - public boolean isReferenceType() { - return this instanceof SwiftHeapObject; - } } diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstanceCleanup.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstanceCleanup.java new file mode 100644 index 00000000..56416968 --- /dev/null +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstanceCleanup.java @@ -0,0 +1,20 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit.core; + +/** + * A Swift memory instance cleanup, e.g. count-down a reference count and destroy a class, or destroy struct/enum etc. + */ +public interface SwiftInstanceCleanup extends Runnable {} \ No newline at end of file diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftLibraries.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftLibraries.java new file mode 100644 index 00000000..2abdaff5 --- /dev/null +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftLibraries.java @@ -0,0 +1,83 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit.core; + +import org.swift.swiftkit.core.util.PlatformUtils; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; + +public final class SwiftLibraries { + + public static final String STDLIB_DYLIB_NAME = "swiftCore"; + public static final String SWIFTKITSWIFT_DYLIB_NAME = "SwiftKitSwift"; + public static final boolean TRACE_DOWNCALLS = Boolean.getBoolean("jextract.trace.downcalls"); + + private static final String STDLIB_MACOS_DYLIB_PATH = "/usr/lib/swift/libswiftCore.dylib"; + + @SuppressWarnings("unused") + private static final boolean INITIALIZED_LIBS = loadLibraries(false); + + public static boolean loadLibraries(boolean loadSwiftKit) { + System.loadLibrary(STDLIB_DYLIB_NAME); + if (loadSwiftKit) { + System.loadLibrary(SWIFTKITSWIFT_DYLIB_NAME); + } + return true; + } + + // ==== ------------------------------------------------------------------------------------------------------------ + // Loading libraries + + public static void loadLibrary(String libname) { + // TODO: avoid concurrent loadResource calls; one load is enough esp since we cause File IO when we do that + try { + // try to load a dylib from our classpath, e.g. when we included it in our jar + loadResourceLibrary(libname); + } catch (UnsatisfiedLinkError | RuntimeException e) { + // fallback to plain system path loading + System.loadLibrary(libname); + } + } + + public static void loadResourceLibrary(String libname) { + String resourceName = PlatformUtils.dynamicLibraryName(libname); + if (SwiftLibraries.TRACE_DOWNCALLS) { + System.out.println("[swift-java] Loading resource library: " + resourceName); + } + + try (InputStream libInputStream = SwiftLibraries.class.getResourceAsStream("/" + resourceName)) { + if (libInputStream == null) { + throw new RuntimeException("Expected library '" + libname + "' ('" + resourceName + "') was not found as resource!"); + } + + // TODO: we could do an in memory file system here + File tempFile = File.createTempFile(libname, ""); + tempFile.deleteOnExit(); + Files.copy(libInputStream, tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + + System.load(tempFile.getAbsolutePath()); + } catch (IOException e) { + throw new RuntimeException("Failed to load dynamic library '" + libname + "' ('" + resourceName + "') as resource!", e); + } + } + + public static String getJavaLibraryPath() { + return System.getProperty("java.library.path"); + } +} diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValue.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftValue.java similarity index 94% rename from SwiftKit/src/main/java/org/swift/swiftkit/SwiftValue.java rename to SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftValue.java index a364c012..3e9c1aff 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValue.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftValue.java @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.core; /** * Represent a wrapper around a Swift value object. e.g. {@code struct} or {@code enum}. diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/ManagedSwiftType.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/WrongThreadException.java similarity index 67% rename from SwiftKit/src/main/java/org/swift/swiftkit/ManagedSwiftType.java rename to SwiftKitCore/src/main/java/org/swift/swiftkit/core/WrongThreadException.java index da25ae4d..d15436f9 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/ManagedSwiftType.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/WrongThreadException.java @@ -12,14 +12,10 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; - -import java.lang.foreign.MemorySegment; - -public interface ManagedSwiftType { - /** - * The memory segment of `self` of the managed Swift object/value. - */ - public MemorySegment $memorySegment(); +package org.swift.swiftkit.core; +public class WrongThreadException extends RuntimeException { + public WrongThreadException(String message) { + super(message); + } } diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/util/PlatformUtils.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/util/PlatformUtils.java similarity index 97% rename from SwiftKit/src/main/java/org/swift/swiftkit/util/PlatformUtils.java rename to SwiftKitCore/src/main/java/org/swift/swiftkit/core/util/PlatformUtils.java index 6addb31d..667bd53b 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/util/PlatformUtils.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/util/PlatformUtils.java @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit.util; +package org.swift.swiftkit.core.util; public class PlatformUtils { public static boolean isLinux() { diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/util/StringUtils.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/util/StringUtils.java similarity index 96% rename from SwiftKit/src/main/java/org/swift/swiftkit/util/StringUtils.java rename to SwiftKitCore/src/main/java/org/swift/swiftkit/core/util/StringUtils.java index 6753ea73..1ce4259c 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/util/StringUtils.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/util/StringUtils.java @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit.util; +package org.swift.swiftkit.core.util; public class StringUtils { public static String stripPrefix(String mangledName, String prefix) { diff --git a/SwiftKitFFM/build.gradle b/SwiftKitFFM/build.gradle new file mode 100644 index 00000000..22f88001 --- /dev/null +++ b/SwiftKitFFM/build.gradle @@ -0,0 +1,87 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +plugins { + id("build-logic.java-application-conventions") +} + +group = "org.swift.swiftkit" +version = "1.0-SNAPSHOT" + +repositories { + mavenCentral() +} + +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(24)) + } +} + +dependencies { + implementation(project(':SwiftKitCore')) + + testImplementation(platform("org.junit:junit-bom:5.10.0")) + testImplementation("org.junit.jupiter:junit-jupiter") +} + +testing { + suites { + test { + useJUnitJupiter('5.10.3') + } + } +} + +tasks.test { + useJUnitPlatform() + testLogging { + events("passed", "skipped", "failed") + } +} + +/// Enable access to preview APIs, e.g. java.lang.foreign.* (Panama) +tasks.withType(JavaCompile).configureEach { + options.compilerArgs.add("--enable-preview") + options.compilerArgs.add("-Xlint:preview") +} + +// SwiftKit depends on SwiftKitSwift (Swift library that this Java library calls into) + +def compileSwift = tasks.register("compileSwift", Exec) { + description "Compile the swift-java SwiftKitSwift dynamic library that SwiftKit (Java) calls into" + + inputs.file(new File(rootDir, "Package.swift")) + inputs.dir(new File(rootDir, "Sources/")) // a bit generous, but better safe than sorry, and include all Swift source changes + outputs.dir(new File(rootDir, ".build")) + + workingDir = rootDir + commandLine "swift" + args("build", "--target", "SwiftKitSwift") +} +tasks.build { + dependsOn("compileSwift") +} + + + +def cleanSwift = tasks.register("cleanSwift", Exec) { + workingDir = rootDir + commandLine "swift" + args("package", "clean") +} +tasks.clean { + dependsOn("cleanSwift") +} + diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/AutoSwiftMemorySession.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/AllocatingAutoSwiftMemorySession.java similarity index 78% rename from SwiftKit/src/main/java/org/swift/swiftkit/AutoSwiftMemorySession.java rename to SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/AllocatingAutoSwiftMemorySession.java index ecbe836e..fecd5202 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/AutoSwiftMemorySession.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/AllocatingAutoSwiftMemorySession.java @@ -12,7 +12,10 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.ffm; + +import org.swift.swiftkit.core.SwiftArena; +import org.swift.swiftkit.core.SwiftInstance; import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; @@ -26,7 +29,7 @@ *

When registered Java wrapper classes around native Swift instances {@link SwiftInstance}, * are eligible for collection, this will trigger the cleanup of the native resources as well. * - *

This memory session is LESS reliable than using a {@link ConfinedSwiftMemorySession} because + *

This memory session is LESS reliable than using a {@link FFMConfinedSwiftMemorySession} because * the timing of when the native resources are cleaned up is somewhat undefined, and rely on the * system GC. Meaning, that if an object nas been promoted to an old generation, there may be a * long time between the resource no longer being referenced "in Java" and its native memory being released, @@ -37,12 +40,12 @@ * *

Whenever possible, prefer using an explicitly managed {@link SwiftArena}, such as {@link SwiftArena#ofConfined()}. */ -final class AutoSwiftMemorySession implements SwiftArena { +final class AllocatingAutoSwiftMemorySession implements AllocatingSwiftArena { private final Arena arena; private final Cleaner cleaner; - public AutoSwiftMemorySession(ThreadFactory cleanerThreadFactory) { + public AllocatingAutoSwiftMemorySession(ThreadFactory cleanerThreadFactory) { this.cleaner = Cleaner.create(cleanerThreadFactory); this.arena = Arena.ofAuto(); } @@ -51,12 +54,9 @@ public AutoSwiftMemorySession(ThreadFactory cleanerThreadFactory) { public void register(SwiftInstance instance) { Objects.requireNonNull(instance, "value"); - // We're doing this dance to avoid keeping a strong reference to the value itself - var statusDestroyedFlag = instance.$statusDestroyedFlag(); - Runnable markAsDestroyed = () -> statusDestroyedFlag.set(true); - - MemorySegment resource = instance.$memorySegment(); - var cleanupAction = new SwiftInstanceCleanup(resource, instance.$swiftType(), markAsDestroyed); + // We make sure we don't capture `instance` in the + // cleanup action, so we can ignore the warning below. + var cleanupAction = instance.createCleanupAction(); cleaner.register(instance, cleanupAction); } @@ -64,4 +64,4 @@ public void register(SwiftInstance instance) { public MemorySegment allocate(long byteSize, long byteAlignment) { return arena.allocate(byteSize, byteAlignment); } -} +} \ No newline at end of file diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/AllocatingSwiftArena.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/AllocatingSwiftArena.java new file mode 100644 index 00000000..08fad15b --- /dev/null +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/AllocatingSwiftArena.java @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit.ffm; + +import org.swift.swiftkit.core.SwiftArena; + +import java.lang.foreign.MemorySegment; +import java.lang.foreign.SegmentAllocator; +import java.util.concurrent.ThreadFactory; + +public interface AllocatingSwiftArena extends SwiftArena, SegmentAllocator { + MemorySegment allocate(long byteSize, long byteAlignment); + + static ClosableAllocatingSwiftArena ofConfined() { + return new FFMConfinedSwiftMemorySession(Thread.currentThread()); + } + + static AllocatingSwiftArena ofAuto() { + ThreadFactory cleanerThreadFactory = r -> new Thread(r, "AutoSwiftArenaCleanerThread"); + return new AllocatingAutoSwiftMemorySession(cleanerThreadFactory); + } +} diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/ClosableAllocatingSwiftArena.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/ClosableAllocatingSwiftArena.java new file mode 100644 index 00000000..70cdcbb6 --- /dev/null +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/ClosableAllocatingSwiftArena.java @@ -0,0 +1,22 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit.ffm; + +import org.swift.swiftkit.core.ClosableSwiftArena; + +/** + * Auto-closable version of {@link AllocatingSwiftArena}. + */ +public interface ClosableAllocatingSwiftArena extends ClosableSwiftArena, AllocatingSwiftArena {} diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMConfinedSwiftMemorySession.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMConfinedSwiftMemorySession.java new file mode 100644 index 00000000..424e54b6 --- /dev/null +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMConfinedSwiftMemorySession.java @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit.ffm; + +import org.swift.swiftkit.core.ConfinedSwiftMemorySession; + +import java.lang.foreign.Arena; +import java.lang.foreign.MemorySegment; + +final class FFMConfinedSwiftMemorySession extends ConfinedSwiftMemorySession implements AllocatingSwiftArena, ClosableAllocatingSwiftArena { + final Arena arena; + + public FFMConfinedSwiftMemorySession(Thread owner) { + super(owner); + this.arena = Arena.ofConfined(); + } + + @Override + public void close() { + super.close(); + this.arena.close(); + } + + @Override + public MemorySegment allocate(long byteSize, long byteAlignment) { + return arena.allocate(byteSize, byteAlignment); + } +} diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstance.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstance.java new file mode 100644 index 00000000..f4a01aa4 --- /dev/null +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstance.java @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift.org project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift.org project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +package org.swift.swiftkit.ffm; + +import org.swift.swiftkit.core.SwiftInstance; +import org.swift.swiftkit.core.SwiftInstanceCleanup; + +import java.lang.foreign.MemorySegment; + +public abstract class FFMSwiftInstance extends SwiftInstance { + private final MemorySegment memorySegment; + + /** + * The pointer to the instance in memory. I.e. the {@code self} of the Swift object or value. + */ + public final MemorySegment $memorySegment() { + return this.memorySegment; + } + + /** + * The Swift type metadata of this type. + */ + public abstract SwiftAnyType $swiftType(); + + /** + * The designated constructor of any imported Swift types. + * + * @param segment the memory segment. + * @param arena the arena this object belongs to. When the arena goes out of scope, this value is destroyed. + */ + protected FFMSwiftInstance(MemorySegment segment, AllocatingSwiftArena arena) { + super(segment.address(), arena); + this.memorySegment = segment; + } + + @Override + public SwiftInstanceCleanup createCleanupAction() { + var statusDestroyedFlag = $statusDestroyedFlag(); + Runnable markAsDestroyed = () -> statusDestroyedFlag.set(true); + + return new FFMSwiftInstanceCleanup( + $memorySegment(), + $swiftType(), + markAsDestroyed + ); + } + + + /** + * Returns `true` if this swift instance is a reference type, i.e. a `class` or (`distributed`) `actor`. + * + * @return `true` if this instance is a reference type, `false` otherwise. + */ + public boolean isReferenceType() { + return this instanceof SwiftHeapObject; + } +} diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstanceCleanup.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstanceCleanup.java similarity index 63% rename from SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstanceCleanup.java rename to SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstanceCleanup.java index a9fdd9c8..a5d0829a 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftInstanceCleanup.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstanceCleanup.java @@ -12,18 +12,22 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.ffm; + +import org.swift.swiftkit.core.SwiftInstanceCleanup; import java.lang.foreign.MemorySegment; -/** - * A Swift memory instance cleanup, e.g. count-down a reference count and destroy a class, or destroy struct/enum etc. - */ -record SwiftInstanceCleanup( - MemorySegment selfPointer, - SwiftAnyType selfType, - Runnable markAsDestroyed -) implements Runnable { +public class FFMSwiftInstanceCleanup implements SwiftInstanceCleanup { + private final MemorySegment selfPointer; + private final SwiftAnyType selfType; + private final Runnable markAsDestroyed; + + public FFMSwiftInstanceCleanup(MemorySegment selfPointer, SwiftAnyType selfType, Runnable markAsDestroyed) { + this.selfPointer = selfPointer; + this.selfType = selfType; + this.markAsDestroyed = markAsDestroyed; + } @Override public void run() { diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/MemorySegmentUtils.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/MemorySegmentUtils.java similarity index 97% rename from SwiftKit/src/main/java/org/swift/swiftkit/MemorySegmentUtils.java rename to SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/MemorySegmentUtils.java index 660a5500..0890b1d8 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/MemorySegmentUtils.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/MemorySegmentUtils.java @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.ffm; import java.lang.foreign.MemorySegment; import java.lang.foreign.ValueLayout; diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftAnyType.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftAnyType.java similarity index 89% rename from SwiftKit/src/main/java/org/swift/swiftkit/SwiftAnyType.java rename to SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftAnyType.java index 4d13ecb7..3915725b 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftAnyType.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftAnyType.java @@ -12,7 +12,10 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.ffm; + +import org.swift.swiftkit.ffm.SwiftRuntime; +import org.swift.swiftkit.ffm.SwiftValueLayout; import java.lang.foreign.GroupLayout; import java.lang.foreign.MemoryLayout; @@ -46,7 +49,7 @@ public SwiftAnyType(MemorySegment memorySegment) { * Get the human-readable Swift type name of this type. */ public String getSwiftName() { - return SwiftKit.nameOfSwiftType(memorySegment, true); + return SwiftRuntime.nameOfSwiftType(memorySegment, true); } @Override diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftHeapObject.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftHeapObject.java similarity index 91% rename from SwiftKit/src/main/java/org/swift/swiftkit/SwiftHeapObject.java rename to SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftHeapObject.java index 89050fb5..b506be90 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftHeapObject.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftHeapObject.java @@ -12,7 +12,8 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.ffm; + import java.lang.foreign.MemorySegment; @@ -25,7 +26,7 @@ public interface SwiftHeapObject { /** * Pointer to the instance. */ - public default MemorySegment $instance() { + default MemorySegment $instance() { return this.$memorySegment().get(SwiftValueLayout.SWIFT_POINTER, 0); } } diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftRuntime.java similarity index 88% rename from SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java rename to SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftRuntime.java index 9c04eded..f734bbef 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftRuntime.java @@ -12,28 +12,22 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.ffm; -import org.swift.swiftkit.util.PlatformUtils; +import org.swift.swiftkit.core.util.PlatformUtils; -import java.io.File; -import java.io.IOException; import java.lang.foreign.*; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; -import java.nio.file.CopyOption; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; import java.util.Arrays; import java.util.Optional; import java.util.stream.Collectors; -import static org.swift.swiftkit.util.StringUtils.stripPrefix; -import static org.swift.swiftkit.util.StringUtils.stripSuffix; +import static org.swift.swiftkit.core.util.StringUtils.stripPrefix; +import static org.swift.swiftkit.core.util.StringUtils.stripSuffix; -public class SwiftKit { +public class SwiftRuntime { public static final String STDLIB_DYLIB_NAME = "swiftCore"; public static final String SWIFTKITSWIFT_DYLIB_NAME = "SwiftKitSwift"; @@ -68,7 +62,7 @@ private static SymbolLookup getSymbolLookup() { } } - public SwiftKit() { + public SwiftRuntime() { } public static void traceDowncall(Object... args) { @@ -103,50 +97,10 @@ static MemorySegment findOrThrow(String symbol) { .orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol: %s".formatted(symbol))); } - public static String getJavaLibraryPath() { - return System.getProperty("java.library.path"); - } - public static boolean getJextractTraceDowncalls() { return Boolean.getBoolean("jextract.trace.downcalls"); } - // ==== ------------------------------------------------------------------------------------------------------------ - // Loading libraries - - public static void loadLibrary(String libname) { - // TODO: avoid concurrent loadResource calls; one load is enough esp since we cause File IO when we do that - try { - // try to load a dylib from our classpath, e.g. when we included it in our jar - loadResourceLibrary(libname); - } catch (UnsatisfiedLinkError | RuntimeException e) { - // fallback to plain system path loading - System.loadLibrary(libname); - } - } - - public static void loadResourceLibrary(String libname) { - var resourceName = PlatformUtils.dynamicLibraryName(libname); - if (SwiftKit.TRACE_DOWNCALLS) { - System.out.println("[swift-java] Loading resource library: " + resourceName); - } - - try (var libInputStream = SwiftKit.class.getResourceAsStream("/" + resourceName)) { - if (libInputStream == null) { - throw new RuntimeException("Expected library '" + libname + "' ('" + resourceName + "') was not found as resource!"); - } - - // TODO: we could do an in memory file system here - var tempFile = File.createTempFile(libname, ""); - tempFile.deleteOnExit(); - Files.copy(libInputStream, tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING); - - System.load(tempFile.getAbsolutePath()); - } catch (IOException e) { - throw new RuntimeException("Failed to load dynamic library '" + libname + "' ('" + resourceName + "') as resource!", e); - } - } - // ==== ------------------------------------------------------------------------------------------------------------ // free diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueLayout.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftValueLayout.java similarity index 98% rename from SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueLayout.java rename to SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftValueLayout.java index 00215ef0..c0a75144 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueLayout.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftValueLayout.java @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.ffm; import java.lang.foreign.AddressLayout; import java.lang.foreign.MemoryLayout; diff --git a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftValueWitnessTable.java similarity index 94% rename from SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java rename to SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftValueWitnessTable.java index 8ddff1b6..a0a6a79f 100644 --- a/SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftValueWitnessTable.java @@ -12,13 +12,12 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.ffm; import java.lang.foreign.*; import java.lang.invoke.*; import static java.lang.foreign.ValueLayout.JAVA_BYTE; -import static org.swift.swiftkit.SwiftKit.getSwiftInt; public abstract class SwiftValueWitnessTable { @@ -86,7 +85,7 @@ public static MemorySegment valueWitnessTable(MemorySegment typeMetadata) { * @param typeMetadata the memory segment must point to a Swift metadata */ public static long sizeOfSwiftType(MemorySegment typeMetadata) { - return getSwiftInt(valueWitnessTable(typeMetadata), SwiftValueWitnessTable.$size$offset); + return SwiftRuntime.getSwiftInt(valueWitnessTable(typeMetadata), SwiftValueWitnessTable.$size$offset); } @@ -112,7 +111,7 @@ public static long sizeOfSwiftType(MemorySegment typeMetadata) { * @param typeMetadata the memory segment must point to a Swift metadata */ public static long strideOfSwiftType(MemorySegment typeMetadata) { - return getSwiftInt(valueWitnessTable(typeMetadata), SwiftValueWitnessTable.$stride$offset); + return SwiftRuntime.getSwiftInt(valueWitnessTable(typeMetadata), SwiftValueWitnessTable.$stride$offset); } @@ -122,7 +121,7 @@ public static long strideOfSwiftType(MemorySegment typeMetadata) { * @param typeMetadata the memory segment must point to a Swift metadata */ public static long alignmentOfSwiftType(MemorySegment typeMetadata) { - long flags = getSwiftInt(valueWitnessTable(typeMetadata), SwiftValueWitnessTable.$flags$offset); + long flags = SwiftRuntime.getSwiftInt(valueWitnessTable(typeMetadata), SwiftValueWitnessTable.$flags$offset); return (flags & 0xFF) + 1; } @@ -156,7 +155,7 @@ public static MemoryLayout layoutOfSwiftType(MemorySegment typeMetadata) { return MemoryLayout.structLayout( layouts - ).withName(SwiftKit.nameOfSwiftType(typeMetadata, true)); + ).withName(SwiftRuntime.nameOfSwiftType(typeMetadata, true)); } @@ -198,7 +197,7 @@ static MemorySegment addr(SwiftAnyType ty) { final var vwt = SwiftValueWitnessTable.valueWitnessTable(ty.$memorySegment()); // Get the address of the destroy function stored at the offset of the witness table - long funcAddress = getSwiftInt(vwt, destroy.$offset); + long funcAddress = SwiftRuntime.getSwiftInt(vwt, destroy.$offset); return MemorySegment.ofAddress(funcAddress); } @@ -258,7 +257,7 @@ static MemorySegment addr(SwiftAnyType ty) { final var vwt = SwiftValueWitnessTable.valueWitnessTable(ty.$memorySegment()); // Get the address of the function stored at the offset of the witness table - long funcAddress = getSwiftInt(vwt, initializeWithCopy.$offset); + long funcAddress = SwiftRuntime.getSwiftInt(vwt, initializeWithCopy.$offset); return MemorySegment.ofAddress(funcAddress); } diff --git a/SwiftKit/src/test/java/org/swift/swiftkit/AutoArenaTest.java b/SwiftKitFFM/src/test/java/org/swift/swiftkit/ffm/AutoArenaTest.java similarity index 78% rename from SwiftKit/src/test/java/org/swift/swiftkit/AutoArenaTest.java rename to SwiftKitFFM/src/test/java/org/swift/swiftkit/ffm/AutoArenaTest.java index 23365de9..b95f6c45 100644 --- a/SwiftKit/src/test/java/org/swift/swiftkit/AutoArenaTest.java +++ b/SwiftKitFFM/src/test/java/org/swift/swiftkit/ffm/AutoArenaTest.java @@ -12,21 +12,19 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; +package org.swift.swiftkit.ffm; import org.junit.jupiter.api.Test; import java.lang.foreign.GroupLayout; import java.lang.foreign.MemorySegment; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.atomic.AtomicBoolean; public class AutoArenaTest { @Test @SuppressWarnings("removal") // System.runFinalization() will be removed public void cleaner_releases_native_resource() { - SwiftArena arena = SwiftArena.ofAuto(); + AllocatingSwiftArena arena = AllocatingSwiftArena.ofAuto(); // This object is registered to the arena. var object = new FakeSwiftInstance(arena); @@ -48,16 +46,11 @@ public void cleaner_releases_native_resource() { } } - private static class FakeSwiftInstance extends SwiftInstance implements SwiftHeapObject { - public FakeSwiftInstance(SwiftArena arena) { + private static class FakeSwiftInstance extends FFMSwiftInstance implements SwiftHeapObject { + public FakeSwiftInstance(AllocatingSwiftArena arena) { super(MemorySegment.NULL, arena); } - @Override - public GroupLayout $layout() { - return null; - } - @Override public SwiftAnyType $swiftType() { return null; diff --git a/SwiftKit/src/test/java/org/swift/swiftkit/SwiftRuntimeMetadataTest.java b/SwiftKitFFM/src/test/java/org/swift/swiftkit/ffm/SwiftRuntimeMetadataTest.java similarity index 95% rename from SwiftKit/src/test/java/org/swift/swiftkit/SwiftRuntimeMetadataTest.java rename to SwiftKitFFM/src/test/java/org/swift/swiftkit/ffm/SwiftRuntimeMetadataTest.java index 3419405e..0ec82123 100644 --- a/SwiftKit/src/test/java/org/swift/swiftkit/SwiftRuntimeMetadataTest.java +++ b/SwiftKitFFM/src/test/java/org/swift/swiftkit/ffm/SwiftRuntimeMetadataTest.java @@ -12,11 +12,7 @@ // //===----------------------------------------------------------------------===// -package org.swift.swiftkit; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; +package org.swift.swiftkit.ffm; public class SwiftRuntimeMetadataTest { diff --git a/Tests/JExtractSwiftTests/ClassPrintingTests.swift b/Tests/JExtractSwiftTests/ClassPrintingTests.swift index 6c0d8d0a..12b11d38 100644 --- a/Tests/JExtractSwiftTests/ClassPrintingTests.swift +++ b/Tests/JExtractSwiftTests/ClassPrintingTests.swift @@ -44,7 +44,7 @@ struct ClassPrintingTests { try assertOutput(input: class_interfaceFile, .ffm, .java, swiftModuleName: "__FakeModule", expectedChunks: [ """ public static final SwiftAnyType TYPE_METADATA = - new SwiftAnyType(SwiftKit.swiftjava.getType("__FakeModule", "MySwiftClass")); + new SwiftAnyType(SwiftRuntime.swiftjava.getType("__FakeModule", "MySwiftClass")); public final SwiftAnyType $swiftType() { return TYPE_METADATA; } diff --git a/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift b/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift index d81dad8c..5f80dd28 100644 --- a/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift +++ b/Tests/JExtractSwiftTests/FuncCallbackImportTests.swift @@ -77,8 +77,8 @@ final class FuncCallbackImportTests { private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static void call(java.lang.foreign.MemorySegment callback) { try { - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(callback); + if (SwiftRuntime.TRACE_DOWNCALLS) { + SwiftRuntime.traceDowncall(callback); } HANDLE.invokeExact(callback); } catch (Throwable ex$) { @@ -96,7 +96,7 @@ final class FuncCallbackImportTests { void apply(); } private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(); - private static final MethodHandle HANDLE = SwiftKit.upcallHandle(Function.class, "apply", DESC); + private static final MethodHandle HANDLE = SwiftRuntime.upcallHandle(Function.class, "apply", DESC); private static MemorySegment toUpcallStub(Function fi, Arena arena) { return Linker.nativeLinker().upcallStub(HANDLE.bindTo(fi), DESC, arena); } @@ -167,8 +167,8 @@ final class FuncCallbackImportTests { private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static void call(java.lang.foreign.MemorySegment callback, java.lang.foreign.MemorySegment fn) { try { - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(callback, fn); + if (SwiftRuntime.TRACE_DOWNCALLS) { + SwiftRuntime.traceDowncall(callback, fn); } HANDLE.invokeExact(callback, fn); } catch (Throwable ex$) { @@ -190,7 +190,7 @@ final class FuncCallbackImportTests { /* _0: */SwiftValueLayout.SWIFT_POINTER, /* _1: */SwiftValueLayout.SWIFT_FLOAT ); - private static final MethodHandle HANDLE = SwiftKit.upcallHandle(Function.class, "apply", DESC); + private static final MethodHandle HANDLE = SwiftRuntime.upcallHandle(Function.class, "apply", DESC); private static MemorySegment toUpcallStub(Function fi, Arena arena) { return Linker.nativeLinker().upcallStub(HANDLE.bindTo(fi), DESC, arena); } @@ -206,7 +206,7 @@ final class FuncCallbackImportTests { void apply(); } private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(); - private static final MethodHandle HANDLE = SwiftKit.upcallHandle(Function.class, "apply", DESC); + private static final MethodHandle HANDLE = SwiftRuntime.upcallHandle(Function.class, "apply", DESC); private static MemorySegment toUpcallStub(Function fi, Arena arena) { return Linker.nativeLinker().upcallStub(HANDLE.bindTo(fi), DESC, arena); } @@ -281,8 +281,8 @@ final class FuncCallbackImportTests { private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static void call(java.lang.foreign.MemorySegment body) { try { - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(body); + if (SwiftRuntime.TRACE_DOWNCALLS) { + SwiftRuntime.traceDowncall(body); } HANDLE.invokeExact(body); } catch (Throwable ex$) { @@ -304,7 +304,7 @@ final class FuncCallbackImportTests { /* _0: */SwiftValueLayout.SWIFT_POINTER, /* _1: */SwiftValueLayout.SWIFT_INT ); - private static final MethodHandle HANDLE = SwiftKit.upcallHandle(Function.class, "apply", DESC); + private static final MethodHandle HANDLE = SwiftRuntime.upcallHandle(Function.class, "apply", DESC); private static MemorySegment toUpcallStub(Function fi, Arena arena) { return Linker.nativeLinker().upcallStub(HANDLE.bindTo(fi), DESC, arena); } diff --git a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift index 7af3c706..a714367e 100644 --- a/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift +++ b/Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift @@ -66,8 +66,8 @@ final class FunctionDescriptorTests { private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static void call(long i) { try { - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(i); + if (SwiftRuntime.TRACE_DOWNCALLS) { + SwiftRuntime.traceDowncall(i); } HANDLE.invokeExact(i); } catch (Throwable ex$) { @@ -102,8 +102,8 @@ final class FunctionDescriptorTests { private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static void call(long l, int i32) { try { - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(l, i32); + if (SwiftRuntime.TRACE_DOWNCALLS) { + SwiftRuntime.traceDowncall(l, i32); } HANDLE.invokeExact(l, i32); } catch (Throwable ex$) { @@ -138,8 +138,8 @@ final class FunctionDescriptorTests { private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static long call(long i) { try { - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(i); + if (SwiftRuntime.TRACE_DOWNCALLS) { + SwiftRuntime.traceDowncall(i); } return (long) HANDLE.invokeExact(i); } catch (Throwable ex$) { @@ -174,8 +174,8 @@ final class FunctionDescriptorTests { private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static int call(java.lang.foreign.MemorySegment self) { try { - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(self); + if (SwiftRuntime.TRACE_DOWNCALLS) { + SwiftRuntime.traceDowncall(self); } return (int) HANDLE.invokeExact(self); } catch (Throwable ex$) { @@ -209,8 +209,8 @@ final class FunctionDescriptorTests { private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static void call(int newValue, java.lang.foreign.MemorySegment self) { try { - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(newValue, self); + if (SwiftRuntime.TRACE_DOWNCALLS) { + SwiftRuntime.traceDowncall(newValue, self); } HANDLE.invokeExact(newValue, self); } catch (Throwable ex$) { diff --git a/Tests/JExtractSwiftTests/MethodImportTests.swift b/Tests/JExtractSwiftTests/MethodImportTests.swift index 36610dcd..118ca789 100644 --- a/Tests/JExtractSwiftTests/MethodImportTests.swift +++ b/Tests/JExtractSwiftTests/MethodImportTests.swift @@ -180,7 +180,7 @@ final class MethodImportTests { */ public static void globalTakeIntLongString(int i32, long l, java.lang.String s) { try(var arena$ = Arena.ofConfined()) { - swiftjava___FakeModule_globalTakeIntLongString_i32_l_s.call(i32, l, SwiftKit.toCString(s, arena$)); + swiftjava___FakeModule_globalTakeIntLongString_i32_l_s.call(i32, l, SwiftRuntime.toCString(s, arena$)); } } """ @@ -222,7 +222,7 @@ final class MethodImportTests { * public func globalReturnClass() -> MySwiftClass * } */ - public static MySwiftClass globalReturnClass(SwiftArena swiftArena$) { + public static MySwiftClass globalReturnClass(AllocatingSwiftArena swiftArena$) { MemorySegment _result = swiftArena$.allocate(MySwiftClass.$LAYOUT); swiftjava___FakeModule_globalReturnClass.call(_result); return new MySwiftClass(_result, swiftArena$); @@ -396,7 +396,7 @@ final class MethodImportTests { * public init(len: Swift.Int, cap: Swift.Int) * } */ - public static MySwiftClass init(long len, long cap, SwiftArena swiftArena$) { + public static MySwiftClass init(long len, long cap, AllocatingSwiftArena swiftArena$) { MemorySegment _result = swiftArena$.allocate(MySwiftClass.$LAYOUT); swiftjava___FakeModule_MySwiftClass_init_len_cap.call(len, cap, _result) return new MySwiftClass(_result, swiftArena$); @@ -440,7 +440,7 @@ final class MethodImportTests { * public init(len: Swift.Int, cap: Swift.Int) * } */ - public static MySwiftStruct init(long len, long cap, SwiftArena swiftArena$) { + public static MySwiftStruct init(long len, long cap, AllocatingSwiftArena swiftArena$) { MemorySegment _result = swiftArena$.allocate(MySwiftStruct.$LAYOUT); swiftjava___FakeModule_MySwiftStruct_init_len_cap.call(len, cap, _result) return new MySwiftStruct(_result, swiftArena$); diff --git a/Tests/JExtractSwiftTests/StringPassingTests.swift b/Tests/JExtractSwiftTests/StringPassingTests.swift index 99dfab5c..6a5c1c80 100644 --- a/Tests/JExtractSwiftTests/StringPassingTests.swift +++ b/Tests/JExtractSwiftTests/StringPassingTests.swift @@ -45,8 +45,8 @@ final class StringPassingTests { private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static long call(java.lang.foreign.MemorySegment string) { try { - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(string); + if (SwiftRuntime.TRACE_DOWNCALLS) { + SwiftRuntime.traceDowncall(string); } return (long) HANDLE.invokeExact(string); } catch (Throwable ex$) { @@ -64,7 +64,7 @@ final class StringPassingTests { */ public static long writeString(java.lang.String string) { try(var arena$ = Arena.ofConfined()) { - return swiftjava___FakeModule_writeString_string.call(SwiftKit.toCString(string, arena$)); + return swiftjava___FakeModule_writeString_string.call(SwiftRuntime.toCString(string, arena$)); } } """ diff --git a/Tests/JExtractSwiftTests/VariableImportTests.swift b/Tests/JExtractSwiftTests/VariableImportTests.swift index 33f41e20..e0a6678c 100644 --- a/Tests/JExtractSwiftTests/VariableImportTests.swift +++ b/Tests/JExtractSwiftTests/VariableImportTests.swift @@ -51,8 +51,8 @@ final class VariableImportTests { private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static long call(java.lang.foreign.MemorySegment self) { try { - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(self); + if (SwiftRuntime.TRACE_DOWNCALLS) { + SwiftRuntime.traceDowncall(self); } return (long) HANDLE.invokeExact(self); } catch (Throwable ex$) { @@ -84,8 +84,8 @@ final class VariableImportTests { private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static void call(long newValue, java.lang.foreign.MemorySegment self) { try { - if (SwiftKit.TRACE_DOWNCALLS) { - SwiftKit.traceDowncall(newValue, self); + if (SwiftRuntime.TRACE_DOWNCALLS) { + SwiftRuntime.traceDowncall(newValue, self); } HANDLE.invokeExact(newValue, self); } catch (Throwable ex$) { diff --git a/settings.gradle b/settings.gradle index fa0fa5bd..9bf38ba5 100644 --- a/settings.gradle +++ b/settings.gradle @@ -18,7 +18,8 @@ pluginManagement { rootProject.name = "swift-java" -include "SwiftKit" +include "SwiftKitCore" +include "SwiftKitFFM" // Include sample apps -- you can run them via `gradle Name:run` new File(rootDir, "Samples").listFiles().each {