The ApplicationStack inside ViewManager reserves a fixed byte arena. All live Apps are constructed in place following stack order, with no per-App heap allocation.
![]()
App A and App B use their actual object sizes. Alignment requirements determine the padding between them. Object bytes and metadata are separate: metadata records rollback positions and concrete destructors.
Arena bytes, maximum alignment, and page depth are fixed configuration values listed in Resource limits.
Layout
1 | arena begin |
Each push aligns the current offset to alignof(T), verifies that padding plus object bytes fit, and placement-constructs the object. Metadata is committed only after construction succeeds. Pop invokes the correct destructor through a type-specific destroy thunk and restores the previous marker.
Why a LIFO arena
- Capacity and failure are predictable.
- App storage avoids heap fragmentation.
- Small Apps consume their own size, while fixed-size slots would reserve the maximum App size for every entry.
- Reclamation needs no general allocator because page navigation is already LIFO.
Destruction follows stack order and applies to the top App. The total size and alignment padding of all live Apps must fit in the arena.
Factory and custom construction
launch() uses the factory in AppItem to construct a concrete type inside the arena. See Launch AppLauncher for regular registration. Use a non-capturing thunk for special constructor arguments:
1 | AppItem item = AppItem::make<MyApp>( |
The thunk may construct exactly the declared concrete type in storage, or return null without constructing anything.
Measure the resulting object sizes with the target compiler:
1 | ./build/tests/memory_metrics |



