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( ...@@ -151,7 +151,7 @@ void CallOrConstructBuiltinsAssembler::CallOrConstructWithArrayLike(
TNode<Int32T> kind = LoadMapElementsKind(arguments_list_map); TNode<Int32T> kind = LoadMapElementsKind(arguments_list_map);
GotoIf(Int32GreaterThan(kind, Int32Constant(LAST_FAST_ELEMENTS_KIND)), GotoIf(IsElementsKindGreaterThan(kind, LAST_FROZEN_ELEMENTS_KIND),
&if_runtime); &if_runtime);
Branch(Word32And(kind, Int32Constant(1)), &if_holey_array, &if_done); Branch(Word32And(kind, Int32Constant(1)), &if_holey_array, &if_done);
} }
...@@ -306,11 +306,13 @@ void CallOrConstructBuiltinsAssembler::CallOrConstructWithSpread( ...@@ -306,11 +306,13 @@ void CallOrConstructBuiltinsAssembler::CallOrConstructWithSpread(
var_elements = LoadElements(spread_array); var_elements = LoadElements(spread_array);
// Check elements kind of {spread}. // Check elements kind of {spread}.
GotoIf(Int32LessThan(spread_kind, Int32Constant(PACKED_DOUBLE_ELEMENTS)), GotoIf(IsElementsKindLessThanOrEqual(spread_kind, HOLEY_ELEMENTS),
&if_smiorobject); &if_smiorobject);
GotoIf(IsElementsKindLessThanOrEqual(spread_kind, LAST_FAST_ELEMENTS_KIND),
&if_double);
Branch( Branch(
Int32GreaterThan(spread_kind, Int32Constant(LAST_FAST_ELEMENTS_KIND)), IsElementsKindLessThanOrEqual(spread_kind, LAST_FROZEN_ELEMENTS_KIND),
&if_generic, &if_double); &if_smiorobject, &if_generic);
} }
BIND(&if_generic); BIND(&if_generic);
......
...@@ -14,6 +14,9 @@ function tests() { ...@@ -14,6 +14,9 @@ function tests() {
assertEquals(3, countArgs(...[1.1, 2, 3])); // Double assertEquals(3, countArgs(...[1.1, 2, 3])); // Double
assertEquals(4, countArgs(...[1.1, 2, , 3])); // HoleyDouble assertEquals(4, countArgs(...[1.1, 2, , 3])); // HoleyDouble
assertEquals(3, countArgs(...[{valueOf: () => 0}, 1.1, '2'])); // Object 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( assertEquals(
4, countArgs(...[{valueOf: () => 0}, 1.1, , '2'])); // HoleyObject 4, countArgs(...[{valueOf: () => 0}, 1.1, , '2'])); // HoleyObject
......
...@@ -756,3 +756,24 @@ arr.length = 3; ...@@ -756,3 +756,24 @@ arr.length = 3;
assertEquals(arr.length, 2); assertEquals(arr.length, 2);
arr.length = 0; arr.length = 0;
assertEquals(arr.length, 2); 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; ...@@ -420,3 +420,24 @@ arr.length = 3;
assertEquals(arr.length, 3); assertEquals(arr.length, 3);
arr.length = 0; arr.length = 0;
assertEquals(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; ...@@ -728,3 +728,24 @@ arr.length = 3;
assertEquals(arr.length, 3); assertEquals(arr.length, 3);
arr.length = 0; arr.length = 0;
assertEquals(arr.length, 1); 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