Skip to content

The module sizes a declared domain from its declaration - #3

Open
biecho wants to merge 1 commit into
feat/domreq-loaderfrom
feat/domreq-module
Open

biecho wants to merge 1 commit into
feat/domreq-loaderfrom
feat/domreq-module

Conversation

@biecho

@biecho biecho commented Sep 13, 2026

Copy link
Copy Markdown
Collaborator

The module sizes a declared domain from its declaration

What was wrong

dom_tot_size = code_len + max(code_len, 64 KiB) funds dom_data out of the
CODE size, which holds only while text >= cap table + carved storage + stack. SQLite
satisfies it with 2.2 MB of text against a modest carve. MicroPython does not: 390 KB of
text against about 500 KB of storage, because its GC heap is a 384 KiB global and under
gp-captable a global's storage comes out of dom_data.

Measured over seven test-table sizes of one MicroPython source, every one reporting
"VERDICT: fits" from the build: at 160 and 200 tests dom_data came up 68,864 and 125,296
bytes short. The shortfall comes out of the BOTTOM of dom_data, so the entry glue's carve
ran past the globals blob the monitor had copied to the front, and .capstone_cap_init is
the LAST thing in that blob. The domain then read a destroyed table and jumped through it:
cause 1 on a nonsense address at 160 tests, cause 24 on the table's own address at 200.
Neither looks like a budget problem.

What changes

A declaring image states what dom_data must hold, all four parts together,
and the region is sized from that instead. The slack covers the monitor's seal region and
the two roundings create_domain applies to the split, at most one representability granule
each. An image that declares nothing keeps the old rule byte for byte.

One region, not two

Two regions are the right answer for an image whose single
power-of-two block would pass the buddy allocator's order ceiling, which is SQLite's case
and needs the monitor to take a second base. That is a separate change and DOM_CREATE
already has two spare SBI arguments for it. Sizing one region correctly is what MicroPython
needs and it stops here.

Expect bigger allocations

That is, and that is the requirement becoming visible rather than a
regression. At 60 tests the image runs today on 71,824 bytes of stack against 61,416 bytes
of measured use, ten kilobytes of margin by accident. Declaring an honest stack does not
fit 1 MiB, so most sizes move to 2 MiB. None approaches the order ceiling.

Tested end to end

After after rebuilding the module package and rolling the rootfs. All seven
test-table sizes now boot, including the two that did not, and the loader reports the
declaration the build wrote: "Domain requirement = 742656 (stack 131072)" against a build
line of "declare dom_data >= 742656 (carve 611584 + stack 131072)".

All seven test-table sizes boot, and the two that did not now run their suites: at 160
tests, in one round. The 60 failures are the usual
feature gating at MICROPY_CONFIG_ROM_LEVEL_MINIMUM.

Stacked on #2, which teaches the loader to read the section.

🤖 Generated with Claude Code

https://claude.ai/code/session_01X1F5RGYoharNoVbUvWNVoz

WHAT WAS WRONG. dom_tot_size = code_len + max(code_len, 64 KiB) funds dom_data out of the
CODE size, which holds only while text >= cap table + carved storage + stack. SQLite
satisfies it with 2.2 MB of text against a modest carve. MicroPython does not: 390 KB of
text against about 500 KB of storage, because its GC heap is a 384 KiB global and under
gp-captable a global's storage comes out of dom_data.

Measured over seven test-table sizes of one MicroPython source, every one reporting
"VERDICT: fits" from the build: at 160 and 200 tests dom_data came up 68,864 and 125,296
bytes short. The shortfall comes out of the BOTTOM of dom_data, so the entry glue's carve
ran past the globals blob the monitor had copied to the front, and .capstone_cap_init is
the LAST thing in that blob. The domain then read a destroyed table and jumped through it:
cause 1 on a nonsense address at 160 tests, cause 24 on the table's own address at 200.
Neither looks like a budget problem.

WHAT CHANGES. A declaring image states what dom_data must hold, all four parts together,
and the region is sized from that instead. The slack covers the monitor's seal region and
the two roundings create_domain applies to the split, at most one representability granule
each. An image that declares nothing keeps the old rule byte for byte.

ONE REGION, NOT TWO. Two regions are the right answer for an image whose single
power-of-two block would pass the buddy allocator's order ceiling, which is SQLite's case
and needs the monitor to take a second base. That is a separate change and DOM_CREATE
already has two spare SBI arguments for it. Sizing one region correctly is what MicroPython
needs and it stops here.

EXPECT BIGGER ALLOCATIONS, and that is the requirement becoming visible rather than a
regression. At 60 tests the image runs today on 71,824 bytes of stack against 61,416 bytes
of measured use, ten kilobytes of margin by accident. Declaring an honest stack does not
fit 1 MiB, so most sizes move to 2 MiB. None approaches the order ceiling.

TESTED end to end, after rebuilding the module package and rolling the rootfs. All seven
test-table sizes now boot, including the two that did not, and the loader reports the
declaration the build wrote: "Domain requirement = 742656 (stack 131072)" against a build
line of "declare dom_data >= 742656 (carve 611584 + stack 131072)".
Copilot AI lite review requested due to automatic review settings September 13, 2026 03:15

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants