Skip to content

Commit f697bef

Browse files
committed
Complete kwasm specification implementation
1 parent 88d93f6 commit f697bef

34 files changed

Lines changed: 3425 additions & 256 deletions

File tree

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ concurrency:
1616

1717
jobs:
1818
kotlin-wasm-compiler-compatibility:
19-
name: Kotlin/Wasm compilers 2.4.10 and 2.3.21
19+
name: Kotlin/Wasm 2.4.10/2.3.21 × 2 EH encodings
2020
runs-on: ubuntu-24.04
2121
timeout-minutes: 60
2222

@@ -33,7 +33,7 @@ jobs:
3333
- name: Set up Gradle
3434
uses: gradle/actions/setup-gradle@v6
3535

36-
- name: Build and execute both pinned compiler rows
36+
- name: Build and execute all four pinned compiler/EH rows
3737
shell: bash
3838
run: bash scripts/verify-kotlin-wasm-compiler-compatibility.sh
3939

.github/workflows/performance.yml

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,38 @@ concurrency:
1717
cancel-in-progress: true
1818

1919
jobs:
20+
ios-footprint:
21+
name: iOS incremental footprint
22+
runs-on: macos-15
23+
timeout-minutes: 60
24+
25+
steps:
26+
- name: Check out repository
27+
uses: actions/checkout@v7
28+
29+
- name: Set up JDK 17
30+
uses: actions/setup-java@v5
31+
with:
32+
distribution: temurin
33+
java-version: "17"
34+
35+
- name: Set up Gradle
36+
uses: gradle/actions/setup-gradle@v6
37+
38+
- name: Link paired final binaries and enforce NFR-2
39+
run: bash scripts/verify-ios-core-footprint.sh
40+
41+
- name: Upload iOS footprint evidence
42+
if: always()
43+
uses: actions/upload-artifact@v7
44+
with:
45+
name: ios-footprint-${{ github.run_id }}
46+
if-no-files-found: error
47+
path: |
48+
build/ios-footprint/report.json
49+
build/ios-footprint/baseline
50+
build/ios-footprint/core
51+
2052
jvm:
2153
name: JVM performance gates
2254
runs-on: ubuntu-24.04
@@ -44,6 +76,12 @@ jobs:
4476
restore-keys: |
4577
kwasm-performance-jvm-${{ runner.os }}-
4678
79+
- name: Prepare pinned Chasm and CoreMark fixture
80+
shell: bash
81+
run: |
82+
coremark_path="$(scripts/prepare-benchmark-upstreams.sh)"
83+
echo "KWASM_COREMARK_WASM=${coremark_path}" >> "$GITHUB_ENV"
84+
4785
- name: Test gate and run JVM benchmark
4886
shell: bash
4987
run: |
@@ -54,10 +92,12 @@ jobs:
5492
"-Pkwasm.benchmark.baseline=benchmarks/.performance-history/jvm.json"
5593
)
5694
fi
95+
./gradlew --stacktrace \
96+
:benchmarks:jvmExternalComparisonReport
5797
./gradlew --stacktrace \
5898
:benchmarks:performanceGateToolTest \
5999
:benchmarks:jvmPerformanceGate \
60-
-Pkwasm.benchmark.externalComparisons=benchmarks/baselines/external-unmeasured.json \
100+
-Pkwasm.benchmark.externalComparisons=benchmarks/build/performance/external-comparisons-jvm.json \
61101
"${gate_args[@]}"
62102
63103
- name: Stage successful JVM history
@@ -84,7 +124,10 @@ jobs:
84124
if-no-files-found: warn
85125
path: |
86126
benchmarks/build/reports/benchmarks/main/**/jvm.json
127+
benchmarks/build/reports/benchmarks/externalComparison/**/jvm.json
87128
benchmarks/build/performance/current-jvm.json
129+
benchmarks/build/performance/external-current-jvm.json
130+
benchmarks/build/performance/external-comparisons-jvm.json
88131
benchmarks/build/performance/gate-jvm.json
89132
90133
native:
@@ -122,6 +165,12 @@ jobs:
122165
restore-keys: |
123166
kwasm-performance-${{ matrix.target }}-${{ runner.os }}-
124167
168+
- name: Prepare pinned Chasm and CoreMark fixture
169+
shell: bash
170+
run: |
171+
coremark_path="$(scripts/prepare-benchmark-upstreams.sh)"
172+
echo "KWASM_COREMARK_WASM=${coremark_path}" >> "$GITHUB_ENV"
173+
125174
- name: Run Native benchmark and gate
126175
shell: bash
127176
env:
@@ -133,9 +182,11 @@ jobs:
133182
if [[ -s "$history" ]]; then
134183
gate_args+=("-Pkwasm.benchmark.baseline=$history")
135184
fi
185+
./gradlew --stacktrace \
186+
":benchmarks:${KWASM_TARGET}ExternalComparisonReport"
136187
./gradlew --stacktrace \
137188
":benchmarks:${KWASM_TARGET}PerformanceGate" \
138-
-Pkwasm.benchmark.externalComparisons=benchmarks/baselines/external-unmeasured.json \
189+
"-Pkwasm.benchmark.externalComparisons=benchmarks/build/performance/external-comparisons-${KWASM_TARGET}.json" \
139190
"${gate_args[@]}"
140191
141192
- name: Stage successful Native history
@@ -164,7 +215,10 @@ jobs:
164215
if-no-files-found: warn
165216
path: |
166217
benchmarks/build/reports/benchmarks/main/**/${{ matrix.target }}.json
218+
benchmarks/build/reports/benchmarks/externalComparison/**/${{ matrix.target }}.json
167219
benchmarks/build/performance/current-${{ matrix.target }}.json
220+
benchmarks/build/performance/external-current-${{ matrix.target }}.json
221+
benchmarks/build/performance/external-comparisons-${{ matrix.target }}.json
168222
benchmarks/build/performance/gate-${{ matrix.target }}.json
169223
170224
native-image:

README.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,13 @@ snapshotted.
1616
> yet claim complete WebAssembly 3.0 conformance. GC, typed references, both
1717
> exception encodings, tail calls, memory64, and multiple memories have
1818
> executable implementations; fixed and relaxed SIMD plus threads are decoded
19-
> and rejected as deferred features. Reproducible full-corpus, cross-target,
20-
> compatibility-matrix, fuzz, and performance release gates remain open. Do
21-
> not deploy kwasm as a security boundary without an independent review.
19+
> and rejected as deferred features. CI contains pinned full-corpus,
20+
> cross-target, Kotlin/Wasm compiler/EH, nightly differential-fuzz, and
21+
> self-history performance and iOS incremental-footprint gates. The benchmark
22+
> harness enforces same-machine, checksum-pinned Chasm/CoreMark comparisons on
23+
> JVM and Native; current local evidence passes those performance gates and the
24+
> paired iOS footprint gate. An independent security review remains open; do
25+
> not deploy kwasm as a security boundary without that review.
2226
2327
The implementation contract and requirement IDs live in
2428
[kwasm-spec.md](kwasm-spec.md).

benchmarks/README.md

Lines changed: 57 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ and the measurable parts of `NFR-1`. It uses
55
`org.jetbrains.kotlinx.benchmark` 0.4.17 on JVM and the host Kotlin/Native
66
target. Reports use average wall time in `ms/op`.
77

8-
No performance number is claimed in this repository until a report has
9-
actually been produced. In particular, the checked-in external-comparison
10-
file is explicitly `unmeasured`.
8+
No performance number is claimed from a checked-in placeholder. CI creates
9+
the external-comparison report from both runtimes in one benchmark process
10+
and preserves the raw and normalized evidence.
1111

1212
## Workloads
1313

@@ -90,34 +90,46 @@ Run the deterministic gate-tool tests without executing benchmarks:
9090

9191
No third-party benchmark binary is vendored. Repositories and immutable
9292
commits for Sightglass methodology, EEMBC CoreMark, Chasm, and Chicory are in
93-
`upstreams.lock.json`. A CoreMark asset needs a separate license/provenance
94-
review and must be a freestanding module for the current seam. The dedicated
95-
external profile runs only CoreMark:
93+
`upstreams.lock.json`. EEMBC distributes CoreMark under Apache-2.0 together
94+
with its acceptable-use and result-disclosure terms. The comparison uses the
95+
exact `coremark.wasm` fixture shipped by Chasm 1.4.8, records the commit that
96+
introduced it, and rejects any bytes whose SHA-256 is not the locked value.
97+
98+
Prepare the immutable Chasm checkout:
99+
100+
```shell
101+
export KWASM_COREMARK_WASM="$(scripts/prepare-benchmark-upstreams.sh)"
102+
```
103+
104+
Run CoreMark alone:
96105

97106
```shell
98107
KWASM_COREMARK_WASM=/absolute/path/coremark.wasm \
99108
KWASM_COREMARK_EXPORT=run \
100109
./gradlew :benchmarks:jvmExternalBenchmark
101110
```
102111

103-
Setting the same environment variables while running `jvmPerformanceGate`
104-
also adds CoreMark to the default report, allowing a complete Chasm geomean
105-
comparison to activate.
106-
107-
Chasm (JVM and Native) and Chicory interpreter/compiler (JVM) measurements
108-
are imported through
109-
`baselines/external-comparisons.schema.json`. Supply that file to the gate:
112+
For the NFR-1 comparison, `externalComparison` runs kwasm and the pinned
113+
Chasm KMP interpreter against the same module bytes and arguments in one
114+
process. It covers fib(35), SHA, JSON, and CoreMark on JVM and every declared
115+
Native benchmark target. The report task verifies the CoreMark checksum and
116+
records both scores, benchmark names, target, machine, command, UTC timestamp,
117+
and Chasm commit:
110118

111119
```shell
120+
./gradlew :benchmarks:jvmExternalComparisonReport
121+
112122
./gradlew :benchmarks:jvmPerformanceGate \
113-
-Pkwasm.benchmark.externalComparisons=/path/to/measured-comparisons.json
123+
-Pkwasm.benchmark.externalComparisons=benchmarks/build/performance/external-comparisons-jvm.json
114124
```
115125

116-
Chicory ratios are informational. Same-target Chasm rows for fib, SHA, JSON,
117-
and CoreMark activate the `NFR-1` ≤2.5× geomean gate. A partial set is
118-
reported as `partial` and is not treated as proof of the requirement. Missing
119-
records remain `unmeasured`; they never become a zero, synthetic baseline, or
120-
pass.
126+
Replace `jvm` with `macosArm64`, `macosX64`, `linuxArm64`, or `linuxX64` for
127+
the per-target Native tasks. Same-target Chasm rows for all four workloads
128+
activate the fatal `NFR-1` ≤2.5× geomean gate. A partial set is reported as
129+
`partial` and is not treated as proof. Missing records remain `unmeasured`;
130+
they never become a zero, synthetic baseline, or pass. The schema still
131+
accepts separately collected Chicory interpreter/compiler rows as
132+
informational JVM context.
121133

122134
For comparable runs, use an idle dedicated runner, fixed power/performance
123135
settings, the same commit and benchmark profile, and preserve the raw report,
@@ -131,3 +143,29 @@ The performance workflow separately builds the real JVM smoke application
131143
with GraalVM `native-image --no-fallback` and executes it. JMH itself is not
132144
used as the native-image proof because its reflective discovery machinery
133145
would test JMH configuration rather than kwasm's zero-reflection runtime.
146+
147+
## iOS incremental footprint
148+
149+
`NFR-2` is enforced with two application-style Kotlin/Native release
150+
frameworks and two final iOS arm64 Mach-O executables:
151+
152+
- the baseline executes a real `runBlocking`/`yield` path, so Kotlin and
153+
`kotlinx.coroutines` are present in both outputs;
154+
- the core probe internally decodes, validates, instantiates, and executes a
155+
Wasm function returning `i32.const 42`;
156+
- `:core` is an implementation dependency, not exported through the
157+
Objective-C API;
158+
- both release frameworks use Kotlin/Native `smallBinary=true` and
159+
`latin1Strings=true`;
160+
- both final executables use linker dead-code elimination and are stripped
161+
before their byte sizes are compared.
162+
163+
Run the macOS/Xcode-only gate with:
164+
165+
```shell
166+
bash scripts/verify-ios-core-footprint.sh
167+
```
168+
169+
The machine-readable evidence is written to
170+
`build/ios-footprint/report.json`. The gate requires the core executable minus
171+
the baseline executable to be at most 1,500,000 bytes.

benchmarks/baselines/external-comparisons.schema.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,22 @@
7373
"type": "number",
7474
"exclusiveMinimum": 0
7575
},
76+
"kwasmScoreMsPerOp": {
77+
"type": "number",
78+
"exclusiveMinimum": 0
79+
},
80+
"kwasmBenchmark": {
81+
"type": "string",
82+
"minLength": 1
83+
},
84+
"externalBenchmark": {
85+
"type": "string",
86+
"minLength": 1
87+
},
88+
"coreMarkSha256": {
89+
"type": "string",
90+
"pattern": "^[0-9a-f]{64}$"
91+
},
7692
"upstreamCommit": {
7793
"type": "string",
7894
"pattern": "^[0-9a-f]{40}$"

0 commit comments

Comments
 (0)