diff --git a/boa_engine/src/object/shape/unique_shape.rs b/boa_engine/src/object/shape/unique_shape.rs index 0c56d80bb3e..707900ad4ef 100644 --- a/boa_engine/src/object/shape/unique_shape.rs +++ b/boa_engine/src/object/shape/unique_shape.rs @@ -6,7 +6,10 @@ use std::{ rc::Rc, }; +use bitflags::bitflags; +use boa_ast::property; use boa_gc::{empty_trace, Finalize, Gc, GcRefCell, Trace, WeakGc}; +use indexmap::{IndexMap, IndexSet}; use rustc_hash::FxHashMap; use crate::{ @@ -16,44 +19,69 @@ use crate::{ use super::{JsPrototype, Slot, TransitionKey}; +/// TODO: doc +#[derive(Default, Debug)] +struct Inner { + property_table: RefCell>, +} + +/// TODO: doc #[derive(Default, Debug, Clone)] pub(crate) struct UniqueShape { - property_table: Rc>>, - // /// Properties stored with `String`s a keys. - // string_properties: OrderedHashMap, - - // /// Properties stored with `Symbol`s a keys. - // symbol_properties: OrderedHashMap, + inner: Rc, } impl UniqueShape { + /// Create shape from a pre initialized property table. + fn new(property_table: IndexSet) -> Self { + Self { + inner: Rc::new(Inner { + property_table: property_table.into(), + }), + } + } + + /// TODO: doc pub(crate) fn insert_property_transition(&self, key: TransitionKey) -> Self { { - // println!("Unique: insert {}", key.property_key); - let mut property_table = self.property_table.borrow_mut(); - let offset = property_table.len() as u32; - property_table.insert(key.property_key, offset); + let mut property_table = self.inner.property_table.borrow_mut(); + let (index, inserted) = property_table.insert_full(key.property_key); + + debug_assert!(inserted); + debug_assert!(index + 1 == property_table.len()); } self.clone() } + /// TODO: doc pub(crate) fn remove_property_transition(&self, key: &TransitionKey) -> Self { - { - let mut property_table = self.property_table.borrow_mut(); - property_table.remove(&key.property_key); + let mut property_table = self.inner.property_table.borrow_mut(); + let Some((index, _property_key)) = property_table.shift_remove_full(&key.property_key) else { + return self.clone(); + }; + + /// Check if it's the last property, that was deleted, + /// if so delete it and return self + if index == property_table.len() { + return self.clone(); } - // self.clone() - todo!("implement deletion!") + // The property that was deleted was not the last property added. + // Therefore we need to create a new unique shape, + // to invalidateany pointers to this shape i.e inline caches. + let property_table = std::mem::take(&mut *property_table); + Self::new(property_table) } - #[inline] + /// TODO: doc pub(crate) fn lookup(&self, key: &PropertyKey) -> Option { // println!("Unique: lookup {key}"); - let mut property_table = self.property_table.borrow(); - if let Some(index) = property_table.get(key) { - return Some(Slot { index: *index }); + let mut property_table = self.inner.property_table.borrow(); + if let Some(index) = property_table.get_index_of(key) { + return Some(Slot { + index: index as u32, + }); } None