5030 Commits
Author SHA1 Message Date
velzieandClaude Opus 5.5 9004980758 test: windows/kde, a ps poll that fails or times out while waiting for Konsole counts as not yet
The wait for Konsole and its shell polls ps, each with a 30 s timeout, and
any failed poll ended the whole wait as a failure. On a busy single-thread page one
ps took over 30 s with Konsole and its shell already up, and the test failed
about 96 s into a 300 s wait. Now such a poll is not yet, and the number of them
goes into the result's times.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-13 13:52:08 -05:00
velzieandClaude Opus 5.5 b314f4636b wine: pin the call-out records array and closing a call-out on a jump out, the split lock's regenerated ABI header, the unhandled exception message and desktop icon selection
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-13 07:50:37 -05:00
velzieandClaude Opus 5.5 8103e93119 page: the rest bundle downloaded ahead in windows of frames not held, its progress counted by frame
The background download was one request from the first frame not held to
the bundle's end. It added that whole span to its total again on every
retry and after every pause (a hidden tab), so the page showed hundreds of
MB. It also fetched again any frame that a read, or an earlier visit, had
already brought in after that point.

Now each request is a window of up to 4 MiB over a run of frames that are
neither held nor in flight. What is held is checked again before every
window. A frame cut in the middle is taken up from its next byte. A read's
frame the download has not reached yet still goes out at once in its own
request. The total is the compressed bytes of the frames this visit did not
hold when the download began. Done is the part of them held by now, however
it came. A frame whose store fails (the origin's quota) is held packed for
the visit instead of being fetched again.

Test: page/lazy-rest-ahead logs every byte the server sends and checks it
against the bundle: a pause, a cut window, a read near the end at 10%, a
cut first visit then a second, a cache that refuses every frame.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-13 07:50:37 -05:00
velzieandClaude Opus 5.5 da81f5cea9 test: fibers from native code (wow64/nfiber)
A gexcc-win program checks that CreateFiber and CreateFiberEx refuse a
native start routine with ERROR_NOT_SUPPORTED and that SwitchToFiber
called from native code ends the process with a message. fibers.c also
runs as an x86-64 program, so guest fibers are checked on both sides.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-13 07:50:37 -05:00
velzieandClaude Opus 5.5 fd0424c3e8 cgen, tier-1: a split lock writes each of its two words by compare-exchange
A locked access across two 8-byte words ran under the global split lock
and stored its value with a plain store. The lock keeps such accesses
atomic against each other, but a store of the value's bytes undid any
aligned atomic another thread made in between to a field overlapping
them. That field may be native code's own, such as kernel32's
InterlockedIncrement on the counter beside.

Both copies now commit through one compare-exchange per word: cgen's
gex_locked_misaligned in the header, and tier-1's emit_misaligned_atomic.
- The first word is written when it is unchanged since the read; if it
  changed, the access starts again.
- The second word retries with whatever the bytes around the value now
  hold.
- If the value's own bytes in the second word changed, the access puts
  the first word's bytes back while they still hold what it wrote, and
  starts again.

Every split access therefore reads and writes the value atomically
against aligned atomics on either word as well.

wow64/splitlock gains a 32-bit "overlap" case.
- One thread makes 1000000 locked increments, in its own code, of a
  counter at 6 mod 8.
- The other thread calls InterlockedIncrement, the whole time, on the
  aligned counter at 8, which overlaps the first counter's upper half.
- The case passes only when both counts are exact.
- Natively, the old code lost 20310 of the other thread's 327824 rounds.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-13 07:50:37 -05:00
velzieandClaude Opus 5.5 ee4c2f52ae test: icallbench takes a built convdll.dll (ICALL_BENCH_DLL), for a bench host without gexcc-win
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-13 07:50:37 -05:00
velzieandClaude Opus 5.5 31bd22c94c test: libs/native-libs, every AAPCS64 shape into a native library
aconv.c, a library of every argument and result shape, built as an LP64
wasm library (gen.py's adapters for its exports, the GexA64Icall pass's
entry thunks for the pointers it hands out) and as the arm64 library; an
arm64 program checks each through both paths, and a callback of its own,
against the same functions compiled in: translated and replaced.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-13 07:50:36 -05:00
velzieandClaude Opus 5.5 1ca2dd9db8 native-libs: a float result in s0 as a float, not a double's bits
An export returning float put the result's double into v0: an aarch64
caller reading s0 got the double's low word (0 for 4.375).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-13 07:50:36 -05:00
velzieandClaude Opus 5.5 ce9dfc6dce test: wine64-page/icallbench, guest-to-native call cost (timed)
Guest x86-64 code calling a native DLL's functions through their table
indices (the entry path) and an export, with guest-to-guest and
native-to-native references, natively and on the page: each kind's ns
per call in the result's times. A timed test, for bench.sh.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-13 07:50:36 -05:00
velzieandClaude Opus 5.5 bdcf027ad0 test: fibers switched inside native functions' guest callbacks (fibcb)
wine64/guestnative and wine64-page/guestnative run fixtures/wine64/fibcb.c
beside convdll: a callback that switches to another fiber and back, and
callbacks nested across two fibers, 2000 times each; then the two calls
returning in the other order (not last in, first out), which may end
the process but must not hang (nt's `code: null`: any exit).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-13 07:50:36 -05:00
velzieandClaude Opus 5.5 db8dafc317 native, browser: a jump out of a callback to the guest frame below closes its call-out
A guest call from native Wine that names no argument bytes counted as
left only with the stack more than NATIVE_UNWOUND (512 bytes) above its
frame, and gexrt64 asked gex to leave it (NATIVE_LEFT) only past the
same margin. A jump out of the callback to the guest frame that called
the native function lands closer than that when the native frames
between are small, so each such jump held one more call-out open: the
page's host stack ran out within 3000 jumps, and natively the call-outs
nested hundreds deep.

A call-out whose stack the TEB names (callout_stack_top) is now left by
any stack pointer above its frame on that stack, on both hosts, and
gexrt64 asks at any such entry (Wine pin). The return to the pad still
matches within NATIVE_UNWOUND. cbthrow passes on the page as well;
100000 jumps natively and on the page keep at most a few call-outs open.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-13 07:50:36 -05:00
velzieandClaude Opus 5.5 3b1c63d4ac native, browser: a call-out is unwound past only on its own stack
A call-out's caller counted as unwound past when the guest's stack
pointer was above its frame. A fiber has a stack of its own: while a
callback's call-out was open and another fiber ran on a stack above it,
a safepoint (or gexrt's leave check, or a change of mode on the page)
abandoned the call-out, and the callback's return later reached native
Wine's return pad with no call-out catching it ("gex: BUG: a guest
return reached native Wine's return pad").

Each call-out now records the top of the stack it was made on, its
thread's TEB StackBase then (a fiber switch changes it), and only a
stack pointer between its frame and that top says the caller has been
left: x86::callout_stack_top, the native host's Callout::left, and on
the page gex_callout_stack_top, #left and gex_callout_guard's new top.
A call-out whose TEB names no stack holding its frame keeps the old
rule.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-13 07:50:36 -05:00
velzieandClaude Opus 5.5 1352381fc7 wine: pin gexrt64's call-out records in a per-thread array; cbthrow passes natively
64-bit Wine's gexrt kept a call-out's record on the stack just above the
callee's frame. Guest code jumping out of a callback to a frame less than
NATIVE_UNWOUND above it reused that stack, and the next entry read the
record from it: two such jumps in a row hung the thread. The records are
now in an array the Unix side allocates with each TEB, so wine64's
guestnative cbthrow (4000 jumps out, one and two native calls deep) passes
natively. On the page it stays a known failure, now a host stack overflow:
each such jump leaves its call-out running, one more host level per jump,
and a Worker's stack holds fewer than 4000.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-13 07:50:36 -05:00
velzieandClaude Opus 5.5 b117b2317c test: guest code calling native functions, natively and on the page
wine64/guestnative (and wine64-page/guestnative on the native PE core):
convdll.c, a native DLL built with gexcc-win, called from MinGW programs
through the pointers it hands out (its entry path) and its exports:
- convmatrix: every Win64 shape against the same functions compiled as x86;
- lateload: the DLL loaded while a thread spins with no system call, called
  from that thread, unloaded, loaded and called again;
- cbthrow: a guest callback jumping out over the native frames, many times
  (a known failure today: gexrt's call-out records on the stack);
- comvt: Wine's own native functions through COM and C++ vtables and
  exports, also as i386 (wow64/comvt).
winerun's nt() takes `known`, for a run whose failure is a known one.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-13 07:50:36 -05:00
velzieandClaude Opus 5.5 94c2718963 test: core/fs-sync writes what is to stay in the cache from a shell that stays
A process's exit writes a generation of the kept root when anything is
waiting (persist::exited, core/fs-persist-exit), so a dd that ended had
already sent its blocks to the store: "stays in the cache" saw them there,
and sync, syncfs and sys.sync() found nothing left to write. The writes
the cache checks look at (the first one, the ones before sync, syncfs and
sys.sync(), and phase 2's write-back age) now come from bash's own printf
in a shell that runs for the whole phase. fsync, fdatasync, the 4 MiB
write, the failing store and the full store keep their own processes.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-12 21:12:05 -05:00
velzieandClaude Opus 5.5 554b208f6e test: wine64/beyond16 gives its run the other wine64 tests' 300 s
The run is also the prefix's first start (wineboot --init, its services,
their drivers' units). On one core with no units built that alone takes
89 s, so a loaded gate host ran past the 120 s the test allowed. The
reservation itself is refused at once.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-12 19:17:51 -05:00
velzieandClaude Opus 5.5 ec4ed848f3 kernel: CPUID and cpuinfo advertise SSE4.1, SSE4.2 and PCLMULQDQ
The lifter implements all of them now and matches a real CPU on
x86-programs' sse4, so gex claims x86-64-v2 and programs' IFUNCs and
feature checks may pick those code paths. glibc_math.c's note said the
C rounding variants were chosen; the provider binds the resolvers, so
it replaces whichever variant would be chosen.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-12 10:59:11 -05:00
velzieandClaude Opus 5.5 3329b69bf7 lift-x86: the rest of SSE4.1 and SSE4.2, and PCLMULQDQ
phminposuw, dpps, dppd, mpsadbw, crc32 (all widths), the four
pcmpXstrX with every immediate (formats, aggregations, polarities,
index and mask forms, the flags) and pclmulqdq were SIGILL. They are
lifted now, in sse/sse4.rs. dpps and dppd sum in the hardware's order
and keep the NaN an x86 add keeps (the first operand's, quieted),
spelled out so the function tier's C gives the same NaN. pcmpestrX
take their lengths from RAX and RDX under REX.W, EAX and EDX
otherwise.

test/fixtures/x86-programs/sse4.c runs SSSE3, SSE4.1, SSE4.2 and
PCLMULQDQ over pseudo-random inputs and every immediate, and compares
a hash per group with the one a real CPU gave, so the native and page
legs check it with no dependency on the host's CPU (programs.mjs's
SELF). The native legs take GEX_TEST_ONLY as the page legs do.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-12 10:59:11 -05:00
velzieandClaude Opus 5.5 faf9222381 wine: pin the menu grab and keys, the topmost taskbar, dwrite's font set match, winebuild's signature index, the toolbar bitmap fix and native fiber refusal
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-12 10:00:59 -05:00
velzieandClaude Opus 5.5 4538a735f6 wine: a builtin's re-export of a DLL it only delay-imports loads that DLL with it
A `-import` export of a DLL the module only delay-imports (imagehlp's
SymSetOptions, dbghelp's) was bound to gexp__missing: gex binds a DLL's
exports when its image maps, and the owner's module, marked delayed, was
not installed by then. Nothing would load it later either, since the
export's callers never go through the module's delay thunks; a program's
crash handler calling it stopped the process ("an export of a replaced
library that its provider does not implement"). pelink now has such an
owner load with the module, as for a delay import it binds directly.

Test: wow64/reexport (64-bit and 32-bit, natively).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-12 10:00:26 -05:00
velzieandClaude Opus 5.5 fa7133c5ca test: the shell desktop's taskbar stays over a normal window and goes under a full-screen foreground one
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-12 10:00:26 -05:00
velzieandClaude Opus 5.5 58496046c4 persist: a process's exit commits a generation when anything is waiting
When a process ends having left the tree changed or a block dirty since the
last generation, the kept root writes one before its parent hears of the
exit. An installer's files were kept only after the write-back's age or a
sync; a page reloaded or closed just after the installer ended lost them.
As on Windows, a program's files are on disk once it has exited.

Tests: persist's an_exit_keeps_what_was_written (ignored set), and
core/fs-persist-exit: an installer-like process writes a large file and
small ones and exits, the page reloads at once with its own flush disabled
and no tick due, and the next load has every byte (it fails without this).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-12 10:00:26 -05:00
velzieandClaude Opus 5.5 9ca52c9821 browser: the browser repeats a held key, the client does not (repeat rate 0)
The browser compositor tells each client's keyboard repeat_info rate 0 and
passes each of the browser's own repeat keydowns on as a press. A client's
repeat timer ran from the press it saw, so when the page's main thread was
busy and handed the release on late, the client repeated a key the user
had already let go of (a command typed into cmd just after a reload came
out garbled). gexc's compositor and the X server's hostwl keep 25/600.

Tests: windows (rt-wl is told rate 0; a key held through a 900 ms
main-thread stall is one press; a held key gives one press per browser
repeat), x11-input (the same through Xwayland, the release after the
repeats), kde (typed into Konsole: a command runs, the stall gives one key,
a held key repeats).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-12 10:00:26 -05:00
velzieandClaude Opus 5.5 acdd9419b7 test: Escape closes the shell desktop's Start menu and desktop menu while a program had the keyboard
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-12 10:00:26 -05:00
velzieandClaude Opus 5.5 2658162c34 wayland: a client's pointer grab for its menu and move loops (window placement version 4)
gex_window_placement_v1.grab and release_grab: while a placed surface's
client holds a grab, every pointer event goes to that surface wherever
the pointer is, other clients' surfaces included, as an X server grab
does. A Win32 menu loop under Wine takes one (winewayland's SetCapture,
as winex11's XGrabPointer), so a click on another program's window or on
the desktop reaches the loop and closes the menu; before, the click went
to the other program and the menu stayed open over it.

The grab rides in the surface record's flags (bit 2). The scene
compositor, the element layout and the native compositor route to the
topmost grabbing surface. windows/desktop-layer checks it with a third
rt-wl that grabs: a press over the desktop and over the other window
reaches it, outside it, until it is gone.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-12 10:00:26 -05:00
velzieandClaude Opus 5.5 341d2f3fd9 wayland: GEX_WL_CURSORTRACE reports every set_cursor
A test of the pointer over a client's windows (a hidden pointer over a menu) reads it as [wl-cursor].

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-12 10:00:25 -05:00
velzieandClaude Opus 5.5 1b85659250 page: a read in the rest bundle is said by its file's name, not the bundle's
A program's read of a lazy file in the rest bundle (BUNDLE#OFFSET) was
looked up without its offset, so the page said "Loading rest.bin" for
every such file. The offset is now part of the lookup.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-12 10:00:25 -05:00
velzieandClaude Opus 5.5 a9a0d8d41f page: the rest bundle downloaded ahead under the name a read gives it
The page names its rest bundle to the lazy-file owner as a path on its
origin; a read names it by its whole URL. The owner kept two indexes, and a
read missed the frames held from the download while their store was in
flight. The bundles the page names are made whole first.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-12 10:00:25 -05:00
velzieandClaude Opus 5.5 b96f2faf91 runtime: the page's own lazy-file owner is the system's, not a second one beside it
An ejected page starts the lazy-file owner itself and hands it to the
System it runs the program in. The System made another one anyway and gave
every Worker that one, so the page's owner (whose cache the rest bundle is
downloaded ahead into) read nothing, the reads went to a second cache, and
each frame was fetched again the first time a program read it. A lazyCache
in the host preset is now the owner.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-12 10:00:25 -05:00
velzieandClaude Opus 5.5 409b3953b8 page: the rest bundle downloaded whole in one request as soon as the title files are in
The background download of a rest bundle starts once the pieces (or the streamed archive) are in, not
once the start-up is over, and for a bundle with a hash in a page cache that holds it is one request at
low priority from the first frame not held yet to the end, each frame stored as it completes: a later
visit downloads none of it, and one cut short (or paused while the page is hidden) is taken up from
where it stopped. A read of a frame the download has not reached still goes out at once in its own
ranged request. The page's progress carries it as `rest` ({done, total, complete}) for a page to show.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-12 10:00:25 -05:00
velzieandClaude Opus 5.5 bfe10fa672 wasmdll: a program's or DLL's native module found without case, as Windows finds files
A skeleton's .wasmref names the module as the link wrote it (zed.exe.wasm);
an installer may give the files other case (Zed.exe, Zed.exe.wasm), and
the exact lookup on a case-sensitive filesystem then failed with ENOENT
when the program started. Both hosts take the exact name first, then the
directory's entry that differs from it only in case.

Test: modcase (gexcc-win, natively and on the page), a program and its
module installed as ModCase.exe and ModCase.exe.wasm.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-12 10:00:25 -05:00
velzieandClaude Opus 5.5 bac771a6bc test: fontset, IDWriteFontSet::GetMatchingFonts by family
The system font set's Tahoma asked for bold has the bold face first,
and a set of a font file in memory (CreateInMemoryFontFileLoader,
AddFontFile), as programs that ship their own fonts build, finds it by
its family. bigdata's main takes argc and argv, as the CRT's call has
it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-12 10:00:25 -05:00
velzieandClaude Opus 5.5 864e83143c gex-cache: a large dynamic-offset element segment compiled as table.init
wasmtime compiles a position-independent module's active element segment
(at global.get __table_base) into its startup code, one table store per
slot; a program's million slots took register allocation hours. A
segment of over 16384 slots is now made passive and filled by one
table.init at the head of the start function, in memory, for wasmtime's
compile only: the cache keys and the shipped module are unchanged (V8
fills an active segment lazily, and a table.init eagerly). Measured, the
rewrite compiles a 64k-slot segment in 1.2 s against 4.0 s.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-12 10:00:25 -05:00
velzieandClaude Opus 5.5 782a39bbb2 page: a module without data exports takes its data from the general allocator
A 64-bit module's data went in the PE data window above the images,
which keeps a data export's RVA from its skeleton positive and under
4 GiB. A module that exports no data (a gexcc-win program's) has no
such RVA, and its data may be larger than the window (16 MiB in the
compact space). It now maps below 4 GiB as an i386 module's does, as
natively. bigdata: a program with 24 MiB of data, in the page pe list.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-12 10:00:25 -05:00
velzieandClaude Opus 5.5 ade910ceab native: a program's own module kept when the core installs after it
A gexcc-win program has no core beside it, so its module installs as the
process's core, before ntdll's skeleton maps; the core installing then
replaced it, and image_of no longer found it: GetModuleHandleExW's
FROM_ADDRESS on the program's own data or functions failed (Zed's window
creation). It now stays with the modules of their own.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-12 10:00:25 -05:00
velzieandClaude Opus 5.5 d2f5ea4c98 pelink: functions over the engines' size limit split
wasm-ld's __wasm_apply_data_relocs has one store for each address in a
module's data, and a large program's passes the 7654321-byte limit a
function body has in V8 and wasmparser, so the module fails to load. A
straight-line function of stores over 1 MiB is split into functions of
its statements, appended after the others, which it calls in order.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-12 10:00:24 -05:00
velzieandClaude Opus 5.5 442c91da45 pelink: modules without gexw.sig64
The ICALL pass's signatures are link-time input: winebuild reads them from
the objects, pelink from the .r.o and the defining DLL's side module.
wasm-ld concatenated every object's into the module, and wasm-opt kept
them, though gex never reads them.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-12 10:00:24 -05:00
velzieandClaude Opus 5.5 e7f210ee4a wine/dist.sh: 64-bit build tools
With no archs and no --enable-win64, Wine's configure builds the tools
-m32, and a large program's link runs winebuild out of its 4 GiB. The
tools tree's key includes the flavour, so the change rebuilds it once.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-12 10:00:24 -05:00
velzieandClaude Opus 5.5 dea26b72f7 pelink, gexcc-win: a program's imports no DLL exports bound to stubs, as Wine's loader binds them
--stub-imports (gexcc-win's link of a program): each function the program
imports that no module exports gets a definition in the program's module
that raises EXCEPTION_WINE_STUB with the DLL whose .spec lists it, as
Wine's stub entry points do, and the link lists them as warnings. The
program runs; a call ends it with Wine's unimplemented-function error.
The core and the tree's DLLs stay checked.

The core's gap stubs stay as they are: on wasm64 pelink reads the linked
module's imports with wasm-objdump, which cannot read a memory64 module,
so it found none.

Test: wine64/gexccwin's missimp.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-12 10:00:24 -05:00
velzieandClaude Opus 5.5 30a5f5d7e9 gexcc-win: hypotf, which the CRT exports only as _hypotf (MinGW's libmingwex has it)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-12 10:00:24 -05:00
velzieandClaude Opus 5.5 c69efa8b09 pesym: segment info built in a bytearray, not by concatenating bytes
A program with millions of data segments (a Rust one, each constant its
own) made the rewrite quadratic: Zed's link ran in it for over 40 minutes;
44 s now.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-12 10:00:24 -05:00
velzieandClaude Opus 5.5 cb97a0299b wine: pin an SRW lock's waiter count kept through the split lock
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-12 05:33:45 -05:00
velzieandClaude Opus 5.5 212d8ed323 toolchain: the pass plugins ask for llvm-config-22 first, so another LLVM's llvm-config on PATH is not picked up
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-11 21:13:26 -05:00
velzieandClaude Opus 5.5 d0e964d1ad wine: pin the misaligned interlocked check kept opaque to the compiler
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-11 18:50:54 -05:00
velzieandClaude Opus 5.5 2d48a6d735 test: wow64/tebframes, a handler that never returns leaves no exception frames behind
An exception handler jumps back to main without unwinding, its stack is
written over, and a second exception is raised and handled; then the same
from a fiber and the thread between switches. Fails until an entry into
64-bit Wine drops the exception frames it pushed on its own stack.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-11 18:50:54 -05:00
velzieandClaude Opus 5.5 9b25787d0e test: wow64/splitlock, Windows locks and interlocked calls at misaligned addresses
A critical section, an SRW lock and an init-once at addresses that are not
a multiple of their fields' size, contended by two threads in Wine's native
wasm code, and (32-bit) translated locked increments racing kernel32's
InterlockedIncrement on one counter. 64-bit and 32-bit, natively and on the
page; fails until Wine's interlocked operations take the split path at
misaligned addresses.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_853378b774d645b4ac78b16d9af91a31
2026-11-11 18:50:54 -05:00
velzieandClaude Opus 5.5 fc59c3b479 gexcc-win: MinGW's sys/param.h, sig_atomic_t, SSIZE_MAX and a socklen_t typedef, C11's static_assert; endian.h for code that sees __wasm__
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_e0aa53aa95eb4b86910519b4d14812a5
2026-11-11 18:49:36 -05:00
velzieandClaude Opus 5.5 3d582b5ab8 wine: pin the classic taskbar and desktop, misaligned interlocked operations, and an entry's exception frames
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_e0aa53aa95eb4b86910519b4d14812a5
2026-11-11 18:28:55 -05:00
velzieandClaude Opus 5.5 e903aa95cd wayland: a desktop layer under every other window (window placement version 3)
A window system's own desktop window -- Wine's virtual desktop, which draws
the background and the desktop's icons and takes the clicks on them -- needs
to be shown, and shown under every other window, placed or not: in the
normal layer a window sent to the bottom (place_below 0xffffffff) would go
under it.

gex_window_placement_v1 version 3 adds the layer "desktop" (3). The server
keeps it only for a client that bound version 3; an older client's layer is
clamped as before. Every compositor stacks it lowest: the native screen
(drawn before the windows nobody placed, and hit-tested under the rest), the
scene compositor and the page's element layout. The scene compositor's
keyboard fallback now takes the top of the stacking, not of the raw order.

rt-wl places itself with "place X Y LAYER [bottom]" and says where each press
landed; windows/desktop-layer (scene) and windows/desktop-layer-single (the
element layout) check that the window sent to the bottom stays over the
desktop and that presses reach each, and a native screen test the same.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_e0aa53aa95eb4b86910519b4d14812a5
2026-11-11 18:28:48 -05:00
velzieandClaude Opus 5.5 21b8afdbc8 page: the rest bundle fetched in the background once the start-up is over
The lazy files' owner fetches every frame of the site's rest bundles it does not hold yet, one at a
time at fetch priority low, into the store reads look in (the page's cache for a bundle with a hash,
the kept frames otherwise). A read's own fetch goes first: none of the background's starts while one
is in flight, and a frame both want is one request. Paused while the page is hidden; none on a
save-data or 2G connection; ?restahead=0 turns it off.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_e0aa53aa95eb4b86910519b4d14812a5
2026-11-11 18:28:48 -05:00