From 2ca84b85530a886bb1d5314ca5c006529e08540b Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Thu, 22 Nov 2018 20:16:59 -0800 Subject: vm: some optimizations. * vm.c (vm_getz): Manual CSE: calculate address of location, then conditionally set to zero. (vm_set_nil_error): New static function. (vm_set, vm_sm_set): Call zero-argument vm_set_nil_error instead of three_argument uw_throwf. (vm_stab_slowpath): New function. (vm_stab): Function marked inline. The slow path when the binding is not cached goes through vm_stab_slowpath which is not inlined. --- vm.c | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/vm.c b/vm.c index 4413faef..7aa463c9 100644 --- a/vm.c +++ b/vm.c @@ -366,9 +366,8 @@ INLINE val vm_get(struct vm_env *dspl, unsigned ref) INLINE val vm_getz(struct vm_env *dspl, unsigned ref) { unsigned lev = vm_lev(ref); - if (lev == 0) - return z(dspl[0].mem[vm_idx(ref)]); - return dspl[lev].mem[vm_idx(ref)]; + val *addr = &dspl[lev].mem[vm_idx(ref)]; + return (lev == 0) ? z(*addr) : *addr; } INLINE val vm_sm_get(struct vm_env *dspl, unsigned ref) @@ -376,6 +375,11 @@ INLINE val vm_sm_get(struct vm_env *dspl, unsigned ref) return dspl[vm_sm_lev(ref)].mem[vm_sm_idx(ref)]; } +NOINLINE static void vm_set_nil_error(void) +{ + uw_throwf(error_s, lit("modification of t00/nil"), nao); +} + INLINE void vm_set(struct vm_env *dspl, unsigned ref, val newval) { unsigned d = vm_lev(ref); @@ -383,7 +387,7 @@ INLINE void vm_set(struct vm_env *dspl, unsigned ref, val newval) struct vm_env *env = &dspl[d]; if (ref == 0) - uw_throwf(error_s, lit("modification of t00/nil"), nao); + vm_set_nil_error(); env->mem[i] = newval; @@ -398,7 +402,7 @@ INLINE void vm_sm_set(struct vm_env *dspl, unsigned ref, val newval) struct vm_env *env = &dspl[d]; if (ref == 0) - uw_throwf(error_s, lit("modification of t00/nil"), nao); + vm_set_nil_error(); env->mem[i] = newval; @@ -522,24 +526,36 @@ NOINLINE static void vm_apply(struct vm *vm, vm_word_t insn) vm_set(vm->dspl, dest, result); } -static loc vm_stab(struct vm *vm, unsigned fun, - val (*lookup_fn)(val env, val sym), val kind_str) + +NOINLINE static loc vm_stab_slowpath(struct vm *vm, unsigned fun, + val (*lookup_fn)(val env, val sym), + val kind_str) { struct vm_desc *vd = vm->vd; struct vm_stent *fe = &vd->stab[fun]; - loc bindloc = fe->bindloc; - - if (!nullocp(bindloc)) - return bindloc; if (nilp(fe->bind = lookup_fn(nil, vecref(vd->symvec, num_fast(fun))))) eval_error(vd->bytecode, lit("~a ~s is not defined"), kind_str, vecref(vd->symvec, num(fun)), nao); setcheck(vd->self, fe->bind); + return (fe->bindloc = cdr_l(fe->bind)); } +INLINE loc vm_stab(struct vm *vm, unsigned fun, + val (*lookup_fn)(val env, val sym), val kind_str) +{ + struct vm_desc *vd = vm->vd; + struct vm_stent *fe = &vd->stab[fun]; + loc bindloc = fe->bindloc; + + if (!nullocp(bindloc)) + return bindloc; + + return vm_stab_slowpath(vm, fun, lookup_fn, kind_str); +} + NOINLINE static void vm_gcall(struct vm *vm, vm_word_t insn) { unsigned nargs = vm_insn_extra(insn); -- cgit v1.2.3