Bug 1365654 - Add a move constructor to HashTable::Enum r=luke
authorJon Coppeard <jcoppeard@mozilla.com>
Thu, 18 May 2017 16:22:00 +0100
changeset 409493 2996f5f166a2e0506896c0b9499e3e72ac2fb369
parent 409492 c67aff0a734d82dd7675392df2e88fc1b805164e
child 409494 bf4c50e7d769b865ba60e0f37b78cfb97fea4902
push id1490
push usermtabara@mozilla.com
push dateMon, 31 Jul 2017 14:08:16 +0000
treeherdermozilla-release@70e32e6bf15e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs1365654
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1365654 - Add a move constructor to HashTable::Enum r=luke
js/public/HashTable.h
js/src/jsapi-tests/testHashTable.cpp
--- a/js/public/HashTable.h
+++ b/js/public/HashTable.h
@@ -1065,23 +1065,31 @@ class HashTable : private AllocPolicy
     class Enum : public Range
     {
         friend class HashTable;
 
         HashTable& table_;
         bool rekeyed;
         bool removed;
 
-        /* Not copyable. */
+        // Enum is movable but not copyable.
         Enum(const Enum&) = delete;
         void operator=(const Enum&) = delete;
 
       public:
-        template<class Map> explicit
-        Enum(Map& map) : Range(map.all()), table_(map.impl), rekeyed(false), removed(false) {}
+        template<class Map>
+        explicit Enum(Map& map)
+          : Range(map.all()), table_(map.impl), rekeyed(false), removed(false) {}
+
+        MOZ_IMPLICIT Enum(Enum&& other)
+          : Range(other), table_(other.table_), rekeyed(other.rekeyed), removed(other.removed)
+        {
+            other.rekeyed = false;
+            other.removed = false;
+        }
 
         // Removes the |front()| element from the table, leaving |front()|
         // invalid until the next call to |popFront()|. For example:
         //
         //   HashSet<int> s;
         //   for (HashSet<int>::Enum e(s); !e.empty(); e.popFront())
         //     if (e.front() == 42)
         //       e.removeFront();
--- a/js/src/jsapi-tests/testHashTable.cpp
+++ b/js/src/jsapi-tests/testHashTable.cpp
@@ -1,16 +1,18 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "js/HashTable.h"
 #include "js/Utility.h"
 #include "jsapi-tests/tests.h"
 
+#include "mozilla/Move.h"
+
 //#define FUZZ
 
 typedef js::HashMap<uint32_t, uint32_t, js::DefaultHasher<uint32_t>, js::SystemAllocPolicy> IntMap;
 typedef js::HashSet<uint32_t, js::DefaultHasher<uint32_t>, js::SystemAllocPolicy> IntSet;
 
 /*
  * The rekeying test as conducted by adding only keys masked with 0x0000FFFF
  * that are unique. We rekey by shifting left 16 bits.
@@ -383,8 +385,50 @@ BEGIN_TEST(testHashMapLookupWithDefaultO
     }
 
     js::oom::ResetSimulatedOOM();
     return true;
 }
 
 END_TEST(testHashMapLookupWithDefaultOOM)
 #endif // defined(DEBUG)
+
+BEGIN_TEST(testHashTableMovableEnum)
+{
+    CHECK(set.init());
+
+    // Exercise returning a hash table Enum object from a function.
+
+    CHECK(set.put(1));
+    for (auto e = enumerateSet(); !e.empty(); e.popFront())
+        e.removeFront();
+    CHECK(set.count() == 0);
+
+    // Test moving an Enum object explicitly.
+
+    CHECK(set.put(1));
+    CHECK(set.put(2));
+    CHECK(set.put(3));
+    CHECK(set.count() == 3);
+    {
+        auto e1 = IntSet::Enum(set);
+        CHECK(!e1.empty());
+        e1.removeFront();
+        e1.popFront();
+
+        auto e2 = mozilla::Move(e1);
+        CHECK(!e2.empty());
+        e2.removeFront();
+        e2.popFront();
+    }
+
+    CHECK(set.count() == 1);
+    return true;
+}
+
+IntSet set;
+
+IntSet::Enum enumerateSet()
+{
+    return IntSet::Enum(set);
+}
+
+END_TEST(testHashTableMovableEnum)