[turbotask] Make turbotask function registration const (#90797)
# What
Make turbotask function registration const -- all function registration
blocks are true &'static items, compiled directly into the binary.
Removes a few thousand allocations of type names and boxed impls of
TaskFn.
# Why
We have approx 2k functions, so the cost of Lazy construction +
temporary allocations adds up (even with compiler optimization). This
also unlocks the opportunity for further startup optimizations (in later
PRs).
# How
The `#[turbo_tasks::function]` macro now generates static items
initialized directly with const fn constructors instead of `Lazy::new(||
...)`, using `const { &into_task_fn(f) as &dyn TaskFn }` blocks to
produce `&'static dyn TaskFn` trait objects at compile time from
zero-sized function items.
Global names that previously required runtime format!() + Box::leak()
are now computed at compile time via `const_type_name()` (a const
wrapper around `std::any::type_name`) and a `const_concat!` macro that
concatenates string slices into a fixed-size byte array.
The NativeFunction struct, ArgMeta, and the
into_task_fn/into_task_fn_with_this wrappers are all const
fn-constructible, with input types inferred through a TaskFnInputs trait
that maps wrapper types to their argument tuples (we use a non-allocated
and non-compiled temporary "duplicate" `TaskFn` instance that is only
useful for type inference in a const context).
# Next Steps
I believe we can remove the const `type_name` in favour of the const
`type_id` and instead pull function names only when needed for display
purposes. This will show up in a future PR.
We can also remove non-const registration for things that aren't
functions as well, though I believe this is less important.