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 temp code parse arena with rewinding

+177 -37
+8
include/runtime.h
··· 32 32 void code_arena_rewind(code_arena_mark_t mark); 33 33 34 34 void code_arena_reset(void); 35 + size_t parse_arena_get_memory(void); 36 + 37 + code_arena_mark_t parse_arena_mark(void); 38 + void parse_arena_rewind(code_arena_mark_t mark); 39 + 40 + void parse_arena_reset(void); 41 + void *parse_arena_bump(size_t size); 42 + 35 43 void destroy_runtime(ant_t *js); 36 44 void *code_arena_bump(size_t size); 37 45
+4
src/ant.c
··· 15702 15702 15703 15703 static ant_value_t js_eval_bytecode_mode(ant_t *js, const char *buf, size_t len, sv_compile_mode_t mode, bool parse_strict) { 15704 15704 if (len == (size_t)~0U) len = strlen(buf); 15705 + 15706 + code_arena_mark_t parse_mark = parse_arena_mark(); 15705 15707 sv_ast_t *program = sv_parse(js, buf, (ant_offset_t)len, parse_strict); 15706 15708 15707 15709 if (!program) { 15710 + parse_arena_rewind(parse_mark); 15708 15711 if (js->thrown_exists) return mkval(T_ERR, 0); 15709 15712 return js_mkerr_typed(js, JS_ERR_INTERNAL | JS_ERR_NO_STACK, "Unexpected parse error"); 15710 15713 } ··· 15715 15718 } 15716 15719 15717 15720 sv_func_t *func = sv_compile(js, program, mode, buf, (ant_offset_t)len); 15721 + parse_arena_rewind(parse_mark); 15718 15722 if (!func) { 15719 15723 if (js->thrown_exists) return mkval(T_ERR, 0); 15720 15724 return js_mkerr_typed(js, JS_ERR_INTERNAL | JS_ERR_NO_STACK, "Unexpected compile error");
+28 -1
src/modules/abort.c
··· 61 61 return get_signal_data(obj); 62 62 } 63 63 64 + static void abort_signal_data_free(abort_signal_data_t *data) { 65 + if (!data) return; 66 + if (data->listeners) utarray_free(data->listeners); 67 + if (data->followers) utarray_free(data->followers); 68 + free(data); 69 + } 70 + 71 + static void abort_signal_finalize(ant_t *js, ant_object_t *obj) { 72 + ant_value_t value = js_obj_from_ptr(obj); 73 + abort_signal_data_t *data = get_signal_data(value); 74 + js_clear_native(value, ABORT_SIGNAL_NATIVE_TAG); 75 + abort_signal_data_free(data); 76 + } 77 + 64 78 static ant_value_t make_abort_error(ant_t *js) { 65 79 return make_dom_exception(js, "signal is aborted without reason", "AbortError"); 66 80 } ··· 188 202 189 203 ant_value_t obj = js_mkobj(js); 190 204 js_set_native(obj, data, ABORT_SIGNAL_NATIVE_TAG); 205 + js_set_finalizer(obj, abort_signal_finalize); 191 206 js_set_slot(obj, SLOT_BRAND, js_mknum(BRAND_ABORT_SIGNAL)); 192 207 if (g_initialized) js_set_slot_wb(js, obj, SLOT_PROTO, g_signal_proto); 193 208 ··· 331 346 332 347 static void abort_timeout_close_cb(uv_handle_t *h) { 333 348 abort_timeout_entry_t *entry = (abort_timeout_entry_t *)h->data; 334 - if (entry) entry->closed = 1; 349 + if (!entry) return; 350 + 351 + abort_timeout_entry_t **it = &timeout_entries; 352 + while (*it) { 353 + if (*it == entry) { 354 + *it = entry->next; 355 + break; 356 + } 357 + it = &(*it)->next; 358 + } 359 + 360 + entry->closed = 1; 361 + free(entry); 335 362 } 336 363 337 364 static void abort_timeout_fire_cb(uv_timer_t *handle) {
+3 -1
src/modules/builtin.c
··· 289 289 290 290 size_t buffer_mem = buffer_get_external_memory(); 291 291 size_t code_mem = code_arena_get_memory(); 292 - size_t external_total = buffer_mem + code_mem; 292 + size_t parse_mem = parse_arena_get_memory(); 293 + size_t external_total = buffer_mem + code_mem + parse_mem; 293 294 294 295 ant_value_t ext = js_newobj(js); 295 296 js_set(js, ext, "buffers", js_mknum((double)buffer_mem)); 296 297 js_set(js, ext, "code", js_mknum((double)code_mem)); 298 + js_set(js, ext, "parse", js_mknum((double)parse_mem)); 297 299 js_set(js, ext, "total", js_mknum((double)external_total)); 298 300 js_set(js, result, "external", ext); 299 301
+2 -2
src/repl.c
··· 231 231 ) { 232 232 if (!js || !reg || !code || len == 0) return true; 233 233 234 - code_arena_mark_t mark = code_arena_mark(); 234 + code_arena_mark_t mark = parse_arena_mark(); 235 235 repl_decl_pending_t pending = {0}; 236 236 bool ok = true; 237 237 ··· 268 268 } 269 269 270 270 done: 271 - code_arena_rewind(mark); 271 + parse_arena_rewind(mark); 272 272 repl_decl_pending_free(&pending); 273 273 274 274 if (ok && js->thrown_exists)
+95 -22
src/runtime.c
··· 31 31 32 32 static struct ant_runtime runtime = {0}; 33 33 struct ant_runtime *const rt = &runtime; 34 - 35 - static code_block_t *code_arena_head = NULL; 36 - static code_block_t *code_arena_current = NULL; 37 34 static intern_entry_t *code_interns = NULL; 35 + 36 + static code_block_t *code_arena_head = NULL; 37 + static code_block_t *code_arena_current = NULL; 38 + static code_block_t *parse_arena_head = NULL; 39 + static code_block_t *parse_arena_current = NULL; 38 40 39 41 static void code_interns_prune_for_block_range( 40 42 const code_block_t *block, ··· 74 76 return block; 75 77 } 76 78 79 + static void *arena_bump( 80 + code_block_t **head, 81 + code_block_t **current, 82 + size_t size 83 + ) { 84 + size = (size + 7) & ~(size_t)7; 85 + if (!*current || (*current)->used + size > (*current)->capacity) { 86 + code_block_t *new_block = code_arena_new_block(size); 87 + if (!new_block) return NULL; 88 + if (!*head) *head = new_block; 89 + else if (*current) (*current)->next = new_block; 90 + *current = new_block; 91 + } 92 + 93 + void *ptr = &(*current)->data[(*current)->used]; 94 + (*current)->used += size; 95 + return ptr; 96 + } 97 + 98 + static size_t arena_get_memory(code_block_t *head) { 99 + size_t total = 0; 100 + for (code_block_t *b = head; b; b = b->next) 101 + total += sizeof(code_block_t) + b->capacity; 102 + return total; 103 + } 104 + 105 + static code_arena_mark_t arena_mark(code_block_t *current) { 106 + code_arena_mark_t mark = {0}; 107 + mark.block = current; 108 + mark.used = current ? current->used : 0; 109 + return mark; 110 + } 111 + 112 + static void arena_rewind_plain( 113 + code_block_t **head, 114 + code_block_t **current, 115 + code_arena_mark_t mark 116 + ) { 117 + code_block_t *target = (code_block_t *)mark.block; 118 + 119 + if (!target) { 120 + code_block_t *block = *head; 121 + while (block) { 122 + code_block_t *next = block->next; 123 + free(block); 124 + block = next; 125 + } 126 + *head = NULL; 127 + *current = NULL; 128 + return; 129 + } 130 + 131 + size_t clamped_used = mark.used <= target->capacity ? mark.used : target->capacity; 132 + target->used = clamped_used; 133 + 134 + code_block_t *b = target->next; 135 + while (b) { 136 + code_block_t *next = b->next; 137 + free(b); 138 + b = next; 139 + } 140 + 141 + target->next = NULL; 142 + *current = target; 143 + } 144 + 77 145 const char *code_arena_alloc(const char *code, size_t len) { 78 146 if (!code || len == 0) return NULL; 79 147 ··· 106 174 } 107 175 108 176 void *code_arena_bump(size_t size) { 109 - size = (size + 7) & ~(size_t)7; 110 - if (!code_arena_current || code_arena_current->used + size > code_arena_current->capacity) { 111 - code_block_t *new_block = code_arena_new_block(size); 112 - if (!new_block) return NULL; 113 - if (!code_arena_head) code_arena_head = new_block; 114 - else if (code_arena_current) code_arena_current->next = new_block; 115 - code_arena_current = new_block; 116 - } 117 - void *ptr = &code_arena_current->data[code_arena_current->used]; 118 - code_arena_current->used += size; 119 - return ptr; 177 + return arena_bump(&code_arena_head, &code_arena_current, size); 120 178 } 121 179 122 180 size_t code_arena_get_memory(void) { 123 - size_t total = 0; 124 - for (code_block_t *b = code_arena_head; b; b = b->next) 125 - total += sizeof(code_block_t) + b->capacity; 126 - return total; 181 + return arena_get_memory(code_arena_head); 127 182 } 128 183 129 184 code_arena_mark_t code_arena_mark(void) { 130 - code_arena_mark_t mark = {0}; 131 - mark.block = code_arena_current; 132 - mark.used = code_arena_current ? code_arena_current->used : 0; 133 - return mark; 185 + return arena_mark(code_arena_current); 134 186 } 135 187 136 188 void code_arena_rewind(code_arena_mark_t mark) { ··· 167 219 code_arena_current = target; 168 220 } 169 221 222 + void *parse_arena_bump(size_t size) { 223 + return arena_bump(&parse_arena_head, &parse_arena_current, size); 224 + } 225 + 226 + size_t parse_arena_get_memory(void) { 227 + return arena_get_memory(parse_arena_head); 228 + } 229 + 230 + code_arena_mark_t parse_arena_mark(void) { 231 + return arena_mark(parse_arena_current); 232 + } 233 + 234 + void parse_arena_rewind(code_arena_mark_t mark) { 235 + arena_rewind_plain(&parse_arena_head, &parse_arena_current, mark); 236 + } 237 + 238 + void parse_arena_reset(void) { 239 + parse_arena_rewind((code_arena_mark_t){0}); 240 + } 241 + 170 242 void code_arena_reset(void) { 171 243 intern_entry_t *entry, *tmp; 172 244 HASH_ITER(hh, code_interns, entry, tmp) { ··· 184 256 185 257 code_arena_head = NULL; 186 258 code_arena_current = NULL; 259 + parse_arena_reset(); 187 260 } 188 261 189 262 void destroy_runtime(ant_t *js) {
+4 -4
src/silver/ast.c
··· 14 14 #include <string.h> 15 15 16 16 sv_ast_t *sv_ast_new(sv_node_type_t type) { 17 - sv_ast_t *n = code_arena_bump(sizeof(sv_ast_t)); 17 + sv_ast_t *n = parse_arena_bump(sizeof(sv_ast_t)); 18 18 if (!n) return NULL; 19 19 memset(n, 0, sizeof(sv_ast_t)); 20 20 n->type = type; ··· 24 24 void sv_ast_list_push(sv_ast_list_t *list, sv_ast_t *node) { 25 25 if (list->count >= list->cap) { 26 26 int new_cap = list->cap ? list->cap * 2 : 4; 27 - sv_ast_t **new_items = code_arena_bump((size_t)new_cap * sizeof(sv_ast_t *)); 27 + sv_ast_t **new_items = parse_arena_bump((size_t)new_cap * sizeof(sv_ast_t *)); 28 28 if (!new_items) return; 29 29 if (list->items) 30 30 memcpy(new_items, list->items, (size_t)list->count * sizeof(sv_ast_t *)); ··· 167 167 return src; 168 168 } 169 169 170 - char *dst = code_arena_bump((size_t)len + 1); 170 + char *dst = parse_arena_bump((size_t)len + 1); 171 171 if (!dst) { 172 172 if (out_len) *out_len = len; 173 173 return src; ··· 371 371 return outv; 372 372 } 373 373 374 - uint8_t *out = code_arena_bump(raw_len); 374 + uint8_t *out = parse_arena_bump(raw_len); 375 375 if (!out) { 376 376 (void)SV_MKERR(JS, "oom"); 377 377 outv.ok = false;
+32 -6
src/silver/compiler.c
··· 5579 5579 wrapped[wrapped_len] = '\0'; 5580 5580 5581 5581 bool parse_strict = sv_vm_is_strict(js->vm); 5582 + code_arena_mark_t parse_mark = parse_arena_mark(); 5582 5583 sv_ast_t *program = sv_parse(js, wrapped, (ant_offset_t)wrapped_len, parse_strict); 5583 - if (!program) { free(wrapped); return NULL; } 5584 + 5585 + if (!program) { 5586 + parse_arena_rewind(parse_mark); 5587 + free(wrapped); 5588 + return NULL; 5589 + } 5584 5590 5585 5591 sv_ast_t *func_node = NULL; 5586 5592 if (program->args.count > 0) { ··· 5589 5595 else if (stmt && stmt->left && stmt->left->type == N_FUNC) func_node = stmt->left; 5590 5596 } 5591 5597 5592 - if (!func_node) { free(wrapped); return NULL; } 5598 + if (!func_node) { 5599 + parse_arena_rewind(parse_mark); 5600 + free(wrapped); 5601 + return NULL; 5602 + } 5593 5603 5594 5604 sv_compiler_t root; 5595 5605 sv_compile_ctx_init_root( ··· 5601 5611 5602 5612 root.line_table = sv_compile_ctx_build_line_table(root.source, (ant_offset_t)wrapped_len); 5603 5613 sv_func_t *func = compile_function_body(&root, func_node, SV_COMPILE_SCRIPT); 5614 + 5604 5615 sv_compile_ctx_free_line_table(root.line_table); 5616 + parse_arena_rewind(parse_mark); 5605 5617 free(wrapped); 5606 5618 5607 5619 if (sv_compile_trace_unlikely) fprintf( ··· 5632 5644 } 5633 5645 5634 5646 bool parse_strict = sv_vm_is_strict(js->vm); 5647 + code_arena_mark_t parse_mark = parse_arena_mark(); 5635 5648 sv_ast_t *program = sv_parse(js, body, (ant_offset_t)body_len, parse_strict); 5636 - if (!program) return NULL; 5649 + 5650 + if (!program) { 5651 + parse_arena_rewind(parse_mark); 5652 + return NULL; 5653 + } 5637 5654 5638 5655 static const char *k_top_name_function = "<function>"; 5639 5656 static const char *k_top_name_async_function = "<async function>"; ··· 5658 5675 } 5659 5676 5660 5677 sv_ast_t *ident = sv_ast_new(N_IDENT); 5661 - if (!ident) return NULL; 5678 + if (!ident) { 5679 + parse_arena_rewind(parse_mark); 5680 + return NULL; 5681 + } 5662 5682 5663 5683 ident->str = name; 5664 5684 ident->len = (uint32_t)name_len; ··· 5668 5688 } 5669 5689 5670 5690 top_fn.body = sv_ast_new(N_BLOCK); 5671 - if (!top_fn.body) return NULL; 5691 + if (!top_fn.body) { 5692 + parse_arena_rewind(parse_mark); 5693 + return NULL; 5694 + } 5695 + 5672 5696 top_fn.body->args = program->args; 5673 - 5674 5697 sv_compiler_t root; 5698 + 5675 5699 sv_compile_ctx_init_root( 5676 5700 &root, js, js->filename, 5677 5701 pin_source_text(body, (ant_offset_t)body_len), ··· 5681 5705 5682 5706 root.line_table = sv_compile_ctx_build_line_table(root.source, (ant_offset_t)body_len); 5683 5707 sv_func_t *func = compile_function_body(&root, &top_fn, SV_COMPILE_SCRIPT); 5708 + 5684 5709 sv_compile_ctx_free_line_table(root.line_table); 5710 + parse_arena_rewind(parse_mark); 5685 5711 5686 5712 if (sv_compile_trace_unlikely) fprintf( 5687 5713 stderr, "[compile] end kind=function-with-params thrown=%d func=%p\n",
+1 -1
src/silver/lexer.c
··· 74 74 outv.ok = true; 75 75 return outv; 76 76 } 77 - uint8_t *out = code_arena_bump(cap); 77 + uint8_t *out = parse_arena_bump(cap); 78 78 if (!out) { 79 79 (void)js_mkerr(js, "oom"); 80 80 return outv;