Repository navigation
Swing, SwingX and JavaFX compatibility layers: desktop Java apps as Codename One apps #1348
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: ParparVM Self-Hosting | |
| # Translates the ByteCodeTranslator with itself and compares the result against | |
| # the same translation run on a JVM. | |
| # | |
| # What this buys that the existing suites do not: ByteCodeTranslator is a 37.6k | |
| # line real program that hammers collections, strings, exceptions, file I/O and | |
| # the GC at a scale no unit test reaches, and the emitted C is a byte-exact | |
| # expected value that costs nothing to maintain -- it is whatever the JVM | |
| # produced from the same inputs. A VM defect that changes behaviour rather than | |
| # crashing (a wrong hash order, a dropped write barrier, a mis-mangled symbol) | |
| # shows up as a diff instead of passing silently. | |
| # | |
| # Gates, cheapest first: | |
| # D native vs native, two fresh processes, same input. If the native side is | |
| # not self-consistent nothing else means anything, so it runs first. | |
| # A JVM vs native over the same corpus. The headline. | |
| # J the same comparison for the JavaScript target: the native translator | |
| # carries the JavaScript backend too, and must emit the same bundle. | |
| # C, S JVM vs the translator TRANSLATED TO JAVASCRIPT and run under Node, for | |
| # the C and the JavaScript targets (verify-selfhost-js.sh): self-hosting on | |
| # the JavaScript target. | |
| # Negative control: after a green comparison one emitted byte is flipped and | |
| # the comparator MUST report exactly that file. A comparator nobody has | |
| # watched fail is not a comparator. | |
| # | |
| # Not on the PR leg by default: a full run builds the translator twice and | |
| # translates a large corpus several times. It runs nightly, on demand, and on a | |
| # PR that opts in with the `selfhost` label. | |
| on: | |
| schedule: | |
| # 04:20 UTC daily, off the hour to avoid the runner rush. | |
| - cron: '20 4 * * *' | |
| workflow_dispatch: | |
| pull_request: | |
| types: [ opened, synchronize, reopened, labeled ] | |
| paths: | |
| - 'vm/**' | |
| - '.github/workflows/parparvm-selfhost.yml' | |
| - '!vm/**/README.md' | |
| - '!vm/**/docs/**' | |
| concurrency: | |
| # Only the latest revision needs validation. PR numbers keep forks isolated; | |
| # event names keep a manual/scheduled run from cancelling a push or PR run. | |
| group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.ref }} | |
| cancel-in-progress: true | |
| env: | |
| CN1_NATIVE_VERIFY: strict | |
| # A method the translator culled as unreachable is still emitted as a stub, | |
| # because dispatch tables name it. With this on, the stub aborts with the | |
| # method's name instead of returning 0, so a wrong cull fails the suite that | |
| # reached it rather than shipping a silent null. Ours to enforce, like | |
| # CN1_NATIVE_VERIFY: customer builds keep the plain stub. See | |
| # BytecodeMethod.appendMethodC. Not in the size or perf benchmarks, whose | |
| # binaries should be the ones customers get. | |
| CN1_CULL_TRAP: '1' | |
| jobs: | |
| selfhost: | |
| # On a pull_request only when the author asked for it; the schedule and | |
| # workflow_dispatch legs always run. | |
| if: >- | |
| github.event_name != 'pull_request' || | |
| contains(github.event.pull_request.labels.*.name, 'selfhost') | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 120 | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v6 | |
| - name: Install native build tools | |
| run: | | |
| bash scripts/ci/apt-get-update.sh | |
| # `time` is GNU time, which is what bench-selfhost.sh's Linux peak-memory | |
| # probe reads ("Maximum resident set size"). The shell builtin is not it. | |
| sudo apt-get install -y clang time | |
| # ONLY A JDK 8 HERE. This workflow used to set up a JDK 25 as well, for a | |
| # performance step that has since moved into each platform's own build (see the | |
| # note further down); nothing left in this job reads JDK_25_HOME, so setting it up | |
| # would just be a slower runner. bench-selfhost.py names each arm after the JDK's | |
| # real feature version, so a missing JDK 25 raises instead of silently measuring | |
| # JDK 8 against itself. | |
| - name: Set up JDK 8 | |
| uses: actions/setup-java@v5 | |
| with: | |
| distribution: 'temurin' | |
| java-version: '8' | |
| cache: 'maven' | |
| - name: Save JDK 8 path | |
| run: echo "JDK_8_HOME=$JAVA_HOME" >> $GITHUB_ENV | |
| # The translator has to exist as classes before it can translate itself. | |
| - name: Build the translator | |
| run: >- | |
| "$GITHUB_WORKSPACE/scripts/ci/retry.sh" mvn -q -B | |
| -pl ByteCodeTranslator -am package -DskipTests | |
| working-directory: vm | |
| # -O1: the diff gates care about the EMITTED C, not about how well clang | |
| # optimised the binary that emitted it, and -O1 links several times faster. | |
| # | |
| # NO -DCN1_GC_MARK_THREADS HERE ANY MORE. This step used to pin 4 markers | |
| # because "the source default resolves to a single marker and makes a large | |
| # corpus take hours" -- both halves of that are now false: the default is | |
| # CPU-derived (capped at 4) on POSIX. Pinning it would leave the one workflow | |
| # that actually self-hosts unable to notice a regression in the very default | |
| # it exists to exercise, which is how the single-marker default survived in | |
| # the first place. Build what ships. | |
| - name: Build the self-hosted translator | |
| run: vm/selfhost/build-selfhost.sh | |
| # The corpus is the translator's OWN classes plus ASM, which build-selfhost.sh | |
| # fetches and extracts as corpus only -- the translator does not use it. verify-selfhost.sh | |
| # prepends vm/selfhost/target/javaapi-classes itself, so it is not repeated | |
| # here. Absolute paths: the script runs both sides under `env -i` into one | |
| # fixed output directory, so a relative path would not survive. | |
| - name: Gate D and Gate A, with the negative control | |
| run: | | |
| vm/selfhost/verify-selfhost.sh \ | |
| "$PWD/vm/selfhost/target/asm-classes;$PWD/vm/selfhost/target/classes" \ | |
| com_codename1_tools_translator_ByteCodeTranslator \ | |
| com.codename1.tools.translator | |
| # PERFORMANCE MOVED OUT, into every platform's own build: vm/selfhost/ci-perf-gate.sh | |
| # runs in linux-build-run.yml (x64, arm64), parparvm-tests-windows.yml (x64, arm64) | |
| # and scripts-macos.yml, fails that build on a regression and puts the per-benchmark | |
| # table in that platform's PR comment. | |
| # | |
| # It used to live here, building the translator a second time at -O3 and then | |
| # reporting (never gating) the ratio against JDK 25. Two reasons it is gone: | |
| # | |
| # - This workflow is the CORRECTNESS suite and it only runs on a PR that asks | |
| # for it by label. A performance regression has to fail on the PR that causes | |
| # it, not on whichever nightly somebody reads next, so the perf gate runs on | |
| # every pull request touching vm/** instead. | |
| # - Keeping it in both places would pay for the expensive -O3 self-host build | |
| # twice on any PR carrying the `selfhost` label. | |
| # | |
| # The baselines and tolerance live in vm/selfhost/perf-baseline/, the | |
| # measurement in vm/selfhost/perf-gate.py. | |
| - name: Set up Node | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: '20' | |
| # The translator as a JavaScript program, against the JVM translator, over the | |
| # same corpus. build-selfhost.sh has already compiled it against JavaAPI. | |
| - name: Gate C and Gate S, self-hosted on JavaScript | |
| run: | | |
| vm/selfhost/verify-selfhost-js.sh \ | |
| "$PWD/vm/selfhost/target/asm-classes;$PWD/vm/selfhost/target/classes" \ | |
| com_codename1_tools_translator_ByteCodeTranslator \ | |
| com.codename1.tools.translator | |
| # Both trees, so a divergence can be inspected rather than guessed at from | |
| # a one-line summary. | |
| - name: Upload the compared trees on failure | |
| if: failure() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: selfhost-trees | |
| path: | | |
| vm/selfhost/target/verify/jvm-tree | |
| vm/selfhost/target/verify/parpar1-tree | |
| vm/selfhost/target/verify/parpar2-tree | |
| vm/selfhost/target/verify/*.txt | |
| vm/selfhost/target/verify/*.log | |
| vm/selfhost/target/verify-js/*-tree | |
| vm/selfhost/target/verify-js/*.txt | |
| vm/selfhost/target/verify-js/*.log | |
| retention-days: 7 | |
| if-no-files-found: ignore |