Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Bumpalo memory arena utilities
//! Copied from [jsparagus](https://github.com/mozilla-spidermonkey/jsparagus/blob/master/crates/ast/src/arena.rs)
//! Arena Box.
//!
//! Originally based on [jsparagus](https://github.com/mozilla-spidermonkey/jsparagus/blob/master/crates/ast/src/arena.rs)

use std::{
self,
Expand All @@ -10,11 +11,8 @@ use std::{
ptr::{self, NonNull},
};

use allocator_api2::vec;
pub use bumpalo::collections::String;
use bumpalo::Bump;
#[cfg(any(feature = "serialize", test))]
use serde::{ser::SerializeSeq, Serialize, Serializer};
use serde::{Serialize, Serializer};

use crate::Allocator;

Expand Down Expand Up @@ -107,111 +105,6 @@ impl<'alloc, T: Hash> Hash for Box<'alloc, T> {
}
}

/// Bumpalo Vec
#[derive(Debug, PartialEq, Eq)]
pub struct Vec<'alloc, T>(vec::Vec<T, &'alloc Bump>);

impl<'alloc, T> Vec<'alloc, T> {
#[inline]
pub fn new_in(allocator: &'alloc Allocator) -> Self {
Self(vec::Vec::new_in(allocator))
}

#[inline]
pub fn with_capacity_in(capacity: usize, allocator: &'alloc Allocator) -> Self {
Self(vec::Vec::with_capacity_in(capacity, allocator))
}

#[inline]
pub fn from_iter_in<I: IntoIterator<Item = T>>(iter: I, allocator: &'alloc Allocator) -> Self {
let iter = iter.into_iter();
let capacity = iter.size_hint().1.unwrap_or(0);
let mut vec = vec::Vec::with_capacity_in(capacity, &**allocator);
vec.extend(iter);
Self(vec)
}
}

impl<'alloc, T> ops::Deref for Vec<'alloc, T> {
type Target = vec::Vec<T, &'alloc Bump>;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl<'alloc, T> ops::DerefMut for Vec<'alloc, T> {
fn deref_mut(&mut self) -> &mut vec::Vec<T, &'alloc Bump> {
&mut self.0
}
}

impl<'alloc, T> IntoIterator for Vec<'alloc, T> {
type IntoIter = <vec::Vec<T, &'alloc Bump> as IntoIterator>::IntoIter;
type Item = T;

fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}

impl<'alloc, T> IntoIterator for &'alloc Vec<'alloc, T> {
type IntoIter = std::slice::Iter<'alloc, T>;
type Item = &'alloc T;

fn into_iter(self) -> Self::IntoIter {
self.0.iter()
}
}

impl<'alloc, T> ops::Index<usize> for Vec<'alloc, T> {
type Output = T;

fn index(&self, index: usize) -> &Self::Output {
self.0.index(index)
}
}

impl<'alloc, T> ops::Index<usize> for &'alloc Vec<'alloc, T> {
type Output = T;

fn index(&self, index: usize) -> &Self::Output {
self.0.index(index)
}
}

// Unused right now.
// impl<'alloc, T> ops::IndexMut<usize> for Vec<'alloc, T> {
// fn index_mut(&mut self, index: usize) -> &mut Self::Output {
// self.0.index_mut(index)
// }
// }

#[cfg(any(feature = "serialize", test))]
impl<'alloc, T> Serialize for Vec<'alloc, T>
where
T: Serialize,
{
fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut seq = s.serialize_seq(Some(self.0.len()))?;
for e in &self.0 {
seq.serialize_element(e)?;
}
seq.end()
}
}

impl<'alloc, T: Hash> Hash for Vec<'alloc, T> {
fn hash<H: Hasher>(&self, state: &mut H) {
for e in &self.0 {
e.hash(state);
}
}
}

/// Memory address of an AST node in arena.
///
/// `Address` is generated from a `Box<T>`.
Expand All @@ -231,7 +124,9 @@ impl<'a, T> Box<'a, T> {
mod test {
use std::hash::{DefaultHasher, Hash, Hasher};

use crate::{Allocator, Box, Vec};
use crate::Allocator;

use super::Box;

#[test]
fn box_deref_mut() {
Expand Down Expand Up @@ -265,15 +160,6 @@ mod test {
assert_eq!(hash(&a), hash(&b));
}

#[test]
fn vec_debug() {
let allocator = Allocator::default();
let mut v = Vec::new_in(&allocator);
v.push("x");
let v = format!("{v:?}");
assert_eq!(v, "Vec([\"x\"])");
}

#[test]
fn box_serialize() {
let allocator = Allocator::default();
Expand All @@ -282,22 +168,10 @@ mod test {
assert_eq!(b, "\"x\"");
}

#[test]
fn vec_serialize() {
let allocator = Allocator::default();
let mut v = Vec::new_in(&allocator);
v.push("x");
let v = serde_json::to_string(&v).unwrap();
assert_eq!(v, "[\"x\"]");
}

#[test]
fn lifetime_variance() {
fn _assert_box_variant_lifetime<'a: 'b, 'b, T>(program: Box<'a, T>) -> Box<'b, T> {
program
}
fn _assert_vec_variant_lifetime<'a: 'b, 'b, T>(program: Vec<'a, T>) -> Vec<'b, T> {
program
}
}
}
11 changes: 7 additions & 4 deletions crates/oxc_allocator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,18 @@ use std::{
ops::{Deref, DerefMut},
};

mod arena;
pub use bumpalo::collections::String;
use bumpalo::Bump;

mod boxed;
mod clone_in;
mod convert;
mod vec;

use bumpalo::Bump;

pub use arena::{Address, Box, String, Vec};
pub use boxed::{Address, Box};
pub use clone_in::CloneIn;
pub use convert::{FromIn, IntoIn};
pub use vec::Vec;

#[derive(Default)]
pub struct Allocator {
Expand Down
154 changes: 154 additions & 0 deletions crates/oxc_allocator/src/vec.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
//! Arena Vec.
//!
//! Originally based on [jsparagus](https://github.com/mozilla-spidermonkey/jsparagus/blob/master/crates/ast/src/arena.rs)

use std::{
self,
fmt::Debug,
hash::{Hash, Hasher},
ops,
};

use allocator_api2::vec;
use bumpalo::Bump;
#[cfg(any(feature = "serialize", test))]
use serde::{ser::SerializeSeq, Serialize, Serializer};

use crate::Allocator;

/// Bumpalo Vec
#[derive(Debug, PartialEq, Eq)]
pub struct Vec<'alloc, T>(vec::Vec<T, &'alloc Bump>);

impl<'alloc, T> Vec<'alloc, T> {
#[inline]
pub fn new_in(allocator: &'alloc Allocator) -> Self {
Self(vec::Vec::new_in(allocator))
}

#[inline]
pub fn with_capacity_in(capacity: usize, allocator: &'alloc Allocator) -> Self {
Self(vec::Vec::with_capacity_in(capacity, allocator))
}

#[inline]
pub fn from_iter_in<I: IntoIterator<Item = T>>(iter: I, allocator: &'alloc Allocator) -> Self {
let iter = iter.into_iter();
let capacity = iter.size_hint().1.unwrap_or(0);
let mut vec = vec::Vec::with_capacity_in(capacity, &**allocator);
vec.extend(iter);
Self(vec)
}
}

impl<'alloc, T> ops::Deref for Vec<'alloc, T> {
type Target = vec::Vec<T, &'alloc Bump>;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl<'alloc, T> ops::DerefMut for Vec<'alloc, T> {
fn deref_mut(&mut self) -> &mut vec::Vec<T, &'alloc Bump> {
&mut self.0
}
}

impl<'alloc, T> IntoIterator for Vec<'alloc, T> {
type IntoIter = <vec::Vec<T, &'alloc Bump> as IntoIterator>::IntoIter;
type Item = T;

fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}

impl<'alloc, T> IntoIterator for &'alloc Vec<'alloc, T> {
type IntoIter = std::slice::Iter<'alloc, T>;
type Item = &'alloc T;

fn into_iter(self) -> Self::IntoIter {
self.0.iter()
}
}

impl<'alloc, T> ops::Index<usize> for Vec<'alloc, T> {
type Output = T;

fn index(&self, index: usize) -> &Self::Output {
self.0.index(index)
}
}

impl<'alloc, T> ops::Index<usize> for &'alloc Vec<'alloc, T> {
type Output = T;

fn index(&self, index: usize) -> &Self::Output {
self.0.index(index)
}
}

// Unused right now.
// impl<'alloc, T> ops::IndexMut<usize> for Vec<'alloc, T> {
// fn index_mut(&mut self, index: usize) -> &mut Self::Output {
// self.0.index_mut(index)
// }
// }

#[cfg(any(feature = "serialize", test))]
impl<'alloc, T> Serialize for Vec<'alloc, T>
where
T: Serialize,
{
fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut seq = s.serialize_seq(Some(self.0.len()))?;
for e in &self.0 {
seq.serialize_element(e)?;
}
seq.end()
}
}

impl<'alloc, T: Hash> Hash for Vec<'alloc, T> {
fn hash<H: Hasher>(&self, state: &mut H) {
for e in &self.0 {
e.hash(state);
}
}
}

#[cfg(test)]
mod test {
use crate::Allocator;

use super::Vec;

#[test]
fn vec_debug() {
let allocator = Allocator::default();
let mut v = Vec::new_in(&allocator);
v.push("x");
let v = format!("{v:?}");
assert_eq!(v, "Vec([\"x\"])");
}

#[test]
fn vec_serialize() {
let allocator = Allocator::default();
let mut v = Vec::new_in(&allocator);
v.push("x");
let v = serde_json::to_string(&v).unwrap();
assert_eq!(v, "[\"x\"]");
}

#[test]
fn lifetime_variance() {
fn _assert_vec_variant_lifetime<'a: 'b, 'b, T>(program: Vec<'a, T>) -> Vec<'b, T> {
program
}
}
}