Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
145 commits
Select commit Hold shift + click to select a range
d4559eb
fix(runtime): instanceof and inherited getters on function objects
jgoux Oct 30, 2026
817f9ba
wpfacts: a method called on a described parameter's reach is a read, …
Oct 30, 2026
aa68ab0
changelog: number the PR fragment
Oct 30, 2026
3077cc8
link: PERRY_LINK_PAD places pad objects between the compiled objects …
Oct 30, 2026
7ead7bf
changelog: number the PR fragment
Oct 30, 2026
698f3fc
compile env: register PERRY_FACTS_CONSUMED as a diagnostics-only vari…
Oct 30, 2026
330a5fa
changelog: number the PR fragment
Oct 30, 2026
d408a4a
fix(runtime): stack-overflow guard under ulimit -s unlimited
Oct 30, 2026
59f8ebc
changelog: name the fragment for numbering
Oct 30, 2026
19a8e46
changelog: number the PR fragment
Oct 30, 2026
6d545a2
fix(runtime): CreateDataProperty defines from a descriptor record, no…
Oct 30, 2026
eb927c2
test(gap): class fields define from a record on callable and plain re…
Oct 30, 2026
21dd89d
changelog: number the PR fragment
Oct 30, 2026
842490b
runtime: state the PerryLayoutKey.off offset per pointer width (wasm3…
Oct 30, 2026
b3d3507
ci(release-wasi): admit perry_host.discard_pages in the wasip1 import…
Oct 30, 2026
ab685af
changelog: number the PR fragment
Oct 30, 2026
8a6b0b1
linkpad: equalize the RELRO size and the aligned TLS size between the…
Oct 30, 2026
d0abc90
changelog: number the PR fragment
Oct 30, 2026
a2f1398
perry-runtime lib tests: pass in release and perry-dev at default thr…
Oct 30, 2026
f94a123
changelog: number the PR fragment
Oct 30, 2026
44ee7ca
codegen: native IR reader builds inline metadata tuples (noalias scop…
Oct 31, 2026
7c18fa9
changelog: number the PR fragment
Oct 31, 2026
e22a12a
test: a relinked parent class constructor runs on the subclass instan…
Oct 30, 2026
661a80a
wpfacts: a class relinked as another unit's parent runs its construct…
Oct 30, 2026
8cd20c4
changelog: relinked parent constructor this per unit
Oct 30, 2026
c298991
changelog: name the fragment for numbering
Oct 31, 2026
0fe9499
changelog: number the PR fragment
Oct 31, 2026
3c815b1
runtime: constructing AbortSignal through a value or a live super() t…
Oct 31, 2026
c69f356
test: a standalone class constructor stores this fields through its o…
Oct 30, 2026
87baefc
codegen: a standalone class constructor is compiled under its constru…
Oct 30, 2026
eb926c4
changelog: standalone constructor function id
Oct 30, 2026
72d58e2
changelog: number the PR fragment
Oct 30, 2026
c111dfc
cjs_wrap: a CommonJS namespace exports only the keys the module writes
Oct 31, 2026
610c439
changelog: fragment for numbering
Oct 31, 2026
1cf8c83
changelog: number the PR fragment
Oct 31, 2026
a587c7f
wpfacts: code that runs with this in a constructor can read the keys …
Oct 31, 2026
833ad2b
test: a method called from the constructor sees the unassigned key; c…
Oct 31, 2026
a55a76a
wpfacts, codegen: a key the constructor stores is present only once s…
Oct 31, 2026
abaa1b2
changelog: number the PR fragment
Oct 31, 2026
8587d82
fix(modules): forward node:trace_events exports through its ESM names…
Oct 31, 2026
19a6de5
changelog: number the PR fragment
Oct 31, 2026
018e749
wpfacts: a literal handed to a closed function is described with its …
Oct 31, 2026
17a931a
changelog: UEB closed-function literal
Oct 31, 2026
86fc76b
changelog: number the PR fragment
Oct 31, 2026
eb57043
fix(wpfacts): forwarded copies of one literal shape join, so the unit…
Oct 30, 2026
dff40c0
changelog: number the PR fragment
Oct 30, 2026
c790df8
test(wpfacts): forwarded copies of one literal shape reach a fixpoint
Oct 30, 2026
afa9c38
fix(wpfacts): forwarded copies of one literal shape join, so the unit…
Oct 30, 2026
1a563b7
changelog: number the PR fragment
Oct 30, 2026
9f7da2f
wpfacts: a forwarded function copy names the functions their owners d…
Oct 31, 2026
2965448
test(wpfacts): forwarded function copies stay bounded (zod v4 compile…
Oct 31, 2026
261895d
changelog: number the PR fragment
Oct 31, 2026
12060d1
feat(compile): export demand, layer 1 of dead-code elimination
Oct 30, 2026
dfca590
export demand: a re-export the collection-time pruner postponed stays…
Oct 30, 2026
2d9877a
changelog: number the PR fragment
Oct 31, 2026
a2fc8dc
compile env: key PERRY_EXPORT_DEMAND, exclude its report knob
Oct 31, 2026
41d31b7
runtime: make atom_bounds visible to the wasm image checks and the Wi…
Oct 31, 2026
f2e0824
changelog: number the PR fragment
Oct 31, 2026
11850fc
wpfacts: a replayed parameter call belongs to its stand-in run (UEB f…
proggeramlug Oct 31, 2026
2afcb01
codegen: holder facts: a read of a field holding only prefix-stable c…
proggeramlug Oct 31, 2026
86c60fc
wpfacts: a literal birth's chunk functions are in its unit (DGL)
Oct 31, 2026
6204206
wpfacts: explain names the unit that reports a contract
Oct 31, 2026
d98608d
changelog: DGL literal chunks in the birth unit
Oct 31, 2026
42873d2
changelog: number the PR fragment
Oct 31, 2026
44d7b65
hir: Expr::clone without recursion per nesting level; run-once view c…
Oct 31, 2026
8a8c0a4
changelog: number the PR fragment
Oct 31, 2026
c7331f1
fix(worker_threads): reuse canonical messaging constructor exports
TheHypnoo Oct 30, 2026
efabfe1
docs(changelog): number constructor export fragment
TheHypnoo Oct 30, 2026
70a57fe
fix(codegen): namespace-importing yourself populates before the body …
TheHypnoo Oct 31, 2026
935405b
changelog: record the self-namespace import fix
TheHypnoo Oct 31, 2026
7c01c10
feat(wpfacts): summarize the builtin constructor families the model w…
TheHypnoo Oct 31, 2026
25f2232
changelog: record the builtin constructor summaries
TheHypnoo Oct 31, 2026
d413e02
wpfacts: a contract publishes the protocol that touches a parameter
Oct 31, 2026
0e1fde9
release: build every native ext in one cargo invocation
Oct 31, 2026
4901eb1
tests: set namespace_self_import in CompileOptions literals
Oct 31, 2026
5339457
wpfacts: an unknown accessor defines the one key it is installed under
Oct 31, 2026
329df17
changelog: unknown accessor key
Oct 31, 2026
c695a9b
changelog: number the PR fragment
Oct 31, 2026
3789b85
wpfacts: a number key reads only number keys a store into ⊤ wrote on …
Oct 31, 2026
86bfb54
wpfacts: per unit, the builtin prototypes' handover writes only the k…
Oct 31, 2026
9e349e2
wpfacts: an E6 on ⊤ in one unit reaches the other units
Oct 31, 2026
5000049
changelog: IPS5 wpfacts soundness fixes
Oct 31, 2026
7be3724
changelog: number the PR fragment
Oct 31, 2026
0e138c0
release: highlights for the 0.5.x release
Oct 31, 2026
436ae7e
release: highlights use the 2026-10-31 release checks
Oct 31, 2026
3a71b6c
feat(compile): drop modules only unreachable import() sites load (DCE…
proggeramlug Oct 31, 2026
b163c51
changelog: record the CompileOptions test-literal repair
TheHypnoo Oct 31, 2026
b9de6d4
fix(worker_threads): share receiver-owned MessagePort operations
TheHypnoo Oct 31, 2026
9ff1a83
docs(changelog): number MessagePort receiver fix fragment
TheHypnoo Oct 31, 2026
30b4d93
fix(codegen): instanceof consults a computed static Symbol.hasInstance
TheHypnoo Oct 31, 2026
adcb854
changelog: record the instanceof Symbol.hasInstance fix
TheHypnoo Oct 31, 2026
8eb99d6
gc: walk x86-64 Linux stacks by frame kind, without the system unwind…
proggeramlug Oct 31, 2026
2350775
wpfacts: order unit cycles by strong edges; parameter types and names…
Oct 31, 2026
e19ea3b
changelog: number the PR fragment
Oct 31, 2026
93ad812
compile: install the GC diagnostics when their knobs are set while co…
Oct 31, 2026
e0cdf25
changelog: number the PR fragment
Oct 31, 2026
53fb3af
wpfacts: own definite data key shadows the prototype chain (DEC 234)
Nov 1, 2026
047ec69
changelog: number the PR fragment
Nov 1, 2026
b28eca7
wpfacts: drop the marker Removed shares; the Hard share covers them (…
Nov 1, 2026
87f8f08
component-host: run live owners' destructors when disposing a driver …
Nov 1, 2026
2dcc006
changelog: number the PR fragment
Nov 1, 2026
121c6ad
component-host: release host-type handles without the synchronous dro…
Nov 1, 2026
a7a12f4
wpfacts: a call through a receiver field runs where the receiver is h…
Nov 1, 2026
058220e
changelog: wpfacts receiver field calls
Nov 1, 2026
f6b9407
changelog: number the PR fragment
Nov 1, 2026
b3f1990
wpfacts: generator next/return/throw return an iterator result, not t…
Nov 1, 2026
b384cd7
changelog: number the PR fragment
Nov 1, 2026
91ddefa
ci(release): move Apple legs from macos-14 to macos-15
Oct 31, 2026
1dde139
dce: the link drops every function nothing live references (layer 0)
Oct 31, 2026
ffcd118
changelog: number the PR fragment
Oct 31, 2026
f82ca7d
docs: refresh runtime, memory and program facts across languages
Nov 1, 2026
dfb26c4
docs: number PR changeset and polish German wording
Nov 1, 2026
297d589
test-wasi: refresh the transform rust-host lock for zstd 0.14
Nov 1, 2026
4cb838f
component: throw a trap's first retirement destructor exception from …
Nov 1, 2026
f163fcb
changelog: number the PR fragment
Nov 1, 2026
87929cc
wpfacts: RegExp test and @@replace/@@match/@@search call the regexp's…
Nov 1, 2026
b218c77
wpfacts: RegExp @@split and @@matchAll run a stored species constructor
Nov 1, 2026
42f39a8
changelog: fragment for the RegExp exec and species lookups
Nov 1, 2026
910d81d
changelog: number the PR fragment
Nov 1, 2026
25c3248
runtime: bind thisArg in TypedArray callback methods and the construc…
Nov 1, 2026
b638fcf
runtime: rustfmt the thisArg change
Nov 1, 2026
0c9f037
changelog: number the PR fragment
Nov 1, 2026
178a637
fix(tty): preserve terminal output flags in raw input mode
Nov 1, 2026
c265974
changelog: number the raw mode fix fragment
Nov 1, 2026
b788e9c
fix(transform): bound cumulative HIR loop expansion
Nov 1, 2026
3f100ab
changelog: number the loop expansion fix fragment
Nov 1, 2026
44441ce
docs: clarify size limits on kernel specialization
Nov 1, 2026
3b09443
wpfacts: prove array iteration; for-of skips member read and array-ar…
Nov 1, 2026
48ea1d3
wpfacts: unit tests for the array iteration facts; codegen tests for …
Nov 1, 2026
876a940
wpfacts: read the unmodeled-operand reason only for tokens on the arr…
Nov 1, 2026
49a8cb9
wpfacts: TypedArray, Date toJSON and TextDecoder run the conversions …
proggeramlug Nov 1, 2026
9070ac6
fix(runtime): a class identity's [[Prototype]] is read from its shape
Nov 1, 2026
55d30fa
fix(runtime): a callable's inherited read is one OrdinaryGet with the…
Nov 1, 2026
dcbad7a
test(gap): inherited reads and prototype links of callable class inst…
Nov 1, 2026
d383bd8
changelog: fragment for the callable inherited read
Nov 1, 2026
f88e162
changelog: number the PR fragment
Nov 1, 2026
7e7871a
wpfacts: no result through an unrun parameter; an element of ⊤ is not…
Nov 1, 2026
2cffa04
changelog: wpfacts unrun parameter fragment
Nov 1, 2026
b1ac1c7
changelog: number the PR fragment
Nov 1, 2026
45c08aa
wpfacts: the arguments object is not an Array
Nov 1, 2026
e6f33b8
changelog: arguments object fragment
Nov 1, 2026
c4222a7
wpfacts: a bound function made inside a summarized body keeps its bou…
Nov 1, 2026
1c9ddf0
changelog: number the PR fragment
Nov 1, 2026
53ac2fa
Merge commit 'd4559eb70549782b15b8f4e925891edef5dfd077' into HEAD
Nov 1, 2026
ea26904
fix(runtime): instanceof Function follows a function object's reset p…
Nov 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
60 changes: 42 additions & 18 deletions .github/workflows/release-packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -667,7 +667,7 @@ jobs:
fail-fast: false
matrix:
include:
- os: macos-14
- os: macos-15
target: aarch64-apple-darwin
artifact: perry-macos-aarch64
wasi: true
Expand Down Expand Up @@ -898,10 +898,16 @@ jobs:
run: |
${{ runner.os == 'Windows' && 'cargo' || 'mbx' }} build --profile prod --target ${{ matrix.target }} -p perry-runtime -p perry-runtime-static
${{ runner.os == 'Windows' && 'cargo' || 'mbx' }} build --profile prod --target ${{ matrix.target }} -p perry-stdlib -p perry-stdlib-static
# The WebAssembly host archive, co-built with the archives it links
# beside: perry links it for a WebAssembly program and never builds
# it while compiling one.
${{ runner.os == 'Windows' && 'cargo' || 'mbx' }} build --profile prod --target ${{ matrix.target }} -p perry -p perry-runtime-static -p perry-stdlib-static -p perry-wasm-host ${{ matrix.wasi && needs.build-wasi.outputs.enabled == 'true' && '--features perry/target-wasi' || '' }}

- name: Build WebAssembly host archive (Windows)
# The WebAssembly host archive, co-built with the archives it links
# beside: perry links it for a WebAssembly program and never builds
# it while compiling one. On Unix the native ext step below builds this
# same package set (plus every extension) in its one invocation, which
# is the build that ships; doing it here too cost a full second
# compile of perry + runtime + stdlib under a different feature union.
if: runner.os == 'Windows' && matrix.old_glibc_image == '' && matrix.musl_image == ''
run: cargo build --profile prod --target ${{ matrix.target }} -p perry -p perry-runtime-static -p perry-stdlib-static -p perry-wasm-host ${{ matrix.wasi && needs.build-wasi.outputs.enabled == 'true' && '--features perry/target-wasi' || '' }}

- name: Build panic=abort runtime variant (Unix)
# Out-of-tree installs can't rebuild the runtime, so ship the
Expand All @@ -926,24 +932,42 @@ jobs:
# needs the prebuilt `libperry_ext_*.a` sitting next to
# libperry_runtime.a so `perry compile` can link them without a
# workspace checkout (see optimized_libs.rs::resolve_prebuilt_ext_libs).
# #7358: keep the compiler and both shipped wrapper archives in each
# Cargo invocation. Building an ext staticlib alone gives its bundled
# runtime/shared dependencies a different feature union from stdlib;
# the link deduper then cannot remove the whole second copy, and the
# HTTP accept loop reads a different async reactor from the one the JS
# event loop drives.
# #7358: build the compiler, both shipped wrapper archives and every
# extension in ONE Cargo invocation, so they all share one feature
# union. Building an ext staticlib with a different union from stdlib
# leaves its bundled runtime/shared dependencies a second copy the
# link deduper cannot remove, and the HTTP accept loop reads a
# different async reactor from the one the JS event loop drives.
# One invocation per extension (the former loop) gave every extension
# its own union, so each iteration recompiled perry, the runtime and
# stdlib (3+ h of the Intel leg) and the shipped archives came from
# whichever iteration wrote them last.
# #5716: the governance inventory is the explicit shipping set; adding
# a crate requires a recorded retain/migration decision. Best-effort
# per crate: a wrapper that can't build on this host must not fail the
# whole release — packaging below ships whatever was produced.
# whole release — packaging below ships whatever was produced. If the
# combined build fails, the core set must still build on its own, and
# each extension is then retried alone as before.
if: runner.os != 'Windows' && matrix.old_glibc_image == '' && matrix.musl_image == ''
run: |
set -euo pipefail
governed_ext_packages=$(./scripts/release_ext_packages.sh)
ext_args=""
while IFS= read -r name; do
ext_args="$ext_args -p $name"
done <<< "$governed_ext_packages"
core_args="-p perry -p perry-runtime-static -p perry-stdlib-static -p perry-wasm-host ${{ matrix.wasi && needs.build-wasi.outputs.enabled == 'true' && '--features perry/target-wasi' || '' }}"
# shellcheck disable=SC2086 # word splitting is the point
if mbx build --keep-going --profile prod --target ${{ matrix.target }} $core_args $ext_args; then
exit 0
fi
echo "::warning::combined ext build failed; building the core alone, then each extension on its own"
# shellcheck disable=SC2086
mbx build --profile prod --target ${{ matrix.target }} $core_args
while IFS= read -r name; do
echo "::group::build $name"
mbx build --profile prod --target ${{ matrix.target }} \
-p perry -p perry-runtime-static -p perry-stdlib-static -p perry-wasm-host -p "$name" ${{ matrix.wasi && needs.build-wasi.outputs.enabled == 'true' && '--features perry/target-wasi' || '' }} \
# shellcheck disable=SC2086
mbx build --profile prod --target ${{ matrix.target }} $core_args -p "$name" \
|| echo " (skipped $name — failed to build on this host)"
echo "::endgroup::"
done <<< "$governed_ext_packages"
Expand Down Expand Up @@ -1742,7 +1766,7 @@ jobs:
# manifest.json (perry_version + target_triple + sha256+size per file)
#
# Each matrix entry runs on the natural host runner for its toolchain:
# - Apple targets: macos-14 (real Xcode + SDKs)
# - Apple targets: macos-15 (real Xcode + SDKs)
# - Android : ubuntu-24.04 + pre-installed NDK
# - Windows MSVC : windows-latest (clang-cl + lib.exe)
# — so no Linux→Apple sysroot or Linux→Windows VM dance is needed inside
Expand All @@ -1757,19 +1781,19 @@ jobs:
matrix:
include:
# --- Apple, Tier-2 (stable) ---------------------------------------
- os: macos-14
- os: macos-15
target: aarch64-apple-darwin
ui_crate: perry-ui-macos
ui_lib: libperry_ui_macos.a
- os: macos-15
target: x86_64-apple-darwin
ui_crate: perry-ui-macos
ui_lib: libperry_ui_macos.a
- os: macos-14
- os: macos-15
target: aarch64-apple-ios
ui_crate: perry-ui-ios
ui_lib: libperry_ui_ios.a
- os: macos-14
- os: macos-15
target: aarch64-apple-ios-sim
ui_crate: perry-ui-ios
ui_lib: libperry_ui_ios.a
Expand Down
7 changes: 4 additions & 3 deletions .github/workflows/release-wasi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,10 @@ jobs:
run: |
set -euo pipefail
archive="$(python3 scripts/wasi_build_runtime.py wasm32-wasip1 | sed -n 's/^WASI archive: //p' | tail -n 1)"
# The optional networking member ships in the archive; default
# linked modules still omit it unless PERRY_WASM_NET=1 is selected.
python3 scripts/wasi_imports_check.py "$archive" --allow-perry-net
# The optional networking and page-discard members ship in the
# archive; default linked modules still omit them unless
# PERRY_WASM_NET=1 / PERRY_WASM_DISCARD=1 is selected.
python3 scripts/wasi_imports_check.py "$archive" --allow-perry-net --allow-perry-host
python3 scripts/wasi_release.py package --target wasm32-wasip1 --revision "$EXPECTED_SHA" \
--runtime "$archive" --output wasip1-release
- name: Upload the wasip1 runtime bundle
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1632,6 +1632,12 @@ jobs:
# Match the PR lane: Blaze cannot unwind through the naked ABI
# trampoline. Keep the full unit/integration/doc test inventory.
MBX_BLAZE=0 RUST_TEST_THREADS=1 python3 scripts/runtime_test_batches.py
# The batches above are the dev profile. Release builds drop the
# debug-only GC instruments and change inlining, so a unit test
# can pass in dev and fail in release (59 did, unseen for weeks).
# Default thread count on purpose: a test that needs exclusive
# process state must serialize itself (`test_isolation`).
MBX_BLAZE=0 cargo test --locked --release -p perry-runtime --lib
fi
# `cargo test` only builds lib/bin/test targets — NOT the `staticlib`
# crate-type — so libperry_runtime.a / libperry_stdlib.a are never
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions changelog.d/0-wpfacts-arguments-object.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Whole-program facts no longer model a function's `arguments` object as an
Array. It is an ordinary object whose prototype is `Object.prototype`, with
own data `length` and `callee`: a store or `Object.defineProperty` on
`arguments.length` now keeps the stored value, where the facts used to say
it was always a Number. Proven site counts are unchanged on the chess
witness, tssrc, tscwork, richards and fastify_inject.
5 changes: 5 additions & 0 deletions changelog.d/13546-function-receiver-instanceof-getter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
`instanceof` on a function object whose prototype was reset
(`Object.setPrototypeOf(fn, C.prototype)`) now follows that chain: `fn
instanceof C` is true, and `fn instanceof Function` is false unless the new
chain reaches `Function.prototype`. Function objects keep a reset prototype
in the closure side table, which these checks ignored.
1 change: 1 addition & 0 deletions changelog.d/13576-worker-constructor-exports.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix worker messaging constructor exports to share their original thread-realm objects across import forms and captured construction. Keep mutable global replacements separate from core-module exports while preserving explicit CommonJS overrides and named-export synchronization.
9 changes: 9 additions & 0 deletions changelog.d/13578-uea2-method-on-read.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Per-unit facts: a method called on what a described parameter reaches
(`context.factory.createIdentifier(..)`, where the callers' values sit beside
the parameter's marker: a closed function, a run method's parameter) is a
read of the method's key, not an escape of the receiver. The call runs on the
values beside the marker, whose contracts carry it to their units. Before,
the escape made every caller report what it passed, and the census broke the
passed class, its method and the method's result layout. A closed-function
fixture now converges in 2 rounds instead of 4 with no broken layout; the
whole program is unchanged and per unit never proves more than whole.
1 change: 1 addition & 0 deletions changelog.d/13579-wpfacts-forwarded-copies-join.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Per-unit facts reach their fixpoint when several units forward copies of one literal shape that no unit of the module births: the copies join, ascending from the last round, instead of the last forwarder of a round replacing the others. Before, a reader solved between two forwarders never read what the round left and was solved again every round (the Supabase CLI never finished its facts pass).
1 change: 1 addition & 0 deletions changelog.d/13580-usg-unlimited-stack.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The stack-overflow guard now works when the stack limit is unlimited (`ulimit -s unlimited`): runaway recursion throws a catchable `RangeError: Maximum call stack size exceeded` instead of dying with SIGSEGV. The main-thread stack bound is derived from the kernel's own stack mapping, and an unlimited (or address-space-wide) limit uses the kernel's default 8 MiB stack size.
17 changes: 17 additions & 0 deletions changelog.d/13581-lpad2-pad-before-runtime.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
`PERRY_LINK_PAD`, a measurement input for startup A/Bs: whitespace-separated objects placed on the link
line right after the compiled objects and before the runtime archive, on every final link perry runs
(executable, dylib, proven tiny program, WASI component), through one reader, `link::link_pad_args()`.
`PERRY_EXTRA_LINK_ARGS` keeps its place (appended last) and meaning. Unset, the link line is unchanged.

The startup A/B harness's link-pad control (`scripts/a1/linkpad.py`, `scripts/a1/irdiff.sh`) now pads in
front of the runtime. The linker lays input sections out in command-line order, so a pad between the
compiled objects and the runtime archive keeps every runtime byte of `.text`, `.rodata` (including the
merged `.rodata.cst*`/`str1.1` blobs), `.eh_frame` (one filler FDE), `.gcc_except_table`, `.data.rel.ro`
(anchored at the end of the RELRO region), `.data` and `.bss` at the same address in both arms; the pad
that is linked last remains only to equalize section ends and the heap start when the runtime itself
differs. The planner relinks the cached objects until the markers coincide; the proof
(`<out>/<witness>.layout.txt`) compares markers, section ends, segment starts, the image end and the
addresses of every runtime symbol both binaries define. Rows that were left by the previous control (ld.so
`check_match` over runtime `.rodata` names, libc compares over runtime literals) now disappear when the
runtime is unchanged. `perry_*` record sections and `.eh_frame_hdr` stay unpadded; both arms must be built
from a perry that has `PERRY_LINK_PAD`.
15 changes: 15 additions & 0 deletions changelog.d/13582-gcw-walk-without-unwinder.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
x86-64 Linux: the GC root scan no longer walks the stack with the system
unwinder. JS frames step by their frame record (two loads, exact `sp` and
`rbp`); Rust, shim and foreign frames between them step by their unwind row
through the runtime's own direct decoder; the walk ends after `main` or at the
worker base trap. The back-edge poll, `gc()` and the inline allocation slow
paths are naked shims that hand their caller's frame to the collections they
run, so those walks start at the JS frame and never step the collector's own
frames (allocation offers it only on the arena slow path, the poll only
when it collects). `match_records` rejects a pc past a function's last record in one
search. On binary-trees a walk drops from 9.1 frames and ~28.7k instructions
to 1.1 frames and ~8.5k; `_Unwind_Find_FDE` is no longer called by any scan.

A row the walk cannot follow fails closed to `_Unwind_Backtrace`, and when
that also stops before the end of the stack the process now aborts naming the
module, instead of silently scanning a truncated stack.
5 changes: 5 additions & 0 deletions changelog.d/13583-facts-consumed-env-registered.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Register `PERRY_FACTS_CONSUMED` (the codegen-consumed marks of the facts
dump) with the compile environment as a diagnostics-only variable, like
`PERRY_FACTS_DUMP`: it records which sites read a program fact and changes
no emitted code, so it is not a build-cache input. Fixes the environment
audit test on main.
7 changes: 7 additions & 0 deletions changelog.d/13584-ctor-own-fn-id.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
A class's standalone constructor (the body `super(...)` and `new` of a class
value run) is compiled under its constructor's own function id instead of
id 0. Its `this`, definite-init proofs and allocation hotness were read
from whichever function had HIR id 0; now a store `this.k = v` into a
definite birth field of a prefix-stable class is the slot store the inlined
`new C(...)` already emits. A synthesized default constructor gets an id
nothing is keyed by.
11 changes: 11 additions & 0 deletions changelog.d/13585-create-data-property-record.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
`CreateDataProperty` (public class fields, and the other runtime callers of
the operation) defines from a Property Descriptor record instead of building a
four-key JS descriptor object and decoding it back through
`Reflect.defineProperty`. A class field on a callable class instance (a bound
function given the class prototype, as ArkType's `Callable` builds) declines
every shape-owned define and paid both steps: 24k instructions per field,
1.57 G instructions of the Supabase CLI's `--version`. It is now about 10k.
Because nothing is read back through `%Object.prototype%`, an inherited `get`
or `set` there no longer turns a class field into an invalid accessor
descriptor; `test_gap_class_field_define_record` pins that and the field
attributes on callable and plain receivers.
13 changes: 13 additions & 0 deletions changelog.d/13586-wasi-layout-key-assert.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Fix the wasm32 (WASI) runtime build: the compile-time check of the
`PerryLayoutKey.off` offset used the 64-bit value (14) on every target, but
with 32-bit pointers the field sits at byte 10, so `perry-runtime` failed to
compile for wasm32-wasip1/wasip2 and the release build-wasi leg went red. The
offset and the key size are now stated per pointer width (14/16 on LP64,
10/12 on ILP32), matching the descriptor constants beside them, and a codegen
test checks the emitted `%PerryLayoutKey` LLVM type has the same offset and
size under both data layouts. Native targets are unchanged.

The release wasip1 step now admits `perry_host.discard_pages` in its import
check (`--allow-perry-host`, as the test workflow already does): the one
wasip1 archive has carried the opt-in page-discard member since it landed,
so the check rejected the archive it was meant to ship.
1 change: 1 addition & 0 deletions changelog.d/13587-lpad3-relro.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
startup A/B link pad (scripts/a1/linkpad.py): equalizes the RELRO region size (end pad then mid pad in .data.rel.ro) and the aligned TLS size (.tbss end pad), so the RW LOAD start, .tdata, .tbss, .init_array, .fini_array and .data.rel.ro starts coincide when one arm has a larger .got; the layout check compares them; the planner runs up to 30 rounds. Measurement script only, no change to shipping links.
1 change: 1 addition & 0 deletions changelog.d/13588-rlt-release-lib-tests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
perry-runtime's lib tests pass in the release and perry-dev profiles with the default thread count. The GC liveness counters (`copying_minor_cycles` and friends) now count in every lib-test build, not only debug ones, which is what 59 moving-GC tests read; shipping archives are unchanged and a compile-time assert keeps their counters zero-sized. Tests that assert on process-wide state (the event-pump wake flag, the has-active registries, typed-feedback counters, thread-slot claims, the guest host tables) run in their own process through `test_isolation::in_own_process`, and `TestOpsGuard` serializes component host-ops installs, which stops an uncaught throw in one `http::pump` test from aborting the whole test binary. CI's full-tier run now also runs the runtime lib tests in release.
15 changes: 15 additions & 0 deletions changelog.d/13589-rlk-relinked-ctor-this.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Per-unit compiles of a class relinked as another class's parent are correct.
After `Object.setPrototypeOf(B, A)`, `Reflect.setPrototypeOf(B, A)` or
`B.__proto__ = A`, `B`'s `super()` runs `A`'s constructor on a `B` instance.
When the relink sat in a different statement or module than `A` or `B`, two
per-unit facts were stronger than the whole program's: `this` of `A`'s
constructor held only `A` instances, and a unit that merely constructed `B`
vouched that `B` was never relinked, so `super()` called `B`'s declared
parent (wrong output, for example `undefined` instead of the fields `A`'s
constructor sets). Now the unit doing the relink reports the given class, and
that class's unit runs its constructor on any receiver, as it does for a class
an `extends` names. Only a class's own unit says whether it is relinked.

Constructing `AbortSignal` through a value (`const S = AbortSignal; new S()`)
or through the live `super()` of `class X extends AbortSignal` now throws
`TypeError: Illegal constructor`, as in Node; it used to return a signal.
12 changes: 12 additions & 0 deletions changelog.d/13598-native-reader-noalias-scopes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Fix split-module native construction of indexed-owner loop regions. The
native IR reader accepted only the `!{!"NAME"}` metadata operand of
`llvm.read_register`, so a function whose typed-array owner region declares
its noalias scopes (`llvm.experimental.noalias.scope.decl`) failed with
"unsupported metadata operand" and the whole build refused to link
(opencode's `@aws-sdk/core` protocols module). The reader now builds any
inline metadata tuple of strings and tuples through the uniquing MDNode API,
on both the line and typed call paths, and attaches inline `!alias.scope` /
`!noalias` tuples on loads and stores, which it used to drop. Comma and
bracket splitting skips quoted strings, since scope domains embed function
names. A reader test holds the result equal to LLVM's own parse, and the
indexed-owner emitter test builds its live output through the reader.
Loading
Loading