The Dart VM uses a sophisticated object model to efficiently represent Dart objects in memory with support for precise garbage collection.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/dart-lang/sdk/llms.txt
Use this file to discover all available pages before exploring further.
Object Pointer Tagging
Object pointers use the low bits as tags to distinguish between immediate and heap objects:| Pointer Type | Tag | Description |
|---|---|---|
| Smi (Small Integer) | 0 | Immediate value, not heap-allocated |
| Heap Object | 1 | Pointer to heap-allocated object |
- Smi operations without untagging/retagging (tag of 0)
- Heap access with no penalty (tag removed via offset folding)
Pointer Examples
Smi (Small Integer)
Smis are immediate objects representing signed integers:- 31-bit values on 32-bit platforms
- 63-bit values on 64-bit platforms
- Upper bits contain the value
- Least significant bit is
0(tag)
int type.
Heap Object Layout
Heap objects are always allocated in double-word increments with specific alignment:- Old-space objects - Double-word aligned (
address % double-word == 0) - New-space objects - Offset from double-word (
address % double-word == word)
- Checking object age without comparing boundary addresses
- Scavenger can skip immediates and old objects with a single branch
Object Header
Every heap object has a single-word header containing:- Class ID - Index into the class table
- Size - Object size in the heap
- Status flags - GC marks, remembered set bits, etc.
- Identity hash - 32-bit hash (on 64-bit platforms; separate table on 32-bit)
Class Identification
Class ID (CID)
A class ID is an integer that uniquely identifies a class within an isolate:- Smaller than a full pointer to the class
- Never changes due to GC (unlike pointers)
- Build-time constant for well-known classes
- Used in type feedback (ICData) and optimizations
Class Table
The class ID from an object’s header is an index into the class table - an array ofClass objects representing all loaded Dart classes.
Object Representation
VM object definitions are split into two parts:Xyzclass inruntime/vm/object.h- C++ methods and high-level interfaceUntaggedXyzclass inruntime/vm/raw_object.h- Actual memory layout
dart::Class+dart::UntaggedClass- Dart class metadatadart::Field+dart::UntaggedField- Dart field within a classdart::Function+dart::UntaggedFunction- Dart function/method
Type Representation
The runtime type of an instance is determined by:- Smi objects - Implicitly the non-nullable
Smitype - Heap objects:
- Extract
ClassIdTagfrom header - Get
Classobject from class table - Read
type_argumentsfield at known offset (if generic) - Build type from class + type arguments
- Extract
Special Case: Closures
ForClosure instances, the runtime type is not Closure but a function type:
- The
functionfield points to the associatedFunctionobject - The
signaturefield inFunctionrepresents the function type - This type is instantiated in the closure’s context
Type Objects
Type
Simple Dart types are represented byType objects containing:
type_class_id- Class of this typearguments- Type argument vector (if generic)nullability-legacy,nullable, ornon-nullablehash- Cached hash codestate- Finalization state
FunctionType
Function signatures are represented byFunctionType objects containing:
- Type parameters and their bounds (if generic)
- Result type
- Parameter types
- Named parameter names
- Required parameter flags
TypeParameter
Type parameters (likeT in class C<T>) are represented by TypeParameter objects:
index- Index into type argument vector for instantiation- Indicates if class or function type parameter
TypeArguments
ATypeArguments object is a vector of AbstractType instances:
- Not a type itself, but the generic component of a type
nulltype arguments = vector ofdynamicof appropriate length- Shared and canonicalized to save memory
Type Argument Flattening
The VM flattens type argument vectors across the class hierarchy:[List<bool>, bool] allows both B.bar() and C.foo() to access the correct type arguments using their respective indices.
Type Argument Overlapping
When type arguments repeat, they are overlapped to save space:Compressed Pointers
On 64-bit platforms with limited memory (mobile devices), pointers can be compressed to 32 bits:- Heap restricted to 4GB-aligned region
- Store: Drop upper 32 bits
- Load: Add heap base to decompress
Smi-Corrupting Strategy
Decompressing unconditionally adds the heap base, so Smi values get corrupted upper bits:| Operation | Uncompressed | Compressed |
|---|---|---|
| Load pointer | ldr x0, [x1, #9] | ldr w0, [x1, #9]add x0, x0, x28 |
| Store pointer | str x0, [x1, #9] | str w0, [x1, #9] |
| Smi add | add x0, x1, x2 | add w0, w1, w2 (32-bit) |
| Smi compare | cmp x0, x1 | cmp w0, w1 (32-bit) |
Compressed Pointer Limitations
- ObjectPool remains uncompressed - Saves net code size
- All isolate groups share the same 4GB region
- Read-only data deserialized into heap (not lazy-loaded from snapshots)
Handles
The Dart VM GC is precise and moving:- Precise - Knows exactly what is a pointer vs. unboxed value
- Moving - Object addresses can change during GC
- Handles are pointers-to-pointers
- Allocated from the VM
- GC visits and updates pointers in handles during collection
- Required because the VM doesn’t know which foreign stack slots/globals contain Dart pointers
Finalization
Types loaded from Kernel files require finalization:- Assign indices to type parameters
- Flatten type argument vectors
- Canonicalize types and type argument vectors
- Minimizes memory usage
- Optimizes type tests (pointer equality works for canonical types)
- Enables type test caching
Object Pool (Literal Pool)
Generated code references constants through an object pool:- Set of objects and raw bits used as constants
- JIT: Per-function pools
- AOT: Global pool
- Accessed via PP (pool pointer) register
Key Source Files
runtime/vm/object.h- Object C++ interfaces (Xyzclasses)runtime/vm/raw_object.h- Object memory layouts (UntaggedXyzclasses)runtime/vm/class_table.h- Class ID tableruntime/vm/heap/- Heap and GC implementationruntime/docs/types.md- Detailed type system documentationruntime/docs/compressed-pointers.md- Compressed pointer details