fixed (again) JS atomics in case of typed array resizing - use same function name as quickjs-ng for js_atomics_get_buf() (#508)

This commit is contained in:
Fabrice Bellard 2026-05-14 15:39:06 +02:00
parent d417cafaf0
commit efda450a21

@ -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) {