summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--share/txr/stdlib/asm.tl37
-rw-r--r--share/txr/stdlib/compiler.tl2
-rw-r--r--vm.c112
-rw-r--r--vm.h3
-rw-r--r--vmop.h56
5 files changed, 176 insertions, 34 deletions
diff --git a/share/txr/stdlib/asm.tl b/share/txr/stdlib/asm.tl
index 521fcaff..6ebf03da 100644
--- a/share/txr/stdlib/asm.tl
+++ b/share/txr/stdlib/asm.tl
@@ -360,6 +360,34 @@
(defopcode-derived op-apply apply auto op-call)
+(defopcode op-gcall gcall auto
+ (:method asm (me asm syntax)
+ me.(chk-arg-count-min 2 syntax)
+ (let* ((nargs (pred (len syntax)))
+ (syn-pat (list* 'r 'n (repeat '(r) (sssucc nargs))))
+ (funargs (ppred nargs))
+ (args asm.(parse-args me syntax syn-pat)))
+ asm.(put-insn me.code funargs (pop args))
+ (while args
+ (let ((x (pop args))
+ (y (or (pop args) 0)))
+ asm.(put-pair y x)))))
+
+ (:method dis (me asm funargs arg0)
+ (let ((first t))
+ (build
+ (add me.symbol)
+ (add (operand-to-sym arg0))
+ (inc funargs 1)
+ (while (> funargs 0)
+ (dec funargs 2)
+ (tree-bind (y x) asm.(get-pair)
+ (add (if (zap first) x (operand-to-sym x)))
+ (unless (minusp funargs)
+ (add (operand-to-sym y)))))))))
+
+(defopcode-derived op-gapply gapply auto op-gcall)
+
(defopcode op-movrs movrs auto
(:method asm (me asm syntax)
me.(chk-arg-count 2 syntax)
@@ -635,14 +663,19 @@
(unless (minusp fix)
(add (operand-to-sym y))))))))))))
-(defun disassemble-c-d (code data *stdout*)
+(defun disassemble-c-d (code data funv *stdout*)
(let ((asm (new assembler buf code)))
(put-line "data:")
(mapdo (do format t " d~,02x: ~s\n" @1 @2) (range 0) data)
+ (put-line "funs:")
+ (mapdo (do format t "~5d: ~s\n" @1 @2) (range 0) funv)
(put-line "code:")
asm.(dis-listing)))
(defun usr:disassemble (obj : (stream *stdout*))
(typecase obj
- (vm-desc (disassemble-c-d (vm-desc-bytecode obj) (vm-desc-datavec obj) stream))
+ (vm-desc (disassemble-c-d (vm-desc-bytecode obj)
+ (vm-desc-datavec obj)
+ (vm-desc-funvec obj)
+ stream))
(t (error "~s: not a compiled object: ~s" 'vm-disassemble obj))))
diff --git a/share/txr/stdlib/compiler.tl b/share/txr/stdlib/compiler.tl
index 54251aed..cd7eb719 100644
--- a/share/txr/stdlib/compiler.tl
+++ b/share/txr/stdlib/compiler.tl
@@ -484,4 +484,4 @@
(let* ((oreg co.(alloc-treg))
(frag co.(compile oreg (new env) (expand* exp))))
as.(asm ^(,*frag.code (end ,frag.oreg)))
- (vm-make-desc co.nlev co.nreg as.buf co.(get-datavec)))))
+ (vm-make-desc co.nlev co.nreg as.buf co.(get-datavec) #()))))
diff --git a/vm.c b/vm.c
index a49b8731..cb0731de 100644
--- a/vm.c
+++ b/vm.c
@@ -67,8 +67,15 @@ struct vm_desc {
int frsz;
val bytecode;
val datavec;
+ val funvec;
vm_word_t *code;
val *data;
+ struct vm_ftent *ftab;
+};
+
+struct vm_ftent {
+ val fb;
+ loc fbloc;
};
struct vm_env {
@@ -104,7 +111,8 @@ static struct vm_desc *vm_desc_struct(val obj)
return coerce(struct vm_desc *, cobj_handle(obj, vm_desc_s));
}
-val vm_make_desc(val nlevels, val nregs, val bytecode, val datavec)
+val vm_make_desc(val nlevels, val nregs, val bytecode,
+ val datavec, val funvec)
{
val self = lit("sys:vm-make-desc");
int nlvl = c_int(nlevels, self), nreg = c_int(nregs, self);
@@ -120,14 +128,20 @@ val vm_make_desc(val nlevels, val nregs, val bytecode, val datavec)
{
mem_t *code = buf_get(bytecode, self);
val dvl = length_vec(datavec);
+ cnum fvl = c_num(length_vec(funvec));
loc data_loc = if3(dvl != zero, vecref_l(datavec, zero), nulloc);
struct vm_desc *vd = coerce(struct vm_desc *, chk_malloc(sizeof *vd));
+ struct vm_ftent *ftab = if3(fvl != 0,
+ coerce(struct vm_ftent *,
+ chk_calloc(fvl, sizeof *ftab)), 0);
+ cnum i;
val desc;
vd->nlvl = nlvl;
vd->nreg = nreg;
vd->code = coerce(vm_word_t *, code);
vd->data = valptr(data_loc);
+ vd->ftab = ftab;
vd->bytecode = nil;
vd->datavec = nil;
@@ -140,8 +154,15 @@ val vm_make_desc(val nlevels, val nregs, val bytecode, val datavec)
vd->bytecode = bytecode;
vd->datavec = datavec;
+ vd->funvec = funvec;
vd->self = desc;
+ for (i = 0; i < fvl; i++) {
+ struct vm_ftent *fe = &ftab[i];
+ fe->fb = lookup_fun(nil, vecref(funvec, num_fast(i)));
+ fe->fbloc = cdr_l(fe->fb);
+ }
+
return desc;
}
}
@@ -158,11 +179,30 @@ static val vm_desc_datavec(val desc)
return vd->datavec;
}
+static val vm_desc_funvec(val desc)
+{
+ struct vm_desc *vd = vm_desc_struct(desc);
+ return vd->funvec;
+}
+
+static void vm_desc_destroy(val obj)
+{
+ struct vm_desc *vd = coerce(struct vm_desc *, obj->co.handle);
+ free(vd->ftab);
+ free(vd);
+}
+
static void vm_desc_mark(val obj)
{
struct vm_desc *vd = coerce(struct vm_desc *, obj->co.handle);
+ cnum i, fvl = c_num(length_vec(vd->funvec));
+
gc_mark(vd->bytecode);
gc_mark(vd->datavec);
+ gc_mark(vd->funvec);
+
+ for (i = 0; i < fvl; i++)
+ gc_mark(vd->ftab[i].fb);
}
static val vm_make_closure(struct vm *vm, int frsz)
@@ -378,6 +418,65 @@ static void vm_apply(struct vm *vm, vm_word_t insn)
vm_set(vm->dspl, dest, result);
}
+static void vm_gcall(struct vm *vm, vm_word_t insn)
+{
+ unsigned nargs = vm_insn_extra(insn);
+ unsigned dest = vm_insn_operand(insn);
+ vm_word_t argw = vm->code[vm->ip++];
+ unsigned fun = vm_arg_operand_lo(argw);
+ val result;
+ args_decl (args, nargs < ARGS_MIN ? ARGS_MIN : nargs);
+
+ if (nargs--) {
+ args_add(args, vm_get(vm->dspl, vm_arg_operand_hi(argw)));
+
+ while (nargs >= 2) {
+ nargs -= 2;
+ argw = vm->code[vm->ip++];
+ args_add(args, vm_get(vm->dspl, vm_arg_operand_lo(argw)));
+ args_add(args, vm_get(vm->dspl, vm_arg_operand_hi(argw)));
+ }
+
+ if (nargs) {
+ argw = vm->code[vm->ip++];
+ args_add(args, vm_get(vm->dspl, vm_arg_operand_lo(argw)));
+ }
+ }
+
+ result = generic_funcall(deref(vm->vd->ftab[fun].fbloc), args);
+ vm_set(vm->dspl, dest, result);
+}
+
+static void vm_gapply(struct vm *vm, vm_word_t insn)
+{
+ unsigned nargs = vm_insn_extra(insn);
+ unsigned dest = vm_insn_operand(insn);
+ vm_word_t argw = vm->code[vm->ip++];
+ unsigned fun = vm_arg_operand_lo(argw);
+ val result;
+ args_decl (args, nargs < ARGS_MIN ? ARGS_MIN : nargs);
+
+ if (nargs--) {
+ args_add(args, vm_get(vm->dspl, vm_arg_operand_hi(argw)));
+
+ while (nargs >= 2) {
+ nargs -= 2;
+ argw = vm->code[vm->ip++];
+ args_add(args, vm_get(vm->dspl, vm_arg_operand_lo(argw)));
+ args_add(args, vm_get(vm->dspl, vm_arg_operand_hi(argw)));
+ }
+
+ if (nargs) {
+ argw = vm->code[vm->ip++];
+ args_add(args, vm_get(vm->dspl, vm_arg_operand_lo(argw)));
+ }
+ }
+
+ result = apply_intrinsic(deref(vm->vd->ftab[fun].fbloc),
+ args_get_list(args));
+ vm_set(vm->dspl, dest, result);
+}
+
static void vm_movrs(struct vm *vm, vm_word_t insn)
{
val datum = vm_get(vm->dspl, vm_insn_extra(insn));
@@ -672,6 +771,12 @@ static val vm_execute(struct vm *vm)
case APPLY:
vm_apply(vm, insn);
break;
+ case GCALL:
+ vm_gcall(vm, insn);
+ break;
+ case GAPPLY:
+ vm_gapply(vm, insn);
+ break;
case MOVRS:
vm_movrs(vm, insn);
break;
@@ -850,7 +955,7 @@ val vm_execute_closure(val fun, struct args *args)
static_def(struct cobj_ops vm_desc_ops =
cobj_ops_init(eq,
cobj_print_op,
- cobj_destroy_free_op,
+ vm_desc_destroy,
vm_desc_mark,
cobj_eq_hash_op));
@@ -865,8 +970,9 @@ void vm_init(void)
{
vm_desc_s = intern(lit("vm-desc"), system_package);
vm_closure_s = intern(lit("vm-closure"), system_package);
- reg_fun(intern(lit("vm-make-desc"), system_package), func_n4(vm_make_desc));
+ reg_fun(intern(lit("vm-make-desc"), system_package), func_n5(vm_make_desc));
reg_fun(intern(lit("vm-desc-bytecode"), system_package), func_n1(vm_desc_bytecode));
reg_fun(intern(lit("vm-desc-datavec"), system_package), func_n1(vm_desc_datavec));
+ reg_fun(intern(lit("vm-desc-funvec"), system_package), func_n1(vm_desc_funvec));
reg_fun(intern(lit("vm-execute-toplevel"), system_package), func_n1(vm_execute_toplevel));
}
diff --git a/vm.h b/vm.h
index 42bd2b36..1a8a1c8e 100644
--- a/vm.h
+++ b/vm.h
@@ -25,7 +25,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-val vm_make_desc(val nlevels, val nregs, val bytecode, val datavec);
+val vm_make_desc(val nlevels, val nregs, val bytecode,
+ val datavec, val funvec);
val vm_execute_toplevel(val desc);
val vm_execute_closure(val fun, struct args *);
void vm_init(void);
diff --git a/vmop.h b/vmop.h
index db907c32..065b159e 100644
--- a/vmop.h
+++ b/vmop.h
@@ -34,31 +34,33 @@ typedef enum vm_op {
FIN = 5,
CALL = 6,
APPLY = 7,
- MOVRS = 8,
- MOVSR = 9,
- MOVRR = 10,
- MOVRSI = 11,
- MOVSMI = 12,
- MOVRBI = 13,
- JMP = 14,
- IF = 15,
- IFQ = 16,
- IFQL = 17,
- UWPROT = 18,
- BLOCK = 19,
- RETSR = 20,
- RETRS = 21,
- RETRR = 22,
- CATCH = 23,
- HANDLE = 24,
- GETV = 25,
- GETF = 26,
- GETL1 = 27,
- GETVB = 28,
- GETFB = 29,
- GETL1B = 30,
- SETV = 31,
- SETL1 = 32,
- BINDV = 33,
- CLOSE = 34,
+ GCALL = 8,
+ GAPPLY = 9,
+ MOVRS = 10,
+ MOVSR = 11,
+ MOVRR = 12,
+ MOVRSI = 13,
+ MOVSMI = 14,
+ MOVRBI = 15,
+ JMP = 16,
+ IF = 17,
+ IFQ = 18,
+ IFQL = 19,
+ UWPROT = 20,
+ BLOCK = 21,
+ RETSR = 22,
+ RETRS = 23,
+ RETRR = 24,
+ CATCH = 25,
+ HANDLE = 26,
+ GETV = 27,
+ GETF = 28,
+ GETL1 = 29,
+ GETVB = 30,
+ GETFB = 31,
+ GETL1B = 32,
+ SETV = 33,
+ SETL1 = 34,
+ BINDV = 35,
+ CLOSE = 36,
} vm_op_t;