| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
|
|
|
|
|
| |
* vm.c (vm_make_closure): Add missing scale factor to memcpy.
This is the memcpy which relocates display frame contents from
the stack to the frame.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/asm.tl (abscsr): New instruction.
(op-abscsr): New opcode class, derived from op-retsr.
* share/txr/stdlib/compiler.tl: Handle sys:abscond-from via
comp-return-from method.
(compiler comp-return-from): Handle sys:abscond-from by
switching to abscsr opcode instead of ret pseudo-op.
* vm.c (vm_abscsr): New static function.
(vm_execute): Dispatch ABSCSR opcode.
* vmop.h: Regenerated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
In most compiler uses of bindv, getv and setv,
the operand which names the dynamic symbol is the data table:
a d0-dff register. The source or destination register of the
transfer could be anything. Therefore, the existing encoding
is suboptimal: the symbol is being put into the full sized
operand field of the instruction, and the source or
destination register into the small, ten-bit extra field
in the upper half. This breaks on cases like (set x y)
where x is a deeply nested lexical variable and y is
a dynamic variable. Let's reverse the encoding.
* share/txr/stdlib/asm.tl (op-getv, op-setv): Reverse the
operands. All derived opcodes follow this since they
reuse the code via inheritance.
* vm.c (vm_get_binding): Fetch the symbol from the small
operand field rather than the main operand field.
(vm_getsym, vm_getbind, vm_setsym, vm_bindv): Pull the
destination or source from the main operand of the instruction
rather than the small opreand.
|
|
|
|
|
|
|
|
| |
* vm.c (vm_make_desc): Initialize vd->funvec to nil so that
when the object is created, it doesn't have a garbage field.
However, there is no risk here that the field will be
traversed by the garbage collector, since immediately after
allocating the objct, we initialize the fields.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Let's have a field in struct vm_desc that keeps track of the
ftab size. The problem is when we do length_vec(vd->funvec) in
vm_desc_mark, we are in the middle of garbage collection.
The object's tag has a reachable bit which blows up the
type check.
* vm.c (struct vm_desc): New member, ftsz.
(vm_make_desc): Store the length of the function table
into ftsz.
(vm_desc_mark): Use the stored length as the loop bound;
do not access vd->funvec.
|
|
|
|
|
|
| |
* vm.c (vm_no_block_err): New static function.
(vm_retsr, vm_retrs, vm_retrr): Call vm_no_block_err if
uw_block_return returns.
|
|
|
|
|
|
|
|
|
|
| |
* vm.c (struct vm_closure): Redeclare display member as array
of 1: old-fashioned version of C struct hack.
(vm_make_closure): Make the necessary adjustments to the
allocation code.
(vm_closure_destroy): Static function removed.
(vm_closure_mark): Wire in cobj_destroy_free_op once again,
since there is just one object to free.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This allows a virtual machine's funvec to refer to functions
that are not yet defined. We resolve all the ones that are
defined when the virtual machine description is constructed.
The others are resolved at vm execution time when accessed.
* vm.c (vm_make_desc): When filling ftab with resolved
function bindings, check that lookup_fun has returned nil; in
that case, initialize the binding location to zero,
instead of blowing up calling cdr_l(nil).
(vm_ftab): New static function. Implements the null check
and late resolution.
(vm_gcall, vm_gapply): Acces ftab through vm_ftab instead
of open-coded expression.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/compiler.tl (sys:env :postinit): The call
to register the environment with the compiler must be outside
of the unless form. Otherwise it never takes place, and so the
compiler doesn't find the maximum number of environment
levels, keeping the value at 2. The executing vm then accesses
out of bounds memory when setting up display frames.
(usr:compile-toplevel): Give the root environment the
compiler. Not strictly necessary since we are constent in
doing this elsewhere, so we are not relying on inheritance
of the compiler from parent environment to child.
* vm.c (vm_make_closure): assert added for the environment
levels of the closure not exceeding the display depth given
in the machine description. This was added during debugging
and going off; I'm keeping it.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* vm.c (vm_execute_closure): Remove bogus nargs local
variable, and replace its uses by fixparam which is the
correct one to use for getting the list of trailing arguments
using args_get_rest and for the loop which extracts the fixed
arguments. The "if (variadic)" statement near the end
specifically depends on the variadic destination register not
having been extracted yet from the instruction space,
so the argument count used in the previousl loop cannot
include that register. This bug was causing that statement to
extract a zero, thus register t0, which then blew up in the vm
execution as an attempt to modify t0.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The vm now supports gcall and gapply opcodes which index
numerically (using an immediate integer field in the
instruction word) into a table of pre-resolved global function
bindings.
* share/txr/stdlib/asm.tl (op-gcall, op-gapply): New opcodes.
(disassemble-c-d): Take the function vector as an argument and
dump it too.
(usr:disassemble): Extract function vector from VM description
and pass it to disassemble-c-d.
* share/txr/stdlib/compiler.tl (usr:compile-toplevel): Pass
empty function symbol vector to vm-make-desc; it's now a
required argument.
* vm.c (struct vm_desc): New members funvec and ftab.
(struct vm_ftent): New struct type.
(vm_make_desc): New argument, funvec. Store funvec in the
descriptor. Allocate a table of vm_ftent structures equal in
number of elements to the function table, and populate it with
resolved bindings.
(vm_desc_funvec, vm_desc_destroy): New static functions.
(vm_desc_mark): Mark the captured bindings in vd->ftab.
(vm_gcall, vm_gapply): New static functions.
(vm_execute): Handle GCALL and GAPPLY opcodes.
(vm_desc_ops): Wire vm_desc_destroy in place of
cobj_destroy_free_op.
(vm_init): Add argument to vm-make-desc intrinsic. Register
vm-desc-funvec intrinsic.
* vm.h (vm_make_desc): Declaration updated.
* vmop.h: Regenerated
|
|
|
|
|
|
| |
* vm.c (vm_closure_destroy): New static function.
(vm_closure_ops): Use vm_closure_destroy rather than
generic cobj_destroy_free_op.
|
|
|
|
|
|
|
|
|
|
| |
* share/txr/stdlib/asm.tl (op-ifq, op-ifql): New opcode
types.
* vm.c (vm_ifq, vm_ifql): New static functions.
(vm_execute): Handle IFQ and IFQL opcodes.
* vmop.h (vm_op_t): Regenerated.
|
|
|
|
|
|
| |
* vm.c (vm_make_desc): We can't call vecref_l on an empty
vector, because it has no index zero. Let's use a null
location in this case.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* lisplib.c (asm_set_entries): Autoload on usr:disassemble.
* share/txr/stdlib/asm.tl (assembler): Drop initializer
from bstr slot. Requires complex initialization for the
case when the buf is supplied by the constructor caller
for the sake of disassembling existing code.
(assembler :postinit): Handle cases when only one of
buf or bstr are set, and when both are not set,
for the greatest flexibility.
(disassemble-c-d, disassemble): New functions.
* vm.c (vm_desc_datavec): New static function.
(vm_init): Registered vm-desc-datavec intrinsic.
|
|
|
|
|
| |
* vm.c (vm_init): Register vm_execute_toplevel as
vm-execute-toplevel rather than vm-interpret-toplevel.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This is for allocating a new frame purely on the stack. The
frame will not be captured by lexical closures, and so can
only be used for non-shared variables and additional
compiler-generated temporaries (if registers run out, for
instance).
* share/txr/stdlib/asm.tl (op-sframe, sframe): New opcode
class and opcode.
* vm.c (vm_do_frame): New static function for the common
implementation of frame and sframe.
(vm_frame): Now just a call with vm_do_frame, passing the flag
indicating that closure capture is enabled for this
environment frame.
(vm_sframe): New static function.
* vmop.h: Regenerated.
|
|
|
|
|
|
| |
* vm.c (vm_make_closure): When copying captured environment
from stack to heap, use memcpy instead of a loop with
assignments.
|
|
This commit is the start of compiler work to make TXR Lisp
execute faster. In six days of part time work, we now have a
register-style virtual machine with 32 instructions, handling
exceptions, unwind-protect, lexical closures, and global
environment access/mutation. We have a complete assembler and
disassembler for this machine. The assembler supports labels
with forward referencing with backpatching, and features
pseudo-ops: for instance the (mov ...) pseudo-instruction
chooses one of three kinds of specific move instruction based
on the operands.
* Makelfile (OBJS): Add vm.o.
* eval.c (lookup_sym_lisp1): Static function becomes external;
the virtual machine needs to use this to support that style
of lookup.
* genvmop.txr: New file. This is the generator for the
"vmop.h" header.
* lib.c (func_vm): New function.
(generic_funcall): Handle the FVM function type via new
vm_execute_closure function. In the variadic case, we want
to avoid the argument copying which we do for the sake of C
functions that get their fixed arguments directly, and then
just the trailing arguments. Thus the code is restructured a
bit in order to switch twice on the function type.
(init): Call vm_init.
* lib.h (functype_t): New enum member FVM.
(struct func): New member in the .f union: vm_desc.
(func_vm): Declared.
* lisplib.c (set_dlt_entries_impl): New static function,
formed from set_dlt_entries.
(set_dlt_entries): Reduced to wrapper for
set_dlt_entries_impl, passing in the user package.
(set_dlt_entries_sys): New static function: like
set_dlt_entries but targetting the sys package.
(asm_instantiate, asm_set_entries): New static functions.
(lisplib_init): Auto-load the sys:assembler class.
* share/txr/stdlib/asm.tl: New file.
* vm.c, vm.h, vmop.h: New files.
|