Skip to content

Commit

Permalink
Implement type safe root object shape
Browse files Browse the repository at this point in the history
  • Loading branch information
HalidOdat committed May 18, 2023
1 parent 06161ed commit c3f62f9
Show file tree
Hide file tree
Showing 12 changed files with 64 additions and 23 deletions.
4 changes: 2 additions & 2 deletions boa_engine/benches/full.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Benchmarks of the whole execution engine in Boa.
use boa_engine::{
context::DefaultHooks, object::shape::SharedShape, optimizer::OptimizerOptions, realm::Realm,
context::DefaultHooks, object::shape::RootShape, optimizer::OptimizerOptions, realm::Realm,
Context, Source,
};
use criterion::{criterion_group, criterion_main, Criterion};
Expand All @@ -16,7 +16,7 @@ static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;

fn create_realm(c: &mut Criterion) {
c.bench_function("Create Realm", move |b| {
let root_shape = SharedShape::root();
let root_shape = RootShape::default();
b.iter(|| Realm::create(&DefaultHooks, &root_shape))
});
}
Expand Down
4 changes: 3 additions & 1 deletion boa_engine/src/builtins/weak/weak_ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,11 @@ impl BuiltInConstructor for WeakRef {

// 3. Let weakRef be ? OrdinaryCreateFromConstructor(NewTarget, "%WeakRef.prototype%", « [[WeakRefTarget]] »).
// 5. Set weakRef.[[WeakRefTarget]] to target.
let prototype =
get_prototype_from_constructor(new_target, StandardConstructors::weak_ref, context)?;
let weak_ref = JsObject::from_proto_and_data_with_shared_shape(
context.root_shape(),
get_prototype_from_constructor(new_target, StandardConstructors::weak_ref, context)?,
prototype,
ObjectData::weak_ref(WeakGc::new(target.inner())),
);

Expand Down
4 changes: 3 additions & 1 deletion boa_engine/src/builtins/weak_map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,11 @@ impl BuiltInConstructor for WeakMap {

// 2. Let map be ? OrdinaryCreateFromConstructor(NewTarget, "%WeakMap.prototype%", « [[WeakMapData]] »).
// 3. Set map.[[WeakMapData]] to a new empty List.
let prototype =
get_prototype_from_constructor(new_target, StandardConstructors::weak_map, context)?;
let map = JsObject::from_proto_and_data_with_shared_shape(
context.root_shape(),
get_prototype_from_constructor(new_target, StandardConstructors::weak_map, context)?,
prototype,
ObjectData::weak_map(boa_gc::WeakMap::new()),
);

Expand Down
4 changes: 3 additions & 1 deletion boa_engine/src/builtins/weak_set/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,11 @@ impl BuiltInConstructor for WeakSet {

// 2. Let set be ? OrdinaryCreateFromConstructor(NewTarget, "%WeakSet.prototype%", « [[WeakSetData]] »).
// 3. Set set.[[WeakSetData]] to a new empty List.
let prototype =
get_prototype_from_constructor(new_target, StandardConstructors::weak_set, context)?;
let weak_set = JsObject::from_proto_and_data_with_shared_shape(
context.root_shape(),
get_prototype_from_constructor(new_target, StandardConstructors::weak_set, context)?,
prototype,
ObjectData::weak_set(WeakMap::new()),
);

Expand Down
8 changes: 5 additions & 3 deletions boa_engine/src/context/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use boa_gc::{Finalize, Trace};
use crate::{
builtins::{iterable::IteratorPrototypes, uri::UriFunctions},
object::{
shape::shared_shape::{template::ObjectTemplate, SharedShape},
shape::{shared_shape::template::ObjectTemplate, RootShape},
JsFunction, JsObject, ObjectData, CONSTRUCTOR, PROTOTYPE,
},
property::{Attribute, PropertyKey},
Expand All @@ -27,7 +27,7 @@ pub struct Intrinsics {
}

impl Intrinsics {
pub(crate) fn new(root_shape: &SharedShape) -> Self {
pub(crate) fn new(root_shape: &RootShape) -> Self {
let constructors = StandardConstructors::default();
let templates = ObjectTemplates::new(root_shape, &constructors);

Expand Down Expand Up @@ -1004,7 +1004,9 @@ pub(crate) struct ObjectTemplates {
}

impl ObjectTemplates {
pub(crate) fn new(root_shape: &SharedShape, constructors: &StandardConstructors) -> Self {
pub(crate) fn new(root_shape: &RootShape, constructors: &StandardConstructors) -> Self {
let root_shape = root_shape.shape();

// pre-initialize used shapes.
let ordinary_object =
ObjectTemplate::with_prototype(root_shape, constructors.object().prototype());
Expand Down
12 changes: 7 additions & 5 deletions boa_engine/src/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use crate::{
job::{JobQueue, NativeJob, SimpleJobQueue},
module::{ModuleLoader, SimpleModuleLoader},
native_function::NativeFunction,
object::{shape::SharedShape, FunctionObjectBuilder, JsObject},
object::{shape::RootShape, FunctionObjectBuilder, JsObject},
optimizer::{Optimizer, OptimizerOptions, OptimizerStatistics},
property::{Attribute, PropertyDescriptor, PropertyKey},
realm::Realm,
Expand Down Expand Up @@ -109,7 +109,7 @@ pub struct Context<'host> {
module_loader: MaybeShared<'host, dyn ModuleLoader>,

optimizer_options: OptimizerOptions,
root_shape: SharedShape,
root_shape: RootShape,

/// Unique identifier for each parser instance used during the context lifetime.
parser_identifier: u32,
Expand Down Expand Up @@ -496,8 +496,10 @@ impl<'host> Context<'host> {
std::mem::replace(&mut self.realm, realm)
}

pub(crate) fn root_shape(&self) -> SharedShape {
self.root_shape.clone()
/// Get the [`RootShape`].
#[inline]
pub const fn root_shape(&self) -> &RootShape {
&self.root_shape
}

/// Gets the host hooks.
Expand Down Expand Up @@ -916,7 +918,7 @@ impl<'icu, 'hooks, 'queue, 'module> ContextBuilder<'icu, 'hooks, 'queue, 'module
'queue: 'host,
'module: 'host,
{
let root_shape = SharedShape::root();
let root_shape = RootShape::default();

let host_hooks = self.host_hooks.unwrap_or_else(|| {
let hooks: &dyn HostHooks = &DefaultHooks;
Expand Down
6 changes: 3 additions & 3 deletions boa_engine/src/object/jsobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use super::{
internal_methods::{InternalObjectMethods, ARRAY_EXOTIC_INTERNAL_METHODS},
shape::{shared_shape::SharedShape, Shape},
shape::RootShape,
JsPrototype, NativeObject, Object, PropertyMap,
};
use crate::{
Expand Down Expand Up @@ -127,7 +127,7 @@ impl JsObject {
///
/// [`OrdinaryObjectCreate`]: https://tc39.es/ecma262/#sec-ordinaryobjectcreate
pub(crate) fn from_proto_and_data_with_shared_shape<O: Into<Option<Self>>>(
root_shape: SharedShape,
root_shape: &RootShape,
prototype: O,
data: ObjectData,
) -> Self {
Expand All @@ -136,7 +136,7 @@ impl JsObject {
object: GcRefCell::new(Object {
kind: data.kind,
properties: PropertyMap::from_prototype_with_shared_shape(
Shape::shared(root_shape),
root_shape,
prototype.into(),
),
extensible: true,
Expand Down
11 changes: 7 additions & 4 deletions boa_engine/src/object/property_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use super::{
property_table::PropertyTableInner,
shared_shape::TransitionKey,
slot::{Slot, SlotAttributes},
ChangeTransitionAction, Shape, UniqueShape,
ChangeTransitionAction, RootShape, Shape, UniqueShape,
},
JsPrototype, ObjectStorage, PropertyDescriptor, PropertyKey,
};
Expand Down Expand Up @@ -252,11 +252,14 @@ impl PropertyMap {
/// Construct a [`PropertyMap`] from with the given prototype with a shared shape [`Shape`].
#[must_use]
#[inline]
pub fn from_prototype_with_shared_shape(mut root_shape: Shape, prototype: JsPrototype) -> Self {
root_shape = root_shape.change_prototype_transition(prototype);
pub fn from_prototype_with_shared_shape(
root_shape: &RootShape,
prototype: JsPrototype,
) -> Self {
let shape = root_shape.shape().change_prototype_transition(prototype);
Self {
indexed_properties: IndexedProperties::default(),
shape: root_shape,
shape: Shape::shared(shape),
storage: Vec::default(),
}
}
Expand Down
2 changes: 2 additions & 0 deletions boa_engine/src/object/shape/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
//! Implements object shapes.
pub(crate) mod property_table;
mod root_shape;
pub(crate) mod shared_shape;
pub(crate) mod slot;
pub(crate) mod unique_shape;

pub use root_shape::RootShape;
pub use shared_shape::SharedShape;
pub(crate) use unique_shape::UniqueShape;

Expand Down
26 changes: 26 additions & 0 deletions boa_engine/src/object/shape/root_shape.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use boa_macros::{Finalize, Trace};

use super::SharedShape;

/// Represent the root shape that [`SharedShape`] transitions start from.
///
/// This is a wrapper around [`SharedShape`] that ensures that the shape the root shape.
#[derive(Debug, Clone, Trace, Finalize)]
pub struct RootShape {
shape: SharedShape,
}

impl Default for RootShape {
fn default() -> Self {
Self {
shape: SharedShape::root(),
}
}
}

impl RootShape {
/// Gets the inner [`SharedShape`].
pub(crate) const fn shape(&self) -> &SharedShape {
&self.shape
}
}
2 changes: 1 addition & 1 deletion boa_engine/src/object/shape/shared_shape/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ impl SharedShape {

/// Create a root [`SharedShape`].
#[must_use]
pub fn root() -> Self {
pub(crate) fn root() -> Self {
Self::new(Inner {
forward_transitions: ForwardTransition::default(),
prototype: None,
Expand Down
4 changes: 2 additions & 2 deletions boa_engine/src/realm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::{
context::{intrinsics::Intrinsics, HostHooks},
environments::DeclarativeEnvironment,
module::Module,
object::{shape::shared_shape::SharedShape, JsObject},
object::{shape::RootShape, JsObject},
JsString,
};
use boa_gc::{Finalize, Gc, GcRefCell, Trace};
Expand Down Expand Up @@ -57,7 +57,7 @@ struct Inner {
impl Realm {
/// Create a new Realm.
#[inline]
pub fn create(hooks: &dyn HostHooks, root_shape: &SharedShape) -> Self {
pub fn create(hooks: &dyn HostHooks, root_shape: &RootShape) -> Self {
let _timer = Profiler::global().start_event("Realm::create", "realm");

let intrinsics = Intrinsics::new(root_shape);
Expand Down

0 comments on commit c3f62f9

Please sign in to comment.