From 6d6893bfa3d383d4952b67954003800aba1f4be8 Mon Sep 17 00:00:00 2001 From: Fabrice Bellard Date: Wed, 19 Mar 2025 12:33:54 +0100 Subject: [PATCH] fixed BigInt hashing - removed -fno-bigint in qjsc and JS_AddIntrinsicBigInt() (BigInt is now considered as a base object) --- Makefile | 2 +- qjsc.c | 2 -- quickjs.c | 31 ++++++++++++++++++------ quickjs.h | 1 - tests/test_builtin.js | 56 +++++++++++++++++++++++++++++-------------- 5 files changed, 63 insertions(+), 29 deletions(-) diff --git a/Makefile b/Makefile index 9c983db..be3f614 100644 --- a/Makefile +++ b/Makefile @@ -371,7 +371,7 @@ endif HELLO_SRCS=examples/hello.js HELLO_OPTS=-fno-string-normalize -fno-map -fno-promise -fno-typedarray \ -fno-typedarray -fno-regexp -fno-json -fno-eval -fno-proxy \ - -fno-date -fno-module-loader -fno-bigint + -fno-date -fno-module-loader hello.c: $(QJSC) $(HELLO_SRCS) $(QJSC) -e $(HELLO_OPTS) -o $@ $(HELLO_SRCS) diff --git a/qjsc.c b/qjsc.c index 7a56a3b..de8ebd1 100644 --- a/qjsc.c +++ b/qjsc.c @@ -76,7 +76,6 @@ static const FeatureEntry feature_list[] = { { "promise", "Promise" }, #define FE_MODULE_LOADER 9 { "module-loader", NULL }, - { "bigint", "BigInt" }, }; void namelist_add(namelist_t *lp, const char *name, const char *short_name, @@ -359,7 +358,6 @@ void help(void) { int i; printf("-flto use link time optimization\n"); - printf("-fbignum enable bignum extensions\n"); printf("-fno-["); for(i = 0; i < countof(feature_list); i++) { if (i != 0) diff --git a/quickjs.c b/quickjs.c index d664ded..161406e 100644 --- a/quickjs.c +++ b/quickjs.c @@ -2035,7 +2035,6 @@ JSContext *JS_NewContext(JSRuntime *rt) JS_AddIntrinsicMapSet(ctx); JS_AddIntrinsicTypedArrays(ctx); JS_AddIntrinsicPromise(ctx); - JS_AddIntrinsicBigInt(ctx); return ctx; } @@ -3060,8 +3059,6 @@ static JSValue JS_AtomIsNumericIndex1(JSContext *ctx, JSAtom atom) return JS_UNDEFINED; } } - /* XXX: bignum: would be better to only accept integer to avoid - relying on current floating point precision */ /* this is ECMA CanonicalNumericIndexString primitive */ num = JS_ToNumber(ctx, JS_MKPTR(JS_TAG_STRING, p)); if (JS_IsException(num)) @@ -46477,7 +46474,9 @@ static uint32_t map_hash_key(JSContext *ctx, JSValueConst key) uint32_t h; double d; JSFloat64Union u; - + JSBigInt *p; + JSBigIntBuf buf; + switch(tag) { case JS_TAG_BOOL: h = JS_VALUE_GET_INT(key); @@ -46500,9 +46499,24 @@ static uint32_t map_hash_key(JSContext *ctx, JSValueConst key) hash_float64: u.d = d; h = (u.u32[0] ^ u.u32[1]) * 3163; - return h ^= JS_TAG_FLOAT64; + return h ^ JS_TAG_FLOAT64; + case JS_TAG_SHORT_BIG_INT: + p = js_bigint_set_short(&buf, key); + goto hash_bigint; + case JS_TAG_BIG_INT: + p = JS_VALUE_GET_PTR(key); + hash_bigint: + { + int i; + h = 1; + for(i = p->len - 1; i >= 0; i--) { + h = h * 263 + p->tab[i]; + } + h *= 3163; + } + break; default: - h = 0; /* XXX: bignum support */ + h = 0; break; } h ^= tag; @@ -50167,7 +50181,7 @@ static const JSCFunctionListEntry js_bigint_proto_funcs[] = { JS_PROP_STRING_DEF("[Symbol.toStringTag]", "BigInt", JS_PROP_CONFIGURABLE ), }; -void JS_AddIntrinsicBigInt(JSContext *ctx) +static void JS_AddIntrinsicBigInt(JSContext *ctx) { JSValueConst obj1; @@ -50454,6 +50468,9 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx) JS_DefinePropertyValue(ctx, ctx->global_obj, JS_ATOM_globalThis, JS_DupValue(ctx, ctx->global_obj), JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE); + + /* BigInt */ + JS_AddIntrinsicBigInt(ctx); } /* Typed Arrays */ diff --git a/quickjs.h b/quickjs.h index c59446d..2463364 100644 --- a/quickjs.h +++ b/quickjs.h @@ -406,7 +406,6 @@ void JS_AddIntrinsicProxy(JSContext *ctx); void JS_AddIntrinsicMapSet(JSContext *ctx); void JS_AddIntrinsicTypedArrays(JSContext *ctx); void JS_AddIntrinsicPromise(JSContext *ctx); -void JS_AddIntrinsicBigInt(JSContext *ctx); JSValue js_string_codePointRange(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv); diff --git a/tests/test_builtin.js b/tests/test_builtin.js index 15cd189..1c47f8f 100644 --- a/tests/test_builtin.js +++ b/tests/test_builtin.js @@ -714,29 +714,26 @@ function test_symbol() assert(b.toString(), "Symbol(aaa)"); } -function test_map() +function test_map1(key_type, n) { - var a, i, n, tab, o, v; - n = 1000; - - a = new Map(); - for (var i = 0; i < n; i++) { - a.set(i, i); - } - a.set(-2147483648, 1); - assert(a.get(-2147483648), 1); - assert(a.get(-2147483647 - 1), 1); - assert(a.get(-2147483647.5 - 0.5), 1); - - a.set(1n, 1n); - assert(a.get(1n), 1n); - assert(a.get(2n**1000n - (2n**1000n - 1n)), 1n); - + var a, i, tab, o, v; a = new Map(); tab = []; for(i = 0; i < n; i++) { v = { }; - o = { id: i }; + switch(key_type) { + case "small_bigint": + o = BigInt(i); + break; + case "bigint": + o = BigInt(i) + (1n << 128n); + break; + case "object": + o = { id: i }; + break; + default: + assert(false); + } tab[i] = [o, v]; a.set(o, v); } @@ -757,6 +754,29 @@ function test_map() assert(a.size, 0); } +function test_map() +{ + var a, i, n, tab, o, v; + n = 1000; + + a = new Map(); + for (var i = 0; i < n; i++) { + a.set(i, i); + } + a.set(-2147483648, 1); + assert(a.get(-2147483648), 1); + assert(a.get(-2147483647 - 1), 1); + assert(a.get(-2147483647.5 - 0.5), 1); + + a.set(1n, 1n); + assert(a.get(1n), 1n); + assert(a.get(2n**1000n - (2n**1000n - 1n)), 1n); + + test_map1("object", n); + test_map1("small_bigint", n); + test_map1("bigint", n); +} + function test_weak_map() { var a, i, n, tab, o, v, n2;