MIRROR: javascript for ๐Ÿœ's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

migrate to cached snapshot, move url module to prototypes

+1216 -172
+1
include/ant.h
··· 44 44 jsval_t js_mkscope(ant_t *); 45 45 jsval_t js_getscope(ant_t *); 46 46 jsval_t js_eval(ant_t *, const char *, size_t); 47 + jsval_t js_eval_cached(ant_t *, const char *, size_t); 47 48 48 49 void js_destroy(ant_t *); 49 50 void js_delscope(ant_t *);
+1
include/common.h
··· 55 55 SLOT_STRICT_ARGS, 56 56 SLOT_NO_FUNC_DECLS, 57 57 SLOT_ITER_STATE, 58 + SLOT_ENTRIES, 58 59 SLOT_MAX = 255 59 60 } internal_slot_t; 60 61
+49 -29
src/ant.c
··· 285 285 bool has_rest; 286 286 bool is_strict; 287 287 bool is_expr; 288 + bool uses_arguments; 288 289 jsoff_t rest_param_start; 289 290 jsoff_t rest_param_len; 290 291 UT_array *params; ··· 3035 3036 3036 3037 jsoff_t header = loadoff(js, head); 3037 3038 jsoff_t first_prop = header & ~(3U | FLAGMASK); 3038 - jsoff_t tail = loadoff(js, head + sizeof(jsoff_t) + sizeof(jsoff_t)); 3039 3039 3040 3040 jsoff_t slot_key = (jsoff_t)slot; 3041 3041 memcpy(buf, &slot_key, sizeof(slot_key)); 3042 3042 memcpy(buf + sizeof(slot_key), &v, sizeof(v)); 3043 3043 3044 3044 jsoff_t new_prop_off = js->brk; 3045 - jsval_t prop = mkentity(js, 0 | T_PROP | SLOTMASK, buf, sizeof(buf)); 3045 + jsval_t prop = mkentity(js, first_prop | T_PROP | SLOTMASK, buf, sizeof(buf)); 3046 3046 if (is_err(prop)) return prop; 3047 + 3048 + jsoff_t new_header = new_prop_off | (header & (3U | FLAGMASK)); 3049 + saveoff(js, head, new_header); 3047 3050 3048 3051 if (first_prop == 0) { 3049 - jsoff_t new_header = new_prop_off | (header & (3U | FLAGMASK)); 3050 - saveoff(js, head, new_header); 3051 - } else { 3052 - jsoff_t tail_header = loadoff(js, tail); 3053 - jsoff_t new_tail_header = new_prop_off | (tail_header & (3U | FLAGMASK)); 3054 - saveoff(js, tail, new_tail_header); 3052 + saveoff(js, head + sizeof(jsoff_t) + sizeof(jsoff_t), new_prop_off); 3055 3053 } 3056 - saveoff(js, head + sizeof(jsoff_t) + sizeof(jsoff_t), new_prop_off); 3057 3054 3058 3055 return prop; 3059 3056 } 3060 3057 3061 - static jsoff_t search_slot(struct js *js, jsval_t obj, internal_slot_t slot) { 3058 + static inline jsoff_t search_slot(struct js *js, jsval_t obj, internal_slot_t slot) { 3062 3059 jsoff_t off = (jsoff_t) vdata(obj); 3063 - if (off >= js->brk) return 0; 3060 + if (__builtin_expect(off >= js->brk, 0)) return 0; 3064 3061 jsoff_t next = loadoff(js, off) & ~(3U | FLAGMASK); 3065 3062 jsoff_t header, koff; 3066 3063 3067 3064 check: 3068 - if (next == 0 || next >= js->brk) return 0; 3065 + if (__builtin_expect(next == 0 || next >= js->brk, 0)) return 0; 3069 3066 header = loadoff(js, next); 3070 - if ((header & SLOTMASK) == 0) goto advance; 3067 + if ((header & SLOTMASK) == 0) return 0; 3071 3068 koff = loadoff(js, next + sizeof(jsoff_t)); 3072 3069 if (koff == (jsoff_t)slot) return next; 3073 - advance: 3074 3070 next = header & ~(3U | FLAGMASK); 3075 3071 goto check; 3076 3072 } ··· 6186 6182 return false; 6187 6183 } 6188 6184 6185 + static bool code_uses_arguments(const char *code, jsoff_t len) { 6186 + if (len < 9) return false; 6187 + for (jsoff_t i = 0; i + 8 < len; i++) { 6188 + if (code[i] == 'a' && memcmp(&code[i], INTERN_ARGUMENTS, 9) == 0) { 6189 + if (i > 0 && (is_alpha(code[i-1]) || code[i-1] == '_' || (code[i-1] >= '0' && code[i-1] <= '9'))) continue; 6190 + if (i + 9 < len && (is_alpha(code[i+9]) || code[i+9] == '_' || (code[i+9] >= '0' && code[i+9] <= '9'))) continue; 6191 + return true; 6192 + } 6193 + } return false; 6194 + } 6195 + 6189 6196 static parsed_func_t *get_or_parse_func(const char *fn, jsoff_t fnlen) { 6190 6197 uint64_t h = hash_key(fn, fnlen); 6191 6198 parsed_func_t *cached = NULL; ··· 6280 6287 pf->body_len = (fnlen > fnpos) ? (fnlen - fnpos - (is_block ? 1 : 0)) : 0; 6281 6288 pf->is_expr = !is_block; 6282 6289 pf->is_strict = is_strict_function_body(&fn[fnpos], pf->body_len); 6290 + pf->uses_arguments = code_uses_arguments(&fn[pf->body_start], pf->body_len); 6283 6291 pf->tokens = NULL; 6284 6292 6285 6293 HASH_ADD(hh, func_parse_cache, code_hash, sizeof(pf->code_hash), pf); ··· 6289 6297 static bool is_eval_or_arguments(struct js *js, jsoff_t toff, jsoff_t tlen) { 6290 6298 if (tlen == 4 && memcmp(&js->code[toff], "eval", 4) == 0) return true; 6291 6299 if (tlen == 9 && memcmp(&js->code[toff], "arguments", 9) == 0) return true; 6292 - return false; 6293 - } 6294 - 6295 - static bool code_uses_arguments(const char *code, jsoff_t len) { 6296 - if (len < 9) return false; 6297 - for (jsoff_t i = 0; i + 8 < len; i++) { 6298 - if (code[i] == 'a' && memcmp(&code[i], INTERN_ARGUMENTS, 9) == 0) { 6299 - if (i > 0 && (is_alpha(code[i-1]) || code[i-1] == '_' || (code[i-1] >= '0' && code[i-1] <= '9'))) continue; 6300 - if (i + 9 < len && (is_alpha(code[i+9]) || code[i+9] == '_' || (code[i+9] >= '0' && code[i+9] <= '9'))) continue; 6301 - return true; 6302 - } 6303 - } 6304 6300 return false; 6305 6301 } 6306 6302 ··· 6473 6469 } 6474 6470 } 6475 6471 6476 - bool needs_arguments = code_uses_arguments(&fn[pf->body_start], pf->body_len); 6472 + bool needs_arguments = pf->uses_arguments; 6477 6473 bool func_strict = pf->is_strict; 6478 6474 6479 6475 if (!func_strict && vtype(func_val) == T_FUNC) { ··· 20779 20775 js_set_filename(js, mod->resolved_path); 20780 20776 mkscope(js); set_slot(js, js->scope, SLOT_MODULE_SCOPE, tov(1)); 20781 20777 20782 - jsval_t result = js_eval(js, js_code, js_len); 20778 + jsval_t result = js_eval_cached(js, js_code, js_len); 20783 20779 free(content); 20784 20780 20785 20781 js->scope = saved_scope; ··· 22695 22691 return js_eval_inherit_strict(js, buf, len, false); 22696 22692 } 22697 22693 22694 + jsval_t js_eval_cached(struct js *js, const char *buf, size_t len) { 22695 + if (len == (size_t)~0U) len = strlen(buf); 22696 + 22697 + void *saved_stream = js->token_stream; 22698 + int saved_pos = js->token_stream_pos; 22699 + const char *saved_code = js->token_stream_code; 22700 + 22701 + token_stream_t *ts = tokenize_body(js, buf, (jsoff_t)len); 22702 + if (ts) { 22703 + js->token_stream = ts; 22704 + js->token_stream_pos = 0; 22705 + js->token_stream_code = buf; 22706 + } 22707 + 22708 + jsval_t result = js_eval_inherit_strict(js, buf, len, false); 22709 + if (ts) { free(ts->tokens); free(ts); } 22710 + 22711 + js->token_stream = saved_stream; 22712 + js->token_stream_pos = saved_pos; 22713 + js->token_stream_code = saved_code; 22714 + 22715 + return result; 22716 + } 22717 + 22698 22718 static jsval_t js_call_internal(struct js *js, jsval_t func, jsval_t bound_this, jsval_t *args, int nargs, bool use_bound_this) { 22699 22719 if (vtype(func) == T_FFI) { 22700 22720 return ffi_call_by_index(js, (unsigned int)vdata(func), args, nargs); ··· 22815 22835 } 22816 22836 } 22817 22837 22818 - if (code_uses_arguments(&fn[pf->body_start], pf->body_len)) { 22838 + if (pf->uses_arguments) { 22819 22839 setup_arguments(js, js->scope, final_args, final_nargs, pf->is_strict); 22820 22840 } 22821 22841
+1 -1
src/main.c
··· 193 193 js_setup_import_meta(js, use_path); 194 194 js_mkscope(js); 195 195 196 - jsval_t result = js_eval(js, js_code, js_len); 196 + jsval_t result = js_eval_cached(js, js_code, js_len); 197 197 free(js_code); 198 198 199 199 if (vtype(result) == T_ERR) {
+139 -141
src/modules/url.c
··· 10 10 #include "internal.h" 11 11 #include "runtime.h" 12 12 #include "modules/url.h" 13 + #include "modules/symbol.h" 13 14 14 15 typedef struct { 15 16 char *protocol; ··· 300 301 } 301 302 302 303 static jsval_t url_toString(struct js *js, jsval_t *args, int nargs) { 303 - (void)args; (void)nargs; 304 304 return js_get(js, js_getthis(js), "href"); 305 + } 306 + 307 + static jsval_t js_URLSearchParams(struct js *js, jsval_t *args, int nargs) { 308 + jsval_t usp = js_mkobj(js); 309 + jsval_t proto = js_get_ctor_proto(js, "URLSearchParams", 15); 310 + if (is_special_object(proto)) js_set_proto(js, usp, proto); 311 + 312 + jsval_t entries = js_mkarr(js); 313 + js_set_slot(js, usp, SLOT_ENTRIES, entries); 314 + 315 + if (nargs < 1 || vtype(args[0]) != T_STR) return usp; 316 + char *init = js_getstr(js, args[0], NULL); 317 + if (!init) return usp; 318 + 319 + const char *p = init; 320 + if (*p == '?') p++; 321 + 322 + parse_pair: 323 + if (!*p) return usp; 324 + const char *amp = strchr(p, '&'); 325 + size_t plen = amp ? (size_t)(amp - p) : strlen(p); 326 + char *pair = strndup(p, plen); 327 + char *eq = strchr(pair, '='); 328 + char *key = pair, *val = eq ? (eq[0] = '\0', eq + 1) : ""; 329 + char *dk = url_decode_component(key); 330 + char *dv = url_decode_component(val); 331 + jsval_t entry = js_mkarr(js); 332 + js_arr_push(js, entry, js_mkstr(js, dk, strlen(dk))); 333 + js_arr_push(js, entry, js_mkstr(js, dv, strlen(dv))); 334 + js_arr_push(js, entries, entry); 335 + free(pair); free(dk); free(dv); 336 + if (!amp) return usp; 337 + p = amp + 1; 338 + goto parse_pair; 305 339 } 306 340 307 341 static jsval_t js_URL(struct js *js, jsval_t *args, int nargs) { ··· 317 351 } 318 352 319 353 jsval_t url_obj = js_mkobj(js); 354 + jsval_t proto = js_get_ctor_proto(js, "URL", 3); 355 + if (is_special_object(proto)) js_set_proto(js, url_obj, proto); 320 356 321 357 js_set(js, url_obj, "protocol", js_mkstr(js, parsed.protocol, strlen(parsed.protocol))); 322 358 js_set(js, url_obj, "username", js_mkstr(js, parsed.username, strlen(parsed.username))); ··· 332 368 jsval_t search_params; 333 369 if (parsed.search && *parsed.search) { 334 370 const char *qs = parsed.search[0] == '?' ? parsed.search + 1 : parsed.search; 335 - char code[1024]; 336 - snprintf(code, sizeof(code), "new URLSearchParams('%s')", qs); 337 - search_params = js_eval(js, code, strlen(code)); 338 - } else { 339 - search_params = js_eval(js, "new URLSearchParams()", 21); 340 - } 341 - js_set(js, search_params, "_url", url_obj); 371 + jsval_t arg = js_mkstr(js, qs, strlen(qs)); 372 + search_params = js_URLSearchParams(js, &arg, 1); 373 + } else search_params = js_URLSearchParams(js, NULL, 0); 374 + 375 + js_set_slot(js, search_params, SLOT_DATA, url_obj); 342 376 js_set(js, url_obj, "searchParams", search_params); 343 377 344 - js_set(js, url_obj, "toString", js_mkfun(url_toString)); 345 - 346 378 free_parsed_url(&parsed); 347 379 return url_obj; 348 380 } ··· 350 382 static jsval_t usp_get(struct js *js, jsval_t *args, int nargs) { 351 383 if (nargs < 1) return js_mknull(); 352 384 jsval_t this_val = js_getthis(js); 385 + 353 386 char *key = js_getstr(js, args[0], NULL); 354 387 if (!key) return js_mknull(); 355 388 356 - jsval_t entries = js_get(js, this_val, "_entries"); 389 + jsval_t entries = js_get_slot(js, this_val, SLOT_ENTRIES); 357 390 if (!is_special_object(entries)) return js_mknull(); 358 391 359 - jsval_t len_val = js_get(js, entries, "length"); 360 - int len = (vtype(len_val) == T_NUM) ? (int)js_getnum(len_val) : 0; 361 - 362 - for (int i = 0; i < len; i++) { 363 - char idx[16]; 364 - snprintf(idx, sizeof(idx), "%d", i); 365 - jsval_t entry = js_get(js, entries, idx); 366 - jsval_t k = js_get(js, entry, "0"); 367 - char *ks = js_getstr(js, k, NULL); 368 - if (ks && strcmp(ks, key) == 0) { 369 - return js_get(js, entry, "1"); 370 - } 392 + jsoff_t len = js_arr_len(js, entries); 393 + for (jsoff_t i = 0; i < len; i++) { 394 + jsval_t entry = js_arr_get(js, entries, i); 395 + char *ks = js_getstr(js, js_arr_get(js, entry, 0), NULL); 396 + if (ks && strcmp(ks, key) == 0) return js_arr_get(js, entry, 1); 371 397 } 398 + 372 399 return js_mknull(); 373 400 } 374 401 375 402 static jsval_t usp_getAll(struct js *js, jsval_t *args, int nargs) { 376 403 if (nargs < 1) return js_mkarr(js); 377 404 jsval_t this_val = js_getthis(js); 405 + 378 406 char *key = js_getstr(js, args[0], NULL); 379 407 if (!key) return js_mkarr(js); 380 408 381 409 jsval_t result = js_mkarr(js); 382 - jsval_t entries = js_get(js, this_val, "_entries"); 410 + jsval_t entries = js_get_slot(js, this_val, SLOT_ENTRIES); 383 411 if (!is_special_object(entries)) return result; 384 412 385 - jsval_t len_val = js_get(js, entries, "length"); 386 - int len = (vtype(len_val) == T_NUM) ? (int)js_getnum(len_val) : 0; 387 - 388 - for (int i = 0; i < len; i++) { 389 - char idx[16]; 390 - snprintf(idx, sizeof(idx), "%d", i); 391 - jsval_t entry = js_get(js, entries, idx); 392 - jsval_t k = js_get(js, entry, "0"); 393 - char *ks = js_getstr(js, k, NULL); 394 - if (ks && strcmp(ks, key) == 0) { 395 - js_arr_push(js, result, js_get(js, entry, "1")); 396 - } 413 + jsoff_t len = js_arr_len(js, entries); 414 + for (jsoff_t i = 0; i < len; i++) { 415 + jsval_t entry = js_arr_get(js, entries, i); 416 + char *ks = js_getstr(js, js_arr_get(js, entry, 0), NULL); 417 + if (ks && strcmp(ks, key) == 0) js_arr_push(js, result, js_arr_get(js, entry, 1)); 397 418 } 419 + 398 420 return result; 399 421 } 400 422 401 423 static jsval_t usp_has(struct js *js, jsval_t *args, int nargs) { 402 424 if (nargs < 1) return js_false; 403 425 jsval_t this_val = js_getthis(js); 426 + 404 427 char *key = js_getstr(js, args[0], NULL); 405 428 if (!key) return js_false; 406 429 407 - jsval_t entries = js_get(js, this_val, "_entries"); 430 + jsval_t entries = js_get_slot(js, this_val, SLOT_ENTRIES); 408 431 if (!is_special_object(entries)) return js_false; 409 432 410 - jsval_t len_val = js_get(js, entries, "length"); 411 - int len = (vtype(len_val) == T_NUM) ? (int)js_getnum(len_val) : 0; 412 - 413 - for (int i = 0; i < len; i++) { 414 - char idx[16]; 415 - snprintf(idx, sizeof(idx), "%d", i); 416 - jsval_t entry = js_get(js, entries, idx); 417 - jsval_t k = js_get(js, entry, "0"); 418 - char *ks = js_getstr(js, k, NULL); 433 + jsoff_t len = js_arr_len(js, entries); 434 + for (jsoff_t i = 0; i < len; i++) { 435 + jsval_t entry = js_arr_get(js, entries, i); 436 + char *ks = js_getstr(js, js_arr_get(js, entry, 0), NULL); 419 437 if (ks && strcmp(ks, key) == 0) return js_true; 420 438 } 439 + 421 440 return js_false; 422 441 } 423 442 424 443 static void usp_sync_url(struct js *js, jsval_t this_val) { 425 - jsval_t url_obj = js_get(js, this_val, "_url"); 444 + jsval_t url_obj = js_get_slot(js, this_val, SLOT_DATA); 426 445 if (!is_special_object(url_obj)) return; 427 446 428 - jsval_t entries = js_get(js, this_val, "_entries"); 429 - jsval_t len_val = js_get(js, entries, "length"); 430 - int len = (vtype(len_val) == T_NUM) ? (int)js_getnum(len_val) : 0; 447 + jsval_t entries = js_get_slot(js, this_val, SLOT_ENTRIES); 448 + jsoff_t len = js_arr_len(js, entries); 431 449 432 450 size_t buf_size = 1024; 433 451 char *buf = malloc(buf_size); 434 452 buf[0] = '?'; 435 453 size_t pos = 1; 436 454 437 - for (int i = 0; i < len; i++) { 438 - char idx[16]; 439 - snprintf(idx, sizeof(idx), "%d", i); 440 - jsval_t entry = js_get(js, entries, idx); 441 - char *k = js_getstr(js, js_get(js, entry, "0"), NULL); 442 - char *v = js_getstr(js, js_get(js, entry, "1"), NULL); 455 + for (jsoff_t i = 0; i < len; i++) { 456 + jsval_t entry = js_arr_get(js, entries, i); 457 + char *k = js_getstr(js, js_arr_get(js, entry, 0), NULL); 458 + char *v = js_getstr(js, js_arr_get(js, entry, 1), NULL); 443 459 if (!k) continue; 460 + 444 461 char *ek = url_encode_component(k); 445 462 char *ev = url_encode_component(v ? v : ""); 463 + 446 464 size_t needed = strlen(ek) + strlen(ev) + 3; 447 465 if (pos + needed >= buf_size) { 448 466 buf_size = buf_size * 2 + needed; 449 467 buf = realloc(buf, buf_size); 450 468 } 469 + 451 470 if (pos > 1) buf[pos++] = '&'; 452 471 pos += sprintf(buf + pos, "%s=%s", ek, ev); 453 - free(ek); 454 - free(ev); 472 + free(ek); free(ev); 455 473 } 474 + 456 475 buf[pos] = '\0'; 457 - 458 476 js_set(js, url_obj, "search", js_mkstr(js, buf, pos)); 459 477 update_url_href(js, url_obj); 460 478 free(buf); ··· 463 481 static jsval_t usp_set(struct js *js, jsval_t *args, int nargs) { 464 482 if (nargs < 2) return js_mkundef(); 465 483 jsval_t this_val = js_getthis(js); 484 + 466 485 char *key = js_getstr(js, args[0], NULL); 467 486 if (!key) return js_mkundef(); 468 487 469 - jsval_t entries = js_get(js, this_val, "_entries"); 470 - jsval_t len_val = js_get(js, entries, "length"); 471 - int len = (vtype(len_val) == T_NUM) ? (int)js_getnum(len_val) : 0; 488 + jsval_t entries = js_get_slot(js, this_val, SLOT_ENTRIES); 489 + jsoff_t len = js_arr_len(js, entries); 472 490 473 491 jsval_t new_entries = js_mkarr(js); 474 492 int found = 0; 475 493 476 - for (int i = 0; i < len; i++) { 477 - char idx[16]; 478 - snprintf(idx, sizeof(idx), "%d", i); 479 - jsval_t entry = js_get(js, entries, idx); 480 - char *ks = js_getstr(js, js_get(js, entry, "0"), NULL); 494 + for (jsoff_t i = 0; i < len; i++) { 495 + jsval_t entry = js_arr_get(js, entries, i); 496 + char *ks = js_getstr(js, js_arr_get(js, entry, 0), NULL); 481 497 if (ks && strcmp(ks, key) == 0) { 482 498 if (!found) { 483 499 jsval_t new_entry = js_mkarr(js); ··· 486 502 js_arr_push(js, new_entries, new_entry); 487 503 found = 1; 488 504 } 489 - } else { 490 - js_arr_push(js, new_entries, entry); 491 - } 505 + } else js_arr_push(js, new_entries, entry); 492 506 } 493 507 494 508 if (!found) { ··· 498 512 js_arr_push(js, new_entries, new_entry); 499 513 } 500 514 501 - js_set(js, this_val, "_entries", new_entries); 515 + js_set_slot(js, this_val, SLOT_ENTRIES, new_entries); 502 516 usp_sync_url(js, this_val); 517 + 503 518 return js_mkundef(); 504 519 } 505 520 ··· 507 522 if (nargs < 2) return js_mkundef(); 508 523 jsval_t this_val = js_getthis(js); 509 524 510 - jsval_t entries = js_get(js, this_val, "_entries"); 525 + jsval_t entries = js_get_slot(js, this_val, SLOT_ENTRIES); 511 526 jsval_t entry = js_mkarr(js); 512 527 js_arr_push(js, entry, args[0]); 513 528 js_arr_push(js, entry, args[1]); ··· 523 538 char *key = js_getstr(js, args[0], NULL); 524 539 if (!key) return js_mkundef(); 525 540 526 - jsval_t entries = js_get(js, this_val, "_entries"); 527 - jsval_t len_val = js_get(js, entries, "length"); 528 - int len = (vtype(len_val) == T_NUM) ? (int)js_getnum(len_val) : 0; 541 + jsval_t entries = js_get_slot(js, this_val, SLOT_ENTRIES); 542 + jsoff_t len = js_arr_len(js, entries); 529 543 530 544 jsval_t new_entries = js_mkarr(js); 531 - for (int i = 0; i < len; i++) { 532 - char idx[16]; 533 - snprintf(idx, sizeof(idx), "%d", i); 534 - jsval_t entry = js_get(js, entries, idx); 535 - char *ks = js_getstr(js, js_get(js, entry, "0"), NULL); 536 - if (!ks || strcmp(ks, key) != 0) { 537 - js_arr_push(js, new_entries, entry); 538 - } 545 + for (jsoff_t i = 0; i < len; i++) { 546 + jsval_t entry = js_arr_get(js, entries, i); 547 + char *ks = js_getstr(js, js_arr_get(js, entry, 0), NULL); 548 + if (!ks || strcmp(ks, key) != 0) js_arr_push(js, new_entries, entry); 539 549 } 540 550 541 - js_set(js, this_val, "_entries", new_entries); 551 + js_set_slot(js, this_val, SLOT_ENTRIES, new_entries); 542 552 usp_sync_url(js, this_val); 543 553 js->needs_gc = true; 554 + 544 555 return js_mkundef(); 545 556 } 546 557 547 558 static jsval_t usp_toString(struct js *js, jsval_t *args, int nargs) { 548 - (void)args; (void)nargs; 549 559 jsval_t this_val = js_getthis(js); 550 - jsval_t entries = js_get(js, this_val, "_entries"); 551 - jsval_t len_val = js_get(js, entries, "length"); 552 - int len = (vtype(len_val) == T_NUM) ? (int)js_getnum(len_val) : 0; 560 + jsval_t entries = js_get_slot(js, this_val, SLOT_ENTRIES); 561 + jsoff_t len = js_arr_len(js, entries); 553 562 554 563 size_t buf_size = 1024; 555 564 char *buf = malloc(buf_size); 556 565 size_t pos = 0; 557 566 558 - for (int i = 0; i < len; i++) { 559 - char idx[16]; 560 - snprintf(idx, sizeof(idx), "%d", i); 561 - jsval_t entry = js_get(js, entries, idx); 562 - char *k = js_getstr(js, js_get(js, entry, "0"), NULL); 563 - char *v = js_getstr(js, js_get(js, entry, "1"), NULL); 567 + for (jsoff_t i = 0; i < len; i++) { 568 + jsval_t entry = js_arr_get(js, entries, i); 569 + char *k = js_getstr(js, js_arr_get(js, entry, 0), NULL); 570 + char *v = js_getstr(js, js_arr_get(js, entry, 1), NULL); 564 571 if (!k) continue; 572 + 565 573 char *ek = url_encode_component(k); 566 574 char *ev = url_encode_component(v ? v : ""); 567 575 size_t needed = strlen(ek) + strlen(ev) + 3; 576 + 568 577 if (pos + needed >= buf_size) { 569 578 buf_size = buf_size * 2 + needed; 570 579 buf = realloc(buf, buf_size); 571 580 } 581 + 572 582 if (pos > 0) buf[pos++] = '&'; 573 583 pos += sprintf(buf + pos, "%s=%s", ek, ev); 574 584 free(ek); 575 585 free(ev); 576 586 } 587 + 577 588 buf[pos] = '\0'; 578 589 jsval_t ret = js_mkstr(js, buf, pos); 579 590 free(buf); 591 + 580 592 return ret; 581 593 } 582 594 583 - static jsval_t js_URLSearchParams(struct js *js, jsval_t *args, int nargs) { 584 - jsval_t usp = js_mkobj(js); 585 - jsval_t entries = js_mkarr(js); 586 - js_set(js, usp, "_entries", entries); 587 - 588 - if (nargs < 1 || vtype(args[0]) != T_STR) goto done_parse; 589 - char *init = js_getstr(js, args[0], NULL); 590 - if (!init) goto done_parse; 591 - 592 - const char *p = init; 593 - if (*p == '?') p++; 594 - 595 - parse_pair: 596 - if (!*p) goto done_parse; 597 - const char *amp = strchr(p, '&'); 598 - size_t plen = amp ? (size_t)(amp - p) : strlen(p); 599 - char *pair = strndup(p, plen); 600 - char *eq = strchr(pair, '='); 601 - char *key = pair, *val = eq ? (eq[0] = '\0', eq + 1) : ""; 602 - char *dk = url_decode_component(key); 603 - char *dv = url_decode_component(val); 604 - jsval_t entry = js_mkarr(js); 605 - js_arr_push(js, entry, js_mkstr(js, dk, strlen(dk))); 606 - js_arr_push(js, entry, js_mkstr(js, dv, strlen(dv))); 607 - js_arr_push(js, entries, entry); 608 - free(pair); free(dk); free(dv); 609 - if (!amp) goto done_parse; 610 - p = amp + 1; 611 - goto parse_pair; 612 - 613 - done_parse: 614 - 615 - js_set(js, usp, "get", js_mkfun(usp_get)); 616 - js_set(js, usp, "getAll", js_mkfun(usp_getAll)); 617 - js_set(js, usp, "has", js_mkfun(usp_has)); 618 - js_set(js, usp, "set", js_mkfun(usp_set)); 619 - js_set(js, usp, "append", js_mkfun(usp_append)); 620 - js_set(js, usp, "delete", js_mkfun(usp_delete)); 621 - js_set(js, usp, "toString", js_mkfun(usp_toString)); 622 - 623 - return usp; 624 - } 625 - 626 595 void init_url_module(void) { 627 - struct js *js = rt->js; 628 - jsval_t glob = js_glob(js); 596 + ant_t *js = rt->js; 597 + jsval_t glob = js->global; 629 598 630 - js_set(js, glob, "URL", js_mkfun(js_URL)); 631 - js_set(js, glob, "URLSearchParams", js_mkfun(js_URLSearchParams)); 599 + jsval_t url_ctor = js_mkobj(js); 600 + jsval_t url_proto = js_mkobj(js); 601 + 602 + js_set(js, url_proto, "toString", js_mkfun(url_toString)); 603 + js_set(js, url_proto, get_toStringTag_sym_key(), js_mkstr(js, "URL", 3)); 604 + 605 + js_set_slot(js, url_ctor, SLOT_CFUNC, js_mkfun(js_URL)); 606 + js_mkprop_fast(js, url_ctor, "prototype", 9, url_proto); 607 + js_mkprop_fast(js, url_ctor, "name", 4, ANT_STRING("URL")); 608 + js_set_descriptor(js, url_ctor, "name", 4, 0); 609 + 610 + js_set(js, glob, "URL", js_obj_to_func(url_ctor)); 611 + 612 + jsval_t usp_ctor = js_mkobj(js); 613 + jsval_t usp_proto = js_mkobj(js); 614 + 615 + js_set(js, usp_proto, "get", js_mkfun(usp_get)); 616 + js_set(js, usp_proto, "getAll", js_mkfun(usp_getAll)); 617 + js_set(js, usp_proto, "has", js_mkfun(usp_has)); 618 + js_set(js, usp_proto, "set", js_mkfun(usp_set)); 619 + js_set(js, usp_proto, "append", js_mkfun(usp_append)); 620 + js_set(js, usp_proto, "delete", js_mkfun(usp_delete)); 621 + js_set(js, usp_proto, "toString", js_mkfun(usp_toString)); 622 + js_set(js, usp_proto, get_toStringTag_sym_key(), js_mkstr(js, "URLSearchParams", 15)); 623 + 624 + js_set_slot(js, usp_ctor, SLOT_CFUNC, js_mkfun(js_URLSearchParams)); 625 + js_mkprop_fast(js, usp_ctor, "prototype", 9, usp_proto); 626 + js_mkprop_fast(js, usp_ctor, "name", 4, ANT_STRING("URLSearchParams")); 627 + js_set_descriptor(js, usp_ctor, "name", 4, 0); 628 + 629 + js_set(js, glob, "URLSearchParams", js_obj_to_func(usp_ctor)); 632 630 }
+1 -1
src/snapshot.c
··· 7 7 8 8 jsval_t ant_load_snapshot(ant_t *js) { 9 9 if (!js) return js_mkundef(); 10 - jsval_t result = js_eval(js, (const char *)ant_snapshot_source, ant_snapshot_source_len); 10 + jsval_t result = js_eval_cached(js, (const char *)ant_snapshot_source, ant_snapshot_source_len); 11 11 12 12 if (vtype(result) == T_ERR) return result; 13 13 return js_true;
+1024
tests/bench.js
··· 1 + /* 2 + * Javascript Micro benchmark 3 + * 4 + * Copyright (c) 2017-2019 Fabrice Bellard 5 + * Copyright (c) 2017-2019 Charlie Gordon 6 + * 7 + * Permission is hereby granted, free of charge, to any person obtaining a copy 8 + * of this software and associated documentation files (the "Software"), to deal 9 + * in the Software without restriction, including without limitation the rights 10 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 + * copies of the Software, and to permit persons to whom the Software is 12 + * furnished to do so, subject to the following conditions: 13 + * 14 + * The above copyright notice and this permission notice shall be included in 15 + * all copies or substantial portions of the Software. 16 + * 17 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 + * THE SOFTWARE. 24 + */ 25 + 26 + function pad(str, n) { 27 + str += ''; 28 + while (str.length < n) str += ' '; 29 + return str; 30 + } 31 + 32 + function pad_left(str, n) { 33 + str += ''; 34 + while (str.length < n) str = ' ' + str; 35 + return str; 36 + } 37 + 38 + function pad_center(str, n) { 39 + str += ''; 40 + while (str.length < n) { 41 + if ((n - str.length) & 1) str = str + ' '; 42 + else str = ' ' + str; 43 + } 44 + return str; 45 + } 46 + 47 + var ref_data; 48 + var log_data; 49 + 50 + var heads = ['TEST', 'N', 'TIME (ns)', 'REF (ns)', 'SCORE (%)']; 51 + var widths = [22, 10, 9, 9, 9]; 52 + var precs = [0, 0, 2, 2, 2]; 53 + var total = [0, 0, 0, 0, 0]; 54 + var total_score = 0; 55 + var total_scale = 0; 56 + 57 + function log_line() { 58 + var i, n, s, a; 59 + s = ''; 60 + for (i = 0, n = arguments.length; i < n; i++) { 61 + if (i > 0) s += ' '; 62 + a = arguments[i]; 63 + if (typeof a == 'number') { 64 + total[i] += a; 65 + a = a.toFixed(precs[i]); 66 + a += ''; 67 + s += pad_left(a, widths[i]); 68 + } else { 69 + s += pad_left(a, widths[i]); 70 + } 71 + } 72 + console.log(s); 73 + } 74 + 75 + var clocks_per_sec = 1000; 76 + var max_iterations = 10; 77 + var clock_threshold = 100; /* favoring short measuring spans */ 78 + var min_n_argument = 1; 79 + var get_clock; 80 + if (typeof performance != 'undefined') get_clock = performance.now; 81 + else get_clock = Date.now; 82 + 83 + function log_one(text, n, ti) { 84 + var ref; 85 + 86 + if (ref_data) ref = ref_data[text]; 87 + else ref = null; 88 + 89 + // XXX 90 + // ti = Math.round(ti * 100) / 100; 91 + log_data[text] = ti; 92 + if (typeof ref === 'number') { 93 + log_line(text, n, ti, ref, (ti * 100) / ref); 94 + total_score += (ti * 100) / ref; 95 + total_scale += 100; 96 + } else { 97 + log_line(text, n, ti); 98 + total_score += 100; 99 + total_scale += 100; 100 + } 101 + } 102 + 103 + function bench(f, text) { 104 + var i, j, n, t, t1, ti, nb_its, ref, ti_n, ti_n1, min_ti; 105 + 106 + nb_its = n = 1; 107 + if (f.bench) { 108 + ti_n = f(text); 109 + } else { 110 + ti_n = 1000000000; 111 + min_ti = clock_threshold / 10; 112 + for (i = 0; i < 30; i++) { 113 + // print("n=", n); 114 + ti = 1000000000; 115 + for (j = 0; j < max_iterations; j++) { 116 + t = get_clock(); 117 + while ((t1 = get_clock()) == t) continue; 118 + nb_its = f(n); 119 + if (nb_its < 0) return; // test failure 120 + t1 = get_clock() - t1; 121 + if (ti > t1) ti = t1; 122 + } 123 + if (ti >= min_ti) { 124 + ti_n1 = ti / nb_its; 125 + if (ti_n > ti_n1) ti_n = ti_n1; 126 + } 127 + if (ti >= clock_threshold && n >= min_n_argument) break; 128 + n = n * [2, 2.5, 2][i % 3]; 129 + } 130 + // to use only the best timing from the last loop, uncomment below 131 + //ti_n = ti / nb_its; 132 + } 133 + /* nano seconds per iteration */ 134 + log_one(text, n, (ti_n * 1e9) / clocks_per_sec); 135 + } 136 + 137 + var global_res; /* to be sure the code is not optimized */ 138 + 139 + function empty_loop(n) { 140 + var j; 141 + for (j = 0; j < n; j++) {} 142 + return n; 143 + } 144 + 145 + function date_now(n) { 146 + var j; 147 + for (j = 0; j < n; j++) { 148 + Date.now(); 149 + } 150 + return n; 151 + } 152 + 153 + function prop_read(n) { 154 + var obj, sum, j; 155 + obj = { a: 1, b: 2, c: 3, d: 4 }; 156 + sum = 0; 157 + for (j = 0; j < n; j++) { 158 + sum += obj.a; 159 + sum += obj.b; 160 + sum += obj.c; 161 + sum += obj.d; 162 + } 163 + global_res = sum; 164 + return n * 4; 165 + } 166 + 167 + function prop_write(n) { 168 + var obj, j; 169 + obj = { a: 1, b: 2, c: 3, d: 4 }; 170 + for (j = 0; j < n; j++) { 171 + obj.a = j; 172 + obj.b = j; 173 + obj.c = j; 174 + obj.d = j; 175 + } 176 + return n * 4; 177 + } 178 + 179 + function prop_update(n) { 180 + var obj, j; 181 + obj = { a: 1, b: 2, c: 3, d: 4 }; 182 + for (j = 0; j < n; j++) { 183 + obj.a += j; 184 + obj.b += j; 185 + obj.c += j; 186 + obj.d += j; 187 + } 188 + return n * 4; 189 + } 190 + 191 + function prop_create(n) { 192 + var obj, i, j; 193 + for (j = 0; j < n; j++) { 194 + obj = {}; 195 + obj.a = 1; 196 + obj.b = 2; 197 + obj.c = 3; 198 + obj.d = 4; 199 + obj.e = 5; 200 + obj.f = 6; 201 + obj.g = 7; 202 + obj.h = 8; 203 + obj.i = 9; 204 + obj.j = 10; 205 + for (i = 0; i < 10; i++) { 206 + obj[i] = i; 207 + } 208 + } 209 + return n * 20; 210 + } 211 + 212 + function prop_delete(n) { 213 + var obj, j, i, len; 214 + len = 1000; 215 + obj = {}; 216 + for (i = 0; i < n; i++) { 217 + for (j = 0; j < len; j++) { 218 + obj[j] = 1; 219 + } 220 + for (j = 0; j < len; j++) { 221 + delete obj[j]; 222 + } 223 + } 224 + return n * len; 225 + } 226 + 227 + function array_read(n) { 228 + var tab, len, sum, i, j; 229 + tab = []; 230 + len = 10; 231 + for (i = 0; i < len; i++) tab[i] = i; 232 + sum = 0; 233 + for (j = 0; j < n; j++) { 234 + sum += tab[0]; 235 + sum += tab[1]; 236 + sum += tab[2]; 237 + sum += tab[3]; 238 + sum += tab[4]; 239 + sum += tab[5]; 240 + sum += tab[6]; 241 + sum += tab[7]; 242 + sum += tab[8]; 243 + sum += tab[9]; 244 + } 245 + global_res = sum; 246 + return len * n; 247 + } 248 + 249 + function array_write(n) { 250 + var tab, len, i, j; 251 + tab = []; 252 + len = 10; 253 + for (i = 0; i < len; i++) tab[i] = i; 254 + for (j = 0; j < n; j++) { 255 + tab[0] = j; 256 + tab[1] = j; 257 + tab[2] = j; 258 + tab[3] = j; 259 + tab[4] = j; 260 + tab[5] = j; 261 + tab[6] = j; 262 + tab[7] = j; 263 + tab[8] = j; 264 + tab[9] = j; 265 + } 266 + return len * n; 267 + } 268 + 269 + function array_update(n) { 270 + var tab, len, i, j; 271 + tab = []; 272 + len = 10; 273 + for (i = 0; i < len; i++) tab[i] = i; 274 + for (j = 0; j < n; j++) { 275 + tab[0] += j; 276 + tab[1] += j; 277 + tab[2] += j; 278 + tab[3] += j; 279 + tab[4] += j; 280 + tab[5] += j; 281 + tab[6] += j; 282 + tab[7] += j; 283 + tab[8] += j; 284 + tab[9] += j; 285 + } 286 + return len * n; 287 + } 288 + 289 + function array_prop_create(n) { 290 + var tab, i, j, len; 291 + len = 1000; 292 + for (j = 0; j < n; j++) { 293 + tab = []; 294 + for (i = 0; i < len; i++) tab[i] = i; 295 + } 296 + return len * n; 297 + } 298 + 299 + function array_length_read(n) { 300 + var tab, sum, j; 301 + tab = [1, 2, 3]; 302 + sum = 0; 303 + for (j = 0; j < n; j++) { 304 + sum += tab.length; 305 + sum += tab.length; 306 + sum += tab.length; 307 + sum += tab.length; 308 + } 309 + global_res = sum; 310 + return n * 4; 311 + } 312 + 313 + function array_length_decr(n) { 314 + var tab, i, j, len; 315 + len = 1000; 316 + for (j = 0; j < n; j++) { 317 + tab = []; 318 + for (i = 0; i < len; i++) tab[i] = i; 319 + for (i = len - 1; i >= 0; i--) tab.length = i; 320 + } 321 + return len * n; 322 + } 323 + 324 + function array_hole_length_decr(n) { 325 + var tab, i, j, len; 326 + len = 1000; 327 + tab = []; 328 + for (i = 0; i < len; i++) { 329 + if (i != 3) tab[i] = i; 330 + } 331 + for (j = 0; j < n; j++) { 332 + for (i = len - 1; i >= 0; i--) tab.length = i; 333 + } 334 + return len * n; 335 + } 336 + 337 + function array_push(n) { 338 + var tab, i, j, len; 339 + len = 500; 340 + for (j = 0; j < n; j++) { 341 + tab = []; 342 + for (i = 0; i < len; i++) tab.push(i); 343 + } 344 + return len * n; 345 + } 346 + 347 + function array_pop(n) { 348 + var tab, ref, i, j, len, sum; 349 + len = 500; 350 + ref = []; 351 + for (i = 0; i < len; i++) ref[i] = i; 352 + for (j = 0; j < n; j++) { 353 + tab = ref.slice(); 354 + sum = 0; 355 + for (i = 0; i < len; i++) sum += tab.pop(); 356 + global_res = sum; 357 + } 358 + return len * n; 359 + } 360 + 361 + function typed_array_read(n) { 362 + var tab, len, sum, i, j; 363 + len = 10; 364 + tab = new Int32Array(len); 365 + for (i = 0; i < len; i++) tab[i] = i; 366 + sum = 0; 367 + for (j = 0; j < n; j++) { 368 + sum += tab[0]; 369 + sum += tab[1]; 370 + sum += tab[2]; 371 + sum += tab[3]; 372 + sum += tab[4]; 373 + sum += tab[5]; 374 + sum += tab[6]; 375 + sum += tab[7]; 376 + sum += tab[8]; 377 + sum += tab[9]; 378 + } 379 + global_res = sum; 380 + return len * n; 381 + } 382 + 383 + function typed_array_write(n) { 384 + var tab, len, i, j; 385 + len = 10; 386 + tab = new Int32Array(len); 387 + for (i = 0; i < len; i++) tab[i] = i; 388 + for (j = 0; j < n; j++) { 389 + tab[0] = j; 390 + tab[1] = j; 391 + tab[2] = j; 392 + tab[3] = j; 393 + tab[4] = j; 394 + tab[5] = j; 395 + tab[6] = j; 396 + tab[7] = j; 397 + tab[8] = j; 398 + tab[9] = j; 399 + } 400 + return len * n; 401 + } 402 + 403 + function closure_read(n) { 404 + function f(n) { 405 + var sum, j; 406 + var0 = 0; 407 + sum = 0; 408 + for (j = 0; j < n; j++) { 409 + sum += var0; 410 + sum += var0; 411 + sum += var0; 412 + sum += var0; 413 + } 414 + global_res = sum; 415 + } 416 + var var0 = 0; 417 + f(n); 418 + return n * 4; 419 + } 420 + 421 + function closure_write(n) { 422 + function f(n) { 423 + var j; 424 + for (j = 0; j < n; j++) { 425 + var0 = j; 426 + var0 = j; 427 + var0 = j; 428 + var0 = j; 429 + } 430 + } 431 + var var0; 432 + 433 + f(n); 434 + return n * 4; 435 + } 436 + 437 + var global_var0; 438 + 439 + function global_read(n) { 440 + var sum, j; 441 + global_var0 = 0; 442 + sum = 0; 443 + for (j = 0; j < n; j++) { 444 + sum += global_var0; 445 + sum += global_var0; 446 + sum += global_var0; 447 + sum += global_var0; 448 + } 449 + global_res = sum; 450 + return n * 4; 451 + } 452 + 453 + function global_write_strict(n) { 454 + var j; 455 + for (j = 0; j < n; j++) { 456 + global_var0 = j; 457 + global_var0 = j; 458 + global_var0 = j; 459 + global_var0 = j; 460 + } 461 + return n * 4; 462 + } 463 + 464 + function func_call(n) { 465 + function f(a) { 466 + return 1; 467 + } 468 + 469 + var j, sum; 470 + sum = 0; 471 + for (j = 0; j < n; j++) { 472 + sum += f(j); 473 + sum += f(j); 474 + sum += f(j); 475 + sum += f(j); 476 + } 477 + global_res = sum; 478 + return n * 4; 479 + } 480 + 481 + function closure_var(n) { 482 + function f(a) { 483 + sum++; 484 + } 485 + 486 + var j, sum; 487 + sum = 0; 488 + for (j = 0; j < n; j++) { 489 + f(j); 490 + f(j); 491 + f(j); 492 + f(j); 493 + } 494 + global_res = sum; 495 + return n * 4; 496 + } 497 + 498 + function int_arith(n) { 499 + var i, j, sum; 500 + global_res = 0; 501 + for (j = 0; j < n; j++) { 502 + sum = 0; 503 + for (i = 0; i < 1000; i++) { 504 + sum += i * i; 505 + } 506 + global_res += sum; 507 + } 508 + return n * 1000; 509 + } 510 + 511 + function float_arith(n) { 512 + var i, j, sum, a, incr, a0; 513 + global_res = 0; 514 + a0 = 0.1; 515 + incr = 1.1; 516 + for (j = 0; j < n; j++) { 517 + sum = 0; 518 + a = a0; 519 + for (i = 0; i < 1000; i++) { 520 + sum += a * a; 521 + a += incr; 522 + } 523 + global_res += sum; 524 + } 525 + return n * 1000; 526 + } 527 + 528 + function bigfloat_arith(n) { 529 + var i, j, sum, a, incr, a0; 530 + global_res = 0; 531 + a0 = BigFloat('0.1'); 532 + incr = BigFloat('1.1'); 533 + for (j = 0; j < n; j++) { 534 + sum = 0; 535 + a = a0; 536 + for (i = 0; i < 1000; i++) { 537 + sum += a * a; 538 + a += incr; 539 + } 540 + global_res += sum; 541 + } 542 + return n * 1000; 543 + } 544 + 545 + function bigint_arith(n, bits) { 546 + var i, j, sum, a, incr, a0, sum0; 547 + sum0 = global_res = BigInt(0); 548 + a0 = BigInt(1) << BigInt(Math.floor((bits - 10) * 0.5)); 549 + incr = BigInt(1); 550 + for (j = 0; j < n; j++) { 551 + sum = sum0; 552 + a = a0; 553 + for (i = 0; i < 1000; i++) { 554 + sum += a * a; 555 + a += incr; 556 + } 557 + global_res += sum; 558 + } 559 + return n * 1000; 560 + } 561 + 562 + function bigint64_arith(n) { 563 + return bigint_arith(n, 64); 564 + } 565 + 566 + function bigint256_arith(n) { 567 + return bigint_arith(n, 256); 568 + } 569 + 570 + function set_collection_add(n) { 571 + var s, 572 + i, 573 + j, 574 + len = 100; 575 + s = new Set(); 576 + for (j = 0; j < n; j++) { 577 + for (i = 0; i < len; i++) { 578 + s.add(String(i), i); 579 + } 580 + for (i = 0; i < len; i++) { 581 + if (!s.has(String(i))) throw Error('bug in Set'); 582 + } 583 + } 584 + return n * len; 585 + } 586 + 587 + function array_for(n) { 588 + var r, i, j, sum; 589 + r = []; 590 + for (i = 0; i < 100; i++) r[i] = i; 591 + for (j = 0; j < n; j++) { 592 + sum = 0; 593 + for (i = 0; i < 100; i++) { 594 + sum += r[i]; 595 + } 596 + global_res = sum; 597 + } 598 + return n * 100; 599 + } 600 + 601 + function array_for_in(n) { 602 + var r, i, j, sum; 603 + r = []; 604 + for (i = 0; i < 100; i++) r[i] = i; 605 + for (j = 0; j < n; j++) { 606 + sum = 0; 607 + for (i in r) { 608 + sum += r[i]; 609 + } 610 + global_res = sum; 611 + } 612 + return n * 100; 613 + } 614 + 615 + function array_for_of(n) { 616 + var r, i, j, sum; 617 + r = []; 618 + for (i = 0; i < 100; i++) r[i] = i; 619 + for (j = 0; j < n; j++) { 620 + sum = 0; 621 + for (i of r) { 622 + sum += i; 623 + } 624 + global_res = sum; 625 + } 626 + return n * 100; 627 + } 628 + 629 + function math_min(n) { 630 + var i, j, r; 631 + r = 0; 632 + for (j = 0; j < n; j++) { 633 + for (i = 0; i < 1000; i++) r = Math.min(i, 500); 634 + global_res = r; 635 + } 636 + return n * 1000; 637 + } 638 + 639 + function regexp_ascii(n) { 640 + var i, j, r, s; 641 + s = 'the quick brown fox jumped over the lazy dog'; 642 + for (j = 0; j < n; j++) { 643 + for (i = 0; i < 1000; i++) r = /the quick brown fox/.exec(s); 644 + global_res = r; 645 + } 646 + return n * 1000; 647 + } 648 + 649 + function regexp_utf16(n) { 650 + var i, j, r, s; 651 + s = 'the quick brown แถ แต’หฃ jumped over the lazy แตˆแต’แต'; 652 + for (j = 0; j < n; j++) { 653 + for (i = 0; i < 1000; i++) r = /the quick brown แถ แต’หฃ/.exec(s); 654 + global_res = r; 655 + } 656 + return n * 1000; 657 + } 658 + 659 + function regexp_replace(n) { 660 + var i, j, r, s; 661 + s = 'the quick abc brown fox jumped abc over the lazy dog'; 662 + for (j = 0; j < n; j++) { 663 + for (i = 0; i < 1000; i++) r = s.replace(/abc /g, '-'); 664 + global_res = r; 665 + } 666 + return n * 1000; 667 + } 668 + 669 + function string_length(n) { 670 + var str, sum, j; 671 + str = 'abcde'; 672 + sum = 0; 673 + for (j = 0; j < n; j++) { 674 + sum += str.length; 675 + sum += str.length; 676 + sum += str.length; 677 + sum += str.length; 678 + } 679 + global_res = sum; 680 + return n * 4; 681 + } 682 + 683 + /* incremental string construction as local var */ 684 + function string_build1(n) { 685 + var i, j, r; 686 + r = ''; 687 + for (j = 0; j < n; j++) { 688 + for (i = 0; i < 100; i++) r += 'x'; 689 + global_res = r; 690 + } 691 + return n * 100; 692 + } 693 + 694 + /* incremental string construction as arg */ 695 + function string_build2(n, r) { 696 + var i, j; 697 + r = ''; 698 + for (j = 0; j < n; j++) { 699 + for (i = 0; i < 100; i++) r += 'x'; 700 + global_res = r; 701 + } 702 + return n * 100; 703 + } 704 + 705 + /* incremental string construction by prepending */ 706 + function string_build3(n, r) { 707 + var i, j; 708 + r = ''; 709 + for (j = 0; j < n; j++) { 710 + for (i = 0; i < 100; i++) r = 'x' + r; 711 + global_res = r; 712 + } 713 + return n * 100; 714 + } 715 + 716 + /* incremental string construction with multiple reference */ 717 + function string_build4(n) { 718 + var i, j, r, s; 719 + r = ''; 720 + for (j = 0; j < n; j++) { 721 + for (i = 0; i < 100; i++) { 722 + s = r; 723 + r += 'x'; 724 + } 725 + global_res = r; 726 + } 727 + return n * 100; 728 + } 729 + 730 + /* sort bench */ 731 + 732 + function sort_bench(text) { 733 + function random(arr, n, def) { 734 + for (var i = 0; i < n; i++) arr[i] = def[(Math.random() * n) >> 0]; 735 + } 736 + function random8(arr, n, def) { 737 + for (var i = 0; i < n; i++) arr[i] = def[(Math.random() * 256) >> 0]; 738 + } 739 + function random1(arr, n, def) { 740 + for (var i = 0; i < n; i++) arr[i] = def[(Math.random() * 2) >> 0]; 741 + } 742 + function hill(arr, n, def) { 743 + var mid = n >> 1; 744 + for (var i = 0; i < mid; i++) arr[i] = def[i]; 745 + for (var i = mid; i < n; i++) arr[i] = def[n - i]; 746 + } 747 + function comb(arr, n, def) { 748 + for (var i = 0; i < n; i++) arr[i] = def[(i & 1) * i]; 749 + } 750 + function crisscross(arr, n, def) { 751 + for (var i = 0; i < n; i++) arr[i] = def[i & 1 ? n - i : i]; 752 + } 753 + function zero(arr, n, def) { 754 + for (var i = 0; i < n; i++) arr[i] = def[0]; 755 + } 756 + function increasing(arr, n, def) { 757 + for (var i = 0; i < n; i++) arr[i] = def[i]; 758 + } 759 + function decreasing(arr, n, def) { 760 + for (var i = 0; i < n; i++) arr[i] = def[n - 1 - i]; 761 + } 762 + function alternate(arr, n, def) { 763 + for (var i = 0; i < n; i++) arr[i] = def[i ^ 1]; 764 + } 765 + function jigsaw(arr, n, def) { 766 + for (var i = 0; i < n; i++) arr[i] = def[i % (n >> 4)]; 767 + } 768 + function incbutone(arr, n, def) { 769 + for (var i = 0; i < n; i++) arr[i] = def[i]; 770 + if (n > 0) arr[n >> 2] = def[n]; 771 + } 772 + function incbutfirst(arr, n, def) { 773 + if (n > 0) arr[0] = def[n]; 774 + for (var i = 1; i < n; i++) arr[i] = def[i]; 775 + } 776 + function incbutlast(arr, n, def) { 777 + for (var i = 0; i < n - 1; i++) arr[i] = def[i + 1]; 778 + if (n > 0) arr[n - 1] = def[0]; 779 + } 780 + 781 + var sort_cases = [ 782 + random, 783 + random8, 784 + random1, 785 + jigsaw, 786 + hill, 787 + comb, 788 + crisscross, 789 + zero, 790 + increasing, 791 + decreasing, 792 + alternate, 793 + incbutone, 794 + incbutlast, 795 + incbutfirst 796 + ]; 797 + 798 + var n = sort_bench.array_size || 10000; 799 + var array_type = sort_bench.array_type || Array; 800 + var def, arr; 801 + var i, j, x, y; 802 + var total = 0; 803 + 804 + var save_total_score = total_score; 805 + var save_total_scale = total_scale; 806 + 807 + // initialize default sorted array (n + 1 elements) 808 + def = new array_type(n + 1); 809 + if (array_type == Array) { 810 + for (i = 0; i <= n; i++) { 811 + def[i] = i + ''; 812 + } 813 + } else { 814 + for (i = 0; i <= n; i++) { 815 + def[i] = i; 816 + } 817 + } 818 + def.sort(); 819 + for (var f of sort_cases) { 820 + var ti = 0, 821 + tx = 0; 822 + for (j = 0; j < 100; j++) { 823 + arr = new array_type(n); 824 + f(arr, n, def); 825 + var t1 = get_clock(); 826 + arr.sort(); 827 + t1 = get_clock() - t1; 828 + tx += t1; 829 + if (!ti || ti > t1) ti = t1; 830 + if (tx >= clocks_per_sec) break; 831 + } 832 + total += ti; 833 + 834 + i = 0; 835 + x = arr[0]; 836 + if (x !== void 0) { 837 + for (i = 1; i < n; i++) { 838 + y = arr[i]; 839 + if (y === void 0) break; 840 + if (x > y) break; 841 + x = y; 842 + } 843 + } 844 + while (i < n && arr[i] === void 0) i++; 845 + if (i < n) { 846 + console.log('sort_bench: out of order error for ' + f.name + ' at offset ' + (i - 1) + ': ' + arr[i - 1] + ' > ' + arr[i]); 847 + } 848 + if (sort_bench.verbose) log_one('sort_' + f.name, n, ti, n * 100); 849 + } 850 + total_score = save_total_score; 851 + total_scale = save_total_scale; 852 + return total / n / 1000; 853 + } 854 + sort_bench.bench = true; 855 + sort_bench.verbose = false; 856 + 857 + function int_to_string(n) { 858 + var s, r, j; 859 + r = 0; 860 + for (j = 0; j < n; j++) { 861 + s = (j + 1).toString(); 862 + } 863 + return n; 864 + } 865 + 866 + function float_to_string(n) { 867 + var s, r, j; 868 + r = 0; 869 + for (j = 0; j < n; j++) { 870 + s = (j + 0.1).toString(); 871 + } 872 + return n; 873 + } 874 + 875 + function string_to_int(n) { 876 + var s, r, j; 877 + r = 0; 878 + s = '12345'; 879 + r = 0; 880 + for (j = 0; j < n; j++) { 881 + r += s | 0; 882 + } 883 + global_res = r; 884 + return n; 885 + } 886 + 887 + function string_to_float(n) { 888 + var s, r, j; 889 + r = 0; 890 + s = '12345.6'; 891 + r = 0; 892 + for (j = 0; j < n; j++) { 893 + r -= s; 894 + } 895 + global_res = r; 896 + return n; 897 + } 898 + 899 + function load_result(filename) { 900 + var f, str, res; 901 + if (typeof std === 'undefined') return null; 902 + f = std.open(filename, 'r'); 903 + if (!f) return null; 904 + str = f.readAsString(); 905 + res = JSON.parse(str); 906 + f.close(); 907 + return res; 908 + } 909 + 910 + function save_result(filename, obj) { 911 + var f; 912 + if (typeof std === 'undefined') return; 913 + f = std.open(filename, 'w'); 914 + f.puts(JSON.stringify(obj, null, 2)); 915 + f.puts('\n'); 916 + f.close(); 917 + } 918 + 919 + function main(argc, argv, g) { 920 + var test_list = [ 921 + empty_loop, 922 + date_now, 923 + prop_read, 924 + prop_write, 925 + prop_update, 926 + prop_create, 927 + prop_delete, 928 + array_read, 929 + array_write, 930 + array_update, 931 + array_prop_create, 932 + array_length_read, 933 + array_length_decr, 934 + // array_hole_length_decr, 935 + array_push, 936 + array_pop, 937 + typed_array_read, 938 + typed_array_write, 939 + closure_read, 940 + closure_write, 941 + global_read, 942 + global_write_strict, 943 + func_call, 944 + closure_var, 945 + int_arith, 946 + float_arith, 947 + // set_collection_add, 948 + array_for, 949 + array_for_in, 950 + array_for_of, 951 + math_min, 952 + regexp_ascii, 953 + regexp_utf16, 954 + regexp_replace, 955 + string_length, 956 + string_build1, 957 + string_build2, 958 + //string_build3, 959 + //string_build4, 960 + sort_bench, 961 + int_to_string, 962 + float_to_string, 963 + string_to_int, 964 + string_to_float 965 + ]; 966 + var tests = []; 967 + var i, j, n, f, name, found; 968 + 969 + if (typeof BigInt == 'function') { 970 + /* BigInt test */ 971 + test_list.push(bigint64_arith); 972 + test_list.push(bigint256_arith); 973 + } 974 + 975 + for (i = 1; i < argc; ) { 976 + name = argv[i++]; 977 + if (name == '-a') { 978 + sort_bench.verbose = true; 979 + continue; 980 + } 981 + if (name == '-t') { 982 + name = argv[i++]; 983 + sort_bench.array_type = g[name]; 984 + if (typeof sort_bench.array_type != 'function') { 985 + console.log('unknown array type: ' + name); 986 + return 1; 987 + } 988 + continue; 989 + } 990 + if (name == '-n') { 991 + sort_bench.array_size = +argv[i++]; 992 + continue; 993 + } 994 + for (j = 0, found = false; j < test_list.length; j++) { 995 + f = test_list[j]; 996 + if (f.name.slice(0, name.length) === name) { 997 + tests.push(f); 998 + found = true; 999 + } 1000 + } 1001 + if (!found) { 1002 + console.log('unknown benchmark: ' + name); 1003 + return 1; 1004 + } 1005 + } 1006 + if (tests.length == 0) tests = test_list; 1007 + 1008 + ref_data = load_result('microbench.txt'); 1009 + log_data = {}; 1010 + log_line.apply(null, heads); 1011 + n = 0; 1012 + 1013 + for (i = 0; i < tests.length; i++) { 1014 + f = tests[i]; 1015 + bench(f, f.name, ref_data, log_data); 1016 + if (ref_data && ref_data[f.name]) n++; 1017 + } 1018 + if (ref_data) log_line('total', '', total[2], total[3], (total_score * 100) / total_scale); 1019 + else log_line('total', '', total[2]); 1020 + 1021 + if (tests == test_list) save_result('microbench-new.txt', log_data); 1022 + } 1023 + 1024 + main(0, null, this);