Revision: 25257
Author:   [email protected]
Date:     Tue Nov 11 09:46:40 2014 UTC
Log: Add optional max elements limit for Map/Set mirror iterator preview.

[email protected]
LOG=N

Review URL: https://codereview.chromium.org/712083002
https://code.google.com/p/v8/source/detail?r=25257

Modified:
 /branches/bleeding_edge/src/mirror-debugger.js
 /branches/bleeding_edge/src/runtime/runtime-collections.cc
 /branches/bleeding_edge/src/runtime/runtime.h
 /branches/bleeding_edge/test/mjsunit/es6/mirror-collections.js
 /branches/bleeding_edge/test/mjsunit/es6/mirror-iterators.js

=======================================
--- /branches/bleeding_edge/src/mirror-debugger.js Tue Nov 4 10:02:25 2014 UTC +++ /branches/bleeding_edge/src/mirror-debugger.js Tue Nov 11 09:46:40 2014 UTC
@@ -1322,13 +1322,14 @@
  * 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 @@

   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 @@
 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 @@
  * 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 @@
  * 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);
   }
 };

=======================================
--- /branches/bleeding_edge/src/runtime/runtime-collections.cc Tue Nov 4 10:02:25 2014 UTC +++ /branches/bleeding_edge/src/runtime/runtime-collections.cc Tue Nov 11 09:46:40 2014 UTC
@@ -227,23 +227,29 @@

 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_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);
 }
=======================================
--- /branches/bleeding_edge/src/runtime/runtime.h Wed Nov 5 07:23:28 2014 UTC +++ /branches/bleeding_edge/src/runtime/runtime.h Tue Nov 11 09:46:40 2014 UTC
@@ -333,8 +333,8 @@
   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)                            \
=======================================
--- /branches/bleeding_edge/test/mjsunit/es6/mirror-collections.js Tue Aug 5 19:37:32 2014 UTC +++ /branches/bleeding_edge/test/mjsunit/es6/mirror-collections.js Tue Nov 11 09:46:40 2014 UTC
@@ -51,6 +51,7 @@
 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(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 @@
 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 @@
 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 @@
 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 @@
 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)) {
=======================================
--- /branches/bleeding_edge/test/mjsunit/es6/mirror-iterators.js Tue Nov 4 10:02:25 2014 UTC +++ /branches/bleeding_edge/test/mjsunit/es6/mirror-iterators.js Tue Nov 11 09:46:40 2014 UTC
@@ -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.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.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);

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to