Bug 1382339 - Improve SpiderMonkey hashing functions by using MFBT's HashGeneric more; r=jandem
authorEhsan Akhgari <ehsan@mozilla.com>
Wed, 19 Jul 2017 15:29:55 -0400
changeset 369894 a7a9d51edeeb569877d21790636eeea4e45cd7c1
parent 369893 eea24721f55d5bc96a7ffaebfd2e71e01a7c36ff
child 369895 f4378a5e6c7ff9e7b00c755c3018f4d5bb844e94
push id92781
push usereakhgari@mozilla.com
push dateThu, 20 Jul 2017 16:59:15 +0000
treeherdermozilla-inbound@a7a9d51edeeb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1382339
milestone56.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 1382339 - Improve SpiderMonkey hashing functions by using MFBT's HashGeneric more; r=jandem
js/ipc/JavaScriptShared.h
js/public/UbiNode.h
js/src/builtin/MapObject.cpp
js/src/gc/StoreBuffer.h
js/src/gc/Zone.h
js/src/jit/OptimizationTracking.cpp
js/src/vm/ObjectGroup.cpp
js/src/vm/RegExpShared.h
js/src/vm/Shape.h
js/src/vm/Stack.h
--- a/js/ipc/JavaScriptShared.h
+++ b/js/ipc/JavaScriptShared.h
@@ -3,16 +3,17 @@
  *
  * 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/. */
 
 #ifndef mozilla_jsipc_JavaScriptShared_h__
 #define mozilla_jsipc_JavaScriptShared_h__
 
+#include "mozilla/HashFunctions.h"
 #include "mozilla/dom/DOMTypes.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
 #include "mozilla/jsipc/PJavaScript.h"
 #include "js/GCHashTable.h"
 #include "nsJSUtils.h"
 
 namespace mozilla {
 namespace jsipc {
@@ -67,17 +68,17 @@ class JavaScriptShared;
 
 // DefaultHasher<T> requires that T coerce to an integral type. We could make
 // ObjectId do that, but doing so would weaken our type invariants, so we just
 // reimplement it manually.
 struct ObjectIdHasher
 {
     typedef ObjectId Lookup;
     static js::HashNumber hash(const Lookup& l) {
-        return l.serialize();
+        return mozilla::HashGeneric(l.serialize());
     }
     static bool match(const ObjectId& k, const ObjectId& l) {
         return k == l;
     }
     static void rekey(ObjectId& k, const ObjectId& newKey) {
         k = newKey;
     }
 };
--- a/js/public/UbiNode.h
+++ b/js/public/UbiNode.h
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef js_UbiNode_h
 #define js_UbiNode_h
 
 #include "mozilla/Alignment.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/HashFunctions.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Move.h"
 #include "mozilla/RangedPtr.h"
 #include "mozilla/TypeTraits.h"
 #include "mozilla/Variant.h"
 
 #include "jspubtd.h"
@@ -421,17 +422,17 @@ class StackFrame {
                                                MutableHandleObject outSavedFrameStack) const {
         return base()->constructSavedFrameStack(cx, outSavedFrameStack);
     }
 
     struct HashPolicy {
         using Lookup = JS::ubi::StackFrame;
 
         static js::HashNumber hash(const Lookup& lookup) {
-            return lookup.identifier();
+            return mozilla::HashGeneric(lookup.identifier());
         }
 
         static bool match(const StackFrame& key, const Lookup& lookup) {
             return key == lookup;
         }
 
         static void rekey(StackFrame& k, const StackFrame& newKey) {
             k = newKey;
--- a/js/src/builtin/MapObject.cpp
+++ b/js/src/builtin/MapObject.cpp
@@ -80,17 +80,17 @@ HashValue(const Value& v, const mozilla:
     if (v.isString())
         return v.toString()->asAtom().hash();
     if (v.isSymbol())
         return v.toSymbol()->hash();
     if (v.isObject())
         return hcs.scramble(v.asRawBits());
 
     MOZ_ASSERT(!v.isGCThing(), "do not reveal pointers via hash codes");
-    return v.asRawBits();
+    return mozilla::HashGeneric(v.asRawBits());
 }
 
 HashNumber
 HashableValue::hash(const mozilla::HashCodeScrambler& hcs) const
 {
     return HashValue(value, hcs);
 }
 
--- a/js/src/gc/StoreBuffer.h
+++ b/js/src/gc/StoreBuffer.h
@@ -3,16 +3,17 @@
  * 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/. */
 
 #ifndef gc_StoreBuffer_h
 #define gc_StoreBuffer_h
 
 #include "mozilla/Attributes.h"
+#include "mozilla/HashFunctions.h"
 #include "mozilla/ReentrancyGuard.h"
 
 #include <algorithm>
 
 #include "jsalloc.h"
 
 #include "ds/LifoAlloc.h"
 #include "gc/Nursery.h"
@@ -202,17 +203,17 @@ class StoreBuffer
       private:
         GenericBuffer& operator=(const GenericBuffer& other) = delete;
     };
 
     template <typename Edge>
     struct PointerEdgeHasher
     {
         typedef Edge Lookup;
-        static HashNumber hash(const Lookup& l) { return uintptr_t(l.edge) >> 3; }
+        static HashNumber hash(const Lookup& l) { return mozilla::HashGeneric(l.edge); }
         static bool match(const Edge& k, const Lookup& l) { return k == l; }
     };
 
     struct CellPtrEdge
     {
         Cell** edge;
 
         CellPtrEdge() : edge(nullptr) {}
@@ -334,17 +335,19 @@ class StoreBuffer
         }
 
         void trace(TenuringTracer& mover) const;
 
         explicit operator bool() const { return objectAndKind_ != 0; }
 
         typedef struct {
             typedef SlotsEdge Lookup;
-            static HashNumber hash(const Lookup& l) { return l.objectAndKind_ ^ l.start_ ^ l.count_; }
+            static HashNumber hash(const Lookup& l) {
+                return mozilla::HashGeneric(l.objectAndKind_, l.start_, l.count_);
+            }
             static bool match(const SlotsEdge& k, const Lookup& l) { return k == l; }
         } Hasher;
 
         static const auto FullBufferReason = JS::gcreason::FULL_SLOT_BUFFER;
     };
 
     template <typename Buffer, typename Edge>
     void unput(Buffer& buffer, const Edge& edge) {
--- a/js/src/gc/Zone.h
+++ b/js/src/gc/Zone.h
@@ -3,16 +3,17 @@
  * 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/. */
 
 #ifndef gc_Zone_h
 #define gc_Zone_h
 
 #include "mozilla/Atomics.h"
+#include "mozilla/HashFunctions.h"
 #include "mozilla/MemoryReporting.h"
 
 #include "jscntxt.h"
 
 #include "ds/SplayTree.h"
 #include "gc/FindSCCs.h"
 #include "gc/GCRuntime.h"
 #include "js/GCHashTable.h"
@@ -503,17 +504,17 @@ struct Zone : public JS::shadow::Zone,
         return !isAtomsZone() && group()->usedByHelperThread;
     }
 
 #ifdef DEBUG
     js::ZoneGroupData<unsigned> gcLastSweepGroupIndex;
 #endif
 
     static js::HashNumber UniqueIdToHash(uint64_t uid) {
-        return js::HashNumber(uid >> 32) ^ js::HashNumber(uid & 0xFFFFFFFF);
+        return mozilla::HashGeneric(uid);
     }
 
     // Creates a HashNumber based on getUniqueId. Returns false on OOM.
     MOZ_MUST_USE bool getHashCode(js::gc::Cell* cell, js::HashNumber* hashp) {
         uint64_t uid;
         if (!getOrCreateUniqueId(cell, &uid))
             return false;
         *hashp = UniqueIdToHash(uid);
--- a/js/src/jit/OptimizationTracking.cpp
+++ b/js/src/jit/OptimizationTracking.cpp
@@ -210,17 +210,17 @@ CombineHash(HashNumber h, HashNumber n)
     return h;
 }
 
 static inline HashNumber
 HashType(TypeSet::Type ty)
 {
     if (ty.isObjectUnchecked())
         return PointerHasher<TypeSet::ObjectKey*>::hash(ty.objectKey());
-    return HashNumber(ty.raw());
+    return mozilla::HashGeneric(ty.raw());
 }
 
 static HashNumber
 HashTypeList(const TempTypeList& types)
 {
     HashNumber h = 0;
     for (uint32_t i = 0; i < types.length(); i++)
         h = CombineHash(h, HashType(types[i]));
--- a/js/src/vm/ObjectGroup.cpp
+++ b/js/src/vm/ObjectGroup.cpp
@@ -400,20 +400,19 @@ struct ObjectGroupCompartment::NewEntry
     }
 
     static bool ensureHash(const Lookup& l) {
         return MovableCellHasher<TaggedProto>::ensureHash(l.proto) &&
                MovableCellHasher<JSObject*>::ensureHash(l.associated);
     }
 
     static inline HashNumber hash(const Lookup& lookup) {
-        HashNumber hash = uintptr_t(lookup.clasp);
-        hash = mozilla::RotateLeft(hash, 4) ^ MovableCellHasher<TaggedProto>::hash(lookup.proto);
-        hash = mozilla::RotateLeft(hash, 4) ^ MovableCellHasher<JSObject*>::hash(lookup.associated);
-        return hash;
+        HashNumber hash = MovableCellHasher<TaggedProto>::hash(lookup.proto);
+        hash = mozilla::AddToHash(hash, MovableCellHasher<JSObject*>::hash(lookup.associated));
+        return mozilla::AddToHash(hash, mozilla::HashGeneric(lookup.clasp));
     }
 
     static inline bool match(const ObjectGroupCompartment::NewEntry& key, const Lookup& lookup) {
         if (lookup.clasp && key.group.unbarrieredGet()->clasp() != lookup.clasp)
             return false;
 
         TaggedProto proto = key.group.unbarrieredGet()->proto();
         if (!MovableCellHasher<TaggedProto>::match(proto, lookup.proto))
@@ -1127,18 +1126,18 @@ struct ObjectGroupCompartment::PlainObje
         uint32_t nproperties;
 
         Lookup(IdValuePair* properties, uint32_t nproperties)
           : properties(properties), nproperties(nproperties)
         {}
     };
 
     static inline HashNumber hash(const Lookup& lookup) {
-        return (HashNumber) (HashId(lookup.properties[lookup.nproperties - 1].id) ^
-                             lookup.nproperties);
+        HashNumber hash = HashId(lookup.properties[lookup.nproperties - 1].id);
+        return mozilla::AddToHash(hash, lookup.nproperties);
     }
 
     static inline bool match(const PlainObjectKey& v, const Lookup& lookup) {
         if (lookup.nproperties != v.nproperties)
             return false;
         for (size_t i = 0; i < lookup.nproperties; i++) {
             if (lookup.properties[i].id != v.properties[i])
                 return false;
--- a/js/src/vm/RegExpShared.h
+++ b/js/src/vm/RegExpShared.h
@@ -243,17 +243,18 @@ class RegExpZone
         { }
         MOZ_IMPLICIT Key(const ReadBarriered<RegExpShared*>& shared)
           : atom(shared.unbarrieredGet()->getSource()),
             flag(shared.unbarrieredGet()->getFlags())
         { }
 
         typedef Key Lookup;
         static HashNumber hash(const Lookup& l) {
-            return DefaultHasher<JSAtom*>::hash(l.atom) ^ (l.flag << 1);
+            HashNumber hash = DefaultHasher<JSAtom*>::hash(l.atom);
+            return mozilla::AddToHash(hash, l.flag);
         }
         static bool match(Key l, Key r) {
             return l.atom == r.atom && l.flag == r.flag;
         }
     };
 
     /*
      * The set of all RegExpShareds in the zone. On every GC, every RegExpShared
--- a/js/src/vm/Shape.h
+++ b/js/src/vm/Shape.h
@@ -4,16 +4,17 @@
  * 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/. */
 
 #ifndef vm_Shape_h
 #define vm_Shape_h
 
 #include "mozilla/Attributes.h"
 #include "mozilla/GuardObjects.h"
+#include "mozilla/HashFunctions.h"
 #include "mozilla/MathAlgorithms.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/TemplateLib.h"
 
 #include "jsapi.h"
 #include "jsatom.h"
 #include "jsfriendapi.h"
@@ -655,19 +656,17 @@ struct StackBaseShape : public DefaultHa
         explicit Lookup(const ReadBarriered<UnownedBaseShape*>& base)
           : flags(base.unbarrieredGet()->getObjectFlags()), clasp(base.unbarrieredGet()->clasp())
         {
             MOZ_ASSERT(!base.unbarrieredGet()->isOwned());
         }
     };
 
     static HashNumber hash(const Lookup& lookup) {
-        HashNumber hash = lookup.flags;
-        hash = mozilla::RotateLeft(hash, 4) ^ (uintptr_t(lookup.clasp) >> 3);
-        return hash;
+        return mozilla::HashGeneric(lookup.flags, lookup.clasp);
     }
     static inline bool match(const ReadBarriered<UnownedBaseShape*>& key, const Lookup& lookup) {
         return key.unbarrieredGet()->flags == lookup.flags &&
                key.unbarrieredGet()->clasp_ == lookup.clasp;
     }
 };
 
 static MOZ_ALWAYS_INLINE js::HashNumber
@@ -1334,17 +1333,18 @@ struct MovableCellHasher<InitialShapePro
 
     static bool hasHash(const Lookup& l) {
         return MovableCellHasher<TaggedProto>::hasHash(l.proto());
     }
     static bool ensureHash(const Lookup& l) {
         return MovableCellHasher<TaggedProto>::ensureHash(l.proto());
     }
     static HashNumber hash(const Lookup& l) {
-        return HashNumber(l.key()) ^ MovableCellHasher<TaggedProto>::hash(l.proto());
+        HashNumber hash = MovableCellHasher<TaggedProto>::hash(l.proto());
+        return mozilla::AddToHash(hash, l.key());
     }
     static bool match(const Key& k, const Lookup& l) {
         return k.key() == l.key() &&
                MovableCellHasher<TaggedProto>::match(k.proto().unbarrieredGet(), l.proto());
     }
 };
 
 /*
@@ -1389,19 +1389,18 @@ struct InitialShapeEntry
             baseFlags = shape->getObjectFlags();
         }
     };
 
     inline InitialShapeEntry();
     inline InitialShapeEntry(Shape* shape, const Lookup::ShapeProto& proto);
 
     static HashNumber hash(const Lookup& lookup) {
-        return (mozilla::RotateLeft(uintptr_t(lookup.clasp) >> 3, 4) ^
-                MovableCellHasher<ShapeProto>::hash(lookup.proto)) +
-               lookup.nfixed;
+        HashNumber hash = MovableCellHasher<ShapeProto>::hash(lookup.proto);
+        return mozilla::AddToHash(hash, mozilla::HashGeneric(lookup.clasp, lookup.nfixed));
     }
     static inline bool match(const InitialShapeEntry& key, const Lookup& lookup) {
         const Shape* shape = key.shape.unbarrieredGet();
         return lookup.clasp == shape->getObjectClass()
             && lookup.nfixed == shape->numFixedSlots()
             && lookup.baseFlags == shape->getObjectFlags()
             && MovableCellHasher<ShapeProto>::match(key.proto, lookup.proto);
     }
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -3,16 +3,17 @@
  * 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/. */
 
 #ifndef vm_Stack_h
 #define vm_Stack_h
 
 #include "mozilla/Atomics.h"
+#include "mozilla/HashFunctions.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Variant.h"
 
 #include "jsfun.h"
 #include "jsscript.h"
 #include "jsutil.h"
 
@@ -1101,17 +1102,17 @@ FillArgumentsFromArraylike(JSContext* cx
     return true;
 }
 
 template <>
 struct DefaultHasher<AbstractFramePtr> {
     typedef AbstractFramePtr Lookup;
 
     static js::HashNumber hash(const Lookup& key) {
-        return size_t(key.raw());
+        return mozilla::HashGeneric(key.raw());
     }
 
     static bool match(const AbstractFramePtr& k, const Lookup& l) {
         return k == l;
     }
 };
 
 /*****************************************************************************/