Fix issue with -0 in Maps
authorarv <arv@chromium.org>
Fri, 20 Feb 2015 21:02:40 +0000 (13:02 -0800)
committerCommit bot <commit-bot@chromium.org>
Fri, 20 Feb 2015 21:02:55 +0000 (21:02 +0000)
Because we generated a different hash code for 0 and -0 we ended up
not even getting to the SameValueZero check.

BUG=v8:3906
LOG=N
R=adamk

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

Cr-Commit-Position: refs/heads/master@{#26787}

src/objects.cc
test/mjsunit/es6/map-minus-zero.js [new file with mode: 0644]
test/mjsunit/es6/set-minus-zero.js [new file with mode: 0644]

index 56c3771..ea4b664 100644 (file)
@@ -798,10 +798,16 @@ Map* Object::GetRootMap(Isolate* isolate) {
 Object* Object::GetHash() {
   // The object is either a number, a name, an odd-ball,
   // a real JS object, or a Harmony proxy.
-  if (IsNumber()) {
-    uint32_t hash = std::isnan(Number())
-                        ? Smi::kMaxValue
-                        : ComputeLongHash(double_to_uint64(Number()));
+  if (IsSmi()) {
+    int num = Smi::cast(this)->value();
+    uint32_t hash = ComputeLongHash(double_to_uint64(static_cast<double>(num)));
+    return Smi::FromInt(hash & Smi::kMaxValue);
+  }
+  if (IsHeapNumber()) {
+    double num = HeapNumber::cast(this)->value();
+    if (std::isnan(num)) return Smi::FromInt(Smi::kMaxValue);
+    if (i::IsMinusZero(num)) num = 0;
+    uint32_t hash = ComputeLongHash(double_to_uint64(num));
     return Smi::FromInt(hash & Smi::kMaxValue);
   }
   if (IsName()) {
diff --git a/test/mjsunit/es6/map-minus-zero.js b/test/mjsunit/es6/map-minus-zero.js
new file mode 100644 (file)
index 0000000..f9f397e
--- /dev/null
@@ -0,0 +1,51 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'use strict';
+
+var map = new Map();
+
+var objectKey = {};
+var stringKey = 'keykeykey';
+var numberKey = 42.24;
+var booleanKey = true;
+var undefinedKey = undefined;
+var nullKey = null;
+var nanKey = NaN;
+var zeroKey = 0;
+var minusZeroKey = -0;
+
+assertEquals(map.size, 0);
+
+map.set(objectKey, 'aaa');
+map.set(stringKey, 'bbb');
+map.set(numberKey, 'ccc');
+map.set(booleanKey, 'ddd');
+map.set(undefinedKey, 'eee');
+map.set(nullKey, 'fff');
+map.set(nanKey, 'ggg');
+map.set(zeroKey, 'hhh');
+
+assertEquals(8, map.size);
+
+assertEquals('aaa', map.get(objectKey));
+assertEquals('bbb', map.get(stringKey));
+assertEquals('ccc', map.get(numberKey));
+assertEquals('ddd', map.get(booleanKey));
+assertEquals('eee', map.get(undefinedKey));
+assertEquals('fff', map.get(nullKey));
+assertEquals('ggg', map.get(nanKey));
+assertEquals('hhh', map.get(zeroKey));
+
+assertEquals(undefined, map.get({}));
+assertEquals('bbb', map.get('keykeykey'));
+assertEquals('ccc', map.get(42.24));
+assertEquals('ddd', map.get(true));
+assertEquals('eee', map.get(undefined));
+assertEquals('fff', map.get(null));
+assertEquals('ggg', map.get(NaN));
+assertEquals('hhh', map.get(0));
+assertEquals('hhh', map.get(-0));
+assertEquals('hhh', map.get(1 / Infinity));
+assertEquals('hhh', map.get(-1 / Infinity));
diff --git a/test/mjsunit/es6/set-minus-zero.js b/test/mjsunit/es6/set-minus-zero.js
new file mode 100644 (file)
index 0000000..792332c
--- /dev/null
@@ -0,0 +1,51 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'use strict';
+
+var set = new Set();
+
+var objectKey = {};
+var stringKey = 'keykeykey';
+var numberKey = 42.24;
+var booleanKey = true;
+var undefinedKey = undefined;
+var nullKey = null;
+var nanKey = NaN;
+var zeroKey = 0;
+var minusZeroKey = -0;
+
+assertEquals(set.size, 0);
+
+set.add(objectKey);
+set.add(stringKey);
+set.add(numberKey);
+set.add(booleanKey);
+set.add(undefinedKey);
+set.add(nullKey);
+set.add(nanKey);
+set.add(zeroKey);
+
+assertEquals(8, set.size);
+
+assertTrue(set.has(objectKey));
+assertTrue(set.has(stringKey));
+assertTrue(set.has(numberKey));
+assertTrue(set.has(booleanKey));
+assertTrue(set.has(undefinedKey));
+assertTrue(set.has(nullKey));
+assertTrue(set.has(nanKey));
+assertTrue(set.has(zeroKey));
+
+assertFalse(set.has({}));
+assertTrue(set.has('keykeykey'));
+assertTrue(set.has(42.24));
+assertTrue(set.has(true));
+assertTrue(set.has(undefined));
+assertTrue(set.has(null));
+assertTrue(set.has(NaN));
+assertTrue(set.has(0));
+assertTrue(set.has(-0));
+assertTrue(set.has(1 / Infinity));
+assertTrue(set.has(-1 / Infinity));