[turbopack] Remove turbotask functions from `trait ResolveOrigin` (#94324)
### What?
Removes the `#[turbo_tasks::function]` annotations from the
`ResolveOrigin` trait methods (`origin_path`, `asset_context`,
`resolve_options`), turning them into plain synchronous trait methods.
Callers obtain the value once via `Vc::into_trait_ref().await?` and then
call the methods directly on the resulting `TraitRef`.
This mirrors the earlier de-functionification of the `Issue` trait
(#92623).
### Why?
The `ResolveOrigin` implementations are all trivial — they return a
stored field or delegate a single call.
| Task (misses, before → after) | Misses removed |
| --- | --- |
| `ResolveOrigin::resolve_options` (dyn) | 92,608 → 0 |
| `EcmascriptModuleAsset::origin_path` | 64,779 → 0 |
| `ResolveOriginWithTransition::asset_context` | 52,292 → 0 |
| `ResolveOriginWithTransition::origin_path` | 52,292 → 0 |
| `EcmascriptModuleAsset::asset_context` | 41,164 → 0 |
| `PlainResolveOrigin::{origin_path, asset_context}` | 105 + 105 → 0 |
| `EcmascriptCssModule::{origin_path, asset_context}` | 32 + 32 → 0 |
| `CssModule::{origin_path, asset_context}` | 19 + 19 → 0 |
Net effect in that run: **~303k fewer cache misses** (total misses
6,197,068 → 5,893,545) — The ~1.35M eliminated cached-task *hits*
additionally remove the per-call task lookup/scheduling overhead.
The caching that genuinely matters is preserved one layer down —
`AssetContext::resolve_options` (which `ResolveOrigin::resolve_options`
delegated to) is still a cached task; its miss count is unchanged
(39,668) since those distinct results were always computed, and it
simply absorbs the call volume directly now (hit rate 57% → 92%).
## Build Performance: `ResolveOrigin` optimization
Benchmark across 10 runs per branch.
| Metric | Base | This branch | Δ |
|---|---|---|---|
| **Wall time** | 43.302 s | 42.692 s | **−0.61 s (−1.4%)** |
| **User time** | 314.249 s | 310.919 s | **−3.33 s (−1.1%)** |
| **Sys time** | 84.225 s | 84.618 s | +0.39 s (+0.5%) |
| **MaxRSS** | 14106.1 MB | 13883.4 MB | **−222.8 MB (−1.6%)** |
### Notes on significance
- **User time** is the cleanest signal: −1.1% with very tight variance
(base σ 0.4%, branch σ 0.3%). The drop (~3.3 s) is well outside the
noise — a real reduction in CPU work.
- **MaxRSS** is down a solid 1.6% (~223 MB) with tight variance on both
sides (σ ≈ 0.5–0.6%) — a clear, reproducible memory win.
- **Wall time** improves 1.4%, but variance is large (base σ 6.6%,
branch σ 4.5%, with one 50 s outlier in the base set), so treat this as
directional. It tracks the user-time improvement.
- **Sys time** is essentially flat (+0.5%, within its ~10% run-to-run
noise) — no meaningful change, as expected for a CPU/allocation
optimization.
### Invalidation tradeoff
The main behavioral risk is invalidation granularity. Removing the
per-method tasks removes their invalidation boundary: a consumer that
previously depended only on the `origin_path()` (or `asset_context()`)
task output now reads the value off the origin directly, so it is tied
to the origin cell rather than to that one method's cached output.
In practice this is narrow, because every `ResolveOrigin` implementor is
an immutable, content-addressed `#[turbo_tasks::value]` (only
`ResolvedVc`/owned fields) — a different field value means a different
cell, so "reading the whole value vs. one field" does not by itself
widen invalidation.
<!-- NEXT_JS_LLM_PR -->