Commit 9ccad33c authored by Z Duong Nguyen-Huu's avatar Z Duong Nguyen-Huu Committed by Commit Bot

Optimize spread call for sealed, frozen objects

Also add mjsunit test for spread call with non-extensible objects

Micro-benchmark JSTests/ObjectFreeze shows ~7x improvement

Before:
SpreadCall
SpreadCall-Numbers(Score): 239

After:
SpreadCall
SpreadCall-Numbers(Score): 1461

Bug: v8:6831
Change-Id: Icefd89ad790ac159b7f0617d0a012eefd90d3b1d
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1614296Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Commit-Queue: Z Nguyen-Huu <duongn@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#61669}
parent 3bebee41
......@@ -151,7 +151,7 @@ void CallOrConstructBuiltinsAssembler::CallOrConstructWithArrayLike(
TNode<Int32T> kind = LoadMapElementsKind(arguments_list_map);
GotoIf(Int32GreaterThan(kind, Int32Constant(LAST_FAST_ELEMENTS_KIND)),
GotoIf(IsElementsKindGreaterThan(kind, LAST_FROZEN_ELEMENTS_KIND),
&if_runtime);
Branch(Word32And(kind, Int32Constant(1)), &if_holey_array, &if_done);
}
......@@ -306,11 +306,13 @@ void CallOrConstructBuiltinsAssembler::CallOrConstructWithSpread(
var_elements = LoadElements(spread_array);
// Check elements kind of {spread}.
GotoIf(Int32LessThan(spread_kind, Int32Constant(PACKED_DOUBLE_ELEMENTS)),
GotoIf(IsElementsKindLessThanOrEqual(spread_kind, HOLEY_ELEMENTS),
&if_smiorobject);
GotoIf(IsElementsKindLessThanOrEqual(spread_kind, LAST_FAST_ELEMENTS_KIND),
&if_double);
Branch(
Int32GreaterThan(spread_kind, Int32Constant(LAST_FAST_ELEMENTS_KIND)),
&if_generic, &if_double);
IsElementsKindLessThanOrEqual(spread_kind, LAST_FROZEN_ELEMENTS_KIND),
&if_smiorobject, &if_generic);
}
BIND(&if_generic);
......
......@@ -14,6 +14,9 @@ function tests() {
assertEquals(3, countArgs(...[1.1, 2, 3])); // Double
assertEquals(4, countArgs(...[1.1, 2, , 3])); // HoleyDouble
assertEquals(3, countArgs(...[{valueOf: () => 0}, 1.1, '2'])); // Object
assertEquals(3, countArgs(...Object.freeze([{valueOf: () => 0}, 1.1, '2']))); // Frozen Object
assertEquals(3, countArgs(...Object.seal([{valueOf: () => 0}, 1.1, '2']))); // Sealed Object
assertEquals(3, countArgs(...Object.preventExtensions([{valueOf: () => 0}, 1.1, '2']))); // Non-extensible Object
assertEquals(
4, countArgs(...[{valueOf: () => 0}, 1.1, , '2'])); // HoleyObject
......
......@@ -756,3 +756,24 @@ arr.length = 3;
assertEquals(arr.length, 2);
arr.length = 0;
assertEquals(arr.length, 2);
// Spread with array
var arr = ['a', 'b', 'c'];
Object.freeze(arr);
var arrSpread = [...arr];
assertEquals(arrSpread.length, arr.length);
assertEquals(arrSpread[0], 'a');
assertEquals(arrSpread[1], 'b');
assertEquals(arrSpread[2], 'c');
// Spread with array-like
function returnArgs() {
return Object.freeze(arguments);
}
var arrLike = returnArgs('a', 'b', 'c');
assertTrue(Object.isFrozen(arrLike));
var arrSpread = [...arrLike];
assertEquals(arrSpread.length, arrLike.length);
assertEquals(arrSpread[0], 'a');
assertEquals(arrSpread[1], 'b');
assertEquals(arrSpread[2], 'c');
......@@ -420,3 +420,24 @@ arr.length = 3;
assertEquals(arr.length, 3);
arr.length = 0;
assertEquals(arr.length, 0);
// Spread with array
var arr = ['a', 'b', 'c'];
Object.preventExtensions(arr);
var arrSpread = [...arr];
assertEquals(arrSpread.length, arr.length);
assertEquals(arrSpread[0], 'a');
assertEquals(arrSpread[1], 'b');
assertEquals(arrSpread[2], 'c');
// Spread with array-like
function returnArgs() {
return Object.preventExtensions(arguments);
}
var arrLike = returnArgs('a', 'b', 'c');
assertFalse(Object.isExtensible(arrLike));
var arrSpread = [...arrLike];
assertEquals(arrSpread.length, arrLike.length);
assertEquals(arrSpread[0], 'a');
assertEquals(arrSpread[1], 'b');
assertEquals(arrSpread[2], 'c');
......@@ -728,3 +728,24 @@ arr.length = 3;
assertEquals(arr.length, 3);
arr.length = 0;
assertEquals(arr.length, 1);
// Spread with array
var arr = ['a', 'b', 'c'];
Object.seal(arr);
var arrSpread = [...arr];
assertEquals(arrSpread.length, arr.length);
assertEquals(arrSpread[0], 'a');
assertEquals(arrSpread[1], 'b');
assertEquals(arrSpread[2], 'c');
// Spread with array-like
function returnArgs() {
return Object.seal(arguments);
}
var arrLike = returnArgs('a', 'b', 'c');
assertTrue(Object.isSealed(arrLike));
var arrSpread = [...arrLike];
assertEquals(arrSpread.length, arrLike.length);
assertEquals(arrSpread[0], 'a');
assertEquals(arrSpread[1], 'b');
assertEquals(arrSpread[2], 'c');
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment