fix: promote 复用 Vm.forwarding,消除 promote 的 HashMap 分配
This commit is contained in:
@@ -2,6 +2,7 @@ use std::collections::HashMap;
|
|||||||
|
|
||||||
use oxide_types::object::JsObject;
|
use oxide_types::object::JsObject;
|
||||||
use oxide_types::value::JsValue;
|
use oxide_types::value::JsValue;
|
||||||
|
use rustc_hash::FxBuildHasher;
|
||||||
|
|
||||||
use crate::builtins::{data_view, map, set, typed_array};
|
use crate::builtins::{data_view, map, set, typed_array};
|
||||||
use crate::vm::Vm;
|
use crate::vm::Vm;
|
||||||
@@ -16,12 +17,15 @@ impl Vm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn promote_object(&mut self, src: *mut JsObject) -> *mut JsObject {
|
pub(crate) fn promote_object(&mut self, src: *mut JsObject) -> *mut JsObject {
|
||||||
let mut forwarding = HashMap::new();
|
let mut forwarding = std::mem::take(&mut self.forwarding);
|
||||||
self.promote_object_inner(src, &mut forwarding)
|
let result = self.promote_object_inner(src, &mut forwarding);
|
||||||
|
forwarding.clear();
|
||||||
|
self.forwarding = forwarding;
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn promote_object_inner(
|
pub(crate) fn promote_object_inner(
|
||||||
&mut self, src: *mut JsObject, forwarding: &mut HashMap<*mut JsObject, *mut JsObject>,
|
&mut self, src: *mut JsObject, forwarding: &mut HashMap<*mut JsObject, *mut JsObject, FxBuildHasher>,
|
||||||
) -> *mut JsObject {
|
) -> *mut JsObject {
|
||||||
if src.is_null() {
|
if src.is_null() {
|
||||||
return src;
|
return src;
|
||||||
@@ -63,7 +67,7 @@ impl Vm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn promote_value_if_epoch_object(
|
pub(crate) fn promote_value_if_epoch_object(
|
||||||
&mut self, value: JsValue, forwarding: &mut HashMap<*mut JsObject, *mut JsObject>,
|
&mut self, value: JsValue, forwarding: &mut HashMap<*mut JsObject, *mut JsObject, FxBuildHasher>,
|
||||||
) -> JsValue {
|
) -> JsValue {
|
||||||
if !value.is_object() {
|
if !value.is_object() {
|
||||||
return value;
|
return value;
|
||||||
@@ -230,4 +234,20 @@ mod tests {
|
|||||||
assert!(!is_epoch_object(&vm, meta.get));
|
assert!(!is_epoch_object(&vm, meta.get));
|
||||||
assert!(!is_epoch_object(&vm, meta.set));
|
assert!(!is_epoch_object(&vm, meta.set));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn promote_clears_forwarding_map() {
|
||||||
|
let mut vm = Vm::new();
|
||||||
|
let first = plain_object(&mut vm);
|
||||||
|
let promoted = vm.promote_object(first);
|
||||||
|
assert!(!promoted.is_null());
|
||||||
|
// The shared forwarding map must be cleared after each promote so a
|
||||||
|
// later promote (or GC sweep) never observes stale old->new mappings.
|
||||||
|
assert!(vm.forwarding.is_empty());
|
||||||
|
|
||||||
|
let second = plain_object(&mut vm);
|
||||||
|
let promoted2 = vm.promote_object(second);
|
||||||
|
assert!(!promoted2.is_null());
|
||||||
|
assert!(vm.forwarding.is_empty());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user