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 swarm.c dry

+159 -70
+60 -70
src/silver/swarm.c
··· 318 318 MIR_new_uint_op(ctx, imm))); 319 319 } 320 320 321 + static void mir_emit_fill_param_slots_from_args( 322 + MIR_context_t ctx, MIR_item_t fn, 323 + MIR_reg_t r_slotbuf, MIR_reg_t r_args, MIR_reg_t r_argc, 324 + int param_count 325 + ) { 326 + for (int i = 0; i < param_count; i++) { 327 + MIR_label_t arg_present = MIR_new_label(ctx); 328 + MIR_label_t arg_done = MIR_new_label(ctx); 329 + MIR_append_insn(ctx, fn, 330 + MIR_new_insn(ctx, MIR_UBGT, 331 + MIR_new_label_op(ctx, arg_present), 332 + MIR_new_reg_op(ctx, r_argc), 333 + MIR_new_int_op(ctx, (int64_t)i))); 334 + MIR_append_insn(ctx, fn, 335 + MIR_new_insn(ctx, MIR_MOV, 336 + MIR_new_mem_op(ctx, MIR_T_I64, 337 + (MIR_disp_t)(i * (int)sizeof(ant_value_t)), r_slotbuf, 0, 1), 338 + MIR_new_uint_op(ctx, mkval(T_UNDEF, 0)))); 339 + MIR_append_insn(ctx, fn, 340 + MIR_new_insn(ctx, MIR_JMP, 341 + MIR_new_label_op(ctx, arg_done))); 342 + MIR_append_insn(ctx, fn, arg_present); 343 + MIR_append_insn(ctx, fn, 344 + MIR_new_insn(ctx, MIR_MOV, 345 + MIR_new_mem_op(ctx, MIR_T_I64, 346 + (MIR_disp_t)(i * (int)sizeof(ant_value_t)), r_slotbuf, 0, 1), 347 + MIR_new_mem_op(ctx, MIR_T_I64, 348 + (MIR_disp_t)(i * (int)sizeof(ant_value_t)), r_args, 0, 1))); 349 + MIR_append_insn(ctx, fn, arg_done); 350 + } 351 + } 352 + 353 + static void mir_emit_close_captured_slots( 354 + MIR_context_t ctx, MIR_item_t fn, 355 + MIR_item_t close_upval_proto, MIR_item_t imp_close_upval, 356 + MIR_reg_t r_vm, MIR_reg_t r_slotbuf, 357 + int captured_slot_count 358 + ) { 359 + if (captured_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_slotbuf), 367 + MIR_new_int_op(ctx, captured_slot_count))); 368 + } 369 + 321 370 static inline void mir_emit_self_tail( 322 371 MIR_context_t ctx, MIR_item_t fn, 323 372 int call_argc, int param_count, ··· 343 392 MIR_new_insn(ctx, MIR_MOV, 344 393 MIR_new_reg_op(ctx, r_argc), 345 394 MIR_new_int_op(ctx, (int64_t)call_argc))); 346 - if (has_captured_slots) { 347 - for (int i = 0; i < param_count; i++) { 348 - MIR_label_t arg_present = MIR_new_label(ctx); 349 - MIR_label_t arg_done = MIR_new_label(ctx); 350 - MIR_append_insn(ctx, fn, 351 - MIR_new_insn(ctx, MIR_UBGT, 352 - MIR_new_label_op(ctx, arg_present), 353 - MIR_new_reg_op(ctx, r_argc), 354 - MIR_new_int_op(ctx, (int64_t)i))); 355 - MIR_append_insn(ctx, fn, 356 - MIR_new_insn(ctx, MIR_MOV, 357 - MIR_new_mem_op(ctx, MIR_T_I64, 358 - (MIR_disp_t)(i * (int)sizeof(ant_value_t)), r_slotbuf, 0, 1), 359 - MIR_new_uint_op(ctx, mkval(T_UNDEF, 0)))); 360 - MIR_append_insn(ctx, fn, 361 - MIR_new_insn(ctx, MIR_JMP, 362 - MIR_new_label_op(ctx, arg_done))); 363 - MIR_append_insn(ctx, fn, arg_present); 364 - MIR_append_insn(ctx, fn, 365 - MIR_new_insn(ctx, MIR_MOV, 366 - MIR_new_mem_op(ctx, MIR_T_I64, 367 - (MIR_disp_t)(i * (int)sizeof(ant_value_t)), r_slotbuf, 0, 1), 368 - MIR_new_mem_op(ctx, MIR_T_I64, 369 - (MIR_disp_t)(i * (int)sizeof(ant_value_t)), r_tco_args, 0, 1))); 370 - MIR_append_insn(ctx, fn, arg_done); 371 - } 372 - } 395 + if (has_captured_slots) 396 + mir_emit_fill_param_slots_from_args(ctx, fn, r_slotbuf, r_tco_args, r_argc, param_count); 373 397 for (int i = 0; i < n_locals; i++) 374 398 mir_load_imm(ctx, fn, local_regs[i], mkval(T_UNDEF, 0)); 375 399 if (has_captures) { ··· 2360 2384 MIR_new_insn(ctx, MIR_ALLOCA, 2361 2385 MIR_new_reg_op(ctx, r_slotbuf), 2362 2386 MIR_new_uint_op(ctx, (uint64_t)captured_slot_count * sizeof(ant_value_t)))); 2363 - for (int i = 0; i < param_count; i++) { 2364 - MIR_label_t arg_present = MIR_new_label(ctx); 2365 - MIR_label_t arg_done = MIR_new_label(ctx); 2366 - MIR_append_insn(ctx, jit_func, 2367 - MIR_new_insn(ctx, MIR_UBGT, 2368 - MIR_new_label_op(ctx, arg_present), 2369 - MIR_new_reg_op(ctx, r_argc), 2370 - MIR_new_int_op(ctx, (int64_t)i))); 2371 - MIR_append_insn(ctx, jit_func, 2372 - MIR_new_insn(ctx, MIR_MOV, 2373 - MIR_new_mem_op(ctx, MIR_T_I64, 2374 - (MIR_disp_t)(i * (int)sizeof(ant_value_t)), r_slotbuf, 0, 1), 2375 - MIR_new_uint_op(ctx, mkval(T_UNDEF, 0)))); 2376 - MIR_append_insn(ctx, jit_func, 2377 - MIR_new_insn(ctx, MIR_JMP, 2378 - MIR_new_label_op(ctx, arg_done))); 2379 - MIR_append_insn(ctx, jit_func, arg_present); 2380 - MIR_append_insn(ctx, jit_func, 2381 - MIR_new_insn(ctx, MIR_MOV, 2382 - MIR_new_mem_op(ctx, MIR_T_I64, 2383 - (MIR_disp_t)(i * (int)sizeof(ant_value_t)), r_slotbuf, 0, 1), 2384 - MIR_new_mem_op(ctx, MIR_T_I64, 2385 - (MIR_disp_t)(i * (int)sizeof(ant_value_t)), r_args, 0, 1))); 2386 - MIR_append_insn(ctx, jit_func, arg_done); 2387 - } 2387 + mir_emit_fill_param_slots_from_args(ctx, jit_func, r_slotbuf, r_args, r_argc, param_count); 2388 2388 for (int i = 0; i < n_locals; i++) 2389 2389 MIR_append_insn(ctx, jit_func, 2390 2390 MIR_new_insn(ctx, MIR_MOV, ··· 4933 4933 case OP_RETURN: { 4934 4934 vstack_ensure_boxed(&vs, vs.sp - 1, ctx, jit_func, r_d_slot); 4935 4935 MIR_reg_t ret_val = vstack_pop(&vs); 4936 - if (has_captured_slots && captured_slot_count > 0) 4937 - MIR_append_insn(ctx, jit_func, 4938 - MIR_new_call_insn(ctx, 6, 4939 - MIR_new_ref_op(ctx, close_upval_proto), 4940 - MIR_new_ref_op(ctx, imp_close_upval), 4941 - MIR_new_reg_op(ctx, r_vm), 4942 - MIR_new_uint_op(ctx, 0), 4943 - MIR_new_reg_op(ctx, r_slotbuf), 4944 - MIR_new_int_op(ctx, captured_slot_count))); 4936 + if (has_captured_slots) 4937 + mir_emit_close_captured_slots(ctx, jit_func, 4938 + close_upval_proto, imp_close_upval, 4939 + r_vm, r_slotbuf, captured_slot_count); 4945 4940 MIR_append_insn(ctx, jit_func, 4946 4941 MIR_new_ret_insn(ctx, 1, MIR_new_reg_op(ctx, ret_val))); 4947 4942 break; 4948 4943 } 4949 4944 4950 4945 case OP_RETURN_UNDEF: { 4951 - if (has_captured_slots && captured_slot_count > 0) 4952 - MIR_append_insn(ctx, jit_func, 4953 - MIR_new_call_insn(ctx, 6, 4954 - MIR_new_ref_op(ctx, close_upval_proto), 4955 - MIR_new_ref_op(ctx, imp_close_upval), 4956 - MIR_new_reg_op(ctx, r_vm), 4957 - MIR_new_uint_op(ctx, 0), 4958 - MIR_new_reg_op(ctx, r_slotbuf), 4959 - MIR_new_int_op(ctx, captured_slot_count))); 4946 + if (has_captured_slots) 4947 + mir_emit_close_captured_slots(ctx, jit_func, 4948 + close_upval_proto, imp_close_upval, 4949 + r_vm, r_slotbuf, captured_slot_count); 4960 4950 MIR_append_insn(ctx, jit_func, 4961 4951 MIR_new_ret_insn(ctx, 1, 4962 4952 MIR_new_uint_op(ctx, mkval(T_UNDEF, 0))));
+50
tests/bench_jit_captured_local_bailout.cjs
··· 1 + const now = () => (typeof performance !== 'undefined' && performance.now ? performance.now() : Date.now()); 2 + 3 + function readScale() { 4 + if (typeof process === 'undefined' || !process || !process.argv) return 1; 5 + const raw = Number(process.argv[2]); 6 + return Number.isFinite(raw) && raw > 0 ? raw : 1; 7 + } 8 + 9 + const SCALE = readScale(); 10 + const REPEATS = 5; 11 + 12 + function bench(name, rounds, fn) { 13 + fn(Math.max(1, (rounds / 8) | 0)); 14 + 15 + const samples = []; 16 + let out = 0; 17 + for (let i = 0; i < REPEATS; i++) { 18 + const t0 = now(); 19 + out = fn(rounds); 20 + samples.push(now() - t0); 21 + } 22 + 23 + let best = samples[0]; 24 + let sum = 0; 25 + for (let i = 0; i < samples.length; i++) { 26 + if (samples[i] < best) best = samples[i]; 27 + sum += samples[i]; 28 + } 29 + 30 + const avg = sum / samples.length; 31 + console.log(`${name}: best ${best.toFixed(2)} ms, avg ${avg.toFixed(2)} ms, out ${out}`); 32 + return out; 33 + } 34 + 35 + function hotCapturedLocalBailout(rounds) { 36 + function f(val, y) { 37 + let x = val + 1; 38 + const g = () => x; 39 + if (typeof y === 'number') return g(); 40 + return 0; 41 + } 42 + 43 + let sum = 0; 44 + for (let i = 0; i < rounds; i++) sum += f(i, i); 45 + return sum; 46 + } 47 + 48 + const rounds = 8_000_000 * SCALE; 49 + console.log(`jit captured-local bailout benchmark (${rounds} rounds)`); 50 + bench('captured local + bailout', rounds, hotCapturedLocalBailout);
+49
tests/bench_jit_captured_param_bailout.cjs
··· 1 + const now = () => (typeof performance !== 'undefined' && performance.now ? performance.now() : Date.now()); 2 + 3 + function readScale() { 4 + if (typeof process === 'undefined' || !process || !process.argv) return 1; 5 + const raw = Number(process.argv[2]); 6 + return Number.isFinite(raw) && raw > 0 ? raw : 1; 7 + } 8 + 9 + const SCALE = readScale(); 10 + const REPEATS = 5; 11 + 12 + function bench(name, rounds, fn) { 13 + fn(Math.max(1, (rounds / 8) | 0)); 14 + 15 + const samples = []; 16 + let out = 0; 17 + for (let i = 0; i < REPEATS; i++) { 18 + const t0 = now(); 19 + out = fn(rounds); 20 + samples.push(now() - t0); 21 + } 22 + 23 + let best = samples[0]; 24 + let sum = 0; 25 + for (let i = 0; i < samples.length; i++) { 26 + if (samples[i] < best) best = samples[i]; 27 + sum += samples[i]; 28 + } 29 + 30 + const avg = sum / samples.length; 31 + console.log(`${name}: best ${best.toFixed(2)} ms, avg ${avg.toFixed(2)} ms, out ${out}`); 32 + return out; 33 + } 34 + 35 + function hotCapturedParamBailout(rounds) { 36 + function f(val, y) { 37 + const g = () => val; 38 + if (typeof y === 'number') return g(); 39 + return 0; 40 + } 41 + 42 + let sum = 0; 43 + for (let i = 0; i < rounds; i++) sum += f(i, i); 44 + return sum; 45 + } 46 + 47 + const rounds = 8_000_000 * SCALE; 48 + console.log(`jit captured-param bailout benchmark (${rounds} rounds)`); 49 + bench('captured param + bailout', rounds, hotCapturedParamBailout);