Skip to content

Commit ddd27eb

Browse files
authored
Merge branch 'swiftlang:main' into main
2 parents 98e2c80 + 165ce8f commit ddd27eb

44 files changed

Lines changed: 2880 additions & 2347 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,5 @@ Package.resolved
4949
*/**/*.swiftdeps~
5050
*/**/.docc-build/
5151

52+
53+
BuildLogic/.kotlin/
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of Swift.org project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
#if canImport(FoundationEssentials)
16+
import FoundationEssentials
17+
#else
18+
import Foundation
19+
#endif
20+
21+
public func echoData(_ data: Data) -> Data {
22+
return data
23+
}
24+
25+
public func makeData() -> Data {
26+
return Data([0x01, 0x02, 0x03, 0x04])
27+
}
28+
29+
public func getDataCount(_ data: Data) -> Int {
30+
return data.count
31+
}
32+
33+
public func compareData(_ data1: Data, _ data2: Data) -> Bool {
34+
return data1 == data2
35+
}
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of Swift.org project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
package org.swift.swiftkit.ffm;
16+
17+
import com.example.swift.Data;
18+
import com.example.swift.MySwiftLibrary;
19+
import org.openjdk.jmh.annotations.*;
20+
import org.openjdk.jmh.infra.Blackhole;
21+
22+
import java.lang.foreign.MemorySegment;
23+
import java.lang.foreign.ValueLayout;
24+
import java.nio.ByteBuffer;
25+
import java.util.concurrent.TimeUnit;
26+
27+
@BenchmarkMode(Mode.AverageTime)
28+
@Warmup(iterations = 5, time = 200, timeUnit = TimeUnit.MILLISECONDS)
29+
@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
30+
@OutputTimeUnit(TimeUnit.NANOSECONDS)
31+
@State(Scope.Benchmark)
32+
@Fork(value = 2, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED" })
33+
public class FFMDataBenchmark {
34+
35+
private static class Holder<T> {
36+
T value;
37+
}
38+
39+
@Param({"4", "100", "1000"})
40+
public int dataSize;
41+
42+
ClosableAllocatingSwiftArena arena;
43+
Data data;
44+
45+
@Setup(Level.Trial)
46+
public void beforeAll() {
47+
arena = AllocatingSwiftArena.ofConfined();
48+
data = Data.init(makeBytes(dataSize), arena);
49+
}
50+
51+
@TearDown(Level.Trial)
52+
public void afterAll() {
53+
arena.close();
54+
}
55+
56+
private static byte[] makeBytes(int size) {
57+
byte[] bytes = new byte[size];
58+
for (int i = 0; i < size; i++) {
59+
bytes[i] = (byte) (i % 256);
60+
}
61+
return bytes;
62+
}
63+
64+
@Benchmark
65+
public long ffm_baseline_globalMakeInt() {
66+
return MySwiftLibrary.globalMakeInt();
67+
}
68+
69+
@Benchmark
70+
public long ffm_passDataToSwift() {
71+
return MySwiftLibrary.getDataCount(data);
72+
}
73+
74+
@Benchmark
75+
public ByteBuffer ffm_data_withUnsafeBytes_asByteBuffer() {
76+
Holder<ByteBuffer> buf = new Holder<>();
77+
data.withUnsafeBytes((bytes) -> {
78+
buf.value = bytes.asByteBuffer();
79+
});
80+
return buf.value;
81+
}
82+
83+
@Benchmark
84+
public byte[] ffm_data_withUnsafeBytes_toArray() {
85+
Holder<byte[]> buf = new Holder<>();
86+
data.withUnsafeBytes((bytes) -> {
87+
buf.value = bytes.toArray(ValueLayout.JAVA_BYTE);
88+
});
89+
return buf.value;
90+
}
91+
92+
@Benchmark
93+
public byte[] ffm_data_toByteArray() {
94+
return data.toByteArray();
95+
}
96+
97+
@Benchmark
98+
public byte[] ffm_data_toByteArray_withArena() {
99+
return data.toByteArray(arena);
100+
}
101+
102+
@Benchmark
103+
public MemorySegment ffm_data_toMemorySegment() {
104+
return data.toMemorySegment(arena);
105+
}
106+
107+
@Benchmark
108+
public ByteBuffer ffm_data_toByteBuffer() {
109+
return data.toByteBuffer(arena);
110+
}
111+
112+
@Benchmark
113+
public Data ffm_receiveDataFromSwift(Blackhole bh) {
114+
Data result = MySwiftLibrary.makeData(arena);
115+
bh.consume(result.getCount());
116+
return result;
117+
}
118+
119+
@Benchmark
120+
public Data ffm_echoData(Blackhole bh) {
121+
Data echoed = MySwiftLibrary.echoData(data, arena);
122+
bh.consume(echoed.getCount());
123+
return echoed;
124+
}
125+
}

Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/DataImportTest.java

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
import org.junit.jupiter.api.Test;
1818
import org.swift.swiftkit.ffm.AllocatingSwiftArena;
1919

20+
import java.lang.foreign.ValueLayout;
21+
2022
import static org.junit.jupiter.api.Assertions.*;
2123

2224
public class DataImportTest {
@@ -46,4 +48,95 @@ void test_DataProtocol_receive() {
4648
assertEquals(6, result);
4749
}
4850
}
51+
52+
@Test
53+
void test_Data_toByteArray() {
54+
try (var arena = AllocatingSwiftArena.ofConfined()) {
55+
byte[] original = new byte[] { 10, 20, 30, 40 };
56+
var data = Data.fromByteArray(original, arena);
57+
byte[] result = data.toByteArray();
58+
assertEquals(original.length, result.length);
59+
assertArrayEquals(original, result);
60+
}
61+
}
62+
63+
@Test
64+
void test_Data_toByteArray_withArena() {
65+
try (var arena = AllocatingSwiftArena.ofConfined()) {
66+
byte[] original = new byte[] { 10, 20, 30, 40 };
67+
var data = Data.fromByteArray(original, arena);
68+
byte[] result = data.toByteArray(arena);
69+
assertEquals(original.length, result.length);
70+
assertArrayEquals(original, result);
71+
}
72+
}
73+
74+
@Test
75+
void test_Data_toByteArray_emptyData() {
76+
try (var arena = AllocatingSwiftArena.ofConfined()) {
77+
byte[] original = new byte[0];
78+
var data = Data.fromByteArray(original, arena);
79+
byte[] result = data.toByteArray();
80+
assertEquals(0, result.length);
81+
}
82+
}
83+
84+
@Test
85+
void test_Data_fromByteArray() {
86+
try (var arena = AllocatingSwiftArena.ofConfined()) {
87+
byte[] original = new byte[] { 1, 2, 3, 4, 5 };
88+
var data = Data.fromByteArray(original, arena);
89+
assertEquals(5, data.getCount());
90+
}
91+
}
92+
93+
@Test
94+
void test_Data_toMemorySegment() {
95+
try (var arena = AllocatingSwiftArena.ofConfined()) {
96+
byte[] original = new byte[] { 10, 20, 30, 40 };
97+
var data = Data.fromByteArray(original, arena);
98+
var segment = data.toMemorySegment(arena);
99+
100+
assertEquals(original.length, segment.byteSize());
101+
for (int i = 0; i < original.length; i++) {
102+
assertEquals(original[i], segment.get(ValueLayout.JAVA_BYTE, i));
103+
}
104+
}
105+
}
106+
107+
@Test
108+
void test_Data_toByteBuffer() {
109+
try (var arena = AllocatingSwiftArena.ofConfined()) {
110+
byte[] original = new byte[] { 10, 20, 30, 40 };
111+
var data = Data.fromByteArray(original, arena);
112+
var buffer = data.toByteBuffer(arena);
113+
114+
assertEquals(original.length, buffer.capacity());
115+
for (int i = 0; i < original.length; i++) {
116+
assertEquals(original[i], buffer.get(i));
117+
}
118+
}
119+
}
120+
121+
@Test
122+
void test_Data_toMemorySegment_emptyData() {
123+
try (var arena = AllocatingSwiftArena.ofConfined()) {
124+
byte[] original = new byte[0];
125+
var data = Data.fromByteArray(original, arena);
126+
var segment = data.toMemorySegment(arena);
127+
assertEquals(0, segment.byteSize());
128+
}
129+
}
130+
131+
@Test
132+
void test_Data_toByteBuffer_emptyData() {
133+
try (var arena = AllocatingSwiftArena.ofConfined()) {
134+
byte[] original = new byte[0];
135+
var data = Data.fromByteArray(original, arena);
136+
var buffer = data.toByteBuffer(arena);
137+
138+
assertEquals(0, buffer.capacity());
139+
}
140+
}
141+
49142
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of Swift.org project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
#if canImport(FoundationEssentials)
16+
import FoundationEssentials
17+
#else
18+
import Foundation
19+
#endif
20+
import SwiftJava
21+
22+
public func echoData(_ data: Data) -> Data {
23+
return data
24+
}
25+
26+
public func makeData() -> Data {
27+
return Data([0x01, 0x02, 0x03, 0x04])
28+
}
29+
30+
public func getDataCount(_ data: Data) -> Int {
31+
return data.count
32+
}
33+
34+
public func compareData(_ data1: Data, _ data2: Data) -> Bool {
35+
return data1 == data2
36+
}

Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ public func globalTakeInt(i: Int64) {
3535
p("i:\(i)")
3636
}
3737

38+
public func globalEchoInt(i: Int64) -> Int64{
39+
i
40+
}
41+
3842
public func globalMakeInt() -> Int64 {
3943
return 42
4044
}

0 commit comments

Comments
 (0)