diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2018-11-22 20:16:59 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2018-11-22 20:16:59 -0800 |
commit | 2ca84b85530a886bb1d5314ca5c006529e08540b (patch) | |
tree | 62bfb2f57cc0c2d4d058d8c452dc906b620f5b3b /vm.c | |
parent | 67266d7fa6b2dc36200caa7d2a83d37238deb427 (diff) | |
download | txr-2ca84b85530a886bb1d5314ca5c006529e08540b.tar.gz txr-2ca84b85530a886bb1d5314ca5c006529e08540b.tar.bz2 txr-2ca84b85530a886bb1d5314ca5c006529e08540b.zip |
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.
Diffstat (limited to 'vm.c')
-rw-r--r-- | vm.c | 38 |
1 files changed, 27 insertions, 11 deletions
@@ -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); |