From e650ab26e123e79ae1eef7179dc51469ee1f0ca1 Mon Sep 17 00:00:00 2001 From: yush-1018 Date: Sun, 15 Mar 2026 02:23:14 +0530 Subject: [PATCH] perf: add dense array fast-path for Array.prototype.unshift --- core/engine/src/builtins/array/mod.rs | 49 +++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/core/engine/src/builtins/array/mod.rs b/core/engine/src/builtins/array/mod.rs index acd695878ea..f07bfb4ba8c 100644 --- a/core/engine/src/builtins/array/mod.rs +++ b/core/engine/src/builtins/array/mod.rs @@ -1291,6 +1291,55 @@ impl Array { .with_message("length + number of arguments exceeds the max safe integer limit") .into()); } + + // Small optimization for arrays using dense properties. + // Mirrors the fast-path in `shift`. + if o.is_array() { + let mut o_borrow = o.borrow_mut(); + let props = &mut o_borrow.properties_mut().indexed_properties; + + let fast_path_done = match props { + IndexedProperties::DenseI32(dense) if len <= dense.len() as u64 => { + // Only take the fast path if ALL new items are i32. + let all_i32: Option> = args.iter().map(JsValue::as_i32).collect(); + if let Some(items) = all_i32 { + for (i, item) in items.into_iter().enumerate() { + dense.insert(i, item); + } + true + } else { + false + } + } + IndexedProperties::DenseF64(dense) if len <= dense.len() as u64 => { + let all_f64: Option> = + args.iter().map(JsValue::as_number).collect(); + if let Some(items) = all_f64 { + for (i, item) in items.into_iter().enumerate() { + dense.insert(i, item); + } + true + } else { + false + } + } + IndexedProperties::DenseElement(dense) if len <= dense.len() as u64 => { + for (i, item) in args.iter().enumerate() { + dense.insert(i, item.clone()); + } + true + } + _ => false, + }; + + drop(o_borrow); + + if fast_path_done { + Self::set_length(&o, len + arg_count, context)?; + return Ok((len + arg_count).into()); + } + } + // b. Let k be len. let mut k = len; // c. Repeat, while k > 0,