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
Expand Up @@ -27,10 +27,7 @@ use crate::{
keyed_collections::map_objects::map_prototype::{
MapPrototypeSet, canonicalize_keyed_collection_key,
},
map::{
Map,
data::{MapData, MapHeapData},
},
map::{Map, data::MapHeapData},
ordinary::ordinary_create_from_constructor,
},
execution::{
Expand Down Expand Up @@ -221,7 +218,7 @@ impl MapConstructor {
let primitive_heap = PrimitiveHeap::new(bigints, numbers, strings);

let map_entry = &mut maps[map];
let MapData {
let MapHeapData {
keys,
values,
map_data,
Expand Down Expand Up @@ -364,7 +361,7 @@ pub fn add_entries_from_iterable_map_constructor<'a>(
// Trivial, dense array of trivial, dense arrays of two elements.
let gc = gc.nogc();
let length = arr_elements.len();
let MapData {
let MapHeapData {
keys,
values,
map_data,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::{
ArgumentsList, Behaviour, Builtin, BuiltinGetter, BuiltinIntrinsic,
indexed_collections::array_objects::array_iterator_objects::array_iterator::CollectionIteratorKind,
keyed_collections::map_objects::map_iterator_objects::map_iterator::MapIterator,
map::{Map, data::MapData},
map::{Map, data::MapHeapData},
},
execution::{Agent, JsResult, Realm, agent::ExceptionType},
types::{BUILTIN_STRING_MEMORY, HeapNumber, IntoValue, PropertyKey, String, Value},
Expand Down Expand Up @@ -157,12 +157,12 @@ impl MapPrototype {
hasher.finish()
};
// 4. For each Record { [[Key]], [[Value]] } p of M.[[MapData]], do
let MapData {
keys,
let MapHeapData {
values,
keys,
map_data,
..
} = maps[m].borrow_mut(&primitive_heap);
} = &mut maps[m].borrow_mut(&primitive_heap);
let map_data = map_data.get_mut();

// a. If p.[[Key]] is not EMPTY and SameValue(p.[[Key]], key) is true, then
Expand Down Expand Up @@ -326,9 +326,9 @@ impl MapPrototype {
hasher.finish()
};
// 4. For each Record { [[Key]], [[Value]] } p of M.[[MapData]], do
let MapData {
keys,
let MapHeapData {
values,
keys,
map_data,
..
} = &maps[m].borrow(&primitive_heap);
Expand Down Expand Up @@ -378,7 +378,7 @@ impl MapPrototype {
hasher.finish()
};
// 4. For each Record { [[Key]], [[Value]] } p of M.[[MapData]], do
let MapData { keys, map_data, .. } = &mut maps[m].borrow_mut(&primitive_heap);
let MapHeapData { keys, map_data, .. } = &mut maps[m].borrow_mut(&primitive_heap);
let map_data = map_data.get_mut();

// a. If p.[[Key]] is not EMPTY and SameValue(p.[[Key]], key) is true, return true.
Expand Down Expand Up @@ -433,7 +433,7 @@ impl MapPrototype {
} = &mut agent.heap;
let primitive_heap = PrimitiveHeap::new(bigints, numbers, strings);

let MapData {
let MapHeapData {
keys,
values,
map_data,
Expand Down
77 changes: 32 additions & 45 deletions nova_vm/src/ecmascript/builtins/map/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,17 @@ use core::{
sync::atomic::{AtomicBool, Ordering},
};
use hashbrown::{HashTable, hash_table::Entry};
use soavec_derive::SoAble;

#[derive(Debug, Default)]
#[derive(Debug, Default, SoAble)]
pub struct MapHeapData<'a> {
pub(crate) object_index: Option<OrdinaryObject<'a>>,
map_data: MapData<'a>,
// TODO: When an non-terminal (start or end) iterator exists for the Map,
// the items in the map cannot be compacted.
// pub(crate) observed: bool;
}

#[derive(Debug, Default)]
pub(crate) struct MapData<'a> {
/// Low-level hash table pointing to keys-values indexes.
pub(crate) map_data: RefCell<HashTable<u32>>,
// TODO: Use a ParallelVec to remove one unnecessary allocation.
// pub(crate) key_values: ParallelVec<Option<Value>, Option<Value>>
pub(crate) keys: Vec<Option<Value<'a>>>,
pub(crate) values: Vec<Option<Value<'a>>>,
/// Low-level hash table pointing to keys-values indexes.
pub(crate) map_data: RefCell<HashTable<u32>>,
pub(crate) keys: Vec<Option<Value<'a>>>,
pub(crate) object_index: Option<OrdinaryObject<'a>>,
/// Flag that lets the Map know if it needs to rehash its primitive keys.
///
/// This happens when an object key needs to be moved in the map_data
Expand All @@ -43,6 +36,9 @@ pub(crate) struct MapData<'a> {
/// garbage collection due to the heap data being concurrently sweeped on
/// another thread.
pub(crate) needs_primitive_rehashing: AtomicBool,
// TODO: When an non-terminal (start or end) iterator exists for the Map,
// the items in the map cannot be compacted.
// pub(crate) observed: bool;
}

impl<'a> MapHeapData<'a> {
Expand All @@ -56,50 +52,48 @@ impl<'a> MapHeapData<'a> {
// 2. For each element e of setData, do
// a. If e is not EMPTY, set count to count + 1.
// 3. Return count.
self.map_data.map_data.borrow().len() as u32
self.map_data.borrow().len() as u32
}

pub fn keys(&self, _gc: NoGcScope<'a, '_>) -> &[Option<Value<'a>>] {
&self.map_data.keys
&self.keys
}

pub fn values(&self, _gc: NoGcScope<'a, '_>) -> &[Option<Value<'a>>] {
&self.map_data.values
&self.values
}

pub fn clear(&mut self) {
// 3. For each Record { [[Key]], [[Value]] } p of M.[[MapData]], do
// a. Set p.[[Key]] to EMPTY.
// b. Set p.[[Value]] to EMPTY.
self.map_data.map_data.get_mut().clear();
self.map_data.values.fill(None);
self.map_data.keys.fill(None);
self.map_data.get_mut().clear();
self.values.fill(None);
self.keys.fill(None);
}

pub(crate) fn borrow(&self, arena: &impl PrimitiveHeapIndexable) -> &MapData<'a> {
self.map_data.rehash_if_needed(arena);
&self.map_data
pub(crate) fn borrow(&self, arena: &impl PrimitiveHeapIndexable) -> &Self {
self.rehash_if_needed(arena);
self
}

pub(crate) fn borrow_mut(&mut self, arena: &impl PrimitiveHeapIndexable) -> &mut MapData<'a> {
self.map_data.rehash_if_needed_mut(arena);
&mut self.map_data
pub(crate) fn borrow_mut(&mut self, arena: &impl PrimitiveHeapIndexable) -> &mut Self {
self.rehash_if_needed_mut(arena);
self
}

pub fn with_capacity(new_len: usize) -> Self {
Self {
map_data: MapData {
keys: Vec::with_capacity(new_len),
values: Vec::with_capacity(new_len),
map_data: RefCell::new(HashTable::with_capacity(new_len)),
needs_primitive_rehashing: AtomicBool::new(false),
},
keys: Vec::with_capacity(new_len),
values: Vec::with_capacity(new_len),
map_data: RefCell::new(HashTable::with_capacity(new_len)),
needs_primitive_rehashing: AtomicBool::new(false),
object_index: None,
}
}
}

impl MapData<'_> {
impl MapHeapData<'_> {
fn rehash_if_needed_mut(&mut self, arena: &impl PrimitiveHeapIndexable) {
if !*self.needs_primitive_rehashing.get_mut() {
return;
Expand Down Expand Up @@ -185,31 +179,24 @@ bindable_handle!(MapHeapData);
impl HeapMarkAndSweep for MapHeapData<'static> {
fn mark_values(&self, queues: &mut WorkQueues) {
let Self {
keys,
values,
object_index,
map_data,
..
} = self;
object_index.mark_values(queues);
map_data
.keys
.iter()
.for_each(|value| value.mark_values(queues));
map_data
.values
.iter()
.for_each(|value| value.mark_values(queues));
keys.iter().for_each(|value| value.mark_values(queues));
values.iter().for_each(|value| value.mark_values(queues));
}

fn sweep_values(&mut self, compactions: &CompactionLists) {
let Self {
object_index,
map_data,
} = self;
let MapData {
keys,
values,
needs_primitive_rehashing,
map_data,
} = map_data;
} = self;
let map_data = map_data.get_mut();
object_index.sweep_values(compactions);

Expand Down
Loading