Skip to content

Commit

Permalink
Direct length access on arrays
Browse files Browse the repository at this point in the history
  • Loading branch information
HalidOdat committed Apr 11, 2023
1 parent 1f90e70 commit d9a712c
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 18 deletions.
54 changes: 38 additions & 16 deletions boa_engine/src/builtins/array/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,29 @@ impl BuiltInConstructor for Array {
}

impl Array {
/// Optimized helper function, that sets the length of the array.
fn set_length(o: &JsObject, len: u64, context: &mut Context<'_>) -> JsResult<()> {
{
let mut borrowed_object = o.borrow_mut();
if borrowed_object.is_array()
&& len < (2u64.pow(32) - 1)
&& borrowed_object.properties().shape.to_addr_usize()
== context
.intrinsics()
.templates()
.array()
.shape()
.to_addr_usize()
{
// NOTE: The "length" property is the first element.
borrowed_object.properties_mut().storage[0] = JsValue::new(len);
return Ok(());
}
}

o.set(utf16!("length"), len, true, context).map(|_| ())
}

/// Utility for constructing `Array` objects.
///
/// More information:
Expand Down Expand Up @@ -655,7 +678,7 @@ impl Array {
}

// 8. Perform ? Set(A, "length", lenNumber, true).
a.set(utf16!("length"), len, true, context)?;
Self::set_length(&a, len as u64, context)?;

// 9. Return A.
Ok(a.into())
Expand Down Expand Up @@ -779,7 +802,7 @@ impl Array {
}
}
// 6. Perform ? Set(A, "length", 𝔽(n), true).
arr.set(utf16!("length"), n, true, context)?;
Self::set_length(&arr, n, context)?;

// 7. Return A.
Ok(JsValue::new(arr))
Expand Down Expand Up @@ -824,7 +847,8 @@ impl Array {
len += 1;
}
// 6. Perform ? Set(O, "length", 𝔽(len), true).
o.set(utf16!("length"), len, true, context)?;
Self::set_length(&o, len, context)?;

// 7. Return 𝔽(len).
Ok(len.into())
}
Expand All @@ -851,7 +875,8 @@ impl Array {
// 3. If len = 0, then
if len == 0 {
// a. Perform ? Set(O, "length", +0𝔽, true).
o.set(utf16!("length"), 0, true, context)?;
Self::set_length(&o, 0, context)?;

// b. Return undefined.
Ok(JsValue::undefined())
// 4. Else,
Expand All @@ -866,7 +891,7 @@ impl Array {
// e. Perform ? DeletePropertyOrThrow(O, index).
o.delete_property_or_throw(index, context)?;
// f. Perform ? Set(O, "length", newLen, true).
o.set(utf16!("length"), new_len, true, context)?;
Self::set_length(&o, new_len, context)?;
// g. Return element.
Ok(element)
}
Expand Down Expand Up @@ -1107,7 +1132,8 @@ impl Array {
// 3. If len = 0, then
if len == 0 {
// a. Perform ? Set(O, "length", +0𝔽, true).
o.set(utf16!("length"), 0, true, context)?;
Self::set_length(&o, 0, context)?;

// b. Return undefined.
return Ok(JsValue::undefined());
}
Expand Down Expand Up @@ -1139,7 +1165,7 @@ impl Array {
// 7. Perform ? DeletePropertyOrThrow(O, ! ToString(𝔽(len - 1))).
o.delete_property_or_throw(len - 1, context)?;
// 8. Perform ? Set(O, "length", 𝔽(len - 1), true).
o.set(utf16!("length"), len - 1, true, context)?;
Self::set_length(&o, len - 1, context)?;
// 9. Return first.
Ok(first)
}
Expand Down Expand Up @@ -1209,7 +1235,8 @@ impl Array {
}
}
// 5. Perform ? Set(O, "length", 𝔽(len + argCount), true).
o.set(utf16!("length"), len + arg_count, true, context)?;
Self::set_length(&o, len + arg_count, context)?;

// 6. Return 𝔽(len + argCount).
Ok((len + arg_count).into())
}
Expand Down Expand Up @@ -2088,7 +2115,7 @@ impl Array {
}

// 15. Perform ? Set(A, "length", 𝔽(n), true).
a.set(utf16!("length"), n, true, context)?;
Self::set_length(&a, n, context)?;

// 16. Return A.
Ok(a.into())
Expand Down Expand Up @@ -2243,7 +2270,7 @@ impl Array {
}

// 14. Perform ? Set(A, "length", 𝔽(actualDeleteCount), true).
arr.set(utf16!("length"), actual_delete_count, true, context)?;
Self::set_length(&arr, actual_delete_count, context)?;

// 15. Let itemCount be the number of elements in items.
let item_count = items.len() as u64;
Expand Down Expand Up @@ -2328,12 +2355,7 @@ impl Array {
}

// 20. Perform ? Set(O, "length", 𝔽(len - actualDeleteCount + itemCount), true).
o.set(
utf16!("length"),
len - actual_delete_count + item_count,
true,
context,
)?;
Self::set_length(&o, len - actual_delete_count + item_count, context)?;

// 21. Return A.
Ok(JsValue::from(arr))
Expand Down
2 changes: 2 additions & 0 deletions boa_engine/src/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,8 @@ impl<'icu, 'hooks, 'queue> ContextBuilder<'icu, 'hooks, 'queue> {
let realm = Realm::create(host_hooks, &root_shape);
let vm = Vm::new(realm.environment().clone());

let root_shape = SharedShape::root();

let mut context = Context {
realm,
interner: self.interner.unwrap_or_default(),
Expand Down
14 changes: 14 additions & 0 deletions boa_engine/src/object/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,20 @@ impl JsObject {
/// [spec]: https://tc39.es/ecma262/#sec-lengthofarraylike
pub(crate) fn length_of_array_like(&self, context: &mut Context<'_>) -> JsResult<u64> {
// 1. Assert: Type(obj) is Object.

// NOTE: This is an optimization, most of the cases that `LengthOfArrayLike` will be called
// is for arrays. The "length" property of an array is stored in the first index.
{
let borrowed_object = self.borrow();
if borrowed_object.is_array() {
// NOTE: using `to_u32` instead of `to_length` is an optimization,
// since arrays are limmited to [0, 2^32 - 1] range.
return borrowed_object.properties().storage[0]
.to_u32(context)
.map(u64::from);
}
}

// 2. Return ℝ(? ToLength(? Get(obj, "length"))).
self.get(utf16!("length"), context)?.to_length(context)
}
Expand Down
7 changes: 5 additions & 2 deletions boa_engine/src/object/shape/shared_shape/template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ impl ObjectTemplate {
self
}

/// Returns the inner shape of the [`ObjectTemplate`].
pub(crate) const fn shape(&self) -> &SharedShape {
&self.shape
}

/// Add a data property to the [`ObjectTemplate`].
///
/// This assumes that the property with the given key was not previously set
Expand All @@ -58,7 +63,6 @@ impl ObjectTemplate {
property_key: key,
attributes,
});

self
}

Expand Down Expand Up @@ -97,7 +101,6 @@ impl ObjectTemplate {
property_key: key,
attributes,
});

self
}

Expand Down

0 comments on commit d9a712c

Please sign in to comment.