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.

restructure Map/Set registry to support GC fwd tracking

+126 -37
+1
.github/download.sh
··· 37 37 38 38 gh api "repos/${REPO}/actions/runs/${RUN_ID}/artifacts" --jq '.artifacts[] | "\(.id) \(.name)"' | \ 39 39 while read -r id name; do 40 + if [[ "$name" == version-* ]]; then continue; fi 40 41 echo " Downloading $name..." 41 42 gh api "repos/${REPO}/actions/artifacts/${id}/zip" > "${OUT_DIR}/${name}.zip" 42 43 done
+14 -1
include/modules/collections.h
··· 3 3 4 4 #include <uthash.h> 5 5 #include "types.h" 6 + #include "gc.h" 6 7 7 8 typedef struct map_entry { 8 9 char *key; ··· 47 48 iter_type_t type; 48 49 } set_iterator_state_t; 49 50 51 + typedef struct map_registry_entry { 52 + map_entry_t **head; 53 + jsoff_t obj_offset; 54 + } map_registry_entry_t; 55 + 56 + typedef struct set_registry_entry { 57 + set_entry_t **head; 58 + jsoff_t obj_offset; 59 + } set_registry_entry_t; 60 + 50 61 void init_collections_module(void); 51 62 void cleanup_collections_module(void); 52 - void collections_gc_update_roots(void (*op_val)(void *, jsval_t *), void *ctx); 63 + 64 + void collections_gc_reserve_roots(GC_OP_VAL_ARGS); 65 + void collections_gc_update_roots(jsoff_t (*fwd_off)(void *ctx, jsoff_t old), GC_OP_VAL_ARGS); 53 66 54 67 map_entry_t **get_map_from_obj(ant_t *js, jsval_t obj); 55 68 set_entry_t **get_set_from_obj(ant_t *js, jsval_t obj);
+2 -1
src/ant.c
··· 21444 21444 child_process_gc_update_roots(op_val, c); 21445 21445 readline_gc_update_roots(op_val, c); 21446 21446 process_gc_update_roots(op_val, c); 21447 - collections_gc_update_roots(op_val, c); 21447 + collections_gc_reserve_roots(op_val, c); 21448 21448 21449 21449 for (int i = 0; i < c->js->for_let_stack_len; i++) { 21450 21450 op_val(c, &c->js->for_let_stack[i].body_scope); ··· 21563 21563 } 21564 21564 21565 21565 memset(intern_prop_cache, 0, sizeof(intern_prop_cache)); 21566 + collections_gc_update_roots(fwd_off, gc_update_val_cb, &cb_ctx); 21566 21567 21567 21568 #undef FWD_OFF 21568 21569 #undef FWD_VAL
+109 -35
src/modules/collections.c
··· 7 7 #include "runtime.h" 8 8 #include "internal.h" 9 9 #include "arena.h" 10 + #include "gc.h" 10 11 11 12 #include "modules/collections.h" 12 13 #include "modules/symbol.h" 13 14 14 - static map_entry_t ***map_registry_heads = NULL; 15 + static map_registry_entry_t *map_registry = NULL; 15 16 static size_t map_registry_count = 0; 16 17 static size_t map_registry_cap = 0; 17 18 18 - static set_entry_t ***set_registry_heads = NULL; 19 + static set_registry_entry_t *set_registry = NULL; 19 20 static size_t set_registry_count = 0; 20 21 static size_t set_registry_cap = 0; 21 22 ··· 23 24 return js->this_val; 24 25 } 25 26 26 - static void register_map(map_entry_t **head) { 27 + static void register_map(map_entry_t **head, jsoff_t obj_offset) { 27 28 if (!head) return; 28 29 if (map_registry_count >= map_registry_cap) { 29 30 size_t new_cap = map_registry_cap ? map_registry_cap * 2 : 64; 30 - map_entry_t ***new_reg = realloc(map_registry_heads, new_cap * sizeof(map_entry_t **)); 31 + map_registry_entry_t *new_reg = realloc(map_registry, new_cap * sizeof(map_registry_entry_t)); 31 32 if (!new_reg) return; 32 - map_registry_heads = new_reg; 33 + map_registry = new_reg; 33 34 map_registry_cap = new_cap; 34 35 } 35 - map_registry_heads[map_registry_count++] = head; 36 + map_registry[map_registry_count].head = head; 37 + map_registry[map_registry_count].obj_offset = obj_offset; 38 + map_registry_count++; 36 39 } 37 40 38 - static void register_set(set_entry_t **head) { 41 + static void register_set(set_entry_t **head, jsoff_t obj_offset) { 39 42 if (!head) return; 40 43 if (set_registry_count >= set_registry_cap) { 41 44 size_t new_cap = set_registry_cap ? set_registry_cap * 2 : 64; 42 - set_entry_t ***new_reg = realloc(set_registry_heads, new_cap * sizeof(set_entry_t **)); 45 + set_registry_entry_t *new_reg = realloc(set_registry, new_cap * sizeof(set_registry_entry_t)); 43 46 if (!new_reg) return; 44 - set_registry_heads = new_reg; 47 + set_registry = new_reg; 45 48 set_registry_cap = new_cap; 46 49 } 47 - set_registry_heads[set_registry_count++] = head; 50 + set_registry[set_registry_count].head = head; 51 + set_registry[set_registry_count].obj_offset = obj_offset; 52 + set_registry_count++; 48 53 } 49 54 50 55 static const char *jsval_to_key(ant_t *js, jsval_t val) { ··· 716 721 717 722 static jsval_t builtin_Map(ant_t *js, jsval_t *args, int nargs) { 718 723 jsval_t map_obj = js_mkobj(js); 724 + jsoff_t obj_offset = (jsoff_t)vdata(map_obj); 719 725 720 726 jsval_t map_proto = js_get_ctor_proto(js, "Map", 3); 721 727 if (is_special_object(map_proto)) js_set_proto(js, map_obj, map_proto); ··· 724 730 if (!map_head) return js_mkerr(js, "out of memory"); 725 731 *map_head = NULL; 726 732 727 - register_map(map_head); 733 + register_map(map_head, obj_offset); 728 734 js_set_slot(js, map_obj, SLOT_MAP, ANT_PTR(map_head)); 729 735 730 736 if (nargs == 0 || vtype(args[0]) != T_ARR) return map_obj; ··· 762 768 763 769 static jsval_t builtin_Set(ant_t *js, jsval_t *args, int nargs) { 764 770 jsval_t set_obj = js_mkobj(js); 771 + jsoff_t obj_offset = (jsoff_t)vdata(set_obj); 765 772 766 773 jsval_t set_proto = js_get_ctor_proto(js, "Set", 3); 767 774 if (is_special_object(set_proto)) js_set_proto(js, set_obj, set_proto); ··· 770 777 if (!set_head) return js_mkerr(js, "out of memory"); 771 778 *set_head = NULL; 772 779 773 - register_set(set_head); 780 + register_set(set_head, obj_offset); 774 781 js_set_slot(js, set_obj, SLOT_SET, ANT_PTR(set_head)); 775 782 776 783 if (nargs == 0 || vtype(args[0]) != T_ARR) return set_obj; ··· 976 983 js_set(js, glob, "FinalizationRegistry", js_obj_to_func(finreg_ctor)); 977 984 } 978 985 979 - void collections_gc_update_roots(void (*op_val)(void *, jsval_t *), void *ctx) { 986 + void collections_gc_reserve_roots(void (*op_val)(void *, jsval_t *), void *ctx) { 980 987 for (size_t i = 0; i < map_registry_count; i++) { 981 - map_entry_t **head = map_registry_heads[i]; 988 + map_entry_t **head = map_registry[i].head; 982 989 if (head && *head) { 983 990 map_entry_t *entry, *tmp; 984 991 HASH_ITER(hh, *head, entry, tmp) op_val(ctx, &entry->value); ··· 986 993 } 987 994 988 995 for (size_t i = 0; i < set_registry_count; i++) { 989 - set_entry_t **head = set_registry_heads[i]; 996 + set_entry_t **head = set_registry[i].head; 990 997 if (head && *head) { 991 998 set_entry_t *entry, *tmp; 992 999 HASH_ITER(hh, *head, entry, tmp) op_val(ctx, &entry->value); ··· 994 1001 } 995 1002 } 996 1003 997 - #define CLEANUP_REGISTRY(type, heads, count, cap) do { \ 998 - for (size_t i = 0; i < count; i++) { \ 999 - type##_entry_t **head = heads[i]; \ 1000 - if (head && *head) { \ 1001 - type##_entry_t *entry, *tmp; \ 1002 - HASH_ITER(hh, *head, entry, tmp) { \ 1003 - HASH_DEL(*head, entry); \ 1004 - free(entry->key); \ 1005 - free(entry); \ 1006 - } \ 1007 - } \ 1008 - free(head); \ 1009 - } \ 1010 - free(heads); \ 1011 - heads = NULL; \ 1012 - count = 0; \ 1013 - cap = 0; \ 1014 - } while(0) 1004 + static void free_map_entries(map_entry_t **head) { 1005 + if (!head || !*head) return; 1006 + map_entry_t *entry, *tmp; 1007 + HASH_ITER(hh, *head, entry, tmp) { 1008 + HASH_DEL(*head, entry); 1009 + free(entry->key); 1010 + free(entry); 1011 + } 1012 + } 1013 + 1014 + static void free_set_entries(set_entry_t **head) { 1015 + if (!head || !*head) return; 1016 + set_entry_t *entry, *tmp; 1017 + HASH_ITER(hh, *head, entry, tmp) { 1018 + HASH_DEL(*head, entry); 1019 + free(entry->key); 1020 + free(entry); 1021 + } 1022 + } 1023 + 1024 + void collections_gc_update_roots(jsoff_t (*fwd_off)(void *ctx, jsoff_t old), GC_OP_VAL_ARGS) { 1025 + size_t write_idx = 0; 1026 + 1027 + for (size_t i = 0; i < map_registry_count; i++) { 1028 + jsoff_t old_off = map_registry[i].obj_offset; 1029 + jsoff_t new_off = fwd_off(ctx, old_off); 1030 + 1031 + if (new_off == old_off && old_off != 0) { 1032 + free_map_entries(map_registry[i].head); 1033 + free(map_registry[i].head); 1034 + continue; 1035 + } 1036 + 1037 + map_registry[i].obj_offset = new_off; 1038 + 1039 + map_entry_t **head = map_registry[i].head; 1040 + if (head && *head) { 1041 + map_entry_t *entry, *tmp; 1042 + HASH_ITER(hh, *head, entry, tmp) op_val(ctx, &entry->value); 1043 + } 1044 + 1045 + if (write_idx != i) map_registry[write_idx] = map_registry[i]; 1046 + write_idx++; 1047 + } 1048 + map_registry_count = write_idx; 1049 + 1050 + write_idx = 0; 1051 + for (size_t i = 0; i < set_registry_count; i++) { 1052 + jsoff_t old_off = set_registry[i].obj_offset; 1053 + jsoff_t new_off = fwd_off(ctx, old_off); 1054 + 1055 + if (new_off == old_off && old_off != 0) { 1056 + free_set_entries(set_registry[i].head); 1057 + free(set_registry[i].head); 1058 + continue; 1059 + } 1060 + 1061 + set_registry[i].obj_offset = new_off; 1062 + 1063 + set_entry_t **head = set_registry[i].head; 1064 + if (head && *head) { 1065 + set_entry_t *entry, *tmp; 1066 + HASH_ITER(hh, *head, entry, tmp) op_val(ctx, &entry->value); 1067 + } 1068 + 1069 + if (write_idx != i) set_registry[write_idx] = set_registry[i]; 1070 + write_idx++; 1071 + } 1072 + set_registry_count = write_idx; 1073 + } 1015 1074 1016 1075 void cleanup_collections_module(void) { 1017 - CLEANUP_REGISTRY(map, map_registry_heads, map_registry_count, map_registry_cap); 1018 - CLEANUP_REGISTRY(set, set_registry_heads, set_registry_count, set_registry_cap); 1076 + for (size_t i = 0; i < map_registry_count; i++) { 1077 + free_map_entries(map_registry[i].head); 1078 + free(map_registry[i].head); 1079 + } 1080 + free(map_registry); 1081 + map_registry = NULL; 1082 + map_registry_count = 0; 1083 + map_registry_cap = 0; 1084 + 1085 + for (size_t i = 0; i < set_registry_count; i++) { 1086 + free_set_entries(set_registry[i].head); 1087 + free(set_registry[i].head); 1088 + } 1089 + free(set_registry); 1090 + set_registry = NULL; 1091 + set_registry_count = 0; 1092 + set_registry_cap = 0; 1019 1093 } 1020 1094 1021 1095 #undef CLEANUP_REGISTRY