Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions quickjs.c
Original file line number Diff line number Diff line change
Expand Up @@ -52665,6 +52665,16 @@ static JSValueConst map_normalize_key_const(JSContext *ctx, JSValueConst key)
}

/* XXX: better hash ? */

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

time to drop the comment now?

static uint32_t map_hash_u64(uint64_t h)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this some well-known formula? maybe add a comment with a reference pl

{
h ^= h >> 33;
h *= 0xff51afd7ed558ccdULL;
h ^= h >> 33;
h *= 0xc4ceb9fe1a85ec53ULL;
h ^= h >> 33;
return (uint32_t)(h ^ (h >> 32));
}

static uint32_t map_hash_key(JSContext *ctx, JSValueConst key)
{
uint32_t tag = JS_VALUE_GET_NORM_TAG(key);
Expand All @@ -52678,10 +52688,10 @@ static uint32_t map_hash_key(JSContext *ctx, JSValueConst key)
h = JS_VALUE_GET_INT(key);
break;
case JS_TAG_STRING:
h = hash_string(JS_VALUE_GET_STRING(key), 0);
h = hash_string(JS_VALUE_GET_STRING(key), JS_VALUE_GET_STRING(key)->len);
break;
case JS_TAG_STRING_ROPE:
h = hash_string_rope(key, 0);
h = hash_string_rope(key, JS_VALUE_GET_STRING_ROPE(key)->len);
break;
case JS_TAG_OBJECT:
case JS_TAG_SYMBOL:
Expand All @@ -52704,7 +52714,7 @@ static uint32_t map_hash_key(JSContext *ctx, JSValueConst key)
d = NAN;
hash_float64:
u.d = d;
h = (u.u32[0] ^ u.u32[1]) * 3163;
h = map_hash_u64(u.u64);
return h ^= JS_TAG_FLOAT64;
default:
h = 0;
Expand Down
101 changes: 101 additions & 0 deletions tests/test_builtin.js
Original file line number Diff line number Diff line change
Expand Up @@ -959,6 +959,23 @@ function test_symbol()
assert(b.toString(), "Symbol(aaa)");
}

function float64_from_words(hi, lo)
{
var buffer, view;
buffer = new ArrayBuffer(8);
view = new DataView(buffer);
view.setUint32(0, hi);
view.setUint32(4, lo);
return view.getFloat64(0);
}

function float64_map_hash_regression_value(i)
{
var word;
word = (0x3ff00000 + (i << 10)) >>> 0;
return float64_from_words(word, word);
}

function test_map()
{
var a, i, n, tab, o, v;
Expand All @@ -973,6 +990,54 @@ function test_map()
assert(a.get(-2147483647 - 1), 1);
assert(a.get(-2147483647.5 - 0.5), 1);

a = new Map();
tab = ["k", "\0k", "\0\0k"];
for(i = 0; i < tab.length; i++) {
a.set(tab[i], i);
}
assert(a.size, tab.length);
for(i = 0; i < tab.length; i++) {
assert(a.get(tab[i]), i);
}

a = new Map();
tab = [
[0, "zero"],
[float64_from_words(0x00000001, 0x00000001), "subnormal"],
[float64_from_words(0x3ff00000, 0x3ff00000), "normal1"],
[float64_from_words(0x40080000, 0x40080000), "normal2"],
];
for(i = 0; i < tab.length; i++) {
a.set(tab[i][0], tab[i][1]);
}
assert(a.size, tab.length);
for(i = 0; i < tab.length; i++) {
assert(a.get(tab[i][0]), tab[i][1]);
}

a = new Map();
n = 4096;
for(i = 0; i < n; i++) {
v = float64_map_hash_regression_value(i);
a.set(v, i);
}
assert(a.size, n);
for(i = 0; i < n; i++) {
v = float64_map_hash_regression_value(i);
assert(a.get(v), i);
}

a = new Map();
a.set(NaN, 1);
a.set(Number.NaN, 2);
assert(a.size, 1);
assert(a.get(NaN), 2);
a.set(-0, 3);
a.set(+0, 4);
assert(a.size, 2);
assert(a.get(-0), 4);
assert(a.get(+0), 4);

a = new Map();
tab = [];
for(i = 0; i < n; i++) {
Expand Down Expand Up @@ -1034,6 +1099,7 @@ function test_weak_map()

function test_set()
{
var i, set, tab;
const iter = {
a: [4, 5, 6],
nextCalls: 0,
Expand Down Expand Up @@ -1101,6 +1167,41 @@ function test_set()
keys() { return [].values() },
})
}

tab = ["k", "\0k", "\0\0k"];
set = new Set(tab);
assert(set.size, tab.length);
for(i = 0; i < tab.length; i++) {
assert(set.has(tab[i]));
}

tab = [
0,
float64_from_words(0x00000001, 0x00000001),
float64_from_words(0x3ff00000, 0x3ff00000),
float64_from_words(0x40080000, 0x40080000),
];
set = new Set(tab);
assert(set.size, tab.length);
for(i = 0; i < tab.length; i++) {
assert(set.has(tab[i]));
}

tab = [];
for(i = 0; i < 4096; i++) {
tab.push(float64_map_hash_regression_value(i));
}
set = new Set(tab);
assert(set.size, tab.length);
for(i = 0; i < tab.length; i++) {
assert(set.has(tab[i]));
}

set = new Set([NaN, Number.NaN, -0, +0]);
assert(set.size, 2);
assert(set.has(NaN));
assert(set.has(-0));
assert(set.has(+0));
}

function test_weak_set()
Expand Down
Loading