From 163b1d4e84d962f912cda56fefc3dc553a1f00c2 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Sat, 9 Nov 2024 20:43:17 +0100 Subject: [PATCH 1/2] Don't use rt->user_opaque in quickjs-libc.c JS_SetRuntimeOpaque() and JS_GetRuntimeOpaque() are intended for embedders. Stop using them in quickjs-libc.c --- quickjs-libc.c | 71 +++++++++++++++++++++++++++++++------------------- quickjs.c | 25 ++++++++++++++++++ quickjs.h | 3 +++ 3 files changed, 72 insertions(+), 27 deletions(-) diff --git a/quickjs-libc.c b/quickjs-libc.c index add3ecbb5..55a0eda6b 100644 --- a/quickjs-libc.c +++ b/quickjs-libc.c @@ -181,6 +181,16 @@ static BOOL my_isdigit(int c) return (c >= '0' && c <= '9'); } +static JSThreadState *js_get_thread_state(JSRuntime *rt) +{ + return (JSThreadState *)js_std_cmd(/*GetOpaque*/0, rt); +} + +static void js_set_thread_state(JSRuntime *rt, JSThreadState *ts) +{ + js_std_cmd(/*SetOpaque*/1, rt, ts); +} + static JSValue js_printf_internal(JSContext *ctx, int argc, JSValue *argv, FILE *fp) { @@ -831,7 +841,7 @@ static JSValue js_evalScript(JSContext *ctx, JSValue this_val, int argc, JSValue *argv) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); + JSThreadState *ts = js_get_thread_state(rt); const char *str = NULL; size_t len; JSValue ret, obj; @@ -905,7 +915,7 @@ static BOOL is_stdio(FILE *f) static void js_std_file_finalizer(JSRuntime *rt, JSValue val) { - JSThreadState *ts = JS_GetRuntimeOpaque(rt); + JSThreadState *ts = js_get_thread_state(rt); JSSTDFile *s = JS_GetOpaque(val, ts->std_file_class_id); if (s) { if (s->f && !is_stdio(s->f)) { @@ -939,7 +949,7 @@ static JSValue js_std_strerror(JSContext *ctx, JSValue this_val, static JSValue js_new_std_file(JSContext *ctx, FILE *f, BOOL is_popen) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); + JSThreadState *ts = js_get_thread_state(rt); JSSTDFile *s; JSValue obj; obj = JS_NewObjectClass(ctx, ts->std_file_class_id); @@ -1099,7 +1109,7 @@ static JSValue js_std_printf(JSContext *ctx, JSValue this_val, static FILE *js_std_file_get(JSContext *ctx, JSValue obj) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); + JSThreadState *ts = js_get_thread_state(rt); JSSTDFile *s = JS_GetOpaque2(ctx, obj, ts->std_file_class_id); if (!s) return NULL; @@ -1140,7 +1150,7 @@ static JSValue js_std_file_close(JSContext *ctx, JSValue this_val, int argc, JSValue *argv) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); + JSThreadState *ts = js_get_thread_state(rt); JSSTDFile *s = JS_GetOpaque2(ctx, this_val, ts->std_file_class_id); int err; if (!s) @@ -1657,7 +1667,7 @@ static int js_std_init(JSContext *ctx, JSModuleDef *m) { JSValue proto; JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); + JSThreadState *ts = js_get_thread_state(rt); /* FILE class */ /* the class ID is created once */ @@ -1945,7 +1955,7 @@ static JSValue js_os_rename(JSContext *ctx, JSValue this_val, static BOOL is_main_thread(JSRuntime *rt) { - JSThreadState *ts = JS_GetRuntimeOpaque(rt); + JSThreadState *ts = js_get_thread_state(rt); return !ts->recv_pipe; } @@ -1976,7 +1986,7 @@ static JSValue js_os_setReadHandler(JSContext *ctx, JSValue this_val, int argc, JSValue *argv, int magic) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); + JSThreadState *ts = js_get_thread_state(rt); JSOSRWHandler *rh; int fd; JSValue func; @@ -2046,7 +2056,7 @@ static JSValue js_os_signal(JSContext *ctx, JSValue this_val, int argc, JSValue *argv) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); + JSThreadState *ts = js_get_thread_state(rt); JSOSSignalHandler *sh; uint32_t sig_num; JSValue func; @@ -2128,7 +2138,7 @@ static JSValue js_os_setTimeout(JSContext *ctx, JSValue this_val, int argc, JSValue *argv, int magic) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); + JSThreadState *ts = js_get_thread_state(rt); int64_t delay; JSValue func; JSOSTimer *th; @@ -2171,7 +2181,7 @@ static JSValue js_os_clearTimeout(JSContext *ctx, JSValue this_val, int argc, JSValue *argv) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); + JSThreadState *ts = js_get_thread_state(rt); JSOSTimer *th; int64_t timer_id; @@ -2189,7 +2199,7 @@ static JSValue js_os_sleepAsync(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); + JSThreadState *ts = js_get_thread_state(rt); int64_t delay; JSOSTimer *th; JSValue promise, resolving_funcs[2]; @@ -2228,7 +2238,7 @@ static int call_handler(JSContext *ctx, JSValue func) r = 0; if (JS_IsException(ret)) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); + JSThreadState *ts = js_get_thread_state(rt); ts->exc = JS_GetException(ctx); r = -1; } @@ -2278,7 +2288,7 @@ static int js_os_run_timers(JSRuntime *rt, JSContext *ctx, JSThreadState *ts, in static int js_os_poll(JSContext *ctx) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); + JSThreadState *ts = js_get_thread_state(rt); int min_delay, console_fd; JSOSRWHandler *rh; struct list_head *el; @@ -2407,7 +2417,7 @@ static int handle_posted_message(JSRuntime *rt, JSContext *ctx, static int js_os_poll(JSContext *ctx) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); + JSThreadState *ts = js_get_thread_state(rt); int ret, fd_max, min_delay; fd_set rfds, wfds; JSOSRWHandler *rh; @@ -3415,7 +3425,7 @@ static void js_free_port(JSRuntime *rt, JSWorkerMessageHandler *port) static void js_worker_finalizer(JSRuntime *rt, JSValue val) { - JSThreadState *ts = JS_GetRuntimeOpaque(rt); + JSThreadState *ts = js_get_thread_state(rt); JSWorkerData *worker = JS_GetOpaque(val, ts->worker_class_id); if (worker) { js_free_message_pipe(worker->recv_pipe); @@ -3448,7 +3458,7 @@ static void *worker_func(void *opaque) JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL); /* set the pipe to communicate with the parent */ - ts = JS_GetRuntimeOpaque(rt); + ts = js_get_thread_state(rt); ts->recv_pipe = args->recv_pipe; ts->send_pipe = args->send_pipe; @@ -3485,7 +3495,7 @@ static JSValue js_worker_ctor_internal(JSContext *ctx, JSValue new_target, JSWorkerMessagePipe *send_pipe) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); + JSThreadState *ts = js_get_thread_state(rt); JSValue obj = JS_UNDEFINED, proto; JSWorkerData *s; @@ -3602,7 +3612,7 @@ static JSValue js_worker_postMessage(JSContext *ctx, JSValue this_val, int argc, JSValue *argv) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); + JSThreadState *ts = js_get_thread_state(rt); JSWorkerData *worker = JS_GetOpaque2(ctx, this_val, ts->worker_class_id); JSWorkerMessagePipe *ps; size_t data_len, i; @@ -3681,7 +3691,7 @@ static JSValue js_worker_set_onmessage(JSContext *ctx, JSValue this_val, JSValue func) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); + JSThreadState *ts = js_get_thread_state(rt); JSWorkerData *worker = JS_GetOpaque2(ctx, this_val, ts->worker_class_id); JSWorkerMessageHandler *port; @@ -3715,7 +3725,7 @@ static JSValue js_worker_set_onmessage(JSContext *ctx, JSValue this_val, static JSValue js_worker_get_onmessage(JSContext *ctx, JSValue this_val) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); + JSThreadState *ts = js_get_thread_state(rt); JSWorkerData *worker = JS_GetOpaque2(ctx, this_val, ts->worker_class_id); JSWorkerMessageHandler *port; if (!worker) @@ -3862,7 +3872,7 @@ static const JSCFunctionListEntry js_os_funcs[] = { static int js_os_init(JSContext *ctx, JSModuleDef *m) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); + JSThreadState *ts = js_get_thread_state(rt); ts->can_js_os_poll = TRUE; @@ -3989,6 +3999,13 @@ void js_std_add_helpers(JSContext *ctx, int argc, char **argv) JS_FreeValue(ctx, global_obj); } +static void js_std_finalize(JSRuntime *rt, void *arg) +{ + JSThreadState *ts = arg; + js_set_thread_state(rt, NULL); + js_free_rt(rt, ts); +} + void js_std_init_handlers(JSRuntime *rt) { JSThreadState *ts; @@ -4006,8 +4023,8 @@ void js_std_init_handlers(JSRuntime *rt) ts->next_timer_id = 1; ts->exc = JS_UNDEFINED; - JS_SetRuntimeOpaque(rt, ts); - JS_AddRuntimeFinalizer(rt, js_free_rt, ts); + js_set_thread_state(rt, ts); + JS_AddRuntimeFinalizer(rt, js_std_finalize, ts); #ifdef USE_WORKER /* set the SharedArrayBuffer memory handlers */ @@ -4024,7 +4041,7 @@ void js_std_init_handlers(JSRuntime *rt) void js_std_free_handlers(JSRuntime *rt) { - JSThreadState *ts = JS_GetRuntimeOpaque(rt); + JSThreadState *ts = js_get_thread_state(rt); struct list_head *el, *el1; list_for_each_safe(el, el1, &ts->os_rw_handlers) { @@ -4101,7 +4118,7 @@ void js_std_promise_rejection_tracker(JSContext *ctx, JSValue promise, JSValue js_std_loop(JSContext *ctx) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); + JSThreadState *ts = js_get_thread_state(rt); JSContext *ctx1; int err; @@ -4131,7 +4148,7 @@ JSValue js_std_loop(JSContext *ctx) JSValue js_std_await(JSContext *ctx, JSValue obj) { JSRuntime *rt = JS_GetRuntime(ctx); - JSThreadState *ts = JS_GetRuntimeOpaque(rt); + JSThreadState *ts = js_get_thread_state(rt); JSValue ret; int state; diff --git a/quickjs.c b/quickjs.c index 97161cde1..ca4db6940 100644 --- a/quickjs.c +++ b/quickjs.c @@ -298,6 +298,7 @@ struct JSRuntime { JSShape **shape_hash; bf_context_t bf_ctx; void *user_opaque; + void *libc_opaque; JSRuntimeFinalizerState *finalizers; }; @@ -55424,6 +55425,30 @@ BOOL JS_DetectModule(const char *input, size_t input_len) return is_module; } +uintptr_t js_std_cmd(int cmd, ...) { + JSRuntime *rt; + uintptr_t rv; + va_list ap; + + rv = 0; + va_start(ap, cmd); + switch (cmd) { + case 0: // GetOpaque + rt = va_arg(ap, JSRuntime *); + rv = (uintptr_t)rt->libc_opaque; + break; + case 1: // SetOpaque + rt = va_arg(ap, JSRuntime *); + rt->libc_opaque = va_arg(ap, void *); + break; + default: + rv = -1; + } + va_end(ap); + + return rv; +} + #undef malloc #undef free #undef realloc diff --git a/quickjs.h b/quickjs.h index 44ce7b9b3..482ebb14e 100644 --- a/quickjs.h +++ b/quickjs.h @@ -1031,6 +1031,9 @@ JS_EXTERN int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m, JS_EXTERN const char* JS_GetVersion(void); +/* Integration point for quickjs-libc.c, not for public use. */ +JS_EXTERN uintptr_t js_std_cmd(int cmd, ...); + #undef JS_EXTERN #undef js_force_inline #undef __js_printf_like From ca4c98953b09754fa67f1ecfd8ec06547b228df9 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Sat, 9 Nov 2024 21:04:59 +0100 Subject: [PATCH 2/2] Don't use _Thread_local in run-test262.c Allows building with tcc and old gcc versions again. --- .github/workflows/ci.yml | 2 +- CMakeLists.txt | 9 +---- run-test262.c | 79 +++++++++++++++++++++++----------------- 3 files changed, 47 insertions(+), 43 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 837de5b57..4b1854a3a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -140,7 +140,7 @@ jobs: make cxxtest - name: test - if: ${{ matrix.config.configType != 'examples' && matrix.config.configType != 'tcc' }} + if: ${{ matrix.config.configType != 'examples' }} run: | make test diff --git a/CMakeLists.txt b/CMakeLists.txt index db4912d83..9fe136f32 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -289,14 +289,7 @@ endif() # Test262 runner # -if(EMSCRIPTEN -OR CMAKE_C_COMPILER_ID STREQUAL "TinyCC" -OR (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_LESS 5)) - # Empty. run-test262 uses pthreads, sorry Windows users. - # tcc and gcc 4.8 don't understand _Thread_local, whereas I - # don't understand why people still use 4.8 in this day and age - # but hey, here we are. -else() +if(NOT EMSCRIPTEN) add_executable(run-test262 run-test262.c ) diff --git a/run-test262.c b/run-test262.c index 5000f4806..c63b9102b 100644 --- a/run-test262.c +++ b/run-test262.c @@ -50,6 +50,17 @@ typedef pthread_t js_thread_t; #define CMD_NAME "run-test262" +typedef struct { + js_mutex_t agent_mutex; + js_cond_t agent_cond; + /* list of Test262Agent.link */ + struct list_head agent_list; + js_mutex_t report_mutex; + /* list of AgentReport.link */ + struct list_head report_list; + int async_done; +} ThreadLocalStorage; + typedef struct namelist_t { char **array; int count; @@ -97,7 +108,6 @@ int start_index, stop_index; int test_excluded; _Atomic int test_count, test_failed, test_skipped; _Atomic int new_errors, changed_errors, fixed_errors; -_Thread_local int async_done; void warning(const char *, ...) __attribute__((__format__(__printf__, 1, 2))); void fatal(int, const char *, ...) __attribute__((__format__(__printf__, 2, 3))); @@ -443,6 +453,7 @@ static void enumerate_tests(const char *path) static JSValue js_print_262(JSContext *ctx, JSValue this_val, int argc, JSValue *argv) { + ThreadLocalStorage *tls = JS_GetRuntimeOpaque(JS_GetRuntime(ctx)); int i; const char *str; @@ -451,9 +462,9 @@ static JSValue js_print_262(JSContext *ctx, JSValue this_val, if (!str) return JS_EXCEPTION; if (!strcmp(str, "Test262:AsyncTestComplete")) { - async_done++; + tls->async_done++; } else if (strstart(str, "Test262:AsyncTestFailure", NULL)) { - async_done = 2; /* force an error */ + tls->async_done = 2; /* force an error */ } if (outfile) { if (i != 0) @@ -552,16 +563,6 @@ static long cpu_count(void) #endif } -typedef struct { - js_mutex_t agent_mutex; - js_cond_t agent_cond; - /* list of Test262Agent.link */ - struct list_head agent_list; - js_mutex_t report_mutex; - /* list of AgentReport.link */ - struct list_head report_list; -} ThreadLocalStorage; - static void init_thread_local_storage(ThreadLocalStorage *p) { js_mutex_init(&p->agent_mutex); @@ -569,11 +570,9 @@ static void init_thread_local_storage(ThreadLocalStorage *p) init_list_head(&p->agent_list); js_mutex_init(&p->report_mutex); init_list_head(&p->report_list); + p->async_done = 0; } -// points to parent thread's TLS in agent threads -static _Thread_local ThreadLocalStorage *tls; - typedef struct { struct list_head link; js_thread_t tid; @@ -597,17 +596,20 @@ static void add_helpers(JSContext *ctx); static void *agent_start(void *arg) { - Test262Agent *agent = arg; + ThreadLocalStorage *tls; + Test262Agent *agent; JSRuntime *rt; JSContext *ctx; JSValue ret_val; int ret; + agent = arg; tls = agent->tls; // shares thread-local storage with parent thread rt = JS_NewRuntime(); if (rt == NULL) { fatal(1, "JS_NewRuntime failure"); } + JS_SetRuntimeOpaque(rt, tls); ctx = JS_NewContext(rt); if (ctx == NULL) { JS_FreeRuntime(rt); @@ -674,6 +676,7 @@ static void *agent_start(void *arg) static JSValue js_agent_start(JSContext *ctx, JSValue this_val, int argc, JSValue *argv) { + ThreadLocalStorage *tls = JS_GetRuntimeOpaque(JS_GetRuntime(ctx)); const char *script; Test262Agent *agent; @@ -697,6 +700,7 @@ static JSValue js_agent_start(JSContext *ctx, JSValue this_val, static void js_agent_free(JSContext *ctx) { + ThreadLocalStorage *tls = JS_GetRuntimeOpaque(JS_GetRuntime(ctx)); struct list_head *el, *el1; Test262Agent *agent; @@ -719,7 +723,7 @@ static JSValue js_agent_leaving(JSContext *ctx, JSValue this_val, return JS_UNDEFINED; } -static BOOL is_broadcast_pending(void) +static BOOL is_broadcast_pending(ThreadLocalStorage *tls) { struct list_head *el; Test262Agent *agent; @@ -734,6 +738,7 @@ static BOOL is_broadcast_pending(void) static JSValue js_agent_broadcast(JSContext *ctx, JSValue this_val, int argc, JSValue *argv) { + ThreadLocalStorage *tls = JS_GetRuntimeOpaque(JS_GetRuntime(ctx)); JSValue sab = argv[0]; struct list_head *el; Test262Agent *agent; @@ -765,7 +770,7 @@ static JSValue js_agent_broadcast(JSContext *ctx, JSValue this_val, } js_cond_broadcast(&tls->agent_cond); - while (is_broadcast_pending()) { + while (is_broadcast_pending(tls)) { js_cond_wait(&tls->agent_cond, &tls->agent_mutex); } js_mutex_unlock(&tls->agent_mutex); @@ -819,6 +824,7 @@ static JSValue js_agent_monotonicNow(JSContext *ctx, JSValue this_val, static JSValue js_agent_getReport(JSContext *ctx, JSValue this_val, int argc, JSValue *argv) { + ThreadLocalStorage *tls = JS_GetRuntimeOpaque(JS_GetRuntime(ctx)); AgentReport *rep; JSValue ret; @@ -843,6 +849,7 @@ static JSValue js_agent_getReport(JSContext *ctx, JSValue this_val, static JSValue js_agent_report(JSContext *ctx, JSValue this_val, int argc, JSValue *argv) { + ThreadLocalStorage *tls = JS_GetRuntimeOpaque(JS_GetRuntime(ctx)); const char *str; AgentReport *rep; @@ -1338,6 +1345,7 @@ static int eval_buf(JSContext *ctx, const char *buf, size_t buf_len, const char *error_type, int eval_flags, int is_async, int *msec) { + ThreadLocalStorage *tls = JS_GetRuntimeOpaque(JS_GetRuntime(ctx)); JSValue res_val, exception_val; int ret, error_line, pos, pos_line; BOOL is_error, has_error_line, ret_promise; @@ -1352,7 +1360,7 @@ static int eval_buf(JSContext *ctx, const char *buf, size_t buf_len, /* a module evaluation returns a promise */ ret_promise = ((eval_flags & JS_EVAL_TYPE_MODULE) != 0); - async_done = 0; /* counter of "Test262:AsyncTestComplete" messages */ + tls->async_done = 0; /* counter of "Test262:AsyncTestComplete" messages */ start = get_clock_ms(); res_val = JS_Eval(ctx, buf, buf_len, filename, eval_flags); @@ -1373,7 +1381,7 @@ static int eval_buf(JSContext *ctx, const char *buf, size_t buf_len, } else if (ret == 0) { if (is_async) { /* test if the test called $DONE() once */ - if (async_done != 1) { + if (tls->async_done != 1) { res_val = JS_ThrowTypeError(ctx, "$DONE() not called"); } else { res_val = JS_UNDEFINED; @@ -1721,10 +1729,10 @@ JSContext *JS_NewCustomContext(JSRuntime *rt) return ctx; } -int run_test_buf(const char *filename, char *harness, namelist_t *ip, - char *buf, size_t buf_len, const char* error_type, - int eval_flags, BOOL is_negative, BOOL is_async, - BOOL can_block, int *msec) +int run_test_buf(ThreadLocalStorage *tls, const char *filename, char *harness, + namelist_t *ip, char *buf, size_t buf_len, + const char* error_type, int eval_flags, BOOL is_negative, + BOOL is_async, BOOL can_block, int *msec) { JSRuntime *rt; JSContext *ctx; @@ -1734,6 +1742,7 @@ int run_test_buf(const char *filename, char *harness, namelist_t *ip, if (rt == NULL) { fatal(1, "JS_NewRuntime failure"); } + JS_SetRuntimeOpaque(rt, tls); js_std_init_handlers(rt); ctx = JS_NewCustomContext(rt); if (ctx == NULL) { @@ -1782,7 +1791,7 @@ int run_test_buf(const char *filename, char *harness, namelist_t *ip, return ret; } -int run_test(const char *filename, int *msec) +int run_test(ThreadLocalStorage *tls, const char *filename, int *msec) { char harnessbuf[1024]; char *harness; @@ -1943,12 +1952,12 @@ int run_test(const char *filename, int *msec) } ret = 0; if (use_nostrict) { - ret = run_test_buf(filename, harness, ip, buf, buf_len, + ret = run_test_buf(tls, filename, harness, ip, buf, buf_len, error_type, eval_flags, is_negative, is_async, can_block, msec); } if (use_strict) { - ret |= run_test_buf(filename, harness, ip, buf, buf_len, + ret |= run_test_buf(tls, filename, harness, ip, buf, buf_len, error_type, eval_flags | JS_EVAL_FLAG_STRICT, is_negative, is_async, can_block, msec); } @@ -1961,7 +1970,8 @@ int run_test(const char *filename, int *msec) } /* run a test when called by test262-harness+eshost */ -int run_test262_harness_test(const char *filename, BOOL is_module) +int run_test262_harness_test(ThreadLocalStorage *tls, const char *filename, + BOOL is_module) { JSRuntime *rt; JSContext *ctx; @@ -1977,6 +1987,7 @@ int run_test262_harness_test(const char *filename, BOOL is_module) if (rt == NULL) { fatal(1, "JS_NewRuntime failure"); } + JS_SetRuntimeOpaque(rt, tls); ctx = JS_NewContext(rt); if (ctx == NULL) { JS_FreeRuntime(rt); @@ -2072,10 +2083,10 @@ int include_exclude_or_skip(int i) // naming is hard... void *run_test_dir_list(void *arg) { + ThreadLocalStorage tls_s, *tls = &tls_s; const char *p; int i, msec; - tls = &(ThreadLocalStorage){}; init_thread_local_storage(tls); for (i = (uintptr_t)arg; i < test_list.count; i += nthreads) { @@ -2083,7 +2094,7 @@ void *run_test_dir_list(void *arg) continue; p = test_list.array[i]; msec = 0; - run_test(p, &msec); + run_test(tls, p, &msec); if (verbose > 1 || (slow_test_threshold && msec >= slow_test_threshold)) fprintf(stderr, "%s (%d ms)\n", p, msec); } @@ -2124,6 +2135,7 @@ char *get_opt_arg(const char *option, char *arg) int main(int argc, char **argv) { + ThreadLocalStorage tls_s, *tls = &tls_s; int i, optind; BOOL is_dir_list; BOOL only_check_errors = FALSE; @@ -2134,7 +2146,6 @@ int main(int argc, char **argv) js_std_set_worker_new_context_func(JS_NewCustomContext); - tls = &(ThreadLocalStorage){}; init_thread_local_storage(tls); js_mutex_init(&stats_mutex); @@ -2209,7 +2220,7 @@ int main(int argc, char **argv) help(); if (is_test262_harness) { - return run_test262_harness_test(argv[optind], is_module); + return run_test262_harness_test(tls, argv[optind], is_module); } nthreads = max_int(nthreads, 1); @@ -2276,7 +2287,7 @@ int main(int argc, char **argv) } else { while (optind < argc) { int msec = 0; - run_test(argv[optind++], &msec); + run_test(tls, argv[optind++], &msec); } }