epsilon-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Preliminary: Porting Poke to the latest Jitter, with sub-package mod


From: Luca Saiu
Subject: Re: Preliminary: Porting Poke to the latest Jitter, with sub-package mode and the unified routine API
Date: Sun, 03 Nov 2019 23:42:35 +0100
User-agent: Gnus (Gnus v5.13), GNU Emacs 27.0.50, x86_64-pc-linux-gnu

On 2019-11-03 at 22:50 +0100, Jose E. Marchesi wrote:

> Hmm, you didn't change pvm_program_point to pvm_routine_point in Jitter?

No, and I like it this way.  "Program point" is a standard phrase,
identifying a source location as related to the dynamic semantics of a
program.

A routine is a compilation unit for Jitter.  Execution will always
start from some program point in a known routine but then it may branch
to some other program point belonging to a different routine.  Soon it
will be possible to have multiple entry points per routine: I have an
important use case for that, related to tail calls.

The mapping between program points and routines will become even more
complex with stepping; imagine being able to run a VM instruction and
then returning to C, with the program point being saved to be able to
branch back to the next instruction.  Which routine is the current one
can be computed if needed, but after the code is compiled it is not even
particularly important, except for debugging.

Of course being very undisciplined in the mapping between closures,
routines and program points might make routine finalization more
difficult when routines are garbage collected, and I do not recommend
it.  I would still say that the name is the right one.

> Hm, if --enable-debug no longer controls how the Jitter VM is built,

With my proposed change --enable-debug no longer does anything, in fact.
We could remove it, but you may want to reuse the option for some other
purpose in the future.

> how can the user force building with direct threading when she wants
> to debug something in pvm.jitter?

You can pass options to the sub-package configure from the super-package
configure: in particular you can, for example, configure *Poke* with
--enable-dispatch-no-threading.  You can pass any combination of options
manually enabling or disabling specific dispatches, if you want.  The
default is meant to always remain safe and correct, even as Jitter
evolves.

Right now there is no obvious way of *computing* options for the
sub-package configure script from the super-package configure script,
even if it would be nice.  The internal implementation in Autoconf makes
it difficult.

If you really like the old behavior of --enable-debug I can reinstate
it.  Otherwise you can now force minimal-threading and no-threading to
be disabled by configuring Poke with
  --disable-dispatch-minimal-threading --disable-dispatch-no-threading

This is almost equivalent to the old --enable-debug, but a little
better: with a compiler only supporting switch dispatching Poke would
use switch dispatching instead of failing.

At the present time even passing
  --disable-dispatch-minimal-threading --disable-dispatch-no-threading
is pointless, however, as minimal-threading and no-threading are already
disabled by default.  They will be enabled when I fix defective
instructions in a reliable way.

> Just a small note: the API is inconsistent there:
> pvm_disassemble_routine vs. pvm_routine_print.  I recommend to settle in
> one style, like verb first and then subject.  Will save us time :)

You are right, that part is ugly -- I would also like to simplify the
options for disassembling, without exposing the objdump command line at
run time, after it is already resolved at Jitter configuration time.
Since the API will change again because of libtextstyle I think I will
seize that occasion to clean it up, once and for all.

It will require another change in Poke, but it will be easy.  Since
integrating libtextstyle turned out not to be completely trivial I
decided to deal with Poke first.

>       #define PKL_COMPILING_EXPRESSION 0
>      -#define PKL_COMPILING_PROGRAM    1
>      +#define PKL_COMPILING_ROUTINE    1
>       #define PKL_COMPILING_STATEMENT  2
>
> Hm, nope.  There PKL_COMPILING_PROGRAM refers to the _Poke_ entity that
> is being compiled.  Unrelated to PVM or jitter.  It should stay
> PKL_COMPILING_PROGRAM.

This escaped me, sorry.  I caught the same nuance in the AST but not
here.  Undoing that change.

> Please do not include GC_disable() in the patch.  The change must work
> with the GC switched on! :)

Thanks for noticing that.  Undoing it.

>      +/* The C header file generated by Jitter for PVM defines pvm_routine as 
> an alias
>      +   to a VM-independent type abstract type named jitter_routine.  We 
> cannot the
>      +   header here without generating a CPP inclusion cycle, so for the 
> time being
>
> You probably mean "We cannot include the header here"?

Fixing that, and improving the comment.

The next iteration is attached here.  The test suite passes.  I have not
tried to pull the most recent changes yet, but they should not interfere
too much.

Points to be settled:
* --enable-debug (remove it, reinstate the old behavior, leave it as a
no-op for the future)?
* ... ?

Regards,

-- 
Luca Saiu
* My personal web site:  http://ageinghacker.net
* GNU epsilon:           http://www.gnu.org/software/epsilon
* Jitter:                http://ageinghacker.net/projects/jitter

I support everyone's freedom of mocking any opinion or belief, no
matter how deeply held, with open disrespect and the same unrelented
enthusiasm of a toddler who has just learned the word "poo".
commit 7ce377b605fa47a3274d1feec14a167809c13c60
Author: Luca Saiu <address@hidden>
Date:   Sun Nov 3 02:07:43 2019 +0100

    port Poke to latest Jitter: ChangeLog entry still to write

diff --git a/HACKING b/HACKING
index bfe535d..873a5d5 100644
--- a/HACKING
+++ b/HACKING
@@ -70,7 +70,7 @@ along with GNU poke.  If not, see 
<https://www.gnu.org/licenses/>.
     10  Memory Management
       10.1  Using ASTREF
       10.2  Using ASTDEREF
-      10.3  PVM values in PVM programs
+      10.3  PVM values in PVM routines
       10.4  PVM values in AST nodes
     11  Terminal Handling
       11.1  pk-term
@@ -820,48 +820,49 @@ This works because ``pkl_ast_make_xxx`` does an 
``ASTREF`` to ``b``
 internally.  The final result is that the reference counter of ``b``
 doesn't change at all.
   
-PVM values in PVM programs
+PVM values in PVM routines
 ~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-The PVM programs (data structures of type ``pvm_program``) are
-allocated by Jitter, using ``malloc``.  Therefore, they are not
-traversed by the GC.
+PVM routines (data structures of type ``pvm_routine``) are
+allocated by Jitter in complicated data structures, internally relying
+on ``malloc``.  Their content is therefore not automatically visible to
+the GC.
 
-Now, the instructions in a program can contain literal PVM values, and
+Now, the instructions in a routine can contain literal PVM values, and
 some of these values will be boxed.  For example, the following
-program contains a pointer to a ``pvm_val_box``::
+routine contains a pointer to a ``pvm_val_box``::
 
   ;; Initialize the element index to 0UL, and put it
   ;; in a local.
   push ulong<64>0
   regvar $eidx
 
-There are two places where PVM programs are stored in other data
+There are two places where PVM routines are stored in other data
 structures: in closures, and in the compiler.
 
 A closure is a kind of PVM value itself, and therefore allocated by
-the GC.  It is composed by a PVM program, a run-time environment and
-an entry point into the program::
+the GC.  It is composed by a PVM routine, a run-time environment and
+an entry point into the routine (as a Jittery VM ``program point``)::
 
   struct pvm_cls
   {
-    struct jitter_program *program;
-    const void *entry_point;
+    pvm_routine routine;
+    pvm_program_point entry_point;
     struct pvm_env *env;
   };
 
-However, since ``program`` is malloc-allocated, the GC can't traverse
+However, since ``routine`` is malloc-allocated, the GC can't traverse
 it.  Consequently, the references to contained boxed values won't be
-accounted, and these values will be collected if there are no more
+accounted for, and these values will be collected if there are no more
 refences to them!
 
 The solution, recommended by Luca Saiu, is to keep an array of
 pointers in the closure structure, containing the pointers to every
-boxed value used in ``program``::
+boxed value used in ``routine``::
 
   struct pvm_cls
   {
-    struct jitter_program *program;
+    pvm_routine routine;
     void **pointers;
     const void *entry_point;
     struct pvm_env *env;
@@ -872,12 +873,12 @@ macro-assembler in ``pkl-asm.c``.  ``pkl_asm_finish`` 
will return the
 array of pointers, and it is up to the caller (in the code generator)
 to install it the corresponding closure structure.
 
-The second place where a PVM program is stored in other data
+The second place where a PVM routine is stored in other data
 structures is the compiler functions ``pkl_compile_file`` and
-``pkl_compile_buffer``.  In both functions, the compiled PVM program
+``pkl_compile_buffer``.  In both functions, the compiled PVM routine
 is executed and then discarded.  However, it is still required to have
-the ``pointers`` array linked from the C stack, to avoid the GC to
-collect the values from the program.  That's the purpose of the weird
+the ``pointers`` array linked from the C stack, to prevent the GC from
+freeing values used in the routine.  That's the purpose of the weird
 local variables, which are set but never used::
 
   int
@@ -886,12 +887,12 @@ local variables, which are set but never used::
   {
     ...
     /* Note that the sole purpose of `pointers' is to serve as a root
-       (in the stack) for the GC, to prevent the boxed values in PROGRAM
+       (in the stack) for the GC, to prevent the boxed values in ROUTINE
        to be collected.  Ugly as shit, but conservative garbage
        collection doesn't really work.  */
     void *pointers;
     ...
-    program = rest_of_compilation (compiler, ast, &pointers);
+    routine = rest_of_compilation (compiler, ast, &pointers);
     ...
   }
 
@@ -899,9 +900,9 @@ PVM values in AST nodes
 ~~~~~~~~~~~~~~~~~~~~~~~
 
 Storing a PVM value (whose memory is handled by GC) in an AST node
-(reference-counted) lead to a problem: the GC is unable to see the
-reference to values, and will collect the memory if there are no other
-references.
+(reference-counted) leads to a problem: the GC is unable to see the
+reference to values, and will therefore collect the memory if there
+are no other reachable references.
 
 Let's see an example of this.  Both array and struct types contain
 closures for mappers, writers, bounders, and the like.  For example,
diff --git a/Makefile.am b/Makefile.am
index 6aa07d8..7fbef12 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,5 +1,5 @@
 ACLOCAL_AMFLAGS = -I m4
-SUBDIRS = lib pickles src doc testsuite etc po
+SUBDIRS = jitter lib pickles src doc testsuite etc po
 
 # This (and the accompanying AC_SUBST of WITH_JITTER) is to be removed
 # as soon as we bump to a Jitter version not requiring --with-jitter
diff --git a/TODO b/TODO
index 1ee13a0..5b50ef3 100644
--- a/TODO
+++ b/TODO
@@ -425,8 +425,8 @@ It would be nice to have some tests too.
 ---------------------------------------------
 
 The macro-assembler keeps an array of pointers to PVM values
-references in the program being assembled.  This is needed because the
-PVM programs (which are Jitter programs) are allocated using the
+references in the routine being assembled.  This is needed because the
+PVM routines (which are Jitter routines) are allocated using the
 system malloc, whereas the PVM values are allocated using the Boehm
 GC.  See HACKING for more information about this.
 
diff --git a/acinclude.m4 b/acinclude.m4
deleted file mode 100644
index ad0a10c..0000000
--- a/acinclude.m4
+++ /dev/null
@@ -1,362 +0,0 @@
-# Autoconf macros for Jitter.
-# Copyright (C) 2017, 2018 Luca Saiu
-# Written by Luca Saiu
-
-# This file is part of Jitter.
-
-# Jitter is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-
-# Jitter is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with Jitter.  If not, see <http://www.gnu.org/licenses/>.
-
-
-# The Autoconf manual says (about writing Autoconf macros):
-# No Autoconf macro should ever enter the user-variable name space;
-# i.e., except for the variables that are the actual result of running the
-# macro, all shell variables should start with 'ac_'.  In addition, small
-# macros or any macro that is likely to be embedded in other macros should
-# be careful not to use obvious names.
-
-
-# Generic M4 machinery.
-################################################################
-
-# jitter_tocpp([my-text])
-# -----------------------
-# Expand to the argument where each letter is converted to upper case, and
-# each dash is replaced by an underscore.
-# Example: jitter_tocpp([my-teXt_4]) --> MY_TEXT_4
-# About the namespace, see the comment for ac_jitter_using_automake.
-m4_define([jitter_tocpp],
-          [m4_translit([m4_toupper([$1])], ][-][, ][_][)])dnl
-
-# jitter_define_iterator([iterator_name], [list])
-# -----------------------------------------------
-# Expand to the *definition* of an iterator like jitter_for_dispatch or
-# jitter_for_flag , below.  Notice that there is an empty line appended to
-# each repetition of the body.
-# This higher-order macro is used internally to define convenient, nestable
-# iterator macros.
-m4_define([jitter_define_iterator],
-  [m4_define([$1],
-             [m4_foreach(][$][1][, [$2],
-                         ][$][2][
-)])])
-# FIXME: no, this doesn't get quoting quite right.  Not using it.  Test case:
-# jitter_for_dispatch([j],
-#   [echo "quoted-[j] is unquoted-j"])
-# =>
-# echo "quoted-switch is unquoted-switch"
-# echo "quoted-direct-threading is unquoted-direct-threading"
-# echo "quoted-minimal-threading is unquoted-minimal-threading"
-# echo "quoted-no-threading is unquoted-no-threading"
-#
-# Instead, by using directly m4_foreach , I get what I want:
-# m4_foreach([i],
-#            [jitter_dispatches],
-#   [echo "quoted-[i] is unquoted-i"
-# ])
-# =>
-# echo "quoted-i is unquoted-switch"
-# echo "quoted-i is unquoted-direct-threading"
-# echo "quoted-i is unquoted-minimal-threading"
-# echo "quoted-i is unquoted-no-threading"
-
-# jitter_for_dispatch([a_dispatch_variable], [body])
-# --------------------------------------------------
-# Expand to a sequence of bodies, each copy with a_dispatch_variable replaced
-# by each of the dispatches in the order of jitter_dispatches; each body
-# repetition has a newline at the end.
-# Example:
-# jitter_for_dispatch([a],
-#   [jitter_for_dispatch([b],
-#     [echo [Here is a dispatch pair: ]a[, ]b])])
-#
-# FIXME: this commented-out definition is not correct with respect to
-# quoting: see the comment above.
-# # jitter_define_iterator([jitter_for_dispatch],
-# #                        [jitter_dispatches])
-m4_define([jitter_for_dispatch],
-  [m4_foreach([$1], [jitter_dispatches], [$2
-])])
-
-# jitter_for_flag([a_flag_variable], [body])
-# ------------------------------------------
-# Like jitter_for_dispatch, using jitter_flags instead of jitter_dispatches .
-#
-# FIXME: this commented-out definition is not correct with respect to
-# quoting: see the comment above.
-# jitter_define_iterator([jitter_for_flag],
-#                        [jitter_flags])
-m4_define([jitter_for_flag],
-  [m4_foreach([$1], [jitter_flags], [$2
-])])
-
-
-# Jitter global definitions.
-################################################################
-
-# jitter_dispatches
-# -----------------
-# An M4 quoted list of every existing Jitter dispatch, including the ones which
-# are not enabled, lower-case with dashes.
-m4_define([jitter_dispatches],
-          [[switch], [direct-threading], [minimal-threading], [no-threading]])
-
-# jitter_flags
-# ------------
-# An M4 quoted list of flag names, lower-case with dashes.
-m4_define([jitter_flags],
-          [[cflags], [cppflags], [ldadd], [ldflags]])
-
-
-# Jitter internal Autoconf macros.
-################################################################
-
-# The Autoconf macros in this section are subject to change in the future, and
-# should not be directly invoked by the user.
-
-# AC_JITTER_USING_AUTOMAKE
-# ------------------------
-# This is only used internally.  If Automake is being used, then define
-# the shell variable ac_jitter_using_automake to "yes".
-AC_DEFUN([AC_JITTER_USING_AUTOMAKE], [
-# Define ac_jitter_using_automake to a non-empty iff the configuration system 
is
-# used Automake and well, and not just Autoconf.  I have found no documented 
way
-# of doing this, so I am relying on am__api_version being defined, which
-# happens, indirectly, when AM_INIT_AUTOMAKE is called.
-# This is not particularly related to Jitter but I found no predefined way
-# of doing it, and I'm adding the variable to the Jitter namespace just so as
-# not to pollute the generic ones.
-if test "x$am__api_version" != "x"; then
-  ac_jitter_using_automake="yes"
-fi
-]) # AC_JITTER_USING_AUTOMAKE
-
-
-# Jitter exported Autoconf macros.
-################################################################
-
-# AC_JITTER_CONFIG
-# ----------------
-# Look for the jitter-config script, by default in $PATH or, if the option
-# --with-jitter="PREFIX" is given, in PREFIX/bin (only).
-#
-# Define the substitution JITTER_CONFIG to either the full pathname of a
-# jitter-config script which appears to be working, or nothing in case of
-# problems.
-# When Automake is used, also define the following Automake conditional:
-# * JITTER_HAVE_JITTER_CONFIG  (true iff jitter-config has been found).
-#
-# In case jitter-config is found, also substitute:
-# * JITTER_CONFIG_VERSION      (the version of Jitter the jitter-config script
-#                               comes from)
-# * JITTER_DISPATCHES          (all the enabled dispatched, small caps, with
-#                               dashes separating words, one space separating
-#                               dispatch names);
-# * JITTER_BEST_DISPATCH       (the best dispatch in JITTER_DISPATCHES);
-# * for every dispatching model $D (in all caps, with underscores separating
-#   words):
-#   - JITTER_$D_CFLAGS         (CFLAGS for using $D);
-#   - JITTER_$D_CPPFLAGS       (CPPFLAGS for using $D);
-#   - JITTER_$D_LDADD          (LDADD for using $D);
-#   - JITTER_$D_LDFLAGS        (LDFLAGS for using $D).
-#
-# When Automake is used, also define the following Automake conditionals
-# for each dispatching model $D (in all caps, with underscores separating
-# words):
-# * JITTER_ENABLE_DISPATCH_$D  (true iff $D is enabled).
-AC_DEFUN([AC_JITTER_CONFIG], [
-# I'd like to define Automake conditionals later on, but that only works if
-# the project is actually using Automake.
-AC_REQUIRE([AC_JITTER_USING_AUTOMAKE])
-
-# Every test from now on is about C.
-AC_LANG_PUSH([C])
-
-# In order to compile Jittery VMs we need a recent C compiler; actually
-# I've never tested on anything as old as C99, and that doesn't seem to
-# be supported by Autoconf yet.  Let's at least test for C99 and give a
-# warning if something is not okay.
-AC_REQUIRE([AC_PROG_CC])  # This defines EXEEXT .
-AC_REQUIRE([AC_PROG_CC_C99])
-if test "x$ac_cv_prog_cc_c99" = "no"; then
-  AC_MSG_WARN([the C compiler $CC does not seem to support C99.  I will
-               try to go on, but there may be problems])
-fi
-
-# Provide an option for the user to explicitly set the prefix to
-# bin/jitter .  ac_jitter_path will be defined as either the given
-# path with "/bin" appended, or $PATH.
-AC_ARG_WITH([jitter],
-            [AS_HELP_STRING([--with-jitter="PREFIX"],
-               [use the jitter program from the bin directory of the given
-                prefix instead of searching for it in $PATH])],
-            [ac_jitter_path="$withval/bin"])
-
-# Search for the "jitter-config" script and perform the JITTER_CONFIG
-# substitution.
-AC_PATH_PROG([JITTER_CONFIG],
-             [jitter-config],
-             ,
-             [$ac_jitter_path])
-
-# However jitter-config was found, verify that it can be used; if not, unset 
the
-# JITTER_CONFIG variable (and substitution).
-AS_IF([test "x$JITTER_CONFIG" = "x"],
-        [AC_MSG_NOTICE([can't find jitter-config])],
-      [! test -r "$JITTER_CONFIG"],
-        [AC_MSG_WARN([can't read jitter-config at $JITTER_CONFIG])
-         JITTER_CONFIG=""],
-      [! test -x "$JITTER_CONFIG"],
-        [AC_MSG_WARN([can't execute jitter-config at $JITTER_CONFIG])
-         JITTER_CONFIG=""],
-      [! "$JITTER_CONFIG" --best-dispatch > /dev/null 2> /dev/null],
-        [AC_MSG_WARN([non-working jitter-config at $JITTER_CONFIG])
-         JITTER_CONFIG=""])
-
-# Define the Automake conditional JITTER_HAVE_JITTER_CONFIG , if we are using
-# Automake.
-if test "x$ac_jitter_using_automake" != "x"; then
-  AM_CONDITIONAL([JITTER_HAVE_JITTER_CONFIG],
-                 [test "x$JITTER_CONFIG" != "x"])
-fi
-
-# At this point $JITTER_CONFIG is either the full pathname to an apparently
-# working script, or empty.  If it seems to work, use it to define the rest of
-# the substitutions.
-if test "x$JITTER_CONFIG" != "x"; then
-  # Define the jitter-config version.
-  AC_SUBST([JITTER_CONFIG_VERSION],
-           [$("$JITTER_CONFIG" --dump-version)])
-
-  # Define the list of enabled dispatching models.
-  AC_SUBST([JITTER_DISPATCHES],
-           [$("$JITTER_CONFIG" --dispatches)])
-  AC_MSG_NOTICE([the available Jitter dispatching models are 
$JITTER_DISPATCHES])
-
-  # Define the best dispatching model.
-  AC_SUBST([JITTER_BEST_DISPATCH],
-           [$("$JITTER_CONFIG" --best-dispatch)])
-  AC_MSG_NOTICE([the best Jitter dispatching model is $JITTER_BEST_DISPATCH])
-
-  # Define flags for the best dispatching model.
-  jitter_for_flag([a_flag],
-    [AC_SUBST([JITTER_]jitter_tocpp(a_flag),
-              [$("$JITTER_CONFIG" --a_flag)])])
-
-  # For every dispatch and flag define a substitution JITTER_$dispatch_$flag .
-  jitter_for_dispatch([a_dispatch],
-    [if "$JITTER_CONFIG" --has-dispatch=a_dispatch; then
-       jitter_for_flag([a_flag],
-         [AC_SUBST([JITTER_]jitter_tocpp(a_dispatch)[_]jitter_tocpp(a_flag),
-                   [$("$JITTER_CONFIG" --dispatch=a_dispatch --a_flag)])])
-     fi])
-fi # ...if jitter-config exists and works
-
-# If using Automake then for every dispatch, define an Automake conditional
-# telling whether it's enabled.  This has to be done even if we couldn't find a
-# usable jitter-config , since Automake conditionals must be always defined:
-# they do not default to false.
-if test "x$ac_jitter_using_automake" != "x"; then
-  jitter_for_dispatch([a_dispatch],
-    [AM_CONDITIONAL([JITTER_ENABLE_DISPATCH_]jitter_tocpp(a_dispatch),
-                    [   test "x$JITTER_CONFIG" != "x" \
-                     && "$JITTER_CONFIG" --has-dispatch=]a_dispatch)])
-fi
-
-# We're done testing C features, for the time being.
-AC_LANG_POP([C])
-]) # AC_JITTER_CONFIG
-
-
-# AC_JITTER_C_GENERATOR
-# ---------------------
-# Look for jitter, the C code generator program in $PATH if the option
-# --with-jitter="PREFIX" is given, in DIRECTORY/bin (only).
-#
-# Substitute:
-# * JITTER                            (the jitter program full path, or empty
-#                                      if not found)
-# * JITTER_VERSION                    (the version of Jitter the C generator
-#                                      program comes from)
-#
-# When Automake is used, also define the following Automake conditional:
-# * JITTER_HAVE_JITTER_C_GENERATOR    (true iff jitter has been found).
-AC_DEFUN([AC_JITTER_C_GENERATOR], [
-# Check for a C compiler, if it hasn't been done already.  This defines EXEEXT 
.
-AC_REQUIRE([AC_PROG_CC])
-
-# I'd like to define an Automake conditional later on, but that only works if
-# the project is actually using Automake.
-AC_REQUIRE([AC_JITTER_USING_AUTOMAKE])
-
-# Search for the "jitter" program and perform the JITTER substitution.
-AC_PATH_PROG([JITTER],
-             [jitter],
-             ,
-             [$ac_jitter_path:$PATH])
-
-# However jitter was found, verify that it can be used; if not, unset the 
JITTER
-# variable (and substitution).
-AS_IF([test "x$JITTER" = "x"],
-        [AC_MSG_NOTICE([can't find jitter])],
-      [! test -r "$JITTER"],
-        [AC_MSG_WARN([can't read jitter at $JITTER])
-         JITTER=""],
-      [! test -x "$JITTER"],
-        [AC_MSG_WARN([can't execute jitter at $JITTER])
-         JITTER=""],
-      [! "$JITTER" --dump-version > /dev/null],
-        [AC_MSG_WARN([jitter at $JITTER seems to fail])
-         JITTER=""])
-
-# Define the Automake conditional JITTER_HAVE_JITTER_C_GENERATOR , if we are
-# using Automake.
-if test "x$ac_jitter_using_automake" != "x"; then
-  AM_CONDITIONAL([JITTER_HAVE_JITTER_C_GENERATOR],
-                 [test "x$JITTER" != "x"])
-fi
-
-# If we found a C generator, make the other substitutions.
-if test "x$JITTER" != "x"; then
-  # Define the Jitter C generator version.
-  AC_SUBST([JITTER_VERSION],
-           [$("$JITTER" --dump-version)])
-fi
-]) # AC_JITTER_C_GENERATOR
-
-
-# AC_JITTER
-# ---------
-# Check for jitter-config and jitter as by calling both AC_JITTER_CONFIG
-# and AC_JITTER_C_GENERATOR , performing the same substitutions and
-# supporting the same command-line options.
-# Warn if jitter-config and jitter have different versions.
-#
-# This is the only macro the user needs to call to check for a Jitter
-# installation, in most cases.
-AC_DEFUN([AC_JITTER], [
-
-# Check for jitter-config .
-AC_REQUIRE([AC_JITTER_CONFIG])
-
-# Check for jitter .
-AC_REQUIRE([AC_JITTER_C_GENERATOR])
-
-# In case we found both, check that their two versions match.
-if test "x$JITTER_CONFIG" != "x" && test "x$JITTER" != "x"; then
-  if test "x$JITTER_CONFIG_VERSION" != "x$JITTER_VERSION"; then
-    AC_MSG_WARN([version mismatch between $JITTER_CONFIG (version
-$JITTER_CONFIG_VERSION) and $JITTER (version $JITTER_VERSION)])
-  fi
-fi
-]) # AC_JITTER
diff --git a/bootstrap.conf b/bootstrap.conf
index b1b0865..8f33e1b 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -63,3 +63,18 @@ if test $gettext_external = 1; then
       m4/xsize.m4
   '
 fi
+
+
+# We have to import Jitter early on, *before* running autoconf on Poke, since
+# Poke's configure.ac requires the Autoconf macros to be copied from Jitter.
+bootstrap_post_import_hook ()
+{
+  echo 'Updating the Jitter submodule'
+  git submodule update --init -- ./jitter
+
+  echo 'Bootstrapping Jitter'
+  (cd jitter && ./bootstrap --gnulib-srcdir=../gnulib --no-git)
+
+  echo 'Importing Autoconf macros from Jitter...'
+  cp jitter/autoconf/jitter.m4 m4/
+}
diff --git a/configure.ac b/configure.ac
index d3a0b37..5e4c651 100644
--- a/configure.ac
+++ b/configure.ac
@@ -26,6 +26,10 @@ AM_INIT_AUTOMAKE
 AC_CONFIG_HEADERS(src/config.h)
 AC_CONFIG_MACRO_DIR([m4])
 
+# Include the Autoconf macros from Jitter.
+m4_include([m4/jitter.m4])
+
+
 dnl Autobuild
 dnl AB_INIT
 
@@ -62,13 +66,7 @@ PKG_CHECK_MODULES(BDW_GC,[bdw-gc])
 
 dnl Jitter
 
-AC_JITTER
-if test "x$JITTER" = "x"; then
-   AC_MSG_WARN([you need Jitter to regenerate C files])
-fi
-if test "x$JITTER_CONFIG" = "x"; then
-   AC_MSG_ERROR([you need jitter-config to compile])
-fi
+AC_JITTER_SUBPACKAGE([jitter])
 
 dnl Used in Makefile.am.  See the note there.
 WITH_JITTER=$with_jitter
@@ -80,9 +78,7 @@ dnl following macro is also supposed to work when 
cross-compiling.
 AC_C_BIGENDIAN
 
 dnl --{enable,disable}-debug controls whether building poke in
-dnl debug mode.  In particular, this causes using a more inefficient
-dnl jitter model that keeps the dwarf info of the instruction
-dnl bodies.
+dnl debug mode.
 
 AC_ARG_ENABLE([debug],
               AS_HELP_STRING([--enable-debug],
diff --git a/src/Makefile.am b/src/Makefile.am
index 500c684..13fff4c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -76,17 +76,10 @@ poke_LDFLAGS =
 
 # Integration with jitter.
 
-if POKE_DEBUG
-  poke_CPPFLAGS += $(JITTER_DIRECT_THREADING_CPPFLAGS)
-  poke_CFLAGS += $(JITTER_DIRECT_THREADING_CFLAGS)
-  poke_LDADD += $(JITTER_DIRECT_THREADING_LDADD)
-  poke_LDFLAGS += $(JITTER_DIRECT_THREADING_LDFLAGS)
-else
-  poke_CPPFLAGS += $(JITTER_CPPFLAGS)
-  poke_CFLAGS += $(JITTER_CFLAGS)
-  poke_LDADD += $(JITTER_LDADD)
-  poke_LDFLAGS += $(JITTER_LDFLAGS)
-endif
+poke_CPPFLAGS += $(JITTER_CPPFLAGS)
+poke_CFLAGS += $(JITTER_CFLAGS)
+poke_LDADD += $(JITTER_LDADD)
+poke_LDFLAGS += $(JITTER_LDFLAGS)
 
 BUILT_SOURCES += pvm-vm.h pvm-vm1.c pvm-vm2.c
 
diff --git a/src/pk-cmd.c b/src/pk-cmd.c
index 9b46349..980efd2 100644
--- a/src/pk-cmd.c
+++ b/src/pk-cmd.c
@@ -353,17 +353,17 @@ pk_cmd_exec_1 (char *str, struct pk_trie *cmds_trie, char 
*prefix)
                 case 'e':
                   {
                     /* Compile a poke program.  */
-                    pvm_program prog;
+                    pvm_routine routine;
                     char *end;
                     char *program_string;
 
                     program_string = p;
-                    prog = pkl_compile_expression (poke_compiler,
-                                                   program_string, &end,
-                                                   &pointers);
-                    if (prog != NULL)
+                    routine = pkl_compile_expression (poke_compiler,
+                                                      program_string, &end,
+                                                      &pointers);
+                    if (routine != NULL)
                       {
-                        argv[argc].val.prog = prog;
+                        argv[argc].val.routine = routine;
                         match = 1;
 
                         argv[argc].type = PK_CMD_ARG_EXP;
@@ -572,7 +572,7 @@ pk_cmd_exec_1 (char *str, struct pk_trie *cmds_trie, char 
*prefix)
       if (argv[i].type == PK_CMD_ARG_EXP
           || argv[i].type == PK_CMD_ARG_DEF
           || argv[i].type == PK_CMD_ARG_STMT)
-        pvm_destroy_program (argv[i].val.prog);
+        pvm_destroy_routine (argv[i].val.routine);
     }
 
   return ret;
diff --git a/src/pk-cmd.h b/src/pk-cmd.h
index 640e2ca..c864251 100644
--- a/src/pk-cmd.h
+++ b/src/pk-cmd.h
@@ -21,7 +21,7 @@
 
 #include <config.h>
 
-#include "pvm.h" /* For pvm_program */
+#include "pvm.h" /* For pvm_routine */
 #include "ios.h"
 
 enum pk_cmd_arg_type
@@ -37,9 +37,9 @@ enum pk_cmd_arg_type
 };
 
 #define PK_CMD_ARG_TYPE(arg) ((arg).type)
-#define PK_CMD_ARG_EXP(arg) ((arg).val.prog)
-#define PK_CMD_ARG_DEF(arg) ((arg).val.prog)
-#define PK_CMD_ARG_STMT(arg) ((arg).val.prog)
+#define PK_CMD_ARG_EXP(arg) ((arg).val.routine)
+#define PK_CMD_ARG_DEF(arg) ((arg).val.routine)
+#define PK_CMD_ARG_STMT(arg) ((arg).val.routine)
 #define PK_CMD_ARG_INT(arg) ((arg).val.integer)
 #define PK_CMD_ARG_ADDR(arg) ((arg).val.addr)
 #define PK_CMD_ARG_STR(arg) ((arg).val.str)
@@ -50,7 +50,7 @@ struct pk_cmd_arg
   enum pk_cmd_arg_type type;
   union
   {
-    pvm_program prog;
+    pvm_routine routine;
     int64_t integer;
     ios_off addr;
     char *str;
diff --git a/src/pk-print.c b/src/pk-print.c
index b22e78c..541c3d3 100644
--- a/src/pk-print.c
+++ b/src/pk-print.c
@@ -36,7 +36,7 @@ pk_cmd_print (int argc, struct pk_cmd_arg argv[], uint64_t 
uflags)
 {
   /* print EXP */
 
-  pvm_program prog;
+  pvm_routine routine;
   pvm_val val;
   int pvm_ret;
   int base;
@@ -45,7 +45,7 @@ pk_cmd_print (int argc, struct pk_cmd_arg argv[], uint64_t 
uflags)
   assert (argc == 1);
   assert (PK_CMD_ARG_TYPE (argv[0]) == PK_CMD_ARG_EXP);
 
-  prog = PK_CMD_ARG_EXP (argv[0]);
+  routine = PK_CMD_ARG_EXP (argv[0]);
 
   /* Numeration base to use while printing values.  Default is
      decimal.  Command flags can be used to change this.  */
@@ -68,7 +68,7 @@ pk_cmd_print (int argc, struct pk_cmd_arg argv[], uint64_t 
uflags)
   if (uflags & PK_PRINT_F_MAP)
     pflags |= PVM_PRINT_F_MAPS;
 
-  pvm_ret = pvm_run (poke_vm, prog, &val);
+  pvm_ret = pvm_run (poke_vm, routine, &val);
   if (pvm_ret != PVM_EXIT_OK)
     goto rterror;
 
diff --git a/src/pk-vm.c b/src/pk-vm.c
index 8c23d70..1021e25 100644
--- a/src/pk-vm.c
+++ b/src/pk-vm.c
@@ -31,18 +31,18 @@ pk_cmd_vm_disas_exp (int argc, struct pk_cmd_arg argv[], 
uint64_t uflags)
 {
   /* disassemble expression EXP.  */
 
-  pvm_program prog;
+  pvm_routine routine;
 
   assert (argc == 1);
   assert (PK_CMD_ARG_TYPE (argv[0]) == PK_CMD_ARG_EXP);
 
-  prog = PK_CMD_ARG_EXP (argv[0]);
+  routine = PK_CMD_ARG_EXP (argv[0]);
 
   if (uflags & PK_VM_DIS_F_NAT)
-    pvm_disassemble_program (prog, true,
+    pvm_disassemble_routine (routine, true,
                              JITTER_OBJDUMP, NULL);
   else
-    pvm_print_program (stdout, prog);
+    pvm_routine_print (stdout, routine);
 
   return 1;
 }
@@ -54,7 +54,7 @@ pk_cmd_vm_disas_fun (int argc, struct pk_cmd_arg argv[], 
uint64_t uflags)
 
   const char *fname;
   pkl_ast_node decl;
-  pvm_program prog;
+  pvm_routine routine;
   int back, over;
   pvm_val val;
 
@@ -89,13 +89,13 @@ pk_cmd_vm_disas_fun (int argc, struct pk_cmd_arg argv[], 
uint64_t uflags)
   val = pvm_env_lookup (runtime_env, back, over);
   assert (val != PVM_NULL);
 
-  prog = PVM_VAL_CLS_PROGRAM (val);
+  routine = PVM_VAL_CLS_ROUTINE (val);
 
   if (uflags & PK_VM_DIS_F_NAT)
-    pvm_disassemble_program (prog, true,
+    pvm_disassemble_routine (routine, true,
                              JITTER_OBJDUMP, NULL);
   else
-    pvm_print_program (stdout, prog);
+    pvm_routine_print (stdout, routine);
 
   return 1;
 }
@@ -107,13 +107,13 @@ pk_cmd_vm_disas_map (int argc, struct pk_cmd_arg argv[], 
uint64_t uflags)
 
   pvm_val exp;
   pvm_val mapper;
-  pvm_program program;
+  pvm_routine routine;
 
   assert (argc == 1);
   assert (PK_CMD_ARG_TYPE (argv[0]) == PK_CMD_ARG_EXP);
 
-  program = PK_CMD_ARG_EXP (argv[0]);
-  if (pvm_run (poke_vm, program, &exp) != PVM_EXIT_OK)
+  routine = PK_CMD_ARG_EXP (argv[0]);
+  if (pvm_run (poke_vm, routine, &exp) != PVM_EXIT_OK)
     return 0;
 
   mapper = pvm_val_mapper (exp);
@@ -126,13 +126,13 @@ pk_cmd_vm_disas_map (int argc, struct pk_cmd_arg argv[], 
uint64_t uflags)
       return 0;
     }
 
-  program = PVM_VAL_CLS_PROGRAM (mapper);
+  routine = PVM_VAL_CLS_ROUTINE (mapper);
 
   if (uflags & PK_VM_DIS_F_NAT)
-    pvm_disassemble_program (program, true,
+    pvm_disassemble_routine (routine, true,
                              JITTER_OBJDUMP, NULL);
   else
-    pvm_print_program (stdout, program);
+    pvm_routine_print (stdout, routine);
 
   return 1;
 }
@@ -144,13 +144,13 @@ pk_cmd_vm_disas_writ (int argc, struct pk_cmd_arg argv[], 
uint64_t uflags)
 
   pvm_val exp;
   pvm_val writer;
-  pvm_program program;
+  pvm_routine routine;
 
   assert (argc == 1);
   assert (PK_CMD_ARG_TYPE (argv[0]) == PK_CMD_ARG_EXP);
 
-  program = PK_CMD_ARG_EXP (argv[0]);
-  if (pvm_run (poke_vm, program, &exp) != PVM_EXIT_OK)
+  routine = PK_CMD_ARG_EXP (argv[0]);
+  if (pvm_run (poke_vm, routine, &exp) != PVM_EXIT_OK)
     return 0;
 
   writer = pvm_val_writer (exp);
@@ -163,13 +163,13 @@ pk_cmd_vm_disas_writ (int argc, struct pk_cmd_arg argv[], 
uint64_t uflags)
       return 0;
     }
 
-  program = PVM_VAL_CLS_PROGRAM (writer);
+  routine = PVM_VAL_CLS_ROUTINE (writer);
 
   if (uflags & PK_VM_DIS_F_NAT)
-    pvm_disassemble_program (program, true,
+    pvm_disassemble_routine (routine, true,
                              JITTER_OBJDUMP, NULL);
   else
-    pvm_print_program (stdout, program);
+    pvm_routine_print (stdout, routine);
 
   return 1;
 }
diff --git a/src/pkl-asm.c b/src/pkl-asm.c
index cdbc8aa..d010f22 100644
--- a/src/pkl-asm.c
+++ b/src/pkl-asm.c
@@ -91,12 +91,12 @@ struct pkl_asm_level
 
    COMPILER is the PKL compiler using the macro-assembler.
 
-   PROGRAM is the PVM program being assembled.
+   ROUTINE is the PVM routine being assembled.
 
    POINTERS is an array of pointers.  Pointers to literal boxed
    instruction arguments are collected and returned to the caller.
    This is to make it possible for callers to garbage-collect these
-   values in the entities containing pvm_programs (such as closures.)
+   values in the entities containing pvm_routines (such as closures.)
 
    NEXT_POINTER is the next available slot in POINTERS.
 
@@ -114,7 +114,7 @@ struct pkl_asm
 {
   pkl_compiler compiler;
 
-  pvm_program program;
+  pvm_routine routine;
   void **pointers;
   int next_pointer;
 
@@ -174,15 +174,15 @@ pkl_asm_poplevel (pkl_asm pasm)
   pasm->level = level->parent;
 }
 
-/* Append instructions to PROGRAM to push VAL into the stack.  */
+/* Append instructions to ROUTINE to push VAL into the stack.  */
 
 static inline void
-pkl_asm_push_val (pvm_program program, pvm_val val)
+pkl_asm_push_val (pvm_routine routine, pvm_val val)
 {
 #if __WORDSIZE == 64
-  PVM_APPEND_INSTRUCTION (program, push);
-  pvm_append_unsigned_literal_parameter (program,
-                                         (jitter_uint) val);
+  PVM_ROUTINE_APPEND_INSTRUCTION (routine, push);
+  pvm_routine_append_unsigned_literal_parameter (routine,
+                                                 (jitter_uint) val);
 #else
   /* Use the push-hi and push-lo instructions, to overcome jitter's
      limitation of only accepting a jitter_uint value as a literal
@@ -190,19 +190,22 @@ pkl_asm_push_val (pvm_program program, pvm_val val)
 
   if (val & ~0xffffffffLL)
     {
-      PVM_APPEND_INSTRUCTION (program, pushhi);
-      pvm_append_unsigned_literal_parameter (program,
-                                             ((jitter_uint) (val >> 32)));
-
-      PVM_APPEND_INSTRUCTION (program, pushlo);
-      pvm_append_unsigned_literal_parameter (program,
-                                             ((jitter_uint) (val & 
0xffffffff)));
+      PVM_ROUTINE_APPEND_INSTRUCTION (routine, pushhi);
+      pvm_routine_append_unsigned_literal_parameter (routine,
+                                                     ((jitter_uint)
+                                                      (val >> 32)));
+
+      PVM_ROUTINE_APPEND_INSTRUCTION (routine, pushlo);
+      pvm_routine_append_unsigned_literal_parameter (routine,
+                                                     ((jitter_uint)
+                                                      (val & 0xffffffff)));
     }
   else
     {
-      PVM_APPEND_INSTRUCTION (program, push32);
-      pvm_append_unsigned_literal_parameter (program,
-                                             ((jitter_uint) (val & 
0xffffffff)));
+      PVM_ROUTINE_APPEND_INSTRUCTION (routine, push32);
+      pvm_routine_append_unsigned_literal_parameter (routine,
+                                                     ((jitter_uint)
+                                                      (val & 0xffffffff)));
     }
 #endif
 }
@@ -967,23 +970,23 @@ pkl_asm_insn_bnz (pkl_asm pasm,
 }
 
 /* Create a new instance of an assembler.  This initializes a new
-   program.  */
+   routine.  */
 
 pkl_asm
 pkl_asm_new (pkl_ast ast, pkl_compiler compiler,
              int prologue)
 {
   pkl_asm pasm = pvm_alloc (sizeof (struct pkl_asm));
-  pvm_program program;
+  pvm_routine routine;
 
   memset (pasm, 0, sizeof (struct pkl_asm));
   pkl_asm_pushlevel (pasm, PKL_ASM_ENV_NULL);
 
   pasm->compiler = compiler;
   pasm->ast = ast;
-  program = pvm_make_program ();
-  pasm->error_label = jitter_fresh_label (program);
-  pasm->program = program;
+  routine = pvm_make_routine ();
+  pasm->error_label = jitter_fresh_label (routine);
+  pasm->routine = routine;
 
   pasm->pointers = pvm_alloc (sizeof (void*) * PKL_AST_MAX_POINTERS);
   memset (pasm->pointers, 0, sizeof (void*) * PKL_AST_MAX_POINTERS);
@@ -1012,26 +1015,26 @@ pkl_asm_new (pkl_ast ast, pkl_compiler compiler,
   return pasm;
 }
 
-/* Finish the assembly of the current program and return it.  This
+/* Finish the assembly of the current routine and return it.  This
    function frees all resources used by the assembler instance, and
    `pkl_asm_new' should be called again in order to assemble another
-   program.  */
+   routine.  */
 
-pvm_program
+pvm_routine
 pkl_asm_finish (pkl_asm pasm, int epilogue, void **pointers)
 {
-  pvm_program program = pasm->program;
+  pvm_routine routine = pasm->routine;
 
   if (epilogue)
     {
       pkl_asm_note (pasm, "#begin epilogue");
 
-      /* Successful program finalization.  */
+      /* Successful routine finalization.  */
       pkl_asm_insn (pasm, PKL_INSN_POPE);
       pkl_asm_insn (pasm, PKL_INSN_PUSH, pvm_make_int (PVM_EXIT_OK, 32));
       pkl_asm_insn (pasm, PKL_INSN_EXIT);
 
-      pvm_append_label (pasm->program, pasm->error_label);
+      pvm_routine_append_label (pasm->routine, pasm->error_label);
 
       /* Default exception handler.  If we are bootstrapping the
          compiler, then use a very simple one inlined here in
@@ -1061,12 +1064,12 @@ pkl_asm_finish (pkl_asm pasm, int epilogue, void 
**pointers)
   /* Free the first level.  */
   pkl_asm_poplevel (pasm);
 
-  /* Free the assembler instance and return the assembled program to
+  /* Free the assembler instance and return the assembled routine to
      the user.  */
-  return program;
+  return routine;
 }
 
-/* Assemble an instruction INSN and append it to the program being
+/* Assemble an instruction INSN and append it to the routine being
    assembled in PASM.  If the instruction takes any argument, they
    follow after INSN.  */
 
@@ -1106,17 +1109,17 @@ pkl_asm_insn (pkl_asm pasm, enum pkl_asm_insn insn, ...)
 
       /* Due to some jitter limitations, we have to do some additional
          work.  See the docstring for `pkl_asm_push_val' - above.  */
-      pkl_asm_push_val (pasm->program, val);
+      pkl_asm_push_val (pasm->routine, val);
     }
   else if (insn < PKL_INSN_MACRO)
     {
       /* This is a PVM instruction.  Process its arguments and append
-         it to the jitter program.  */
+         it to the jitter routine.  */
 
       const char *insn_name = insn_names[insn];
       const char *p;
 
-      pvm_append_instruction_name (pasm->program, insn_name);
+      pvm_routine_append_instruction_name (pasm->routine, insn_name);
 
       va_start (valist, insn);
       for (p = insn_args[insn]; *p != '\0'; ++p)
@@ -1129,14 +1132,15 @@ pkl_asm_insn (pkl_asm pasm, enum pkl_asm_insn insn, ...)
               {
                 pvm_val val = va_arg (valist, pvm_val);
                 /* XXX: this doesn't work in 32-bit  */
-                pvm_append_unsigned_literal_parameter (pasm->program,
-                                                       (jitter_uint) val);
+                pvm_routine_append_unsigned_literal_parameter (pasm->routine,
+                                                               (jitter_uint)
+                                                               val);
                 break;
               }
             case 'n':
               {
                 jitter_uint n = va_arg (valist, jitter_uint);
-                pvm_append_unsigned_literal_parameter (pasm->program, n);
+                pvm_routine_append_unsigned_literal_parameter (pasm->routine, 
n);
                 break;
               }
             case 'a':
@@ -1145,7 +1149,7 @@ pkl_asm_insn (pkl_asm pasm, enum pkl_asm_insn insn, ...)
             case 'l':
               {
                 jitter_label label = va_arg (valist, jitter_label);
-                pvm_append_label_parameter (pasm->program, label);
+                pvm_routine_append_label_parameter (pasm->routine, label);
                 break;
               }
             case 'i':
@@ -1154,7 +1158,7 @@ pkl_asm_insn (pkl_asm pasm, enum pkl_asm_insn insn, ...)
             case 'r':
               {
                 jitter_uint reg = va_arg (valist, jitter_uint);
-                PVM_APPEND_REGISTER_PARAMETER (pasm->program, r, reg);
+                PVM_ROUTINE_APPEND_REGISTER_PARAMETER (pasm->routine, r, reg);
                 break;
               }
             }
@@ -1450,8 +1454,8 @@ pkl_asm_if (pkl_asm pasm, pkl_ast_node exp)
 {
   pkl_asm_pushlevel (pasm, PKL_ASM_ENV_CONDITIONAL);
 
-  pasm->level->label1 = jitter_fresh_label (pasm->program);
-  pasm->level->label2 = jitter_fresh_label (pasm->program);
+  pasm->level->label1 = jitter_fresh_label (pasm->routine);
+  pasm->level->label2 = jitter_fresh_label (pasm->routine);
   pasm->level->node1 = ASTREF (exp);
 }
 
@@ -1473,7 +1477,7 @@ pkl_asm_else (pkl_asm pasm)
   assert (pasm->level->current_env == PKL_ASM_ENV_CONDITIONAL);
 
   pkl_asm_insn (pasm, PKL_INSN_BA, pasm->level->label2);
-  pvm_append_label (pasm->program, pasm->level->label1);
+  pvm_routine_append_label (pasm->routine, pasm->level->label1);
   /* Pop the expression condition from the stack.  */
   pkl_asm_insn (pasm, PKL_INSN_DROP);
 }
@@ -1482,7 +1486,7 @@ void
 pkl_asm_endif (pkl_asm pasm)
 {
   assert (pasm->level->current_env == PKL_ASM_ENV_CONDITIONAL);
-  pvm_append_label (pasm->program, pasm->level->label2);
+  pvm_routine_append_label (pasm->routine, pasm->level->label2);
 
   /* Cleanup and pop the current level.  */
   pkl_ast_node_free (pasm->level->node1);
@@ -1514,8 +1518,8 @@ pkl_asm_try (pkl_asm pasm, pkl_ast_node arg)
 
   if (arg)
     pasm->level->node1 = ASTREF (arg);
-  pasm->level->label1 = jitter_fresh_label (pasm->program);
-  pasm->level->label2 = jitter_fresh_label (pasm->program);
+  pasm->level->label1 = jitter_fresh_label (pasm->routine);
+  pasm->level->label2 = jitter_fresh_label (pasm->routine);
 
   /* pkl_asm_note (pasm, "PUSH-REGISTERS"); */
   pkl_asm_insn (pasm, PKL_INSN_PUSHE, pasm->level->label1);
@@ -1529,7 +1533,7 @@ pkl_asm_catch (pkl_asm pasm)
   pkl_asm_insn (pasm, PKL_INSN_POPE);
   /* XXX pkl_asm_note (pasm, "POP-REGISTERS"); */
   pkl_asm_insn (pasm, PKL_INSN_BA, pasm->level->label2);
-  pvm_append_label (pasm->program, pasm->level->label1);
+  pvm_routine_append_label (pasm->routine, pasm->level->label1);
 
   /* At this point the exception number is at the top of the stack.
      If the catch block received an argument, push a new environment
@@ -1553,7 +1557,7 @@ pkl_asm_endtry (pkl_asm pasm)
   if (pasm->level->node1)
     pkl_asm_insn (pasm, PKL_INSN_POPF, 1);
 
-  pvm_append_label (pasm->program, pasm->level->label2);
+  pvm_routine_append_label (pasm->routine, pasm->level->label2);
 
   /* Cleanup and pop the current level.  */
   pkl_ast_node_free (pasm->level->node1);
@@ -1580,11 +1584,11 @@ pkl_asm_while (pkl_asm pasm)
 {
   pkl_asm_pushlevel (pasm, PKL_ASM_ENV_LOOP);
 
-  pasm->level->label1 = jitter_fresh_label (pasm->program);
-  pasm->level->label2 = jitter_fresh_label (pasm->program);
-  pasm->level->break_label = jitter_fresh_label (pasm->program);
+  pasm->level->label1 = jitter_fresh_label (pasm->routine);
+  pasm->level->label2 = jitter_fresh_label (pasm->routine);
+  pasm->level->break_label = jitter_fresh_label (pasm->routine);
 
-  pvm_append_label (pasm->program, pasm->level->label1);
+  pvm_routine_append_label (pasm->routine, pasm->level->label1);
 }
 
 void
@@ -1599,11 +1603,11 @@ void
 pkl_asm_endloop (pkl_asm pasm)
 {
   pkl_asm_insn (pasm, PKL_INSN_BA, pasm->level->label1);
-  pvm_append_label (pasm->program, pasm->level->label2);
+  pvm_routine_append_label (pasm->routine, pasm->level->label2);
   /* Pop the loop condition from the stack.  */
   pkl_asm_insn (pasm, PKL_INSN_DROP);
 
-  pvm_append_label (pasm->program, pasm->level->break_label);
+  pvm_routine_append_label (pasm->routine, pasm->level->break_label);
 
   /* Cleanup and pop the current level.  */
   pkl_asm_poplevel (pasm);
@@ -1670,10 +1674,10 @@ pkl_asm_for (pkl_asm pasm, int container_type,
 {
   pkl_asm_pushlevel (pasm, PKL_ASM_ENV_FOR_LOOP);
 
-  pasm->level->label1 = jitter_fresh_label (pasm->program);
-  pasm->level->label2 = jitter_fresh_label (pasm->program);
-  pasm->level->label3 = jitter_fresh_label (pasm->program);
-  pasm->level->break_label = jitter_fresh_label (pasm->program);
+  pasm->level->label1 = jitter_fresh_label (pasm->routine);
+  pasm->level->label2 = jitter_fresh_label (pasm->routine);
+  pasm->level->label3 = jitter_fresh_label (pasm->routine);
+  pasm->level->break_label = jitter_fresh_label (pasm->routine);
 
   if (selector)
     pasm->level->node1 = ASTREF (selector);
@@ -1685,7 +1689,7 @@ pkl_asm_for (pkl_asm pasm, int container_type,
 void
 pkl_asm_for_where (pkl_asm pasm)
 {
-  pvm_append_label (pasm->program, pasm->level->label1);
+  pvm_routine_append_label (pasm->routine, pasm->level->label1);
 
   pkl_asm_insn (pasm, PKL_INSN_PUSHF);
   pkl_asm_insn (pasm, PKL_INSN_PUSH, PVM_NULL);
@@ -1695,7 +1699,7 @@ pkl_asm_for_where (pkl_asm pasm)
   pkl_asm_insn (pasm, PKL_INSN_SWAP);
   pkl_asm_insn (pasm, PKL_INSN_PUSH, PVM_NULL);
 
-  pvm_append_label (pasm->program, pasm->level->label2);
+  pvm_routine_append_label (pasm->routine, pasm->level->label2);
 
   pkl_asm_insn (pasm, PKL_INSN_DROP);
   pkl_asm_insn (pasm, PKL_INSN_EQLU);
@@ -1740,12 +1744,12 @@ pkl_asm_for_endloop (pkl_asm pasm)
   pkl_asm_insn (pasm, PKL_INSN_PUSH, PVM_NULL);
   pkl_asm_insn (pasm, PKL_INSN_BA, pasm->level->label2);
 
-  pvm_append_label (pasm->program, pasm->level->label3);
+  pvm_routine_append_label (pasm->routine, pasm->level->label3);
 
   /* Cleanup the stack, and pop the current frame from the
      environment.  */
   pkl_asm_insn (pasm, PKL_INSN_DROP);
-  pvm_append_label (pasm->program, pasm->level->break_label);
+  pvm_routine_append_label (pasm->routine, pasm->level->break_label);
   pkl_asm_insn (pasm, PKL_INSN_DROP);
   pkl_asm_insn (pasm, PKL_INSN_DROP);
   pkl_asm_insn (pasm, PKL_INSN_DROP);
@@ -1796,11 +1800,11 @@ pkl_asm_break_label (pkl_asm pasm)
 jitter_label
 pkl_asm_fresh_label (pkl_asm pasm)
 {
-  return jitter_fresh_label (pasm->program);
+  return jitter_fresh_label (pasm->routine);
 }
 
 void
 pkl_asm_label (pkl_asm pasm, jitter_label label)
 {
-  pvm_append_label (pasm->program, label);
+  pvm_routine_append_label (pasm->routine, label);
 }
diff --git a/src/pkl-asm.h b/src/pkl-asm.h
index 5e1e687..160c106 100644
--- a/src/pkl-asm.h
+++ b/src/pkl-asm.h
@@ -29,7 +29,7 @@
 #include "pvm.h"
 
 /* The macro-assembler provides constants, enumerations, C macros and
-   functions to make it easier to program the Poke Virtual Machine.  */
+   functions to make it easier to routine the Poke Virtual Machine.  */
 
 /* The user of the assembler refers to specific instructions using the
    PKL_INSN_* symbols defined below.  See the file pkl-insn.def for
@@ -64,23 +64,23 @@ enum pkl_asm_reg
 typedef struct pkl_asm *pkl_asm;
 
 /* Create a new instance of an assembler.  This initializes a new
-   program.  */
+   routine.  */
 
 pkl_asm pkl_asm_new (pkl_ast ast, pkl_compiler compiler,
                      int prologue);
 
-/* Finish the assembly of the current program and return it.  This
+/* Finish the assembly of the current routine and return it.  This
    function frees all resources used by the assembler instance, and
    `pkl_asm_new' should be called again in order to assemble another
-   program.
+   routine.
 
    If POINTERS is not NULL, then it is an array of pointers to boxed
-   values stored in the returned program.  */
+   values stored in the returned routine.  */
 
-pvm_program pkl_asm_finish (pkl_asm pasm, int epilogue,
+pvm_routine pkl_asm_finish (pkl_asm pasm, int epilogue,
                             void **pointers);
 
-/* Assemble an instruction INSN and append it to the program being
+/* Assemble an instruction INSN and append it to the routine being
    assembled in PASM.  If the instruction takes any argument, they
    follow after INSN.  */
 
diff --git a/src/pkl-gen.c b/src/pkl-gen.c
index 24f9e52..e5974f4 100644
--- a/src/pkl-gen.c
+++ b/src/pkl-gen.c
@@ -101,7 +101,7 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_ps_program)
            && PKL_AST_CODE (PKL_AST_PROGRAM_ELEMS (PKL_PASS_NODE)) == 
PKL_AST_EXP_STMT))
     pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, PVM_NULL);
 
-  PKL_GEN_PAYLOAD->program = pkl_asm_finish (PKL_GEN_ASM,
+  PKL_GEN_PAYLOAD->routine = pkl_asm_finish (PKL_GEN_ASM,
                                              1 /* prologue */,
                                              &PKL_GEN_PAYLOAD->pointers);
 }
@@ -266,21 +266,19 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_ps_decl)
       {
         /* At this point the code for the function specification
            INITIAL has been assembled in the current macroassembler.
-           Finalize the program and put it in a PVM closure, along
+           Finalize the routine and put it in a PVM closure, along
            with the current environment.  */
 
         void *pointers;
-        pvm_program program = pkl_asm_finish (PKL_GEN_ASM,
+        pvm_routine routine = pkl_asm_finish (PKL_GEN_ASM,
                                               0 /* epilogue */,
                                               &pointers);
         pvm_val closure;
 
         PKL_GEN_POP_ASM;
-        pvm_specialize_program (program);
-        closure = pvm_make_cls (program, pointers);
-
+        closure = pvm_make_cls (routine, pointers);
         /*XXX*/
-        /* pvm_print_program (stdout, program); */
+        /* pvm_routine_print (stdout, routine); */
 
         pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, closure);
         pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC);
@@ -1923,7 +1921,7 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_pr_type_array)
       pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_DROP);                  /* _ */
 
       /* XXX */
-      /* pvm_print_program (stdout, PVM_VAL_CLS_PROGRAM (bounder_closure)); */
+      /* pvm_routine_print (stdout, PVM_VAL_CLS_ROUTINE (bounder_closure)); */
 
       PKL_AST_TYPE_A_BOUNDER (array_type) = bounder_closure;
       PKL_PASS_BREAK;
diff --git a/src/pkl-gen.h b/src/pkl-gen.h
index ab1e9c7..8bca2fd 100644
--- a/src/pkl-gen.h
+++ b/src/pkl-gen.h
@@ -44,20 +44,20 @@
    COMPILER is the Pkl compiler driving the compilation.
 
    PASM and PASM2 are stacks of macro-assemblers.  Assemblers in PASM
-   are used for assembling the main program, struct mappers, and
+   are used for assembling the main routine, struct mappers, and
    functions.  Assemblers in PASM2 are used for compiling struct
    constructors.
 
    CUR_PASM and CUR_PASM2 are the pointers to the top of PASM and
    PASM2, respectively.
 
-   PROGRAM is the main PVM program being compiled.  When the phase is
-   completed, the program is "finished" (in jitter parlance) and ready
+   ROUTINE is the main PVM routine being compiled.  When the phase is
+   completed, the routine is "finished" (in jitter parlance) and ready
    to be used.
 
    POINTERS is an array of pointers to the boxed PVM values referenced
-   in PROGRAM.  It is necessary in order to provide the GC visibility
-   into the program.
+   in ROUTINE.  It is necessary in order to provide the GC visibility
+   into the routine.
 
    IN_STRUCT_DECL is 1 when a struct declaration is being generated.
    0 otherwise.
@@ -84,7 +84,7 @@ struct pkl_gen_payload
   pkl_asm pasm2[PKL_GEN_MAX_PASM];
   int cur_pasm;
   int cur_pasm2;
-  pvm_program program;
+  pvm_routine routine;
   void *pointers;
   int in_struct_decl;
   int in_mapper;
diff --git a/src/pkl.c b/src/pkl.c
index c5672a5..6e49bc5 100644
--- a/src/pkl.c
+++ b/src/pkl.c
@@ -105,7 +105,7 @@ pkl_free (pkl_compiler compiler)
   free (compiler);
 }
 
-static pvm_program
+static pvm_routine
 rest_of_compilation (pkl_compiler compiler,
                      pkl_ast ast,
                      void **pointers)
@@ -235,7 +235,7 @@ rest_of_compilation (pkl_compiler compiler,
 
   pkl_ast_free (ast);
   *pointers = gen_payload.pointers;
-  return gen_payload.program;
+  return gen_payload.routine;
 
  error:
   pkl_ast_free (ast);
@@ -247,12 +247,12 @@ pkl_compile_buffer (pkl_compiler compiler,
                     char *buffer, char **end)
 {
   pkl_ast ast = NULL;
-  pvm_program program;
+  pvm_routine routine;
   int ret;
   pkl_env env = NULL;
 
   /* Note that the sole purpose of `pointers' is to serve as a root
-     (in the stack) for the GC, to prevent the boxed values in PROGRAM
+     (in the stack) for the GC, to prevent the boxed values in ROUTINE
      to be collected.  Ugly as shit, but conservative garbage
      collection doesn't really work.  */
   void *pointers;
@@ -260,7 +260,7 @@ pkl_compile_buffer (pkl_compiler compiler,
   compiler->compiling = PKL_COMPILING_PROGRAM;
   env = pkl_env_dup_toplevel (compiler->env);
 
-  /* Parse the input program into an AST.  */
+  /* Parse the input routine into an AST.  */
   ret = pkl_parse_buffer (compiler, &env, &ast,
                           PKL_PARSE_PROGRAM,
                           buffer, end);
@@ -271,25 +271,24 @@ pkl_compile_buffer (pkl_compiler compiler,
     /* Memory exhaustion.  */
     printf (_("out of memory\n"));
 
-  program = rest_of_compilation (compiler, ast, &pointers);
-  if (program == NULL)
+  routine = rest_of_compilation (compiler, ast, &pointers);
+  if (routine == NULL)
     goto error;
 
-  pvm_specialize_program (program);
   /* XXX */
-  /* pvm_print_program (stdout, program); */
+  /* pvm_routine_print (stdout, routine); */
 
-  /* Execute the program in the poke vm.  */
+  /* Execute the routine in the poke vm.  */
   {
     pvm_val val;
 
-    if (pvm_run (poke_vm, program, &val) != PVM_EXIT_OK)
+    if (pvm_run (poke_vm, routine, &val) != PVM_EXIT_OK)
       goto error;
 
     /* Discard the value.  */
   }
 
-  pvm_destroy_program (program);
+  pvm_destroy_routine (routine);
   pkl_env_free (compiler->env);
   compiler->env = env;
   return 1;
@@ -305,12 +304,12 @@ pkl_compile_statement (pkl_compiler compiler,
                        pvm_val *val)
 {
   pkl_ast ast = NULL;
-  pvm_program program;
+  pvm_routine routine;
   int ret;
   pkl_env env = NULL;
 
   /* Note that the sole purpose of `pointers' is to serve as a root
-     (in the stack) for the GC, to prevent the boxed values in PROGRAM
+     (in the stack) for the GC, to prevent the boxed values in ROUTINE
      to be collected.  Ugly as shit, but conservative garbage
      collection doesn't really work.  */
   void *pointers;
@@ -318,7 +317,7 @@ pkl_compile_statement (pkl_compiler compiler,
   compiler->compiling = PKL_COMPILING_STATEMENT;
   env = pkl_env_dup_toplevel (compiler->env);
 
-  /* Parse the input program into an AST.  */
+  /* Parse the input routine into an AST.  */
   ret = pkl_parse_buffer (compiler, &env, &ast,
                           PKL_PARSE_STATEMENT,
                           buffer, end);
@@ -329,19 +328,18 @@ pkl_compile_statement (pkl_compiler compiler,
     /* Memory exhaustion.  */
     printf (_("out of memory\n"));
 
-  program = rest_of_compilation (compiler, ast, &pointers);
-  if (program == NULL)
+  routine = rest_of_compilation (compiler, ast, &pointers);
+  if (routine == NULL)
     goto error;
 
-  pvm_specialize_program (program);
   /* XXX */
-  /* pvm_print_program (stdout, program); */
+  /* pvm_routine_print (stdout, routine); */
 
-  /* Execute the program in the poke vm.  */
-  if (pvm_run (poke_vm, program, val) != PVM_EXIT_OK)
+  /* Execute the routine in the poke vm.  */
+  if (pvm_run (poke_vm, routine, val) != PVM_EXIT_OK)
     goto error;
 
-  pvm_destroy_program (program);
+  pvm_destroy_routine (routine);
   pkl_env_free (compiler->env);
   compiler->env = env;
   return 1;
@@ -352,19 +350,19 @@ pkl_compile_statement (pkl_compiler compiler,
 }
 
 
-pvm_program
+pvm_routine
 pkl_compile_expression (pkl_compiler compiler,
                         char *buffer, char **end, void **pointers)
 {
   pkl_ast ast = NULL;
-  pvm_program program;
+  pvm_routine routine;
   int ret;
   pkl_env env = NULL;
 
   compiler->compiling = PKL_COMPILING_EXPRESSION;
   env = pkl_env_dup_toplevel (compiler->env);
 
-  /* Parse the input program into an AST.  */
+  /* Parse the input routine into an AST.  */
   ret = pkl_parse_buffer (compiler, &env, &ast,
                           PKL_PARSE_EXPRESSION,
                           buffer, end);
@@ -375,16 +373,15 @@ pkl_compile_expression (pkl_compiler compiler,
     /* Memory exhaustion.  */
     printf (_("out of memory\n"));
 
-  program = rest_of_compilation (compiler, ast, pointers);
-  if (program == NULL)
+  routine = rest_of_compilation (compiler, ast, pointers);
+  if (routine == NULL)
     goto error;
 
   pkl_env_free (compiler->env);
   compiler->env = env;
-  pvm_specialize_program (program);
   /* XXX */
-  /* pvm_print_program (stdout, program); */
-  return program;
+  /* pvm_routine_print (stdout, routine); */
+  return routine;
 
  error:
   pkl_env_free (env);
@@ -397,12 +394,12 @@ pkl_compile_file (pkl_compiler compiler, const char 
*fname)
 {
   int ret;
   pkl_ast ast = NULL;
-  pvm_program program;
+  pvm_routine routine;
   FILE *fd;
   pkl_env env = NULL;
 
   /* Note that the sole purpose of `pointers' is to serve as a root
-     (in the stack) for the GC, to prevent the boxed values in PROGRAM
+     (in the stack) for the GC, to prevent the boxed values in ROUTINE
      to be collected.  Ugly as shit, but conservative garbage
      collection doesn't really work.  */
   void *pointers;
@@ -427,26 +424,25 @@ pkl_compile_file (pkl_compiler compiler, const char 
*fname)
       printf (_("out of memory\n"));
     }
 
-  program = rest_of_compilation (compiler, ast, &pointers);
-  if (program == NULL)
+  routine = rest_of_compilation (compiler, ast, &pointers);
+  if (routine == NULL)
     goto error;
 
-  pvm_specialize_program (program);
   /* XXX */
-  /* pvm_print_program (stdout, program); */
+  /* pvm_routine_print (stdout, routine); */
   fclose (fd);
 
-  /* Execute the program in the poke vm.  */
+  /* Execute the routine in the poke vm.  */
   {
     pvm_val val;
 
-    if (pvm_run (poke_vm, program, &val) != PVM_EXIT_OK)
+    if (pvm_run (poke_vm, routine, &val) != PVM_EXIT_OK)
       goto error_no_close;
 
     /* Discard the value.  */
   }
 
-  pvm_destroy_program (program);
+  pvm_destroy_routine (routine);
   pkl_env_free (compiler->env);
   compiler->env = env;
   return 1;
diff --git a/src/pkl.h b/src/pkl.h
index 4a984c8..c2c65a5 100644
--- a/src/pkl.h
+++ b/src/pkl.h
@@ -48,9 +48,9 @@
    types, function etc from the user.
 
    At any point, the user can request to compile a poke expression
-   with `pkl_compile_expression'.  This returns a PVM program that,
+   with `pkl_compile_expression'.  This returns a PVM routine that,
    can be executed in a virtual machine.  It is up to the user to free
-   the returned PVM program when it is not useful anymore.
+   the returned PVM routine when it is not useful anymore.
 
    `pkl_compile_buffer', `pkl_compile_file' and
    `pkl_compile_expression' can be called any number of times, in any
@@ -88,10 +88,10 @@ int pkl_compile_statement (pkl_compiler compiler, char 
*buffer, char **end,
 
 
 /* Like pkl_compile_buffer, but compile a Poke expression and return a
-   PVM program that evaluates to the expression.  In case of error
+   PVM routine that evaluates to the expression.  In case of error
    return NULL.  */
 
-pvm_program pkl_compile_expression (pkl_compiler compiler,
+pvm_routine pkl_compile_expression (pkl_compiler compiler,
                                     char *buffer, char **end,
                                     void **pointers);
 
diff --git a/src/pvm-alloc.c b/src/pvm-alloc.c
index b3c00a0..f68b54f 100644
--- a/src/pvm-alloc.c
+++ b/src/pvm-alloc.c
@@ -36,7 +36,7 @@ static void
 pvm_alloc_finalize_closure (void *object, void *client_data)
 {
   pvm_cls cls = (pvm_cls) object;
-  pvm_destroy_program (cls->program);
+  pvm_destroy_routine (cls->routine);
 }
 
 void *
diff --git a/src/pvm-env.h b/src/pvm-env.h
index a129361..f3255d3 100644
--- a/src/pvm-env.h
+++ b/src/pvm-env.h
@@ -26,7 +26,7 @@
 
 /* The poke virtual machine (PVM) maintains a data structure called
    the run-time environment.  This structure contains run-time frames,
-   which in turn store the variables of PVM programs.
+   which in turn store the variables of PVM routines.
 
    A set of PVM instructions are provided to allow programs to
    manipulate the run-time environment.  These are implemented in
diff --git a/src/pvm-val.c b/src/pvm-val.c
index 3cd9b9f..e7a3f65 100644
--- a/src/pvm-val.c
+++ b/src/pvm-val.c
@@ -315,14 +315,14 @@ pvm_make_closure_type (pvm_val rtype,
 }
 
 pvm_val
-pvm_make_cls (pvm_program program, void **pointers)
+pvm_make_cls (pvm_routine routine, void **pointers)
 {
   pvm_val_box box = pvm_make_box (PVM_VAL_TAG_CLS);
   pvm_cls cls = pvm_alloc_cls ();
 
-  cls->program = program;
+  cls->routine = routine;
   cls->pointers = pointers;
-  cls->entry_point = PVM_PROGRAM_BEGINNING (program);
+  cls->entry_point = PVM_ROUTINE_BEGINNING (routine);
   cls->env = NULL; /* This should be set by a PEC instruction before
                       using the closure.  */
 
@@ -1137,7 +1137,7 @@ pvm_print_string (pvm_val string)
 int
 pvm_call_pretty_printer (pvm_val val, pvm_val cls)
 {
-  pvm_program program;
+  pvm_routine routine;
   int ret;
   pkl_asm pasm = pkl_asm_new (NULL /* ast */,
                               poke_compiler, 1 /* prologue */);
@@ -1153,11 +1153,10 @@ pvm_call_pretty_printer (pvm_val val, pvm_val cls)
   pkl_asm_insn (pasm, PKL_INSN_PUSH, cls);
   pkl_asm_insn (pasm, PKL_INSN_CALL);
 
-  /* Run the program in the poke VM.  */
-  program = pkl_asm_finish (pasm, 1 /* epilogue */, NULL /* pointers */);
-  pvm_specialize_program (program);
-  ret = pvm_run (poke_vm, program, NULL);
-  pvm_destroy_program (program);
+  /* Run the routine in the poke VM.  */
+  routine = pkl_asm_finish (pasm, 1 /* epilogue */, NULL /* pointers */);
+  ret = pvm_run (poke_vm, routine, NULL);
+  pvm_destroy_routine (routine);
 
   return (ret == PVM_EXIT_OK);
 }
diff --git a/src/pvm-val.h b/src/pvm-val.h
index 1f051ff..664c14c 100644
--- a/src/pvm-val.h
+++ b/src/pvm-val.h
@@ -26,6 +26,8 @@
 #include <stdint.h>
 #include <xalloc.h>
 
+#include <jitter/jitter-routine.h> /* For Jitter routine types.  See below. */
+
 /* The pvm_val opaque type implements values that are native to the
    poke virtual machine:
 
@@ -453,23 +455,30 @@ int pvm_type_equal (pvm_val type1, pvm_val type2);
 
 #define PVM_VAL_CLS(V) (PVM_VAL_BOX_CLS (PVM_VAL_BOX ((V))))
 
-#define PVM_VAL_CLS_PROGRAM(V) (PVM_VAL_CLS((V))->program)
+#define PVM_VAL_CLS_ROUTINE(V) (PVM_VAL_CLS((V))->routine)
 #define PVM_VAL_CLS_ENTRY_POINT(V) (PVM_VAL_CLS((V))->entry_point)
 #define PVM_VAL_CLS_ENV(V) (PVM_VAL_CLS((V))->env)
 
+/* The C header file generated by Jitter for PVM defines pvm_routine as an 
alias
+   for a VM-independent type abstract type named jitter_routine.  We cannot
+   include the header here without generating a CPP inclusion cycle, so for the
+   time being we resort to using the VM-independent type rather than its
+   VM-specific counterpart.  For all intents and purposes they are the same
+   type.
+   The same remark applies to pvm_program_point versus jitter_program_point. */
 struct pvm_cls
 {
-  /* Note we have to use explicit pointers here due to the include
-     mess induced by jitter's combined header files :/ */
-  struct jitter_program *program;
+  jitter_routine routine;
   void **pointers;
-  const void *entry_point;
+  jitter_program_point entry_point;
   struct pvm_env *env;
 };
 
 typedef struct pvm_cls *pvm_cls;
 
-pvm_val pvm_make_cls (struct jitter_program *program,
+/* See the comment above about our usage of jitter_routine versus
+   pvm_routine. */
+pvm_val pvm_make_cls (jitter_routine routine,
                       void **pointers);
 int pvm_call_pretty_printer (pvm_val val, pvm_val cls);
 
diff --git a/src/pvm.c b/src/pvm.c
index 7c86e1f..0ee9974 100644
--- a/src/pvm.c
+++ b/src/pvm.c
@@ -115,12 +115,12 @@ pvm_shutdown (pvm apvm)
 }
 
 enum pvm_exit_code
-pvm_run (pvm apvm, pvm_program prog, pvm_val *res)
+pvm_run (pvm apvm, pvm_routine routine, pvm_val *res)
 {
   PVM_STATE_RESULT_VALUE (apvm) = PVM_NULL;
   PVM_STATE_EXIT_CODE (apvm) = PVM_EXIT_OK;
 
-  pvm_interpret (prog, &apvm->pvm_state);
+  pvm_execute_routine (routine, &apvm->pvm_state);
 
   if (res != NULL)
     *res = PVM_STATE_RESULT_VALUE (apvm);
diff --git a/src/pvm.h b/src/pvm.h
index 6ece18c..2f186e1 100644
--- a/src/pvm.h
+++ b/src/pvm.h
@@ -28,9 +28,9 @@
 #include "pvm-alloc.h"
 
 /* The following enumeration contains every possible exit code
-   resulting from the execution of a program in the PVM.
+   resulting from the execution of a routine in the PVM.
 
-   PVM_EXIT_OK is returned if the program was executed successfully,
+   PVM_EXIT_OK is returned if the routine was executed successfully,
    and every raised exception was properly handled.
 
    PVM_EXIT_ERROR is returned in case of an unhandled exception.  */
@@ -63,12 +63,6 @@ enum pvm_exit_code
 
 typedef struct pvm *pvm;
 
-/* A PVM program can be executed in the virtual machine at any time.
-   The struct pvm_program is provided by Jitter, but we provide here
-   an opaque type to be used by the PVM users.  */
-
-typedef struct pvm_program *pvm_program;
-
 /* Initialize a new Poke Virtual Machine and return it.  */
 
 pvm pvm_init (void);
@@ -81,11 +75,11 @@ void pvm_shutdown (pvm pvm);
 
 pvm_env pvm_get_env (pvm pvm);
 
-/* Run a PVM program in a given Poke Virtual Machine.  Put the
+/* Run a PVM routine in a given Poke Virtual Machine.  Put the
    resulting value in RES, if any, and return an exit code.  */
 
 enum pvm_exit_code pvm_run (pvm pvm,
-                            pvm_program prog,
+                            pvm_routine routine,
                             pvm_val *res);
 
 /* Get and set the current endianness, negative encoding and other
diff --git a/src/ras b/src/ras
index 18a8aa1..d9149e2 100755
--- a/src/ras
+++ b/src/ras
@@ -78,7 +78,7 @@
 #
 # This translates into a C macro RAS_FUNCTION_NAME(CLOSURE), with a
 # single argument which should be an l-value.  The macro will compile
-# the function into a pvm_program, and install it into a PVM closure
+# the function into a pvm_routine, and install it into a PVM closure
 # value that is assigned to CLOSURE.
 #
 # Expanding Macros
@@ -284,7 +284,7 @@
 # Another difficulty when dealing with lexical addresses is that
 # different addresses are required to refer to the same variable,
 # depending on the context.  For example, consider the following PVM
-# program:
+# routine:
 #
 # pushf
 # regvar        ; A
@@ -588,7 +588,7 @@ BEGIN {
 
     out("#define RAS_FUNCTION_" toupper($2) "(CLOSURE)  \\")
     out("\tdo {                                         \\")
-    out("\tpvm_program program;                         \\")
+    out("\tpvm_routine routine;                         \\")
     out("\t                                             \\")
     out("\tPKL_GEN_PUSH_ASM (pkl_asm_new (PKL_PASS_AST, \\")
     out("\t                               PKL_GEN_PAYLOAD->compiler, \\")
@@ -611,12 +611,11 @@ BEGIN {
     {
         out("\t{                                                       \\")
         out("\t  void *pointers;                                       \\")
-        out("\t  program = pkl_asm_finish (RAS_ASM,                    \\")
+        out("\t  routine = pkl_asm_finish (RAS_ASM,                    \\")
         out("\t                            0 /* epilogue */,           \\")
         out("\t                            &pointers);                 \\")
         out("\t  PKL_GEN_POP_ASM;                                      \\")
-        out("\t  pvm_specialize_program (program);                     \\")
-        out("\t  (CLOSURE) = pvm_make_cls (program, pointers);         \\")
+        out("\t  (CLOSURE) = pvm_make_cls (routine, pointers);         \\")
         out("\t}                                                       \\")
     }
     out("\t} while (0)")

Attachment: signature.asc
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]