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.

re-sync cached pointers in sv_frame

+108 -7
+20 -7
src/silver/engine.c
··· 195 195 return sv_start_tla(js, func, this_val); 196 196 } 197 197 198 + static inline void sv_sync_frame_locals( 199 + sv_vm_t *vm, sv_frame_t **frame, sv_func_t **func, 200 + ant_value_t **bp, ant_value_t **lp 201 + ) { 202 + *frame = &vm->frames[vm->fp]; *func = (*frame)->func; 203 + *bp = (*frame)->bp; *lp = (*frame)->lp; 204 + } 198 205 199 206 static inline ant_value_t sv_stage_frame_args( 200 207 sv_vm_t *vm, ant_t *js, sv_func_t *func, ant_value_t *args, int argc, ··· 449 456 }; 450 457 451 458 ant_value_t sv_err; 452 - #define VM_CHECK(expr) do { \ 453 - frame->ip = ip; \ 454 - sv_err = (expr); \ 455 - if (is_err(sv_err)) goto sv_throw; \ 456 - } while (0) 457 459 ant_value_t tc_this = js_mkundef(); 460 + 461 + #define VM_CHECK(expr) ({ \ 462 + frame->ip = ip; \ 463 + sv_err = (expr); \ 464 + if (is_err(sv_err)) goto sv_throw; \ 465 + }) 458 466 459 - #define DISPATCH() goto *dispatch[*ip] 460 - #define NEXT(n) do { ip += (n); DISPATCH(); } while (0) 467 + #define DISPATCH() goto *dispatch[*ip] 468 + #define NEXT(n) ({ ip += (n); DISPATCH(); }) 461 469 462 470 #ifdef ANT_JIT 463 471 #define JIT_OSR_BACK_EDGE() do { \ ··· 848 856 ant_value_t call_result = sv_vm_call( 849 857 vm, js, call_func, call_this, call_args, call_argc, 850 858 is_super_call ? &super_this_c : NULL, is_super_call); 859 + sv_sync_frame_locals(vm, &frame, &func, &bp, &lp); 851 860 vm->sp -= call_argc + 1; 852 861 if (is_err(call_result)) { sv_err = call_result; goto sv_throw; } 853 862 if (is_super_call) ··· 937 946 ant_value_t call_result = sv_vm_call( 938 947 vm, js, call_func, call_this, call_args, call_argc, 939 948 is_super_call ? &super_this_cm : NULL, is_super_call); 949 + sv_sync_frame_locals(vm, &frame, &func, &bp, &lp); 940 950 vm->sp -= call_argc + 2; 941 951 if (is_err(call_result)) { sv_err = call_result; goto sv_throw; } 942 952 if (is_super_call) ··· 960 970 ant_value_t call_args[1] = { call_arg }; 961 971 frame->ip = ip; 962 972 call_result = sv_vm_call(vm, js, call_func, call_this, call_args, 1, NULL, false); 973 + sv_sync_frame_locals(vm, &frame, &func, &bp, &lp); 963 974 } 964 975 965 976 vm->sp -= 3; ··· 990 1001 frame->ip = ip; 991 1002 ant_value_t call_result = sv_vm_call( 992 1003 vm, js, call_func, tc_this, call_args, call_argc, NULL, false); 1004 + sv_sync_frame_locals(vm, &frame, &func, &bp, &lp); 993 1005 vm->sp -= call_argc + 1; 994 1006 if (is_err(call_result)) { sv_err = call_result; goto sv_throw; } 995 1007 vm->stack[vm->sp++] = call_result; ··· 1017 1029 ant_value_t *call_args = &vm->stack[vm->sp - call_argc]; 1018 1030 ant_value_t call_result = sv_vm_call( 1019 1031 vm, js, call_func, tc_this, call_args, call_argc, NULL, false); 1032 + sv_sync_frame_locals(vm, &frame, &func, &bp, &lp); 1020 1033 vm->sp -= call_argc + 2; 1021 1034 if (is_err(call_result)) { sv_err = call_result; goto sv_throw; } 1022 1035 vm->stack[vm->sp++] = call_result;
+88
tests/bench_call_fallback.js
··· 1 + // Benchmark: interpreter fallback-call overhead. 2 + // 3 + // This targets the paths in silver/engine.c that call sv_vm_call(...) and then 4 + // continue executing in the current frame. It is useful for tracking the cost 5 + // of refreshing cached frame/stack locals after re-entrant native calls. 6 + 7 + const now = 8 + typeof performance !== "undefined" && performance && typeof performance.now === "function" 9 + ? () => performance.now() 10 + : () => Date.now(); 11 + 12 + let sink = 0; 13 + 14 + function bench(name, iterations, fn) { 15 + for (let i = 0; i < 3; i++) fn(iterations >> 3 || 1); 16 + 17 + const start = now(); 18 + const ops = fn(iterations); 19 + const elapsed = now() - start; 20 + const nsPerOp = (elapsed * 1e6) / ops; 21 + const opsPerSec = (ops * 1000) / elapsed; 22 + 23 + console.log( 24 + name + 25 + ": " + 26 + elapsed.toFixed(2) + 27 + "ms (" + 28 + ops + 29 + " ops, " + 30 + nsPerOp.toFixed(2) + 31 + " ns/op, " + 32 + opsPerSec.toFixed(0) + 33 + " ops/s)" 34 + ); 35 + } 36 + 37 + function jsAdd(a, b) { 38 + return a + b; 39 + } 40 + 41 + bench("js direct call", 5000000, function(n) { 42 + let sum = 0; 43 + for (let i = 0; i < n; i++) sum += jsAdd(i, 1); 44 + sink = sum; 45 + return n; 46 + }); 47 + 48 + bench("native method Math.abs", 5000000, function(n) { 49 + let sum = 0; 50 + for (let i = 0; i < n; i++) sum += Math.abs(-i); 51 + sink = sum; 52 + return n; 53 + }); 54 + 55 + bench("native method Math.imul", 5000000, function(n) { 56 + let sum = 0; 57 + for (let i = 0; i < n; i++) sum += Math.imul(i, 3); 58 + sink = sum; 59 + return n; 60 + }); 61 + 62 + bench("native method array push/pop", 3000000, function(n) { 63 + const arr = []; 64 + let sum = 0; 65 + for (let i = 0; i < n; i++) { 66 + arr.push(i); 67 + sum += arr.pop(); 68 + } 69 + sink = sum + arr.length; 70 + return n * 2; 71 + }); 72 + 73 + bench("native method string charCodeAt", 5000000, function(n) { 74 + const str = "fallback"; 75 + let sum = 0; 76 + for (let i = 0; i < n; i++) sum += str.charCodeAt(i & 7); 77 + sink = sum; 78 + return n; 79 + }); 80 + 81 + bench("native method Date.now", 1000000, function(n) { 82 + let sum = 0; 83 + for (let i = 0; i < n; i++) sum += Date.now() & 1; 84 + sink = sum; 85 + return n; 86 + }); 87 + 88 + console.log("sink:", sink);