Skip to content

Commit

Permalink
Proxy static shape and remove old builtin code
Browse files Browse the repository at this point in the history
  • Loading branch information
HalidOdat committed May 27, 2023
1 parent 7907c49 commit dbff374
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 138 deletions.
6 changes: 6 additions & 0 deletions boa_builtins/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1087,6 +1087,12 @@ fn main() -> io::Result<()> {
.property(WellKnown::ToStringTag, Attribute::CONFIGURABLE)
.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")]
{
BuiltInBuilder::new(&context, "INTL_OBJECT")
Expand Down
185 changes: 72 additions & 113 deletions boa_engine/src/builtins/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,8 @@ use crate::{
js_string,
native_function::{NativeFunction, NativeFunctionPointer},
object::{
shape::{
property_table::PropertyTableInner, slot::SlotAttributes, static_shape::StaticShape,
},
FunctionBinding, JsFunction, JsObject, JsPrototype, Object, ObjectData, ObjectKind,
CONSTRUCTOR, PROTOTYPE,
shape::static_shape::StaticShape, JsFunction, JsObject, JsPrototype, Object, ObjectData,
ObjectKind, CONSTRUCTOR, PROTOTYPE,
},
property::{Attribute, PropertyDescriptor, PropertyKey},
realm::Realm,
Expand Down Expand Up @@ -635,8 +632,6 @@ impl<'ctx> BuiltInBuilder {
prototype_shape: &'static RawStaticShape,
) -> BuiltInBuilderConstructorStaticShape<'ctx> {
let constructor = SC::STANDARD_CONSTRUCTOR(realm.intrinsics().constructors());
// println!("{constructor_shape:#?}");
// println!("{prototype_shape:#?}");
let mut this = BuiltInBuilderConstructorStaticShape {
realm,
function: SC::constructor,
Expand Down Expand Up @@ -667,6 +662,35 @@ impl<'ctx> BuiltInBuilder {

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<'_> {
Expand Down Expand Up @@ -822,6 +846,47 @@ impl BuiltInBuilderConstructorStaticShape<'_> {
.push(self.inherits.map(JsValue::new).unwrap_or_default());
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> {
Expand Down Expand Up @@ -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> {
realm: &'ctx Realm,
function: NativeFunctionPointer,
Expand Down Expand Up @@ -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()),
}
}
}
9 changes: 6 additions & 3 deletions boa_engine/src/builtins/proxy/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,12 @@ impl IntrinsicObject for Proxy {
fn init(realm: &Realm) {
let _timer = Profiler::global().start_event(Self::NAME, "init");

BuiltInBuilder::from_standard_constructor::<Self>(realm)
.static_method(Self::revocable, "revocable", 2)
.build_without_prototype();
BuiltInBuilder::from_standard_constructor_static_shape_without_prototype::<Self>(
realm,
&boa_builtins::PROXY_CONSTRUCTOR_STATIC_SHAPE,
)
.static_method(Self::revocable, 2)
.build_without_prototype();
}

fn get(intrinsics: &Intrinsics) -> JsObject {
Expand Down
12 changes: 6 additions & 6 deletions boa_engine/src/context/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,14 +167,14 @@ impl Default for StandardConstructors {
object: StandardConstructor::with_prototype(
JsObject::from_data_and_empty_static_shape(ObjectData::object_prototype()),
),
async_generator_function: StandardConstructor::default(),
proxy: StandardConstructor::default(),
async_generator_function: StandardConstructor::default_static_shape(),
proxy: StandardConstructor::default_static_shape(),
date: StandardConstructor::default_static_shape(),
function: StandardConstructor {
constructor: JsFunction::empty_intrinsic_function_static_shape(true),
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(),
array: StandardConstructor::with_prototype(JsObject::from_data_and_empty_static_shape(
ObjectData::array(),
Expand Down Expand Up @@ -225,11 +225,11 @@ impl Default for StandardConstructors {
#[cfg(feature = "intl")]
collator: StandardConstructor::default_static_shape(),
#[cfg(feature = "intl")]
list_format: StandardConstructor::default(),
list_format: StandardConstructor::default_static_shape(),
#[cfg(feature = "intl")]
locale: StandardConstructor::default(),
locale: StandardConstructor::default_static_shape(),
#[cfg(feature = "intl")]
segmenter: StandardConstructor::default(),
segmenter: StandardConstructor::default_static_shape(),
}
}
}
Expand Down
7 changes: 0 additions & 7 deletions boa_engine/src/object/shape/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,6 @@ impl Shape {
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`].
///
/// NOTE: This assumes that there is no property with the given key!
Expand Down
9 changes: 0 additions & 9 deletions boa_engine/src/object/shape/unique_shape.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`].
pub(crate) fn prototype(&self) -> JsPrototype {
self.inner.prototype.borrow().clone()
Expand Down

0 comments on commit dbff374

Please sign in to comment.