Provides utility functions, arena allocator, and arena-backed containers.
Overview
This functionality is primarily intended for AsmJit's internal use, but is exposed to users since it may be used in public headers as well. Arena and arena-backed containers are used by many AsmJit classes, which are public, and AsmJit doesn't try to hide the use.
The arena allocator is used for most allocations within AsmJit. It is optimized for fast allocation of small objects, avoiding the overhead of malloc()
. Memory is managed in large blocks that are split into smaller chunks, reducing fragmentation and improving performance.
Releasing an arena allocator invalidates memory it holds, allowing efficient cleanup without per-object destruction. Long-lived objects typically reset their data in the destructor or via reset()
for allocation reuse. All AsmJit containers use Arena allocator.
Using Arena-Allocated Containers [¶]
The most common data structure exposed by AsmJit is ArenaVector. It's very similar to std::vector
, but the implementation doesn't use exceptions and uses the mentioned Arena allocator for increased performance and decreased memory footprint. You don't have to worry about allocations as you should not need to add items to AsmJit's data structures directly as there should be API for all required operations.
Most of the time, AsmJit returns a non-owning Span instead of a reference to the allocator when it returns an array of something. For example, the following APIs in CodeHolder return a non-owning Span instance:
Span has overloaded array access operator to make it possible to access its elements through operator[]. Some standard functions like ArenaVector::is_empty(), ArenaVector::size(), and ArenaVector::data() are provided as well. Vectors are also iterable through a range-based for loop:
for (size_t label_id = 0; label_id < label_entries.size(); label_id++) {
printf(
"Bound Label #%u at offset=%llu\n", uint32_t(label_id), (
unsigned long long)le.
offset());
}
}
}
Design Considerations [¶]
Arena-allocated containers do not store the allocator within the container. This decision was made to reduce the footprint of such containers as AsmJit tooling, especially Compiler's register allocation, may use many instances of such containers to perform code analysis and register allocation.
For example to append an item into an ArenaVector it's required to pass the allocator as the first argument, so it can be used in case that the vector needs to grow. Such function also returns an error, which must be propagated to the caller.
for (int i = 0; i < 100; i++) {
}
}
Containers like ArenaVector also provide a functionality to reserve a certain number of items before any items are added to it. This approach is used internally in most places as it allows to prepare space for data that will be added to some container before the data itself was created.
for (int i = 0; i < 100; i++) {
}
}