[turbopack] Add BumpVec (vector implementation that takes a Bump)#94296
[turbopack] Add BumpVec (vector implementation that takes a Bump)#94296sampoder wants to merge 3 commits into
BumpVec (vector implementation that takes a Bump)#94296Conversation
Failing test suitesCommit: 01e3dd5 | About building and testing Next.js
Expand output● app-dir - server-action-period-hash-custom-key › should have a different manifest if the encryption key from process env is changed ● app-dir - server-action-period-hash-custom-key › should have the same manifest if the encryption key from process env is same
Expand output● interception-dynamic-segment › should work when interception route is paired with a dynamic segment ● interception-dynamic-segment › should intercept consistently with back/forward navigation ● interception-dynamic-segment › should intercept multiple times from root Other failing CI jobs |
Stats skippedCommit: 01e3dd5 |
Introduces `BumpVec<'a, T>`, a minimal growable vector for bump-allocated data. It stores only an arena-allocated buffer and a length, so it is `Send`/`Sync` (a `&'a mut [T]` is, when `T` is) with no `unsafe impl` — the only `unsafe` is the localized `MaybeUninit` bookkeeping. Growth methods take the `&'a Bump` to allocate from; `Drop` drops the live elements (the arena only frees memory). Includes unit tests covering growth, `split_off`, the three iterators, and drop/double-free behavior. This is the first of a two-PR stack; a follow-up uses it to arena-allocate the analyzer's `JsValue`s.
a98d014 to
e21492c
Compare
JsValuesBumpVec (vector implementation that takes a Bump)
| pub fn extend(&mut self, bump: &'a Bump, iter: impl IntoIterator<Item = T>) { | ||
| for value in iter { | ||
| self.push(bump, value); | ||
| } | ||
| } |
There was a problem hiding this comment.
If we can, we should implement extend_from_slice instead, and use memcopy to implement that.
This is also not ideal as-implemented because it could lead to multiple reallocs, when there should only be one.
| impl<T> Drop for BumpVec<'_, T> { | ||
| fn drop(&mut self) { | ||
| // SAFETY: `0..len` is initialized; drop each element (the arena only frees memory). | ||
| unsafe { ptr::drop_in_place(&mut **self) } | ||
| } | ||
| } |
There was a problem hiding this comment.
Potential follow up: See if we can eliminate reference-counted types in JsValue and develop a unit test that checks that std::mem::needs_drop::<JsValue>() == false.
| /// Binds the arena lifetime and signals ownership/variance over `T` to the compiler. | ||
| _marker: PhantomData<&'a mut [T]>, |
There was a problem hiding this comment.
| /// Binds the arena lifetime and signals ownership/variance over `T` to the compiler. | |
| _marker: PhantomData<&'a mut [T]>, | |
| /// Binds the arena lifetime and signals ownership/variance over `T` to the compiler. | |
| _marker: PhantomData<&'a ()>, |
| /// Collect `iter` into a growable [`BumpVec`]. | ||
| pub fn from_iter_in(bump: &'a Bump, iter: impl IntoIterator<Item = T>) -> Self { | ||
| let iter = iter.into_iter(); | ||
| let mut vec = Self::with_capacity_in(bump, iter.size_hint().0); |
There was a problem hiding this comment.
Maybe prefer the upper bound if it exists
This PR implements
BumpVecthis is a custom vector implementation that takes in aBumpas a type (from bumpalo) so that we getSend/Syncon ourJSValuevectors when we make that switch in: #94297.