Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
164 commits
Select commit Hold shift + click to select a range
17c5ce8
ParparVM perf tier1: box caches, BCE, conditional-volatile SSA, nurse…
shai-almog Jun 27, 2026
185085c
ParparVM: pre-size the StringBuilder in invokedynamic string-concat l…
shai-almog Jun 27, 2026
f123617
ParparVM tagged-int: fix 4 header-deref crashes found by edge-case re…
shai-almog Jun 27, 2026
7049ad0
ParparVM: native HashMap.get (closed-world hot-path wrapper collapse)
shai-almog Jun 27, 2026
519d5e1
ParparVM: native HashMap.put (closed-world hot-path wrapper collapse)
shai-almog Jun 27, 2026
bc9e713
ParparVM: native StringBuilder.append(int)/append(long) digit writers
shai-almog Jun 27, 2026
5da6233
ParparVM: HashMap Entry object pool (eliminate churn allocation)
shai-almog Jun 27, 2026
ae6af08
ParparVM: StringBuilder.toString shares the buffer (copy-on-write)
shai-almog Jun 27, 2026
be882e4
ParparVM: inline the full method-frame setup/teardown
shai-almog Jun 27, 2026
7fc70f2
ParparVM: inline pop() (operand-stack pop helper)
shai-almog Jun 27, 2026
d4185da
ParparVM: @StackAllocate annotation -> stack-allocate non-escaping ob…
shai-almog Jun 28, 2026
8ea3c18
ParparVM: scalar-replace @StackAllocate objects -> clang promotes to …
shai-almog Jun 28, 2026
7469b54
ParparVM: fuse LCMP+IFxx into a direct long comparison (clang can vec…
shai-almog Jun 28, 2026
ab36ca8
ParparVM: elide per-line stack-trace line stores on non-throwing lines
shai-almog Jun 28, 2026
aa2838e
ParparVM: parallel GC marking (work-pool drain, atomic claim)
shai-almog Jun 28, 2026
7df04ea
ParparVM: non-moving BiBOP segregated heap + page sweep for small obj…
shai-almog Jun 28, 2026
0260fe8
ParparVM: frameless codegen for primitive-only methods (recursion 4.6…
shai-almog Jun 29, 2026
b0e6c98
ParparVM: conservative native-stack GC + frameless for object-bearing…
shai-almog Jun 29, 2026
9933311
ParparVM: fix Thread.start/join visibility race (alive set on wrong t…
shai-almog Jun 29, 2026
d34c80c
ParparVM: default-on conservative native-stack GC + object/instance f…
shai-almog Jun 29, 2026
37e8f62
ParparVM: inline BiBOP bump alloc fast-path at the new-site (-DCN1_IN…
shai-almog Jun 29, 2026
85502d5
ParparVM: inline tiny leaf constructors + de-atomic byte accounting (…
shai-almog Jun 29, 2026
3edcbc8
ParparVM: fix use-after-free in conservative-GC root-snapshot build (…
shai-almog Jun 29, 2026
b3dcdf3
ParparVM: make the alloc fast-path default-on (un-gate; this is an AO…
shai-almog Jun 30, 2026
bd0d808
ParparVM: adaptive allocation pacing (bound churn RSS) + batched page…
shai-almog Jun 30, 2026
9c9e298
ParparVM: O(live-pages) BiBOP sweep -- O(1) reclaim/skip of homogeneo…
shai-almog Jun 30, 2026
4b82a95
ParparVM: trim the per-object BiBOP alloc fast path (dead store + cou…
shai-almog Jun 30, 2026
60b9910
ParparVM: shrink the per-object header 48 -> 16 bytes (relocate 3 GC …
shai-almog Jun 30, 2026
3008cfa
ParparVM: always-on per-object memset elimination + thread-stop GC ha…
shai-almog Jul 2, 2026
0f8afae
ParparVM: single-writer allObjectsInHeap (dead-thread drain) + once-p…
shai-almog Jul 2, 2026
a7de4b0
ParparVM: general fused objects (@Fused) + small arrays in BiBOP + Ja…
shai-almog Jul 2, 2026
6373a47
ParparVM: computed-size fused children (new int[w*h]) + ThinLTO for R…
shai-almog Jul 2, 2026
d136205
ParparVM: register-allocatable locals, frameless whitelist holes, fmo…
shai-almog Jul 2, 2026
7a507a4
ParparVM: per-page sticky monitor flag replaces the global sweep supp…
shai-almog Jul 2, 2026
04e9dad
ParparVM: closed-world devirtualization, String finalizer removal, st…
shai-almog Jul 2, 2026
4a2aa8b
Compact open-addressed HashMap + native String compare: hashMapChurn …
shai-almog Jul 2, 2026
fe7a37e
Fused StringBuilder + native single-block toString; setLength zero-fi…
shai-almog Jul 2, 2026
65a965f
Diverging array checks in frameless loops: quicksort below HotSpot
shai-almog Jul 2, 2026
088d89e
Implicit stack allocation of non-escaping StringBuilders + two GC-tri…
shai-almog Jul 2, 2026
287369b
Merge remote-tracking branch 'origin/master' into parparvm-perf-tier1
shai-almog Jul 2, 2026
d58d816
String/StringBuilder call-site intrinsics; native-bracket elision; GC…
shai-almog Jul 2, 2026
a2148bd
Fix Linux/Windows portability of the conservative-GC + allocator code
shai-almog Jul 2, 2026
ecaa19e
Fix remaining CI failures: Win32 shim gaps, JS delegate retention, st…
shai-almog Jul 2, 2026
64946a6
Fix missing include when trivial-accessor inlining crosses classes
shai-almog Jul 2, 2026
59ea779
Fix two more trivial-accessor inlining bugs: setter arity, fold order…
shai-almog Jul 2, 2026
f363d3f
Fix setjmp/longjmp UB in try/catch codegen: restoreTo must be volatile
shai-almog Jul 2, 2026
acd947f
Fix mid-line preprocessor directive from the ctor-inlining emission
shai-almog Jul 2, 2026
e094586
iOS port: migrate the ellipsis-string pin to the immortal-root registry
shai-almog Jul 3, 2026
3a2eb81
Preallocate StackOverflowError: throwing at exhaustion must not build…
shai-almog Jul 3, 2026
ba4ed19
Fix the two SpotBugs gate violations in BytecodeMethod
shai-almog Jul 3, 2026
4f911a8
Benchmark suite in-repo; charAt logical-length bound; tagged ints def…
shai-almog Jul 3, 2026
39e18bb
Developer guide: satisfy the prose quality gates on the new section
shai-almog Jul 3, 2026
1669554
Refresh Linux picker goldens: the old ones encoded the case-conversio…
shai-almog Jul 3, 2026
736f43b
watch tests: capture app console + instrument toast/annotation state
shai-almog Jul 3, 2026
86bbe64
VM: release the class-init monitor when a static initializer throws
shai-almog Jul 3, 2026
5f0af69
Merge remote-tracking branch 'origin/master' into parparvm-perf-tier1
shai-almog Jul 3, 2026
3cdc797
signed bytes on ARM-Linux; deterministic toast test; linux suite diag…
shai-almog Jul 3, 2026
c879be9
VM: key monitor reentrancy on the pthread, not the thread-state id
shai-almog Jul 3, 2026
6a0070c
CN1_MONITOR_SELF: use the compat shim's pthread_self().id on Windows
shai-almog Jul 3, 2026
81af321
linux harness: create CN1_APP_LOG_TEE parent dirs
shai-almog Jul 3, 2026
1bcf273
JS port: protect runtime-delegate twins from identifier minification
shai-almog Jul 3, 2026
d2b2608
linux CI: gdb hang watchdog for the suite wedge
shai-almog Jul 3, 2026
7072d13
VM: frameless SOE guard must not misfire on foreign stacks
shai-almog Jul 3, 2026
66378a1
linux CI: the suite wedge is a silent crash -- capture cores + exit s…
shai-almog Jul 3, 2026
64c1dce
linux CI: richer GC-crash post-mortem
shai-almog Jul 3, 2026
163a5aa
toast test: hold for the slide animation before capturing
shai-almog Jul 3, 2026
30257f5
VM: acquire-load the mark word in parallel GC marking (arm64 heap cor…
shai-almog Jul 3, 2026
3ad6797
VM: default parallel GC marking to serial (arm64 isolation experiment)
shai-almog Jul 3, 2026
2763ccf
VM: exempt conservative stack scan from ASan (enables meaningful ASan…
shai-almog Jul 3, 2026
52bd25b
ToastBar: add non-animated show; make the TOP-position screenshot det…
shai-almog Jul 3, 2026
ef6e7b6
Revert ToastBar test changes to the known-good baseline
shai-almog Jul 3, 2026
c9d3b55
TEMP: Linux x64 ASan diagnostic workflow
shai-almog Jul 4, 2026
3a5b59c
linux-asan-x64: push-trigger on the feature branch (workflow_dispatch…
shai-almog Jul 4, 2026
c400885
linux-asan-x64: build the maven plugin before suite classes (mirror p…
shai-almog Jul 4, 2026
094245a
Remove temp Linux x64 ASan diagnostic workflow
shai-almog Jul 4, 2026
27a3332
VM: CN1_BIBOP_VALIDATE invariant checks for the x64 allocator crash
shai-almog Jul 4, 2026
68db022
TEMP: Linux x64 BiBOP-validate diagnostic workflow (x3 suite runs, re…
shai-almog Jul 4, 2026
0d1f7a1
CN1_BIBOP_VALIDATE: validate the object at the mark-drain source
shai-almog Jul 4, 2026
9c5ab69
CN1_BIBOP_VALIDATE: catch stale-mark + out-of-text markFunction at drain
shai-almog Jul 4, 2026
78752a2
VM FIX: gcMarkObject must reject freed BiBOP slots (x64 GC crash)
shai-almog Jul 4, 2026
de65c2c
Remove temp x64 BiBOP-validate diagnostic workflow (bug fixed + confi…
shai-almog Jul 4, 2026
0abf15f
Windows port: offscreen WIC capture for the cn1ss suite + BiBOP no-fa…
shai-almog Jul 5, 2026
1ab06af
GC forensics: pin the intermittent Linux gcMarkObject mid-mark SIGSEGV
shai-almog Jul 5, 2026
ff7a1f1
GC: SATB write barrier to close the concurrent-mark cross-thread race
shai-almog Jul 5, 2026
9ccb524
GC forensics: name the corrupt-child culprit (parent class + mark cal…
shai-almog Jul 5, 2026
2faff80
ci: post-mortem prints the mark drain-parent + its class name
shai-almog Jul 5, 2026
60ef4c7
GC: belt pass -- guarantee mark-drain completeness before sweep
shai-almog Jul 5, 2026
58b71b4
ci: A/B the O(1) all-dead reclaim (-DCN1_BIBOP_NO_FASTSWEEP) as crash…
shai-almog Jul 5, 2026
952ae3d
GC forensics: name the drain-incompleteness (belt-recovered class -> …
shai-almog Jul 5, 2026
8b6a56f
GC: revert looped belt to single-pass (looping livelocks vs active mu…
shai-almog Jul 5, 2026
0171685
GC: drain grace-object subtrees before sweep (fixes swept-while-reach…
shai-almog Jul 5, 2026
6dd95de
GC: add SATB insertion barrier to close the grace-object residual
shai-almog Jul 5, 2026
ffde9e2
GC: keep SATB armed through grace pass + belt (drain the log last)
shai-almog Jul 5, 2026
4888b66
GC: stop-the-world final mark -- loop belt to a true fixpoint (deadlo…
shai-almog Jul 5, 2026
275b672
Revert "GC: stop-the-world final mark -- loop belt to a true fixpoint…
shai-almog Jul 5, 2026
8055d28
GC: poor-man's generational adoption -- mature surviving BiBOP subtre…
shai-almog Jul 5, 2026
2a8e47a
GC: teach the remaining -4 (adopted) sentinel sites + VALIDATE guards
shai-almog Jul 5, 2026
7340a05
ci(linux): drop the temporary CN1_BIBOP_VALIDATE diagnostic from the …
shai-almog Jul 5, 2026
9c9bccf
GC: defer adoption registration out of the mark (fix reentrant allObj…
shai-almog Jul 5, 2026
35978db
GC: don't resurrect a dead matured object as an immortal root in the …
shai-almog Jul 5, 2026
47d7e5a
ci(linux): TEMP disambiguation -- build with adoption disabled (CN1_A…
shai-almog Jul 5, 2026
1df30d3
GC: a matured object's DEATH belongs to one collector (fix double-fin…
shai-almog Jul 5, 2026
8a14511
GC/stack: compute the real native stack limit on Linux (fix frameless…
shai-almog Jul 6, 2026
e7c670b
Revert "GC/stack: compute the real native stack limit on Linux (fix f…
shai-almog Jul 6, 2026
e8b3c11
linux: raise CN1 thread stack 16MB -> 64MB (fix arm64 EDT stack overf…
shai-almog Jul 6, 2026
3f8c626
ci(diag): dump native backtrace at 40MB stack depth to pin the arm64 …
shai-almog Jul 6, 2026
8cbd52e
Revert "ci(diag): dump native backtrace at 40MB stack depth to pin th…
shai-almog Jul 6, 2026
7fa3f90
Revert "linux: raise CN1 thread stack 16MB -> 64MB (fix arm64 EDT sta…
shai-almog Jul 6, 2026
58d4c9d
linux: register a per-thread alternate signal stack (make stack-overf…
shai-almog Jul 6, 2026
31ec45e
linux: dump the crash backtrace to stderr too (not just the BuildClou…
shai-almog Jul 6, 2026
4064ad5
linux: make stack-overflow faults dump a backtrace (SA_ONSTACK + wild…
shai-almog Jul 6, 2026
6bd4d7f
ci(linux): addr2line the CN1 fault-backtrace addresses in the post-mo…
shai-almog Jul 6, 2026
21040cc
ci(diag): fault dump prints faultPC/SP + thread stack bounds (is it a…
shai-almog Jul 6, 2026
4e9c332
ci(experiment): force CN1_GC_SIGNAL_STOP=1 to test the conservative r…
shai-almog Jul 6, 2026
6526da7
Revert "ci(experiment): force CN1_GC_SIGNAL_STOP=1 to test the conser…
shai-almog Jul 6, 2026
c55bd60
TEMP experiment: default frameless.objects/instance OFF to test arm64…
shai-almog Jul 6, 2026
77718d1
ci(diag): count conservative-resolve rejections of plausible live obj…
shai-almog Jul 6, 2026
1aa8d05
GC: conservative resolve must not drop a live object past the STALE s…
shai-almog Jul 6, 2026
3cc11bf
Revert "GC: conservative resolve must not drop a live object past the…
shai-almog Jul 6, 2026
64b64bd
Revert resolve idx>=bump change + drop diag flag (fix was wrong: acce…
shai-almog Jul 6, 2026
4447e98
GC: anchor object-bearing frameless frames in memory so the conservat…
shai-almog Jul 6, 2026
c554c2a
GC: zero the frameless frame at entry (memset) alongside the escape a…
shai-almog Jul 6, 2026
c6144be
GC: default object-bearing frameless OFF (unsound under conservative …
shai-almog Jul 6, 2026
8ab9c72
Revert anchor/memset/frameless-off experiments to baseline (best-know…
shai-almog Jul 6, 2026
d19c6bf
GC forensic (TEMP): detect + identify the arm64 conservative-scan roo…
shai-almog Jul 6, 2026
9171a22
GC forensic (TEMP): guard+identify the garbage parentCls gcMarkObject…
shai-almog Jul 6, 2026
dc2d1d7
GC forensic: fix build - widen gcMarkCurrentDrainObj to CN1_ROOTMISS_…
shai-almog Jul 6, 2026
94eeafb
GC: validate parentCls before dereferencing it in gcMarkObject (conse…
shai-almog Jul 6, 2026
b0f8f7c
GC: never let a finalizer/collection exception kill the GC thread (fi…
shai-almog Jul 7, 2026
0c1f0f5
Merge remote-tracking branch 'origin/master' into parparvm-perf-tier1
shai-almog Jul 7, 2026
de59f33
docs: migrate the @Fused perf-guide snippet to a demo-backed include
shai-almog Jul 7, 2026
d467f6b
Merge remote-tracking branch 'origin/master' into parparvm-perf-tier1
shai-almog Jul 7, 2026
26a1b92
mac-native: refresh ToastBarTopPosition golden (deterministic render,…
shai-almog Jul 7, 2026
6294eaf
tvOS: refresh ToastBarTopPosition golden (deterministic, max_channel_…
shai-almog Jul 7, 2026
4a970d8
screenshots: make ToastBar deterministic on slow sims + retry unready…
shai-almog Jul 7, 2026
5cc5d1b
iOS: re-baseline ToastBarTopPosition golden from the settled (6000ms)…
shai-almog Jul 7, 2026
dc4e152
Revert ToastBar goldens to the correct with-toast reference
shai-almog Jul 7, 2026
2001bd0
Merge remote-tracking branch 'origin/master' into parparvm-perf-tier1
shai-almog Jul 7, 2026
72f55ac
ToastBar screenshot: poll until the toast is actually visible before …
shai-almog Jul 7, 2026
88eb7f6
screenshots: never capture the wrong/unpainted form (fixes watch css-…
shai-almog Jul 7, 2026
07e4a20
Windows: symbolize the native crash backtrace in-process (dbghelp)
shai-almog Jul 8, 2026
1b5b7f1
sockets: keep the read buffer alive across the parked recv (fixes GC …
shai-almog Jul 8, 2026
57f1029
Windows WebSocket: pin the reader impl in a static so the GC can't sw…
shai-almog Jul 8, 2026
e9a9c7b
GC: capture the stack in CN1_YIELD_THREAD so parked native-blocking t…
shai-almog Jul 8, 2026
07f8219
WindowsSocket: directly-root a reused per-socket read buffer (fix con…
shai-almog Jul 8, 2026
35328bb
Grab reliability fixes from #5343: java.time parse/format + iOS schem…
shai-almog Jul 8, 2026
d11ba58
Revert the java.time grab from #5343 (broke TimeApiIntegrationTest vm…
shai-almog Jul 8, 2026
c4c4089
Merge remote-tracking branch 'origin/master' into parparvm-perf-tier1
shai-almog Jul 8, 2026
a41c38e
run-tv-ui-tests: don't prematurely settle capture on a slow-render stall
shai-almog Jul 8, 2026
193d95d
ParparVM conservative GC: capture the ACTUAL register file on Apple i…
shai-almog Jul 8, 2026
be8a17f
ParparVM GC: scan only GPR thread-state (__ss) in the Apple signal ha…
shai-almog Jul 8, 2026
65865f2
Document the conservative-GC root resolver architecture (why the per-…
shai-almog Jul 9, 2026
17c1e8d
ParparVM GC: dynamic, high-throughput-aware pacing cap (stop starving…
shai-almog Jul 9, 2026
d08dcd6
ParparVM: no-signal-mask setjmp/longjmp on Apple (try-blocks cost a s…
shai-almog Jul 9, 2026
5bcaf25
cn1ss: fix the landscape-leak suite corruption (VideoIODecodedFrames …
shai-almog Jul 9, 2026
bfc676e
cn1ss: don't poll restore-to-portrait on fixed-orientation platforms …
shai-almog Jul 9, 2026
477d053
Windows port: clamp clips to the flush region (#5273 class); gate Win…
shai-almog Jul 9, 2026
4047196
Windows: refresh graphics-partial-flush-clip-escape golden (old one b…
shai-almog Jul 9, 2026
e0bd1cb
ParparVM GC: exact clazz registry replaces the distance heuristic in …
shai-almog Jul 9, 2026
3f00a6c
maven plugin: pre-create lib/ in generated ant projects (updater File…
shai-almog Jul 9, 2026
dea3154
Fix updater lib/ FNFE at its real site (the antrun poms) + harden int…
shai-almog Jul 9, 2026
0cf1b87
cn1ss: fix the three remaining iOS screenshot races (vector-map readi…
shai-almog Jul 9, 2026
5dde4bc
Merge master: vector-map tile work off-EDT (#5350), skin scrollbar re…
shai-almog Jul 9, 2026
ba49900
cn1ss: don't freeze first-paint transients into the mutable-image gra…
shai-almog Jul 9, 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
43 changes: 42 additions & 1 deletion .github/workflows/linux-build-run.yml
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,9 @@ jobs:
working-directory: vm
env:
CN1_SHOT_OUTPUT_DIR: ${{ github.workspace }}/artifacts/linux-port/raw
# Full app stdout/stderr -- the only evidence when the suite wedges
# mid-run (uploaded with the screenshot artifact below).
CN1_APP_LOG_TEE: ${{ github.workspace }}/artifacts/linux-port/raw/app-output.log
# Build the native ELF (and the demo) against an old glibc for portability.
CN1_CC: /usr/local/bin/cn1-zig-cc
# After the suite runs, the capture test relinks the same objects into a
Expand All @@ -215,13 +218,50 @@ jobs:
LIBGL_ALWAYS_SOFTWARE: '1'
run: |
set -e
sudo apt-get install -y --no-install-recommends gdb >/dev/null 2>&1 || true
Xvfb :99 -screen 0 1200x1600x24 >/tmp/xvfb-run.log 2>&1 &
export DISPLAY=:99
sleep 2
# The suite intermittently DIES mid-run with no output (gdb-attach
# watchdog found the pid already gone -- a silent crash, not a hang).
# Enable core dumps and post-mortem them into the artifact.
ulimit -c unlimited
echo '/tmp/cn1-cores/core.%e.%p' | sudo tee /proc/sys/kernel/core_pattern >/dev/null
mkdir -p /tmp/cn1-cores
rc=0
mvn -B clean package -pl JavaAPI -am -DskipTests
mvn -B test -pl tests -am \
'-Dtest=CleanTargetLinuxIntegrationTest#capturesHelloSuiteOverWebSocketLinux' \
'-Dsurefire.failIfNoSpecifiedTests=false'
'-Dsurefire.failIfNoSpecifiedTests=false' || rc=$?
for core in /tmp/cn1-cores/core.*; do
[ -f "$core" ] || continue
elf="$(/usr/bin/find /tmp -maxdepth 4 -name LinuxHelloMain -type f 2>/dev/null | head -1)"
mkdir -p "$(dirname "$CN1_APP_LOG_TEE")"
{
echo "=== post-mortem of $core (elf=$elf) ==="
gdb "$elf" "$core" -batch -ex 'set pagination off' \
-ex 'thread apply all bt' \
-ex 'thread 1' -ex 'bt full' \
-ex 'frame 0' -ex 'info args' \
-ex 'frame 1' -ex 'info locals' -ex 'info args' \
-ex 'p gcMarkWorklistTop' -ex 'p currentGcMarkValue' \
2>&1
} >> "$(dirname "$CN1_APP_LOG_TEE")/crash-stacks.txt" || true
done
# Resolve the CN1 FAULT/ABORT backtrace addresses (LinuxHelloMain[0x...]) that the
# SA_ONSTACK handler dumped to app-output.log into function names -- the faulting
# frames (e.g. a stack overflow's recursion / the caller that ran CN1 on a small
# native stack). The suite binary is not stripped, so addr2line resolves them.
elf="$(/usr/bin/find /tmp -maxdepth 4 -name LinuxHelloMain -type f 2>/dev/null | head -1)"
if [ -n "$elf" ] && [ -f "$CN1_APP_LOG_TEE" ]; then
{
echo "=== addr2line of CN1 backtrace addresses (from app log) ==="
grep -oE "LinuxHelloMain\[0x[0-9a-f]+\]" "$CN1_APP_LOG_TEE" | grep -oE "0x[0-9a-f]+" | while read a; do
echo "$a -> $(addr2line -f -C -e "$elf" "$a" 2>/dev/null | tr '\n' ' ')"
done
} >> "$(dirname "$CN1_APP_LOG_TEE")/crash-stacks.txt" 2>&1 || true
fi
exit $rc

- name: Upload screenshot artifact (${{ matrix.arch }})
if: always()
Expand Down Expand Up @@ -268,6 +308,7 @@ jobs:
docker run --rm \
-v "$GITHUB_WORKSPACE":/cn1 -w /cn1 \
-e CN1_SHOT_OUTPUT_DIR=/cn1/artifacts/linux-port/raw-musl \
-e CN1_APP_LOG_TEE=/cn1/artifacts/linux-port/raw-musl/app-output.log \
-e LIBGL_ALWAYS_SOFTWARE=1 \
docker.io/library/alpine:3.20 sh -ec '
sed -i "s|^#\(.*/community\)|\1|" /etc/apk/repositories
Expand Down
69 changes: 69 additions & 0 deletions .github/workflows/parparvm-tests-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,22 @@ jobs:
mvn -B clean package -pl JavaAPI -am -DskipTests
mvn -B test -pl tests -am '-Dtest=CleanTargetIntegrationTest#capturesHelloSuiteOverWebSocket' '-Dsurefire.failIfNoSpecifiedTests=false'

# Preserve the native cn1WindowsLog output so the offscreen-capture path is
# confirmable on the green x64 gate too (compare against the arm64 leg).
- name: Collect native windows log (x64)
if: always()
shell: pwsh
run: |
New-Item -ItemType Directory -Force -Path artifacts/windows-port/raw | Out-Null
$log = Join-Path $env:TEMP 'cn1windows.log'
if (Test-Path $log) {
Copy-Item $log artifacts/windows-port/raw/cn1windows-native.log -Force
Write-Host "collected native log ($((Get-Item $log).Length) bytes)"
} else {
"no native cn1windows.log found at $log" | Out-File artifacts/windows-port/raw/cn1windows-native.log
Write-Host "no native log at $log"
}

- name: Upload screenshot artifact (x64)
if: always()
uses: actions/upload-artifact@v4
Expand Down Expand Up @@ -474,6 +490,24 @@ jobs:
mvn -B clean package -pl JavaAPI -am -DskipTests
mvn -B test -pl tests -am '-Dtest=CleanTargetIntegrationTest#capturesHelloSuiteOverWebSocket' '-Dsurefire.failIfNoSpecifiedTests=false'

# Preserve the native cn1WindowsLog output (%TEMP%\cn1windows.log) so an
# offscreen-target / capture failure is diagnosable from the artifact, and
# so the raw dir is never empty (the arm64 artifact would otherwise not be
# produced when the suite stalls before writing any PNG).
- name: Collect native windows log (arm64)
if: always()
shell: pwsh
run: |
New-Item -ItemType Directory -Force -Path artifacts/windows-port/raw | Out-Null
$log = Join-Path $env:TEMP 'cn1windows.log'
if (Test-Path $log) {
Copy-Item $log artifacts/windows-port/raw/cn1windows-native.log -Force
Write-Host "collected native log ($((Get-Item $log).Length) bytes)"
} else {
"no native cn1windows.log found at $log" | Out-File artifacts/windows-port/raw/cn1windows-native.log
Write-Host "no native log at $log"
}

- name: Upload screenshot artifact (arm64)
if: always()
uses: actions/upload-artifact@v4
Expand Down Expand Up @@ -538,11 +572,29 @@ jobs:
source scripts/lib/cn1ss.sh
cn1ss_setup "$JAVA_HOME/bin/java" "$(pwd)/scripts/common/java"
REF_DIR="$(pwd)/scripts/windows/screenshots"
# Gate the Windows port like the Linux one: fail on any mismatch/error or
# a new screenshot with no committed golden (missing_expected). Without
# this the comparison only posted a PR comment and stale goldens slipped
# through green CI (the picker case-conversion refresh was missed here).
export CN1SS_FAIL_ON_MISMATCH=1
export CN1SS_ALLOWED_MISSING=0
set +e
cn1ss_process_and_report \
"Native Windows port (x64)" \
"$ART/compare.json" "$ART/summary.txt" "$ART/comment.md" \
"$REF_DIR" "$ART/previews" "$ART" \
"${entries[@]}"
gate_rc=$?
set -e
fail=0
if [ "$gate_rc" -ne 0 ]; then
echo "[windows-native-port x64] FATAL: screenshot gate failed (rc=$gate_rc)"; fail=1
fi
if [ -f "$ART/summary.txt" ] && grep -q "^missing_expected|" "$ART/summary.txt"; then
me="$(grep -c "^missing_expected|" "$ART/summary.txt" || echo 0)"
echo "[windows-native-port x64] FATAL: $me screenshot(s) streamed with no stored golden (missing_expected) -- add them to $REF_DIR."; fail=1
fi
if [ "$fail" -ne 0 ]; then echo "Windows x64 screenshot gate failed."; exit 1; fi

windows-port-screenshot-comment-arm64:
name: screenshot-comment (arm64)
Expand Down Expand Up @@ -594,8 +646,25 @@ jobs:
source scripts/lib/cn1ss.sh
cn1ss_setup "$JAVA_HOME/bin/java" "$(pwd)/scripts/common/java"
REF_DIR="$(pwd)/scripts/windows/screenshots"
# Same gate as the x64 leg. The job itself is continue-on-error
# (experimental arm64 runner), so this reports red without blocking
# the PR -- but the mismatch is no longer silent.
export CN1SS_FAIL_ON_MISMATCH=1
export CN1SS_ALLOWED_MISSING=0
set +e
cn1ss_process_and_report \
"Native Windows port (arm64)" \
"$ART/compare.json" "$ART/summary.txt" "$ART/comment.md" \
"$REF_DIR" "$ART/previews" "$ART" \
"${entries[@]}"
gate_rc=$?
set -e
fail=0
if [ "$gate_rc" -ne 0 ]; then
echo "[windows-native-port arm64] FATAL: screenshot gate failed (rc=$gate_rc)"; fail=1
fi
if [ -f "$ART/summary.txt" ] && grep -q "^missing_expected|" "$ART/summary.txt"; then
me="$(grep -c "^missing_expected|" "$ART/summary.txt" || echo 0)"
echo "[windows-native-port arm64] FATAL: $me screenshot(s) streamed with no stored golden (missing_expected) -- add them to $REF_DIR."; fail=1
fi
if [ "$fail" -ne 0 ]; then echo "Windows arm64 screenshot gate failed."; exit 1; fi
20 changes: 20 additions & 0 deletions .github/workflows/purchase-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -272,17 +272,37 @@ jobs:
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
# The emulator boot on GitHub-hosted runners intermittently dies before the
# device ever appears ("device 'emulator-5554' not found" -> the runner
# action's own boot timeout). One explicit retry recovers the infra lottery;
# a genuine test failure fails both attempts. emulator-boot-timeout is
# raised over the action's default for the slow-runner case where the boot
# is merely late rather than dead.
- name: Run Android purchase instrumentation test (targeted)
id: purchase-emu-attempt1
continue-on-error: true
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 36
arch: x86_64
target: google_apis
disk-size: 2048M
emulator-boot-timeout: 900
# android-emulator-runner runs each script line in its own shell, so
# cd + gradlew must be a single `&&` line. Runs ONLY the purchase test
# (it self-asserts by scraping logcat for CN1SS:IAP:SUBMITTED).
script: cd "${{ steps.build-android-app.outputs.gradle_project_dir }}" && ./gradlew --no-daemon --stacktrace connectedDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.codenameone.examples.purchasetest.PurchaseBillingInstrumentationTest
- name: Run Android purchase instrumentation test (retry after emulator-boot failure)
if: steps.purchase-emu-attempt1.outcome == 'failure'
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 36
arch: x86_64
target: google_apis
disk-size: 2048M
emulator-boot-timeout: 900
force-avd-creation: true
script: cd "${{ steps.build-android-app.outputs.gradle_project_dir }}" && ./gradlew --no-daemon --stacktrace connectedDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.codenameone.examples.purchasetest.PurchaseBillingInstrumentationTest
- name: Upload Android purchase test report
if: always()
uses: actions/upload-artifact@v7
Expand Down
18 changes: 18 additions & 0 deletions .github/workflows/windows-cross-build-run.yml
Original file line number Diff line number Diff line change
Expand Up @@ -312,8 +312,26 @@ jobs:
source scripts/lib/cn1ss.sh
cn1ss_setup "$JAVA_HOME/bin/java" "$(pwd)/scripts/common/java"
REF_DIR="$(pwd)/scripts/windows/screenshots"
# Gate like the Linux port: fail on any mismatch/error or a new
# screenshot with no committed golden. Previously this job only
# posted the comparison as a PR comment, so stale goldens sailed
# through green CI.
export CN1SS_FAIL_ON_MISMATCH=1
export CN1SS_ALLOWED_MISSING=0
set +e
cn1ss_process_and_report \
"Native Windows port (cross-compiled)" \
"$ART/compare.json" "$ART/summary.txt" "$ART/comment.md" \
"$REF_DIR" "$ART/previews" "$ART" \
"${entries[@]}"
gate_rc=$?
set -e
fail=0
if [ "$gate_rc" -ne 0 ]; then
echo "[windows-cross] FATAL: screenshot gate failed (rc=$gate_rc)"; fail=1
fi
if [ -f "$ART/summary.txt" ] && grep -q "^missing_expected|" "$ART/summary.txt"; then
me="$(grep -c "^missing_expected|" "$ART/summary.txt" || echo 0)"
echo "[windows-cross] FATAL: $me screenshot(s) streamed with no stored golden (missing_expected) -- add them to $REF_DIR."; fail=1
fi
if [ "$fail" -ne 0 ]; then echo "Windows cross screenshot gate failed."; exit 1; fi
36 changes: 36 additions & 0 deletions CodenameOne/src/com/codename1/annotations/Fused.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.codename1.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/// Marks a class whose constructor-created primitive-array fields are fully
/// ENCAPSULATED, letting ParparVM allocate each instance TOGETHER with those
/// arrays as a single heap block ("fused object"): one allocation instead of
/// several, one object for the garbage collector instead of several, and the
/// arrays share the owner's cache lines. A fused array keeps a completely
/// ordinary header -- all reading code, `System.arraycopy`, iteration and
/// bounds checks work unchanged -- but it has no independent GC identity: it
/// is never separately tracked, marked for reclamation, or swept; it simply
/// lives and dies with its owner.
///
/// The translator fuses a constructor-assigned field when the constructor
/// contains an unconditional `this.f = new T[n]` where `T` is a primitive type
/// and `n` is a constructor parameter or constant (bounds-check guards that
/// throw are fine before it). Constructors keep chaining normally, and every
/// other instantiation path -- reflection, deserialization, oversized arrays
/// that do not fit a fused block -- transparently falls back to ordinary
/// separate allocations with identical semantics.
///
/// THE CONTRACT: the marked class must never let a fused array reference
/// escape into another object's field, an array element, or a static that can
/// outlive the instance. Holding it in locals, passing it as a call argument,
/// or copying its contents out is always safe (the VM keeps the whole block
/// alive through any reference into it held on a thread stack). Typical
/// candidates: string/buffer classes owning their `char[]`, image types owning
/// their pixel `int[]`/`byte[]` data.
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.TYPE)
public @interface Fused {
}
41 changes: 41 additions & 0 deletions Ports/LinuxPort/nativeSources/cn1_linux_crash_protection.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,34 @@ static void cn1_cp_write_dec(int fd, long v) {
}

static void cn1_cp_signal_handler(int sig, siginfo_t *info, void *ctx) {
/* Always dump the faulting thread's backtrace to stderr (fd 2 -> the app-output tee),
* not just to the BuildCloud pending file. This is how a STACK-OVERFLOW crash becomes
* legible: with the per-thread alt signal stack this handler now runs even on overflow,
* and the repeating ADDR/off= lines below are the recursion. Addresses only (async-
* signal-safe writes; no -rdynamic, so no codegen perturbation). off= is the address
* minus the load base = the binary's static address (matches addr2line / gdb symbols). */
#if CN1_CP_HAVE_BACKTRACE
{
void *bt[96];
int bn = backtrace(bt, 96);
CN1_CP_W_STR(2, "\n===CN1CRASH sig=");
cn1_cp_write_dec(2, (long)sig);
CN1_CP_W_STR(2, " frames=");
cn1_cp_write_dec(2, (long)bn);
CN1_CP_W_STR(2, " base=");
cn1_cp_write_hex(2, cn1_cp_load_base);
if (info != NULL) { CN1_CP_W_STR(2, " fault="); cn1_cp_write_hex(2, (uintptr_t)info->si_addr); }
CN1_CP_W_STR(2, "===\n");
for (int i = 0; i < bn; i++) {
CN1_CP_W_STR(2, "CN1BT off=");
cn1_cp_write_hex(2, (uintptr_t)bt[i] - cn1_cp_load_base);
CN1_CP_W_STR(2, " abs=");
cn1_cp_write_hex(2, (uintptr_t)bt[i]);
CN1_CP_W_STR(2, "\n");
}
CN1_CP_W_STR(2, "===CN1CRASH END===\n");
}
#endif
if (cn1_cp_pending_path_set) {
int fd = open(cn1_cp_pending_path,
O_WRONLY | O_CREAT | O_TRUNC, 0600);
Expand Down Expand Up @@ -285,6 +313,19 @@ void cn1_crash_protection_install(void) {
cn1_cp_resolve_pending_path();
cn1_cp_log_install();
cn1_cp_install_signal_handlers();
/* Alternate signal stack for THIS (main) thread, so the SA_ONSTACK handler runs even
* on a stack-overflow SIGSEGV when the main stack is exhausted. Per-thread; the CN1
* worker/EDT/GC threads register their own in threadRunner/gcMarkWorkerMain. Without
* it a stack overflow dies silently instead of dumping the recursion backtrace. */
{
stack_t ss;
ss.ss_sp = malloc(512 * 1024);
if (ss.ss_sp != NULL) {
ss.ss_size = 512 * 1024;
ss.ss_flags = 0;
sigaltstack(&ss, NULL);
}
}
}

/* ----------------------------------------------------------------------
Expand Down
9 changes: 9 additions & 0 deletions Ports/LinuxPort/nativeSources/cn1_linux_socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@
extern JAVA_OBJECT newStringFromCString(CODENAME_ONE_THREAD_STATE, const char* str);
extern const char* stringToUTF8(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT str);

/* Sink that forces a socket buffer object to stay live across a parked blocking read
* so the conservative GC cannot sweep it mid-I/O (see socketRead). */
static volatile void* cn1SocketReadKeepAlive;

typedef struct {
int fd;
int lastError;
Expand Down Expand Up @@ -111,6 +115,11 @@ JAVA_INT com_codename1_impl_linux_LinuxNative_socketRead___long_byte_1ARRAY_int_
CN1_YIELD_THREAD;
n = read(s->fd, data + offset, (size_t) length);
CN1_RESUME_THREAD;
/* Keep the buffer array object reachable across the parked read: only `data` (an
* interior pointer) is used, so the optimizer may drop `buffer` and the concurrent GC
* -- scanning this parked thread -- can sweep it mid-read (a use-after-free; see the
* Windows port where this manifested on the cn1ss WebSocket reader). Force liveness. */
cn1SocketReadKeepAlive = (volatile void*) buffer;
if (n <= 0) {
s->lastError = n < 0 ? errno : 0;
if (n == 0) {
Expand Down
Loading
Loading