From efda450a21df42764f68d4b29501a6c7e4b67edb Mon Sep 17 00:00:00 2001 From: Fabrice Bellard Date: Thu, 14 May 2026 15:39:06 +0200 Subject: [PATCH] fixed (again) JS atomics in case of typed array resizing - use same function name as quickjs-ng for js_atomics_get_buf() (#508) --- quickjs.c | 84 ++++++++++++++++++++++++++----------------------------- 1 file changed, 40 insertions(+), 44 deletions(-) diff --git a/quickjs.c b/quickjs.c index 23f2dfc..14f8509 100644 --- a/quickjs.c +++ b/quickjs.c @@ -58998,19 +58998,16 @@ typedef enum AtomicsOpEnum { ATOMICS_OP_LOAD, } AtomicsOpEnum; -static int js_atomics_get_ptr(JSContext *ctx, void **pptr, - JSObject **pobj, uint64_t *pidx, - int *psize_log2, JSClassID *pclass_id, - JSValueConst obj, JSValueConst idx_val, - int is_waitable) +static JSObject *js_atomics_get_buf(JSContext *ctx, + JSValueConst obj, JSValueConst idx_val, + uint64_t *pidx, int is_waitable) { JSObject *p; JSTypedArray *ta; JSArrayBuffer *abuf; - void *ptr; uint64_t idx; BOOL err; - int size_log2, old_len; + int old_len; if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) goto fail; @@ -59024,59 +59021,44 @@ static int js_atomics_get_ptr(JSContext *ctx, void **pptr, if (err) { fail: JS_ThrowTypeError(ctx, "integer TypedArray expected"); - return -1; + return NULL; } ta = p->u.typed_array; abuf = ta->buffer->u.array_buffer; if (!abuf->shared) { if (is_waitable == 2) { JS_ThrowTypeError(ctx, "not a SharedArrayBuffer TypedArray"); - return -1; + return NULL; } if (abuf->detached) { JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - return -1; + return NULL; } } old_len = p->u.array.count; if (JS_ToIndex(ctx, &idx, idx_val)) { - return -1; + return NULL; } if (idx >= old_len) goto oob; - if (is_waitable == 1) { - /* notify(): just avoid having an invalid pointer if overflow */ - if (idx >= p->u.array.count) - ptr = NULL; - } else { + if (is_waitable != 1) { /* RevalidateAtomicAccess() */ if (typed_array_is_oob(p)) { JS_ThrowTypeErrorArrayBufferOOB(ctx); - return -1; + return NULL; } if (idx >= p->u.array.count) { oob: JS_ThrowRangeError(ctx, "out-of-bound access"); - return -1; + return NULL; } } - size_log2 = typed_array_size_log2(p->class_id); - ptr = p->u.array.u.uint8_ptr + ((uintptr_t)idx << size_log2); - - *pptr = ptr; - if (pobj) - *pobj = p; - if (pidx) - *pidx = idx; - if (psize_log2) - *psize_log2 = size_log2; - if (pclass_id) - *pclass_id = p->class_id; - return 0; + *pidx = idx; + return p; } static JSValue js_atomics_op(JSContext *ctx, @@ -59087,12 +59069,12 @@ static JSValue js_atomics_op(JSContext *ctx, uint64_t v, a, rep_val, idx; void *ptr; JSValue ret; - JSClassID class_id; JSObject *p; - if (js_atomics_get_ptr(ctx, &ptr, &p, &idx, &size_log2, &class_id, - argv[0], argv[1], 0)) + p = js_atomics_get_buf(ctx, argv[0], argv[1], &idx, 0); + if (!p) return JS_EXCEPTION; + size_log2 = typed_array_size_log2(p->class_id); rep_val = 0; if (op == ATOMICS_OP_LOAD) { v = 0; @@ -59122,9 +59104,10 @@ static JSValue js_atomics_op(JSContext *ctx, return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); if (idx >= p->u.array.count) return JS_ThrowRangeError(ctx, "out-of-bound access"); - } - - switch(op | (size_log2 << 3)) { + } + ptr = p->u.array.u.uint8_ptr + ((uintptr_t)idx << size_log2); + + switch(op | (size_log2 << 3)) { #define OP(op_name, func_name) \ case ATOMICS_OP_ ## op_name | (0 << 3): \ @@ -59193,7 +59176,7 @@ static JSValue js_atomics_op(JSContext *ctx, abort(); } - switch(class_id) { + switch(p->class_id) { case JS_CLASS_INT8_ARRAY: a = (int8_t)a; goto done; @@ -59235,10 +59218,11 @@ static JSValue js_atomics_store(JSContext *ctx, JSObject *p; uint64_t idx; int64_t v; - - if (js_atomics_get_ptr(ctx, &ptr, &p, &idx, &size_log2, NULL, - argv[0], argv[1], 0)) + + p = js_atomics_get_buf(ctx, argv[0], argv[1], &idx, 0); + if (!p) return JS_EXCEPTION; + size_log2 = typed_array_size_log2(p->class_id); if (size_log2 == 3) { ret = JS_ToBigIntFree(ctx, JS_DupValue(ctx, argv[2])); if (JS_IsException(ret)) @@ -59264,6 +59248,8 @@ static JSValue js_atomics_store(JSContext *ctx, if (idx >= p->u.array.count) return JS_ThrowRangeError(ctx, "out-of-bound access"); + ptr = p->u.array.u.uint8_ptr + ((uintptr_t)idx << size_log2); + switch(size_log2) { case 0: atomic_store((_Atomic(uint8_t) *)ptr, v); @@ -59352,8 +59338,10 @@ static JSValue js_atomics_wait(JSContext *ctx, JSValueConst this_obj, int argc, JSValueConst *argv) { + JSObject *p; int64_t v; int32_t v32; + uint64_t idx; void *ptr; int64_t timeout; struct timespec ts; @@ -59361,9 +59349,12 @@ static JSValue js_atomics_wait(JSContext *ctx, int ret, size_log2, res; double d; - if (js_atomics_get_ptr(ctx, &ptr, NULL, NULL, &size_log2, NULL, - argv[0], argv[1], 2)) + p = js_atomics_get_buf(ctx, argv[0], argv[1], &idx, 2); + if (!p) return JS_EXCEPTION; + size_log2 = typed_array_size_log2(p->class_id); + ptr = p->u.array.u.uint8_ptr + ((uintptr_t)idx << size_log2); + /* 'argv[0]' is a SharedArrayBuffer so it cannot be detached nor reduced */ if (size_log2 == 3) { if (JS_ToBigInt64(ctx, &v, argv[2])) @@ -59437,13 +59428,17 @@ static JSValue js_atomics_notify(JSContext *ctx, { struct list_head *el, *el1, waiter_list; int32_t count, n; + uint64_t idx; + int size_log2; void *ptr; JSAtomicsWaiter *waiter; JSArrayBuffer *abuf; JSObject *p; - if (js_atomics_get_ptr(ctx, &ptr, &p, NULL, NULL, NULL, argv[0], argv[1], 1)) + p = js_atomics_get_buf(ctx, argv[0], argv[1], &idx, 1); + if (!p) return JS_EXCEPTION; + size_log2 = typed_array_size_log2(p->class_id); if (JS_IsUndefined(argv[2])) { count = INT32_MAX; @@ -59456,6 +59451,7 @@ static JSValue js_atomics_notify(JSContext *ctx, abuf = p->u.typed_array->buffer->u.array_buffer; if (abuf->shared && count > 0) { /* 'argv[0]' is a SharedArrayBuffer so it cannot be detached nor reduced */ + ptr = p->u.array.u.uint8_ptr + ((uintptr_t)idx << size_log2); pthread_mutex_lock(&js_atomics_mutex); init_list_head(&waiter_list); list_for_each_safe(el, el1, &js_atomics_waiter_list) {