Map::Hash() calculation made deterministic in predictable mode.
authorishell@chromium.org <ishell@chromium.org>
Mon, 29 Sep 2014 11:29:43 +0000 (11:29 +0000)
committerishell@chromium.org <ishell@chromium.org>
Mon, 29 Sep 2014 11:29:43 +0000 (11:29 +0000)
BUG=v8:3563
LOG=N
R=jkummerow@chromium.org

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24281 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/objects.cc

index 0ff5973..482b5be 100644 (file)
@@ -9010,19 +9010,25 @@ void String::PrintOn(FILE* file) {
 }
 
 
+inline static uint32_t ObjectAddressForHashing(Object* object) {
+  uint32_t value = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(object));
+  return value & MemoryChunk::kAlignmentMask;
+}
+
+
 int Map::Hash() {
   // For performance reasons we only hash the 3 most variable fields of a map:
-  // constructor, prototype and bit_field2.
+  // constructor, prototype and bit_field2. For predictability reasons we
+  // use objects' offsets in respective pages for hashing instead of raw
+  // addresses.
 
   // Shift away the tag.
-  int hash = (static_cast<uint32_t>(
-        reinterpret_cast<uintptr_t>(constructor())) >> 2);
+  int hash = ObjectAddressForHashing(constructor()) >> 2;
 
   // XOR-ing the prototype and constructor directly yields too many zero bits
   // when the two pointers are close (which is fairly common).
-  // To avoid this we shift the prototype 4 bits relatively to the constructor.
-  hash ^= (static_cast<uint32_t>(
-        reinterpret_cast<uintptr_t>(prototype())) << 2);
+  // To avoid this we shift the prototype bits relatively to the constructor.
+  hash ^= ObjectAddressForHashing(prototype()) << (32 - kPageSizeBits);
 
   return hash ^ (hash >> 16) ^ bit_field2();
 }