* module/system/base/syntax.scm (define-record): So, in the generated
constructors, allow optional arguments, but not keyword arguments.
Conses much less in the constructors.
(define-record/keywords): And the old define-record is here.
* module/language/ghil.scm (parse-ghil):
* module/language/ghil/compile-glil.scm (codegen):
* module/language/scheme/compile-ghil.scm (translate-1, quote)
(quasiquote): Don't use keywords in this compiler hotpath.
* module/system/base/language.scm (<language>):
* module/system/repl/common.scm (<repl>):
* module/system/vm/debug.scm (<debugger>): Use define-record/keywords.
* module/language/ghil.scm: Whoops, export some unquote-splicing
accessors that we didn't have exported before.
* module/system/base/syntax.scm: Speed up record-case, by syntactically
determining the predicates and accessors. Nasty, in a way; but also
much faster.
* module/system/base/pmatch.scm (ppat): Match atoms with eq?, not equal?.
This speeds up compilation considerably, as we never match against
numbers or strings or what-have-you. Note, you can match against
literals with equal? via quoting the literal in the pattern.
* module/language/ghil/compile-glil.scm (codegen): Record source location
for offset 0 into a lambda, if we can.
* module/language/scheme/compile-ghil.scm (translate-1)
(define-scheme-translator): In the retrans procedures, propagate the
location information from the enclosing expression if the subexpression
has no location information. Gives source information to many more
expressions.
(location): Just propagate the source properties as they are, the
glil->assembly compiler will interpret them.
* module/language/glil.scm (<glil>): Change glil-source to take "props"
and not "loc", as it's the source properties that we're interested in.
* module/language/glil/compile-assembly.scm (limn-sources): New function,
takes a list of addr-source property pairs and "compresses" them for
serialization to disk.
(glil->assembly): Limn the sources before writing them to disk. Avoid
non-tail recursion when determining total byte length of code.
* module/system/vm/program.scm (source:file, source:line, source:column):
Update for new source representation.
(program-source): Export.
(write-program): Nicer pretty-printing of anonymous procedures.
* libguile/backtrace.c (display_backtrace_get_file_line): Update for the
new VM source representation.
* libguile/programs.h:
* libguile/programs.c (scm_program_sources): Update for the new
serialized source representation, where the filename is not in the
stream unless it changes.
(scm_program_source): New exported function, looks up the source for a
given ip offset.
(scm_c_program_source): Update to return the last source information
that was <= the given IP, because we only serialize source info when it
changes.
* module/language/scheme/compile-ghil.scm (lookup-transformer): Allow
macros to be unquoted into the car of any form that results from macro
expansion. This lets modules export defmacros built on other defmacros
that are not exported.
* libguile/stacks.c (scm_make_stack): Instead of aborting when we misread
the number of stack frames, just print a warning. I'd like to figure
out what these cases are, exactly.
* module/language/scheme/compile-ghil.scm (lambda): Reindent the lambda
transformer.
* module/system/base/compile.scm (call-with-compile-error-catch): Write
the expression instead of displaying it.
(call-with-output-file/atomic): Don't actually redirect output to this
port, as it's not necessary -- the language-printer should respect the
port that we pass.
* libguile/frames.c (vm_frame_print): Add a frame printer.
* libguile/stacks.c (stack_depth, read_frames): Only switch the VM stack
for boot program dframes.
* libguile/vm-engine.c (VM_NAME): Push one debug frame per invocation,
unconditionally. (If we push them at all, of course.)
* libguile/programs.h (SCM_F_PROGRAM_IS_BOOT, SCM_PROGRAM_IS_BOOT): Flags
for determining if a program is a boot program. It turns out that our
heuristics e.g. in stacks.c would catch non-boot programs, like
programs that end with (goto/args 1), because the 1 is the same byte as
`halt'. That took a while to find...
* libguile/stacks.c (stack_depth, read_frames): Use the new boot prog
macros.
(scm_make_stack): Assert that we read the number of frames that we said
we would.
* libguile/vm.c (really_make_boot_program): Mark boot programs
appropriately.
* libguile/vm-engine.c (VM_PUSH_DEBUG_FRAMES): New knob, if true we much
with the scm_i_last_debug_frame when entering the VM, because sometimes
the evaluator doesn't do it for us.
(VM_ENGINE): Plug through debug frame fondling. Now, program exit comes
back to the main text. Rename err_args to finish_args, and reuse for
the return value.
* libguile/vm-engine.h (PUSH_LIST):
* libguile/vm-i-loader.c:
* libguile/vm-i-scheme.c:
* libguile/vm-i-system.c: Update for finish_args.
(halt): goto vm_done, now, instead of returning directly.
* libguile/eval.c (scm_call_0, scm_call_1, scm_call_2, scm_call_3)
(scm_call_4): Special-case compiled procedures here, to avoid consing.
* libguile/vm.h:
* libguile/vm.c (scm_c_vm_run): Take a SCM after all.
(scm_vm_apply, scm_load_compiled_with_vm): Adapt to vm_run change.
* libguile/programs.c (scm_make_program): Add a comment.
* libguile/vm-engine.h (INIT_ARGS): Add a couple of UNLIKELY notes.
* libguile/vm-i-system.c (make-closure): Inline the call to
scm_make_program, which avoids some redundant checks.
* libguile/vm-engine.c (VM_USE_HOOKS, VM_USE_CLOCK, VM_CHECK_EXTERNAL)
(VM_CHECK_OBJECT): Update to define these here, before including
vm-engine.h.
(vm_run): Change so that we can make different engines. Also, we take
an array of arguments, and the struct scm_vm directly, so as to avoid
any need to cons.
* libguile/vm-engine.h (CHECK_EXTERNAL, CHECK_OBJECT): Add some UNLIKELY
bits; don't seem to help.
* libguile/vm.c (vm_dispatch_hook): Change to not pass the VP. This needs
some love, and perhaps we revert to the old way.
(VM_ENGINE): Actually make two engines, vm_regular_engine and
vm_debug_engine. Probably there is room for improvement here. Actually
their speeds are the same at the moment.
(make_vm): Choose which engine to run; currently the debug engine by
default.
(scm_c_vm_run): A thin wrapper to invoke a VM without consing.
(scm_vm_apply): Use scm_c_vm_run.
(scm_load_compiled_with_vm): Use scm_c_vm_run.
* libguile/throw.c (scm_c_catch): Stash away the current vm's regs, and
restore them if there's a nonlocal exit. There is a terrible case we
have to handle if we catch from when the vm smob type isn't registered
but the throw has the vm registered, but I think we handle this fine.
* libguile/vm-engine.c (vm_run):
* libguile/vm-i-system.c (halt): Don't make a dynwind context, so that
entering the VM doesn't cons at all, except for the arg list. Maybe we
can fix that bit too.
* libguile/vm.c (vm_reset_stack): Remove, as there is no more dynwind.
(make_vm): Return #f if the tc16 hasn't yet been registered.
* libguile/instructions.c (fetch_instruction_table)
(scm_lookup_instruction_by_name): Rework so we lazily load instructions
into an array keyed by opcode, and a hash table keyed by symbolic name.
Much faster, in this hot spot of compilation.
* libguile/vm-engine.c (vm_run): Use malloc instead of scm_gc_malloc,
given that we aren't ever going to free this thing.
* libguile/vm-expand.h (VM_DEFINE_FUNCTION, VM_DEFINE_LOADER): Rework to
always be aliases to VM_DEFINE_INSTRUCTION.
(VM_DEFINE_INSTRUCTION): In the table case, update to work with
fetch_instruction_table().
* libguile/objects.c (scm_apply_generic): Inline the case when the
generic is a program.
* libguile/vm-i-system.c (return): Tick when functions return.
* module/oop/goops.scm (object-eqv?, object-equal?): Remove these
historical methods.
* module/system/vm/program.scm:
* libguile/programs.h:
* libguile/programs.c (scm_program_bindings, scm_program_bindings)
(scm_program_properties, scm_program_name): Unfortunately, implement
more procs in C, so that C can use them more easily.
* libguile/debug.c (scm_procedure_name): Dispatch to scm_program_name as
appropriate.
* libguile/vm-i-system.c (call): Tick in a call.
* libguile/vm-i-system.c (vector): Don't cons up a list just to make a
vector. Saves a couple percent in total cell allocation when loading
syncase. Probably not worth it, but foo!
* libguile/objcodes.c (scm_bytecode_to_objcode): Check that the length of
the vector matches the length embedded in the bytecode.
* libguile/programs.c (scm_program_meta): Call through to
scm_objcode_meta, instead of looking in the object table. Avoids
consing up a program+objcode slice for the meta until the meta is
actually called.
* libguile/vm-i-loader.c (load-program): Step past the metadata too.
* module/language/glil/compile-assembly.scm (make-meta): Just return the
load-program form, or #f.
(assoc-ref-or-acons, object-index-and-alist, make-object-table): Don't
write the meta into the object table.
(glil->assembly): Instead write the meta into the load-program form.
* libguile/objcodes.c (make_objcode_by_mmap, scm_c_make_objcode_slice):
Verify the lengths with the meta-length.
(scm_objcode_meta): New procedure, for getting at the meta-info of an
objcode.
(scm_objcode_to_bytecode):
(scm_write_objcode): Write bytecode with the metadata too.
* module/system/vm/objcode.scm: Export object-meta.
* module/language/assembly.scm (byte-length):
* module/language/assembly/compile-bytecode.scm (write-bytecode):
* module/language/assembly/decompile-bytecode.scm (decode-load-program):
* module/language/assembly/disassemble.scm (disassemble-load-program):
* module/language/glil/compile-assembly.scm (glil->assembly):
* test-suite/tests/asm-to-bytecode.test ("compiler"): Change to
load-program format to have meta-or-#f instead of meta-length, so that
we can serialize the meta as objcode without a load-program byte. Add a
test for writing out the meta.
* module/system/vm/Makefile.am:
* module/system/vm/conv.scm:
* module/system/vm/disasm.scm: Remove these modules, as their
functionality is now in (language ...).
* libguile/objcodes.h:
* libguile/objcodes.c:
* module/system/vm/objcode.scm: Rename objcode->u8vector to
objcode->bytecode.
* module/system/vm/frame.scm:
* module/language/bytecode/spec.scm: Fix for objcode->bytecode.
* scripts/disassemble:
* testsuite/run-vm-tests.scm: Fix for (system vm disasm) removal.
* module/system/repl/command.scm: Use the right disassembler.
* module/language/assembly/Makefile.am:
* module/language/assembly/disassemble.scm: Add a disassembler, based on
the old one but fitting in with the decompiler tower.
* module/language/objcode/spec.scm (decompile-value): When decompiling
programs, shove all the metadata that we know about into the "env".
* module/system/base/compile.scm (decompile-fold, decompile): Return the
env from `decompile' as a second value. Not sure if `compile' should do
this too.
* module/language/assembly/Makefile.am:
* module/language/assembly/spec.scm:
* module/language/assembly/decompile-bytecode.scm: Add a bytecode
decompiler. Neat!
* module/language/bytecode/spec.scm (decompile-objcode):
* module/language/objcode/spec.scm (decompile-value): Add some
"decompilers" here too.
* module/system/base/compile.scm (current-language): Since we can refer
to languages by name, do so here -- removes the previous
anti-circularity hack.
(compile-file, compile): Refer to target languages by name.
(decompile): New public function. Neat!
* module/system/base/language.scm (lookup-decompilation-order): Fix so we
look for decompilers with the high-level language definition.
* module/system/base/language.scm (lookup-decompilation-order): New
function, like its compiling cousin, but backwards.
(compute-translation-order): Rework so that languages can be specified
either by name or by identity. Return a list of language - procedure
pairs, without the "to" language in the list, instead of a list of
languages.
(invalidate-compilation-cache!): Invalidate the decompilation cache
too.
(<language>): Add a decompiler field.
* module/system/base/compile.scm (compile-passes): Much simpler now that
lookup-compilation-order gives us the procedures directly.
* module/language/*/spec.scm: Specify compilers by name, so that we can
avoid unnecessary module loads, and so that when we specify
decompilers, we can avoid cycles.
* module/language/assembly.scm: Refactor a bit; remove the name "code"
from the API, as it's too generic, and replace with "assembly".
* module/language/assembly/compile-bytecode.scm: Get byte lengths via,
well, byte-length.
* module/language/glil/Makefile.am:
* module/language/glil/spec.scm:
* module/language/glil/compile-objcode.scm: Remove compile-objcode, as we
just go through bytecode now.
* module/language/glil/compile-assembly.scm (glil->assembly)
(dump-object): s/object->code/object->assembly/.
* module/language/bytecode/Makefile.am:
* module/language/bytecode/spec.scm: Add another language to the stack,
bytecode. Bytecode is the u8vector form of object code..
* configure.in:
* module/language/Makefile.am:
* module/language/assembly/Makefile.am:
* test-suite/tests/asm-to-bytecode.test:
* module/language/assembly/spec.scm:
* module/language/assembly/compile-bytecode.scm: Update to include the
new pass.
* gdbinit: Untested attempts to get the stack fondling macros to deal
with the new program representation.
* libguile/frames.c (scm_vm_frame_arguments, scm_vm_frame_source)
(scm_vm_frame_local_ref, scm_vm_frame_local_set_x): SCM_PROGRAM_DATA is
a struct scm_objcode*.
* libguile/instructions.h:
* libguile/instructions.c: Hide the instruction table and the struct
scm_instruction structure; all access to instructions now goes through
procedures. This is because instructions are no longer in a packed
array indexed by opcode. Also, declare a mask that all instructions
should fit in.
* libguile/objcodes.h:
* libguile/objcodes.c: Rewrite so that object code directly maps its
arity and length from its bytecode. This makes it unnecessary to keep
this information in programs, allowing programs to be simple conses
between the code (objcodes) and data (the object table and the closure
variables).
* libguile/programs.c (scm_make_program): Rework so that make-program
takes objcode, an object table, and externals as arguments. It's much
clearer this way, and we avoid malloc().
* libguile/stacks.c (is_vm_bootstrap_frame): Update for program/objcode
changes.
* libguile/vm-engine.c (vm_run): Initialize the jump table on the first
run, with the opcodes declared in the instruction sources, and with bad
instructions raising an error instead of wandering off into the
Unknown.
* libguile/vm-engine.h (FETCH_LENGTH): Always represent lengths as 3
bytes. The old code was too error-prone.
(NEXT_JUMP): Mask the instruction with SCM_VM_INSTRUCTION_MASK.
(NEW_FRAME): Update for program/objcode changes.
* libguile/vm-expand.h (VM_DEFINE_FUNCTION, VM_DEFINE_INSTRUCTION)
(VM_DEFINE_LOADER): Update so that we explicitly specify opcodes, so
that we have a stable bytecode API.
* libguile/vm-i-loader.c: Update license to LGPLv2+. Explicitly declare
opcodes.
(load-integer): Use an int instead of a long as the accumulator; still
need to revisit this code at some point, I think.
(load-program): Simplify, thankfully!! Just creates the objcode slice
and rolls with it.
* libguile/vm-i-scheme.c: Number the opcodes explicitly.
* libguile/vm-i-system.c: Update license to LGPLv2+. Explicitly declare
opcodes.
(make-closure): Update for new program API.
* libguile/vm.c (vm_make_boot_program): Update for new program/objcode
API. Still a bit ugly.
(scm_load_compiled_with_vm): Update for new program/objcode API.
* module/language/assembly.scm (byte-length): Fix byte-length calculation
for loaders, and load-program.
(code-pack, code-unpack): Start to move things from (system vm conv)
here.
(object->code, code->object): More things from conv.scm.
* module/language/glil.scm (<glil-program>): Add a new field,
closure-level.
(make-glil-program, compute-closure-level): Calculate the "closure
level" when making a glil program. This is the maximum depth of
external binding refs in this closure.
(unparse-glil): Fix label serialization.
* module/language/glil/compile-assembly.scm (make-meta): Prepend #f for
the meta's object table, though maybe in the future we can avoid
creating assembly in the first place.
(assoc-ref-or-acons, object-index-and-alist): GRRR! Caught again by the
different sets of arguments to assoc and assoc-ref!
(glil->assembly): Attempt to make the <glil-program> case more
readable, and fix the bugs. Sorry I don't know how to comment this
change any more than this.
(glil->assembly): For <glil-module> serialize the whole key, not just
the name.
(dump-object): subprogram-code is already a list. Serialize integers as
strings, not u8vectors. Fix the order of lists and vectors.
* module/language/glil/spec.scm (glil): Switch orders, so we prefer glil
-> assembly -> objcode. Actually glil->objcode doesn't work any more,
needs to be removed I think.
* module/language/objcode/spec.scm (objcode->value):
s/objcode->program/make-program/.
* module/language/scheme/inline.scm: Add acons inline.
* module/system/vm/conv.scm (make-byte-decoder): Skip the first 8 bytes,
they are header. Handle subprograms properly. Still needs help though.
(decode-length): Lengths are always 3 bytes now.
* module/system/vm/disasm.scm: Superficial changes to keep things
working. I'd like to fix this better in the future.
* module/system/vm/frame.scm (bootstrap-frame?): Fixes for
program-bytecode.
* module/system/vm/program.scm: Export make-program. It's program-objcode
now, no more program-bytecode.
* module/system/vm/vm.scm (vm-load): Use make-program.
* test-suite/tests/asm-to-bytecode.test: New test, very minimal.
* module/system/vm/objcode.scm: Export word-size, byte-order, and
write-objcode.
* configure.in:
* module/language/Makefile.am:
* module/language/assembly/Makefile.am: Automakery.
* module/language/assembly.scm:
* module/language/assembly/spec.scm: Add a new language, which is oddly
even lower than GLIL. I got tired of GLIL's terrible
compile-objcode.scm, and wanted a cleaner intermediate format.
* module/language/glil/compile-assembly.scm: A purely-functional
assembler, that produces "assembly". Will document later.
* module/language/glil/spec.scm: Declare the compiler to assembly.
* libguile/programs.h (struct scm_program): Remove the module and meta
fields.
* libguile/programs.c (scm_c_make_program): Add a new argument, `objs'.
If it's a vector, we'll look for the module and the metadata in there,
instead of having them in the scm_program structure.
(scm_c_make_closure, program_mark, scm_program_meta)
(scm_c_program_source, scm_program_module): Adapt to the new program
representation.
* libguile/objcodes.c (scm_objcode_to_program): Pass #f as the object
table when making the program.
* libguile/vm-engine.h (CACHE_PROGRAM):
* libguile/vm-engine.c (vm_run): Rework to use the simple vector API for
getting the current object table. Call the helper,
vm_make_boot_program, to make the boot program.
* libguile/vm-i-loader.c (load-program): Set the current module and the
meta in the object vector, which we pass to scm_c_make_program.
* libguile/vm-i-system.c (toplevel-ref, toplevel-set): Adapt to the new
program representation.
* module/language/glil/compile-objcode.scm (codegen): Clarify.
* module/language/glil/compile-objcode.scm (codegen): If the generated
objcode will have a meta or it has objects, prepend two cells to the
object table: one for the meta, and one for the module. This is a
placeholder for future work.
* libguile/vm.h (struct scm_vm_cont):
* libguile/vm.c (capture_vm_cont, reinstate_vm_cont): Change so we just
store the registers as they are, with the reloc.
(vm_cont_mark): Only mark the stack if it has elements on it, otherwise
we get a bogus fp.
* libguile/stacks.c (scm_make_stack): Update for change to vm
continuations.