Commit 4984224a authored by aandrey@chromium.org's avatar aandrey@chromium.org

Add optional max elements limit for Map/Set mirror iterator preview.

R=yangguo@chromium.org
LOG=N

Review URL: https://codereview.chromium.org/712083002

Cr-Commit-Position: refs/heads/master@{#25257}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25257 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent ce336605
......@@ -1322,13 +1322,14 @@ inherits(MapMirror, ObjectMirror);
* Returns an array of key/value pairs of a map.
* This will keep keys alive for WeakMaps.
*
* @param {number=} opt_limit Max elements to return.
* @returns {Array.<Object>} Array of key/value pairs of a map.
*/
MapMirror.prototype.entries = function() {
MapMirror.prototype.entries = function(opt_limit) {
var result = [];
if (IS_WEAKMAP(this.value_)) {
var entries = %GetWeakMapEntries(this.value_);
var entries = %GetWeakMapEntries(this.value_, opt_limit || 0);
for (var i = 0; i < entries.length; i += 2) {
result.push({
key: entries[i],
......@@ -1340,7 +1341,8 @@ MapMirror.prototype.entries = function() {
var iter = %_CallFunction(this.value_, builtins.MapEntries);
var next;
while (!(next = iter.next()).done) {
while ((!opt_limit || result.length < opt_limit) &&
!(next = iter.next()).done) {
result.push({
key: next.value[0],
value: next.value[1]
......@@ -1356,10 +1358,11 @@ function SetMirror(value) {
inherits(SetMirror, ObjectMirror);
function IteratorGetValues_(iter, next_function) {
function IteratorGetValues_(iter, next_function, opt_limit) {
var result = [];
var next;
while (!(next = %_CallFunction(iter, next_function)).done) {
while ((!opt_limit || result.length < opt_limit) &&
!(next = %_CallFunction(iter, next_function)).done) {
result.push(next.value);
}
return result;
......@@ -1370,15 +1373,16 @@ function IteratorGetValues_(iter, next_function) {
* Returns an array of elements of a set.
* This will keep elements alive for WeakSets.
*
* @param {number=} opt_limit Max elements to return.
* @returns {Array.<Object>} Array of elements of a set.
*/
SetMirror.prototype.values = function() {
SetMirror.prototype.values = function(opt_limit) {
if (IS_WEAKSET(this.value_)) {
return %GetWeakSetValues(this.value_);
return %GetWeakSetValues(this.value_, opt_limit || 0);
}
var iter = %_CallFunction(this.value_, builtins.SetValues);
return IteratorGetValues_(iter, builtins.SetIteratorNextJS);
return IteratorGetValues_(iter, builtins.SetIteratorNextJS, opt_limit);
};
......@@ -1392,15 +1396,18 @@ inherits(IteratorMirror, ObjectMirror);
* Returns a preview of elements of an iterator.
* Does not change the backing iterator state.
*
* @param {number=} opt_limit Max elements to return.
* @returns {Array.<Object>} Array of elements of an iterator.
*/
IteratorMirror.prototype.preview = function() {
IteratorMirror.prototype.preview = function(opt_limit) {
if (IS_MAP_ITERATOR(this.value_)) {
return IteratorGetValues_(%MapIteratorClone(this.value_),
builtins.MapIteratorNextJS);
builtins.MapIteratorNextJS,
opt_limit);
} else if (IS_SET_ITERATOR(this.value_)) {
return IteratorGetValues_(%SetIteratorClone(this.value_),
builtins.SetIteratorNextJS);
builtins.SetIteratorNextJS,
opt_limit);
}
};
......
......@@ -227,23 +227,29 @@ RUNTIME_FUNCTION(Runtime_MapIteratorClone) {
RUNTIME_FUNCTION(Runtime_GetWeakMapEntries) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
DCHECK(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, holder, 0);
CONVERT_NUMBER_CHECKED(int, max_entries, Int32, args[1]);
RUNTIME_ASSERT(max_entries >= 0);
Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
if (max_entries == 0 || max_entries > table->NumberOfElements()) {
max_entries = table->NumberOfElements();
}
Handle<FixedArray> entries =
isolate->factory()->NewFixedArray(table->NumberOfElements() * 2);
isolate->factory()->NewFixedArray(max_entries * 2);
{
DisallowHeapAllocation no_gc;
int number_of_non_hole_elements = 0;
for (int i = 0; i < table->Capacity(); i++) {
int count = 0;
for (int i = 0; count / 2 < max_entries && i < table->Capacity(); i++) {
Handle<Object> key(table->KeyAt(i), isolate);
if (table->IsKey(*key)) {
entries->set(number_of_non_hole_elements++, *key);
entries->set(count++, *key);
Object* value = table->Lookup(key);
entries->set(number_of_non_hole_elements++, value);
entries->set(count++, value);
}
}
DCHECK_EQ(table->NumberOfElements() * 2, number_of_non_hole_elements);
DCHECK_EQ(max_entries * 2, count);
}
return *isolate->factory()->NewJSArrayWithElements(entries);
}
......@@ -346,21 +352,24 @@ RUNTIME_FUNCTION(Runtime_WeakCollectionSet) {
RUNTIME_FUNCTION(Runtime_GetWeakSetValues) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
DCHECK(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, holder, 0);
CONVERT_NUMBER_CHECKED(int, max_values, Int32, args[1]);
RUNTIME_ASSERT(max_values >= 0);
Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
Handle<FixedArray> values =
isolate->factory()->NewFixedArray(table->NumberOfElements());
if (max_values == 0 || max_values > table->NumberOfElements()) {
max_values = table->NumberOfElements();
}
Handle<FixedArray> values = isolate->factory()->NewFixedArray(max_values);
{
DisallowHeapAllocation no_gc;
int number_of_non_hole_elements = 0;
for (int i = 0; i < table->Capacity(); i++) {
int count = 0;
for (int i = 0; count < max_values && i < table->Capacity(); i++) {
Handle<Object> key(table->KeyAt(i), isolate);
if (table->IsKey(*key)) {
values->set(number_of_non_hole_elements++, *key);
}
if (table->IsKey(*key)) values->set(count++, *key);
}
DCHECK_EQ(table->NumberOfElements(), number_of_non_hole_elements);
DCHECK_EQ(max_values, count);
}
return *isolate->factory()->NewJSArrayWithElements(values);
}
......
......@@ -333,8 +333,8 @@ namespace internal {
F(WeakCollectionDelete, 2, 1) \
F(WeakCollectionSet, 3, 1) \
\
F(GetWeakMapEntries, 1, 1) \
F(GetWeakSetValues, 1, 1) \
F(GetWeakMapEntries, 2, 1) \
F(GetWeakSetValues, 2, 1) \
\
/* Harmony events */ \
F(EnqueueMicrotask, 1, 1) \
......
......@@ -51,6 +51,7 @@ map.set(o2, 22);
map.delete(o1);
var mapMirror = debug.MakeMirror(map);
testMapMirror(mapMirror);
var entries = mapMirror.entries();
assertEquals(1, entries.length);
assertSame(o2, entries[0].key);
......@@ -59,6 +60,7 @@ map.set(o1, 33);
map.set(o3, o2);
map.delete(o2);
map.set(undefined, 44);
entries = mapMirror.entries();
assertEquals(3, entries.length);
assertSame(o1, entries[0].key);
......@@ -68,6 +70,10 @@ assertSame(o2, entries[1].value);
assertEquals(undefined, entries[2].key);
assertEquals(44, entries[2].value);
assertEquals(3, mapMirror.entries(0).length);
assertEquals(1, mapMirror.entries(1).length);
assertEquals(2, mapMirror.entries(2).length);
// Test the mirror object for Sets
var set = new Set();
set.add(o1);
......@@ -78,6 +84,7 @@ var setMirror = debug.MakeMirror(set);
testSetMirror(setMirror);
var values = setMirror.values();
assertEquals(2, values.length);
assertEquals(1, setMirror.values(1).length);
assertSame(o2, values[0]);
assertEquals(undefined, values[1]);
......@@ -96,6 +103,8 @@ gc();
function testWeakMapEntries(weakMapMirror) {
var entries = weakMapMirror.entries();
assertEquals(2, entries.length);
assertEquals(2, weakMapMirror.entries(0).length);
assertEquals(1, weakMapMirror.entries(1).length);
var found = 0;
for (var i = 0; i < entries.length; i++) {
if (Object.is(entries[i].key, o1)) {
......@@ -129,6 +138,8 @@ gc();
function testWeakSetValues(weakSetMirror) {
var values = weakSetMirror.values();
assertEquals(2, values.length);
assertEquals(2, weakSetMirror.values(0).length);
assertEquals(1, weakSetMirror.values(1).length);
var found = 0;
for (var i = 0; i < values.length; i++) {
if (Object.is(values[i], o1)) {
......
......@@ -5,18 +5,21 @@
// Flags: --expose-debug-as debug
// Test the mirror object for collection iterators.
function testIteratorMirror(iter, offset, expected) {
function testIteratorMirror(iter, offset, expected, opt_limit) {
while (offset-- > 0) iter.next();
var mirror = debug.MakeMirror(iter);
assertTrue(mirror.isIterator());
var preview = mirror.preview();
var preview = mirror.preview(opt_limit);
assertArrayEquals(expected, preview);
// Check that iterator has not changed after taking preview.
var values = [];
for (var i of iter) values.push(i);
for (var i of iter) {
if (opt_limit && values.length >= opt_limit) break;
values.push(i);
}
assertArrayEquals(expected, values);
}
......@@ -39,6 +42,11 @@ testIteratorMirror(map.keys(), 2, []);
testIteratorMirror(map.values(), 2, []);
testIteratorMirror(map.entries(), 2, []);
// Test with maximum limit.
testIteratorMirror(map.keys(), 0, [41], 1);
testIteratorMirror(map.values(), 0, [42], 1);
testIteratorMirror(map.entries(), 0, [[41, 42]], 1);
var set = new Set();
set.add(41);
set.add(42);
......@@ -60,3 +68,8 @@ testIteratorMirror(set.entries(), 3, [[o2, o2]]);
testIteratorMirror(set.keys(), 5, []);
testIteratorMirror(set.values(), 5, []);
testIteratorMirror(set.entries(), 5, []);
// Test with maximum limit.
testIteratorMirror(set.keys(), 1, [42, o1], 2);
testIteratorMirror(set.values(), 1, [42, o1], 2);
testIteratorMirror(set.entries(), 1, [[42, 42], [o1, o1]], 2);
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