Add cross-platform Atomics support

Fixes: https://github.com/quickjs-ng/quickjs/issues/1
This commit is contained in:
Saúl Ibarra Corretgé 2024-04-02 21:50:42 +02:00 committed by GitHub
parent 0de570988a
commit 569b238ec4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 1331 additions and 1075 deletions

View file

@ -51,7 +51,7 @@ if(MSVC)
xcheck_add_c_compiler_flag(-Wno-reserved-macro-identifier) xcheck_add_c_compiler_flag(-Wno-reserved-macro-identifier)
xcheck_add_c_compiler_flag(-Wno-reserved-identifier) xcheck_add_c_compiler_flag(-Wno-reserved-identifier)
xcheck_add_c_compiler_flag(-Wdeprecated-declarations) xcheck_add_c_compiler_flag(-Wdeprecated-declarations)
add_compile_definitions(WIN32_LEAN_AND_MEAN) xcheck_add_c_compiler_flag(/experimental:c11atomics)
endif() endif()
if(CMAKE_SYSTEM_NAME STREQUAL "WASI") if(CMAKE_SYSTEM_NAME STREQUAL "WASI")
@ -153,10 +153,16 @@ if(BUILD_QJS_LIBC)
list(APPEND qjs_sources quickjs-libc.c) list(APPEND qjs_sources quickjs-libc.c)
endif() endif()
list(APPEND qjs_defines _GNU_SOURCE) list(APPEND qjs_defines _GNU_SOURCE)
if(WIN32)
list(APPEND qjs_defines WIN32_LEAN_AND_MEAN _WIN32_WINNT=0x0602)
endif()
list(APPEND qjs_libs qjs ${CMAKE_DL_LIBS}) list(APPEND qjs_libs qjs ${CMAKE_DL_LIBS})
if(NOT MSVC)
find_package(Threads) find_package(Threads)
list(APPEND qjs_libs ${CMAKE_THREAD_LIBS_INIT} m) if(NOT CMAKE_SYSTEM_NAME STREQUAL "WASI")
list(APPEND qjs_libs ${CMAKE_THREAD_LIBS_INIT})
endif()
if(NOT MSVC)
list(APPEND qjs_libs m)
endif() endif()
add_library(qjs ${qjs_sources}) add_library(qjs ${qjs_sources})

222
cutils.c
View file

@ -34,6 +34,9 @@
#include "cutils.h" #include "cutils.h"
#undef NANOSEC
#define NANOSEC ((uint64_t) 1e9)
#pragma GCC visibility push(default) #pragma GCC visibility push(default)
void pstrcpy(char *buf, int buf_size, const char *str) void pstrcpy(char *buf, int buf_size, const char *str)
@ -649,7 +652,7 @@ uint64_t js__hrtime_ns(void) {
* performance counter interval, integer math could cause this computation * performance counter interval, integer math could cause this computation
* to overflow. Therefore we resort to floating point math. * to overflow. Therefore we resort to floating point math.
*/ */
scaled_freq = (double) frequency.QuadPart / 1e9; scaled_freq = (double) frequency.QuadPart / NANOSEC;
result = (double) counter.QuadPart / scaled_freq; result = (double) counter.QuadPart / scaled_freq;
return (uint64_t) result; return (uint64_t) result;
} }
@ -660,7 +663,7 @@ uint64_t js__hrtime_ns(void) {
if (clock_gettime(CLOCK_MONOTONIC, &t)) if (clock_gettime(CLOCK_MONOTONIC, &t))
abort(); abort();
return t.tv_sec * (uint64_t) 1e9 + t.tv_nsec; return t.tv_sec * NANOSEC + t.tv_nsec;
} }
#endif #endif
@ -674,4 +677,219 @@ int64_t js__gettimeofday_us(void) {
return ((int64_t)tv.tv_sec * 1000000) + tv.tv_usec; return ((int64_t)tv.tv_sec * 1000000) + tv.tv_usec;
} }
/* Cross-platform threading APIs. */
#if !defined(EMSCRIPTEN) && !defined(__wasi__)
#if defined(_WIN32)
typedef void (*js__once_cb)(void);
typedef struct {
js__once_cb callback;
} js__once_data_t;
static BOOL WINAPI js__once_inner(INIT_ONCE *once, void *param, void **context) {
js__once_data_t *data = param;
data->callback();
return TRUE;
}
void js_once(js_once_t *guard, js__once_cb callback) {
js__once_data_t data = { .callback = callback };
InitOnceExecuteOnce(guard, js__once_inner, (void*) &data, NULL);
}
void js_mutex_init(js_mutex_t *mutex) {
InitializeCriticalSection(mutex);
}
void js_mutex_destroy(js_mutex_t *mutex) {
DeleteCriticalSection(mutex);
}
void js_mutex_lock(js_mutex_t *mutex) {
EnterCriticalSection(mutex);
}
void js_mutex_unlock(js_mutex_t *mutex) {
LeaveCriticalSection(mutex);
}
void js_cond_init(js_cond_t *cond) {
InitializeConditionVariable(cond);
}
void js_cond_destroy(js_cond_t *cond) {
/* nothing to do */
(void) cond;
}
void js_cond_signal(js_cond_t *cond) {
WakeConditionVariable(cond);
}
void js_cond_broadcast(js_cond_t *cond) {
WakeAllConditionVariable(cond);
}
void js_cond_wait(js_cond_t *cond, js_mutex_t *mutex) {
if (!SleepConditionVariableCS(cond, mutex, INFINITE))
abort();
}
int js_cond_timedwait(js_cond_t *cond, js_mutex_t *mutex, uint64_t timeout) {
if (SleepConditionVariableCS(cond, mutex, (DWORD)(timeout / 1e6)))
return 0;
if (GetLastError() != ERROR_TIMEOUT)
abort();
return -1;
}
#else /* !defined(_WIN32) */
void js_once(js_once_t *guard, void (*callback)(void)) {
if (pthread_once(guard, callback))
abort();
}
void js_mutex_init(js_mutex_t *mutex) {
if (pthread_mutex_init(mutex, NULL))
abort();
}
void js_mutex_destroy(js_mutex_t *mutex) {
if (pthread_mutex_destroy(mutex))
abort();
}
void js_mutex_lock(js_mutex_t *mutex) {
if (pthread_mutex_lock(mutex))
abort();
}
void js_mutex_unlock(js_mutex_t *mutex) {
if (pthread_mutex_unlock(mutex))
abort();
}
void js_cond_init(js_cond_t *cond) {
#if defined(__APPLE__) && defined(__MACH__)
if (pthread_cond_init(cond, NULL))
abort();
#else
pthread_condattr_t attr;
int err;
if (pthread_condattr_init(&attr))
abort();
if (pthread_condattr_setclock(&attr, CLOCK_MONOTONIC))
abort();
if (pthread_cond_init(cond, &attr))
abort();
if (pthread_condattr_destroy(&attr))
abort();
#endif
}
void js_cond_destroy(js_cond_t *cond) {
#if defined(__APPLE__) && defined(__MACH__)
/* It has been reported that destroying condition variables that have been
* signalled but not waited on can sometimes result in application crashes.
* See https://codereview.chromium.org/1323293005.
*/
pthread_mutex_t mutex;
struct timespec ts;
int err;
if (pthread_mutex_init(&mutex, NULL))
abort();
if (pthread_mutex_lock(&mutex))
abort();
ts.tv_sec = 0;
ts.tv_nsec = 1;
err = pthread_cond_timedwait_relative_np(cond, &mutex, &ts);
if (err != 0 && err != ETIMEDOUT)
abort();
if (pthread_mutex_unlock(&mutex))
abort();
if (pthread_mutex_destroy(&mutex))
abort();
#endif /* defined(__APPLE__) && defined(__MACH__) */
if (pthread_cond_destroy(cond))
abort();
}
void js_cond_signal(js_cond_t *cond) {
if (pthread_cond_signal(cond))
abort();
}
void js_cond_broadcast(js_cond_t *cond) {
if (pthread_cond_broadcast(cond))
abort();
}
void js_cond_wait(js_cond_t *cond, js_mutex_t *mutex) {
#if defined(__APPLE__) && defined(__MACH__)
int r;
errno = 0;
r = pthread_cond_wait(cond, mutex);
/* Workaround for a bug in OS X at least up to 13.6
* See https://github.com/libuv/libuv/issues/4165
*/
if (r == EINVAL && errno == EBUSY)
return;
if (r)
abort();
#else
if (pthread_cond_wait(cond, mutex))
abort();
#endif
}
int js_cond_timedwait(js_cond_t *cond, js_mutex_t *mutex, uint64_t timeout) {
int r;
struct timespec ts;
#if !defined(__APPLE__)
timeout += js__hrtime_ns();
#endif
ts.tv_sec = timeout / NANOSEC;
ts.tv_nsec = timeout % NANOSEC;
#if defined(__APPLE__) && defined(__MACH__)
r = pthread_cond_timedwait_relative_np(cond, mutex, &ts);
#else
r = pthread_cond_timedwait(cond, mutex, &ts);
#endif
if (r == 0)
return 0;
if (r == ETIMEDOUT)
return -1;
abort();
/* Pacify some compilers. */
return -1;
}
#endif
#endif /* !defined(EMSCRIPTEN) && !defined(__wasi__) */
#pragma GCC visibility pop #pragma GCC visibility pop

View file

@ -29,8 +29,10 @@
#include <string.h> #include <string.h>
#include <inttypes.h> #include <inttypes.h>
#if defined(_MSC_VER) #if defined(_WIN32)
#include <windows.h> #include <windows.h>
#endif
#if defined(_MSC_VER)
#include <winsock2.h> #include <winsock2.h>
#include <malloc.h> #include <malloc.h>
#define alloca _alloca #define alloca _alloca
@ -43,7 +45,10 @@
#elif defined(__FreeBSD__) #elif defined(__FreeBSD__)
#include <malloc_np.h> #include <malloc_np.h>
#endif #endif
#if !defined(_WIN32)
#include <errno.h>
#include <pthread.h>
#endif
#if defined(_MSC_VER) && !defined(__clang__) #if defined(_MSC_VER) && !defined(__clang__)
# define likely(x) (x) # define likely(x) (x)
@ -426,4 +431,36 @@ static inline size_t js__malloc_usable_size(const void *ptr)
#endif #endif
} }
/* Cross-platform threading APIs. */
#if !defined(EMSCRIPTEN) && !defined(__wasi__)
#if defined(_WIN32)
#define JS_ONCE_INIT INIT_ONCE_STATIC_INIT
typedef INIT_ONCE js_once_t;
typedef CRITICAL_SECTION js_mutex_t;
typedef CONDITION_VARIABLE js_cond_t;
#else
#define JS_ONCE_INIT PTHREAD_ONCE_INIT
typedef pthread_once_t js_once_t;
typedef pthread_mutex_t js_mutex_t;
typedef pthread_cond_t js_cond_t;
#endif
void js_once(js_once_t *guard, void (*callback)(void));
void js_mutex_init(js_mutex_t *mutex);
void js_mutex_destroy(js_mutex_t *mutex);
void js_mutex_lock(js_mutex_t *mutex);
void js_mutex_unlock(js_mutex_t *mutex);
void js_cond_init(js_cond_t *cond);
void js_cond_destroy(js_cond_t *cond);
void js_cond_signal(js_cond_t *cond);
void js_cond_broadcast(js_cond_t *cond);
void js_cond_wait(js_cond_t *cond, js_mutex_t *mutex);
int js_cond_timedwait(js_cond_t *cond, js_mutex_t *mutex, uint64_t timeout);
#endif /* !defined(EMSCRIPTEN) && !defined(__wasi__) */
#endif /* CUTILS_H */ #endif /* CUTILS_H */

View file

@ -5,7 +5,7 @@
const uint32_t qjsc_function_source_size = 384; const uint32_t qjsc_function_source_size = 384;
const uint8_t qjsc_function_source[384] = { const uint8_t qjsc_function_source[384] = {
0x09, 0x06, 0x0c, 0x61, 0x63, 0x74, 0x75, 0x61, 0x0a, 0x06, 0x0c, 0x61, 0x63, 0x74, 0x75, 0x61,
0x6c, 0x02, 0x66, 0x0c, 0x65, 0x78, 0x70, 0x65, 0x6c, 0x02, 0x66, 0x0c, 0x65, 0x78, 0x70, 0x65,
0x63, 0x74, 0x14, 0x75, 0x73, 0x65, 0x20, 0x73, 0x63, 0x74, 0x14, 0x75, 0x73, 0x65, 0x20, 0x73,
0x74, 0x72, 0x69, 0x63, 0x74, 0x34, 0x66, 0x75, 0x74, 0x72, 0x69, 0x63, 0x74, 0x34, 0x66, 0x75,
@ -17,38 +17,38 @@ const uint8_t qjsc_function_source[384] = {
0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x6a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x6a,
0x73, 0x0c, 0x00, 0x02, 0x01, 0x9e, 0x01, 0x00, 0x73, 0x0c, 0x00, 0x02, 0x01, 0x9e, 0x01, 0x00,
0x06, 0x00, 0x03, 0x00, 0x01, 0xa0, 0x01, 0x06, 0x06, 0x00, 0x03, 0x00, 0x01, 0xa0, 0x01, 0x06,
0xa0, 0x01, 0x00, 0x00, 0x00, 0xac, 0x03, 0x02, 0xa0, 0x01, 0x00, 0x00, 0x00, 0xb2, 0x03, 0x02,
0x00, 0x30, 0xae, 0x03, 0x04, 0x00, 0x70, 0xac, 0x00, 0x30, 0xb4, 0x03, 0x04, 0x00, 0x70, 0xb2,
0x03, 0x04, 0x03, 0x70, 0x10, 0x00, 0x01, 0x00, 0x03, 0x04, 0x03, 0x70, 0x10, 0x00, 0x01, 0x00,
0xe0, 0x01, 0x00, 0x01, 0x00, 0x0c, 0x03, 0xc1, 0xe0, 0x01, 0x00, 0x01, 0x00, 0x0c, 0x03, 0xc1,
0x05, 0x08, 0xc1, 0x04, 0x3f, 0xd8, 0x00, 0x00, 0x05, 0x08, 0xc1, 0x04, 0x3f, 0xdb, 0x00, 0x00,
0x00, 0x80, 0x3f, 0xd7, 0x00, 0x00, 0x00, 0x40, 0x00, 0x80, 0x3f, 0xda, 0x00, 0x00, 0x00, 0x40,
0x3e, 0xd8, 0x00, 0x00, 0x00, 0x80, 0xbe, 0x00, 0x3e, 0xdb, 0x00, 0x00, 0x00, 0x80, 0xbe, 0x00,
0x40, 0xd7, 0x00, 0x00, 0x00, 0x00, 0x04, 0xd9, 0x40, 0xda, 0x00, 0x00, 0x00, 0x00, 0x04, 0xdc,
0x00, 0x00, 0x00, 0xc8, 0x04, 0xda, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x04, 0xdd, 0x00, 0x00,
0x00, 0x3a, 0xd8, 0x00, 0x00, 0x00, 0x61, 0x01, 0x00, 0x3a, 0xdb, 0x00, 0x00, 0x00, 0x61, 0x01,
0x00, 0x38, 0xd7, 0x00, 0x00, 0x00, 0x42, 0x36, 0x00, 0x38, 0xda, 0x00, 0x00, 0x00, 0x42, 0x36,
0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0xc9, 0x06, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0xc9, 0x06,
0xc8, 0x62, 0x01, 0x00, 0x38, 0xd8, 0x00, 0x00, 0xc8, 0x62, 0x01, 0x00, 0x38, 0xdb, 0x00, 0x00,
0x00, 0xaf, 0xe9, 0x0b, 0x38, 0x8f, 0x00, 0x00, 0x00, 0xaf, 0xe9, 0x0b, 0x38, 0x92, 0x00, 0x00,
0x00, 0x62, 0x01, 0x00, 0xee, 0x2f, 0x61, 0x03, 0x00, 0x62, 0x01, 0x00, 0xee, 0x2f, 0x61, 0x03,
0x00, 0x61, 0x02, 0x00, 0x38, 0x39, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x38, 0x39, 0x00, 0x00,
0x00, 0x38, 0xd8, 0x00, 0x00, 0x00, 0x04, 0xd7, 0x00, 0x38, 0xdb, 0x00, 0x00, 0x00, 0x04, 0xda,
0x00, 0x00, 0x00, 0x9d, 0x31, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x9d, 0x31, 0x01, 0x00, 0x04,
0x00, 0xca, 0x62, 0x02, 0x00, 0x42, 0x36, 0x00, 0x00, 0xca, 0x62, 0x02, 0x00, 0x42, 0x36, 0x00,
0x00, 0x00, 0x24, 0x00, 0x00, 0xcb, 0x06, 0xc8, 0x00, 0x00, 0x24, 0x00, 0x00, 0xcb, 0x06, 0xc8,
0x62, 0x03, 0x00, 0x38, 0xd8, 0x00, 0x00, 0x00, 0x62, 0x03, 0x00, 0x38, 0xdb, 0x00, 0x00, 0x00,
0xaf, 0xe9, 0x0b, 0x38, 0x8f, 0x00, 0x00, 0x00, 0xaf, 0xe9, 0x0b, 0x38, 0x92, 0x00, 0x00, 0x00,
0x62, 0x03, 0x00, 0xee, 0x2f, 0x68, 0x03, 0x00, 0x62, 0x03, 0x00, 0xee, 0x2f, 0x68, 0x03, 0x00,
0x68, 0x02, 0x00, 0xc4, 0x28, 0xb6, 0x03, 0x01, 0x68, 0x02, 0x00, 0xc4, 0x28, 0xbc, 0x03, 0x01,
0x01, 0x28, 0x60, 0x01, 0x49, 0x02, 0x21, 0x1a, 0x01, 0x28, 0x60, 0x01, 0x49, 0x02, 0x21, 0x1a,
0x1b, 0x04, 0x1e, 0x1d, 0x12, 0x26, 0x49, 0x1d, 0x1b, 0x04, 0x1e, 0x1d, 0x12, 0x26, 0x49, 0x1d,
0x0c, 0x06, 0x11, 0x18, 0x2a, 0x1c, 0x37, 0x41, 0x0c, 0x06, 0x11, 0x18, 0x2a, 0x1c, 0x37, 0x41,
0x21, 0x1c, 0x34, 0x18, 0x1b, 0x04, 0x26, 0x11, 0x21, 0x1c, 0x34, 0x18, 0x1b, 0x04, 0x26, 0x11,
0x3f, 0x1d, 0x0c, 0x06, 0x11, 0x18, 0x2a, 0x1c, 0x3f, 0x1d, 0x0c, 0x06, 0x11, 0x18, 0x2a, 0x1c,
0x53, 0x41, 0x00, 0x0c, 0x43, 0x02, 0x01, 0xae, 0x53, 0x41, 0x00, 0x0c, 0x43, 0x02, 0x01, 0xb4,
0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03,
0x00, 0xbb, 0x2a, 0x28, 0xb6, 0x03, 0x03, 0x01, 0x00, 0xbb, 0x2a, 0x28, 0xbc, 0x03, 0x03, 0x01,
0x04, 0x02, 0x1e, 0x0c, 0x0e, 0x1a, 0x66, 0x75, 0x04, 0x02, 0x1e, 0x0c, 0x0e, 0x1a, 0x66, 0x75,
0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66,
0x28, 0x29, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x28, 0x29, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74,

View file

@ -5,7 +5,7 @@
const uint32_t qjsc_hello_size = 89; const uint32_t qjsc_hello_size = 89;
const uint8_t qjsc_hello[89] = { const uint8_t qjsc_hello[89] = {
0x09, 0x04, 0x0e, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x0a, 0x04, 0x0e, 0x63, 0x6f, 0x6e, 0x73, 0x6f,
0x6c, 0x65, 0x06, 0x6c, 0x6f, 0x67, 0x16, 0x48, 0x6c, 0x65, 0x06, 0x6c, 0x6f, 0x67, 0x16, 0x48,
0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72,
0x6c, 0x64, 0x22, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x64, 0x22, 0x65, 0x78, 0x61, 0x6d, 0x70,
@ -13,9 +13,9 @@ const uint8_t qjsc_hello[89] = {
0x6f, 0x2e, 0x6a, 0x73, 0x0c, 0x00, 0x02, 0x00, 0x6f, 0x2e, 0x6a, 0x73, 0x0c, 0x00, 0x02, 0x00,
0x9e, 0x01, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x9e, 0x01, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00,
0x14, 0x01, 0xa0, 0x01, 0x00, 0x00, 0x00, 0x38, 0x14, 0x01, 0xa0, 0x01, 0x00, 0x00, 0x00, 0x38,
0xd6, 0x00, 0x00, 0x00, 0x42, 0xd7, 0x00, 0x00, 0xd9, 0x00, 0x00, 0x00, 0x42, 0xda, 0x00, 0x00,
0x00, 0x04, 0xd8, 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0x04, 0xdb, 0x00, 0x00, 0x00, 0x24, 0x01,
0x00, 0xcc, 0x28, 0xb2, 0x03, 0x01, 0x01, 0x00, 0x00, 0xcc, 0x28, 0xb8, 0x03, 0x01, 0x01, 0x00,
0x00, 0x00,
}; };

View file

@ -5,23 +5,23 @@
const uint32_t qjsc_fib_module_size = 310; const uint32_t qjsc_fib_module_size = 310;
const uint8_t qjsc_fib_module[310] = { const uint8_t qjsc_fib_module[310] = {
0x09, 0x03, 0x2c, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x0a, 0x03, 0x2c, 0x65, 0x78, 0x61, 0x6d, 0x70,
0x6c, 0x65, 0x73, 0x2f, 0x66, 0x69, 0x62, 0x5f, 0x6c, 0x65, 0x73, 0x2f, 0x66, 0x69, 0x62, 0x5f,
0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x2e, 0x6a, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x2e, 0x6a,
0x73, 0x06, 0x66, 0x69, 0x62, 0x02, 0x6e, 0x0d, 0x73, 0x06, 0x66, 0x69, 0x62, 0x02, 0x6e, 0x0d,
0xac, 0x03, 0x00, 0x01, 0x00, 0x00, 0xae, 0x03, 0xb2, 0x03, 0x00, 0x01, 0x00, 0x00, 0xb4, 0x03,
0x00, 0x00, 0x0c, 0x20, 0x02, 0x01, 0x9e, 0x01, 0x00, 0x00, 0x0c, 0x20, 0x02, 0x01, 0x9e, 0x01,
0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x09, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x09, 0x00,
0xae, 0x03, 0x00, 0x01, 0x08, 0xe9, 0x05, 0xbe, 0xb4, 0x03, 0x00, 0x01, 0x08, 0xe9, 0x05, 0xbe,
0x00, 0xe0, 0x29, 0x06, 0x2e, 0xac, 0x03, 0x01, 0x00, 0xe0, 0x29, 0x06, 0x2e, 0xb2, 0x03, 0x01,
0x01, 0x06, 0x01, 0x01, 0x00, 0x07, 0x14, 0x02, 0x01, 0x06, 0x01, 0x01, 0x00, 0x07, 0x14, 0x02,
0x00, 0x0c, 0x43, 0x02, 0x01, 0xae, 0x03, 0x01, 0x00, 0x0c, 0x43, 0x02, 0x01, 0xb4, 0x03, 0x01,
0x00, 0x01, 0x04, 0x01, 0x00, 0x1a, 0x01, 0xb0, 0x00, 0x01, 0x04, 0x01, 0x00, 0x1a, 0x01, 0xb6,
0x03, 0x00, 0x01, 0x00, 0xae, 0x03, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0xb4, 0x03, 0x00, 0x00,
0xd0, 0xb3, 0xa7, 0xe9, 0x03, 0xb3, 0x28, 0xd0, 0xd0, 0xb3, 0xa7, 0xe9, 0x03, 0xb3, 0x28, 0xd0,
0xb4, 0xac, 0xe9, 0x03, 0xb4, 0x28, 0xdc, 0xd0, 0xb4, 0xac, 0xe9, 0x03, 0xb4, 0x28, 0xdc, 0xd0,
0xb4, 0x9e, 0xee, 0xdc, 0xd0, 0xb5, 0x9e, 0xee, 0xb4, 0x9e, 0xee, 0xdc, 0xd0, 0xb5, 0x9e, 0xee,
0x9d, 0x28, 0xac, 0x03, 0x02, 0x08, 0x20, 0x04, 0x9d, 0x28, 0xb2, 0x03, 0x02, 0x08, 0x20, 0x04,
0x00, 0x07, 0x06, 0x07, 0x06, 0x12, 0x09, 0x08, 0x00, 0x07, 0x06, 0x07, 0x06, 0x12, 0x09, 0x08,
0x07, 0x07, 0x10, 0x07, 0x06, 0x07, 0x06, 0x12, 0x07, 0x07, 0x10, 0x07, 0x06, 0x07, 0x06, 0x12,
0x13, 0x08, 0x07, 0x08, 0x16, 0x0c, 0x0c, 0x07, 0x13, 0x08, 0x07, 0x08, 0x16, 0x0c, 0x0c, 0x07,
@ -49,7 +49,7 @@ const uint8_t qjsc_fib_module[310] = {
const uint32_t qjsc_hello_module_size = 177; const uint32_t qjsc_hello_module_size = 177;
const uint8_t qjsc_hello_module[177] = { const uint8_t qjsc_hello_module[177] = {
0x09, 0x07, 0x30, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x0a, 0x07, 0x30, 0x65, 0x78, 0x61, 0x6d, 0x70,
0x6c, 0x65, 0x73, 0x2f, 0x68, 0x65, 0x6c, 0x6c, 0x6c, 0x65, 0x73, 0x2f, 0x68, 0x65, 0x6c, 0x6c,
0x6f, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x6f, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65,
0x2e, 0x6a, 0x73, 0x1e, 0x2e, 0x2f, 0x66, 0x69, 0x2e, 0x6a, 0x73, 0x1e, 0x2e, 0x2f, 0x66, 0x69,
@ -59,17 +59,17 @@ const uint8_t qjsc_hello_module[177] = {
0x6c, 0x6f, 0x67, 0x16, 0x48, 0x65, 0x6c, 0x6c, 0x6c, 0x6f, 0x67, 0x16, 0x48, 0x65, 0x6c, 0x6c,
0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x10, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x10,
0x66, 0x69, 0x62, 0x28, 0x31, 0x30, 0x29, 0x3d, 0x66, 0x69, 0x62, 0x28, 0x31, 0x30, 0x29, 0x3d,
0x0d, 0xac, 0x03, 0x01, 0xae, 0x03, 0x00, 0x00, 0x0d, 0xb2, 0x03, 0x01, 0xb4, 0x03, 0x00, 0x00,
0x01, 0x00, 0xb0, 0x03, 0x00, 0x0c, 0x20, 0x02, 0x01, 0x00, 0xb6, 0x03, 0x00, 0x0c, 0x20, 0x02,
0x01, 0x9e, 0x01, 0x00, 0x00, 0x00, 0x05, 0x01, 0x01, 0x9e, 0x01, 0x00, 0x00, 0x00, 0x05, 0x01,
0x00, 0x32, 0x00, 0xb0, 0x03, 0x00, 0x0c, 0x08, 0x00, 0x32, 0x00, 0xb6, 0x03, 0x00, 0x0c, 0x08,
0xe9, 0x02, 0x29, 0x38, 0xd9, 0x00, 0x00, 0x00, 0xe9, 0x02, 0x29, 0x38, 0xdc, 0x00, 0x00, 0x00,
0x42, 0xda, 0x00, 0x00, 0x00, 0x04, 0xdb, 0x00, 0x42, 0xdd, 0x00, 0x00, 0x00, 0x04, 0xde, 0x00,
0x00, 0x00, 0x24, 0x01, 0x00, 0x0e, 0x38, 0xd9, 0x00, 0x00, 0x24, 0x01, 0x00, 0x0e, 0x38, 0xdc,
0x00, 0x00, 0x00, 0x42, 0xda, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xdd, 0x00, 0x00, 0x00,
0x04, 0xdc, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x04, 0xdf, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00,
0xbb, 0x0a, 0xee, 0x24, 0x02, 0x00, 0x0e, 0x06, 0xbb, 0x0a, 0xee, 0x24, 0x02, 0x00, 0x0e, 0x06,
0x2e, 0xac, 0x03, 0x01, 0x01, 0x0a, 0x01, 0x01, 0x2e, 0xb2, 0x03, 0x01, 0x01, 0x0a, 0x01, 0x01,
0x00, 0x04, 0x0a, 0x02, 0x62, 0x00, 0x4d, 0x30, 0x00, 0x04, 0x0a, 0x02, 0x62, 0x00, 0x4d, 0x30,
0x00, 0x00,
}; };

1972
gen/repl.c

File diff suppressed because it is too large Load diff

View file

@ -5,7 +5,7 @@
const uint32_t qjsc_test_fib_size = 166; const uint32_t qjsc_test_fib_size = 166;
const uint8_t qjsc_test_fib[166] = { const uint8_t qjsc_test_fib[166] = {
0x09, 0x07, 0x28, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x0a, 0x07, 0x28, 0x65, 0x78, 0x61, 0x6d, 0x70,
0x6c, 0x65, 0x73, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x6c, 0x65, 0x73, 0x2f, 0x74, 0x65, 0x73, 0x74,
0x5f, 0x66, 0x69, 0x62, 0x2e, 0x6a, 0x73, 0x10, 0x5f, 0x66, 0x69, 0x62, 0x2e, 0x6a, 0x73, 0x10,
0x2e, 0x2f, 0x66, 0x69, 0x62, 0x2e, 0x73, 0x6f, 0x2e, 0x2f, 0x66, 0x69, 0x62, 0x2e, 0x73, 0x6f,
@ -13,17 +13,17 @@ const uint8_t qjsc_test_fib[166] = {
0x73, 0x6f, 0x6c, 0x65, 0x06, 0x6c, 0x6f, 0x67, 0x73, 0x6f, 0x6c, 0x65, 0x06, 0x6c, 0x6f, 0x67,
0x16, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x16, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57,
0x6f, 0x72, 0x6c, 0x64, 0x10, 0x66, 0x69, 0x62, 0x6f, 0x72, 0x6c, 0x64, 0x10, 0x66, 0x69, 0x62,
0x28, 0x31, 0x30, 0x29, 0x3d, 0x0d, 0xac, 0x03, 0x28, 0x31, 0x30, 0x29, 0x3d, 0x0d, 0xb2, 0x03,
0x01, 0xae, 0x03, 0x00, 0x00, 0x01, 0x00, 0xb0, 0x01, 0xb4, 0x03, 0x00, 0x00, 0x01, 0x00, 0xb6,
0x03, 0x00, 0x0c, 0x20, 0x02, 0x01, 0x9e, 0x01, 0x03, 0x00, 0x0c, 0x20, 0x02, 0x01, 0x9e, 0x01,
0x00, 0x00, 0x00, 0x05, 0x01, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x05, 0x01, 0x00, 0x32, 0x00,
0xb0, 0x03, 0x00, 0x0c, 0x08, 0xe9, 0x02, 0x29, 0xb6, 0x03, 0x00, 0x0c, 0x08, 0xe9, 0x02, 0x29,
0x38, 0xd9, 0x00, 0x00, 0x00, 0x42, 0xda, 0x00, 0x38, 0xdc, 0x00, 0x00, 0x00, 0x42, 0xdd, 0x00,
0x00, 0x00, 0x04, 0xdb, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x04, 0xde, 0x00, 0x00, 0x00, 0x24,
0x01, 0x00, 0x0e, 0x38, 0xd9, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0e, 0x38, 0xdc, 0x00, 0x00, 0x00,
0x42, 0xda, 0x00, 0x00, 0x00, 0x04, 0xdc, 0x00, 0x42, 0xdd, 0x00, 0x00, 0x00, 0x04, 0xdf, 0x00,
0x00, 0x00, 0x65, 0x00, 0x00, 0xbb, 0x0a, 0xee, 0x00, 0x00, 0x65, 0x00, 0x00, 0xbb, 0x0a, 0xee,
0x24, 0x02, 0x00, 0x0e, 0x06, 0x2e, 0xac, 0x03, 0x24, 0x02, 0x00, 0x0e, 0x06, 0x2e, 0xb2, 0x03,
0x01, 0x01, 0x0a, 0x01, 0x01, 0x00, 0x04, 0x0a, 0x01, 0x01, 0x0a, 0x01, 0x01, 0x00, 0x04, 0x0a,
0x02, 0x62, 0x00, 0x4d, 0x30, 0x00, 0x02, 0x62, 0x00, 0x4d, 0x30, 0x00,
}; };

View file

@ -170,11 +170,9 @@ DEF(status, "status")
DEF(reason, "reason") DEF(reason, "reason")
DEF(globalThis, "globalThis") DEF(globalThis, "globalThis")
DEF(bigint, "bigint") DEF(bigint, "bigint")
#ifdef CONFIG_ATOMICS
DEF(not_equal, "not-equal") DEF(not_equal, "not-equal")
DEF(timed_out, "timed-out") DEF(timed_out, "timed-out")
DEF(ok, "ok") DEF(ok, "ok")
#endif
DEF(toJSON, "toJSON") DEF(toJSON, "toJSON")
/* class names */ /* class names */
DEF(Object, "Object") DEF(Object, "Object")

View file

@ -67,6 +67,11 @@
#define NO_TM_GMTOFF #define NO_TM_GMTOFF
#endif #endif
#if !defined(EMSCRIPTEN) && !defined(__wasi__)
#include "quickjs-c-atomics.h"
#define CONFIG_ATOMICS
#endif
/* dump object free */ /* dump object free */
//#define DUMP_FREE //#define DUMP_FREE
//#define DUMP_CLOSURE //#define DUMP_CLOSURE
@ -99,12 +104,6 @@
/* test the GC by forcing it before each object allocation */ /* test the GC by forcing it before each object allocation */
//#define FORCE_GC_AT_MALLOC //#define FORCE_GC_AT_MALLOC
#ifdef CONFIG_ATOMICS
#include <pthread.h>
#include "quickjs-c-atomics.h"
#include <errno.h>
#endif
#define STRINGIFY_(x) #x #define STRINGIFY_(x) #x
#define STRINGIFY(x) STRINGIFY_(x) #define STRINGIFY(x) STRINGIFY_(x)
@ -32561,7 +32560,7 @@ typedef enum BCTagEnum {
BC_TAG_OBJECT_REFERENCE, BC_TAG_OBJECT_REFERENCE,
} BCTagEnum; } BCTagEnum;
#define BC_VERSION 9 #define BC_VERSION 10
typedef struct BCWriterState { typedef struct BCWriterState {
JSContext *ctx; JSContext *ctx;
@ -51497,11 +51496,12 @@ static JSValue js_atomics_isLockFree(JSContext *ctx,
typedef struct JSAtomicsWaiter { typedef struct JSAtomicsWaiter {
struct list_head link; struct list_head link;
BOOL linked; BOOL linked;
pthread_cond_t cond; js_cond_t cond;
int32_t *ptr; int32_t *ptr;
} JSAtomicsWaiter; } JSAtomicsWaiter;
static pthread_mutex_t js_atomics_mutex = PTHREAD_MUTEX_INITIALIZER; static js_once_t js_atomics_once = JS_ONCE_INIT;
static js_mutex_t js_atomics_mutex;
static struct list_head js_atomics_waiter_list = static struct list_head js_atomics_waiter_list =
LIST_HEAD_INIT(js_atomics_waiter_list); LIST_HEAD_INIT(js_atomics_waiter_list);
@ -51543,44 +51543,34 @@ static JSValue js_atomics_wait(JSContext *ctx,
/* XXX: inefficient if large number of waiters, should hash on /* XXX: inefficient if large number of waiters, should hash on
'ptr' value */ 'ptr' value */
/* XXX: use Linux futexes when available ? */ js_mutex_lock(&js_atomics_mutex);
pthread_mutex_lock(&js_atomics_mutex);
if (size_log2 == 3) { if (size_log2 == 3) {
res = *(int64_t *)ptr != v; res = *(int64_t *)ptr != v;
} else { } else {
res = *(int32_t *)ptr != v; res = *(int32_t *)ptr != v;
} }
if (res) { if (res) {
pthread_mutex_unlock(&js_atomics_mutex); js_mutex_unlock(&js_atomics_mutex);
return JS_AtomToString(ctx, JS_ATOM_not_equal); return JS_AtomToString(ctx, JS_ATOM_not_equal);
} }
waiter = &waiter_s; waiter = &waiter_s;
waiter->ptr = ptr; waiter->ptr = ptr;
pthread_cond_init(&waiter->cond, NULL); js_cond_init(&waiter->cond);
waiter->linked = TRUE; waiter->linked = TRUE;
list_add_tail(&waiter->link, &js_atomics_waiter_list); list_add_tail(&waiter->link, &js_atomics_waiter_list);
if (timeout == INT64_MAX) { if (timeout == INT64_MAX) {
pthread_cond_wait(&waiter->cond, &js_atomics_mutex); js_cond_wait(&waiter->cond, &js_atomics_mutex);
ret = 0; ret = 0;
} else { } else {
/* XXX: use clock monotonic */ ret = js_cond_timedwait(&waiter->cond, &js_atomics_mutex, timeout * 1e6 /* to ns */);
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec += timeout / 1000;
ts.tv_nsec += (timeout % 1000) * 1000000;
if (ts.tv_nsec >= 1000000000) {
ts.tv_nsec -= 1000000000;
ts.tv_sec++;
}
ret = pthread_cond_timedwait(&waiter->cond, &js_atomics_mutex,
&ts);
} }
if (waiter->linked) if (waiter->linked)
list_del(&waiter->link); list_del(&waiter->link);
pthread_mutex_unlock(&js_atomics_mutex); js_mutex_unlock(&js_atomics_mutex);
pthread_cond_destroy(&waiter->cond); js_cond_destroy(&waiter->cond);
if (ret == ETIMEDOUT) { if (ret == -1) {
return JS_AtomToString(ctx, JS_ATOM_timed_out); return JS_AtomToString(ctx, JS_ATOM_timed_out);
} else { } else {
return JS_AtomToString(ctx, JS_ATOM_ok); return JS_AtomToString(ctx, JS_ATOM_ok);
@ -51612,7 +51602,7 @@ static JSValue js_atomics_notify(JSContext *ctx,
n = 0; n = 0;
if (abuf->shared && count > 0) { if (abuf->shared && count > 0) {
pthread_mutex_lock(&js_atomics_mutex); js_mutex_lock(&js_atomics_mutex);
init_list_head(&waiter_list); init_list_head(&waiter_list);
list_for_each_safe(el, el1, &js_atomics_waiter_list) { list_for_each_safe(el, el1, &js_atomics_waiter_list) {
waiter = list_entry(el, JSAtomicsWaiter, link); waiter = list_entry(el, JSAtomicsWaiter, link);
@ -51627,9 +51617,9 @@ static JSValue js_atomics_notify(JSContext *ctx,
} }
list_for_each(el, &waiter_list) { list_for_each(el, &waiter_list) {
waiter = list_entry(el, JSAtomicsWaiter, link); waiter = list_entry(el, JSAtomicsWaiter, link);
pthread_cond_signal(&waiter->cond); js_cond_signal(&waiter->cond);
} }
pthread_mutex_unlock(&js_atomics_mutex); js_mutex_unlock(&js_atomics_mutex);
} }
return js_int32(n); return js_int32(n);
} }
@ -51654,8 +51644,15 @@ static const JSCFunctionListEntry js_atomics_obj[] = {
JS_OBJECT_DEF("Atomics", js_atomics_funcs, countof(js_atomics_funcs), JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE ), JS_OBJECT_DEF("Atomics", js_atomics_funcs, countof(js_atomics_funcs), JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE ),
}; };
static void js__atomics_init(void) {
js_mutex_init(&js_atomics_mutex);
}
/* TODO(saghul) make this public and not dependent on typed arrays? */
void JS_AddIntrinsicAtomics(JSContext *ctx) void JS_AddIntrinsicAtomics(JSContext *ctx)
{ {
js_once(&js_atomics_once, js__atomics_init);
/* add Atomics as autoinit object */ /* add Atomics as autoinit object */
JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_atomics_obj, countof(js_atomics_obj)); JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_atomics_obj, countof(js_atomics_obj));
} }

View file

@ -69,7 +69,7 @@ arraybuffer-transfer
arrow-function arrow-function
async-functions async-functions
async-iteration async-iteration
Atomics=skip # disabled because of Windows <-> pthreads Atomics
Atomics.waitAsync=skip Atomics.waitAsync=skip
BigInt BigInt
caller caller