Skip to content

Commit 961266e

Browse files
committed
pass the self pointer through another pointer indirectly to destroy
1 parent d3e4a6e commit 961266e

File tree

5 files changed

+53
-29
lines changed

5 files changed

+53
-29
lines changed

Samples/SwiftKitSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ public static void main(String[] args) {
3030
boolean traceDowncalls = Boolean.getBoolean("jextract.trace.downcalls");
3131
System.out.println("Property: jextract.trace.downcalls = " + traceDowncalls);
3232

33+
System.out.printf("java.library.path = %s\n", System.getProperty("java.library.path"));
34+
3335
examples();
3436
}
3537

@@ -51,13 +53,13 @@ static void examples() {
5153
var instance = new MySwiftClass(arena, 1111, 2222);
5254
unsafelyEscaped = instance;
5355

54-
var num = instance.makeIntMethod();
56+
// var num = instance.makeIntMethod();
57+
58+
System.out.println("SwiftKit.retainCount(instance) = " + SwiftKit.retainCount(instance));
5559

5660
System.out.println("MySwiftClass.TYPE_MANGLED_NAME = " + MySwiftClass.TYPE_MANGLED_NAME);
5761
MemorySegment typeMetadata = SwiftValueWitnessTable.fullTypeMetadata(MySwiftClass.TYPE_METADATA.$memorySegment());
5862
System.out.println("typeMetadata = " + typeMetadata);
59-
60-
SwiftKit.release(instance);
6163
} // instance should be deallocated
6264

6365
var num = unsafelyEscaped.makeIntMethod();

Samples/SwiftKitSampleApp/src/test/java/org/swift/swiftkit/MySwiftClassTest.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,16 @@ static void beforeAll() {
3737

3838
@Test
3939
void call_retain_retainCount_release() {
40-
var obj = new MySwiftClass(1, 2);
40+
var arena = SwiftArena.ofConfined();
41+
var obj = new MySwiftClass(arena, 1, 2);
4142

42-
assertEquals(1, SwiftKit.retainCount(obj.$memorySegment()));
43-
// TODO: test directly on SwiftHeapObject inheriting obj
43+
assertEquals(1, SwiftKit.retainCount(obj.$memorySegment()));
44+
// TODO: test directly on SwiftHeapObject inheriting obj
4445

45-
SwiftKit.retain(obj.$memorySegment());
46-
assertEquals(2, SwiftKit.retainCount(obj.$memorySegment()));
46+
SwiftKit.retain(obj.$memorySegment());
47+
assertEquals(2, SwiftKit.retainCount(obj.$memorySegment()));
4748

48-
SwiftKit.release(obj.$memorySegment());
49-
assertEquals(1, SwiftKit.retainCount(obj.$memorySegment()));
49+
SwiftKit.release(obj.$memorySegment());
50+
assertEquals(1, SwiftKit.retainCount(obj.$memorySegment()));
5051
}
5152
}

SwiftKit/src/main/java/org/swift/swiftkit/SwiftKit.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import java.lang.invoke.MethodHandle;
2121
import java.util.Arrays;
2222
import java.util.Optional;
23-
import java.util.logging.Logger;
2423
import java.util.stream.Collectors;
2524

2625
import static org.swift.swiftkit.util.StringUtils.stripPrefix;
@@ -35,6 +34,7 @@ public class SwiftKit {
3534
static final boolean TRACE_DOWNCALLS = Boolean.getBoolean("jextract.trace.downcalls");
3635

3736
static {
37+
System.load(STDLIB_MACOS_DYLIB_PATH);
3838
System.loadLibrary(STDLIB_DYLIB_NAME);
3939
System.loadLibrary("SwiftKitSwift");
4040
}
@@ -159,8 +159,8 @@ public static void retain(MemorySegment object) {
159159
}
160160
}
161161

162-
public static long retain(SwiftHeapObject object) {
163-
return retainCount(object.$memorySegment());
162+
public static void retain(SwiftHeapObject object) {
163+
retain(object.$memorySegment());
164164
}
165165

166166
// ==== ------------------------------------------------------------------------------------------------------------
@@ -181,7 +181,7 @@ public static void release(MemorySegment object) {
181181
var mh$ = swift_release.HANDLE;
182182
try {
183183
if (TRACE_DOWNCALLS) {
184-
traceDowncall("swift_release_retain", object);
184+
traceDowncall("swift_release", object);
185185
}
186186
mh$.invokeExact(object);
187187
} catch (Throwable ex$) {

SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueLayout.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.lang.foreign.ValueLayout;
2020

2121
import static java.lang.foreign.ValueLayout.JAVA_BYTE;
22+
import static java.lang.foreign.ValueLayout.JAVA_LONG;
2223

2324
/**
2425
* Similar to {@link java.lang.foreign.ValueLayout} however with some Swift specifics.
@@ -32,9 +33,6 @@ public static long addressByteSize() {
3233
return ValueLayout.ADDRESS.byteSize();
3334
}
3435

35-
public static final AddressLayout SWIFT_POINTER = ValueLayout.ADDRESS
36-
.withTargetLayout(MemoryLayout.sequenceLayout(Long.MAX_VALUE, JAVA_BYTE));
37-
3836
/**
3937
* The value layout for Swift's {@code Int} type, which is a signed type that follows
4038
* the size of a pointer (aka C's {@code ptrdiff_t}).
@@ -52,4 +50,7 @@ public static long addressByteSize() {
5250
public static ValueLayout SWIFT_UINT = SWIFT_INT;
5351

5452

53+
public static final AddressLayout SWIFT_POINTER = ValueLayout.ADDRESS
54+
.withTargetLayout(MemoryLayout.sequenceLayout(Long.MAX_VALUE, JAVA_BYTE));
55+
5556
}

SwiftKit/src/main/java/org/swift/swiftkit/SwiftValueWitnessTable.java

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@
1616

1717
import java.lang.foreign.*;
1818
import java.lang.invoke.MethodHandle;
19-
import org.swift.swiftkit.util.StringUtils;
2019

20+
import static java.lang.foreign.ValueLayout.ADDRESS;
2121
import static java.lang.foreign.ValueLayout.JAVA_BYTE;
2222
import static org.swift.swiftkit.SwiftKit.getSwiftInt;
23+
import static org.swift.swiftkit.util.StringUtils.hexString;
2324

2425
public abstract class SwiftValueWitnessTable {
2526

@@ -162,7 +163,7 @@ public static MemoryLayout layoutOfSwiftType(MemorySegment typeMetadata) {
162163
$LAYOUT.byteOffset(MemoryLayout.PathElement.groupElement("flags"));
163164

164165
/**
165-
* {@snippet lang=C :
166+
* {@snippet lang = C:
166167
* ///void(*destroy)(T *object, witness_t *self);
167168
* ///
168169
* /// Given a valid object of this type, destroy it, leaving it as an
@@ -173,23 +174,24 @@ public static MemoryLayout layoutOfSwiftType(MemorySegment typeMetadata) {
173174
* Destroy,
174175
* VOID_TYPE,
175176
* (MUTABLE_VALUE_TYPE, TYPE_TYPE))
176-
* }
177+
*}
177178
*/
178179
private static class destroy {
179180

180181
static final long $offset =
181182
$LAYOUT.byteOffset(MemoryLayout.PathElement.groupElement("destroy"));
182183

183184
static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(
184-
SwiftValueLayout.SWIFT_POINTER
185+
ValueLayout.ADDRESS
186+
// SwiftValueLayout.SWIFT_POINTER // should be a "pointer to the self pointer"
185187
// , // the object
186188
// SwiftValueLayout.SWIFT_POINTER // the type
187189
);
188190

189191
/**
190192
* Function pointer for the destroy operation
191193
*/
192-
static MemorySegment addr(SwiftAnyType ty, MemorySegment memory) {
194+
static MemorySegment addr(SwiftAnyType ty) {
193195
// Get the value witness table of the type
194196
final var vwt = SwiftValueWitnessTable.valueWitnessTable(ty.$memorySegment());
195197

@@ -198,8 +200,8 @@ static MemorySegment addr(SwiftAnyType ty, MemorySegment memory) {
198200
return MemorySegment.ofAddress(funcAddress);
199201
}
200202

201-
static MethodHandle handle(SwiftAnyType ty, MemorySegment memory) {
202-
return Linker.nativeLinker().downcallHandle(addr(ty, memory), DESC);
203+
static MethodHandle handle(SwiftAnyType ty) {
204+
return Linker.nativeLinker().downcallHandle(addr(ty), DESC);
203205
}
204206
}
205207

@@ -213,14 +215,32 @@ public static void destroy(SwiftAnyType type, MemorySegment object) {
213215
System.out.println("Destroy object: " + object);
214216
System.out.println("Destroy object type: " + type);
215217

216-
var handle = destroy.handle(type, object);
218+
var handle = destroy.handle(type);
217219
System.out.println("Destroy object handle: " + handle);
218220

219-
try {
220-
handle.invokeExact(object);
221-
// handle.invokeExact(object, type.$memorySegment());
221+
try (var arena = Arena.ofConfined()) {
222+
// we need to make a pointer to the self pointer when calling witness table functions:
223+
MemorySegment indirect = arena.allocate(SwiftValueLayout.SWIFT_POINTER);
224+
225+
// Write the address of as the value of the newly created pointer.
226+
// We need to type-safely set the pointer value which may be 64 or 32-bit.
227+
if (SwiftValueLayout.SWIFT_INT == ValueLayout.JAVA_LONG) {
228+
indirect.set(ValueLayout.JAVA_LONG, /*offset=*/0, object.address());
229+
} else {
230+
indirect.set(ValueLayout.JAVA_INT, /*offset=*/0, (int) object.address());
231+
}
232+
233+
System.out.println("indirect = " + indirect);
234+
if (SwiftValueLayout.SWIFT_INT == ValueLayout.JAVA_LONG) {
235+
System.out.println("indirect.get(ValueLayout.JAVA_LONG, 0) = " + hexString(indirect.get(ValueLayout.JAVA_LONG, 0)));
236+
} else {
237+
System.out.println("indirect.get(ValueLayout.JAVA_INT, 0) = " + hexString(indirect.get(ValueLayout.JAVA_INT, 0)));
238+
}
239+
240+
// handle.invokeExact(object); // NOTE: This does "nothing"
241+
handle.invokeExact(indirect);
222242
} catch (Throwable th) {
223-
throw new AssertionError("Failed to destroy '"+type+"' at " + object, th);
243+
throw new AssertionError("Failed to destroy '" + type + "' at " + object, th);
224244
}
225245
}
226246

0 commit comments

Comments
 (0)