7033ae511f
This patch makes ArraySpeciesCreate fast in V8 by avoiding two property reads when the following conditions are met: - No Array instance has had its __proto__ reset - No Array instance has had a constructor property defined - Array.prototype has not had its constructor changed - Array[Symbol.species] has not been reset For subclasses of Array, or for conditions where one of these assumptions is violated, the full lookup of species is done according to the ArraySpeciesCreate algorithm. Although this is a "performance cliff", it does not come up in the expected typical use case of @@species (Array subclassing), so it is hoped that this can form a good start. Array subclasses will incur the slowness of looking up @@species, but their use won't slow down invocations of, for example, Array.prototype.slice on Array base class instances. Possible future optimizations: - For the fallback case where the assumptions don't hold, optimize the two property lookups. - For Array.prototype.slice and Array.prototype.splice, even if the full lookup of @@species needs to take place, we still could take the rest of the C++ fastpath. However, to do this correctly requires changing the calling convention from C++ to JS to pass the @@species out, so it is not attempted in this patch. With this patch, microbenchmarks of Array.prototype.slice do not suffer a noticeable performance regression, unlike their previous 2.5x penalty. TBR=hpayer@chromium.org Review URL: https://codereview.chromium.org/1689733002 Cr-Commit-Position: refs/heads/master@{#34199}
28 lines
891 B
JavaScript
28 lines
891 B
JavaScript
// Copyright 2016 the V8 project authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
// Flags: --harmony-species
|
|
|
|
// Overwriting the constructor of an instance updates the protector
|
|
|
|
let x = [];
|
|
|
|
assertEquals(Array, x.map(()=>{}).constructor);
|
|
assertEquals(Array, x.filter(()=>{}).constructor);
|
|
assertEquals(Array, x.slice().constructor);
|
|
assertEquals(Array, x.splice().constructor);
|
|
assertEquals(Array, x.concat([1]).constructor);
|
|
assertEquals(1, x.concat([1])[0]);
|
|
|
|
class MyArray extends Array { }
|
|
|
|
x.constructor = MyArray;
|
|
|
|
assertEquals(MyArray, x.map(()=>{}).constructor);
|
|
assertEquals(MyArray, x.filter(()=>{}).constructor);
|
|
assertEquals(MyArray, x.slice().constructor);
|
|
assertEquals(MyArray, x.splice().constructor);
|
|
assertEquals(MyArray, x.concat([1]).constructor);
|
|
assertEquals(1, x.concat([1])[0]);
|