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/+/1614296 Reviewed-by: Benedikt Meurer <bmeurer@chromium.org> Commit-Queue: Z Nguyen-Huu <duongn@microsoft.com> Cr-Commit-Position: refs/heads/master@{#61669}
This commit is contained in:
parent
3bebee412f
commit
9ccad33c97
@ -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');
|
||||
|
Loading…
Reference in New Issue
Block a user