quickjs 0.19.0 → 0.20.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/quickjsrb/quickjs/cutils.c +31 -23
- data/ext/quickjsrb/quickjs/cutils.h +40 -6
- data/ext/quickjsrb/quickjs/libregexp-opcode.h +14 -8
- data/ext/quickjsrb/quickjs/libregexp.c +658 -490
- data/ext/quickjsrb/quickjs/libregexp.h +4 -0
- data/ext/quickjsrb/quickjs/libunicode-table.h +2273 -2216
- data/ext/quickjsrb/quickjs/libunicode.c +3 -2
- data/ext/quickjsrb/quickjs/libunicode.h +10 -0
- data/ext/quickjsrb/quickjs/qjs.c +24 -7
- data/ext/quickjsrb/quickjs/quickjs-atom.h +13 -0
- data/ext/quickjsrb/quickjs/quickjs-libc.c +90 -29
- data/ext/quickjsrb/quickjs/quickjs-opcode.h +5 -9
- data/ext/quickjsrb/quickjs/quickjs.c +7997 -2829
- data/ext/quickjsrb/quickjs/quickjs.h +35 -23
- data/ext/quickjsrb/quickjs/run-test262.c +377 -150
- data/ext/quickjsrb/quickjs/unicode_gen_def.h +5 -0
- data/lib/quickjs/version.rb +1 -1
- data/polyfills/package-lock.json +2 -2
- data/polyfills/package.json +1 -1
- metadata +1 -1
|
@@ -34,27 +34,66 @@
|
|
|
34
34
|
#include <time.h>
|
|
35
35
|
#include <dirent.h>
|
|
36
36
|
#include <ftw.h>
|
|
37
|
+
#include <stdatomic.h>
|
|
38
|
+
#include <pthread.h>
|
|
39
|
+
#ifdef _WIN32
|
|
40
|
+
#include <windows.h>
|
|
41
|
+
#endif
|
|
37
42
|
|
|
38
43
|
#include "cutils.h"
|
|
39
44
|
#include "list.h"
|
|
40
45
|
#include "quickjs-libc.h"
|
|
41
46
|
|
|
42
|
-
/* enable test262 thread support to test SharedArrayBuffer and Atomics */
|
|
43
|
-
#define CONFIG_AGENT
|
|
44
|
-
|
|
45
47
|
#define CMD_NAME "run-test262"
|
|
46
48
|
|
|
47
49
|
typedef struct namelist_t {
|
|
48
50
|
char **array;
|
|
49
51
|
int count;
|
|
50
52
|
int size;
|
|
51
|
-
unsigned int sorted : 1;
|
|
52
53
|
} namelist_t;
|
|
53
54
|
|
|
55
|
+
/* per execution thread context */
|
|
56
|
+
typedef struct {
|
|
57
|
+
pthread_mutex_t agent_mutex;
|
|
58
|
+
pthread_cond_t agent_cond;
|
|
59
|
+
/* list of Test262Agent.link */
|
|
60
|
+
struct list_head agent_list;
|
|
61
|
+
|
|
62
|
+
pthread_mutex_t report_mutex;
|
|
63
|
+
/* list of AgentReport.link */
|
|
64
|
+
struct list_head report_list;
|
|
65
|
+
|
|
66
|
+
int async_done;
|
|
67
|
+
} ThreadLocalStorage;
|
|
68
|
+
|
|
69
|
+
typedef struct {
|
|
70
|
+
struct list_head link;
|
|
71
|
+
ThreadLocalStorage *tls;
|
|
72
|
+
pthread_t tid;
|
|
73
|
+
char *script;
|
|
74
|
+
JSValue broadcast_func;
|
|
75
|
+
BOOL broadcast_pending;
|
|
76
|
+
JSValue broadcast_sab; /* in the main context */
|
|
77
|
+
uint8_t *broadcast_sab_buf;
|
|
78
|
+
size_t broadcast_sab_size;
|
|
79
|
+
int32_t broadcast_val;
|
|
80
|
+
} Test262Agent;
|
|
81
|
+
|
|
82
|
+
typedef struct {
|
|
83
|
+
struct list_head link;
|
|
84
|
+
char *str;
|
|
85
|
+
} AgentReport;
|
|
86
|
+
|
|
54
87
|
namelist_t test_list;
|
|
55
88
|
namelist_t exclude_list;
|
|
56
89
|
namelist_t exclude_dir_list;
|
|
57
90
|
|
|
91
|
+
int nthreads;
|
|
92
|
+
pthread_t progress_thread;
|
|
93
|
+
BOOL progress_exit_request;
|
|
94
|
+
pthread_cond_t progress_cond;
|
|
95
|
+
pthread_mutex_t progress_mutex;
|
|
96
|
+
|
|
58
97
|
FILE *outfile;
|
|
59
98
|
enum test_mode_t {
|
|
60
99
|
TEST_DEFAULT_NOSTRICT, /* run tests as nostrict unless test is flagged as strictonly */
|
|
@@ -73,6 +112,7 @@ int stats_count;
|
|
|
73
112
|
JSMemoryUsage stats_all, stats_avg, stats_min, stats_max;
|
|
74
113
|
char *stats_min_filename;
|
|
75
114
|
char *stats_max_filename;
|
|
115
|
+
pthread_mutex_t stats_mutex;
|
|
76
116
|
int verbose;
|
|
77
117
|
char *harness_dir;
|
|
78
118
|
char *harness_exclude;
|
|
@@ -84,13 +124,115 @@ char *error_file;
|
|
|
84
124
|
FILE *error_out;
|
|
85
125
|
char *report_filename;
|
|
86
126
|
int update_errors;
|
|
87
|
-
int
|
|
88
|
-
int
|
|
89
|
-
int
|
|
127
|
+
int slow_test_threshold;
|
|
128
|
+
int start_index, stop_index;
|
|
129
|
+
int test_excluded;
|
|
130
|
+
_Atomic int test_count, test_failed, test_skipped;
|
|
131
|
+
_Atomic int new_errors, changed_errors, fixed_errors;
|
|
90
132
|
|
|
91
133
|
void warning(const char *, ...) __attribute__((__format__(__printf__, 1, 2)));
|
|
92
134
|
void fatal(int, const char *, ...) __attribute__((__format__(__printf__, 2, 3)));
|
|
93
135
|
|
|
136
|
+
void atomic_inc(volatile _Atomic int *p)
|
|
137
|
+
{
|
|
138
|
+
atomic_fetch_add(p, 1);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
#if defined(_WIN32)
|
|
142
|
+
static int cpu_count(void)
|
|
143
|
+
{
|
|
144
|
+
DWORD_PTR procmask, sysmask;
|
|
145
|
+
long count;
|
|
146
|
+
int i;
|
|
147
|
+
|
|
148
|
+
count = 0;
|
|
149
|
+
if (GetProcessAffinityMask(GetCurrentProcess(), &procmask, &sysmask))
|
|
150
|
+
for (i = 0; i < 8 * sizeof(procmask); i++)
|
|
151
|
+
count += 1 & (procmask >> i);
|
|
152
|
+
return count;
|
|
153
|
+
}
|
|
154
|
+
#elif defined(__linux__)
|
|
155
|
+
/* return the number of available physical cores or -1 if not available */
|
|
156
|
+
static int get_cpu_info_physical_cores(void)
|
|
157
|
+
{
|
|
158
|
+
FILE *f;
|
|
159
|
+
int nb_cores, physical_id;
|
|
160
|
+
char line[1024], *p;
|
|
161
|
+
char *field, *value;
|
|
162
|
+
int len;
|
|
163
|
+
|
|
164
|
+
f = fopen("/proc/cpuinfo", "rb");
|
|
165
|
+
if (!f)
|
|
166
|
+
return -1;
|
|
167
|
+
nb_cores = 0;
|
|
168
|
+
physical_id = -1;
|
|
169
|
+
for(;;) {
|
|
170
|
+
if (fgets(line, sizeof(line), f) == NULL)
|
|
171
|
+
break;
|
|
172
|
+
len = strlen(line);
|
|
173
|
+
while (len > 0 && isspace(line[len - 1]))
|
|
174
|
+
len--;
|
|
175
|
+
line[len] = '\0';
|
|
176
|
+
field = line;
|
|
177
|
+
p = line;
|
|
178
|
+
if (*p == '#')
|
|
179
|
+
continue;
|
|
180
|
+
while (*p != ':' && *p != '\0')
|
|
181
|
+
p++;
|
|
182
|
+
if (*p == '\0')
|
|
183
|
+
continue;
|
|
184
|
+
*p = '\0';
|
|
185
|
+
p++;
|
|
186
|
+
while (isspace(*p))
|
|
187
|
+
p++;
|
|
188
|
+
value = p;
|
|
189
|
+
|
|
190
|
+
len = strlen(field);
|
|
191
|
+
while (len > 0 && isspace(field[len - 1]))
|
|
192
|
+
len--;
|
|
193
|
+
field[len] = '\0';
|
|
194
|
+
|
|
195
|
+
// printf("'%s' '%s'\n", field, value);
|
|
196
|
+
if (!strcmp(field, "cpu cores")) {
|
|
197
|
+
if (nb_cores == 0) {
|
|
198
|
+
nb_cores = strtol(value, NULL, 0);
|
|
199
|
+
}
|
|
200
|
+
} else if (!strcmp(field, "physical id")) {
|
|
201
|
+
physical_id = max_int(physical_id, strtol(value, NULL, 0));
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
fclose(f);
|
|
205
|
+
// printf("nb_cores=%d physical_id=%d\n", nb_cores, physical_id);
|
|
206
|
+
if (nb_cores <= 0 || physical_id < 0)
|
|
207
|
+
return -1;
|
|
208
|
+
return nb_cores * (physical_id + 1);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
static int cpu_count(void)
|
|
212
|
+
{
|
|
213
|
+
int n = get_cpu_info_physical_cores();
|
|
214
|
+
if (n <= 0)
|
|
215
|
+
n = 1;
|
|
216
|
+
return n;
|
|
217
|
+
}
|
|
218
|
+
#else /* __linux__ */
|
|
219
|
+
static int cpu_count(void)
|
|
220
|
+
{
|
|
221
|
+
return sysconf(_SC_NPROCESSORS_ONLN);
|
|
222
|
+
}
|
|
223
|
+
#endif /* !__linux__ */
|
|
224
|
+
|
|
225
|
+
static void init_thread_local_storage(ThreadLocalStorage *tls)
|
|
226
|
+
{
|
|
227
|
+
memset(tls, 0, sizeof(*tls));
|
|
228
|
+
pthread_mutex_init(&tls->agent_mutex, NULL);
|
|
229
|
+
pthread_cond_init(&tls->agent_cond, NULL);
|
|
230
|
+
init_list_head(&tls->agent_list);
|
|
231
|
+
|
|
232
|
+
pthread_mutex_init(&tls->report_mutex, NULL);
|
|
233
|
+
init_list_head(&tls->report_list);
|
|
234
|
+
}
|
|
235
|
+
|
|
94
236
|
void warning(const char *fmt, ...)
|
|
95
237
|
{
|
|
96
238
|
va_list ap;
|
|
@@ -263,16 +405,13 @@ void namelist_sort(namelist_t *lp)
|
|
|
263
405
|
}
|
|
264
406
|
lp->count = count;
|
|
265
407
|
}
|
|
266
|
-
lp->sorted = 1;
|
|
267
408
|
}
|
|
268
409
|
|
|
269
|
-
|
|
410
|
+
/* the list must be sorted */
|
|
411
|
+
int namelist_find(const namelist_t *lp, const char *name)
|
|
270
412
|
{
|
|
271
413
|
int a, b, m, cmp;
|
|
272
414
|
|
|
273
|
-
if (!lp->sorted) {
|
|
274
|
-
namelist_sort(lp);
|
|
275
|
-
}
|
|
276
415
|
for (a = 0, b = lp->count; a < b;) {
|
|
277
416
|
m = a + (b - a) / 2;
|
|
278
417
|
cmp = namelist_cmp(lp->array[m], name);
|
|
@@ -382,33 +521,37 @@ static void js_print_value_write(void *opaque, const char *buf, size_t len)
|
|
|
382
521
|
static JSValue js_print(JSContext *ctx, JSValueConst this_val,
|
|
383
522
|
int argc, JSValueConst *argv)
|
|
384
523
|
{
|
|
524
|
+
ThreadLocalStorage *tls = JS_GetRuntimeOpaque(JS_GetRuntime(ctx));
|
|
385
525
|
int i;
|
|
386
526
|
JSValueConst v;
|
|
387
527
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
528
|
+
for (i = 0; i < argc; i++) {
|
|
529
|
+
if (i != 0 && outfile)
|
|
530
|
+
fputc(' ', outfile);
|
|
531
|
+
v = argv[i];
|
|
532
|
+
if (JS_IsString(v)) {
|
|
533
|
+
const char *str;
|
|
534
|
+
size_t len;
|
|
535
|
+
str = JS_ToCStringLen(ctx, &len, v);
|
|
536
|
+
if (!str)
|
|
537
|
+
return JS_EXCEPTION;
|
|
538
|
+
if (!strcmp(str, "Test262:AsyncTestComplete")) {
|
|
539
|
+
tls->async_done++;
|
|
540
|
+
} else if (strstart(str, "Test262:AsyncTestFailure", NULL)) {
|
|
541
|
+
tls->async_done = 2; /* force an error */
|
|
542
|
+
}
|
|
543
|
+
if (outfile) {
|
|
404
544
|
fwrite(str, 1, len, outfile);
|
|
405
|
-
|
|
406
|
-
|
|
545
|
+
}
|
|
546
|
+
JS_FreeCString(ctx, str);
|
|
547
|
+
} else {
|
|
548
|
+
if (outfile) {
|
|
407
549
|
JS_PrintValue(ctx, js_print_value_write, outfile, v, NULL);
|
|
408
550
|
}
|
|
409
551
|
}
|
|
410
|
-
fputc('\n', outfile);
|
|
411
552
|
}
|
|
553
|
+
if (outfile)
|
|
554
|
+
fputc('\n', outfile);
|
|
412
555
|
return JS_UNDEFINED;
|
|
413
556
|
}
|
|
414
557
|
|
|
@@ -433,42 +576,13 @@ static JSValue js_evalScript(JSContext *ctx, JSValue this_val,
|
|
|
433
576
|
return ret;
|
|
434
577
|
}
|
|
435
578
|
|
|
436
|
-
#ifdef CONFIG_AGENT
|
|
437
|
-
|
|
438
|
-
#include <pthread.h>
|
|
439
|
-
|
|
440
|
-
typedef struct {
|
|
441
|
-
struct list_head link;
|
|
442
|
-
pthread_t tid;
|
|
443
|
-
char *script;
|
|
444
|
-
JSValue broadcast_func;
|
|
445
|
-
BOOL broadcast_pending;
|
|
446
|
-
JSValue broadcast_sab; /* in the main context */
|
|
447
|
-
uint8_t *broadcast_sab_buf;
|
|
448
|
-
size_t broadcast_sab_size;
|
|
449
|
-
int32_t broadcast_val;
|
|
450
|
-
} Test262Agent;
|
|
451
|
-
|
|
452
|
-
typedef struct {
|
|
453
|
-
struct list_head link;
|
|
454
|
-
char *str;
|
|
455
|
-
} AgentReport;
|
|
456
|
-
|
|
457
579
|
static JSValue add_helpers1(JSContext *ctx);
|
|
458
580
|
static void add_helpers(JSContext *ctx);
|
|
459
581
|
|
|
460
|
-
static pthread_mutex_t agent_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
461
|
-
static pthread_cond_t agent_cond = PTHREAD_COND_INITIALIZER;
|
|
462
|
-
/* list of Test262Agent.link */
|
|
463
|
-
static struct list_head agent_list = LIST_HEAD_INIT(agent_list);
|
|
464
|
-
|
|
465
|
-
static pthread_mutex_t report_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
466
|
-
/* list of AgentReport.link */
|
|
467
|
-
static struct list_head report_list = LIST_HEAD_INIT(report_list);
|
|
468
|
-
|
|
469
582
|
static void *agent_start(void *arg)
|
|
470
583
|
{
|
|
471
584
|
Test262Agent *agent = arg;
|
|
585
|
+
ThreadLocalStorage *tls = agent->tls;
|
|
472
586
|
JSRuntime *rt;
|
|
473
587
|
JSContext *ctx;
|
|
474
588
|
JSValue ret_val;
|
|
@@ -478,6 +592,7 @@ static void *agent_start(void *arg)
|
|
|
478
592
|
if (rt == NULL) {
|
|
479
593
|
fatal(1, "JS_NewRuntime failure");
|
|
480
594
|
}
|
|
595
|
+
JS_SetRuntimeOpaque(rt, tls);
|
|
481
596
|
ctx = JS_NewContext(rt);
|
|
482
597
|
if (ctx == NULL) {
|
|
483
598
|
JS_FreeRuntime(rt);
|
|
@@ -507,15 +622,15 @@ static void *agent_start(void *arg)
|
|
|
507
622
|
} else {
|
|
508
623
|
JSValue args[2];
|
|
509
624
|
|
|
510
|
-
pthread_mutex_lock(&agent_mutex);
|
|
625
|
+
pthread_mutex_lock(&tls->agent_mutex);
|
|
511
626
|
while (!agent->broadcast_pending) {
|
|
512
|
-
pthread_cond_wait(&agent_cond, &agent_mutex);
|
|
627
|
+
pthread_cond_wait(&tls->agent_cond, &tls->agent_mutex);
|
|
513
628
|
}
|
|
514
629
|
|
|
515
630
|
agent->broadcast_pending = FALSE;
|
|
516
|
-
pthread_cond_signal(&agent_cond);
|
|
631
|
+
pthread_cond_signal(&tls->agent_cond);
|
|
517
632
|
|
|
518
|
-
pthread_mutex_unlock(&agent_mutex);
|
|
633
|
+
pthread_mutex_unlock(&tls->agent_mutex);
|
|
519
634
|
|
|
520
635
|
args[0] = JS_NewArrayBuffer(ctx, agent->broadcast_sab_buf,
|
|
521
636
|
agent->broadcast_sab_size,
|
|
@@ -543,6 +658,7 @@ static void *agent_start(void *arg)
|
|
|
543
658
|
static JSValue js_agent_start(JSContext *ctx, JSValue this_val,
|
|
544
659
|
int argc, JSValue *argv)
|
|
545
660
|
{
|
|
661
|
+
ThreadLocalStorage *tls = JS_GetRuntimeOpaque(JS_GetRuntime(ctx));
|
|
546
662
|
const char *script;
|
|
547
663
|
Test262Agent *agent;
|
|
548
664
|
pthread_attr_t attr;
|
|
@@ -555,11 +671,12 @@ static JSValue js_agent_start(JSContext *ctx, JSValue this_val,
|
|
|
555
671
|
return JS_EXCEPTION;
|
|
556
672
|
agent = malloc(sizeof(*agent));
|
|
557
673
|
memset(agent, 0, sizeof(*agent));
|
|
674
|
+
agent->tls = tls;
|
|
558
675
|
agent->broadcast_func = JS_UNDEFINED;
|
|
559
676
|
agent->broadcast_sab = JS_UNDEFINED;
|
|
560
677
|
agent->script = strdup(script);
|
|
561
678
|
JS_FreeCString(ctx, script);
|
|
562
|
-
list_add_tail(&agent->link, &agent_list);
|
|
679
|
+
list_add_tail(&agent->link, &tls->agent_list);
|
|
563
680
|
pthread_attr_init(&attr);
|
|
564
681
|
// musl libc gives threads 80 kb stacks, much smaller than
|
|
565
682
|
// JS_DEFAULT_STACK_SIZE (256 kb)
|
|
@@ -571,10 +688,11 @@ static JSValue js_agent_start(JSContext *ctx, JSValue this_val,
|
|
|
571
688
|
|
|
572
689
|
static void js_agent_free(JSContext *ctx)
|
|
573
690
|
{
|
|
691
|
+
ThreadLocalStorage *tls = JS_GetRuntimeOpaque(JS_GetRuntime(ctx));
|
|
574
692
|
struct list_head *el, *el1;
|
|
575
693
|
Test262Agent *agent;
|
|
576
694
|
|
|
577
|
-
list_for_each_safe(el, el1, &agent_list) {
|
|
695
|
+
list_for_each_safe(el, el1, &tls->agent_list) {
|
|
578
696
|
agent = list_entry(el, Test262Agent, link);
|
|
579
697
|
pthread_join(agent->tid, NULL);
|
|
580
698
|
JS_FreeValue(ctx, agent->broadcast_sab);
|
|
@@ -593,11 +711,11 @@ static JSValue js_agent_leaving(JSContext *ctx, JSValue this_val,
|
|
|
593
711
|
return JS_UNDEFINED;
|
|
594
712
|
}
|
|
595
713
|
|
|
596
|
-
static BOOL is_broadcast_pending(
|
|
714
|
+
static BOOL is_broadcast_pending(ThreadLocalStorage *tls)
|
|
597
715
|
{
|
|
598
716
|
struct list_head *el;
|
|
599
717
|
Test262Agent *agent;
|
|
600
|
-
list_for_each(el, &agent_list) {
|
|
718
|
+
list_for_each(el, &tls->agent_list) {
|
|
601
719
|
agent = list_entry(el, Test262Agent, link);
|
|
602
720
|
if (agent->broadcast_pending)
|
|
603
721
|
return TRUE;
|
|
@@ -608,6 +726,7 @@ static BOOL is_broadcast_pending(void)
|
|
|
608
726
|
static JSValue js_agent_broadcast(JSContext *ctx, JSValue this_val,
|
|
609
727
|
int argc, JSValue *argv)
|
|
610
728
|
{
|
|
729
|
+
ThreadLocalStorage *tls = JS_GetRuntimeOpaque(JS_GetRuntime(ctx));
|
|
611
730
|
JSValueConst sab = argv[0];
|
|
612
731
|
struct list_head *el;
|
|
613
732
|
Test262Agent *agent;
|
|
@@ -626,8 +745,8 @@ static JSValue js_agent_broadcast(JSContext *ctx, JSValue this_val,
|
|
|
626
745
|
|
|
627
746
|
/* broadcast the values and wait until all agents have started
|
|
628
747
|
calling their callbacks */
|
|
629
|
-
pthread_mutex_lock(&agent_mutex);
|
|
630
|
-
list_for_each(el, &agent_list) {
|
|
748
|
+
pthread_mutex_lock(&tls->agent_mutex);
|
|
749
|
+
list_for_each(el, &tls->agent_list) {
|
|
631
750
|
agent = list_entry(el, Test262Agent, link);
|
|
632
751
|
agent->broadcast_pending = TRUE;
|
|
633
752
|
/* the shared array buffer is used by the thread, so increment
|
|
@@ -637,12 +756,12 @@ static JSValue js_agent_broadcast(JSContext *ctx, JSValue this_val,
|
|
|
637
756
|
agent->broadcast_sab_size = buf_size;
|
|
638
757
|
agent->broadcast_val = val;
|
|
639
758
|
}
|
|
640
|
-
pthread_cond_broadcast(&agent_cond);
|
|
759
|
+
pthread_cond_broadcast(&tls->agent_cond);
|
|
641
760
|
|
|
642
|
-
while (is_broadcast_pending()) {
|
|
643
|
-
pthread_cond_wait(&agent_cond, &agent_mutex);
|
|
761
|
+
while (is_broadcast_pending(tls)) {
|
|
762
|
+
pthread_cond_wait(&tls->agent_cond, &tls->agent_mutex);
|
|
644
763
|
}
|
|
645
|
-
pthread_mutex_unlock(&agent_mutex);
|
|
764
|
+
pthread_mutex_unlock(&tls->agent_mutex);
|
|
646
765
|
return JS_UNDEFINED;
|
|
647
766
|
}
|
|
648
767
|
|
|
@@ -685,17 +804,18 @@ static JSValue js_agent_monotonicNow(JSContext *ctx, JSValue this_val,
|
|
|
685
804
|
static JSValue js_agent_getReport(JSContext *ctx, JSValue this_val,
|
|
686
805
|
int argc, JSValue *argv)
|
|
687
806
|
{
|
|
807
|
+
ThreadLocalStorage *tls = JS_GetRuntimeOpaque(JS_GetRuntime(ctx));
|
|
688
808
|
AgentReport *rep;
|
|
689
809
|
JSValue ret;
|
|
690
810
|
|
|
691
|
-
pthread_mutex_lock(&report_mutex);
|
|
692
|
-
if (list_empty(&report_list)) {
|
|
811
|
+
pthread_mutex_lock(&tls->report_mutex);
|
|
812
|
+
if (list_empty(&tls->report_list)) {
|
|
693
813
|
rep = NULL;
|
|
694
814
|
} else {
|
|
695
|
-
rep = list_entry(report_list.next, AgentReport, link);
|
|
815
|
+
rep = list_entry(tls->report_list.next, AgentReport, link);
|
|
696
816
|
list_del(&rep->link);
|
|
697
817
|
}
|
|
698
|
-
pthread_mutex_unlock(&report_mutex);
|
|
818
|
+
pthread_mutex_unlock(&tls->report_mutex);
|
|
699
819
|
if (rep) {
|
|
700
820
|
ret = JS_NewString(ctx, rep->str);
|
|
701
821
|
free(rep->str);
|
|
@@ -709,6 +829,7 @@ static JSValue js_agent_getReport(JSContext *ctx, JSValue this_val,
|
|
|
709
829
|
static JSValue js_agent_report(JSContext *ctx, JSValue this_val,
|
|
710
830
|
int argc, JSValue *argv)
|
|
711
831
|
{
|
|
832
|
+
ThreadLocalStorage *tls = JS_GetRuntimeOpaque(JS_GetRuntime(ctx));
|
|
712
833
|
const char *str;
|
|
713
834
|
AgentReport *rep;
|
|
714
835
|
|
|
@@ -719,9 +840,9 @@ static JSValue js_agent_report(JSContext *ctx, JSValue this_val,
|
|
|
719
840
|
rep->str = strdup(str);
|
|
720
841
|
JS_FreeCString(ctx, str);
|
|
721
842
|
|
|
722
|
-
pthread_mutex_lock(&report_mutex);
|
|
723
|
-
list_add_tail(&rep->link, &report_list);
|
|
724
|
-
pthread_mutex_unlock(&report_mutex);
|
|
843
|
+
pthread_mutex_lock(&tls->report_mutex);
|
|
844
|
+
list_add_tail(&rep->link, &tls->report_list);
|
|
845
|
+
pthread_mutex_unlock(&tls->report_mutex);
|
|
725
846
|
return JS_UNDEFINED;
|
|
726
847
|
}
|
|
727
848
|
|
|
@@ -747,7 +868,6 @@ static JSValue js_new_agent(JSContext *ctx)
|
|
|
747
868
|
countof(js_agent_funcs));
|
|
748
869
|
return agent;
|
|
749
870
|
}
|
|
750
|
-
#endif
|
|
751
871
|
|
|
752
872
|
static JSValue js_createRealm(JSContext *ctx, JSValue this_val,
|
|
753
873
|
int argc, JSValue *argv)
|
|
@@ -798,9 +918,7 @@ static JSValue add_helpers1(JSContext *ctx)
|
|
|
798
918
|
JS_SetPropertyStr(ctx, obj262, "codePointRange",
|
|
799
919
|
JS_NewCFunction(ctx, js_string_codePointRange,
|
|
800
920
|
"codePointRange", 2));
|
|
801
|
-
#ifdef CONFIG_AGENT
|
|
802
921
|
JS_SetPropertyStr(ctx, obj262, "agent", js_new_agent(ctx));
|
|
803
|
-
#endif
|
|
804
922
|
|
|
805
923
|
JS_SetPropertyStr(ctx, obj262, "global",
|
|
806
924
|
JS_DupValue(ctx, global_obj));
|
|
@@ -947,7 +1065,7 @@ void update_exclude_dirs(void)
|
|
|
947
1065
|
char *name;
|
|
948
1066
|
int i, j, count;
|
|
949
1067
|
|
|
950
|
-
/* split
|
|
1068
|
+
/* split directories from exclude_list */
|
|
951
1069
|
for (count = i = 0; i < ep->count; i++) {
|
|
952
1070
|
name = ep->array[i];
|
|
953
1071
|
if (has_suffix(name, "/")) {
|
|
@@ -1245,6 +1363,7 @@ static int eval_buf(JSContext *ctx, const char *buf, size_t buf_len,
|
|
|
1245
1363
|
const char *error_type, FILE *outfile, int eval_flags,
|
|
1246
1364
|
int is_async)
|
|
1247
1365
|
{
|
|
1366
|
+
ThreadLocalStorage *tls = JS_GetRuntimeOpaque(JS_GetRuntime(ctx));
|
|
1248
1367
|
JSValue res_val, exception_val;
|
|
1249
1368
|
int ret, error_line, pos, pos_line;
|
|
1250
1369
|
BOOL is_error, has_error_line, ret_promise;
|
|
@@ -1258,7 +1377,7 @@ static int eval_buf(JSContext *ctx, const char *buf, size_t buf_len,
|
|
|
1258
1377
|
|
|
1259
1378
|
/* a module evaluation returns a promise */
|
|
1260
1379
|
ret_promise = ((eval_flags & JS_EVAL_TYPE_MODULE) != 0);
|
|
1261
|
-
async_done = 0; /* counter of "Test262:AsyncTestComplete" messages */
|
|
1380
|
+
tls->async_done = 0; /* counter of "Test262:AsyncTestComplete" messages */
|
|
1262
1381
|
|
|
1263
1382
|
res_val = JS_Eval(ctx, buf, buf_len, filename, eval_flags);
|
|
1264
1383
|
|
|
@@ -1277,7 +1396,7 @@ static int eval_buf(JSContext *ctx, const char *buf, size_t buf_len,
|
|
|
1277
1396
|
} else if (ret == 0) {
|
|
1278
1397
|
if (is_async) {
|
|
1279
1398
|
/* test if the test called $DONE() once */
|
|
1280
|
-
if (async_done != 1) {
|
|
1399
|
+
if (tls->async_done != 1) {
|
|
1281
1400
|
res_val = JS_ThrowTypeError(ctx, "$DONE() not called");
|
|
1282
1401
|
} else {
|
|
1283
1402
|
res_val = JS_UNDEFINED;
|
|
@@ -1545,6 +1664,8 @@ static char *get_option(char **pp, int *state)
|
|
|
1545
1664
|
void update_stats(JSRuntime *rt, const char *filename) {
|
|
1546
1665
|
JSMemoryUsage stats;
|
|
1547
1666
|
JS_ComputeMemoryUsage(rt, &stats);
|
|
1667
|
+
|
|
1668
|
+
pthread_mutex_lock(&stats_mutex);
|
|
1548
1669
|
if (stats_count++ == 0) {
|
|
1549
1670
|
stats_avg = stats_all = stats_min = stats_max = stats;
|
|
1550
1671
|
stats_min_filename = strdup(filename);
|
|
@@ -1587,9 +1708,11 @@ void update_stats(JSRuntime *rt, const char *filename) {
|
|
|
1587
1708
|
update(fast_array_elements);
|
|
1588
1709
|
}
|
|
1589
1710
|
#undef update
|
|
1711
|
+
pthread_mutex_unlock(&stats_mutex);
|
|
1590
1712
|
}
|
|
1591
1713
|
|
|
1592
|
-
int run_test_buf(
|
|
1714
|
+
int run_test_buf(ThreadLocalStorage *tls,
|
|
1715
|
+
const char *filename, const char *harness, namelist_t *ip,
|
|
1593
1716
|
char *buf, size_t buf_len, const char* error_type,
|
|
1594
1717
|
int eval_flags, BOOL is_negative, BOOL is_async,
|
|
1595
1718
|
BOOL can_block)
|
|
@@ -1602,6 +1725,7 @@ int run_test_buf(const char *filename, const char *harness, namelist_t *ip,
|
|
|
1602
1725
|
if (rt == NULL) {
|
|
1603
1726
|
fatal(1, "JS_NewRuntime failure");
|
|
1604
1727
|
}
|
|
1728
|
+
JS_SetRuntimeOpaque(rt, tls);
|
|
1605
1729
|
ctx = JS_NewContext(rt);
|
|
1606
1730
|
if (ctx == NULL) {
|
|
1607
1731
|
JS_FreeRuntime(rt);
|
|
@@ -1630,15 +1754,13 @@ int run_test_buf(const char *filename, const char *harness, namelist_t *ip,
|
|
|
1630
1754
|
if (dump_memory) {
|
|
1631
1755
|
update_stats(rt, filename);
|
|
1632
1756
|
}
|
|
1633
|
-
#ifdef CONFIG_AGENT
|
|
1634
1757
|
js_agent_free(ctx);
|
|
1635
|
-
#endif
|
|
1636
1758
|
JS_FreeContext(ctx);
|
|
1637
1759
|
JS_FreeRuntime(rt);
|
|
1638
1760
|
|
|
1639
|
-
test_count
|
|
1761
|
+
atomic_inc(&test_count);
|
|
1640
1762
|
if (ret) {
|
|
1641
|
-
test_failed
|
|
1763
|
+
atomic_inc(&test_failed);
|
|
1642
1764
|
if (outfile) {
|
|
1643
1765
|
/* do not output a failure number to minimize diff */
|
|
1644
1766
|
fprintf(outfile, " FAILED\n");
|
|
@@ -1647,7 +1769,7 @@ int run_test_buf(const char *filename, const char *harness, namelist_t *ip,
|
|
|
1647
1769
|
return ret;
|
|
1648
1770
|
}
|
|
1649
1771
|
|
|
1650
|
-
int run_test(const char *filename, int index)
|
|
1772
|
+
int run_test(ThreadLocalStorage *tls, const char *filename, int index)
|
|
1651
1773
|
{
|
|
1652
1774
|
char harnessbuf[1024];
|
|
1653
1775
|
char *harness;
|
|
@@ -1853,7 +1975,7 @@ int run_test(const char *filename, int index)
|
|
|
1853
1975
|
}
|
|
1854
1976
|
|
|
1855
1977
|
if (skip || use_strict + use_nostrict == 0) {
|
|
1856
|
-
test_skipped
|
|
1978
|
+
atomic_inc(&test_skipped);
|
|
1857
1979
|
ret = -2;
|
|
1858
1980
|
} else {
|
|
1859
1981
|
clock_t clocks;
|
|
@@ -1866,12 +1988,12 @@ int run_test(const char *filename, int index)
|
|
|
1866
1988
|
clocks = clock();
|
|
1867
1989
|
ret = 0;
|
|
1868
1990
|
if (use_nostrict) {
|
|
1869
|
-
ret = run_test_buf(filename, harness, ip, buf, buf_len,
|
|
1991
|
+
ret = run_test_buf(tls, filename, harness, ip, buf, buf_len,
|
|
1870
1992
|
error_type, eval_flags, is_negative, is_async,
|
|
1871
1993
|
can_block);
|
|
1872
1994
|
}
|
|
1873
1995
|
if (use_strict) {
|
|
1874
|
-
ret |= run_test_buf(filename, harness, ip, buf, buf_len,
|
|
1996
|
+
ret |= run_test_buf(tls, filename, harness, ip, buf, buf_len,
|
|
1875
1997
|
error_type, eval_flags | JS_EVAL_FLAG_STRICT,
|
|
1876
1998
|
is_negative, is_async, can_block);
|
|
1877
1999
|
}
|
|
@@ -1889,7 +2011,8 @@ int run_test(const char *filename, int index)
|
|
|
1889
2011
|
}
|
|
1890
2012
|
|
|
1891
2013
|
/* run a test when called by test262-harness+eshost */
|
|
1892
|
-
int run_test262_harness_test(
|
|
2014
|
+
int run_test262_harness_test(ThreadLocalStorage *tls,
|
|
2015
|
+
const char *filename, BOOL is_module, BOOL can_block)
|
|
1893
2016
|
{
|
|
1894
2017
|
JSRuntime *rt;
|
|
1895
2018
|
JSContext *ctx;
|
|
@@ -1897,7 +2020,6 @@ int run_test262_harness_test(const char *filename, BOOL is_module)
|
|
|
1897
2020
|
size_t buf_len;
|
|
1898
2021
|
int eval_flags, ret_code, ret;
|
|
1899
2022
|
JSValue res_val;
|
|
1900
|
-
BOOL can_block;
|
|
1901
2023
|
|
|
1902
2024
|
outfile = stdout; /* for js_print */
|
|
1903
2025
|
|
|
@@ -1905,6 +2027,7 @@ int run_test262_harness_test(const char *filename, BOOL is_module)
|
|
|
1905
2027
|
if (rt == NULL) {
|
|
1906
2028
|
fatal(1, "JS_NewRuntime failure");
|
|
1907
2029
|
}
|
|
2030
|
+
JS_SetRuntimeOpaque(rt, tls);
|
|
1908
2031
|
ctx = JS_NewContext(rt);
|
|
1909
2032
|
if (ctx == NULL) {
|
|
1910
2033
|
JS_FreeRuntime(rt);
|
|
@@ -1912,7 +2035,6 @@ int run_test262_harness_test(const char *filename, BOOL is_module)
|
|
|
1912
2035
|
}
|
|
1913
2036
|
JS_SetRuntimeInfo(rt, filename);
|
|
1914
2037
|
|
|
1915
|
-
can_block = TRUE;
|
|
1916
2038
|
JS_SetCanBlock(rt, can_block);
|
|
1917
2039
|
|
|
1918
2040
|
/* loader for ES6 modules */
|
|
@@ -1960,78 +2082,115 @@ int run_test262_harness_test(const char *filename, BOOL is_module)
|
|
|
1960
2082
|
JS_FreeValue(ctx, promise);
|
|
1961
2083
|
}
|
|
1962
2084
|
free(buf);
|
|
1963
|
-
#ifdef CONFIG_AGENT
|
|
1964
2085
|
js_agent_free(ctx);
|
|
1965
|
-
#endif
|
|
1966
2086
|
JS_FreeContext(ctx);
|
|
1967
2087
|
JS_FreeRuntime(rt);
|
|
1968
2088
|
return ret_code;
|
|
1969
2089
|
}
|
|
1970
2090
|
|
|
1971
|
-
|
|
2091
|
+
static int pthread_cond_timedwait2(pthread_cond_t *cond, pthread_mutex_t *mutex, int timeout)
|
|
2092
|
+
{
|
|
2093
|
+
struct timespec ts;
|
|
2094
|
+
|
|
2095
|
+
clock_gettime(CLOCK_REALTIME, &ts);
|
|
2096
|
+
ts.tv_sec += timeout / 1000;
|
|
2097
|
+
ts.tv_nsec += (timeout % 1000) * 1000000;
|
|
2098
|
+
if (ts.tv_nsec >= 1000000000) {
|
|
2099
|
+
ts.tv_nsec -= 1000000000;
|
|
2100
|
+
ts.tv_sec++;
|
|
2101
|
+
}
|
|
2102
|
+
return pthread_cond_timedwait(cond, mutex, &ts);
|
|
2103
|
+
}
|
|
2104
|
+
|
|
2105
|
+
void *show_progress(void *opaque)
|
|
2106
|
+
{
|
|
2107
|
+
int test_skipped1, test_failed1, test_count1;
|
|
2108
|
+
|
|
2109
|
+
pthread_mutex_lock(&progress_mutex);
|
|
2110
|
+
for(;;) {
|
|
2111
|
+
pthread_cond_timedwait2(&progress_cond, &progress_mutex, 50);
|
|
2112
|
+
|
|
2113
|
+
test_failed1 = atomic_load(&test_failed);
|
|
2114
|
+
test_count1 = atomic_load(&test_count);
|
|
2115
|
+
test_skipped1 = atomic_load(&test_skipped);
|
|
1972
2116
|
|
|
1973
|
-
void show_progress(int force) {
|
|
1974
|
-
clock_t t = clock();
|
|
1975
|
-
if (force || !last_clock || (t - last_clock) > CLOCKS_PER_SEC / 20) {
|
|
1976
|
-
last_clock = t;
|
|
1977
2117
|
if (compact) {
|
|
1978
2118
|
static int last_test_skipped;
|
|
1979
2119
|
static int last_test_failed;
|
|
1980
2120
|
static int dots;
|
|
1981
2121
|
char c = '.';
|
|
1982
|
-
|
|
2122
|
+
|
|
2123
|
+
if (test_skipped1 > last_test_skipped)
|
|
1983
2124
|
c = '-';
|
|
1984
|
-
if (
|
|
2125
|
+
if (test_failed1 > last_test_failed)
|
|
1985
2126
|
c = '!';
|
|
1986
|
-
last_test_skipped =
|
|
1987
|
-
last_test_failed =
|
|
2127
|
+
last_test_skipped = test_skipped1;
|
|
2128
|
+
last_test_failed = test_failed1;
|
|
2129
|
+
|
|
1988
2130
|
fputc(c, stderr);
|
|
1989
|
-
if (
|
|
2131
|
+
if (progress_exit_request || ++dots % 60 == 0) {
|
|
1990
2132
|
fprintf(stderr, " %d/%d/%d\n",
|
|
1991
|
-
|
|
2133
|
+
test_failed1, test_count1, test_skipped1);
|
|
1992
2134
|
}
|
|
1993
2135
|
} else {
|
|
1994
2136
|
/* output progress indicator: erase end of line and return to col 0 */
|
|
1995
2137
|
fprintf(stderr, "%d/%d/%d\033[K\r",
|
|
1996
|
-
|
|
2138
|
+
test_failed1, test_count1, test_skipped1);
|
|
1997
2139
|
}
|
|
1998
2140
|
fflush(stderr);
|
|
2141
|
+
if (progress_exit_request)
|
|
2142
|
+
break;
|
|
1999
2143
|
}
|
|
2144
|
+
pthread_mutex_unlock(&progress_mutex);
|
|
2145
|
+
return NULL;
|
|
2000
2146
|
}
|
|
2001
2147
|
|
|
2002
|
-
|
|
2148
|
+
enum { INCLUDE, EXCLUDE, SKIP };
|
|
2003
2149
|
|
|
2004
|
-
|
|
2150
|
+
int include_exclude_or_skip(int i) // naming is hard...
|
|
2005
2151
|
{
|
|
2006
|
-
|
|
2152
|
+
if (namelist_find(&exclude_list, test_list.array[i]) >= 0)
|
|
2153
|
+
return EXCLUDE;
|
|
2154
|
+
if (i < start_index)
|
|
2155
|
+
return SKIP;
|
|
2156
|
+
if (stop_index >= 0 && i > stop_index)
|
|
2157
|
+
return SKIP;
|
|
2158
|
+
return INCLUDE;
|
|
2159
|
+
}
|
|
2007
2160
|
|
|
2008
|
-
|
|
2009
|
-
|
|
2161
|
+
typedef struct {
|
|
2162
|
+
pthread_t tid;
|
|
2163
|
+
int thread_index;
|
|
2164
|
+
} RunTestDirThread;
|
|
2165
|
+
|
|
2166
|
+
void *run_test_dir_list(void *opaque)
|
|
2167
|
+
{
|
|
2168
|
+
RunTestDirThread *th = opaque;
|
|
2169
|
+
ThreadLocalStorage tls_s, *tls = &tls_s;
|
|
2170
|
+
namelist_t *lp = &test_list;
|
|
2171
|
+
int i;
|
|
2172
|
+
|
|
2173
|
+
init_thread_local_storage(tls);
|
|
2174
|
+
|
|
2175
|
+
for (i = th->thread_index; i < lp->count; i += nthreads) {
|
|
2010
2176
|
const char *p = lp->array[i];
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2177
|
+
int ti;
|
|
2178
|
+
if (INCLUDE != include_exclude_or_skip(i))
|
|
2179
|
+
continue;
|
|
2180
|
+
|
|
2181
|
+
if (slow_test_threshold != 0) {
|
|
2182
|
+
ti = get_clock_ms();
|
|
2017
2183
|
} else {
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
if (slow_test_threshold != 0) {
|
|
2026
|
-
ti = get_clock_ms() - ti;
|
|
2027
|
-
if (ti >= slow_test_threshold)
|
|
2028
|
-
fprintf(stderr, "\n%s (%d ms)\n", p, ti);
|
|
2029
|
-
}
|
|
2030
|
-
show_progress(FALSE);
|
|
2184
|
+
ti = 0;
|
|
2185
|
+
}
|
|
2186
|
+
run_test(tls, p, i);
|
|
2187
|
+
if (slow_test_threshold != 0) {
|
|
2188
|
+
ti = get_clock_ms() - ti;
|
|
2189
|
+
if (ti >= slow_test_threshold)
|
|
2190
|
+
fprintf(stderr, "\n%s (%d ms)\n", p, ti);
|
|
2031
2191
|
}
|
|
2032
|
-
test_index++;
|
|
2033
2192
|
}
|
|
2034
|
-
|
|
2193
|
+
return NULL;
|
|
2035
2194
|
}
|
|
2036
2195
|
|
|
2037
2196
|
void help(void)
|
|
@@ -2049,13 +2208,15 @@ void help(void)
|
|
|
2049
2208
|
"-t show timings\n"
|
|
2050
2209
|
"-u update error file\n"
|
|
2051
2210
|
"-v verbose: output error messages\n"
|
|
2052
|
-
"-
|
|
2211
|
+
"-D duration display tests taking more than 'duration' ms\n"
|
|
2212
|
+
"-T threads number of parallel threads\n"
|
|
2053
2213
|
"-c file read configuration from 'file'\n"
|
|
2054
2214
|
"-d dir run all test files in directory tree 'dir'\n"
|
|
2055
2215
|
"-e file load the known errors from 'file'\n"
|
|
2056
2216
|
"-f file execute single test from 'file'\n"
|
|
2057
2217
|
"-r file set the report file name (default=none)\n"
|
|
2058
|
-
"-x file exclude tests listed in 'file'\n"
|
|
2218
|
+
"-x file exclude tests listed in 'file'\n"
|
|
2219
|
+
"--no-can-block set [[CanBlock]] to false (Atomics.wait will throw)\n");
|
|
2059
2220
|
exit(1);
|
|
2060
2221
|
}
|
|
2061
2222
|
|
|
@@ -2069,15 +2230,20 @@ char *get_opt_arg(const char *option, char *arg)
|
|
|
2069
2230
|
|
|
2070
2231
|
int main(int argc, char **argv)
|
|
2071
2232
|
{
|
|
2072
|
-
|
|
2233
|
+
ThreadLocalStorage tls_s, *tls = &tls_s;
|
|
2234
|
+
int optind;
|
|
2073
2235
|
BOOL is_dir_list;
|
|
2074
2236
|
BOOL only_check_errors = FALSE;
|
|
2075
2237
|
const char *filename;
|
|
2076
2238
|
const char *ignore = "";
|
|
2077
2239
|
BOOL is_test262_harness = FALSE;
|
|
2078
2240
|
BOOL is_module = FALSE;
|
|
2241
|
+
BOOL can_block = TRUE;
|
|
2079
2242
|
BOOL count_skipped_features = FALSE;
|
|
2080
2243
|
clock_t clocks;
|
|
2244
|
+
|
|
2245
|
+
init_thread_local_storage(tls);
|
|
2246
|
+
pthread_mutex_init(&stats_mutex, NULL);
|
|
2081
2247
|
|
|
2082
2248
|
#if !defined(_WIN32)
|
|
2083
2249
|
compact = !isatty(STDERR_FILENO);
|
|
@@ -2091,7 +2257,7 @@ int main(int argc, char **argv)
|
|
|
2091
2257
|
if (*arg != '-')
|
|
2092
2258
|
break;
|
|
2093
2259
|
optind++;
|
|
2094
|
-
if (strstr("-c -d -e -x -f -r -E -T", arg))
|
|
2260
|
+
if (strstr("-c -d -e -x -f -r -E -D -T", arg))
|
|
2095
2261
|
optind++;
|
|
2096
2262
|
if (strstr("-d -f", arg))
|
|
2097
2263
|
ignore = "testdir"; // run only the tests from -d or -f
|
|
@@ -2138,12 +2304,16 @@ int main(int argc, char **argv)
|
|
|
2138
2304
|
report_filename = get_opt_arg(arg, argv[optind++]);
|
|
2139
2305
|
} else if (str_equal(arg, "-E")) {
|
|
2140
2306
|
only_check_errors = TRUE;
|
|
2141
|
-
} else if (str_equal(arg, "-
|
|
2307
|
+
} else if (str_equal(arg, "-D")) {
|
|
2142
2308
|
slow_test_threshold = atoi(get_opt_arg(arg, argv[optind++]));
|
|
2309
|
+
} else if (str_equal(arg, "-T")) {
|
|
2310
|
+
nthreads = atoi(get_opt_arg(arg, argv[optind++]));
|
|
2143
2311
|
} else if (str_equal(arg, "-N")) {
|
|
2144
2312
|
is_test262_harness = TRUE;
|
|
2145
2313
|
} else if (str_equal(arg, "--module")) {
|
|
2146
2314
|
is_module = TRUE;
|
|
2315
|
+
} else if (str_equal(arg, "--no-can-block")) {
|
|
2316
|
+
can_block = FALSE;
|
|
2147
2317
|
} else if (str_equal(arg, "--count_skipped_features")) {
|
|
2148
2318
|
count_skipped_features = TRUE;
|
|
2149
2319
|
} else {
|
|
@@ -2156,9 +2326,18 @@ int main(int argc, char **argv)
|
|
|
2156
2326
|
help();
|
|
2157
2327
|
|
|
2158
2328
|
if (is_test262_harness) {
|
|
2159
|
-
return run_test262_harness_test(argv[optind], is_module);
|
|
2329
|
+
return run_test262_harness_test(tls, argv[optind], is_module, can_block);
|
|
2160
2330
|
}
|
|
2161
2331
|
|
|
2332
|
+
if (nthreads == 0) {
|
|
2333
|
+
nthreads = cpu_count();
|
|
2334
|
+
if (nthreads >= 8) {
|
|
2335
|
+
// minus one to not (over)commit the system completely
|
|
2336
|
+
nthreads--;
|
|
2337
|
+
}
|
|
2338
|
+
}
|
|
2339
|
+
nthreads = max_int(nthreads, 1);
|
|
2340
|
+
|
|
2162
2341
|
error_out = stdout;
|
|
2163
2342
|
if (error_filename) {
|
|
2164
2343
|
error_file = load_file(error_filename, NULL);
|
|
@@ -2189,10 +2368,14 @@ int main(int argc, char **argv)
|
|
|
2189
2368
|
}
|
|
2190
2369
|
|
|
2191
2370
|
if (is_dir_list) {
|
|
2371
|
+
RunTestDirThread *threads;
|
|
2372
|
+
int i;
|
|
2373
|
+
|
|
2192
2374
|
if (optind < argc && !isdigit((unsigned char)argv[optind][0])) {
|
|
2193
2375
|
filename = argv[optind++];
|
|
2194
2376
|
namelist_load(&test_list, filename);
|
|
2195
2377
|
}
|
|
2378
|
+
|
|
2196
2379
|
start_index = 0;
|
|
2197
2380
|
stop_index = -1;
|
|
2198
2381
|
if (optind < argc) {
|
|
@@ -2201,7 +2384,8 @@ int main(int argc, char **argv)
|
|
|
2201
2384
|
stop_index = atoi(argv[optind++]);
|
|
2202
2385
|
}
|
|
2203
2386
|
}
|
|
2204
|
-
|
|
2387
|
+
/* XXX: could reorder the report and the errors when nthreads > 1 */
|
|
2388
|
+
if (!report_filename || str_equal(report_filename, "none") || nthreads > 1) {
|
|
2205
2389
|
outfile = NULL;
|
|
2206
2390
|
} else if (str_equal(report_filename, "-")) {
|
|
2207
2391
|
outfile = stdout;
|
|
@@ -2211,7 +2395,50 @@ int main(int argc, char **argv)
|
|
|
2211
2395
|
perror_exit(1, report_filename);
|
|
2212
2396
|
}
|
|
2213
2397
|
}
|
|
2214
|
-
|
|
2398
|
+
|
|
2399
|
+
// exclude_dir_list has already been sorted by update_exclude_dirs()
|
|
2400
|
+
namelist_sort(&test_list);
|
|
2401
|
+
namelist_sort(&exclude_list);
|
|
2402
|
+
|
|
2403
|
+
for (i = 0; i < test_list.count; i++) {
|
|
2404
|
+
switch (include_exclude_or_skip(i)) {
|
|
2405
|
+
case EXCLUDE:
|
|
2406
|
+
test_excluded++;
|
|
2407
|
+
break;
|
|
2408
|
+
case SKIP:
|
|
2409
|
+
test_skipped++;
|
|
2410
|
+
break;
|
|
2411
|
+
}
|
|
2412
|
+
}
|
|
2413
|
+
|
|
2414
|
+
pthread_cond_init(&progress_cond, NULL);
|
|
2415
|
+
pthread_mutex_init(&progress_mutex, NULL);
|
|
2416
|
+
pthread_create(&progress_thread, NULL, show_progress, NULL);
|
|
2417
|
+
|
|
2418
|
+
threads = malloc(sizeof(threads[0]) * nthreads);
|
|
2419
|
+
for (i = 0; i < nthreads; i++) {
|
|
2420
|
+
RunTestDirThread *th = &threads[i];
|
|
2421
|
+
pthread_attr_t attr;
|
|
2422
|
+
|
|
2423
|
+
th->thread_index = i;
|
|
2424
|
+
|
|
2425
|
+
pthread_attr_init(&attr);
|
|
2426
|
+
pthread_attr_setstacksize(&attr, 2 << 20); // 2 MB, glibc default
|
|
2427
|
+
pthread_create(&th->tid, &attr, run_test_dir_list, th);
|
|
2428
|
+
pthread_attr_destroy(&attr);
|
|
2429
|
+
}
|
|
2430
|
+
for (i = 0; i < nthreads; i++)
|
|
2431
|
+
pthread_join(threads[i].tid, NULL);
|
|
2432
|
+
free(threads);
|
|
2433
|
+
|
|
2434
|
+
pthread_mutex_lock(&progress_mutex);
|
|
2435
|
+
progress_exit_request = TRUE;
|
|
2436
|
+
pthread_cond_signal(&progress_cond);
|
|
2437
|
+
pthread_mutex_unlock(&progress_mutex);
|
|
2438
|
+
pthread_join(progress_thread, NULL);
|
|
2439
|
+
|
|
2440
|
+
pthread_mutex_destroy(&progress_mutex);
|
|
2441
|
+
pthread_cond_destroy(&progress_cond);
|
|
2215
2442
|
|
|
2216
2443
|
if (outfile && outfile != stdout) {
|
|
2217
2444
|
fclose(outfile);
|
|
@@ -2220,7 +2447,7 @@ int main(int argc, char **argv)
|
|
|
2220
2447
|
} else {
|
|
2221
2448
|
outfile = stdout;
|
|
2222
2449
|
while (optind < argc) {
|
|
2223
|
-
run_test(argv[optind++], -1);
|
|
2450
|
+
run_test(tls, argv[optind++], -1);
|
|
2224
2451
|
}
|
|
2225
2452
|
}
|
|
2226
2453
|
|
|
@@ -2279,7 +2506,7 @@ int main(int argc, char **argv)
|
|
|
2279
2506
|
}
|
|
2280
2507
|
fprintf(stderr, "\n");
|
|
2281
2508
|
if (show_timings)
|
|
2282
|
-
fprintf(stderr, "Total time: %.3fs\n", (double)clocks / CLOCKS_PER_SEC);
|
|
2509
|
+
fprintf(stderr, "Total user time: %.3fs (nthreads=%d)\n", (double)clocks / CLOCKS_PER_SEC, nthreads);
|
|
2283
2510
|
}
|
|
2284
2511
|
|
|
2285
2512
|
if (error_out && error_out != stdout) {
|