Browse Source

Proxy static shape and remove old builtin code

optimization/static-shapes
Haled Odat 2 years ago
parent
commit
e89803a51f
  1. 6
      boa_builtins/build.rs
  2. 185
      boa_engine/src/builtins/mod.rs
  3. 7
      boa_engine/src/builtins/proxy/mod.rs
  4. 12
      boa_engine/src/context/intrinsics.rs
  5. 7
      boa_engine/src/object/shape/mod.rs
  6. 9
      boa_engine/src/object/shape/unique_shape.rs

6
boa_builtins/build.rs

@ -1087,6 +1087,12 @@ fn main() -> io::Result<()> {
.property(WellKnown::ToStringTag, Attribute::CONFIGURABLE) .property(WellKnown::ToStringTag, Attribute::CONFIGURABLE)
.build(file)?; .build(file)?;
BuiltInBuilder::new(&context, "PROXY_CONSTRUCTOR")
.property(utf16!("length"), Attribute::CONFIGURABLE)
.property(utf16!("name"), Attribute::CONFIGURABLE)
.method(utf16!("revocable"))
.build(file)?;
#[cfg(feature = "intl")] #[cfg(feature = "intl")]
{ {
BuiltInBuilder::new(&context, "INTL_OBJECT") BuiltInBuilder::new(&context, "INTL_OBJECT")

185
boa_engine/src/builtins/mod.rs

@ -97,11 +97,8 @@ use crate::{
js_string, js_string,
native_function::{NativeFunction, NativeFunctionPointer}, native_function::{NativeFunction, NativeFunctionPointer},
object::{ object::{
shape::{ shape::static_shape::StaticShape, JsFunction, JsObject, JsPrototype, Object, ObjectData,
property_table::PropertyTableInner, slot::SlotAttributes, static_shape::StaticShape, ObjectKind, CONSTRUCTOR, PROTOTYPE,
},
FunctionBinding, JsFunction, JsObject, JsPrototype, Object, ObjectData, ObjectKind,
CONSTRUCTOR, PROTOTYPE,
}, },
property::{Attribute, PropertyDescriptor, PropertyKey}, property::{Attribute, PropertyDescriptor, PropertyKey},
realm::Realm, realm::Realm,
@ -635,8 +632,6 @@ impl<'ctx> BuiltInBuilder {
prototype_shape: &'static RawStaticShape, prototype_shape: &'static RawStaticShape,
) -> BuiltInBuilderConstructorStaticShape<'ctx> { ) -> BuiltInBuilderConstructorStaticShape<'ctx> {
let constructor = SC::STANDARD_CONSTRUCTOR(realm.intrinsics().constructors()); let constructor = SC::STANDARD_CONSTRUCTOR(realm.intrinsics().constructors());
// println!("{constructor_shape:#?}");
// println!("{prototype_shape:#?}");
let mut this = BuiltInBuilderConstructorStaticShape { let mut this = BuiltInBuilderConstructorStaticShape {
realm, realm,
function: SC::constructor, function: SC::constructor,
@ -667,6 +662,35 @@ impl<'ctx> BuiltInBuilder {
this this
} }
fn from_standard_constructor_static_shape_without_prototype<SC: BuiltInConstructor>(
realm: &'ctx Realm,
constructor_shape: &'static RawStaticShape,
) -> BuiltInBuilderConstructorStaticShape<'ctx> {
let constructor = SC::STANDARD_CONSTRUCTOR(realm.intrinsics().constructors());
let mut this = BuiltInBuilderConstructorStaticShape {
realm,
function: SC::constructor,
constructor_property_index: 0,
constructor_shape,
constructor_storage: Vec::with_capacity(constructor_shape.storage_len),
constructor_object: constructor.constructor(),
prototype_property_index: 0,
prototype_shape: &boa_builtins::EMPTY_OBJECT_STATIC_SHAPE,
prototype_storage: Vec::default(),
prototype_object: constructor.prototype(),
__proto__: Some(realm.intrinsics().constructors().function().prototype()),
inherits: Some(realm.intrinsics().constructors().object().prototype()),
};
this.constructor_storage.push(SC::LENGTH.into());
this.constructor_storage.push(js_string!(SC::NAME).into());
this
}
} }
impl BuiltInBuilderConstructorStaticShape<'_> { impl BuiltInBuilderConstructorStaticShape<'_> {
@ -822,6 +846,47 @@ impl BuiltInBuilderConstructorStaticShape<'_> {
.push(self.inherits.map(JsValue::new).unwrap_or_default()); .push(self.inherits.map(JsValue::new).unwrap_or_default());
prototype.properties_mut().storage = self.prototype_storage; prototype.properties_mut().storage = self.prototype_storage;
} }
fn build_without_prototype(mut self) {
debug_assert_eq!(
self.constructor_storage.len() + 1,
self.constructor_shape.storage_len
);
debug_assert_eq!(
self.constructor_storage.capacity(),
self.constructor_shape.storage_len
);
let function = function::Function::new(
function::FunctionKind::Native {
function: NativeFunction::from_fn_ptr(self.function),
constructor: (true).then_some(function::ConstructorKind::Base),
},
self.realm.clone(),
);
let mut object = self.constructor_object.borrow_mut();
*object.kind_mut() = ObjectKind::Function(function);
object.properties_mut().shape = StaticShape::new(self.constructor_shape).into();
self.constructor_storage.push(
self.__proto__
.unwrap_or_else(|| {
self.realm
.intrinsics()
.constructors()
.function()
.prototype()
})
.into(),
);
object.properties_mut().storage = self.constructor_storage;
debug_assert_eq!(self.prototype_storage.len(), 0);
debug_assert!(std::ptr::eq(
self.prototype_shape,
&boa_builtins::EMPTY_OBJECT_STATIC_SHAPE
));
}
} }
struct BuiltInBuilderStaticShape<'ctx> { struct BuiltInBuilderStaticShape<'ctx> {
@ -909,94 +974,6 @@ impl<'ctx> BuiltInBuilder {
} }
} }
struct BuiltInConstructorWithPrototype<'ctx> {
realm: &'ctx Realm,
function: NativeFunctionPointer,
name: JsString,
length: usize,
object_property_table: PropertyTableInner,
object_storage: Vec<JsValue>,
object: JsObject,
__proto__: JsPrototype,
}
impl BuiltInConstructorWithPrototype<'_> {
/// Adds a new static method to the builtin object.
fn static_method<B>(
mut self,
function: NativeFunctionPointer,
binding: B,
length: usize,
) -> Self
where
B: Into<FunctionBinding>,
{
let binding = binding.into();
let function = BuiltInBuilder::callable(self.realm, function)
.name(binding.name)
.length(length)
.build();
debug_assert!(self
.object_property_table
.map
.get(&binding.binding)
.is_none());
self.object_property_table.insert(
binding.binding,
SlotAttributes::WRITABLE | SlotAttributes::CONFIGURABLE,
);
self.object_storage.push(function.into());
self
}
/// Adds a new static data property to the builtin object.
fn static_property<K, V>(mut self, key: K, value: V, attribute: Attribute) -> Self
where
K: Into<PropertyKey>,
V: Into<JsValue>,
{
let key = key.into();
debug_assert!(self.object_property_table.map.get(&key).is_none());
self.object_property_table
.insert(key, SlotAttributes::from_bits_truncate(attribute.bits()));
self.object_storage.push(value.into());
self
}
fn build_without_prototype(mut self) {
let function = function::Function::new(
function::FunctionKind::Native {
function: NativeFunction::from_fn_ptr(self.function),
constructor: (true).then_some(function::ConstructorKind::Base),
},
self.realm.clone(),
);
let length = self.length;
let name = self.name.clone();
self = self.static_property("length", length, Attribute::CONFIGURABLE);
self = self.static_property("name", name, Attribute::CONFIGURABLE);
let mut object = self.object.borrow_mut();
*object.kind_mut() = ObjectKind::Function(function);
object
.properties_mut()
.shape
.as_unique()
.expect("The object should have a unique shape")
.override_internal(self.object_property_table, self.__proto__);
let object_old_storage =
std::mem::replace(&mut object.properties_mut().storage, self.object_storage);
debug_assert_eq!(object_old_storage.len(), 0);
}
}
struct BuiltInCallable<'ctx> { struct BuiltInCallable<'ctx> {
realm: &'ctx Realm, realm: &'ctx Realm,
function: NativeFunctionPointer, function: NativeFunctionPointer,
@ -1062,21 +1039,3 @@ impl<'ctx> BuiltInBuilder {
} }
} }
} }
impl<'ctx> BuiltInBuilder {
fn from_standard_constructor<SC: BuiltInConstructor>(
realm: &'ctx Realm,
) -> BuiltInConstructorWithPrototype<'ctx> {
let constructor = SC::STANDARD_CONSTRUCTOR(realm.intrinsics().constructors());
BuiltInConstructorWithPrototype {
realm,
function: SC::constructor,
name: js_string!(SC::NAME),
length: SC::LENGTH,
object_property_table: PropertyTableInner::default(),
object_storage: Vec::default(),
object: constructor.constructor(),
__proto__: Some(realm.intrinsics().constructors().function().prototype()),
}
}
}

7
boa_engine/src/builtins/proxy/mod.rs

@ -35,8 +35,11 @@ impl IntrinsicObject for Proxy {
fn init(realm: &Realm) { fn init(realm: &Realm) {
let _timer = Profiler::global().start_event(Self::NAME, "init"); let _timer = Profiler::global().start_event(Self::NAME, "init");
BuiltInBuilder::from_standard_constructor::<Self>(realm) BuiltInBuilder::from_standard_constructor_static_shape_without_prototype::<Self>(
.static_method(Self::revocable, "revocable", 2) realm,
&boa_builtins::PROXY_CONSTRUCTOR_STATIC_SHAPE,
)
.static_method(Self::revocable, 2)
.build_without_prototype(); .build_without_prototype();
} }

12
boa_engine/src/context/intrinsics.rs

@ -167,14 +167,14 @@ impl Default for StandardConstructors {
object: StandardConstructor::with_prototype( object: StandardConstructor::with_prototype(
JsObject::from_data_and_empty_static_shape(ObjectData::object_prototype()), JsObject::from_data_and_empty_static_shape(ObjectData::object_prototype()),
), ),
async_generator_function: StandardConstructor::default(), async_generator_function: StandardConstructor::default_static_shape(),
proxy: StandardConstructor::default(), proxy: StandardConstructor::default_static_shape(),
date: StandardConstructor::default_static_shape(), date: StandardConstructor::default_static_shape(),
function: StandardConstructor { function: StandardConstructor {
constructor: JsFunction::empty_intrinsic_function_static_shape(true), constructor: JsFunction::empty_intrinsic_function_static_shape(true),
prototype: JsFunction::empty_intrinsic_function_static_shape(false).into(), prototype: JsFunction::empty_intrinsic_function_static_shape(false).into(),
}, },
async_function: StandardConstructor::default(), async_function: StandardConstructor::default_static_shape(),
generator_function: StandardConstructor::default_static_shape(), generator_function: StandardConstructor::default_static_shape(),
array: StandardConstructor::with_prototype(JsObject::from_data_and_empty_static_shape( array: StandardConstructor::with_prototype(JsObject::from_data_and_empty_static_shape(
ObjectData::array(), ObjectData::array(),
@ -225,11 +225,11 @@ impl Default for StandardConstructors {
#[cfg(feature = "intl")] #[cfg(feature = "intl")]
collator: StandardConstructor::default_static_shape(), collator: StandardConstructor::default_static_shape(),
#[cfg(feature = "intl")] #[cfg(feature = "intl")]
list_format: StandardConstructor::default(), list_format: StandardConstructor::default_static_shape(),
#[cfg(feature = "intl")] #[cfg(feature = "intl")]
locale: StandardConstructor::default(), locale: StandardConstructor::default_static_shape(),
#[cfg(feature = "intl")] #[cfg(feature = "intl")]
segmenter: StandardConstructor::default(), segmenter: StandardConstructor::default_static_shape(),
} }
} }
} }

7
boa_engine/src/object/shape/mod.rs

@ -106,13 +106,6 @@ impl Shape {
matches!(self.inner, Inner::Static(_)) matches!(self.inner, Inner::Static(_))
} }
pub(crate) const fn as_unique(&self) -> Option<&UniqueShape> {
if let Inner::Unique(shape) = &self.inner {
return Some(shape);
}
None
}
/// Create an insert property transitions returning the new transitioned [`Shape`]. /// Create an insert property transitions returning the new transitioned [`Shape`].
/// ///
/// NOTE: This assumes that there is no property with the given key! /// NOTE: This assumes that there is no property with the given key!

9
boa_engine/src/object/shape/unique_shape.rs

@ -44,15 +44,6 @@ impl UniqueShape {
} }
} }
pub(crate) fn override_internal(
&self,
property_table: PropertyTableInner,
prototype: JsPrototype,
) {
*self.inner.property_table.borrow_mut() = property_table;
*self.inner.prototype.borrow_mut() = prototype;
}
/// Get the prototype of the [`UniqueShape`]. /// Get the prototype of the [`UniqueShape`].
pub(crate) fn prototype(&self) -> JsPrototype { pub(crate) fn prototype(&self) -> JsPrototype {
self.inner.prototype.borrow().clone() self.inner.prototype.borrow().clone()

Loading…
Cancel
Save