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.

disable gc compacting and switch to bdwgc

+77 -18
+19
include/arena.h
··· 1 + #ifndef ARENA_H 2 + #define ARENA_H 3 + 4 + #define NO_EXECUTE_PERMISSION 1 5 + #define GC_NO_THREAD_REDIRECTS 1 6 + #define GC_THREADS 1 7 + #include <gc.h> 8 + 9 + #define ANT_GC_INIT() GC_INIT() 10 + #define ANT_GC_MALLOC(size) GC_MALLOC(size) 11 + #define ANT_GC_MALLOC_ATOMIC(size) GC_MALLOC_ATOMIC(size) 12 + #define ANT_GC_REALLOC(ptr, size) GC_REALLOC(ptr, size) 13 + #define ANT_GC_FREE(ptr) GC_FREE(ptr) 14 + #define ANT_GC_COLLECT() GC_gcollect() 15 + 16 + #define ANT_GC_REGISTER_ROOT(ptr) 17 + #define ANT_GC_UNREGISTER_ROOT(ptr) 18 + 19 + #endif
+3
maidfile.toml
··· 6 6 path = "build" 7 7 script = "meson clean" 8 8 9 + [tasks.setup] 10 + script = "bash -c 'CC=/opt/homebrew/opt/llvm/bin/clang meson setup build --wipe -Dc_args=-DNO_EXECUTE_PERMISSION'" 11 + 9 12 [tasks.run] 10 13 script = ["maid build -q", "./build/ant %{arg.1}"] 11 14
+7 -2
meson.build
··· 68 68 build_date = run_command('date', '+%Y-%m-%d', check: true).stdout().strip() 69 69 70 70 version_conf = configuration_data() 71 - version_conf.set('ANT_VERSION', '0.0.6.41') 71 + version_conf.set('ANT_VERSION', '0.0.7.1') 72 72 version_conf.set('ANT_GIT_HASH', git_hash) 73 73 version_conf.set('ANT_BUILD_DATE', build_date) 74 74 ··· 79 79 ) 80 80 81 81 build_include = include_directories('.') 82 - add_project_arguments('-D JS_DUMP', '-Wno-unused-function', language: 'c') 82 + 83 + add_project_arguments( 84 + '-D JS_DUMP', 85 + '-Wno-unused-function', 86 + '-D NO_EXECUTE_PERMISSION', 87 + language: 'c') 83 88 84 89 gen_snapshot = executable( 85 90 'gen_snapshot',
+48 -16
src/ant.c
··· 17 17 18 18 #include "ant.h" 19 19 #include "config.h" 20 + #include "arena.h" 20 21 21 22 #include "modules/fs.h" 22 23 #include "modules/timer.h" ··· 121 122 static esm_module_cache_t global_module_cache = {NULL, 0}; 122 123 123 124 void ant_register_library(const char *name, ant_library_init_fn init_fn) { 124 - ant_library_t *lib = (ant_library_t *)malloc(sizeof(ant_library_t)); 125 + ant_library_t *lib = (ant_library_t *)ANT_GC_MALLOC(sizeof(ant_library_t)); 125 126 if (!lib) return; 126 127 127 - lib->name = strdup(name); 128 + size_t name_len = strlen(name) + 1; 129 + lib->name = (char *)ANT_GC_MALLOC_ATOMIC(name_len); 130 + if (lib->name) memcpy(lib->name, name, name_len); 131 + 128 132 lib->init_fn = init_fn; 129 133 lib->next = library_registry; 130 134 library_registry = lib; ··· 500 504 501 505 static jsval_t start_async_in_coroutine(struct js *js, const char *code, size_t code_len, jsval_t closure_scope, jsval_t *args, int nargs) { 502 506 jsval_t promise = js_mkpromise(js); 503 - async_exec_context_t *ctx = (async_exec_context_t *)malloc(sizeof(async_exec_context_t)); 507 + async_exec_context_t *ctx = (async_exec_context_t *)ANT_GC_MALLOC(sizeof(async_exec_context_t)); 504 508 if (!ctx) return js_mkerr(js, "out of memory for async context"); 505 509 506 510 ctx->js = js; ··· 518 522 mco_coro* mco = NULL; 519 523 mco_result res = mco_create(&mco, &desc); 520 524 if (res != MCO_SUCCESS) { 521 - free(ctx); 525 + ANT_GC_FREE(ctx); 522 526 return js_mkerr(js, "failed to create minicoro coroutine"); 523 527 } 524 528 525 - coroutine_t *coro = (coroutine_t *)malloc(sizeof(coroutine_t)); 529 + coroutine_t *coro = (coroutine_t *)ANT_GC_MALLOC(sizeof(coroutine_t)); 526 530 if (!coro) { 527 531 mco_destroy(mco); 528 - free(ctx); 532 + ANT_GC_FREE(ctx); 529 533 return js_mkerr(js, "out of memory for coroutine"); 530 534 } 531 535 ··· 537 541 coro->result = js_mkundef(); 538 542 coro->async_func = js->current_func; 539 543 if (nargs > 0) { 540 - coro->args = (jsval_t *)malloc(sizeof(jsval_t) * nargs); 544 + coro->args = (jsval_t *)ANT_GC_MALLOC(sizeof(jsval_t) * nargs); 541 545 if (coro->args) memcpy(coro->args, args, sizeof(jsval_t) * nargs); 542 546 } else { 543 547 coro->args = NULL; ··· 560 564 if (res != MCO_SUCCESS && mco_status(mco) != MCO_DEAD) { 561 565 dequeue_coroutine(); 562 566 free_coroutine(coro); 563 - free(ctx); 567 + ANT_GC_FREE(ctx); 564 568 return js_mkerr(js, "failed to start coroutine"); 565 569 } 566 570 ··· 568 572 if (mco_status(mco) == MCO_DEAD) { 569 573 dequeue_coroutine(); 570 574 free_coroutine(coro); 571 - free(ctx); 575 + ANT_GC_FREE(ctx); 572 576 } 573 577 574 578 return promise; ··· 580 584 mco_destroy(coro->mco); 581 585 coro->mco = NULL; 582 586 } 583 - if (coro->args) free(coro->args); 584 - free(coro); 587 + if (coro->args) ANT_GC_FREE(coro->args); 588 + ANT_GC_FREE(coro); 585 589 } 586 590 } 587 591 ··· 982 986 if (new_size <= current_total) return false; 983 987 984 988 void *old_buf = (void *)((uint8_t *)js - 0); 985 - void *new_buf = realloc(old_buf, new_size); 989 + void *new_buf = ANT_GC_REALLOC(old_buf, new_size); 986 990 987 991 if (new_buf == NULL) return false; 988 992 struct js *new_js = (struct js *)new_buf; ··· 1009 1013 ofs = js->brk; 1010 1014 if (js->brk + size > js->size) return ~(jsoff_t) 0; 1011 1015 } else { 1016 + // Call bdwgc collector instead of custom GC 1017 + ANT_GC_COLLECT(); 1018 + // Also compact our arena if needed 1012 1019 js_gc(js); 1013 1020 ofs = js->brk; 1014 1021 if (js->brk + size > js->size) { ··· 1110 1117 return t == T_OBJ || t == T_PROP || t == T_STR || t == T_FUNC || t == T_ARR || t == T_PROMISE; 1111 1118 } 1112 1119 1120 + // DISABLED: These functions were causing memory corruption by moving offsets 1121 + // Now we use bdwgc for C allocations and keep JS arena stable (no compacting) 1122 + /* 1113 1123 static void js_fixup_offsets(struct js *js, jsoff_t start, jsoff_t size) { 1114 1124 for (jsoff_t n, v, off = 0; off < js->brk; off += n) { 1115 1125 v = loadoff(js, off); ··· 1155 1165 } 1156 1166 } 1157 1167 } 1168 + */ 1158 1169 1159 1170 static void js_mark_all_entities_for_deletion(struct js *js) { 1160 1171 for (jsoff_t v, off = 0; off < js->brk; off += esize(v & ~(GCMASK | CONSTMASK))) { ··· 1188 1199 if (js->nogc) js_unmark_entity(js, js->nogc); 1189 1200 } 1190 1201 1202 + static void js_clear_gc_marks(struct js *js) { 1203 + // Simply clear all GC marks without moving memory 1204 + for (jsoff_t v, off = 0; off < js->brk; off += esize(v & ~(GCMASK | CONSTMASK))) { 1205 + v = loadoff(js, off); 1206 + if (v & GCMASK) { 1207 + // Keep the entity but clear the GC mark 1208 + saveoff(js, off, v & ~GCMASK); 1209 + } 1210 + } 1211 + } 1212 + 1191 1213 void js_gc(struct js *js) { 1192 1214 setlwm(js); 1193 1215 if (js->nogc == (jsoff_t) ~0) return; 1216 + 1217 + // NOTE: We still do mark-and-sweep to identify live objects, 1218 + // but we NO LONGER compact/move memory. This prevents offset corruption. 1219 + // The bdwgc handles C-side allocations, and we keep the JS arena stable. 1220 + 1194 1221 js_mark_all_entities_for_deletion(js); 1195 1222 js_unmark_used_entities(js); 1196 - js_delete_marked_entities(js); 1223 + // REMOVED: js_delete_marked_entities(js); // This was causing offset corruption 1224 + 1225 + // Instead, we just clear the GC marks without moving anything 1226 + js_clear_gc_marks(js); 1197 1227 } 1198 1228 1199 1229 static jsoff_t skiptonext(const char *code, jsoff_t len, jsoff_t n) { ··· 7759 7789 } 7760 7790 7761 7791 struct js *js_create(void *buf, size_t len) { 7792 + ANT_GC_INIT(); 7793 + 7762 7794 struct js *js = NULL; 7763 7795 if (len < sizeof(*js) + esize(T_OBJ)) return js; 7764 7796 memset(buf, 0, len); ··· 7839 7871 if (initial_size < sizeof(struct js) + esize(T_OBJ)) initial_size = 1024 * 1024; 7840 7872 if (max_size == 0 || max_size < initial_size) max_size = 512 * 1024 * 1024; 7841 7873 7842 - void *buf = malloc(initial_size); 7874 + void *buf = ANT_GC_MALLOC(initial_size); 7843 7875 if (buf == NULL) return NULL; 7844 7876 7845 7877 struct js *js = js_create(buf, initial_size); 7846 7878 if (js == NULL) { 7847 - free(buf); 7879 + ANT_GC_FREE(buf); 7848 7880 return NULL; 7849 7881 } 7850 7882 ··· 7858 7890 if (js == NULL) return; 7859 7891 7860 7892 if (js->owns_mem) { 7861 - free((void *)((uint8_t *)js - 0)); 7893 + ANT_GC_FREE((void *)((uint8_t *)js - 0)); 7862 7894 } 7863 7895 } 7864 7896