Recover concrete AST nodes from their embedded headers
The Issue & Context
Previously, every AST node stored a self-referential interface along with a separate node header, leading to larger memory footprints and redundant data in the TypeScript compiler's internal AST representation.
Root Cause Analysis
The node header and the node's kind were stored separately, causing duplication and larger header sizes (48 bytes). The self-referential interface was maintained despite the node kind already enabling dispatch, resulting in inefficient memory layout and higher GC overhead.
Solution Strategy & Architectural Pattern
This PR reworks the AST node layout to embed the node header at offset zero within the concrete node structures, reducing the header size from 48 to 32 bytes. Generated accessor casts now verify node kinds and assert offset-zero embedding at compile time, enabling safe recovery of concrete nodes from their headers. Additionally, it omits DWARF debug info in non-debug coverage builds to save disk space on ARM64 CI. These changes collectively reduce retained heap size, GC scanning, and allocated bytes as measured in VS Code.
Key Takeaway for Contributors
Embedding metadata directly within data structures and verifying invariants at compile time can significantly reduce memory overhead and improve runtime efficiency in large, performance-sensitive systems like compilers.