Skip to content

Commit 981c09c

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

File tree

3 files changed

+40
-17
lines changed

3 files changed

+40
-17
lines changed

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,13 @@ static void examples() {
5353

5454
var num = instance.makeIntMethod();
5555

56+
SwiftKit.retain(instance);
57+
SwiftKit.retain(instance);
58+
SwiftKit.retain(instance);
59+
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();

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)