1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-04-30 11:50:28 +02:00

Update "Why a VM?"

* doc/ref/vm.texi (Why a VM?): Update.
This commit is contained in:
Andy Wingo 2018-09-28 12:14:55 +02:00
parent f1b745eec5
commit 2018609a69

View file

@ -50,26 +50,28 @@ programs to Guile's VM.
@subsection Why a VM? @subsection Why a VM?
@cindex interpreter @cindex interpreter
For a long time, Guile only had an interpreter. Guile's interpreter For a long time, Guile only had a Scheme interpreter, implemented in C.
operated directly on the S-expression representation of Scheme source Guile's interpreter operated directly on the S-expression representation
code. of Scheme source code.
But while the interpreter was highly optimized and hand-tuned, it still But while the interpreter was highly optimized and hand-tuned, it still
performed many needless computations during the course of evaluating an performed many needless computations during the course of evaluating a
expression. For example, application of a function to arguments Scheme expression. For example, application of a function to arguments
needlessly consed up the arguments in a list. Evaluation of an needlessly consed up the arguments in a list. Evaluation of an
expression always had to figure out what the car of the expression is -- expression like @code{(f x y)} always had to figure out whether @var{f}
a procedure, a memoized form, or something else. All values have to be was a procedure, or a special form like @code{if}, or something else.
allocated on the heap. Et cetera. The interpreter represented the lexical environment as a heap data
structure, so every evaluation caused allocation, which was of course
slow. Et cetera.
The solution to this problem was to compile the higher-level language, The solution to the slow-interpreter problem was to compile the
Scheme, into a lower-level language for which all of the checks and higher-level language, Scheme, into a lower-level language for which all
dispatching have already been done---the code is instead stripped to of the checks and dispatching have already been done---the code is
the bare minimum needed to ``do the job''. instead stripped to the bare minimum needed to ``do the job''.
The question becomes then, what low-level language to choose? There The question becomes then, what low-level language to choose? There are
are many options. We could compile to native code directly, but that many options. We could compile to native code directly, but that poses
poses portability problems for Guile, as it is a highly cross-platform portability problems for Guile, as it is a highly cross-platform
project. project.
So we want the performance gains that compilation provides, but we So we want the performance gains that compilation provides, but we
@ -82,33 +84,36 @@ implement the virtual machine within Guile itself. Guile contains a
bytecode interpreter (written in C) and a Scheme to bytecode compiler bytecode interpreter (written in C) and a Scheme to bytecode compiler
(written in Scheme). This way the virtual machine provides what Scheme (written in Scheme). This way the virtual machine provides what Scheme
needs (tail calls, multiple values, @code{call/cc}) and can provide needs (tail calls, multiple values, @code{call/cc}) and can provide
optimized inline instructions for Guile (@code{cons}, @code{struct-ref}, optimized inline instructions for Guile as well (GC-managed allocations,
etc.). type checks, etc.).
So this is what Guile does. The rest of this section describes that VM Guie also includes a just-in-time (JIT) compiler to translate bytecode
that Guile implements, and the compiled procedures that run on it. to native code. Because Guile uses the portable GNU Lightning library
to emit that code, we keep the benefits of portability while also
benefitting from fast native code. To avoid too much time spent in the
JIT compiler itself, Guile is tuned to only emit machine code for
bytecode that is called often.
The rest of this section describes that VM that Guile implements, and
the compiled procedures that run on it.
Before moving on, though, we should note that though we spoke of the Before moving on, though, we should note that though we spoke of the
interpreter in the past tense, Guile still has an interpreter. The interpreter in the past tense, Guile still has an interpreter. The
difference is that before, it was Guile's main evaluator, and so was difference is that before, it was Guile's main Scheme implementation,
implemented in highly optimized C; now, it is actually implemented in and so was implemented in highly optimized C; now, it is actually
Scheme, and compiled down to VM bytecode, just like any other program. implemented in Scheme, and compiled down to VM bytecode, just like any
(There is still a C interpreter around, used to bootstrap the compiler, other program. (There is still a C interpreter around, used to
but it is not normally used at runtime.) bootstrap the compiler, but it is not normally used at runtime.)
The upside of implementing the interpreter in Scheme is that we preserve The upside of implementing the interpreter in Scheme is that we preserve
tail calls and multiple-value handling between interpreted and compiled tail calls and multiple-value handling between interpreted and compiled
code. The downside is that the interpreter in Guile 2.2 is still about code, and with advent of the JIT compiler in Guile 3.0 we reach the
twice as slow as the interpreter in 1.8. Since Scheme users are mostly speed of the old hand-tuned C implementation; it's the best of both
running compiled code, the compiler's speed more than makes up for the worlds.
loss. In any case, once we have native compilation for Scheme code, we
expect the self-hosted interpreter to handily beat the old hand-tuned C
implementation.
Also note that this decision to implement a bytecode compiler does not Also note that this decision to implement a bytecode compiler does not
preclude native compilation. We can compile from bytecode to native preclude ahead-of-time native compilation. More possibilities are
code at runtime, or even do ahead of time compilation. More discussed in @ref{Extending the Compiler}.
possibilities are discussed in @ref{Extending the Compiler}.
@node VM Concepts @node VM Concepts
@subsection VM Concepts @subsection VM Concepts