3b84cbfeb0
This is the next step towards faster Map and Set iteration. It introduces the appropriate instance types for Map and Set iterators (following the pattern for Array iterators) and migrates the following builtins to the CodeStubAssembler: - Set.prototype.entries - Set.prototype.values - Map.prototype.entries - Map.prototype.keys - Map.prototype.values - %SetIteratorPrototype%.next - %MapIteratorPrototype%.next This already provides a significant performance boost for regular for-of iteration of Sets and Maps, by a factor of 5-10 depending on the input. The final step will be to inline some fast-paths into TurboFan. Drive-by-fix: Remove obsolete %IsJSSetIterator and %IsJSMapIterator intrinsics and runtime functions. TBR=jgruber@chromium.org Bug: v8:6344, v8:6571, chromium:740122 Change-Id: I3ab0ee49e2afe8d4295707a5ecbd51adda621918 Reviewed-on: https://chromium-review.googlesource.com/563626 Commit-Queue: Benedikt Meurer <bmeurer@chromium.org> Reviewed-by: Benedikt Meurer <bmeurer@chromium.org> Cr-Commit-Position: refs/heads/master@{#46497}
256 lines
7.2 KiB
JavaScript
256 lines
7.2 KiB
JavaScript
// Copyright 2014 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: --allow-natives-syntax
|
|
|
|
|
|
(function TestSetIterator() {
|
|
var s = new Set;
|
|
var iter = s.values();
|
|
assertEquals('Set Iterator', %_ClassOf(iter));
|
|
|
|
var SetIteratorPrototype = iter.__proto__;
|
|
assertFalse(SetIteratorPrototype.hasOwnProperty('constructor'));
|
|
assertEquals(SetIteratorPrototype.__proto__, Object.prototype);
|
|
|
|
var propertyNames = Object.getOwnPropertyNames(SetIteratorPrototype);
|
|
assertArrayEquals(['next'], propertyNames);
|
|
|
|
assertEquals(new Set().values().__proto__, SetIteratorPrototype);
|
|
assertEquals(new Set().entries().__proto__, SetIteratorPrototype);
|
|
|
|
assertEquals("[object Set Iterator]",
|
|
Object.prototype.toString.call(iter));
|
|
assertEquals("Set Iterator", SetIteratorPrototype[Symbol.toStringTag]);
|
|
var desc = Object.getOwnPropertyDescriptor(
|
|
SetIteratorPrototype, Symbol.toStringTag);
|
|
assertTrue(desc.configurable);
|
|
assertFalse(desc.writable);
|
|
assertEquals("Set Iterator", desc.value);
|
|
})();
|
|
|
|
|
|
(function TestSetIteratorValues() {
|
|
var s = new Set;
|
|
s.add(1);
|
|
s.add(2);
|
|
s.add(3);
|
|
var iter = s.values();
|
|
|
|
assertEquals({value: 1, done: false}, iter.next());
|
|
assertEquals({value: 2, done: false}, iter.next());
|
|
assertEquals({value: 3, done: false}, iter.next());
|
|
assertEquals({value: undefined, done: true}, iter.next());
|
|
assertEquals({value: undefined, done: true}, iter.next());
|
|
})();
|
|
|
|
|
|
(function TestSetIteratorKeys() {
|
|
assertEquals(Set.prototype.keys, Set.prototype.values);
|
|
})();
|
|
|
|
|
|
(function TestSetIteratorEntries() {
|
|
var s = new Set;
|
|
s.add(1);
|
|
s.add(2);
|
|
s.add(3);
|
|
var iter = s.entries();
|
|
|
|
assertEquals({value: [1, 1], done: false}, iter.next());
|
|
assertEquals({value: [2, 2], done: false}, iter.next());
|
|
assertEquals({value: [3, 3], done: false}, iter.next());
|
|
assertEquals({value: undefined, done: true}, iter.next());
|
|
assertEquals({value: undefined, done: true}, iter.next());
|
|
})();
|
|
|
|
|
|
(function TestSetIteratorMutations() {
|
|
var s = new Set;
|
|
s.add(1);
|
|
var iter = s.values();
|
|
assertEquals({value: 1, done: false}, iter.next());
|
|
s.add(2);
|
|
s.add(3);
|
|
s.add(4);
|
|
s.add(5);
|
|
assertEquals({value: 2, done: false}, iter.next());
|
|
s.delete(3);
|
|
assertEquals({value: 4, done: false}, iter.next());
|
|
s.delete(5);
|
|
assertEquals({value: undefined, done: true}, iter.next());
|
|
s.add(4);
|
|
assertEquals({value: undefined, done: true}, iter.next());
|
|
})();
|
|
|
|
|
|
(function TestSetIteratorMutations2() {
|
|
var s = new Set;
|
|
s.add(1);
|
|
s.add(2);
|
|
var i = s.values();
|
|
assertEquals({value: 1, done: false}, i.next());
|
|
s.delete(2);
|
|
s.delete(1);
|
|
s.add(2);
|
|
assertEquals({value: 2, done: false}, i.next());
|
|
assertEquals({value: undefined, done: true}, i.next());
|
|
})();
|
|
|
|
|
|
(function TestSetIteratorMutations3() {
|
|
var s = new Set;
|
|
s.add(1);
|
|
s.add(2);
|
|
var i = s.values();
|
|
assertEquals({value: 1, done: false}, i.next());
|
|
s.delete(2);
|
|
s.delete(1);
|
|
for (var x = 2; x < 500; ++x) s.add(x);
|
|
for (var x = 2; x < 500; ++x) s.delete(x);
|
|
for (var x = 2; x < 1000; ++x) s.add(x);
|
|
assertEquals({value: 2, done: false}, i.next());
|
|
for (var x = 1001; x < 2000; ++x) s.add(x);
|
|
s.delete(3);
|
|
for (var x = 6; x < 2000; ++x) s.delete(x);
|
|
assertEquals({value: 4, done: false}, i.next());
|
|
s.delete(5);
|
|
assertEquals({value: undefined, done: true}, i.next());
|
|
s.add(4);
|
|
assertEquals({value: undefined, done: true}, i.next());
|
|
})();
|
|
|
|
|
|
(function TestSetInvalidReceiver() {
|
|
assertThrows(function() {
|
|
Set.prototype.values.call({});
|
|
}, TypeError);
|
|
assertThrows(function() {
|
|
Set.prototype.entries.call({});
|
|
}, TypeError);
|
|
})();
|
|
|
|
|
|
(function TestSetIteratorInvalidReceiver() {
|
|
var iter = new Set().values();
|
|
assertThrows(function() {
|
|
iter.next.call({});
|
|
});
|
|
})();
|
|
|
|
|
|
(function TestSetIteratorSymbol() {
|
|
assertEquals(Set.prototype[Symbol.iterator], Set.prototype.values);
|
|
assertTrue(Set.prototype.hasOwnProperty(Symbol.iterator));
|
|
assertFalse(Set.prototype.propertyIsEnumerable(Symbol.iterator));
|
|
|
|
var iter = new Set().values();
|
|
assertEquals(iter, iter[Symbol.iterator]());
|
|
assertEquals(iter[Symbol.iterator].name, '[Symbol.iterator]');
|
|
})();
|
|
|
|
|
|
(function TestMapIterator() {
|
|
var m = new Map;
|
|
var iter = m.values();
|
|
assertEquals('Map Iterator', %_ClassOf(iter));
|
|
|
|
var MapIteratorPrototype = iter.__proto__;
|
|
assertFalse(MapIteratorPrototype.hasOwnProperty('constructor'));
|
|
assertEquals(MapIteratorPrototype.__proto__, Object.prototype);
|
|
|
|
var propertyNames = Object.getOwnPropertyNames(MapIteratorPrototype);
|
|
assertArrayEquals(['next'], propertyNames);
|
|
|
|
assertEquals(new Map().values().__proto__, MapIteratorPrototype);
|
|
assertEquals(new Map().keys().__proto__, MapIteratorPrototype);
|
|
assertEquals(new Map().entries().__proto__, MapIteratorPrototype);
|
|
|
|
assertEquals("[object Map Iterator]",
|
|
Object.prototype.toString.call(iter));
|
|
assertEquals("Map Iterator", MapIteratorPrototype[Symbol.toStringTag]);
|
|
var desc = Object.getOwnPropertyDescriptor(
|
|
MapIteratorPrototype, Symbol.toStringTag);
|
|
assertTrue(desc.configurable);
|
|
assertFalse(desc.writable);
|
|
assertEquals("Map Iterator", desc.value);
|
|
})();
|
|
|
|
|
|
(function TestMapIteratorValues() {
|
|
var m = new Map;
|
|
m.set(1, 11);
|
|
m.set(2, 22);
|
|
m.set(3, 33);
|
|
var iter = m.values();
|
|
|
|
assertEquals({value: 11, done: false}, iter.next());
|
|
assertEquals({value: 22, done: false}, iter.next());
|
|
assertEquals({value: 33, done: false}, iter.next());
|
|
assertEquals({value: undefined, done: true}, iter.next());
|
|
assertEquals({value: undefined, done: true}, iter.next());
|
|
})();
|
|
|
|
|
|
(function TestMapIteratorKeys() {
|
|
var m = new Map;
|
|
m.set(1, 11);
|
|
m.set(2, 22);
|
|
m.set(3, 33);
|
|
var iter = m.keys();
|
|
|
|
assertEquals({value: 1, done: false}, iter.next());
|
|
assertEquals({value: 2, done: false}, iter.next());
|
|
assertEquals({value: 3, done: false}, iter.next());
|
|
assertEquals({value: undefined, done: true}, iter.next());
|
|
assertEquals({value: undefined, done: true}, iter.next());
|
|
})();
|
|
|
|
|
|
(function TestMapIteratorEntries() {
|
|
var m = new Map;
|
|
m.set(1, 11);
|
|
m.set(2, 22);
|
|
m.set(3, 33);
|
|
var iter = m.entries();
|
|
|
|
assertEquals({value: [1, 11], done: false}, iter.next());
|
|
assertEquals({value: [2, 22], done: false}, iter.next());
|
|
assertEquals({value: [3, 33], done: false}, iter.next());
|
|
assertEquals({value: undefined, done: true}, iter.next());
|
|
assertEquals({value: undefined, done: true}, iter.next());
|
|
})();
|
|
|
|
|
|
(function TestMapInvalidReceiver() {
|
|
assertThrows(function() {
|
|
Map.prototype.values.call({});
|
|
}, TypeError);
|
|
assertThrows(function() {
|
|
Map.prototype.keys.call({});
|
|
}, TypeError);
|
|
assertThrows(function() {
|
|
Map.prototype.entries.call({});
|
|
}, TypeError);
|
|
})();
|
|
|
|
|
|
(function TestMapIteratorInvalidReceiver() {
|
|
var iter = new Map().values();
|
|
assertThrows(function() {
|
|
iter.next.call({});
|
|
}, TypeError);
|
|
})();
|
|
|
|
|
|
(function TestMapIteratorSymbol() {
|
|
assertEquals(Map.prototype[Symbol.iterator], Map.prototype.entries);
|
|
assertTrue(Map.prototype.hasOwnProperty(Symbol.iterator));
|
|
assertFalse(Map.prototype.propertyIsEnumerable(Symbol.iterator));
|
|
|
|
var iter = new Map().values();
|
|
assertEquals(iter, iter[Symbol.iterator]());
|
|
assertEquals(iter[Symbol.iterator].name, '[Symbol.iterator]');
|
|
})();
|