Skip to content

Commit c4eb484

Browse files
authored
feat(ecmascript): WeakMap and GC ephemerons (#902)
* feat(ecmascript): WeakMap * perf(gc): Store mark bits in a single allocation * feat(gc): Ephemerons * chore: update dylint and nightly version
1 parent 5f43606 commit c4eb484

File tree

35 files changed

+2709
-2286
lines changed

35 files changed

+2709
-2286
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ jobs:
3737
- name: Install Rust toolchain
3838
uses: dtolnay/rust-toolchain@nightly
3939
with:
40-
toolchain: nightly-2025-05-14
40+
toolchain: nightly-2025-10-31
4141
components: rustfmt, clippy, llvm-tools-preview, rustc-dev
4242
- name: Cache on ${{ github.ref_name }}
4343
uses: Swatinem/rust-cache@v2
@@ -52,7 +52,7 @@ jobs:
5252
- name: Clippy
5353
run: |
5454
cargo +stable clippy --all-targets -- -D warnings
55-
cargo +nightly-2025-05-14 clippy --all-targets --all-features -- -D warnings
55+
cargo +nightly-2025-10-31 clippy --all-targets --all-features -- -D warnings
5656
- name: Dylint tests
5757
working-directory: nova_lint
5858
run: cargo test

nova_lint/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ name = "gc_scope_is_only_passed_by_value"
2525
path = "ui/gc_scope_is_only_passed_by_value.rs"
2626

2727
[dependencies]
28-
clippy_utils = { git = "https://github.com/rust-lang/rust-clippy", rev = "0450db33a5d8587f7c1d4b6d233dac963605766b" }
29-
dylint_linting = { version = "4.1.0", features = ["constituent"] }
28+
clippy_utils = { git = "https://github.com/rust-lang/rust-clippy", rev = "c936595d17413c1f08e162e117e504fb4ed126e4" }
29+
dylint_linting = { version = "5.0.0", features = ["constituent"] }
3030

3131
[dev-dependencies]
32-
dylint_testing = "4.1.0"
32+
dylint_testing = "5.0.0"
3333
nova_vm = { path = "../nova_vm" }
3434

3535
[package.metadata.rust-analyzer]
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
[toolchain]
2-
channel = "nightly-2025-05-14"
2+
channel = "nightly-2025-10-31"
33
components = ["llvm-tools-preview", "rustc-dev"]

nova_vm/src/ecmascript/abstract_operations/operations_on_objects.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -895,7 +895,6 @@ pub(crate) fn set_integrity_level<'a, T: Level>(
895895
// 3. Perform ? DefinePropertyOrThrow(O, k, desc).
896896
define_property_or_throw(agent, o, k.get(agent), desc, gc.reborrow()).unbind()?;
897897
}
898-
i += 1;
899898
}
900899
}
901900
// 6. Return true.

nova_vm/src/ecmascript/builtins/array.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ impl<'a> Array<'a> {
183183
create_array_from_list(agent, elements, gc)
184184
}
185185

186-
pub(crate) fn get_index(self) -> usize {
186+
pub(crate) const fn get_index(self) -> usize {
187187
self.0.into_index()
188188
}
189189

nova_vm/src/ecmascript/builtins/array/data.rs

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -56,23 +56,3 @@ impl HeapMarkAndSweep for ArrayHeapDataMut<'_, 'static> {
5656
object_index.sweep_values(compactions);
5757
}
5858
}
59-
60-
impl HeapMarkAndSweep for ArrayHeapData<'static> {
61-
fn mark_values(&self, queues: &mut WorkQueues) {
62-
let Self {
63-
object_index,
64-
elements,
65-
} = self;
66-
object_index.mark_values(queues);
67-
elements.mark_values(queues);
68-
}
69-
70-
fn sweep_values(&mut self, compactions: &CompactionLists) {
71-
let Self {
72-
object_index,
73-
elements,
74-
} = self;
75-
object_index.sweep_values(compactions);
76-
elements.sweep_values(compactions);
77-
}
78-
}

nova_vm/src/ecmascript/builtins/data_view/data.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use crate::{
1616
heap::{CompactionLists, HeapMarkAndSweep, WorkQueues},
1717
};
1818

19+
#[derive(Debug)]
1920
pub struct DataViewRecord<'a> {
2021
pub(crate) object_index: Option<OrdinaryObject<'a>>,
2122
// TODO: Add a helper function for a u32::MAX value which signifies an a under-construction value:
@@ -41,6 +42,7 @@ impl Default for DataViewRecord<'_> {
4142
}
4243

4344
#[cfg(feature = "shared-array-buffer")]
45+
#[derive(Debug)]
4446
pub struct SharedDataViewRecord<'a> {
4547
pub(crate) object_index: Option<OrdinaryObject<'a>>,
4648
// TODO: Add a helper function for a u32::MAX value which signifies an a under-construction value:

nova_vm/src/ecmascript/builtins/indexed_collections/array_objects/array_iterator_objects/array_iterator.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ impl<'a> ArrayIterator<'a> {
3030
Self(BaseIndex::from_u32_index(0))
3131
}
3232

33-
pub(crate) fn get_index(self) -> usize {
33+
pub(crate) const fn get_index(self) -> usize {
3434
self.0.into_index()
3535
}
3636

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

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -440,14 +440,15 @@ pub fn add_entries_from_iterable_map_constructor<'a>(
440440
/// > element array-like object whose first element is a value that will be used
441441
/// > as a Map key and whose second element is the value to associate with that
442442
/// > key.
443-
pub(crate) fn add_entries_from_iterable<'a>(
443+
pub(crate) fn add_entries_from_iterable<'a, T: Into<Object<'a>> + TryFrom<Object<'a>>>(
444444
agent: &mut Agent,
445-
target: Map,
445+
target: T,
446446
iterable: Value,
447447
adder: Function,
448448
mut gc: GcScope<'a, '_>,
449-
) -> JsResult<'a, Map<'a>> {
449+
) -> JsResult<'a, T> {
450450
let nogc = gc.nogc();
451+
let target: Object = target.into();
451452
let target = target.scope(agent, nogc);
452453
let iterable = iterable.bind(nogc);
453454
let adder = adder.scope(agent, nogc);
@@ -482,7 +483,11 @@ pub(crate) fn add_entries_from_iterable<'a>(
482483
.bind(gc.nogc());
483484
// b. If next is DONE, return target.
484485
let Some(next) = next else {
485-
return Ok(target.get(agent).bind(gc.into_nogc()));
486+
// SAFETY: not shared.
487+
let target = unsafe { target.take(agent).bind(gc.into_nogc()) };
488+
// SAFETY: passed in type is still the same type.
489+
let target = unsafe { T::try_from(target).unwrap_unchecked() };
490+
return Ok(target);
486491
};
487492
// c. If next is not an Object, then
488493
let Ok(next) = Object::try_from(next) else {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ impl MapIterator<'_> {
3434
Self(BaseIndex::from_u32_index(0))
3535
}
3636

37-
pub(crate) fn get_index(self) -> usize {
37+
pub(crate) const fn get_index(self) -> usize {
3838
self.0.into_index()
3939
}
4040

0 commit comments

Comments
 (0)