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.

add gc_apply_off_callback and gc_apply_val

+125 -90
+2
include/internal.h
··· 84 84 85 85 jsoff_t esize(jsoff_t w); 86 86 87 + void js_gc_reserve_roots(GC_UPDATE_ARGS); 87 88 void js_gc_update_roots(GC_UPDATE_ARGS); 89 + 88 90 bool js_has_pending_coroutines(void); 89 91 bool is_internal_prop(const char *key, jsoff_t klen); 90 92
+67 -81
src/ant.c
··· 22924 22924 return js_type(val); 22925 22925 } 22926 22926 22927 - #define FWD_OFF(off) ((off) ? ((off) = fwd_off(ctx, off)) : 0) 22928 - #define FWD_VAL(val) ((val) = fwd_val(ctx, val)) 22929 - #define UTARRAY_EACH(arr, type, var) if (arr) for (type *var = (type *)utarray_front(arr), *_end = var + utarray_len(arr); var < _end; var++) 22927 + #define UTARRAY_EACH(arr, type, var) \ 22928 + if (arr) for (type *var = (type *)utarray_front(arr), *_end = var + utarray_len(arr); var < _end; var++) 22930 22929 22931 22930 #define REHASH_REGISTRY(registry, entry, tmp, new_reg, key_field, key_size, body) \ 22932 22931 for (typeof(registry) new_reg = NULL, *_once = NULL; !_once; _once = (void*)1, registry = new_reg) \ ··· 22936 22935 HASH_ADD(hh, new_reg, key_field, key_size, entry); \ 22937 22936 } 22938 22937 22939 - void js_gc_update_roots(GC_UPDATE_ARGS) { 22940 - UTARRAY_EACH(global_scope_stack, jsoff_t, off) FWD_OFF(*off); 22941 - UTARRAY_EACH(saved_scope_stack, jsval_t, val) FWD_VAL(*val); 22938 + #define GC_ROOTS_COMMON(OP_OFF, OP_VAL) \ 22939 + UTARRAY_EACH(global_scope_stack, jsoff_t, off) OP_OFF(*off); \ 22940 + UTARRAY_EACH(saved_scope_stack, jsval_t, val) OP_VAL(*val); \ 22941 + for (int i = 0; i < global_this_stack.depth; i++) OP_VAL(global_this_stack.stack[i]); \ 22942 + UTARRAY_EACH(propref_stack, propref_data_t, pref) { OP_OFF(pref->obj_off); OP_OFF(pref->key_off); } \ 22943 + UTARRAY_EACH(prim_propref_stack, prim_propref_data_t, ppref) { OP_VAL(ppref->prim_val); OP_OFF(ppref->key_off); } \ 22944 + if (rt && rt->js == js) OP_VAL(rt->ant_obj); \ 22945 + for (coroutine_t *coro = pending_coroutines.head; coro; coro = coro->next) { \ 22946 + OP_VAL(coro->scope); OP_VAL(coro->this_val); OP_VAL(coro->super_val); OP_VAL(coro->new_target); \ 22947 + OP_VAL(coro->awaited_promise); OP_VAL(coro->result); OP_VAL(coro->async_func); OP_VAL(coro->yield_value); \ 22948 + for (int i = 0; i < coro->for_let_stack_len; i++) { OP_VAL(coro->for_let_stack[i].body_scope); OP_OFF(coro->for_let_stack[i].prop_off); } \ 22949 + if (coro->scope_stack) UTARRAY_EACH(coro->scope_stack, jsoff_t, off) OP_OFF(*off); \ 22950 + if (coro->mco) { async_exec_context_t *actx = (async_exec_context_t *)mco_get_user_data(coro->mco); \ 22951 + if (actx) { OP_VAL(actx->closure_scope); OP_VAL(actx->result); OP_VAL(actx->promise); } } \ 22952 + } \ 22953 + { esm_module_t *mod, *mod_tmp; HASH_ITER(hh, global_module_cache.modules, mod, mod_tmp) { OP_VAL(mod->namespace_obj); OP_VAL(mod->default_export); } } \ 22954 + timer_gc_update_roots(fwd_val, ctx); ffi_gc_update_roots(fwd_val, ctx); fetch_gc_update_roots(fwd_val, ctx); \ 22955 + fs_gc_update_roots(fwd_val, ctx); child_process_gc_update_roots(fwd_val, ctx); readline_gc_update_roots(fwd_val, ctx); \ 22956 + { map_registry_entry_t *map_reg, *map_reg_tmp; HASH_ITER(hh, map_registry, map_reg, map_reg_tmp) { \ 22957 + if (map_reg->head && *map_reg->head) { map_entry_t *me, *me_tmp; HASH_ITER(hh, *map_reg->head, me, me_tmp) OP_VAL(me->value); } } } \ 22958 + { set_registry_entry_t *set_reg, *set_reg_tmp; HASH_ITER(hh, set_registry, set_reg, set_reg_tmp) { \ 22959 + if (set_reg->head && *set_reg->head) { set_entry_t *se, *se_tmp; HASH_ITER(hh, *set_reg->head, se, se_tmp) OP_VAL(se->value); } } } \ 22960 + for (int i = 0; i < js->for_let_stack_len; i++) { OP_VAL(js->for_let_stack[i].body_scope); OP_OFF(js->for_let_stack[i].prop_off); } 22942 22961 22943 - for (int i = 0; i < global_this_stack.depth; i++) 22944 - FWD_VAL(global_this_stack.stack[i]); 22962 + void js_gc_reserve_roots(GC_UPDATE_ARGS) { 22963 + #define RSV_OFF(x) ((x) ? (void)fwd_off(ctx, x) : (void)0) 22964 + #define RSV_VAL(x) (void)fwd_val(ctx, x) 22965 + 22966 + GC_ROOTS_COMMON(RSV_OFF, RSV_VAL) 22967 + 22968 + promise_data_entry_t *pd, *pd_tmp; 22969 + HASH_ITER(hh, promise_registry, pd, pd_tmp) { 22970 + (void)fwd_off(ctx, pd->obj_offset); 22971 + RSV_VAL(pd->value); 22972 + UTARRAY_EACH(pd->handlers, promise_handler_t, h) { 22973 + RSV_VAL(h->onFulfilled); RSV_VAL(h->onRejected); RSV_VAL(h->nextPromise); 22974 + } 22975 + } 22945 22976 22946 - UTARRAY_EACH(propref_stack, propref_data_t, pref) { 22947 - FWD_OFF(pref->obj_off); 22948 - FWD_OFF(pref->key_off); 22977 + proxy_data_t *proxy, *proxy_tmp; 22978 + HASH_ITER(hh, proxy_registry, proxy, proxy_tmp) { 22979 + (void)fwd_off(ctx, proxy->obj_offset); RSV_VAL(proxy->target); RSV_VAL(proxy->handler); 22949 22980 } 22950 22981 22951 - UTARRAY_EACH(prim_propref_stack, prim_propref_data_t, ppref) { 22952 - FWD_VAL(ppref->prim_val); 22953 - FWD_OFF(ppref->key_off); 22982 + dynamic_accessors_t *acc, *acc_tmp; 22983 + HASH_ITER(hh, accessor_registry, acc, acc_tmp) { (void)fwd_off(ctx, acc->obj_offset); } 22984 + 22985 + descriptor_entry_t *desc, *desc_tmp; 22986 + HASH_ITER(hh, desc_registry, desc, desc_tmp) { 22987 + if (desc->has_getter) RSV_VAL(desc->getter); 22988 + if (desc->has_setter) RSV_VAL(desc->setter); 22989 + (void)fwd_off(ctx, (jsoff_t)(desc->key >> 32)); 22954 22990 } 22991 + 22992 + #undef RSV_OFF 22993 + #undef RSV_VAL 22994 + } 22955 22995 22996 + void js_gc_update_roots(GC_UPDATE_ARGS) { 22997 + #define FWD_OFF(x) ((x) ? ((x) = fwd_off(ctx, x)) : 0) 22998 + #define FWD_VAL(x) ((x) = fwd_val(ctx, x)) 22999 + 23000 + GC_ROOTS_COMMON(FWD_OFF, FWD_VAL) 23001 + 22956 23002 promise_data_entry_t *pd, *pd_tmp; 22957 23003 promise_data_entry_t *new_unhandled = NULL; 22958 - 22959 23004 for ( 22960 23005 promise_data_entry_t *new_promise_registry = NULL, *_once = NULL; !_once; _once = (void*)1, 22961 23006 promise_registry = new_promise_registry, unhandled_rejections = new_unhandled ··· 22968 23013 22969 23014 jsoff_t new_off = fwd_off(ctx, pd->obj_offset); 22970 23015 if (new_off == pd->obj_offset && pd->obj_offset != 0) { 22971 - utarray_free(pd->handlers); 22972 - free(pd); continue; 23016 + utarray_free(pd->handlers); free(pd); continue; 22973 23017 } 22974 23018 22975 23019 pd->obj_offset = new_off; 22976 23020 FWD_VAL(pd->value); 22977 23021 UTARRAY_EACH(pd->handlers, promise_handler_t, h) { 22978 - FWD_VAL(h->onFulfilled); 22979 - FWD_VAL(h->onRejected); 22980 - FWD_VAL(h->nextPromise); 23022 + FWD_VAL(h->onFulfilled); FWD_VAL(h->onRejected); FWD_VAL(h->nextPromise); 22981 23023 } 22982 23024 22983 23025 HASH_ADD(hh, new_promise_registry, promise_id, sizeof(uint32_t), pd); 22984 23026 if (in_unhandled) HASH_ADD(hh_unhandled, new_unhandled, promise_id, sizeof(uint32_t), pd); 22985 23027 } 22986 - 22987 - if (rt && rt->js == js) FWD_VAL(rt->ant_obj); 22988 23028 22989 23029 proxy_data_t *proxy, *proxy_tmp; 22990 23030 REHASH_REGISTRY(proxy_registry, proxy, proxy_tmp, new_proxy, obj_offset, sizeof(jsoff_t), { 22991 - FWD_OFF(proxy->obj_offset); 22992 - FWD_VAL(proxy->target); 22993 - FWD_VAL(proxy->handler); 23031 + FWD_OFF(proxy->obj_offset); FWD_VAL(proxy->target); FWD_VAL(proxy->handler); 22994 23032 }); 22995 23033 22996 23034 dynamic_accessors_t *acc, *acc_tmp; ··· 23007 23045 desc->obj_off = obj_off; 23008 23046 }); 23009 23047 23010 - for (coroutine_t *coro = pending_coroutines.head; coro; coro = coro->next) { 23011 - FWD_VAL(coro->scope); 23012 - FWD_VAL(coro->this_val); 23013 - FWD_VAL(coro->super_val); 23014 - FWD_VAL(coro->new_target); 23015 - FWD_VAL(coro->awaited_promise); 23016 - FWD_VAL(coro->result); 23017 - FWD_VAL(coro->async_func); 23018 - FWD_VAL(coro->yield_value); 23019 - for (int i = 0; i < coro->for_let_stack_len; i++) { 23020 - FWD_VAL(coro->for_let_stack[i].body_scope); 23021 - FWD_OFF(coro->for_let_stack[i].prop_off); 23022 - } 23023 - if (coro->scope_stack) UTARRAY_EACH(coro->scope_stack, jsoff_t, off) FWD_OFF(*off); 23024 - if (coro->mco) { 23025 - async_exec_context_t *actx = (async_exec_context_t *)mco_get_user_data(coro->mco); 23026 - if (actx) { FWD_VAL(actx->closure_scope); FWD_VAL(actx->result); FWD_VAL(actx->promise); } 23027 - } 23028 - } 23029 - 23030 - esm_module_t *mod, *mod_tmp; 23031 - HASH_ITER(hh, global_module_cache.modules, mod, mod_tmp) { 23032 - FWD_VAL(mod->namespace_obj); 23033 - FWD_VAL(mod->default_export); 23034 - } 23035 - 23036 - timer_gc_update_roots(fwd_val, ctx); 23037 - ffi_gc_update_roots(fwd_val, ctx); 23038 - fetch_gc_update_roots(fwd_val, ctx); 23039 - fs_gc_update_roots(fwd_val, ctx); 23040 - child_process_gc_update_roots(fwd_val, ctx); 23041 - readline_gc_update_roots(fwd_val, ctx); 23042 - 23043 - map_registry_entry_t *map_reg, *map_reg_tmp; 23044 - HASH_ITER(hh, map_registry, map_reg, map_reg_tmp) { 23045 - if (map_reg->head && *map_reg->head) { 23046 - map_entry_t *me, *me_tmp; 23047 - HASH_ITER(hh, *map_reg->head, me, me_tmp) FWD_VAL(me->value); 23048 - } 23049 - } 23050 - 23051 - set_registry_entry_t *set_reg, *set_reg_tmp; 23052 - HASH_ITER(hh, set_registry, set_reg, set_reg_tmp) { 23053 - if (set_reg->head && *set_reg->head) { 23054 - set_entry_t *se, *se_tmp; 23055 - HASH_ITER(hh, *set_reg->head, se, se_tmp) FWD_VAL(se->value); 23056 - } 23057 - } 23058 - 23059 - for (int i = 0; i < js->for_let_stack_len; i++) { 23060 - FWD_VAL(js->for_let_stack[i].body_scope); 23061 - FWD_OFF(js->for_let_stack[i].prop_off); 23062 - } 23063 - 23064 23048 memset(intern_prop_cache, 0, sizeof(intern_prop_cache)); 23049 + 23050 + #undef FWD_OFF 23051 + #undef FWD_VAL 23065 23052 } 23066 23053 23067 - #undef FWD_OFF 23068 - #undef FWD_VAL 23069 23054 #undef UTARRAY_EACH 23070 23055 #undef REHASH_REGISTRY 23056 + #undef GC_ROOTS_COMMON 23071 23057 23072 23058 bool js_chkargs(jsval_t *args, int nargs, const char *spec) { 23073 23059 int i = 0, ok = 1;
+56 -9
src/gc.c
··· 436 436 return gc_update_val(ctx, val); 437 437 } 438 438 439 + static jsoff_t gc_apply_off_callback(void *ctx_ptr, jsoff_t old_off) { 440 + gc_ctx_t *ctx = (gc_ctx_t *)ctx_ptr; 441 + if (old_off == 0) return 0; 442 + if (old_off >= ctx->js->brk) return old_off; 443 + 444 + jsoff_t new_off = fwd_lookup(&ctx->fwd, old_off); 445 + return (new_off != (jsoff_t)~0) ? new_off : old_off; 446 + } 447 + 448 + static jsval_t gc_apply_val(gc_ctx_t *ctx, jsval_t val) { 449 + if (!gc_is_tagged(val)) return val; 450 + 451 + uint8_t type = gc_vtype(val); 452 + jsoff_t old_off = (jsoff_t)gc_vdata(val); 453 + if (old_off >= ctx->js->brk) return val; 454 + 455 + switch (type) { 456 + case T_OBJ: 457 + case T_FUNC: 458 + case T_ARR: 459 + case T_PROMISE: 460 + case T_GENERATOR: 461 + case T_STR: 462 + case T_PROP: 463 + case T_BIGINT: { 464 + jsoff_t new_off = fwd_lookup(&ctx->fwd, old_off); 465 + if (new_off != (jsoff_t)~0) return gc_mkval(type, new_off); 466 + break; 467 + } 468 + default: break; 469 + } 470 + 471 + return val; 472 + } 473 + 474 + static jsval_t gc_apply_val_callback(void *ctx_ptr, jsval_t val) { 475 + gc_ctx_t *ctx = (gc_ctx_t *)ctx_ptr; 476 + return gc_apply_val(ctx, val); 477 + } 478 + 439 479 size_t js_gc_compact(ant_t *js) { 440 480 if (!js || js->brk == 0) return 0; 441 481 ··· 485 525 } 486 526 487 527 ctx.failed = false; 488 - 528 + 489 529 if (js->brk > 0) { 490 530 jsoff_t header_at_0 = gc_loadoff(js->mem, 0); 491 531 if ((header_at_0 & 3) == T_OBJ) gc_reserve_object(&ctx, 0); ··· 493 533 494 534 jsoff_t scope_off = (jsoff_t)gc_vdata(js->scope); 495 535 if (scope_off < js->brk) { 496 - jsoff_t new_scope = gc_reserve_object(&ctx, scope_off); 497 - js->scope = gc_mkval(T_OBJ, new_scope); 536 + (void)gc_reserve_object(&ctx, scope_off); 498 537 } 499 538 500 - js->this_val = gc_update_val(&ctx, js->this_val); 501 - js->module_ns = gc_update_val(&ctx, js->module_ns); 502 - js->current_func = gc_update_val(&ctx, js->current_func); 503 - js->thrown_value = gc_update_val(&ctx, js->thrown_value); 504 - js->tval = gc_update_val(&ctx, js->tval); 505 - js_gc_update_roots(js, gc_fwd_off_callback, gc_fwd_val_callback, &ctx); 539 + (void)gc_update_val(&ctx, js->this_val); 540 + (void)gc_update_val(&ctx, js->module_ns); 541 + (void)gc_update_val(&ctx, js->current_func); 542 + (void)gc_update_val(&ctx, js->thrown_value); 543 + (void)gc_update_val(&ctx, js->tval); 544 + js_gc_reserve_roots(js, gc_fwd_off_callback, gc_fwd_val_callback, &ctx); 506 545 507 546 gc_drain_work_queue(&ctx); 508 547 ··· 513 552 ANT_GC_FREE(new_mem); 514 553 return 0; 515 554 } 555 + 556 + js->scope = gc_apply_val(&ctx, js->scope); 557 + js->this_val = gc_apply_val(&ctx, js->this_val); 558 + js->module_ns = gc_apply_val(&ctx, js->module_ns); 559 + js->current_func = gc_apply_val(&ctx, js->current_func); 560 + js->thrown_value = gc_apply_val(&ctx, js->thrown_value); 561 + js->tval = gc_apply_val(&ctx, js->tval); 562 + js_gc_update_roots(js, gc_apply_off_callback, gc_apply_val_callback, &ctx); 516 563 517 564 uint8_t *old_mem = js->mem; 518 565 js->mem = new_mem;