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 marking for lmdb, tls, napi, and generators

+92 -40
+1
include/gc/modules.h
··· 33 33 void gc_mark_zlib(ant_t *js, gc_mark_fn mark); 34 34 void gc_mark_wasm(ant_t *js, gc_mark_fn mark); 35 35 void gc_mark_napi(ant_t *js, gc_mark_fn mark); 36 + void gc_clear_napi_weak_refs(ant_t *js, bool minor); 36 37 void gc_mark_abort_signal_object(ant_t *js, ant_value_t signal, gc_mark_fn mark); 37 38 38 39 #endif
+2
src/gc/objects.c
··· 749 749 } 750 750 751 751 gc_mark_roots(js); 752 + gc_clear_napi_weak_refs(js, false); 752 753 gc_sweep_regex_cache(); 753 754 gc_sweep(js); 754 755 ··· 840 841 841 842 js->remember_set_len = 0; 842 843 gc_mark_roots(js); 844 + gc_clear_napi_weak_refs(js, true); 843 845 g_minor_gc = false; 844 846 845 847 gc_sweep_regex_cache();
+1 -2
src/modules/generator.c
··· 288 288 289 289 if (!data) return; 290 290 if (data->coro) generator_clear_coro(gen, data->coro); 291 - 292 - js_set_native(gen, NULL, 0); 291 + js_clear_native(gen, GENERATOR_NATIVE_TAG); 293 292 294 293 generator_free_queue(data); 295 294 free(data);
+64 -31
src/modules/lmdb.c
··· 77 77 }; 78 78 79 79 static ant_value_t make_env_obj(ant_t *js, lmdb_env_handle_t *env); 80 - static ant_value_t make_db_obj(ant_t *js, lmdb_db_handle_t *db); 81 - static ant_value_t make_txn_obj(ant_t *js, lmdb_txn_handle_t *txn); 80 + static ant_value_t make_db_obj(ant_t *js, lmdb_db_handle_t *db, ant_value_t env_obj); 81 + static ant_value_t make_txn_obj(ant_t *js, lmdb_txn_handle_t *txn, ant_value_t env_obj); 82 82 83 83 static void list_remove_db(lmdb_env_handle_t *env, lmdb_db_handle_t *target) { 84 84 if (!env || !target) return; ··· 133 133 txn_refs = ref; 134 134 } 135 135 136 - static lmdb_env_handle_t *find_env_by_obj(ant_value_t obj) { 137 - for (lmdb_env_ref_t *ref = env_refs; ref; ref = ref->next) 138 - if (ref->obj == obj) return ref->env; 139 - return NULL; 140 - } 141 - 142 - static lmdb_db_handle_t *find_db_by_obj(ant_value_t obj) { 143 - for (lmdb_db_ref_t *ref = db_refs; ref; ref = ref->next) 144 - if (ref->obj == obj) return ref->db; 145 - return NULL; 146 - } 147 - 148 - static lmdb_txn_handle_t *find_txn_by_obj(ant_value_t obj) { 149 - for (lmdb_txn_ref_t *ref = txn_refs; ref; ref = ref->next) 150 - if (ref->obj == obj) return ref->txn; 151 - return NULL; 152 - } 153 - 154 136 static void unregister_env_ref_by_obj(ant_value_t obj) { 155 137 lmdb_env_ref_t **cur = &env_refs; 156 138 while (*cur) { 157 139 if ((*cur)->obj == obj) { 158 140 lmdb_env_ref_t *next = (*cur)->next; 141 + js_clear_native((*cur)->obj, LMDB_ENV_NATIVE_TAG); 159 142 free(*cur); 160 143 *cur = next; 161 144 return; ··· 169 152 while (*cur) { 170 153 if ((*cur)->obj == obj) { 171 154 lmdb_db_ref_t *next = (*cur)->next; 155 + js_clear_native((*cur)->obj, LMDB_DB_NATIVE_TAG); 172 156 free(*cur); 173 157 *cur = next; 174 158 return; ··· 182 166 while (*cur) { 183 167 if ((*cur)->obj == obj) { 184 168 lmdb_txn_ref_t *next = (*cur)->next; 169 + js_clear_native((*cur)->obj, LMDB_TXN_NATIVE_TAG); 185 170 free(*cur); 186 171 *cur = next; 187 172 return; ··· 195 180 while (*cur) { 196 181 if ((*cur)->db && (*cur)->db->env == env) { 197 182 lmdb_db_ref_t *next = (*cur)->next; 183 + js_clear_native((*cur)->obj, LMDB_DB_NATIVE_TAG); 198 184 free(*cur); 199 185 *cur = next; 200 186 continue; ··· 208 194 while (*cur) { 209 195 if ((*cur)->txn && (*cur)->txn->env == env) { 210 196 lmdb_txn_ref_t *next = (*cur)->next; 197 + js_clear_native((*cur)->obj, LMDB_TXN_NATIVE_TAG); 211 198 free(*cur); 212 199 *cur = next; 213 200 continue; ··· 249 236 } 250 237 251 238 static lmdb_env_handle_t *get_env_handle(ant_t *js, ant_value_t obj, bool open_required) { 252 - lmdb_env_handle_t *env = find_env_by_obj(obj); 239 + lmdb_env_handle_t *env = (lmdb_env_handle_t *)js_get_native(obj, LMDB_ENV_NATIVE_TAG); 253 240 if (!env) return NULL; 254 241 if (open_required && env->closed) return NULL; 255 242 return env; 256 243 } 257 244 258 245 static lmdb_db_handle_t *get_db_handle(ant_t *js, ant_value_t obj, bool open_required) { 259 - lmdb_db_handle_t *db = find_db_by_obj(obj); 246 + lmdb_db_handle_t *db = (lmdb_db_handle_t *)js_get_native(obj, LMDB_DB_NATIVE_TAG); 260 247 if (!db) return NULL; 261 248 if (open_required && (db->closed || !db->env || db->env->closed)) return NULL; 262 249 return db; 263 250 } 264 251 265 252 static lmdb_txn_handle_t *get_txn_handle(ant_t *js, ant_value_t obj, bool open_required) { 266 - lmdb_txn_handle_t *txn = find_txn_by_obj(obj); 253 + lmdb_txn_handle_t *txn = (lmdb_txn_handle_t *)js_get_native(obj, LMDB_TXN_NATIVE_TAG); 267 254 if (!txn) return NULL; 268 - if (open_required && (txn->closed || !txn->txn)) return NULL; 255 + if (open_required && (txn->closed || !txn->txn || !txn->env || txn->env->closed)) return NULL; 269 256 return txn; 270 257 } 271 258 259 + static void lmdb_env_finalize(ant_t *js, ant_object_t *obj) { 260 + ant_value_t value = js_obj_from_ptr(obj); 261 + lmdb_env_handle_t *env = 262 + (lmdb_env_handle_t *)js_get_native(value, LMDB_ENV_NATIVE_TAG); 263 + if (!env) return; 264 + env_handle_close(env); 265 + unregister_env_ref_by_obj(value); 266 + js_clear_native(value, LMDB_ENV_NATIVE_TAG); 267 + } 268 + 269 + static void lmdb_db_finalize(ant_t *js, ant_object_t *obj) { 270 + ant_value_t value = js_obj_from_ptr(obj); 271 + lmdb_db_handle_t *db = (lmdb_db_handle_t *)js_get_native(value, LMDB_DB_NATIVE_TAG); 272 + 273 + if (!db) return; 274 + if (!db->closed && db->env && !db->env->closed) { 275 + mdb_dbi_close(db->env->env, db->dbi); 276 + list_remove_db(db->env, db); 277 + } 278 + 279 + db->closed = true; 280 + unregister_db_ref_by_obj(value); 281 + js_clear_native(value, LMDB_DB_NATIVE_TAG); 282 + } 283 + 284 + static void lmdb_txn_finalize(ant_t *js, ant_object_t *obj) { 285 + ant_value_t value = js_obj_from_ptr(obj); 286 + lmdb_txn_handle_t *txn = (lmdb_txn_handle_t *)js_get_native(value, LMDB_TXN_NATIVE_TAG); 287 + 288 + (void)js; 289 + if (!txn) return; 290 + if (!txn->closed && txn->txn) { 291 + mdb_txn_abort(txn->txn); 292 + txn->txn = NULL; 293 + } 294 + txn->closed = true; 295 + if (txn->env) list_remove_txn(txn->env, txn); 296 + unregister_txn_ref_by_obj(value); 297 + js_clear_native(value, LMDB_TXN_NATIVE_TAG); 298 + } 299 + 272 300 static bool option_bool(ant_t *js, ant_value_t options, const char *key, bool fallback) { 273 301 if (vtype(options) != T_OBJ) return fallback; 274 302 ant_value_t val = js_get(js, options, key); ··· 516 544 db->next_global = db_handles; 517 545 db_handles = db; 518 546 519 - return make_db_obj(js, db); 547 + return make_db_obj(js, db, js_getthis(js)); 520 548 } 521 549 522 550 static ant_value_t lmdb_env_begin_txn(ant_t *js, ant_value_t *args, int nargs) { ··· 550 578 handle->next_global = txn_handles; 551 579 txn_handles = handle; 552 580 553 - return make_txn_obj(js, handle); 581 + return make_txn_obj(js, handle, js_getthis(js)); 554 582 } 555 583 556 584 static ant_value_t lmdb_env_close_method(ant_t *js, ant_value_t *args, int nargs) { ··· 1041 1069 ensure_lmdb_prototypes(js); 1042 1070 ant_value_t obj = js_mkobj(js); 1043 1071 js_set_native(obj, env, LMDB_ENV_NATIVE_TAG); 1072 + js_set_finalizer(obj, lmdb_env_finalize); 1044 1073 register_env_ref(obj, env); 1045 1074 if (is_special_object(lmdb_types.env_proto)) js_set_proto_init(obj, lmdb_types.env_proto); 1046 1075 return obj; 1047 1076 } 1048 1077 1049 - static ant_value_t make_db_obj(ant_t *js, lmdb_db_handle_t *db) { 1078 + static ant_value_t make_db_obj(ant_t *js, lmdb_db_handle_t *db, ant_value_t env_obj) { 1050 1079 ensure_lmdb_prototypes(js); 1051 1080 ant_value_t obj = js_mkobj(js); 1052 1081 js_set_native(obj, db, LMDB_DB_NATIVE_TAG); 1082 + js_set_finalizer(obj, lmdb_db_finalize); 1083 + js_set_slot_wb(js, obj, SLOT_DATA, env_obj); 1053 1084 register_db_ref(obj, db); 1054 1085 if (is_special_object(lmdb_types.db_proto)) js_set_proto_init(obj, lmdb_types.db_proto); 1055 1086 return obj; 1056 1087 } 1057 1088 1058 - static ant_value_t make_txn_obj(ant_t *js, lmdb_txn_handle_t *txn) { 1089 + static ant_value_t make_txn_obj(ant_t *js, lmdb_txn_handle_t *txn, ant_value_t env_obj) { 1059 1090 ensure_lmdb_prototypes(js); 1060 1091 ant_value_t obj = js_mkobj(js); 1061 1092 js_set_native(obj, txn, LMDB_TXN_NATIVE_TAG); 1093 + js_set_finalizer(obj, lmdb_txn_finalize); 1094 + js_set_slot_wb(js, obj, SLOT_DATA, env_obj); 1062 1095 register_txn_ref(obj, txn); 1063 1096 if (is_special_object(lmdb_types.txn_proto)) js_set_proto_init(obj, lmdb_types.txn_proto); 1064 1097 return obj; ··· 1110 1143 mark(js, lmdb_types.db_proto); 1111 1144 mark(js, lmdb_types.txn_proto); 1112 1145 } 1113 - for (lmdb_env_ref_t *ref = env_refs; ref; ref = ref->next) mark(js, ref->obj); 1114 - for (lmdb_db_ref_t *ref = db_refs; ref; ref = ref->next) mark(js, ref->obj); 1115 - for (lmdb_txn_ref_t *ref = txn_refs; ref; ref = ref->next) mark(js, ref->obj); 1116 1146 } 1117 1147 1118 1148 void cleanup_lmdb_module(void) { ··· 1169 1199 1170 1200 while (env_refs) { 1171 1201 lmdb_env_ref_t *next = env_refs->next; 1202 + js_clear_native(env_refs->obj, LMDB_ENV_NATIVE_TAG); 1172 1203 free(env_refs); 1173 1204 env_refs = next; 1174 1205 } 1175 1206 1176 1207 while (db_refs) { 1177 1208 lmdb_db_ref_t *next = db_refs->next; 1209 + js_clear_native(db_refs->obj, LMDB_DB_NATIVE_TAG); 1178 1210 free(db_refs); 1179 1211 db_refs = next; 1180 1212 } 1181 1213 1182 1214 while (txn_refs) { 1183 1215 lmdb_txn_ref_t *next = txn_refs->next; 1216 + js_clear_native(txn_refs->obj, LMDB_TXN_NATIVE_TAG); 1184 1217 free(txn_refs); 1185 1218 txn_refs = next; 1186 1219 }
+23 -5
src/modules/napi.c
··· 48 48 #include "modules/buffer.h" 49 49 #include "modules/date.h" 50 50 #include "modules/napi.h" 51 + #include "gc/objects.h" 51 52 #include "gc/roots.h" 52 53 #include "gc/modules.h" 53 54 #include "utf8.h" ··· 315 316 if (nenv->has_pending_exception) 316 317 mark(js, (ant_value_t)nenv->pending_exception); 317 318 318 - for (struct napi_ref__ *r = nenv->refs; r; r = r->next) { 319 + for (struct napi_ref__ *r = nenv->refs; r; r = r->next) 319 320 if (r->refcount > 0) mark(js, r->ref_val); 320 - mark(js, (ant_value_t)r->value); 321 - } 322 321 323 322 for (struct napi_deferred__ *d = nenv->deferreds; d; d = d->next) 324 323 if (!d->settled) mark(js, d->promise_val); 325 324 326 325 for (struct napi_threadsafe_function__ *t = nenv->tsfns; t; t = t->next) mark(js, t->func_val); 327 326 for (size_t i = 0; i < nenv->handle_slots_len; i++) mark(js, nenv->handle_slots[i]); 327 + } 328 + 329 + void gc_clear_napi_weak_refs(ant_t *js, bool minor) { 330 + if (!g_napi_env || g_napi_env->js != js) return; 331 + ant_napi_env_t *nenv = g_napi_env; 332 + 333 + for (struct napi_ref__ *r = nenv->refs; r; r = r->next) { 334 + if (r->refcount > 0 || !r->value) continue; 335 + ant_value_t value = (ant_value_t)r->value; 336 + ant_object_t *obj = is_object_type(value) ? js_obj_ptr(value) : NULL; 337 + if (obj && (!minor || obj->generation == 0) && !gc_obj_is_marked(obj)) r->value = 0; 338 + } 328 339 } 329 340 330 341 static inline napi_value napi_scope_pin(ant_napi_env_t *nenv, napi_value val) { ··· 1535 1546 ) { 1536 1547 ant_napi_env_t *nenv = (ant_napi_env_t *)env; 1537 1548 struct napi_ref__ *r = (struct napi_ref__ *)ref; 1538 - if (!nenv || !nenv->js || !r) return napi_set_last(env, napi_invalid_arg, "invalid argument"); 1549 + 1550 + if (!nenv || !nenv->js || !r) 1551 + return napi_set_last(env, napi_invalid_arg, "invalid argument"); 1552 + 1553 + if (!r->value) { 1554 + if (result) *result = 0; 1555 + return napi_set_last(env, napi_ok, NULL); 1556 + } 1539 1557 1540 1558 if (r->refcount == 0) r->ref_val = (ant_value_t)r->value; 1541 1559 r->refcount++; ··· 1571 1589 if (!nenv || !nenv->js || !r || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); 1572 1590 1573 1591 if (r->refcount > 0) *result = NAPI_RETURN(nenv, r->ref_val); 1574 - else *result = r->value; 1592 + else *result = r->value ? NAPI_RETURN(nenv, r->value) : 0; 1575 1593 1576 1594 return napi_set_last(env, napi_ok, NULL); 1577 1595 }
+1 -2
src/modules/tls.c
··· 92 92 static ant_value_t js_tls_context_close(ant_t *js, ant_value_t *args, int nargs) { 93 93 ant_tls_context_wrap_t *wrap = tls_context_data(js_getthis(js)); 94 94 if (!wrap) return js_getthis(js); 95 - 96 95 tls_context_free(wrap); 97 - js_set_native(wrap->obj, NULL, 0); 96 + js_clear_native(wrap->obj, TLS_CONTEXT_NATIVE_TAG); 98 97 return js_getthis(js); 99 98 } 100 99