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 3b083cc0..cecb1231 100644 --- a/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java +++ b/Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java @@ -18,6 +18,7 @@ // Import javakit/swiftkit support libraries +import org.swift.swiftkit.core.CallTraces; import org.swift.swiftkit.core.SwiftLibraries; import org.swift.swiftkit.ffm.AllocatingSwiftArena; import org.swift.swiftkit.ffm.SwiftRuntime; @@ -43,30 +44,30 @@ static void examples() { long cnt = MySwiftLibrary.globalWriteString("String from Java"); - SwiftRuntime.trace("count = " + cnt); + CallTraces.trace("count = " + cnt); MySwiftLibrary.globalCallMeRunnable(() -> { - SwiftRuntime.trace("running runnable"); + CallTraces.trace("running runnable"); }); - SwiftRuntime.trace("getGlobalBuffer().byteSize()=" + MySwiftLibrary.getGlobalBuffer().byteSize()); + CallTraces.trace("getGlobalBuffer().byteSize()=" + MySwiftLibrary.getGlobalBuffer().byteSize()); MySwiftLibrary.withBuffer((buf) -> { - SwiftRuntime.trace("withBuffer{$0.byteSize()}=" + buf.byteSize()); + CallTraces.trace("withBuffer{$0.byteSize()}=" + buf.byteSize()); }); // Example of using an arena; MyClass.deinit is run at end of scope try (var arena = AllocatingSwiftArena.ofConfined()) { MySwiftClass obj = MySwiftClass.init(2222, 7777, arena); // just checking retains/releases work - SwiftRuntime.trace("retainCount = " + SwiftRuntime.retainCount(obj)); + CallTraces.trace("retainCount = " + SwiftRuntime.retainCount(obj)); SwiftRuntime.retain(obj); - SwiftRuntime.trace("retainCount = " + SwiftRuntime.retainCount(obj)); + CallTraces.trace("retainCount = " + SwiftRuntime.retainCount(obj)); SwiftRuntime.release(obj); - SwiftRuntime.trace("retainCount = " + SwiftRuntime.retainCount(obj)); + CallTraces.trace("retainCount = " + SwiftRuntime.retainCount(obj)); obj.setCounter(12); - SwiftRuntime.trace("obj.counter = " + obj.getCounter()); + CallTraces.trace("obj.counter = " + obj.getCounter()); obj.voidMethod(); obj.takeIntMethod(42); @@ -75,9 +76,9 @@ static void examples() { otherObj.voidMethod(); MySwiftStruct swiftValue = MySwiftStruct.init(2222, 1111, arena); - SwiftRuntime.trace("swiftValue.capacity = " + swiftValue.getCapacity()); + CallTraces.trace("swiftValue.capacity = " + swiftValue.getCapacity()); swiftValue.withCapLen((cap, len) -> { - SwiftRuntime.trace("withCapLenCallback: cap=" + cap + ", len=" + len); + CallTraces.trace("withCapLenCallback: cap=" + cap + ", len=" + len); }); } @@ -85,12 +86,12 @@ static void examples() { try (var arena = AllocatingSwiftArena.ofConfined()) { var origBytes = arena.allocateFrom("foobar"); var origDat = Data.init(origBytes, origBytes.byteSize(), arena); - SwiftRuntime.trace("origDat.count = " + origDat.getCount()); + CallTraces.trace("origDat.count = " + origDat.getCount()); var retDat = MySwiftLibrary.globalReceiveReturnData(origDat, arena); retDat.withUnsafeBytes((retBytes) -> { var str = retBytes.getString(0); - SwiftRuntime.trace("retStr=" + str); + CallTraces.trace("retStr=" + str); }); } diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift index 13230a32..28b3aba1 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 (SwiftRuntime.TRACE_DOWNCALLS) { - SwiftRuntime.traceDowncall(\(argsStr)); + if (CallTraces.TRACE_DOWNCALLS) { + CallTraces.traceDowncall(\(argsStr)); } \(maybeReturn)HANDLE.invokeExact(\(argsStr)); } catch (Throwable ex$) { diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift index d717255d..10dab4b9 100644 --- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift @@ -131,6 +131,7 @@ extension FFMSwift2JavaGenerator { } printer.print("import \(module)") } + printer.println() } } diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift index 80b47760..4f4ad4d8 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift @@ -206,13 +206,15 @@ extension JNISwift2JavaGenerator { printDeclDocumentation(&printer, decl) printer.printBraceBlock("public \(renderFunctionSignature(decl))") { printer in var arguments = translatedDecl.translatedFunctionSignature.parameters.map(\.name) - arguments.append("selfPointer") + + let selfVarName = "self$" + arguments.append(selfVarName) let returnKeyword = translatedDecl.translatedFunctionSignature.resultType.isVoid ? "" : "return " printer.print( """ - long selfPointer = this.pointer(); + long \(selfVarName) = this.$memoryAddress(); \(returnKeyword)\(translatedDecl.parentName).$\(translatedDecl.name)(\(arguments.joined(separator: ", "))); """ ) @@ -235,8 +237,8 @@ extension JNISwift2JavaGenerator { let initArguments = translatedDecl.translatedFunctionSignature.parameters.map(\.name) printer.print( """ - long selfPointer = \(type.qualifiedName).allocatingInit(\(initArguments.joined(separator: ", "))); - return new \(type.qualifiedName)(selfPointer, swiftArena$); + long self$ = \(type.qualifiedName).allocatingInit(\(initArguments.joined(separator: ", "))); + return new \(type.qualifiedName)(self$, swiftArena$); """ ) } @@ -262,15 +264,24 @@ extension JNISwift2JavaGenerator { private func printDestroyFunction(_ printer: inout CodePrinter, _ type: ImportedNominalType) { printer.print("private static native void $destroy(long selfPointer);") + let funcName = "$createDestroyFunction" printer.print("@Override") - printer.printBraceBlock("protected Runnable $createDestroyFunction()") { printer in + printer.printBraceBlock("protected Runnable \(funcName)()") { printer in printer.print( """ - long $selfPointer = this.pointer(); + long self$ = this.$memoryAddress(); + if (CallTraces.TRACE_DOWNCALLS) { + CallTraces.traceDowncall("\(type.swiftNominal.name).\(funcName)", + "this", this, + "self", self$); + } return new Runnable() { @Override public void run() { - \(type.swiftNominal.name).$destroy($selfPointer); + if (CallTraces.TRACE_DOWNCALLS) { + CallTraces.traceDowncall("\(type.swiftNominal.name).$destroy", "self", self$); + } + \(type.swiftNominal.name).$destroy(self$); } }; """ diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift index 30db69d1..38d4ff79 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift @@ -138,9 +138,9 @@ extension JNISwift2JavaGenerator { // TODO: Throwing initializers printer.print( """ - let selfPointer = UnsafeMutablePointer<\(typeName)>.allocate(capacity: 1) - selfPointer.initialize(to: \(typeName)(\(downcallArguments))) - return Int64(Int(bitPattern: selfPointer)).getJNIValue(in: environment) + let self$ = UnsafeMutablePointer<\(typeName)>.allocate(capacity: 1) + self$.initialize(to: \(typeName)(\(downcallArguments))) + return Int64(Int(bitPattern: self$)).getJNIValue(in: environment) """ ) } @@ -184,22 +184,20 @@ extension JNISwift2JavaGenerator { let translatedDecl = self.translatedDecl(for: decl)! // We will only call this method if can translate the decl. let swiftParentName = decl.parentType!.asNominalTypeDeclaration!.qualifiedName + let selfPointerParam = JavaParameter(name: "selfPointer", type: .long) printCDecl( &printer, javaMethodName: "$\(translatedDecl.name)", parentName: translatedDecl.parentName, parameters: translatedDecl.translatedFunctionSignature.parameters + [ - JavaParameter(name: "selfPointer", type: .long) + selfPointerParam ], isStatic: true, resultType: translatedDecl.translatedFunctionSignature.resultType ) { printer in - printer.print( - """ - let self$ = UnsafeMutablePointer<\(swiftParentName)>(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! - """ - ) - self.printFunctionDowncall(&printer, decl, calleeName: "self$.pointee") + let selfVar = self.printSelfJLongToUnsafeMutablePointer(&printer, + swiftParentName: swiftParentName, selfPointerParam) + self.printFunctionDowncall(&printer, decl, calleeName: "\(selfVar).pointee") } } @@ -320,28 +318,53 @@ extension JNISwift2JavaGenerator { /// Prints the implementation of the destroy function. private func printDestroyFunctionThunk(_ printer: inout CodePrinter, _ type: ImportedNominalType) { + let selfPointerParam = JavaParameter(name: "selfPointer", type: .long) printCDecl( &printer, javaMethodName: "$destroy", parentName: type.swiftNominal.name, parameters: [ - JavaParameter(name: "selfPointer", type: .long) + selfPointerParam ], isStatic: true, resultType: .void ) { printer in + let parentName = type.qualifiedName + let selfVar = self.printSelfJLongToUnsafeMutablePointer(&printer, swiftParentName: parentName, selfPointerParam) // Deinitialize the pointer allocated (which will call the VWT destroy method) // then deallocate the memory. printer.print( """ - let pointer = UnsafeMutablePointer<\(type.qualifiedName)>(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! - pointer.deinitialize(count: 1) - pointer.deallocate() + \(selfVar).deinitialize(count: 1) + \(selfVar).deallocate() """ ) } } + /// Print the necessary conversion logic to go from a `jlong` to a `UnsafeMutablePointer` + /// + /// - Returns: name of the created "self" variable + private func printSelfJLongToUnsafeMutablePointer( + _ printer: inout CodePrinter, + swiftParentName: String, _ selfPointerParam: JavaParameter) -> String { + let newSelfParamName = "self$" + printer.print( + """ + guard let env$ = environment else { + fatalError("Missing JNIEnv in downcall to \\(#function)") + } + assert(\(selfPointerParam.name) != 0, "\(selfPointerParam.name) memory address was null") + let selfBits$ = Int(Int64(fromJNI: \(selfPointerParam.name), in: env$)) + guard let \(newSelfParamName) = UnsafeMutablePointer<\(swiftParentName)>(bitPattern: selfBits$) else { + fatalError("self memory address was null in call to \\(#function)!") + } + """ + ) + return newSelfParamName + } + + /// Renders the arguments for making a downcall private func renderDowncallArguments( swiftFunctionSignature: SwiftFunctionSignature, diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/CallTraces.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/CallTraces.java new file mode 100644 index 00000000..358205ff --- /dev/null +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/CallTraces.java @@ -0,0 +1,61 @@ +//===----------------------------------------------------------------------===// +// +// 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; + +public class CallTraces { + public static final boolean TRACE_DOWNCALLS = + Boolean.getBoolean("jextract.trace.downcalls"); + + // Used to manually debug with complete backtraces on every traceDowncall + public static final boolean TRACE_DOWNCALLS_FULL = false; + + public static void traceDowncall(Object... args) { + RuntimeException ex = new RuntimeException(); + + String traceArgs = joinArgs(args); + System.err.printf("[java][%s:%d] Downcall: %s.%s(%s)\n", + ex.getStackTrace()[1].getFileName(), + ex.getStackTrace()[1].getLineNumber(), + ex.getStackTrace()[1].getClassName(), + ex.getStackTrace()[1].getMethodName(), + traceArgs); + if (TRACE_DOWNCALLS_FULL) { + ex.printStackTrace(); + } + } + + public static void trace(Object... args) { + RuntimeException ex = new RuntimeException(); + + String traceArgs = joinArgs(args); + System.err.printf("[java][%s:%d] %s: %s\n", + ex.getStackTrace()[1].getFileName(), + ex.getStackTrace()[1].getLineNumber(), + ex.getStackTrace()[1].getMethodName(), + traceArgs); + } + + private static String joinArgs(Object[] args) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < args.length; i++) { + if (i > 0) { + sb.append(", "); + } + sb.append(args[i].toString()); + } + return sb.toString(); + } + +} diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ConfinedSwiftMemorySession.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ConfinedSwiftMemorySession.java index 1b6821ca..7c6e80fb 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ConfinedSwiftMemorySession.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ConfinedSwiftMemorySession.java @@ -60,7 +60,7 @@ public void close() { public void register(SwiftInstance instance) { checkValid(); - SwiftInstanceCleanup cleanup = instance.createCleanupAction(); + SwiftInstanceCleanup cleanup = instance.$createCleanup(); this.resources.add(cleanup); } diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java index f9966793..6b30ed2f 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java @@ -14,17 +14,30 @@ package org.swift.swiftkit.core; +import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; public abstract class JNISwiftInstance extends SwiftInstance { + // Pointer to the "self". + protected final long selfPointer; + /** * The designated constructor of any imported Swift types. * - * @param pointer a pointer to the memory containing the value + * @param selfPointer 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); + protected JNISwiftInstance(long selfPointer, SwiftArena arena) { + SwiftObjects.requireNonZero(selfPointer, "selfPointer"); + this.selfPointer = selfPointer; + + // Only register once we have fully initialized the object since this will need the object pointer. + arena.register(this); + } + + @Override + public long $memoryAddress() { + return this.selfPointer; } /** @@ -42,7 +55,7 @@ protected JNISwiftInstance(long pointer, SwiftArena arena) { protected abstract Runnable $createDestroyFunction(); @Override - public SwiftInstanceCleanup createCleanupAction() { + public SwiftInstanceCleanup $createCleanup() { final AtomicBoolean statusDestroyedFlag = $statusDestroyedFlag(); Runnable markAsDestroyed = new Runnable() { @Override diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstance.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstance.java index 638cb8be..44955cc6 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstance.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstance.java @@ -17,49 +17,38 @@ import java.util.concurrent.atomic.AtomicBoolean; public abstract class SwiftInstance { - /// Pointer to the "self". - private final long selfPointer; + + // 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); /** - * The pointer to the instance in memory. I.e. the {@code self} of the Swift object or value. + * Pointer to the {@code self} of the underlying Swift object or value. + * + * @apiNote When using this pointer one must ensure that the underlying object + * is kept alive using some means (e.g. a class remains retained), as + * this function does not ensure safety of the address in any way. */ - public final long pointer() { - return this.selfPointer; - } + public abstract long $memoryAddress(); /** * 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); + public abstract SwiftInstanceCleanup $createCleanup(); /** * Exposes a boolean value which can be used to indicate if the object was destroyed. *

* This is exposing the object, rather than performing the action because we don't want to accidentally * form a strong reference to the {@code SwiftInstance} which could prevent the cleanup from running, - * if using an GC managed instance (e.g. using an {@link AutoSwiftMemorySession}. + * if using an GC managed instance (e.g. using an {@code AutoSwiftMemorySession}. */ public final AtomicBoolean $statusDestroyedFlag() { return this.$state$destroyed; } - /** - * 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 SwiftInstance(long pointer, SwiftArena arena) { - this.selfPointer = pointer; - arena.register(this); - } - /** * Ensures that this instance has not been destroyed. *

diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftLibraries.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftLibraries.java index 2abdaff5..3230e52a 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftLibraries.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftLibraries.java @@ -26,7 +26,6 @@ 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"; @@ -57,7 +56,7 @@ public static void loadLibrary(String libname) { public static void loadResourceLibrary(String libname) { String resourceName = PlatformUtils.dynamicLibraryName(libname); - if (SwiftLibraries.TRACE_DOWNCALLS) { + if (CallTraces.TRACE_DOWNCALLS) { System.out.println("[swift-java] Loading resource library: " + resourceName); } diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftObjects.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftObjects.java new file mode 100644 index 00000000..c508e90e --- /dev/null +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftObjects.java @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// 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; + +/** + * Utility functions, similar to @{link java.util.Objects} + */ +public class SwiftObjects { + public static void requireNonZero(long number, String name) { + if (number == 0) { + throw new IllegalArgumentException(String.format("'%s' must not be zero!", name)); + } + } +} diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/AllocatingAutoSwiftMemorySession.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/AllocatingAutoSwiftMemorySession.java index fecd5202..7063fefb 100644 --- a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/AllocatingAutoSwiftMemorySession.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/AllocatingAutoSwiftMemorySession.java @@ -56,7 +56,7 @@ public void register(SwiftInstance instance) { // We make sure we don't capture `instance` in the // cleanup action, so we can ignore the warning below. - var cleanupAction = instance.createCleanupAction(); + var cleanupAction = instance.$createCleanup(); cleaner.register(instance, cleanupAction); } diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstance.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstance.java index f4a01aa4..1236bad2 100644 --- a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstance.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstance.java @@ -22,6 +22,19 @@ public abstract class FFMSwiftInstance extends SwiftInstance { private final MemorySegment memorySegment; + /** + * 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) { + this.memorySegment = segment; + + // Only register once we have fully initialized the object since this will need the object pointer. + arena.register(this); + } + /** * The pointer to the instance in memory. I.e. the {@code self} of the Swift object or value. */ @@ -29,24 +42,19 @@ public abstract class FFMSwiftInstance extends SwiftInstance { return this.memorySegment; } + @Override + public long $memoryAddress() { + return $memorySegment().address(); + } + /** * 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() { + public SwiftInstanceCleanup $createCleanup() { var statusDestroyedFlag = $statusDestroyedFlag(); Runnable markAsDestroyed = () -> statusDestroyedFlag.set(true); diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstanceCleanup.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstanceCleanup.java index a5d0829a..c3a9beb6 100644 --- a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstanceCleanup.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstanceCleanup.java @@ -19,13 +19,13 @@ import java.lang.foreign.MemorySegment; public class FFMSwiftInstanceCleanup implements SwiftInstanceCleanup { - private final MemorySegment selfPointer; - private final SwiftAnyType selfType; + private final MemorySegment memoryAddress; + private final SwiftAnyType type; private final Runnable markAsDestroyed; - public FFMSwiftInstanceCleanup(MemorySegment selfPointer, SwiftAnyType selfType, Runnable markAsDestroyed) { - this.selfPointer = selfPointer; - this.selfType = selfType; + public FFMSwiftInstanceCleanup(MemorySegment memoryAddress, SwiftAnyType type, Runnable markAsDestroyed) { + this.memoryAddress = memoryAddress; + this.type = type; this.markAsDestroyed = markAsDestroyed; } @@ -34,9 +34,9 @@ public void run() { markAsDestroyed.run(); // Allow null pointers just for AutoArena tests. - if (selfType != null && selfPointer != null) { - System.out.println("[debug] Destroy swift value [" + selfType.getSwiftName() + "]: " + selfPointer); - SwiftValueWitnessTable.destroy(selfType, selfPointer); + if (type != null && memoryAddress != null) { + System.out.println("[debug] Destroy swift value [" + type.getSwiftName() + "]: " + memoryAddress); + SwiftValueWitnessTable.destroy(type, memoryAddress); } } } diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftRuntime.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftRuntime.java index dc18b445..eca6be82 100644 --- a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftRuntime.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/SwiftRuntime.java @@ -15,6 +15,7 @@ package org.swift.swiftkit.ffm; import org.swift.swiftkit.core.SwiftInstance; +import org.swift.swiftkit.core.CallTraces; import org.swift.swiftkit.core.util.PlatformUtils; import java.lang.foreign.*; @@ -24,6 +25,7 @@ import java.util.*; import java.util.stream.Collectors; +import static org.swift.swiftkit.core.CallTraces.traceDowncall; import static org.swift.swiftkit.core.util.StringUtils.stripPrefix; import static org.swift.swiftkit.core.util.StringUtils.stripSuffix; @@ -31,7 +33,6 @@ public class SwiftRuntime { 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"; @@ -65,33 +66,6 @@ private static SymbolLookup getSymbolLookup() { public SwiftRuntime() { } - public static void traceDowncall(Object... args) { - var ex = new RuntimeException(); - - String traceArgs = Arrays.stream(args) - .map(Object::toString) - .collect(Collectors.joining(", ")); - System.out.printf("[java][%s:%d] Downcall: %s.%s(%s)\n", - ex.getStackTrace()[1].getFileName(), - ex.getStackTrace()[1].getLineNumber(), - ex.getStackTrace()[1].getClassName(), - ex.getStackTrace()[1].getMethodName(), - traceArgs); - } - - public static void trace(Object... args) { - var ex = new RuntimeException(); - - String traceArgs = Arrays.stream(args) - .map(Object::toString) - .collect(Collectors.joining(", ")); - System.out.printf("[java][%s:%d] %s: %s\n", - ex.getStackTrace()[1].getFileName(), - ex.getStackTrace()[1].getLineNumber(), - ex.getStackTrace()[1].getMethodName(), - traceArgs); - } - static MemorySegment findOrThrow(String symbol) { return SYMBOL_LOOKUP.find(symbol) .orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol: %s".formatted(symbol))); @@ -152,7 +126,7 @@ private static class swift_retainCount { public static long retainCount(MemorySegment object) { var mh$ = swift_retainCount.HANDLE; try { - if (TRACE_DOWNCALLS) { + if (CallTraces.TRACE_DOWNCALLS) { traceDowncall("swift_retainCount", object); } return (long) mh$.invokeExact(object); @@ -182,7 +156,7 @@ private static class swift_retain { public static void retain(MemorySegment object) { var mh$ = swift_retain.HANDLE; try { - if (TRACE_DOWNCALLS) { + if (CallTraces.TRACE_DOWNCALLS) { traceDowncall("swift_retain", object); } mh$.invokeExact(object); @@ -212,7 +186,7 @@ private static class swift_release { public static void release(MemorySegment object) { var mh$ = swift_release.HANDLE; try { - if (TRACE_DOWNCALLS) { + if (CallTraces.TRACE_DOWNCALLS) { traceDowncall("swift_release", object); } mh$.invokeExact(object); @@ -248,7 +222,7 @@ private static class swift_getTypeByName { public static MemorySegment getTypeByName(String string) { var mh$ = swift_getTypeByName.HANDLE; try { - if (TRACE_DOWNCALLS) { + if (CallTraces.TRACE_DOWNCALLS) { traceDowncall("_typeByName"); } // TODO: A bit annoying to generate, we need an arena for the conversion... @@ -303,7 +277,7 @@ public static Optional getTypeByMangledNameInEnvironment(String ma // contain this, but we don't need it for type lookup mangledName = stripSuffix(mangledName, "Ma"); mangledName = stripSuffix(mangledName, "CN"); - if (TRACE_DOWNCALLS) { + if (CallTraces.TRACE_DOWNCALLS) { traceDowncall("swift_getTypeByMangledNameInEnvironment", mangledName); } try (Arena arena = Arena.ofConfined()) { diff --git a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift index 3c4ad56a..5b70f68a 100644 --- a/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift +++ b/Tests/JExtractSwiftTests/Asserts/TextAssertions.swift @@ -28,7 +28,7 @@ func assertOutput( _ mode: JExtractGenerationMode, _ renderKind: RenderKind, swiftModuleName: String = "SwiftModule", - detectChunkByInitialLines: Int = 4, + detectChunkByInitialLines _detectChunkByInitialLines: Int = 4, expectedChunks: [String], fileID: String = #fileID, filePath: String = #filePath, @@ -79,19 +79,22 @@ func assertOutput( let gotLines = output.split(separator: "\n").filter { l in l.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines).count > 0 } - for expected in expectedChunks { - let expectedLines = expected.split(separator: "\n") + for expectedChunk in expectedChunks { + let expectedLines = expectedChunk.split(separator: "\n") + let detectChunkByInitialLines = min(expectedLines.count, _detectChunkByInitialLines) + precondition(detectChunkByInitialLines > 0, "Chunk size to detect cannot be zero lines!") var matchingOutputOffset: Int? = nil let expectedInitialMatchingLines = expectedLines[0.. (offset+detectChunkByInitialLines) { - let textLinesAtOffset = gotLines[offset.. (lineOffset+detectChunkByInitialLines) { + let textLinesAtOffset = gotLines[lineOffset..!, thisClass: jclass) -> jlong { - let selfPointer = UnsafeMutablePointer.allocate(capacity: 1) - selfPointer.initialize(to: MyClass()) - return Int64(Int(bitPattern: selfPointer)).getJNIValue(in: environment) + let self$ = UnsafeMutablePointer.allocate(capacity: 1) + self$.initialize(to: MyClass()) + return Int64(Int(bitPattern: self$)).getJNIValue(in: environment) } """, """ @_cdecl("Java_com_example_swift_MyClass_allocatingInit__JJ") func Java_com_example_swift_MyClass_allocatingInit__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, x: jlong, y: jlong) -> jlong { - let selfPointer = UnsafeMutablePointer.allocate(capacity: 1) - selfPointer.initialize(to: MyClass(x: Int64(fromJNI: x, in: environment!), y: Int64(fromJNI: y, in: environment!))) - return Int64(Int(bitPattern: selfPointer)).getJNIValue(in: environment) + let self$ = UnsafeMutablePointer.allocate(capacity: 1) + self$.initialize(to: MyClass(x: Int64(fromJNI: x, in: environment!), y: Int64(fromJNI: y, in: environment!))) + return Int64(Int(bitPattern: self$)).getJNIValue(in: environment) } """ ] @@ -200,9 +207,16 @@ struct JNIClassTests { """ @_cdecl("Java_com_example_swift_MyClass__00024destroy__J") func Java_com_example_swift_MyClass__00024destroy__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) { - let pointer = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! - pointer.deinitialize(count: 1) - pointer.deallocate() + guard let env$ = environment else { + fatalError("Missing JNIEnv in downcall to \\(#function)") + } + assert(selfPointer != 0, "selfPointer memory address was null") + let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + fatalError("self memory address was null in call to \\(#function)!") + } + self$.deinitialize(count: 1) + self$.deallocate() } """ ] @@ -218,14 +232,14 @@ struct JNIClassTests { expectedChunks: [ """ /** - * Downcall to Swift: - * {@snippet lang=swift : - * public func doSomething(x: Int64) - * } - */ + * Downcall to Swift: + * {@snippet lang=swift : + * public func doSomething(x: Int64) + * } + */ public void doSomething(long x) { - long selfPointer = this.pointer(); - MyClass.$doSomething(x, selfPointer); + long self$ = this.$memoryAddress(); + MyClass.$doSomething(x, self$); } """, """ @@ -246,7 +260,14 @@ struct JNIClassTests { """ @_cdecl("Java_com_example_swift_MyClass__00024doSomething__JJ") func Java_com_example_swift_MyClass__00024doSomething__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, x: jlong, selfPointer: jlong) { - let self$ = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + guard let env$ = environment else { + fatalError("Missing JNIEnv in downcall to \\(#function)") + } + assert(selfPointer != 0, "selfPointer memory address was null") + let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + fatalError("self memory address was null in call to \\(#function)!") + } self$.pointee.doSomething(x: Int64(fromJNI: x, in: environment!)) } """, diff --git a/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift b/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift index 0a883ed1..47b1c4dc 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift @@ -63,11 +63,19 @@ struct JNIStructTests { """ @Override protected Runnable $createDestroyFunction() { - long $selfPointer = this.pointer(); + long self$ = this.$memoryAddress(); + if (CallTraces.TRACE_DOWNCALLS) { + CallTraces.traceDowncall("MyStruct.$createDestroyFunction", + "this", this, + "self", self$); + } return new Runnable() { @Override public void run() { - MyStruct.$destroy($selfPointer); + if (CallTraces.TRACE_DOWNCALLS) { + CallTraces.traceDowncall("MyStruct.$destroy", "self", self$); + } + MyStruct.$destroy(self$); } }; } @@ -90,8 +98,8 @@ struct JNIStructTests { * } */ public static MyStruct init(long x, long y, SwiftArena swiftArena$) { - long selfPointer = MyStruct.allocatingInit(x, y); - return new MyStruct(selfPointer, swiftArena$); + long self$ = MyStruct.allocatingInit(x, y); + return new MyStruct(self$, swiftArena$); } """, """ @@ -112,9 +120,9 @@ struct JNIStructTests { """ @_cdecl("Java_com_example_swift_MyStruct_allocatingInit__JJ") func Java_com_example_swift_MyStruct_allocatingInit__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, x: jlong, y: jlong) -> jlong { - let selfPointer = UnsafeMutablePointer.allocate(capacity: 1) - selfPointer.initialize(to: MyStruct(x: Int64(fromJNI: x, in: environment!), y: Int64(fromJNI: y, in: environment!))) - return Int64(Int(bitPattern: selfPointer)).getJNIValue(in: environment) + let self$ = UnsafeMutablePointer.allocate(capacity: 1) + self$.initialize(to: MyStruct(x: Int64(fromJNI: x, in: environment!), y: Int64(fromJNI: y, in: environment!))) + return Int64(Int(bitPattern: self$)).getJNIValue(in: environment) } """ ] @@ -127,14 +135,20 @@ struct JNIStructTests { input: source, .jni, .swift, - detectChunkByInitialLines: 1, expectedChunks: [ """ @_cdecl("Java_com_example_swift_MyStruct__00024destroy__J") func Java_com_example_swift_MyStruct__00024destroy__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) { - let pointer = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! - pointer.deinitialize(count: 1) - pointer.deallocate() + guard let env$ = environment else { + fatalError("Missing JNIEnv in downcall to \\(#function)") + } + assert(selfPointer != 0, "selfPointer memory address was null") + let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + fatalError("self memory address was null in call to \\(#function)!") + } + self$.deinitialize(count: 1) + self$.deallocate() } """ ] @@ -156,8 +170,8 @@ struct JNIStructTests { * } */ public void doSomething(long x) { - long selfPointer = this.pointer(); - MyStruct.$doSomething(x, selfPointer); + long self$ = this.$memoryAddress(); + MyStruct.$doSomething(x, self$); } """, """ @@ -178,7 +192,14 @@ struct JNIStructTests { """ @_cdecl("Java_com_example_swift_MyStruct__00024doSomething__JJ") func Java_com_example_swift_MyStruct__00024doSomething__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, x: jlong, selfPointer: jlong) { - let self$ = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + guard let env$ = environment else { + fatalError("Missing JNIEnv in downcall to \\(#function)") + } + assert(selfPointer != 0, "selfPointer memory address was null") + let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + fatalError("self memory address was null in call to \\(#function)!") + } self$.pointee.doSomething(x: Int64(fromJNI: x, in: environment!)) } """, diff --git a/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift b/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift index f09789d4..3f65bd97 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIVariablesTests.swift @@ -48,8 +48,8 @@ struct JNIVariablesTests { * } */ public long getConstant() { - long selfPointer = this.pointer(); - return MyClass.$getConstant(selfPointer); + long self$ = this.$memoryAddress(); + return MyClass.$getConstant(self$); } """, """ @@ -69,7 +69,14 @@ struct JNIVariablesTests { """ @_cdecl("Java_com_example_swift_MyClass__00024getConstant__J") func Java_com_example_swift_MyClass__00024getConstant__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jlong { - let self$ = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + guard let env$ = environment else { + fatalError("Missing JNIEnv in downcall to \\(#function)") + } + assert(selfPointer != 0, "selfPointer memory address was null") + let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + fatalError("self memory address was null in call to \\(#function)!") + } let result = self$.pointee.constant return result.getJNIValue(in: environment) } @@ -94,8 +101,8 @@ struct JNIVariablesTests { * } */ public long getMutable() { - long selfPointer = this.pointer(); - return MyClass.$getMutable(selfPointer); + long self$ = this.$memoryAddress(); + return MyClass.$getMutable(self$); } """, """ @@ -106,8 +113,8 @@ struct JNIVariablesTests { * } */ public void setMutable(long newValue) { - long selfPointer = this.pointer(); - MyClass.$setMutable(newValue, selfPointer); + long self$ = this.$memoryAddress(); + MyClass.$setMutable(newValue, self$); } """, """ @@ -131,7 +138,14 @@ struct JNIVariablesTests { """ @_cdecl("Java_com_example_swift_MyClass__00024getMutable__J") func Java_com_example_swift_MyClass__00024getMutable__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jlong { - let self$ = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + guard let env$ = environment else { + fatalError("Missing JNIEnv in downcall to \\(#function)") + } + assert(selfPointer != 0, "selfPointer memory address was null") + let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + fatalError("self memory address was null in call to \\(#function)!") + } let result = self$.pointee.mutable return result.getJNIValue(in: environment) } @@ -139,7 +153,14 @@ struct JNIVariablesTests { """ @_cdecl("Java_com_example_swift_MyClass__00024setMutable__JJ") func Java_com_example_swift_MyClass__00024setMutable__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, newValue: jlong, selfPointer: jlong) { - let self$ = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + guard let env$ = environment else { + fatalError("Missing JNIEnv in downcall to \\(#function)") + } + assert(selfPointer != 0, "selfPointer memory address was null") + let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + fatalError("self memory address was null in call to \\(#function)!") + } self$.pointee.mutable = Int64(fromJNI: newValue, in: environment!) } """ @@ -163,8 +184,8 @@ struct JNIVariablesTests { * } */ public long getComputed() { - long selfPointer = this.pointer(); - return MyClass.$getComputed(selfPointer); + long self$ = this.$memoryAddress(); + return MyClass.$getComputed(self$); } """, """ @@ -185,7 +206,15 @@ struct JNIVariablesTests { """ @_cdecl("Java_com_example_swift_MyClass__00024getComputed__J") func Java_com_example_swift_MyClass__00024getComputed__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jlong { - let self$ = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + guard let env$ = environment else { + fatalError("Missing JNIEnv in downcall to \\(#function)") + } + assert(selfPointer != 0, "selfPointer memory address was null") + let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + fatalError("self memory address was null in call to \\(#function)!") + } + let result = self$.pointee.computed return result.getJNIValue(in: environment) } @@ -210,8 +239,8 @@ struct JNIVariablesTests { * } */ public long getComputedThrowing() throws Exception { - long selfPointer = this.pointer(); - return MyClass.$getComputedThrowing(selfPointer); + long self$ = this.$memoryAddress(); + return MyClass.$getComputedThrowing(self$); } """, """ @@ -232,7 +261,15 @@ struct JNIVariablesTests { """ @_cdecl("Java_com_example_swift_MyClass__00024getComputedThrowing__J") func Java_com_example_swift_MyClass__00024getComputedThrowing__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jlong { - let self$ = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + guard let env$ = environment else { + fatalError("Missing JNIEnv in downcall to \\(#function)") + } + assert(selfPointer != 0, "selfPointer memory address was null") + let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + fatalError("self memory address was null in call to \\(#function)!") + } + do { let result = try self$.pointee.computedThrowing return result.getJNIValue(in: environment) @@ -262,8 +299,8 @@ struct JNIVariablesTests { * } */ public long getGetterAndSetter() { - long selfPointer = this.pointer(); - return MyClass.$getGetterAndSetter(selfPointer); + long self$ = this.$memoryAddress(); + return MyClass.$getGetterAndSetter(self$); } """, """ @@ -274,8 +311,8 @@ struct JNIVariablesTests { * } */ public void setGetterAndSetter(long newValue) { - long selfPointer = this.pointer(); - MyClass.$setGetterAndSetter(newValue, selfPointer); + long self$ = this.$memoryAddress(); + MyClass.$setGetterAndSetter(newValue, self$); } """, """ @@ -299,7 +336,15 @@ struct JNIVariablesTests { """ @_cdecl("Java_com_example_swift_MyClass__00024getGetterAndSetter__J") func Java_com_example_swift_MyClass__00024getGetterAndSetter__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jlong { - let self$ = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + guard let env$ = environment else { + fatalError("Missing JNIEnv in downcall to \\(#function)") + } + assert(selfPointer != 0, "selfPointer memory address was null") + let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + fatalError("self memory address was null in call to \\(#function)!") + } + let result = self$.pointee.getterAndSetter return result.getJNIValue(in: environment) } @@ -307,7 +352,15 @@ struct JNIVariablesTests { """ @_cdecl("Java_com_example_swift_MyClass__00024setGetterAndSetter__JJ") func Java_com_example_swift_MyClass__00024setGetterAndSetter__JJ(environment: UnsafeMutablePointer!, thisClass: jclass, newValue: jlong, selfPointer: jlong) { - let self$ = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + guard let env$ = environment else { + fatalError("Missing JNIEnv in downcall to \\(#function)") + } + assert(selfPointer != 0, "selfPointer memory address was null") + let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + fatalError("self memory address was null in call to \\(#function)!") + } + self$.pointee.getterAndSetter = Int64(fromJNI: newValue, in: environment!) } """ @@ -331,8 +384,8 @@ struct JNIVariablesTests { * } */ public boolean isSomeBoolean() { - long selfPointer = this.pointer(); - return MyClass.$isSomeBoolean(selfPointer); + long self$ = this.$memoryAddress(); + return MyClass.$isSomeBoolean(self$); } """, """ @@ -343,8 +396,8 @@ struct JNIVariablesTests { * } */ public void setSomeBoolean(boolean newValue) { - long selfPointer = this.pointer(); - MyClass.$setSomeBoolean(newValue, selfPointer); + long self$ = this.$memoryAddress(); + MyClass.$setSomeBoolean(newValue, self$); } """, """ @@ -368,7 +421,14 @@ struct JNIVariablesTests { """ @_cdecl("Java_com_example_swift_MyClass__00024isSomeBoolean__J") func Java_com_example_swift_MyClass__00024isSomeBoolean__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jboolean { - let self$ = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + guard let env$ = environment else { + fatalError("Missing JNIEnv in downcall to \\(#function)") + } + assert(selfPointer != 0, "selfPointer memory address was null") + let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + fatalError("self memory address was null in call to \\(#function)!") + } let result = self$.pointee.someBoolean return result.getJNIValue(in: environment) } @@ -376,7 +436,14 @@ struct JNIVariablesTests { """ @_cdecl("Java_com_example_swift_MyClass__00024setSomeBoolean__ZJ") func Java_com_example_swift_MyClass__00024setSomeBoolean__ZJ(environment: UnsafeMutablePointer!, thisClass: jclass, newValue: jboolean, selfPointer: jlong) { - let self$ = UnsafeMutablePointer(bitPattern: Int(Int64(fromJNI: selfPointer, in: environment!)))! + guard let env$ = environment else { + fatalError("Missing JNIEnv in downcall to \\(#function)") + } + assert(selfPointer != 0, "selfPointer memory address was null") + let selfBits$ = Int(Int64(fromJNI: selfPointer, in: env$)) + guard let self$ = UnsafeMutablePointer(bitPattern: selfBits$) else { + fatalError("self memory address was null in call to \\(#function)!") + } self$.pointee.someBoolean = Bool(fromJNI: newValue, in: environment!) } """ diff --git a/Tests/JExtractSwiftTests/MethodImportTests.swift b/Tests/JExtractSwiftTests/MethodImportTests.swift index 118ca789..73357d6b 100644 --- a/Tests/JExtractSwiftTests/MethodImportTests.swift +++ b/Tests/JExtractSwiftTests/MethodImportTests.swift @@ -168,7 +168,6 @@ final class MethodImportTests { } assertOutput( - dump: true, output, expected: """ @@ -212,7 +211,6 @@ final class MethodImportTests { } assertOutput( - dump: true, output, expected: """ @@ -256,7 +254,6 @@ final class MethodImportTests { } assertOutput( - dump: true, output, expected: """ diff --git a/Tests/JExtractSwiftTests/OptionalImportTests.swift b/Tests/JExtractSwiftTests/OptionalImportTests.swift index 756bb3d9..daa9fe66 100644 --- a/Tests/JExtractSwiftTests/OptionalImportTests.swift +++ b/Tests/JExtractSwiftTests/OptionalImportTests.swift @@ -47,8 +47,8 @@ final class OptionalImportTests { private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static void call(java.lang.foreign.MemorySegment arg) { try { - if (SwiftRuntime.TRACE_DOWNCALLS) { - SwiftRuntime.traceDowncall(arg); + if (CallTraces.TRACE_DOWNCALLS) { + CallTraces.traceDowncall(arg); } HANDLE.invokeExact(arg); } catch (Throwable ex$) { @@ -87,8 +87,8 @@ final class OptionalImportTests { private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static void call(java.lang.foreign.MemorySegment arg) { try { - if (SwiftRuntime.TRACE_DOWNCALLS) { - SwiftRuntime.traceDowncall(arg); + if (CallTraces.TRACE_DOWNCALLS) { + CallTraces.traceDowncall(arg); } HANDLE.invokeExact(arg); } catch (Throwable ex$) { @@ -128,8 +128,8 @@ final class OptionalImportTests { private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); public static void call(java.lang.foreign.MemorySegment arg) { try { - if (SwiftRuntime.TRACE_DOWNCALLS) { - SwiftRuntime.traceDowncall(arg); + if (CallTraces.TRACE_DOWNCALLS) { + CallTraces.traceDowncall(arg); } HANDLE.invokeExact(arg); } catch (Throwable ex$) { diff --git a/Tests/JExtractSwiftTests/StringPassingTests.swift b/Tests/JExtractSwiftTests/StringPassingTests.swift index 6a5c1c80..ea81ac84 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 (SwiftRuntime.TRACE_DOWNCALLS) { - SwiftRuntime.traceDowncall(string); + if (CallTraces.TRACE_DOWNCALLS) { + CallTraces.traceDowncall(string); } return (long) HANDLE.invokeExact(string); } catch (Throwable ex$) { diff --git a/Tests/JExtractSwiftTests/VariableImportTests.swift b/Tests/JExtractSwiftTests/VariableImportTests.swift index e0a6678c..da0c1afa 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 (SwiftRuntime.TRACE_DOWNCALLS) { - SwiftRuntime.traceDowncall(self); + if (CallTraces.TRACE_DOWNCALLS) { + CallTraces.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 (SwiftRuntime.TRACE_DOWNCALLS) { - SwiftRuntime.traceDowncall(newValue, self); + if (CallTraces.TRACE_DOWNCALLS) { + CallTraces.traceDowncall(newValue, self); } HANDLE.invokeExact(newValue, self); } catch (Throwable ex$) {