Skip to content

Commit 90fca78

Browse files
authored
feat: store map in soavec on heap (#906)
1 parent 790d800 commit 90fca78

File tree

9 files changed

+157
-137
lines changed

9 files changed

+157
-137
lines changed

nova_vm/src/ecmascript/builtins/control_abstraction_objects/promise_objects/promise_constructor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -946,7 +946,7 @@ fn perform_promise_group<'gc>(
946946
let capacity = match iterator.get(agent) {
947947
Object::Array(array) => array.len(agent),
948948
#[cfg(feature = "set")]
949-
Object::Map(map) => agent[map].size(),
949+
Object::Map(map) => map.len(agent),
950950
#[cfg(feature = "set")]
951951
Object::Set(set) => set.get(agent).set_data.borrow().len() as u32,
952952
_ => 0,

nova_vm/src/ecmascript/builtins/keyed_collections/map_objects/map_constructor.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ use crate::{
2727
keyed_collections::map_objects::map_prototype::{
2828
MapPrototypeSet, canonicalize_keyed_collection_key,
2929
},
30-
map::{Map, data::MapHeapData},
30+
map::{
31+
Map,
32+
data::{MapHeapData, MapHeapDataMut},
33+
},
3134
ordinary::ordinary_create_from_constructor,
3235
},
3336
execution::{
@@ -217,13 +220,12 @@ impl MapConstructor {
217220
} = &mut agent.heap;
218221
let primitive_heap = PrimitiveHeap::new(bigints, numbers, strings);
219222

220-
let map_entry = &mut maps[map];
221-
let MapHeapData {
223+
let MapHeapDataMut {
222224
keys,
223225
values,
224226
map_data,
225227
..
226-
} = &mut map_entry.borrow_mut(&primitive_heap);
228+
} = map.get_direct_mut(maps);
227229
let map_data = map_data.get_mut();
228230
let hasher = |value: Value| {
229231
let mut hasher = AHasher::default();
@@ -361,12 +363,12 @@ pub fn add_entries_from_iterable_map_constructor<'a>(
361363
// Trivial, dense array of trivial, dense arrays of two elements.
362364
let gc = gc.nogc();
363365
let length = arr_elements.len();
364-
let MapHeapData {
366+
let MapHeapDataMut {
365367
keys,
366368
values,
367369
map_data,
368370
..
369-
} = maps[target].borrow_mut(&primitive_heap);
371+
} = target.get_direct_mut(maps);
370372
let map_data = map_data.get_mut();
371373

372374
let length = length as usize;

nova_vm/src/ecmascript/builtins/keyed_collections/map_objects/map_iterator_objects/map_iterator_prototype.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ impl MapIteratorPrototype {
6060
// a. Let entries be map.[[MapData]].
6161
// c. Let numEntries be the number of elements in entries.
6262
// d. Repeat, while index < numEntries,
63-
while agent[iterator].next_index < agent[map].keys(gc).len() {
63+
while agent[iterator].next_index < map.get(agent).keys.len() {
6464
// i. Let e be entries[index].
6565
// ii. Set index to index + 1.
6666
let index = agent[iterator].next_index;
@@ -71,7 +71,7 @@ impl MapIteratorPrototype {
7171
// iii. If e.[[Key]] is not EMPTY, then
7272
// 1. If kind is KEY, then
7373
// a. Let result be e.[[Key]].
74-
let Some(key) = agent[map].keys(gc)[index] else {
74+
let Some(key) = map.get(agent).keys[index] else {
7575
continue;
7676
};
7777
key
@@ -80,7 +80,7 @@ impl MapIteratorPrototype {
8080
// iii. If e.[[Key]] is not EMPTY, then
8181
// 2. If kind is VALUE, then
8282
// a. Let result be e.[[Value]].
83-
let Some(value) = agent[map].values(gc)[index] else {
83+
let Some(value) = map.get(agent).values[index] else {
8484
continue;
8585
};
8686
value
@@ -90,10 +90,10 @@ impl MapIteratorPrototype {
9090
// 3. Else,
9191
// a. Assert: kind is KEY+VALUE.
9292
// b. Let result be CreateArrayFromList(« e.[[Key]], e.[[Value]] »).
93-
let Some(key) = agent[map].keys(gc)[index] else {
93+
let Some(key) = map.get(agent).keys[index] else {
9494
continue;
9595
};
96-
let value = agent[map].values(gc)[index].unwrap();
96+
let value = map.get(agent).values[index].unwrap();
9797
create_array_from_list(agent, &[key, value], gc).into_value()
9898
}
9999
};
@@ -103,7 +103,7 @@ impl MapIteratorPrototype {
103103
.map(|o| o.into_value());
104104
}
105105

106-
debug_assert_eq!(agent[iterator].next_index, agent[map].keys(gc).len());
106+
debug_assert_eq!(agent[iterator].next_index, map.get(agent).keys.len());
107107

108108
// e. Return undefined.
109109
agent[iterator].map = None;

nova_vm/src/ecmascript/builtins/keyed_collections/map_objects/map_prototype.rs

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use crate::{
1717
ArgumentsList, Behaviour, Builtin, BuiltinGetter, BuiltinIntrinsic,
1818
indexed_collections::array_objects::array_iterator_objects::array_iterator::CollectionIteratorKind,
1919
keyed_collections::map_objects::map_iterator_objects::map_iterator::MapIterator,
20-
map::{Map, data::MapHeapData},
20+
map::{Map, data::MapHeapDataMut},
2121
},
2222
execution::{Agent, JsResult, Realm, agent::ExceptionType},
2323
types::{BUILTIN_STRING_MEMORY, HeapNumber, IntoValue, PropertyKey, String, Value},
@@ -117,7 +117,7 @@ impl MapPrototype {
117117
// 3. For each Record { [[Key]], [[Value]] } p of M.[[MapData]], do
118118
// a. Set p.[[Key]] to EMPTY.
119119
// b. Set p.[[Value]] to EMPTY.
120-
agent[m].clear();
120+
m.clear(agent);
121121
// 4. Return undefined.
122122
Ok(Value::Undefined)
123123
}
@@ -157,12 +157,12 @@ impl MapPrototype {
157157
hasher.finish()
158158
};
159159
// 4. For each Record { [[Key]], [[Value]] } p of M.[[MapData]], do
160-
let MapHeapData {
160+
let MapHeapDataMut {
161161
values,
162162
keys,
163163
map_data,
164164
..
165-
} = &mut maps[m].borrow_mut(&primitive_heap);
165+
} = m.get_direct_mut(maps);
166166
let map_data = map_data.get_mut();
167167

168168
// a. If p.[[Key]] is not EMPTY and SameValue(p.[[Key]], key) is true, then
@@ -253,7 +253,7 @@ impl MapPrototype {
253253

254254
// 4. Let entries be M.[[MapData]].
255255
// 5. Let numEntries be the number of elements in entries.
256-
let mut num_entries = agent[m].values(gc.nogc()).len();
256+
let mut num_entries = m.get(agent).values.len();
257257

258258
let this_arg = this_arg.scope(agent, nogc);
259259
let callback_fn = callback_fn.scope(agent, nogc);
@@ -264,14 +264,14 @@ impl MapPrototype {
264264
// 7. Repeat, while index < numEntries,
265265
while index < num_entries {
266266
// a. Let e be entries[index].
267-
let data = &agent[m];
267+
let data = &m.get(agent);
268268
let entry_index = index;
269269
// b. Set index to index + 1.
270270
index += 1;
271-
let k = data.keys(gc.nogc())[entry_index];
271+
let k = data.keys[entry_index];
272272
// c. If e.[[Key]] is not EMPTY, then
273273
if let Some(k) = k {
274-
let v = data.values(gc.nogc())[entry_index].unwrap();
274+
let v = data.values[entry_index].unwrap();
275275
// i. Perform ? Call(callbackfn, thisArg, « e.[[Value]], e.[[Key]], M »).
276276
call_function(
277277
agent,
@@ -289,7 +289,7 @@ impl MapPrototype {
289289
// increased during execution of callbackfn.
290290
// iii. Set numEntries to the number of elements in entries.
291291
m = scoped_m.get(agent).bind(gc.nogc());
292-
num_entries = agent[m].values(gc.nogc()).len();
292+
num_entries = m.get(agent).values.len();
293293
}
294294
}
295295
// 8. Return undefined.
@@ -309,36 +309,44 @@ impl MapPrototype {
309309
// 2. Perform ? RequireInternalSlot(M, [[MapData]]).
310310
let m = require_map_data_internal_slot(agent, this_value, gc)?;
311311

312+
// 3. Set key to CanonicalizeKeyedCollectionKey(key).
313+
let key = canonicalize_keyed_collection_key(&agent.heap.numbers, key);
314+
let key_hash = {
315+
let Heap {
316+
bigints,
317+
numbers,
318+
strings,
319+
..
320+
} = &agent.heap;
321+
let primitive_heap = PrimitiveHeap::new(bigints, numbers, strings);
322+
let mut hasher = AHasher::default();
323+
key.hash(&primitive_heap, &mut hasher);
324+
hasher.finish()
325+
};
326+
312327
let Heap {
313328
bigints,
314329
numbers,
315330
strings,
316331
maps,
317332
..
318-
} = &agent.heap;
333+
} = &mut agent.heap;
319334
let primitive_heap = PrimitiveHeap::new(bigints, numbers, strings);
320335

321-
// 3. Set key to CanonicalizeKeyedCollectionKey(key).
322-
let key = canonicalize_keyed_collection_key(agent, key);
323-
let key_hash = {
324-
let mut hasher = AHasher::default();
325-
key.hash(agent, &mut hasher);
326-
hasher.finish()
327-
};
328336
// 4. For each Record { [[Key]], [[Value]] } p of M.[[MapData]], do
329-
let MapHeapData {
337+
let MapHeapDataMut {
330338
values,
331339
keys,
332340
map_data,
333341
..
334-
} = &maps[m].borrow(&primitive_heap);
342+
} = m.get_direct_mut(maps);
335343
let map_data = map_data.borrow();
336344

337345
// a. If p.[[Key]] is not EMPTY and SameValue(p.[[Key]], key) is true, return p.[[Value]].
338346
let found = map_data.find(key_hash, |hash_equal_index| {
339347
let found_key = keys[*hash_equal_index as usize].unwrap();
340348
// Quick check: Equal keys have the same value.
341-
found_key == key || same_value(agent, found_key, key)
349+
found_key == key || same_value(&primitive_heap, found_key, key)
342350
});
343351
if let Some(index) = found {
344352
Ok(values[*index as usize].unwrap().unbind().bind(gc))
@@ -378,7 +386,7 @@ impl MapPrototype {
378386
hasher.finish()
379387
};
380388
// 4. For each Record { [[Key]], [[Value]] } p of M.[[MapData]], do
381-
let MapHeapData { keys, map_data, .. } = &mut maps[m].borrow_mut(&primitive_heap);
389+
let MapHeapDataMut { keys, map_data, .. } = m.get_direct_mut(maps);
382390
let map_data = map_data.get_mut();
383391

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

436-
let MapHeapData {
444+
let MapHeapDataMut {
437445
keys,
438446
values,
439447
map_data,
440448
..
441-
} = &mut maps[m].borrow_mut(&primitive_heap);
449+
} = m.get_direct_mut(maps);
442450
let map_data = map_data.get_mut();
443451

444452
let hasher = |value: Value| {
@@ -490,7 +498,7 @@ impl MapPrototype {
490498
) -> JsResult<'gc, Value<'gc>> {
491499
let gc = gc.into_nogc();
492500
let m = require_map_data_internal_slot(agent, this_value, gc)?;
493-
let count = agent[m].size();
501+
let count = m.get(agent).size();
494502
Ok(count.into())
495503
}
496504

0 commit comments

Comments
 (0)