Skip to content

Core crypto-currency support: wallets, chains, native/GPU kernels, async batches - #6118

Open
shai-almog wants to merge 56 commits into
masterfrom
core-crypto-wallets
Open

shai-almog wants to merge 56 commits into
masterfrom
core-crypto-wallets

Conversation

@shai-almog

Copy link
Copy Markdown
Collaborator

Adds a built-in crypto-currency stack, shared between the client and the backend, with no third-party libraries.

API (com.codename1.crypto.*, plus additions to com.codename1.security)

  • Primitives: secp256k1 (ECDSA and recovery), BIP-340 Schnorr, Ed25519, Keccak-256, SHA-256/512, RIPEMD-160, HMAC and PBKDF2.
  • Keys: BIP-39 mnemonics, BIP-32 (including xpub derivation), SLIP-10 and derivation paths.
  • Chains:
    • EVM: addresses, legacy/EIP-2930/EIP-1559 transactions, EIP-191/712 signing, the Solidity ABI.
    • Bitcoin: addresses, transactions with sighash, Taproot and PSBT.
    • Solana: addresses, messages, transactions and instructions.
  • Wallets: Signer, SeedSigner, the vault-backed VaultSigner, and the Wallet facade.
  • Network: RPC clients for EVM, Esplora and Solana, and price feeds.
  • Bastion now uses the core classes instead of its own copies.

Performance

  • Native C kernels on ParparVM targets and Android JNI, with SIMD paths:
    • ARMv8.2 SHA3 instructions for Keccak;
    • SHA instructions for SHA-256;
    • AVX2 hash groups on x86.
  • CryptoBatch verifies and hashes many entries on every core, with packed zero-copy forms.
  • Large batches are split between the CPU and the GPU: Metal on Apple platforms, Vulkan elsewhere, WebGPU in the browser.
  • Every batch method has an ...Async form that takes a Callback, delivered on the EDT.
  • crypto-bench.yml holds each kernel to a ratio floor against libsecp256k1, OpenSSL/libsodium and BouncyCastle on the same runner.

Docs: a new developer-guide chapter, "Crypto wallets". It covers:

  • background on the algorithms;
  • each chain end to end;
  • batches and the asynchronous forms;
  • a Performance section with tables and five charts, drawn by scripts/crypto-bench/charts.py from the committed results.

Verification

  • The WebGPU kernels agree with the C kernels on 518 test vectors.
  • The Java record prep matches the C prep word for word.
  • In the browser, every GPU answer is checked against the CPU engine, including a pass where every GPU dispatch is forced to fail.
  • Local checks:
    • core-unittests: 8272 tests pass, SpotBugs 0;
    • ByteCodeTranslator SpotBugs 0;
    • PMD and Checkstyle clean;
    • javadoc builds for the client and backend references;
    • vm/tests JavaScript: 413 tests pass.

🤖 Generated with Claude Code

shai-almog and others added 30 commits October 26, 2026 15:11
secp256k1 moves from 16-bit limbs and Fermat inversion to 26-bit field
limbs with lazy reduction, safegcd inversion, a signed-digit comb for k*G
and a GLV/wNAF Strauss double multiplication for verify and recover:
pubkey 573 -> ~45k/s, sign 506 -> ~34k/s, verify 266 -> ~20k/s on
HotSpot, 1.2-2x BouncyCastle. Keccak-f is unrolled into locals (8x).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…pto kernels

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nk them on use

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…bsodium, OpenSSL, BouncyCastle

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…swords, probed against the Mac loop

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ation, SLIP-10 Ed25519, derivation paths

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…VM addresses, transactions, ABI, EIP-191, EIP-712, ERC-20

java.math is not in the device class library, so the encoding commit's Rlp
could never have linked on a device; UInt256 replaces it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…BIP-341 sighash, Taproot, PSBT, WIF

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…sactions, System/Token/ComputeBudget/Memo; shared Base64

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… PSBT signs through BitcoinKey and reads BIP-32 origins

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ort with client and backend transports; randomness through CryptoEngine so the crypto stack builds in the backend; SpotBugs fixes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… caching decorator

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-1559/Wei/address classes

ChainVectorTest keeps the recorded signed bytes and derived addresses
byte-identical; EthRpc is a thin EvmRpc subclass over WebRpcTransport that
keeps the HTTPS-or-localhost rule. SpotBugs exclusion for the one-shot
NetworkTransport request.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Recovery phrase to wallet, addresses per chain, sending on EVM, Bitcoin
(PSBT) and Solana, price feeds, and where keys live (vault vs server).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…encodings, HD and chain formats

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… usage

The ParparVM kernel sources compile unchanged against a JNI shim; four ABIs,
API 21, 16 KB pages. AndroidImplementation loads them behind a guarded
System.loadLibrary and falls back to the Java engine. A source stamp and
scripts/check-android-crypto-kernels.sh catch stale binaries. Bench: dalvikvm
leg in scripts/crypto-bench/android-run.sh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d CryptoEngine

SHA instructions where the CPU has them (ARMv8 SHA-256, ARMv8.2 SHA-512,
x86 SHA-NI), picked once per process, unrolled portable C otherwise; Ed25519's
SHA-512 goes through the same path. Hash, Hmac and Pbkdf2 route the one-shot
SHA-256/512 and RIPEMD-160 forms through new engine hooks, so BIP-32 and BIP-39
run native. Android libraries rebuilt; bulk ParparVM run covers every padding
boundary (349 checks, 0 failing).

Apple silicon vs OpenSSL: sha256 1.09x, sha512 1.21x, hmac 2.62x, pbkdf2
1.18x, ripemd160 1.34x. Android emulator vs BouncyCastle: 1.8-6.6x.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One native call per batch, cut into chunks run by libdispatch on Apple,
pthreads on Linux/Android and Win32 threads on Windows; small batches run
inline. Every entry gets the single-call answer (no Ed25519 batch equation),
and a malformed entry is invalid rather than an exception. The JNI wrapper
uses Get<Type>ArrayElements so a long batch never holds a critical region.

16-core Apple silicon vs the reference on one core: ECDSA 8.0x libsecp256k1,
Ed25519 17.6x OpenSSL, SHA-256 Merkle nodes 5.5x OpenSSL. Android emulator
vs BouncyCastle: ECDSA 18.3x, Ed25519 4.7x. Bulk ParparVM run: 351 checks,
0 failing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ve kernels

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Debian 12's clang 14 declares the SHA intrinsics only for a translation unit
built for the extension, and GCC 12 refuses to inline them under the target
names clang uses. Old clang gets the instructions as inline assembly, GCC
asks for the targets its own header declares them under. selftest.c checks
the hash kernels with only a C compiler, which is how this was found.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ructions

CryptoBatch gains fixed-stride forms of every batch (hashes 32*n, signatures
64*n, keys keyLength*n, one result byte each). On ParparVM the kernels read
those arrays where they are: no flattening, no per-entry objects, nothing
copied in or out. Simd.allocByte aligns them for the vector units.

Keccak-f runs on EOR3/RAX1/XAR/BCAX, two states per permutation, one per
lane: a single hash is 1.04x the portable code and a batch hashes two inputs
per permutation, 2.1x on one core. SHA-256 batches run two streams through
the SHA unit together. The core count is asked once, not per batch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…N-wide batch grouping

Hash batches now run in groups of the widest lane count the CPU has: two on
ARMv8 (SHA3 / two-stream SHA-256), four Keccak and eight SHA-256 lanes in AVX2
on x86 (SHA-256 only without SHA-NI). AVX2 is used only when cpuid reports it
and XGETBV says the OS saves YMM state.

Also restores the escaped newlines in the old-clang SHA3 asm shims, which had
become literal newlines and failed to compile on clang 14.

selftest.c cross-checks every lane of each group against the single hash;
passes on Apple clang, clang 14, GCC 12 (arm64) and x86-64 under Rosetta with
and without ROSETTA_ADVERTISE_AVX.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Large verify and hash batches are split between the GPU and every CPU core in
the ratio of their measured throughput, and both halves run at once. Metal on
iOS and macOS; Vulkan, loaded at run time, on Android, Linux and Windows. The
GPU only does the scalar multiplications of public data; parsing,
decompression and challenge hashes are prepared on the CPU, so every result
is exactly what a single verify answers.

The curve kernels use complete projective formulas with one addition and one
doubling site per scalar multiplication: drivers inline every call, and the
earlier layout took 214 s to compile on lavapipe. All five pipelines now
build in seconds.

scripts/crypto-gpu holds the shader generator, a check of the hand-declared
Vulkan subset against vulkan_core.h, and batch-check, which holds GPU batches
to CPU batches and reports throughput and crossover per kernel; the
crypto-bench workflow runs them on lavapipe. libcn1crypto.so is rebuilt with
the Vulkan host.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
rand_s was implicitly declared, which clang 16+ rejects; found by a mingw
cross build of the Vulkan host. libcn1crypto.so rebuilt for the new digest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…hmarks in the guide

Every CryptoBatch method gains an Async form taking a Callback: arguments are
checked before it returns, the batch runs through CryptoEngine.runInBackground
and the answer arrives through deliver (the EDT on a port). The JavaScript
port's HTML5CryptoEngine sends large batches to WebGPU kernels generated from
the same source as the Metal and Vulkan ones (WGSL through naga), with the
Java prep held to the C prep word for word and the kernels to the C answers.
The kernel asset ships only with applications that run a batch.

The developer guide gains a Performance section: tables for the JVM, native,
Android, the GPU split and the browser, and two charts drawn by
scripts/crypto-bench/charts.py from the committed results.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

✅ Continuous Quality Report

Test & Coverage

Static Analysis

  • SpotBugs [Report archive]
    • ✅ ByteCodeTranslator: 0 findings (no issues)
    • ✅ android: 0 findings (no issues)
    • ✅ android-compat: 0 findings (no issues)
    • ✅ android-res-compiler: 0 findings (no issues)
    • ✅ backend: 0 findings (no issues)
    • ✅ backend-test: 0 findings (no issues)
    • ✅ build-engine: 0 findings (no issues)
    • ✅ build-hint-catalog: 0 findings (no issues)
    • ✅ build-hint-tools: 0 findings (no issues)
    • ✅ codenameone-gradle-plugin: 0 findings (no issues)
    • ✅ codenameone-maven-plugin: 0 findings (no issues)
    • ✅ core-unittests: 0 findings (no issues)
    • ✅ desktop-compat-runtime: 0 findings (no issues)
    • ✅ fxml-compiler: 0 findings (no issues)
    • ✅ ios: 0 findings (no issues)
    • ✅ javac: 0 findings (no issues)
    • ✅ javafx-compat: 0 findings (no issues)
    • ✅ project-model: 0 findings (no issues)
    • ✅ swing-compat: 0 findings (no issues)
  • ✅ PMD: 0 findings (no issues) [Report archive]
  • ✅ Checkstyle: 0 findings (no issues) [Report archive]

Generated automatically by the PR CI workflow.

@shai-almog

shai-almog commented Oct 27, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 206 screenshots: 206 matched.
Native Windows port, REAL shipping pipeline: the hellocodenameone screenshot suite rendered by a binary CROSS-COMPILED on Linux (clang-cl + xwin, WebView2 linked) and RUN on a Windows x64 runner. Compared against the in-repo baseline in scripts/windows/screenshots.

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 56ms / native 4ms = 14.0x speedup
SIMD float-mul (64K x300) java 56ms / native 6ms = 9.3x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 native bridge unavailable (CN1 + SIMD + image benchmarks only)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path gated to scalar (CPU autovectorizes scalar; explicit SIMD not beneficial here)
Base64 CN1 encode 74.000 ms
Base64 CN1 decode 89.000 ms
Base64 SIMD encode 112.000 ms
Base64 encode ratio (SIMD/CN1) 1.514x (51.4% slower)
Base64 SIMD decode 104.000 ms
Base64 decode ratio (SIMD/CN1) 1.169x (16.9% slower)
Image encode benchmark iterations 100
Image createMask (SIMD off) 9.000 ms
Image createMask (SIMD on) 3.000 ms
Image createMask ratio (SIMD on/off) 0.333x (66.7% faster)
Image applyMask (SIMD off) 28.000 ms
Image applyMask (SIMD on) 25.000 ms
Image applyMask ratio (SIMD on/off) 0.893x (10.7% faster)
Image modifyAlpha (SIMD off) 33.000 ms
Image modifyAlpha (SIMD on) 14.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.424x (57.6% faster)
Image modifyAlpha removeColor (SIMD off) 29.000 ms
Image modifyAlpha removeColor (SIMD on) 20.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.690x (31.0% faster)

@shai-almog

shai-almog commented Oct 27, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 206 screenshots: 206 matched.
Native Windows port (x64 / Intel-AMD): full hellocodenameone screenshot suite rendered offscreen with Direct2D/DirectWrite, plus the real benchmarks (base64 native/CN1/SIMD, image createMask/applyMask/modifyAlpha/PNG/JPEG, SSE2 SIMD kernels). Compared against the in-repo baseline in scripts/windows/screenshots.

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 58ms / native 5ms = 11.6x speedup
SIMD float-mul (64K x300) java 62ms / native 4ms = 15.5x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 native bridge unavailable (CN1 + SIMD + image benchmarks only)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path gated to scalar (CPU autovectorizes scalar; explicit SIMD not beneficial here)
Base64 CN1 encode 73.000 ms
Base64 CN1 decode 89.000 ms
Base64 SIMD encode 104.000 ms
Base64 encode ratio (SIMD/CN1) 1.425x (42.5% slower)
Base64 SIMD decode 101.000 ms
Base64 decode ratio (SIMD/CN1) 1.135x (13.5% slower)
Image encode benchmark iterations 100
Image createMask (SIMD off) 12.000 ms
Image createMask (SIMD on) 4.000 ms
Image createMask ratio (SIMD on/off) 0.333x (66.7% faster)
Image applyMask (SIMD off) 38.000 ms
Image applyMask (SIMD on) 29.000 ms
Image applyMask ratio (SIMD on/off) 0.763x (23.7% faster)
Image modifyAlpha (SIMD off) 34.000 ms
Image modifyAlpha (SIMD on) 18.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.529x (47.1% faster)
Image modifyAlpha removeColor (SIMD off) 28.000 ms
Image modifyAlpha removeColor (SIMD on) 20.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.714x (28.6% faster)

ParparVM vs HotSpot (JDK 25): Windows x64

Runner CPU: AMD64 Family 25 Model 1 Stepping 1, AuthenticAMD (baseline windows-x64@amd64-family-25-model-1-authenticamd)

Ratios are ParparVM / JDK 25: below 1.00x ParparVM is faster (time) or smaller (RAM). Median of 5 interleaved, paired rounds; every run's output was verified. A ratio more than 20% (time) / 25% (RAM) above its baseline in vm/selfhost/perf-baseline/ is a regression and fails; one that far below is an improvement, reported but not failed (a row whose calibration runs were noisier carries a wider tolerance), and for RAM the change must also exceed 0.05x in absolute terms. Both run unpinned on all of the runner's CPUs, with their own default thread counts.

Benchmark Cores Time RAM Status
hello (WinHelloMain) 4 1.32x (base 1.22x, +8.4%) 0.74x (base 0.94x, -20.6%) ok
translator (self) 4 0.72x (base 0.83x, -13.8%) 0.55x (base 0.54x, +1.0%) ok
intArithmetic 4 1.10x (base 1.10x, -0.0%) 0.06x (base 0.06x, +2.6%) ok
longArithmetic 4 1.14x (base 1.08x, +5.1%) 0.06x (base 0.05x, +3.5%) ok
mathTranscendental 4 0.79x (base 0.79x, -0.3%) 0.06x (base 0.06x, +2.9%) ok
arraySequential 4 1.35x (base 1.36x, -1.1%) 0.39x (base 0.39x, +0.3%) ok
arrayRandom 4 1.22x (base 1.06x, +15.0%) 0.23x (base 0.23x, +0.5%) ok
objectAllocation 4 1.55x (base 1.56x, -0.6%) 0.31x (base 0.39x, -18.8%) ok
valueEscape 4 0.10x (base 0.10x, +0.4%) 0.05x (base 0.04x, +3.6%) ok
hashMapChurn 4 1.88x (base 1.80x, +4.4%) 0.09x (base 0.09x, -1.1%) ok
stringBuilding 4 1.34x (base 1.22x, +9.9%) 0.32x (base 0.32x, +0.1%) ok
recursion 4 1.41x (base 1.49x, -5.9%) 0.06x (base 0.06x, +1.5%) ok
quicksort 4 1.11x (base 1.13x, -2.3%) 0.12x (base 0.12x, +1.0%) ok

Result: no regression

@shai-almog

shai-almog commented Oct 27, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 206 screenshots: 206 matched.
Native Linux port (x64), GTK3/Cairo/Pango, ParparVM bytecode-to-C (no JVM): the hellocodenameone screenshot suite rendered by a native ELF built + run on the GitHub x64 runner. Baseline: scripts/linux/screenshots.

ParparVM vs HotSpot (JDK 25): Linux x64

Runner CPU: AMD EPYC 9V74 80-Core Processor (baseline linux-x64@amd-epyc-9v74-80-core-processor)

1 improvement past the baseline (not a failure; rebaseline to lock it in):

  • hello (LinuxHelloMain) on all 4 CPUs: RAM 0.69x against a 0.96x baseline (-28.3%, tolerance 25%)

Ratios are ParparVM / JDK 25: below 1.00x ParparVM is faster (time) or smaller (RAM). Median of 5 interleaved, paired rounds; every run's output was verified. A ratio more than 20% (time) / 25% (RAM) above its baseline in vm/selfhost/perf-baseline/ is a regression and fails; one that far below is an improvement, reported but not failed (a row whose calibration runs were noisier carries a wider tolerance), and for RAM the change must also exceed 0.05x in absolute terms. Both run unpinned on all of the runner's CPUs, with their own default thread counts.

Benchmark Cores Time RAM Status
hello (LinuxHelloMain) 4 0.95x (base 0.90x, +6.1%) 0.69x (base 0.96x, -28.3%) improved: rebaseline to lock in (RAM -28.3%)
translator (self) 4 0.58x (base 0.63x, -7.1%) 0.45x (base 0.46x, -3.3%) ok
intArithmetic 4 1.10x (base 1.10x, -0.0%) 0.07x (base 0.06x, +36.0%) ok
longArithmetic 4 1.08x (base 1.08x, +0.0%) 0.07x (base 0.06x, +35.1%) ok
mathTranscendental 4 1.10x (base 1.09x, +0.2%) 0.08x (base 0.07x, +13.9%) ok
arraySequential 4 3.04x (base 2.81x, +8.2%) 0.38x (base 0.35x, +5.7%) ok
arrayRandom 4 1.07x (base 1.02x, +4.1%) 0.21x (base 0.21x, +1.1%) ok
objectAllocation 4 1.27x (base 1.21x, +5.6%) 0.34x (base 0.39x, -11.1%) ok
valueEscape 4 0.10x (base 0.10x, -0.0%) 0.04x (base 0.06x, -23.0%) ok
hashMapChurn 4 1.13x (base 1.10x, +2.9%) 0.10x (base 0.10x, +3.5%) ok
stringBuilding 4 1.47x (base 1.49x, -1.2%) 0.26x (base 0.26x, +0.0%) ok
recursion 4 1.25x (base 1.24x, +0.4%) 0.06x (base 0.06x, +2.0%) ok
quicksort 4 1.08x (base 1.07x, +0.9%) 0.11x (base 0.11x, +1.1%) ok

A change that moves performance ON PURPOSE records the new baseline in vm/selfhost/perf-baseline/pr/6118.json, with the reason, from this job's perf-results.json. The rebaseline is then part of this pull request's diff:

python3 vm/selfhost/calibrate-perf-baseline.py --pr 6118 --reason "<why these benchmarks moved>" perf-results.json

Result: no regression (improved past the baseline: consider rebaselining)

@shai-almog

shai-almog commented Oct 27, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 206 screenshots: 206 matched.
Native Linux port (arm64), GTK3/Cairo/Pango, ParparVM bytecode-to-C (no JVM): the hellocodenameone screenshot suite rendered by a native ELF built + run on the GitHub arm64 runner. Baseline: scripts/linux/screenshots-arm.

ParparVM vs HotSpot (JDK 25): Linux arm64

Runner CPU: Neoverse-V3 (no baseline for this CPU model -- the gate fails until one is added; see below)

Ratios are ParparVM / JDK 25: below 1.00x ParparVM is faster (time) or smaller (RAM). Median of 5 interleaved, paired rounds; every run's output was verified. A ratio more than 20% (time) / 25% (RAM) above its baseline in vm/selfhost/perf-baseline/ is a regression and fails; one that far below is an improvement, reported but not failed (a row whose calibration runs were noisier carries a wider tolerance), and for RAM the change must also exceed 0.05x in absolute terms. Both run unpinned on all of the runner's CPUs, with their own default thread counts.

Benchmark Cores Time RAM Status
hello (LinuxHelloMain) 4 1.00x 0.89x NO BASELINE
translator (self) 4 0.74x 0.42x NO BASELINE
intArithmetic 4 1.00x 0.03x NO BASELINE
longArithmetic 4 1.04x 0.04x NO BASELINE
mathTranscendental 4 1.08x 0.04x NO BASELINE
arraySequential 4 0.36x 0.37x NO BASELINE
arrayRandom 4 0.94x 0.20x NO BASELINE
objectAllocation 4 2.32x 0.32x NO BASELINE
valueEscape 4 0.51x 0.03x NO BASELINE
hashMapChurn 4 0.70x 0.12x NO BASELINE
stringBuilding 4 1.57x 0.32x NO BASELINE
recursion 4 1.42x 0.04x NO BASELINE
quicksort 4 0.97x 0.09x NO BASELINE

No baseline for 13 rows on linux-arm64@neoverse-v3, so this gate fails. Add them to vm/selfhost/perf-baseline/pr/6118.json from this job's perf-results.json (in its uploaded artifact) and commit it with this pull request:

python3 vm/selfhost/calibrate-perf-baseline.py --pr 6118 perf-results.json
The rows it will add
{
 "linux-arm64@neoverse-v3": {
  "hello": {
   "all": {
    "time": 1.001,
    "memory": 0.886
   }
  },
  "translator": {
   "all": {
    "time": 0.739,
    "memory": 0.417
   }
  },
  "intArithmetic": {
   "all": {
    "time": 1.0,
    "memory": 0.035
   }
  },
  "longArithmetic": {
   "all": {
    "time": 1.043,
    "memory": 0.036
   }
  },
  "mathTranscendental": {
   "all": {
    "time": 1.076,
    "memory": 0.037
   }
  },
  "arraySequential": {
   "all": {
    "time": 0.362,
    "memory": 0.368
   }
  },
  "arrayRandom": {
   "all": {
    "time": 0.939,
    "memory": 0.202
   }
  },
  "objectAllocation": {
   "all": {
    "time": 2.32,
    "memory": 0.316
   }
  },
  "valueEscape": {
   "all": {
    "time": 0.508,
    "memory": 0.031
   }
  },
  "hashMapChurn": {
   "all": {
    "time": 0.696,
    "memory": 0.118
   }
  },
  "stringBuilding": {
   "all": {
    "time": 1.573,
    "memory": 0.317
   }
  },
  "recursion": {
   "all": {
    "time": 1.419,
    "memory": 0.036
   }
  },
  "quicksort": {
   "all": {
    "time": 0.972,
    "memory": 0.094
   }
  }
 }
}

Result: no baseline: calibration required

@shai-almog

shai-almog commented Oct 27, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 206 screenshots: 206 matched.
Native Windows port (arm64 / Apple Silicon - Arm): full hellocodenameone screenshot suite rendered offscreen with Direct2D/DirectWrite, plus the real benchmarks (base64 native/CN1/SIMD, image createMask/applyMask/modifyAlpha/PNG/JPEG, NEON SIMD kernels). Compared against the in-repo baseline in scripts/windows/screenshots.

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 53ms / native 3ms = 17.6x speedup
SIMD float-mul (64K x300) java 54ms / native 2ms = 27.0x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 native bridge unavailable (CN1 + SIMD + image benchmarks only)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path gated to scalar (CPU autovectorizes scalar; explicit SIMD not beneficial here)
Base64 CN1 encode 60.000 ms
Base64 CN1 decode 70.000 ms
Base64 SIMD encode 77.000 ms
Base64 encode ratio (SIMD/CN1) 1.283x (28.3% slower)
Base64 SIMD decode 73.000 ms
Base64 decode ratio (SIMD/CN1) 1.043x (4.3% slower)
Image encode benchmark iterations 100
Image createMask (SIMD off) 6.000 ms
Image createMask (SIMD on) 2.000 ms
Image createMask ratio (SIMD on/off) 0.333x (66.7% faster)
Image applyMask (SIMD off) 19.000 ms
Image applyMask (SIMD on) 20.000 ms
Image applyMask ratio (SIMD on/off) 1.053x (5.3% slower)
Image modifyAlpha (SIMD off) 17.000 ms
Image modifyAlpha (SIMD on) 18.000 ms
Image modifyAlpha ratio (SIMD on/off) 1.059x (5.9% slower)
Image modifyAlpha removeColor (SIMD off) 30.000 ms
Image modifyAlpha removeColor (SIMD on) 24.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.800x (20.0% faster)

ParparVM vs HotSpot (JDK 25): Windows arm64

Runner CPU: ARMv8 (64-bit) Family 8 Model D49 Revision 0, MICROSOFT CORPORATION (baseline windows-arm64@armv8-64-bit-family-8-model-d49-microsoft-corporation)

Ratios are ParparVM / JDK 25: below 1.00x ParparVM is faster (time) or smaller (RAM). Median of 5 interleaved, paired rounds; every run's output was verified. A ratio more than 20% (time) / 25% (RAM) above its baseline in vm/selfhost/perf-baseline/ is a regression and fails; one that far below is an improvement, reported but not failed (a row whose calibration runs were noisier carries a wider tolerance), and for RAM the change must also exceed 0.05x in absolute terms. Both run unpinned on all of the runner's CPUs, with their own default thread counts.

Benchmark Cores Time RAM Status
hello (WinHelloMain) 4 1.04x (base 1.11x, -6.5%) 0.60x (base 0.75x, -20.1%) ok
translator (self) 4 0.88x (base 0.84x, +5.4%) 0.47x (base 0.51x, -7.3%) ok
intArithmetic 4 1.04x (base 1.04x, -0.0%) 0.06x (base 0.06x, +3.0%) ok
longArithmetic 4 0.79x (base 0.80x, -0.0%) 0.06x (base 0.06x, +3.5%) ok
mathTranscendental 4 0.72x (base 0.72x, -0.0%) 0.07x (base 0.06x, +1.6%) ok
arraySequential 4 0.36x (base 0.46x, -20.3%) 0.39x (base 0.39x, +0.1%) ok
arrayRandom 4 0.94x (base 0.94x, +0.7%) 0.23x (base 0.23x, +0.2%) ok
objectAllocation 4 1.80x (base 1.82x, -1.2%) 0.33x (base 0.43x, -23.8%) ok
valueEscape 4 0.76x (base 0.76x, +0.0%) 0.05x (base 0.05x, +2.4%) ok
hashMapChurn 4 0.99x (base 0.98x, +0.1%) 0.12x (base 0.12x, -0.3%) ok
stringBuilding 4 1.60x (base 1.43x, +12.4%) 0.27x (base 0.27x, -0.1%) ok
recursion 4 1.55x (base 1.46x, +5.7%) 0.07x (base 0.07x, +1.1%) ok
quicksort 4 1.00x (base 1.00x, +0.2%) 0.12x (base 0.12x, +0.5%) ok

Result: no regression

…uct on x86, CI fixes

- Ed25519.verify checks [u]B - [v1]R - [v0]A = O with v0 = v1 k (mod 8L), v1 odd,
  both near 2^127 (binary Euclid on the lattice); exact for every input, torsion
  included, with (k, 1) as the fallback row. Half the doublings.
- Field product: Karatsuba over the two limb halves (75 products instead of 100)
  on x86 JVMs, where ref10's form is multiplier-bound; ref10 stays on arm64.
- Guide and javadoc snippets self-contained for the Playground; the bash block
  moved to docs/demos. The Playground auto-imports the outer class of Outer.Inner.
- Android kernel stamp, bastion template zip, Vulkan ABI check kernel ids, a
  narrowing compound assignment CodeQL flagged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

✅ ByteCodeTranslator Quality Report

Test & Coverage

  • ✅ Tests: 883 total, 0 failed, 55 skipped

Benchmark Results

  • Execution Time: 9508 ms

  • Hotspots (Top 20 sampled methods):

    • 9.52% com.codename1.tools.translator.IteratorEscape.ctorOnlyStoresParamsIntoThis (138 samples)
    • 8.01% java.util.ArrayList.indexOf (116 samples)
    • 5.59% java.lang.Object.hashCode (81 samples)
    • 5.38% java.lang.System.identityHashCode (78 samples)
    • 4.35% com.codename1.tools.translator.classfile.analysis.Frame.execute (63 samples)
    • 3.80% java.lang.StringBuilder.append (55 samples)
    • 3.31% com.codename1.tools.translator.BytecodeMethod.equals (48 samples)
    • 2.48% com.codename1.tools.translator.bytecodes.Invoke.findMethodUp (36 samples)
    • 2.42% com.codename1.tools.translator.IteratorEscape.mangle (35 samples)
    • 1.79% java.lang.String.equals (26 samples)
    • 1.52% java.util.HashMap.hash (22 samples)
    • 1.45% java.util.AbstractCollection.containsAll (21 samples)
    • 1.38% com.codename1.tools.translator.bytecodes.Invoke.resolveDirectTarget (20 samples)
    • 1.31% com.codename1.tools.translator.ReachabilityCull.run (19 samples)
    • 1.10% com.codename1.tools.translator.ByteCodeClass.hasDeclaredMethod (16 samples)
    • 1.04% java.util.HashMap.putVal (15 samples)
    • 0.97% com.codename1.tools.translator.JavascriptReachability.enqueueResolved (14 samples)
    • 0.90% java.io.FileOutputStream.open0 (13 samples)
    • 0.90% com.codename1.tools.translator.Parser.cullMethods (13 samples)
    • 0.90% com.codename1.tools.translator.BytecodeMethod.updateInlinableFieldDependencies (13 samples)
  • ⚠️ Coverage report not generated.

Static Analysis

  • ✅ SpotBugs: no findings (report was not generated by the build).
  • ⚠️ PMD report not generated.
  • ⚠️ Checkstyle report not generated.

Generated automatically by the PR CI workflow.

@github-actions

github-actions Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Flutter vs Codename One

No benchmark results were produced.

@github-actions

github-actions Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Developer Guide build artifacts are available for download from this workflow run:

Developer Guide quality checks:

  • AsciiDoc linter: No issues found (report)
  • Vale: No alerts found (report)
  • Paragraph capitalization: No paragraph capitalization issues (report)
  • LanguageTool: No grammar matches (report)
  • Image references: No unused images detected (report)

shai-almog and others added 20 commits October 27, 2026 15:45
… chart alt texts

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… guide names the core classes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…point

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	Ports/LinuxPort/src/com/codename1/impl/linux/LinuxImplementation.java
#	docs/developer-guide/languagetool-accept.txt
#	vm/backend/package-docs/com/codename1/security/package-info.java
Two runners read 2.15 and 1.74 with our side unchanged (45 and 47
batches/s); the single-core reference moved 21 to 27. The row pits all
cores against one, so it measures the runner's core count too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The arm64 Linux suite landed on a runner CPU no run had measured, which the
gate reports as calibration required. Rows from that job's perf-results.json
via calibrate-perf-baseline.py; folded into base/ by the nightly job.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	scripts/bastion/common/src/test/java/com/codenameone/examples/bastion/net/GuardTest.java
…he Rust rps floor

crypto.encoding.Hex and crypto.encoding.Base64 duplicated Hash.toHex/fromHex and
java.util.Base64, which every target already has. Hash.fromHex now takes the 0x
prefix Ethereum writes. The backend gate's peak-throughput floor against Rust
moves from 1.0 to 0.97: passing runs lead by 0.5-2.7% and a noisy one fell 0.7%
short with the request path unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
UTF-8 goes through StandardCharsets.UTF_8, which every target has; Bech32 uses
Rlp's concat; Secp256k1Math's generator constants decode with Hash.fromHex.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d parsers

JSONParser no longer reaches processing.Result (mapToJson now has its own
writer, held byte-for-byte to Result's output by JSONParserSharedTest), Log
(a package-private Diagnostics sink Log installs from its static
initializer) or Util. It, JSONParseCallback, JSONSanitizer and
CharArrayReader are @SharedWithBackend.

New JSONParser.parseStrict(String[, exactIntegers]) is the RFC 8259 reader
moved from com.codename1.backend.Json; backend Json.parse delegates to it.
Crypto uses parseStrict(.., true) (an integer past a long is a RawJson of
its exact digits, never a double) and toJson for JSON-RPC requests;
crypto/encoding/Json is deleted. NetworkTransport uses StandardCharsets.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
JSONParser now carries the writer Result used, so HashtableContent calls
mapToJson and the new listToJson instead of keeping a second copy.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
com.codename1.util.BigInteger and the T* helpers it needs (plus MathUtil,
for TConversion's radix log) are marked @SharedWithBackend. The three
static bit helpers the T* classes borrowed from TBigDecimal move to
TBitLevel so TBigDecimal stays client-only. UInt256 drops its hand-written
limb arithmetic and keeps its API as a range-checked wrapper. Also removes
the redundant java.util.List qualifiers PMD flagged in JSONParser.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PrettyPrinter's code moved into JSONParser without the licence it carries;
it is io.PrettyPrinter now, notice and history intact, shared with the
backend. PriceFeeds wraps a malformed raw number in IOException as it does a
string one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e backend

The @SharedWithBackend marker touched eight vendored files (Apache Harmony,
Google json-sanitizer, Bouncy Castle), which pulled them into the diff-scoped
header gate. They keep their original notices, as their already-listed siblings do.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…64 and Hex

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants