Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
da3e292
Give ParparVM real primitive class objects; Integer.TYPE was null
shai-almog Sep 9, 2026
87be20f
Make ParparVM self-hosting: the translator now translates itself
shai-almog Sep 9, 2026
9ebb174
Measure the self-hosted translator: it is 6x slower and uses 2.8x the…
shai-almog Sep 9, 2026
842bc63
Stop stubbing JavascriptNativeRegistry; gates A and B are now byte-id…
shai-almog Sep 10, 2026
6263a35
Profile the self-hosted translator: the 6x gap is one pacing clamp, n…
shai-almog Sep 10, 2026
fff6f53
Scale the GC pacing floor with available RAM, and index the constant …
shai-almog Sep 10, 2026
0077691
Wire up the heap/allocation census, and make -O3 imply ThinLTO
shai-almog Sep 10, 2026
82a710a
Stop ArrayList and IdentityHashMap allocating for nothing
shai-almog Sep 10, 2026
3f20c45
Add a live-heap census: what is IN the heap, not just what was allocated
shai-almog Sep 10, 2026
3f1bee7
Census the heap by WHY each slot is occupied, and answer it with expe…
shai-almog Sep 10, 2026
d12892d
Make the second grace cycle optional: it is a 2014 pre-SATB workaround
shai-almog Sep 10, 2026
6069535
Revert the aging switch: the rule is load-bearing, and it was only wo…
shai-almog Sep 10, 2026
f44235f
Record why the second grace cycle stays: four mechanisms now depend o…
shai-almog Sep 10, 2026
118044d
ParparVM: make the translator self-hosting, and fix what that exposed
shaiblah Sep 10, 2026
01643b7
Review fixes: guard on the completion flag, refuse stack manipulation…
shai-almog Sep 10, 2026
a57b3ec
Apple targets: stop the translated java.io.File overwriting the port'…
shai-almog Sep 10, 2026
b236ee3
Revert the inline class-init guards; keep the memory-ordering fix
shai-almog Sep 10, 2026
28e62d6
Park at the safepoint after a pacing assist, and drop a synthetic bridge
shai-almog Sep 11, 2026
f0718e6
Give a for-each the concrete Iterator type its collection returns
shai-almog Sep 11, 2026
68503d5
Collect real crash evidence, and withdraw the lazy ArrayList allocation
shai-almog Sep 11, 2026
2ad038a
Root cause: the fused concat natives allocate with the source strings…
shai-almog Sep 11, 2026
a5ec187
Revert the fused-concat GC bracket: the premise was wrong
shai-almog Sep 11, 2026
7d1b503
BISECT PROBE: turn off both bytecode-rewriting passes
shai-almog Sep 11, 2026
718aa7b
BISECT PROBE 2: revert the whole runtime side to the merge base
shai-almog Sep 11, 2026
036daff
BISECT PROBE 3: the cause is in the runtime; narrow it to java/util
shai-almog Sep 11, 2026
25205a8
Bounds-check the ArrayList iterator's array read
shai-almog Sep 11, 2026
2700998
Withdraw the GC pacing work and the String natives; keep what is just…
shai-almog Sep 12, 2026
84065db
Restore the pacing cap, drop the StringBuilder growth change
shai-almog Sep 12, 2026
7d8754b
Merge remote-tracking branch 'origin/master' into parparvm-selfhost-o…
shai-almog Sep 12, 2026
c81f41d
Re-apply the self-hosting rewrites on top of master's refactor
shai-almog Sep 12, 2026
f00db7e
Fix the iterator lowering's lifetime bug, and withdraw the concat fusion
shai-almog Sep 12, 2026
8275e5b
Review round: primitive-class reflection, empty resources, duplicate …
shai-almog Sep 12, 2026
ea47102
Restore readFileAsString, and make replaceInFile single-pass
shai-almog Sep 12, 2026
4333174
Install gdb from an absolute path: it has never been installed at all
shai-almog Sep 12, 2026
1b2cbfb
Guard class use on completion, not on "initialisation started"
shai-almog Sep 12, 2026
670fb6c
Bind Class.getResourceAsStream to the generated port resource tables
shai-almog Sep 12, 2026
73a49fc
PROBE: run the Linux suite with the mutator assist disabled
shai-almog Sep 12, 2026
a995987
Add a diagnostic define hook to the generated Linux CMake project
shai-almog Sep 12, 2026
3c32a10
Guard the Windows resource override behind _WIN32
shai-almog Sep 12, 2026
7a4b086
The mutator assist is exonerated; turn the heap verifier on instead
shai-almog Sep 12, 2026
8483268
Make the verifier run prove it ran
shai-almog Sep 12, 2026
a86b7cd
Report whether the generated project declares the diagnostic hook
shai-almog Sep 12, 2026
7eaab0b
Probe the built ELF for the verifier instead of trusting the chain
shai-almog Sep 12, 2026
ef5b6f9
The GC is exonerated: 2213 clean epochs. Look at page recycling instead
shai-almog Sep 12, 2026
2f6748b
PROBE: revert java/util, the last delta the collector work did not clear
shai-almog Sep 12, 2026
628c0da
PROBE: withdraw the safepoint park; restore java/util, which is clear
shai-almog Sep 12, 2026
c66da37
PROBE: stop handing out the primitive class objects
shai-almog Sep 12, 2026
ed057be
Initialise java.lang.Class before handing out a primitive class object
shai-almog Sep 12, 2026
1c6dc85
Register the primitive class descriptors in the GC's clazz registry
shai-almog Sep 12, 2026
f1da543
Withdraw the primitive class objects; key the C-type tables on an enum
shai-almog Sep 13, 2026
c851171
Review round: resource lookup hardening, CI paths, and the JS getenv …
shai-almog Sep 13, 2026
25159f2
Merge remote-tracking branch 'origin/master' into parparvm-selfhost-o…
shai-almog Sep 13, 2026
23a9399
Count a backslash as a separator in the resource traversal check
shai-almog Sep 13, 2026
df53b70
Withdraw the pacing growth-floor scaling; it disarmed the bound CI en…
shai-almog Sep 13, 2026
66d247a
Withdraw the pacing run-ahead bound too; restore master's cap exactly
shai-almog Sep 13, 2026
8d2a8f0
Stop reading embedded resources from getResourceAsStream; it moved ap…
shai-almog Sep 13, 2026
52f3d46
Correct the record: withdrawing the embedded tier did not fix the scr…
shai-almog Sep 13, 2026
3550d2e
Fix the iOS warning-census regression, and PROBE the inline class-ini…
shai-almog Sep 13, 2026
8fc9a4c
Guard class init on an ACQUIRE load of .initialized, not on __X_LOADED__
shai-almog Sep 13, 2026
f20c895
Give the neutrality gate a vs-master mode, and drop the now-vestigial…
shai-almog Sep 13, 2026
8c67b53
Review round: the gate I built to catch codegen drift could not fail
shai-almog Sep 13, 2026
26d6b04
Record the three pushbacks in the code, so every review thread has an…
shai-almog Sep 13, 2026
9a59f2f
Two findings I resolved without reading: unique arm names, quiesced e…
shai-almog Sep 13, 2026
64e5fa5
The self-hosting gates ran with the native verifier OFF, and invented…
shai-almog Sep 13, 2026
d669466
Fix the runtime exclusion regex: two backslashes matched nothing
shai-almog Sep 13, 2026
8dbdec3
Restore the absolute-path gdb install, and stop the GC loop before th…
shai-almog Sep 14, 2026
8947134
Merge remote-tracking branch 'origin/master' into parparvm-selfhost-o…
shai-almog Sep 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .github/workflows/linux-build-run.yml
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,13 @@ jobs:
# hang-stacks.txt with nothing but sample headers -- which is how four
# occurrences of the suite stall ended up with no evidence at all. Still
# best-effort: a runner without gdb must not fail the suite, it must say so.
bash scripts/ci/apt-get-install.sh gdb || echo "WARNING: gdb install failed"
# ABSOLUTE path. This step runs under `working-directory: vm`, so the
# relative form resolved to vm/scripts/ci/apt-get-install.sh, bash answered
# "No such file or directory", and the `|| echo` swallowed it -- gdb has
# NEVER been installed here. Every post-mortem in this job therefore
# produced nothing, including the SIGSEGV this run just hit, which uploads
# a core nobody can read. Same shape as the retry.sh path fixed elsewhere.
bash "$GITHUB_WORKSPACE/scripts/ci/apt-get-install.sh" gdb || echo "WARNING: gdb install failed"
if command -v gdb >/dev/null 2>&1; then
echo "gdb available: $(gdb --version | head -1)"
else
Expand Down
121 changes: 121 additions & 0 deletions .github/workflows/parparvm-selfhost.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
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.
# 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:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

env:
CN1_NATIVE_VERIFY: strict

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-latest
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
sudo apt-get install -y clang

- 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

- name: Resolve the ASM classpath
run: >-
"$GITHUB_WORKSPACE/scripts/ci/retry.sh" mvn -q -B -pl ByteCodeTranslator
dependency:build-classpath
-Dmdep.outputFile=target/selfhost-asm-classpath.txt
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.
# Mark threads are set explicitly rather than left to the source default,
# which resolves to a single marker and makes a large corpus take hours.
- name: Build the self-hosted translator
run: vm/selfhost/build-selfhost.sh
env:
CN1_SELFHOST_CFLAGS: -DCN1_GC_MARK_THREADS=4

# The corpus is the translator's OWN classes plus ASM. 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

# 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
retention-days: 7
if-no-files-found: ignore
4 changes: 2 additions & 2 deletions scripts/check-native-signatures.sh
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ for arg in "$@"; do
esac
done

if [[ ! -f "$TRANSLATOR/com/codename1/tools/translator/NativeSignatureVerifier.class" ]]; then
if [[ ! -f "$TRANSLATOR/com/codename1/tools/translator/NativeSignatureVerifierCli.class" ]]; then
echo "check-native-signatures: building the translator" >&2
(cd "$REPO_ROOT/vm" && mvn -q -B -pl ByteCodeTranslator -am package -DskipTests)
fi
Expand Down Expand Up @@ -95,7 +95,7 @@ for entry in "${PORTS[@]}"; do

echo "== $name"
if ! java -cp "$TRANSLATOR:$(cat "$ASM_CP_FILE")" \
com.codename1.tools.translator.NativeSignatureVerifier "${args[@]}"; then
com.codename1.tools.translator.NativeSignatureVerifierCli "${args[@]}"; then
status=1
fi
checked=$((checked + 1))
Expand Down
1 change: 1 addition & 0 deletions scripts/copyright-header-exclusions.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,4 @@ vm/JavaAPI/src/java/util/Collections.java | Apache Harmony source retaining its
vm/JavaAPI/src/java/util/HashMap.java | Apache Harmony source retaining its original Apache-2.0 notice
vm/JavaAPI/src/java/util/Hashtable.java | Apache Harmony source retaining its original Apache-2.0 notice
vm/JavaAPI/src/java/util/IdentityHashMap.java | Apache Harmony source retaining its original Apache-2.0 notice
vm/JavaAPI/src/java/util/ArrayList.java | Apache Harmony source retaining its original Apache-2.0 notice
4 changes: 2 additions & 2 deletions vm/ByteCodeTranslator/src/cn1_globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -2218,15 +2218,15 @@ static inline JAVA_OBJECT cn1BibopFastAllocNoZero(CODENAME_ONE_THREAD_STATE, int
// because bibopCurrent[] is shared across all classes of the same size class).
#if !defined(CN1_DISABLE_INLINE_ALLOC) && !defined(CN1_DISABLE_BIBOP)
#define CN1_FAST_NEW(X) ({ \
if(__builtin_expect(!class__##X.initialized, 0)) __STATIC_INITIALIZER_##X(threadStateData); \
if(__builtin_expect(!__atomic_load_n(&class__##X.initialized, __ATOMIC_ACQUIRE), 0)) __STATIC_INITIALIZER_##X(threadStateData); \
JAVA_OBJECT __cn1fo = cn1BibopFastAlloc(threadStateData, sizeof(struct obj__##X), &class__##X, CN1_BIBOP_CIDX(sizeof(struct obj__##X))); \
if(__builtin_expect(__cn1fo == (JAVA_OBJECT)0, 0)) __cn1fo = __NEW_##X(threadStateData); \
__cn1fo; })
// No-body-zero variant (init-before-publish). The slow-path fallback __NEW_X
// still fully zeroes (calloc) -- correct, just un-elided on the rare page-full
// path.
#define CN1_FAST_NEW_NOZERO(X) ({ \
if(__builtin_expect(!class__##X.initialized, 0)) __STATIC_INITIALIZER_##X(threadStateData); \
if(__builtin_expect(!__atomic_load_n(&class__##X.initialized, __ATOMIC_ACQUIRE), 0)) __STATIC_INITIALIZER_##X(threadStateData); \
JAVA_OBJECT __cn1fo = cn1BibopFastAllocNoZero(threadStateData, sizeof(struct obj__##X), &class__##X, CN1_BIBOP_CIDX(sizeof(struct obj__##X))); \
if(__builtin_expect(__cn1fo == (JAVA_OBJECT)0, 0)) __cn1fo = __NEW_##X(threadStateData); \
__cn1fo; })
Expand Down
Loading
Loading