epsilon-devel
[Top][All Lists]
Advanced

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

Porting Poke to latest Jitter in sub-package mode, cleaned up version


From: Luca Saiu
Subject: Porting Poke to latest Jitter in sub-package mode, cleaned up version
Date: Tue, 05 Nov 2019 01:48:32 +0100
User-agent: Gnus (Gnus v5.13), GNU Emacs 27.0.50, x86_64-pc-linux-gnu

This should be the good version.

-- 
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 9fa1925299c7441522392b4b6e395d1e410cc4c8
Author: Luca Saiu <address@hidden>
Date:   Sun Nov 3 02:07:43 2019 +0100

    port to jitter master, introducing sub-package mode
    
    2019-11-05  Luca Saiu  <address@hidden>
    
            * HACKING: Replace "program" to "routine".  Update data
            structure description.  Update debugging and configuration
            information as related to Jitter.  Minor rewording and grammar
            fixes.
            * TODO: Change "program" to "routine".
            * Makefile.am (SUBDIRS): Add jitter.
            * acinclude.m4: Remove file.
            * bootstrap.conf (bootstrap_post_import_hook): New function.
            * configure.ac: Include m4/jitter.m4, now copied from jitter by
            bootstrap.
            (AC_JITTER): Remove along with checks.  Replace with
            AC_JITTER_SUBPACKAGE, which includes tests.
            (--enable-debug, --disable-debug): Remove options.
            (ENABLE_DEBUG): Remove variable.  Remove substitution.
            (POKE_DEBUG): Remove Automake conditional.
            * src/Makefile.am (poke_CPPFLAGS, poke_CFLAGS, poke_LDADD)
            (poke_LDFLAGS): Unconditionalize.
            * src/pvm-val.h: Change to Jitter unified routine API.
            Include jitter/jitter-routine.h to break dependency cycle.
            Add comments.
            (struct pvm_cls): Rename field program to routine, type
            from struct jitter_program * to jitter_routine.
            Change type for field entry_point from void * to
            jitter_program_point.
            (pvm_program): Remove typedef.  Now the include cycle breaking works
            differently.
            * src/pvm-val.c: Change to Jitter unified routine API.
            * src/pk-cmd.c: Change to Jitter unified routine API.
            * src/pk-cmd.h: Change to Jitter unified routine API.
            * src/pk-print.c: Change to Jitter unified routine API.
            * src/pkl-asm.c: Change to Jitter unified routine API.
            * src/pkl-gen.c: Change to Jitter unified routine API.
            * src/pkl-gen.h: Change to Jitter unified routine API.
            * src/pkl.c: Change to Jitter unified routine API.
            * src/pkl.h: Change to Jitter unified routine API.
            * src/pvm-alloc.c: Change to Jitter unified routine API.
            * src/pvm-env.h: Change to Jitter unified routine API.
            * src/pvm.c: Change to Jitter unified routine API.
            * src/pvm.h: Change to Jitter unified routine API.
            * src/ras: Change to Jitter unified routine API.

diff --git a/ChangeLog b/ChangeLog
index 013a6fa..e31d1ad 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,46 @@
+2019-11-05  Luca Saiu  <address@hidden>
+
+       * HACKING: Replace "program" to "routine".  Update data
+       structure description.  Update debugging and configuration
+       information as related to Jitter.  Minor rewording and grammar
+       fixes.
+       * TODO: Change "program" to "routine".
+       * Makefile.am (SUBDIRS): Add jitter.
+       * acinclude.m4: Remove file.
+       * bootstrap.conf (bootstrap_post_import_hook): New function.
+       * configure.ac: Include m4/jitter.m4, now copied from jitter by
+       bootstrap.
+       (AC_JITTER): Remove along with checks.  Replace with
+       AC_JITTER_SUBPACKAGE, which includes tests.
+       (--enable-debug, --disable-debug): Remove options.
+       (ENABLE_DEBUG): Remove variable.  Remove substitution.
+       (POKE_DEBUG): Remove Automake conditional.
+       * src/Makefile.am (poke_CPPFLAGS, poke_CFLAGS, poke_LDADD)
+       (poke_LDFLAGS): Unconditionalize.
+       * src/pvm-val.h: Change to Jitter unified routine API.
+       Include jitter/jitter-routine.h to break dependency cycle.
+       Add comments.
+       (struct pvm_cls): Rename field program to routine, type
+       from struct jitter_program * to jitter_routine.
+       Change type for field entry_point from void * to
+       jitter_program_point.
+       (pvm_program): Remove typedef.  Now the include cycle breaking works
+       differently.
+       * src/pvm-val.c: Change to Jitter unified routine API.
+       * src/pk-cmd.c: Change to Jitter unified routine API.
+       * src/pk-cmd.h: Change to Jitter unified routine API.
+       * src/pk-print.c: Change to Jitter unified routine API.
+       * src/pkl-asm.c: Change to Jitter unified routine API.
+       * src/pkl-gen.c: Change to Jitter unified routine API.
+       * src/pkl-gen.h: Change to Jitter unified routine API.
+       * src/pkl.c: Change to Jitter unified routine API.
+       * src/pkl.h: Change to Jitter unified routine API.
+       * src/pvm-alloc.c: Change to Jitter unified routine API.
+       * src/pvm-env.h: Change to Jitter unified routine API.
+       * src/pvm.c: Change to Jitter unified routine API.
+       * src/pvm.h: Change to Jitter unified routine API.
+       * src/ras: Change to Jitter unified routine API.
+
 2019-11-04  Jose E. Marchesi  <address@hidden>
 
        * doc/poke.texi (Structs): New chapter.
diff --git a/HACKING b/HACKING
index 0ce7b71..f714cbf 100644
--- a/HACKING
+++ b/HACKING
@@ -76,7 +76,7 @@ along with GNU poke.  If not, see 
<https://www.gnu.org/licenses/>.
     11  Memory Management
       11.1  Using ASTREF
       11.2  Using ASTDEREF
-      11.3  PVM values in PVM programs
+      11.3  PVM values in PVM routines
       11.4  PVM values in AST nodes
     12  Terminal Handling
       12.1  pk-term
@@ -224,21 +224,17 @@ Jitter
 ~~~~~~
 
 In order to build and run poke, you need Luca Saiu's jitter.  Jitter
-is available in http://ageinghacker.net/git/cgit.cgi/jitter.  You need
-a specic revision. The command to download it is::
-  
-  wget 
http://ageinghacker.net/git/cgit.cgi/jitter/snapshot/jitter-745ba29c15dd56c60a7ab0320e09c1ca705018b7.tar.xz
-
-Configure and install jitter in some prefix.  For the time being, you
-should use when configuring jitter::
-
+is available at http://ageinghacker.net/git/cgit.cgi/jitter.
 
-  --disable-dispatch-minimal-threading --disable-dispatch-no-threading
+The appropriate version of Jitter is now downloaded and bootstrapped
+automatically by Poke's ``bootstrap`` script, which frees the user
+from the annoyance of installing Jitter as a dependency.
 
-or, alternatively, use ``--enable-debug`` when configuring poke.
+Configuring and compiling Poke will also compile and configure
+Jitter in a subdirectory.  Jitter, when configured in ``sub-package
+mode`` as Poke does, only generates static libraries and requires
+no installation.
 
-When configuring poke, specify the location of the jitter installation
-with --with-jitter.
 
 libtextstyle
 ~~~~~~~~~~~~
@@ -881,48 +877,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;
@@ -933,12 +930,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
@@ -947,12 +944,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);
     ...
   }
 
@@ -960,9 +957,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,
@@ -1082,10 +1079,43 @@ Debugging Poke
 Building with Debugging support
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-Configure the sources with ``--enable-debug``.  This will:
-
-1. Use a threaded jitter dispatching model.
-2. Build the sources with ``-O0 -g3`` in CFLAGS.
+Short summary: at the present time Poke and its Jittery VM are not
+especially difficult to debug; however the situation is going to
+change as Jitter evolves and the following details will become more
+important to Poke hackers.
+
+In order to make debugging easier you may want to disable advanced
+dispatches in Jitter, which make the generated code harder to follow
+and confuse GDB.
+
+Jitter by default will use the most efficient dispatch which is both
+stable and available for the current configuration.  The remark about
+stability is important: at the time of writing there are still bugs
+in the two most advanced dispatching modes, ``minimal-threading`` and
+``no-threading``, which may result in subtly incorrect compiled code.
+For this reason Jitter disables those dispatches by default; they will
+be re-enabled in Jitter as soon as they are deemed ready for production
+use, at which point Poke will make use of them automatically.
+
+Jitter supports two alternative dispatches, slower but very stable
+and friendly to debugging: ``switch`` and ``direct-threading``.
+
+Any dispatch can be selectively enabled or disabled from the Poke
+``configure`` script, by passing the following options which will be
+automatically relayed to Jitter's ``configure`` script:
+
+- ``--enable-dispatch-switch``
+- ``--disable-dispatch-switch``
+- ``--enable-dispatch-direct-threading``
+- ``--disable-dispatch-direct-threading``
+- ``--enable-dispatch-minimal-threading``
+- ``--disable-dispatch-minimal-threading``
+- ``--enable-dispatch-no-threading``
+- ``--disable-dispatch-no-threading``
+
+When configured in sub-package mode, as is the case when used with
+Poke, Jitter will only actually compile the single most efficient
+enabled dispatch.
 
 Using GDB extensions
 ~~~~~~~~~~~~~~~~~~~~
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 3daf34b..bd91a79 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -90,3 +90,17 @@ flex        2.6.1
 gettext     0.18.2
 pkg-config  -
 "
+
+# 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 15d5a09..a666396 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
@@ -79,22 +77,6 @@ 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.
-
-AC_ARG_ENABLE([debug],
-              AS_HELP_STRING([--enable-debug],
-                             [Build poke in debug mode (default is NO)]),
-                             [poke_debug=$enableval], [poke_debug=no])
-
-ENABLE_DEBUG=$enable_debug
-AC_SUBST([ENABLE_DEBUG])
-
-AM_CONDITIONAL([POKE_DEBUG],
-               [test "x$poke_debug" = "xyes"])
-
 dnl Use libtextstyle if available.  Otherwise, use the dummy header
 dnl file provided by gnulib's libtextstyle-optional module.
 
diff --git a/src/Makefile.am b/src/Makefile.am
index 4384fe9..9af0e8c 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 bca2bfe..1ad42bc 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
 }
@@ -980,23 +983,23 @@ pkl_asm_insn_ais (pkl_asm pasm, pkl_ast_node atype)
 }
 
 /* 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);
@@ -1025,26 +1028,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
@@ -1074,12 +1077,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.  */
 
@@ -1119,17 +1122,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)
@@ -1142,14 +1145,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':
@@ -1158,7 +1162,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':
@@ -1167,7 +1171,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;
               }
             }
@@ -1474,8 +1478,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);
 }
 
@@ -1497,7 +1501,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);
 }
@@ -1506,7 +1510,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);
@@ -1538,8 +1542,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);
@@ -1553,7 +1557,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
@@ -1577,7 +1581,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);
@@ -1604,11 +1608,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
@@ -1623,11 +1627,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);
@@ -1694,10 +1698,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);
@@ -1709,7 +1713,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);
@@ -1719,7 +1723,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);
@@ -1764,12 +1768,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);
@@ -1820,11 +1824,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 10e4250..9dd1e6d 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,21 @@ 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);
+        jitter_routine_make_executable_if_needed (routine);
+        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 +1923,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..56246c3 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,25 @@ 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);
+  jitter_routine_make_executable_if_needed (routine);
   /* 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 +305,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 +318,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 +329,19 @@ 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);
+  jitter_routine_make_executable_if_needed (routine);
   /* 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 +352,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 +375,16 @@ 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);
+  jitter_routine_make_executable_if_needed (routine);
   /* XXX */
-  /* pvm_print_program (stdout, program); */
-  return program;
+  /* pvm_routine_print (stdout, routine); */
+  return routine;
 
  error:
   pkl_env_free (env);
@@ -397,12 +397,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 +427,26 @@ 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);
+  jitter_routine_make_executable_if_needed (routine);
   /* 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..f71d79e 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,11 @@ 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 */);
+  jitter_routine_make_executable_if_needed (routine);
+  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 31976ba..316e3b0 100755
--- a/src/ras
+++ b/src/ras
@@ -80,7 +80,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
@@ -286,7 +286,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
@@ -590,7 +590,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, \\")
@@ -613,12 +613,12 @@ 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  jitter_routine_make_executable_if_needed (routine);   \\")
+        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]