summaryrefslogtreecommitdiffstats
path: root/vm.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2018-11-22 20:16:59 -0800
committerKaz Kylheku <kaz@kylheku.com>2018-11-22 20:16:59 -0800
commit2ca84b85530a886bb1d5314ca5c006529e08540b (patch)
tree62bfb2f57cc0c2d4d058d8c452dc906b620f5b3b /vm.c
parent67266d7fa6b2dc36200caa7d2a83d37238deb427 (diff)
downloadtxr-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.c38
1 files 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);