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.

make jit capture lazy

+78 -56
+1
src/silver/glue.c
··· 280 280 281 281 while (*pp) { 282 282 sv_upvalue_t *uv = *pp; 283 + if (uv->location < lo) break; 283 284 if (uv->location >= lo && uv->location < hi) { 284 285 uv->closed = *uv->location; 285 286 uv->location = &uv->closed;
+77 -56
src/silver/swarm.c
··· 321 321 static void mir_emit_fill_param_slots_from_args( 322 322 MIR_context_t ctx, MIR_item_t fn, 323 323 MIR_reg_t r_slotbuf, MIR_reg_t r_args, MIR_reg_t r_argc, 324 - int param_count 324 + bool *captured_params, int param_count 325 325 ) { 326 + if (!captured_params) return; 326 327 for (int i = 0; i < param_count; i++) { 328 + if (!captured_params[i]) continue; 327 329 MIR_label_t arg_present = MIR_new_label(ctx); 328 330 MIR_label_t arg_done = MIR_new_label(ctx); 329 331 MIR_append_insn(ctx, fn, ··· 350 352 } 351 353 } 352 354 353 - static void mir_emit_close_captured_slots( 355 + static void mir_emit_spill_child_captured_locals( 356 + MIR_context_t ctx, MIR_item_t fn, 357 + sv_func_t *parent_func, sv_func_t *child, 358 + MIR_reg_t *local_regs, int n_locals, MIR_reg_t r_lbuf 359 + ) { 360 + if (!child || !parent_func || !local_regs || n_locals <= 0 || !r_lbuf) return; 361 + 362 + for (int i = 0; i < child->upvalue_count; i++) { 363 + sv_upval_desc_t *desc = &child->upval_descs[i]; 364 + if (!desc->is_local) continue; 365 + 366 + int li = (int)desc->index - parent_func->param_count; 367 + if (li < 0 || li >= n_locals) continue; 368 + 369 + MIR_append_insn(ctx, fn, 370 + MIR_new_insn(ctx, MIR_MOV, 371 + MIR_new_mem_op(ctx, MIR_T_I64, 372 + (MIR_disp_t)(li * (int)sizeof(ant_value_t)), r_lbuf, 0, 1), 373 + MIR_new_reg_op(ctx, local_regs[li]))); 374 + } 375 + } 376 + 377 + static void mir_emit_close_marked_slots( 354 378 MIR_context_t ctx, MIR_item_t fn, 355 379 MIR_item_t close_upval_proto, MIR_item_t imp_close_upval, 356 380 MIR_reg_t r_vm, MIR_reg_t r_slots, 357 - int slot_count 381 + bool *captured, int start_idx, int slot_count 358 382 ) { 359 - if (slot_count <= 0) return; 360 - MIR_append_insn(ctx, fn, 361 - MIR_new_call_insn(ctx, 6, 362 - MIR_new_ref_op(ctx, close_upval_proto), 363 - MIR_new_ref_op(ctx, imp_close_upval), 364 - MIR_new_reg_op(ctx, r_vm), 365 - MIR_new_uint_op(ctx, 0), 366 - MIR_new_reg_op(ctx, r_slots), 367 - MIR_new_int_op(ctx, slot_count))); 383 + if (!captured || start_idx >= slot_count || slot_count <= 0 || !r_slots) return; 384 + if (start_idx < 0) start_idx = 0; 385 + 386 + for (int i = start_idx; i < slot_count; i++) { 387 + if (!captured[i]) continue; 388 + MIR_append_insn(ctx, fn, 389 + MIR_new_call_insn(ctx, 6, 390 + MIR_new_ref_op(ctx, close_upval_proto), 391 + MIR_new_ref_op(ctx, imp_close_upval), 392 + MIR_new_reg_op(ctx, r_vm), 393 + MIR_new_uint_op(ctx, (uint64_t)i), 394 + MIR_new_reg_op(ctx, r_slots), 395 + MIR_new_int_op(ctx, i + 1))); 396 + } 368 397 } 369 398 370 399 static inline void mir_emit_self_tail( ··· 373 402 MIR_reg_t r_tco_args, MIR_reg_t r_arg_arr, 374 403 MIR_reg_t r_args, MIR_reg_t r_argc, 375 404 MIR_reg_t *local_regs, int n_locals, 376 - bool has_captured_slots, MIR_reg_t r_slotbuf, 405 + bool has_captured_slots, MIR_reg_t r_slotbuf, bool *captured_params, 377 406 bool has_captures, bool *captured_locals, 378 407 MIR_reg_t r_lbuf, MIR_label_t entry 379 408 ) { ··· 393 422 MIR_new_reg_op(ctx, r_argc), 394 423 MIR_new_int_op(ctx, (int64_t)call_argc))); 395 424 if (has_captured_slots) 396 - mir_emit_fill_param_slots_from_args(ctx, fn, r_slotbuf, r_tco_args, r_argc, param_count); 425 + mir_emit_fill_param_slots_from_args(ctx, fn, r_slotbuf, r_tco_args, r_argc, captured_params, param_count); 397 426 for (int i = 0; i < n_locals; i++) 398 427 mir_load_imm(ctx, fn, local_regs[i], mkval(T_UNDEF, 0)); 399 428 if (has_captures) { ··· 2369 2398 if (captured_locals[i]) { has_captures = true; break; } 2370 2399 } 2371 2400 bool has_captured_slots = has_captured_params; 2372 - int captured_slot_count = param_count + n_locals; 2401 + bool use_unified_slotbuf = has_captured_slots && has_captures; 2402 + int slotbuf_count = use_unified_slotbuf ? (param_count + n_locals) : param_count; 2373 2403 2374 2404 if (has_captured_params && needs_bailout) { 2375 2405 free(vs.regs); free(vs.known_func); free(vs.d_regs); free(vs.slot_type); ··· 2380 2410 } 2381 2411 2382 2412 MIR_reg_t r_slotbuf = MIR_new_func_reg(ctx, jit_func->u.func, MIR_T_I64, "slotbuf"); 2383 - if (has_captured_slots && captured_slot_count > 0) { 2413 + if (has_captured_slots && slotbuf_count > 0) { 2384 2414 MIR_append_insn(ctx, jit_func, 2385 2415 MIR_new_insn(ctx, MIR_ALLOCA, 2386 2416 MIR_new_reg_op(ctx, r_slotbuf), 2387 - MIR_new_uint_op(ctx, (uint64_t)captured_slot_count * sizeof(ant_value_t)))); 2388 - mir_emit_fill_param_slots_from_args(ctx, jit_func, r_slotbuf, r_args, r_argc, param_count); 2389 - for (int i = 0; i < n_locals; i++) 2390 - MIR_append_insn(ctx, jit_func, 2391 - MIR_new_insn(ctx, MIR_MOV, 2392 - MIR_new_mem_op(ctx, MIR_T_I64, 2393 - (MIR_disp_t)((param_count + i) * (int)sizeof(ant_value_t)), r_slotbuf, 0, 1), 2394 - MIR_new_uint_op(ctx, mkval(T_UNDEF, 0)))); 2417 + MIR_new_uint_op(ctx, (uint64_t)slotbuf_count * sizeof(ant_value_t)))); 2418 + mir_emit_fill_param_slots_from_args(ctx, jit_func, r_slotbuf, r_args, r_argc, captured_params, param_count); 2395 2419 } else mir_load_imm(ctx, jit_func, r_slotbuf, 0); 2396 2420 2397 - bool needs_lbuf = needs_bailout || feat.needs_close_upval || has_captures || has_captured_slots; 2421 + bool needs_lbuf = needs_bailout || feat.needs_close_upval || has_captures; 2398 2422 MIR_reg_t r_lbuf = MIR_new_func_reg(ctx, jit_func->u.func, MIR_T_I64, "lbuf"); 2399 - if (has_captured_slots && n_locals > 0) { 2423 + if (use_unified_slotbuf && n_locals > 0) { 2400 2424 MIR_append_insn(ctx, jit_func, 2401 2425 MIR_new_insn(ctx, MIR_ADD, 2402 2426 MIR_new_reg_op(ctx, r_lbuf), ··· 4502 4526 if (is_tail && jit_try_depth == 0) { 4503 4527 mir_emit_self_tail(ctx, jit_func, (int)call_argc, param_count, 4504 4528 r_tco_args, r_arg_arr, r_args, r_argc, 4505 - local_regs, n_locals, has_captured_slots, r_slotbuf, 4529 + local_regs, n_locals, has_captured_slots, r_slotbuf, captured_params, 4506 4530 has_captures, 4507 4531 captured_locals, r_lbuf, self_tail_entry); 4508 4532 break; ··· 4625 4649 if (is_tail && jit_try_depth == 0) { 4626 4650 mir_emit_self_tail(ctx, jit_func, (int)call_argc, param_count, 4627 4651 r_tco_args, r_arg_arr, r_args, r_argc, 4628 - local_regs, n_locals, has_captured_slots, r_slotbuf, 4652 + local_regs, n_locals, has_captured_slots, r_slotbuf, captured_params, 4629 4653 has_captures, 4630 4654 captured_locals, r_lbuf, self_tail_entry); 4631 4655 } else { ··· 4874 4898 4875 4899 case OP_CLOSE_UPVAL: { 4876 4900 uint16_t idx = sv_get_u16(ip + 1); 4877 - if (n_locals > 0 && r_lbuf) { 4901 + if (has_captures && n_locals > 0 && r_lbuf) { 4878 4902 for (int i = 0; i < n_locals; i++) 4903 + if (captured_locals[i]) 4879 4904 MIR_append_insn(ctx, jit_func, 4880 4905 MIR_new_insn(ctx, MIR_MOV, 4881 4906 MIR_new_mem_op(ctx, MIR_T_I64, 4882 4907 (MIR_disp_t)(i * (int)sizeof(ant_value_t)), r_lbuf, 0, 1), 4883 4908 MIR_new_reg_op(ctx, local_regs[i]))); 4884 4909 } 4885 - MIR_append_insn(ctx, jit_func, 4886 - MIR_new_call_insn(ctx, 6, 4887 - MIR_new_ref_op(ctx, close_upval_proto), 4888 - MIR_new_ref_op(ctx, imp_close_upval), 4889 - MIR_new_reg_op(ctx, r_vm), 4890 - MIR_new_uint_op(ctx, has_captured_slots ? (uint64_t)idx : (uint64_t)(idx >= (uint16_t)param_count ? idx - (uint16_t)param_count : 0)), 4891 - MIR_new_reg_op(ctx, has_captured_slots ? r_slotbuf : r_lbuf), 4892 - MIR_new_int_op(ctx, has_captured_slots ? captured_slot_count : n_locals))); 4910 + if (has_captured_slots && idx < (uint16_t)param_count) 4911 + mir_emit_close_marked_slots(ctx, jit_func, 4912 + close_upval_proto, imp_close_upval, 4913 + r_vm, r_slotbuf, captured_params, (int)idx, param_count); 4914 + if (has_captures) 4915 + mir_emit_close_marked_slots(ctx, jit_func, 4916 + close_upval_proto, imp_close_upval, 4917 + r_vm, r_lbuf, captured_locals, 4918 + idx >= (uint16_t)param_count ? (int)idx - param_count : 0, n_locals); 4893 4919 break; 4894 4920 } 4895 4921 ··· 4935 4961 vstack_ensure_boxed(&vs, vs.sp - 1, ctx, jit_func, r_d_slot); 4936 4962 MIR_reg_t ret_val = vstack_pop(&vs); 4937 4963 if (has_captured_slots) 4938 - mir_emit_close_captured_slots(ctx, jit_func, 4964 + mir_emit_close_marked_slots(ctx, jit_func, 4939 4965 close_upval_proto, imp_close_upval, 4940 - r_vm, r_slotbuf, captured_slot_count); 4941 - else if (has_captures) 4942 - mir_emit_close_captured_slots(ctx, jit_func, 4966 + r_vm, r_slotbuf, captured_params, 0, param_count); 4967 + if (has_captures) 4968 + mir_emit_close_marked_slots(ctx, jit_func, 4943 4969 close_upval_proto, imp_close_upval, 4944 - r_vm, r_lbuf, n_locals); 4970 + r_vm, r_lbuf, captured_locals, 0, n_locals); 4945 4971 MIR_append_insn(ctx, jit_func, 4946 4972 MIR_new_ret_insn(ctx, 1, MIR_new_reg_op(ctx, ret_val))); 4947 4973 break; ··· 4949 4975 4950 4976 case OP_RETURN_UNDEF: { 4951 4977 if (has_captured_slots) 4952 - mir_emit_close_captured_slots(ctx, jit_func, 4978 + mir_emit_close_marked_slots(ctx, jit_func, 4953 4979 close_upval_proto, imp_close_upval, 4954 - r_vm, r_slotbuf, captured_slot_count); 4955 - else if (has_captures) 4956 - mir_emit_close_captured_slots(ctx, jit_func, 4980 + r_vm, r_slotbuf, captured_params, 0, param_count); 4981 + if (has_captures) 4982 + mir_emit_close_marked_slots(ctx, jit_func, 4957 4983 close_upval_proto, imp_close_upval, 4958 - r_vm, r_lbuf, n_locals); 4984 + r_vm, r_lbuf, captured_locals, 0, n_locals); 4959 4985 MIR_append_insn(ctx, jit_func, 4960 4986 MIR_new_ret_insn(ctx, 1, 4961 4987 MIR_new_uint_op(ctx, mkval(T_UNDEF, 0)))); ··· 7082 7108 if (idx >= (uint32_t)func->const_count) { ok = false; break; } 7083 7109 MIR_reg_t dst = vstack_push(&vs); 7084 7110 ant_value_t cv = func->constants[idx]; 7111 + sv_func_t *child = (sv_func_t *)(uintptr_t)vdata(cv); 7085 7112 vs.known_func[vs.sp - 1] = (sv_func_t *)(uintptr_t)vdata(cv); 7086 - if (n_locals > 0) { 7087 - for (int i = 0; i < n_locals; i++) 7088 - MIR_append_insn(ctx, jit_func, 7089 - MIR_new_insn(ctx, MIR_MOV, 7090 - MIR_new_mem_op(ctx, MIR_T_I64, 7091 - (MIR_disp_t)(i * (int)sizeof(ant_value_t)), r_lbuf, 0, 1), 7092 - MIR_new_reg_op(ctx, local_regs[i]))); 7093 - } 7113 + mir_emit_spill_child_captured_locals( 7114 + ctx, jit_func, func, child, local_regs, n_locals, r_lbuf); 7094 7115 MIR_append_insn(ctx, jit_func, 7095 7116 MIR_new_call_insn(ctx, 11, 7096 7117 MIR_new_ref_op(ctx, closure_proto), ··· 7102 7123 MIR_new_reg_op(ctx, r_this), 7103 7124 MIR_new_reg_op(ctx, has_captured_slots ? r_slotbuf : r_lbuf), 7104 7125 MIR_new_int_op(ctx, has_captured_slots ? 0 : param_count), 7105 - MIR_new_int_op(ctx, has_captured_slots ? captured_slot_count : n_locals), 7126 + MIR_new_int_op(ctx, has_captured_slots ? slotbuf_count : n_locals), 7106 7127 MIR_new_uint_op(ctx, (uint64_t)idx))); 7107 7128 break; 7108 7129 }