Merged new changes from default (manually: src/vm/jit/emit-common.cpp, src/vm/ji
authorStefan Ring <stefan@complang.tuwien.ac.at>
Mon, 13 Oct 2008 14:34:46 +0000 (16:34 +0200)
committerStefan Ring <stefan@complang.tuwien.ac.at>
Mon, 13 Oct 2008 14:34:46 +0000 (16:34 +0200)
t/emit-common.hpp)

--HG--
branch : subtype-trunk

34 files changed:
INSTALL
configure.ac
src/mm/boehm-gc/include/private/gcconfig.h
src/vm/jit/Makefile.am
src/vm/jit/allocator/simplereg.h
src/vm/jit/alpha/codegen.c
src/vm/jit/arm/codegen.c
src/vm/jit/emit-common.cpp
src/vm/jit/emit-common.hpp
src/vm/jit/i386/codegen.c
src/vm/jit/inline/Makefile.am
src/vm/jit/inline/inline.c [deleted file]
src/vm/jit/inline/inline.cpp [new file with mode: 0644]
src/vm/jit/inline/inline.h [deleted file]
src/vm/jit/inline/inline.hpp [new file with mode: 0644]
src/vm/jit/intrp/codegen.c
src/vm/jit/jit.cpp
src/vm/jit/jit.hpp
src/vm/jit/m68k/codegen.c
src/vm/jit/mips/codegen.c
src/vm/jit/parse.c [deleted file]
src/vm/jit/parse.cpp [new file with mode: 0644]
src/vm/jit/parse.h [deleted file]
src/vm/jit/parse.hpp [new file with mode: 0644]
src/vm/jit/powerpc/codegen.c
src/vm/jit/powerpc64/codegen.c
src/vm/jit/s390/codegen.c
src/vm/jit/show.cpp
src/vm/jit/sparc64/codegen.c
src/vm/jit/stack.c
src/vm/jit/verify/typecheck-stackbased.c
src/vm/jit/verify/typecheck-typeinferer.c
src/vm/jit/verify/typecheck.c
src/vm/jit/x86_64/codegen.c

diff --git a/INSTALL b/INSTALL
index f3869a941abc66166ca5ac152b1c526998c696cf..d3c5b40a94091285c27361905f591af64c1f7b21 100644 (file)
--- a/INSTALL
+++ b/INSTALL
-Quick start instructions
-========================
+Installation Instructions
+*************************
 
-You can check the configure options via `./configure --help'. But the
-default settings should be ok. For building the package type:
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
+2006, 2007 Free Software Foundation, Inc.
 
-   $ ./configure
-   $ make
-   $ make install
+This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
 
-The default installation prefix is `/usr/local/cacao'. You can change
-this destination by providing the `--prefix=PATH' option to configure.
+Basic Installation
+==================
 
-This version of cacao only supports the `--prefix' option, even if
-configure processes the other options (`--bindir', `--libdir', etc.),
-it will screw up your installation since CACAO tries to setup a
-directory tree like the JVMs from Sun or IBM do.
+Briefly, the shell commands `./configure; make; make install' should
+configure, build, and install this package.  The following
+more-detailed instructions are generic; see the `README' file for
+instructions specific to this package.
 
+   The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
 
-Requirements:
--------------
+   It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring.  Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.
+
+   If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+   The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'.  You need `configure.ac' if
+you want to change it or regenerate `configure' using a newer version
+of `autoconf'.
+
+The simplest way to compile this package is:
+
+  1. `cd' to the directory containing the package's source code and type
+     `./configure' to configure the package for your system.
+
+     Running `configure' might take a while.  While running, it prints
+     some messages telling which features it is checking for.
+
+  2. Type `make' to compile the package.
+
+  3. Optionally, type `make check' to run any self-tests that come with
+     the package.
+
+  4. Type `make install' to install the programs and any data files and
+     documentation.
+
+  5. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  To also remove the
+     files that `configure' created (so you can compile the package for
+     a different kind of computer), type `make distclean'.  There is
+     also a `make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+  6. Often, you can also type `make uninstall' to remove the installed
+     files again.
+
+Compilers and Options
+=====================
+
+Some systems require unusual options for compilation or linking that the
+`configure' script does not know about.  Run `./configure --help' for
+details on some of the pertinent environment variables.
+
+   You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment.  Here
+is an example:
+
+     ./configure CC=c99 CFLAGS=-g LIBS=-lposix
+
+   *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you can use GNU `make'.  `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script.  `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+   With a non-GNU `make', it is safer to compile the package for one
+architecture at a time in the source code directory.  After you have
+installed the package for one architecture, use `make distclean' before
+reconfiguring for another architecture.
+
+Installation Names
+==================
+
+By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc.  You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX'.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+   In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' to specify different values for particular
+kinds of files.  Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+There may be some features `configure' cannot figure out automatically,
+but needs to determine by the type of machine the package will run on.
+Usually, assuming the package is built to be run on the _same_
+architectures, `configure' can figure that out, but if it prints a
+message saying it cannot guess the machine type, give it the
+`--build=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+     CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+     OS KERNEL-OS
+
+   See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+   If you are _building_ compiler tools for cross-compiling, you should
+use the option `--target=TYPE' to select the type of system they will
+produce code for.
+
+   If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+If you want to set default values for `configure' scripts to share, you
+can create a site shell script called `config.site' that gives default
+values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+Variables not defined in a site shell script can be set in the
+environment passed to `configure'.  However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost.  In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'.  For example:
+
+     ./configure CC=/usr/local2/bin/gcc
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+Unfortunately, this technique does not work for `CONFIG_SHELL' due to
+an Autoconf bug.  Until the bug is fixed you can use this workaround:
+
+     CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+`configure' Invocation
+======================
+
+`configure' recognizes the following options to control how it operates.
+
+`--help'
+`-h'
+     Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`--cache-file=FILE'
+     Enable the cache: use and save the results of the tests in FILE,
+     traditionally `config.cache'.  FILE defaults to `/dev/null' to
+     disable caching.
+
+`--config-cache'
+`-C'
+     Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.  To
+     suppress all normal output, redirect it to `/dev/null' (any error
+     messages will still be shown).
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options.  Run
+`configure --help' for more details.
 
-In order to compile the Java classes from GNU classpath, you need a
-Java compiler supported by GNU classpath. To get a working classpath
-in an appropriate time, we recommend IBM jikes 1.18 or newer. For
-further instructions concerning GNU classpath, please refer to
-`src/classpath/INSTALL'.
index a9572aad24d93a69bb131314587dec47abcbd850..3f0c8a4577d96c79b00231bc5f435a516455f253 100644 (file)
@@ -67,13 +67,18 @@ m68k )
     JAVA_ARCH="m68k"
     ;;
 
-mips | mipsel )
+mips )
     ARCH_DIR="mips"
     ARCH_FLAGS="-D__MIPS__"
-    dnl Is this correct for mipsel?
     JAVA_ARCH="mips"
     ;;
 
+mipsel )
+    ARCH_DIR="mips"
+    ARCH_FLAGS="-D__MIPS__"
+    JAVA_ARCH="mipsel"
+    ;;
+
 powerpc )
     ARCH_DIR="powerpc"
     ARCH_FLAGS="-m32 -D__POWERPC__"
index b828759d0cb5d6d204113ebe0ba82ca85dd023d6..e1377ac088e223ea88e3ab0d3a26db54201b9902 100644 (file)
 #     define DYNAMIC_LOADING
       extern int _end[];
 #     define DATAEND (_end)
-      extern int __data_start[];
-#     define DATASTART ((ptr_t)(__data_start))
+#     define SEARCH_FOR_DATA_START
 #     define CPP_WORDSZ _MIPS_SZPTR
 #     define ALIGNMENT (_MIPS_SZPTR/8)
 #     if __GLIBC__ == 2 && __GLIBC_MINOR__ >= 2 || __GLIBC__ > 2
 #       define OS_TYPE "LINUX"
 #       define LINUX_STACKBOTTOM
 #       define DYNAMIC_LOADING
-       extern int __data_start[];
-#       define DATASTART ((ptr_t)(__data_start))
-    extern int _end[];
+#       define SEARCH_FOR_DATA_START
+        extern int _end[];
 #   define DATAEND (_end)
 #   define CACHE_LINE_SIZE 256
 #   define GETPAGESIZE() 4096
index c8d27ba749d5334d83230a0ae1d4c9c6e27790f8..42bb842472aa8567c9cfe6f2fa9a93639f4f548c 100644 (file)
@@ -181,8 +181,8 @@ libjit_la_SOURCES = \
        linenumbertable.hpp \
        methodtree.c \
        methodtree.h \
-       parse.c \
-       parse.h \
+       parse.cpp \
+       parse.hpp \
        patcher-common.cpp \
        patcher-common.hpp \
        $(RECOMPILE_SOURCES) \
index 9ca4373a65fda07b4c20debf2ed17e45cfdce5db..619a039515bb6c507ed554af03d02d022f9af0e1 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "vm/jit/codegen-common.hpp"
 #include "vm/jit/jit.hpp"
-#include "vm/jit/inline/inline.h"
+#include "vm/jit/inline/inline.hpp"
 
 
 /* function prototypes ********************************************************/
index d44e2f8d16e005a618f278b9c6e39fcbef83d8cf..b136fd4dcaaefac36a11c63d4a751ac2f4c60b23 100644 (file)
@@ -57,7 +57,7 @@
 #include "vm/jit/emit-common.hpp"
 #include "vm/jit/jit.hpp"
 #include "vm/jit/linenumbertable.hpp"
-#include "vm/jit/parse.h"
+#include "vm/jit/parse.hpp"
 #include "vm/jit/patcher-common.hpp"
 #include "vm/jit/reg.h"
 #include "vm/jit/replace.hpp"
index efe6d3d746eac7d775dae8bc56eb9495294cb972..0df334e9ada5e4effd16a5da8fc7af1400bbddb6 100644 (file)
@@ -58,7 +58,7 @@
 #include "vm/jit/jitcache.hpp"
 #include "vm/jit/linenumbertable.hpp"
 #include "vm/jit/methodheader.h"
-#include "vm/jit/parse.h"
+#include "vm/jit/parse.hpp"
 #include "vm/jit/patcher-common.hpp"
 #include "vm/jit/reg.h"
 
index 3bc48fa9cca6b8d2edabb5973c78602118d7db38..370a64bd024fd6463f35a6bb03e6077bcc67d076 100644 (file)
@@ -656,19 +656,48 @@ void emit_label_br(codegendata *cd, s4 label)
 
 #if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
 
-void emit_label_beqz(codegendata *cd, s4 label, s4 reg)
+void emit_label_beqz(codegendata* cd, int label, int reg)
 {
        emit_label_bccz(cd, label, BRANCH_EQ, reg, BRANCH_OPT_NONE);
 }
 
-void emit_label_bnez(codegendata *cd, s4 label, s4 reg)
+void emit_label_bnez(codegendata* cd, int label, int reg)
 {
        emit_label_bccz(cd, label, BRANCH_NE, reg, BRANCH_OPT_NONE);
 }
 
+void emit_label_bltz(codegendata* cd, int label, int reg)
+{
+       emit_label_bccz(cd, label, BRANCH_LT, reg, BRANCH_OPT_NONE);
+}
+
+void emit_label_bgtz(codegendata* cd, int label, int reg)
+{
+       emit_label_bccz(cd, label, BRANCH_GT, reg, BRANCH_OPT_NONE);
+}
+
 #endif /* SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER */
 
 
+/* emit_label_bxx **************************************************************
+
+   Wrappers for label-branches on two integer registers.
+
+   We use PACK_REGS here, so we don't have to change the branchref
+   data structure and the emit_bccz function.
+
+*******************************************************************************/
+
+#if SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS
+
+void emit_label_bne(codegendata* cd, int label, int s1, int s2)
+{
+       emit_label_bccz(cd, label, BRANCH_NE, PACK_REGS(s1, s2), BRANCH_OPT_NONE);
+}
+
+#endif /* SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS */
+
+
 /* emit_label_bxx **************************************************************
 
    Wrappers for label-branches on condition codes.
index b96bc08ea213fe19a7c355b3dfde5cdf9d8f6ae5..611eca43d943175d53a70e6dba14fe1a9b107aef 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vm/jit/emit-common.hpp - common code emitter functions
 
-   Copyright (C) 2006, 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
-   R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
-   C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
-   Institut f. Computersprachen - TU Wien
+   Copyright (C) 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
@@ -163,8 +161,14 @@ void emit_label_bcc(codegendata *cd, s4 label, s4 condition, u4 options);
 void emit_label_br(codegendata *cd, s4 label);
 
 #if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
-void emit_label_beqz(codegendata *cd, s4 label, s4 reg);
-void emit_label_bnez(codegendata *cd, s4 label, s4 reg);
+void emit_label_beqz(codegendata* cd, int label, int reg);
+void emit_label_bnez(codegendata* cd, int label, int reg);
+void emit_label_bltz(codegendata* cd, int label, int reg);
+void emit_label_bgtz(codegendata* cd, int label, int reg);
+#endif
+
+#if SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS
+void emit_label_bne(codegendata* cd, int label, int s1, int s2);
 #endif
 
 #if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
index bdedf5b6459f6c813c9f85ff1099689106b164ad..c7adf83a5bddb1b7d8c110e6ea20420fdb3bc110 100644 (file)
@@ -60,7 +60,7 @@
 #include "vm/jit/jit.hpp"
 #include "vm/jit/jitcache.hpp"
 #include "vm/jit/linenumbertable.hpp"
-#include "vm/jit/parse.h"
+#include "vm/jit/parse.hpp"
 #include "vm/jit/patcher-common.hpp"
 #include "vm/jit/reg.h"
 #include "vm/jit/replace.hpp"
index 8b46e133284226aa11fffb07bd6e6b8ac2b1e63f..e3ca1468f4926c13255d4f298680792ec78bf527 100644 (file)
@@ -31,8 +31,8 @@ noinst_LTLIBRARIES = \
        libinline.la
 
 libinline_la_SOURCES = \
-       inline.c \
-       inline.h \
+       inline.cpp \
+       inline.hpp \
        inline_debug.inc
 
 
diff --git a/src/vm/jit/inline/inline.c b/src/vm/jit/inline/inline.c
deleted file mode 100644 (file)
index ca7fb42..0000000
+++ /dev/null
@@ -1,3237 +0,0 @@
-/* src/vm/jit/inline/inline.c - method inlining
-
-   Copyright (C) 1996-2005, 2006, 2007, 2008
-   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
-   This file is part of CACAO.
-
-   This program 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 2, or (at
-   your option) any later version.
-
-   This program 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 this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "vm/types.h"
-
-#include "mm/memory.h"
-
-#include "threads/lock.hpp"
-#include "threads/mutex.hpp"
-#include "threads/thread.hpp"
-
-#include "toolbox/logging.h"
-
-#include "vm/jit/builtin.hpp"
-#include "vm/class.hpp"
-#include "vm/global.h"
-#include "vm/initialize.hpp"
-#include "vm/method.h"
-#include "vm/options.h"
-#include "vm/statistics.h"
-
-#include "vm/jit/jit.hpp"
-#include "vm/jit/parse.h"
-#include "vm/jit/reg.h"
-#include "vm/jit/show.hpp"
-#include "vm/jit/stack.h"
-
-#include "vm/jit/inline/inline.h"
-#include "vm/jit/loop/loop.h"
-
-#include "vm/jit/verify/typecheck.h"
-
-
-/* algorithm tuning constants *************************************************/
-
-/* Algorithm Selection                                                        */
-/* Define exactly one of the following three to select the inlining           */
-/* heuristics.                                                                */
-
-/*#define INLINE_DEPTH_FIRST*/
-/*#define INLINE_BREADTH_FIRST*/
-#define INLINE_KNAPSACK
-
-/* Parameters for knapsack heuristics:                                        */
-
-#if defined(INLINE_KNAPSACK)
-
-#define INLINE_COUNTDOWN_INIT       1000
-#define INLINE_COST_OFFSET          -16
-#define INLINE_COST_BUDGET          100
-/*#define INLINE_WEIGHT_BUDGET        5.0*/
-/*#define INLINE_ADD_NEGATIVE_TO_BUDGET*/
-/*#define INLINE_MAX_DEPTH            3*/
-/*#define INLINE_DIVIDE_COST_BY_FREQ */
-
-#endif
-
-/* Parameters for depth-first heuristics:                                     */
-
-#if defined(INLINE_DEPTH_FIRST)
-
-#define INLINE_MAX_DEPTH            3
-#define INLINE_MAX_BLOCK_EXPANSION  10
-/*#define INLINE_MAX_ICMD_EXPANSION  10*/
-/*#define INLINE_CANCEL_ON_THRESHOLD*/
-
-#endif
-
-/* Parameters for breadth-first heuristics:                                   */
-
-#if defined(INLINE_BREADTH_FIRST)
-
-/*#define INLINE_MAX_BLOCK_EXPANSION  10*/
-#define INLINE_MAX_ICMD_EXPANSION  5
-
-#endif
-
-
-/* debugging ******************************************************************/
-
-#if !defined(NDEBUG)
-#define INLINE_VERBOSE
-#define DOLOG(code)       do{ if (opt_TraceInlining >= 2) { code; } }while(0)
-#define DOLOG_SHORT(code) do{ if (opt_TraceInlining >= 1) { code; } }while(0)
-#else
-#define DOLOG(code)
-#endif
-
-#if defined(ENABLE_VERIFIER) && !defined(NDEBUG)
-/* Define this to verify the resulting code after inlining.                 */
-/* Note: This is only useful for development and may require patches to the */
-/*       verifier code.                                                     */
-/* #define INLINE_VERIFY_RESULT */
-#endif
-
-
-/* types **********************************************************************/
-
-typedef struct inline_node inline_node;
-typedef struct inline_target_ref inline_target_ref;
-typedef struct inline_context inline_context;
-typedef struct inline_block_map inline_block_map;
-typedef struct inline_site inline_site;
-typedef struct inline_candidate inline_candidate;
-
-struct inline_node {
-       inline_context *ctx;
-
-       jitdata *jd;
-       methodinfo *m;
-       inline_node *children;
-       inline_node *next;                             /* next node at this depth */
-       inline_node *prev;                             /* prev node at this depth */
-       int depth;                                  /* inlining depth, 0 for root */
-
-       /* info about the call site (if depth > 0)*/
-       inline_node *parent;                /* node of the caller (NULL for root) */
-       basicblock *callerblock;         /* original block containing the INVOKE* */
-       instruction *callerins;               /* the original INVOKE* instruction */
-       s4 callerpc;
-       s4 *n_passthroughvars;
-       int n_passthroughcount;
-       int n_selfpassthroughcount;  /* # of pass-through vars of the call itself */
-       exception_entry **o_handlers;
-       int n_handlercount;                 /* # of handlers protecting this call */
-       int n_resultlocal;
-       int synclocal;                    /* variable used for synchr., or UNUSED */
-       bool isstatic;                                   /* this is a static call */
-
-       bool blockbefore;                  /* block boundary before inlined body? */
-       bool blockafter;                   /* block boundary after inlined body?  */
-
-       /* info about the callee */
-       int localsoffset;
-       int prolog_instructioncount;         /* # of ICMDs in the inlining prolog */
-       int epilog_instructioncount;         /* # of ICMDs in the inlining epilog */
-       int extra_instructioncount;
-       int extra_exceptiontablelength;   /* # of extra handlers to put in caller */
-       bool synchronize;                /* do we have to synchronize enter/exit? */
-       basicblock *handler_monitorexit;     /* handler for synchronized inlinees */
-       s4 *varmap;
-
-       /* cumulative values */
-       int cumul_instructioncount;  /* ICMDs in this node and its children       */
-       int cumul_basicblockcount;   /* BBs started by this node and its children */
-       int cumul_basicblockcount_root;  /* BBs that have to be added to the root */
-                                        /* node if this node is inlined          */
-       int cumul_blockmapcount;
-       int cumul_maxlocals;
-       int cumul_exceptiontablelength;
-
-       /* output */
-       instruction *inlined_iinstr;
-       instruction *inlined_iinstr_cursor;
-       basicblock *inlined_basicblocks;
-       basicblock *inlined_basicblocks_cursor;
-
-       /* register data */
-       registerdata *regdata;
-
-       /* temporary */
-       inline_target_ref *refs;
-       instruction *inline_start_instruction;
-       s4 *javalocals;
-
-       /* XXX debug */
-       char *indent;
-       int debugnr;
-};
-
-struct inline_target_ref {
-       inline_target_ref *next;
-       union {
-               basicblock **block;
-               s4 *nr;
-       } ref;
-       basicblock *target;
-       bool isnumber;
-};
-
-struct inline_block_map {
-       inline_node *iln;
-       basicblock *o_block;
-       basicblock *n_block;
-};
-
-struct inline_context {
-       inline_node *master;
-
-       jitdata *resultjd;
-
-       inline_candidate *candidates;
-
-       int next_block_number;
-       inline_block_map *blockmap;
-       int blockmap_index;
-
-       int maxinoutdepth;
-
-       bool stopped;
-
-       int next_debugnr; /* XXX debug */
-};
-
-struct inline_site {
-       bool              speculative;  /* true, if inlining would be speculative */
-       bool              inlined;      /* true, if this site has been inlined    */
-
-       basicblock       *bptr;         /* basic block containing the call site   */
-       instruction      *iptr;         /* the invocation instruction             */
-       exception_entry **handlers;     /* active handlers at the call site       */
-       s4                nhandlers;    /* number of active handlers              */
-       s4                pc;           /* PC of the invocation instruction       */
-};
-
-struct inline_candidate {
-       inline_candidate *next;
-       int freq;
-       int cost;
-       double weight;
-       inline_node *caller;
-       methodinfo *callee;
-       inline_site site;
-};
-
-
-/* prototypes *****************************************************************/
-
-static bool inline_analyse_code(inline_node *iln);
-static void inline_post_process(jitdata *jd);
-
-
-/* debug helpers **************************************************************/
-
-#if !defined(NDEBUG)
-#include "inline_debug.inc"
-#endif
-
-
-/* statistics *****************************************************************/
-
-/*#define INLINE_STATISTICS*/
-
-#if !defined(NDEBUG)
-#define INLINE_STATISTICS
-#endif
-
-#if defined(INLINE_STATISTICS)
-int inline_stat_roots = 0;
-int inline_stat_roots_transformed = 0;
-int inline_stat_inlined_nodes = 0;
-int inline_stat_max_depth = 0;
-
-void inline_print_stats()
-{
-       printf("inlining statistics:\n");
-       printf("    roots analysed   : %d\n", inline_stat_roots);
-       printf("    roots transformed: %d\n", inline_stat_roots_transformed);
-       printf("    inlined nodes    : %d\n", inline_stat_inlined_nodes);
-       printf("    max depth        : %d\n", inline_stat_max_depth);
-}
-#endif
-
-
-/* compilation of callees *****************************************************/
-
-static bool inline_jit_compile_intern(jitdata *jd)
-{
-       methodinfo *m;
-
-       /* XXX should share code with jit.c */
-
-       assert(jd);
-
-       /* XXX initialize the static function's class */
-
-       m = jd->m;
-
-       /* call the compiler passes ***********************************************/
-
-       /* call parse pass */
-
-       DOLOG( log_message_class("Parsing ", m->clazz) );
-       if (!parse(jd)) {
-               return false;
-       }
-
-       /* call stack analysis pass */
-
-       if (!stack_analyse(jd)) {
-               return false;
-       }
-
-       return true;
-}
-
-
-static bool inline_jit_compile(inline_node *iln)
-{
-       bool                r;
-       methodinfo         *m;
-       jitdata            *jd;
-
-       /* XXX should share code with jit.c */
-
-       assert(iln);
-       m = iln->m;
-       assert(m);
-
-       /* enter a monitor on the method */
-
-       Mutex_lock(m->mutex);
-
-       /* allocate jitdata structure and fill it */
-
-       jd = jit_jitdata_new(m);
-       iln->jd = jd;
-
-       jd->flags = 0; /* XXX */
-
-       /* initialize the register allocator */
-
-       reg_setup(jd);
-
-       /* setup the codegendata memory */
-
-       /* XXX do a pseudo setup */
-       jd->cd = DNEW(codegendata);
-       MZERO(jd->cd, codegendata, 1);
-       jd->cd->method = m;
-       /* XXX uses too much dump memory codegen_setup(jd); */
-
-       /* now call internal compile function */
-
-       r = inline_jit_compile_intern(jd);
-
-       if (r) {
-               iln->regdata = jd->rd;
-       }
-
-       /* free some memory */
-#if 0
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
-       if (!opt_intrp)
-# endif
-               codegen_free(jd);
-#endif
-
-#endif
-
-       /* leave the monitor */
-
-       Mutex_unlock(m->mutex);
-
-       return r;
-}
-
-
-/* inlining tree handling *****************************************************/
-
-static void inline_insert_inline_node(inline_node *parent, inline_node *child)
-{
-       inline_node *first;
-       inline_node *succ;
-
-       assert(parent && child);
-
-       child->parent = parent;
-
-       child->debugnr = parent->ctx->next_debugnr++; /* XXX debug */
-
-       first = parent->children;
-       if (!first) {
-               /* insert as only node */
-               parent->children = child;
-               child->next = child;
-               child->prev = child;
-               return;
-       }
-
-       /* {there is at least one child already there} */
-
-       /* XXX is this search necessary, or could we always add at the end? */
-
-       succ = first;
-       while (succ->callerpc < child->callerpc) {
-               succ = succ->next;
-               if (succ == first) {
-                       /* insert as last node */
-                       child->prev = first->prev;
-                       child->next = first;
-                       child->prev->next = child;
-                       child->next->prev = child;
-                       return;
-               }
-       }
-
-       assert(succ->callerpc > child->callerpc);
-
-       /* insert before succ */
-
-       child->prev = succ->prev;
-       child->next = succ;
-       child->prev->next = child;
-       child->next->prev = child;
-
-       if (parent->children == succ)
-               parent->children = child;
-}
-
-
-static void inline_remove_inline_node(inline_node *parent, inline_node *child)
-{
-       assert(parent);
-       assert(child);
-       assert(child->parent == parent);
-
-       if (child->prev == child) {
-               /* remove the only child node */
-               parent->children = NULL;
-       }
-       else {
-               child->prev->next = child->next;
-               child->next->prev = child->prev;
-
-               if (parent->children == child)
-                       parent->children = child->next;
-       }
-}
-
-
-/* inlining candidate handling ************************************************/
-
-#if defined(INLINE_KNAPSACK) || defined(INLINE_BREADTH_FIRST)
-static void inline_add_candidate(inline_context *ctx,
-                                                                inline_node *caller,
-                                                                methodinfo *callee,
-                                                                inline_site *site)
-{
-       inline_candidate **link;
-       inline_candidate *cand;
-
-       cand = DNEW(inline_candidate);
-#if defined(INLINE_DIVIDE_COST_BY_FREQ)
-       cand->freq = INLINE_COUNTDOWN_INIT - callee->hitcountdown;
-       if (cand->freq < 1)
-#endif
-               cand->freq = 1;
-#if defined(INLINE_KNAPSACK)
-       cand->cost = callee->jcodelength + INLINE_COST_OFFSET;
-#endif
-#if defined(INLINE_BREADTH_FIRST)
-       cand->cost = caller->depth;
-#endif
-       cand->caller = caller;
-       cand->callee = callee;
-       cand->site = *site;
-
-       cand->weight = (double)cand->cost / cand->freq;
-
-       for (link = &(ctx->candidates); ; link = &((*link)->next)) {
-               if (!*link || (*link)->weight > cand->weight) {
-                       cand->next = *link;
-                       *link = cand;
-                       break;
-               }
-       }
-}
-#endif /* defined(INLINE_KNAPSACK) || defined(INLINE_BREADTH_FIRST) */
-
-#if defined(INLINE_KNAPSACK) || defined(INLINE_BREADTH_FIRST)
-static inline_candidate * inline_pick_best_candidate(inline_context *ctx)
-{
-       inline_candidate *cand;
-
-       cand = ctx->candidates;
-
-       if (cand)
-               ctx->candidates = cand->next;
-
-       return cand;
-}
-#endif /* defined(INLINE_KNAPSACK) || defined(INLINE_BREADTH_FIRST) */
-
-#if !defined(NDEBUG) && (defined(INLINE_KNAPSACK) || defined(INLINE_BREADTH_FIRST))
-static void inline_candidate_println(inline_candidate *cand)
-{
-       printf("%10g (%5d / %5d) depth %2d ",
-                       cand->weight, cand->cost, cand->freq, cand->caller->depth + 1);
-       method_println(cand->callee);
-}
-#endif /* !defined(NDEBUG) && (defined(INLINE_KNAPSACK) || defined(INLINE_BREADTH_FIRST)) */
-
-
-#if !defined(NDEBUG) && (defined(INLINE_KNAPSACK) || defined(INLINE_BREADTH_FIRST))
-static void inline_candidates_println(inline_context *ctx)
-{
-       inline_candidate *cand;
-
-       for (cand = ctx->candidates; cand != NULL; cand = cand->next) {
-               printf("    ");
-               inline_candidate_println(cand);
-       }
-}
-#endif /* !defined(NDEBUG) && (defined(INLINE_KNAPSACK) || defined(INLINE_BREADTH_FIRST)) */
-
-
-/* variable handling **********************************************************/
-
-static s4 inline_new_variable(jitdata *jd, s4 type, s4 flags)
-{
-       s4 index;
-       s4 newcount;
-
-       index = jd->vartop++;
-       if (index >= jd->varcount) {
-               newcount = jd->vartop * 2; /* XXX */
-               jd->var = DMREALLOC(jd->var, varinfo, jd->varcount, newcount);
-               MZERO(jd->var + jd->varcount, varinfo, (newcount - jd->varcount));
-               jd->varcount = newcount;
-       }
-
-       jd->var[index].type = type;
-       jd->var[index].flags = flags;
-
-       return index;
-}
-
-
-static s4 inline_new_variable_clone(jitdata *jd, jitdata *origjd, s4 origidx)
-{
-       varinfo *v;
-       s4       newidx;
-
-       v = &(origjd->var[origidx]);
-
-       newidx = inline_new_variable(jd, v->type, v->flags);
-
-       jd->var[newidx].vv = v->vv;
-
-       return newidx;
-}
-
-
-static s4 inline_new_temp_variable(jitdata *jd, s4 type)
-{
-       return inline_new_variable(jd, type, 0);
-}
-
-
-static s4 inline_translate_variable(jitdata *jd, jitdata *origjd, s4 *varmap, s4 index)
-{
-       s4 idx;
-
-       idx = varmap[index];
-
-       if (idx < 0) {
-               idx = inline_new_variable_clone(jd, origjd, index);
-               varmap[index] = idx;
-       }
-
-       return idx;
-}
-
-
-static s4 *create_variable_map(inline_node *callee)
-{
-       s4 *varmap;
-       s4 i, t;
-       s4 varindex;
-       s4 n_javaindex;
-       s4 avail;
-       varinfo *v;
-
-       /* create the variable mapping */
-
-       varmap = DMNEW(s4, callee->jd->varcount);
-       for (i=0; i<callee->jd->varcount; ++i)
-               varmap[i] = -1;
-
-       /* translate local variables */
-
-       for (i=0; i<callee->m->maxlocals; ++i) {
-               for (t=0; t<5; ++t) {
-                       varindex = callee->jd->local_map[5*i + t];
-                       if (varindex == UNUSED)
-                               continue;
-
-                       v = &(callee->jd->var[varindex]);
-                       assert(v->type == t || v->type == TYPE_VOID); /* XXX stack leaves VOID */
-                       v->type = t; /* XXX restore if it is TYPE_VOID */
-
-                       avail = callee->ctx->resultjd->local_map[5*(callee->localsoffset + i) + t];
-
-                       if (avail == UNUSED) {
-                               avail = inline_new_variable_clone(callee->ctx->resultjd, callee->jd, varindex);
-                               callee->ctx->resultjd->local_map[5*(callee->localsoffset + i) + t] = avail;
-                       }
-
-                       varmap[varindex] = avail;
-               }
-       }
-
-       /* for synchronized instance methods we need an extra local */
-
-       if (callee->synchronize && !(callee->m->flags & ACC_STATIC)) {
-               n_javaindex = callee->localsoffset - 1;
-               assert(n_javaindex >= 0);
-               assert(callee->parent);
-               assert(n_javaindex == callee->parent->localsoffset + callee->parent->m->maxlocals);
-
-               avail = callee->ctx->resultjd->local_map[5*n_javaindex + TYPE_ADR];
-
-               if (avail == UNUSED) {
-                       avail = inline_new_variable(callee->ctx->resultjd, TYPE_ADR, 0);
-                       callee->ctx->resultjd->local_map[5*n_javaindex + TYPE_ADR] = avail;
-               }
-
-               callee->synclocal = avail;
-       }
-       else {
-               callee->synclocal = UNUSED;
-       }
-
-       return varmap;
-}
-
-
-/* basic block translation ****************************************************/
-
-#define INLINE_RETURN_REFERENCE(callee)  \
-       ( (basicblock *) (ptrint) (0x333 + (callee)->depth) )
-
-
-static void inline_add_block_reference(inline_node *iln, basicblock **blockp)
-{
-       inline_target_ref *ref;
-
-       ref = DNEW(inline_target_ref);
-       ref->ref.block = blockp;
-       ref->isnumber = false;
-       ref->next = iln->refs;
-       iln->refs = ref;
-}
-
-
-#if 0
-static void inline_add_blocknr_reference(inline_node *iln, s4 *nrp)
-{
-       inline_target_ref *ref;
-
-       ref = DNEW(inline_target_ref);
-       ref->ref.nr = nrp;
-       ref->isnumber = true;
-       ref->next = iln->refs;
-       iln->refs = ref;
-}
-#endif
-
-
-static void inline_block_translation(inline_node *iln, basicblock *o_bptr, basicblock *n_bptr)
-{
-       inline_context *ctx;
-
-       ctx = iln->ctx;
-       assert(ctx->blockmap_index < ctx->master->cumul_blockmapcount);
-
-       ctx->blockmap[ctx->blockmap_index].iln = iln;
-       ctx->blockmap[ctx->blockmap_index].o_block = o_bptr;
-       ctx->blockmap[ctx->blockmap_index].n_block = n_bptr;
-
-       ctx->blockmap_index++;
-}
-
-
-static basicblock * inline_map_block(inline_node *iln,
-                                                                        basicblock *o_block,
-                                                                        inline_node *targetiln)
-{
-       inline_block_map *bm;
-       inline_block_map *bmend;
-
-       assert(iln);
-       assert(targetiln);
-
-       if (!o_block)
-               return NULL;
-
-       bm = iln->ctx->blockmap;
-       bmend = bm + iln->ctx->blockmap_index;
-
-       while (bm < bmend) {
-               assert(bm->iln && bm->o_block && bm->n_block);
-               if (bm->o_block == o_block && bm->iln == targetiln)
-                       return bm->n_block;
-               bm++;
-       }
-
-       assert(false);
-       return NULL; /* not reached */
-}
-
-
-static void inline_resolve_block_refs(inline_target_ref **refs,
-                                                                         basicblock *o_bptr,
-                                                                         basicblock *n_bptr,
-                                                                         bool returnref)
-{
-       inline_target_ref *ref;
-       inline_target_ref *prev;
-
-       prev = NULL;
-       for (ref = *refs; ref != NULL; ref = ref->next) {
-               if (ref->isnumber && !returnref) {
-                       if (*(ref->ref.nr) == JAVALOCAL_FROM_RETADDR(o_bptr->nr)) {
-                               *(ref->ref.nr) = JAVALOCAL_FROM_RETADDR(n_bptr->nr);
-                               goto remove_ref;
-                       }
-               }
-               else {
-                       if (*(ref->ref.block) == o_bptr) {
-                               *(ref->ref.block) = n_bptr;
-                               goto remove_ref;
-                       }
-               }
-
-               /* skip this ref */
-
-               prev = ref;
-               continue;
-
-remove_ref:
-               /* remove this ref */
-
-               if (prev) {
-                       prev->next = ref->next;
-               }
-               else {
-                       *refs = ref->next;
-               }
-       }
-}
-
-
-/* basic block creation *******************************************************/
-
-static basicblock * create_block(inline_node *container,
-                                                                inline_node *iln,
-                                                                inline_node *inner,
-                                                                int indepth)
-{
-       basicblock  *n_bptr;
-       inline_node *outer;
-       s4           i;
-       s4           depth;
-       s4           varidx;
-       s4           newvaridx;
-
-       assert(container);
-       assert(iln);
-       assert(inner);
-       assert(indepth >= 0);
-
-       n_bptr = container->inlined_basicblocks_cursor++;
-       assert(n_bptr);
-       assert((n_bptr - container->inlined_basicblocks) < container->cumul_basicblockcount);
-
-       BASICBLOCK_INIT(n_bptr, iln->m);
-
-       n_bptr->iinstr = container->inlined_iinstr_cursor;
-       n_bptr->next = n_bptr + 1;
-       n_bptr->nr = container->ctx->next_block_number++;
-       n_bptr->indepth = indepth;
-       n_bptr->flags = BBFINISHED; /* XXX */
-
-       /* set the inlineinfo of the new block */
-
-       if (iln->inline_start_instruction)
-               n_bptr->inlineinfo = iln->inline_start_instruction->sx.s23.s3.inlineinfo;
-
-       if (indepth > container->ctx->maxinoutdepth)
-               container->ctx->maxinoutdepth = indepth;
-
-       if (indepth) {
-               n_bptr->invars = DMNEW(s4, indepth);
-
-
-               for (i=0; i<indepth; ++i)
-                       n_bptr->invars[i] = -1; /* XXX debug */
-
-               /* pass-through variables enter the block */
-
-               outer = inner->parent;
-               while (outer != NULL) {
-                       depth = outer->n_passthroughcount;
-
-                       assert(depth + inner->n_selfpassthroughcount <= indepth);
-
-                       for (i=0; i<inner->n_selfpassthroughcount; ++i) {
-                               varidx = inner->n_passthroughvars[i];
-                               newvaridx =
-                                       inline_new_variable_clone(container->ctx->resultjd,
-                                                                                         outer->jd,
-                                                                                         varidx);
-                               n_bptr->invars[depth + i] = newvaridx;
-                               outer->varmap[varidx] = newvaridx;
-                       }
-                       inner = outer;
-                       outer = outer->parent;
-               }
-       }
-       else {
-               n_bptr->invars = NULL;
-       }
-
-       /* XXX for the verifier. should not be here */
-
-       {
-               varinfo *dv;
-
-               dv = DMNEW(varinfo, iln->ctx->resultjd->localcount + VERIFIER_EXTRA_LOCALS);
-               MZERO(dv, varinfo,  iln->ctx->resultjd->localcount + VERIFIER_EXTRA_LOCALS);
-               n_bptr->inlocals = dv;
-       }
-
-       return n_bptr;
-}
-
-
-static s4 *translate_javalocals(inline_node *iln, s4 *javalocals)
-{
-       s4 *jl;
-       s4 i, j;
-
-       jl = DMNEW(s4, iln->jd->maxlocals);
-
-       for (i=0; i<iln->jd->maxlocals; ++i) {
-               j = javalocals[i];
-               if (j > UNUSED)
-                       j = inline_translate_variable(iln->ctx->resultjd, iln->jd, iln->varmap, j);
-               jl[i] = j;
-
-#if 0
-               if (j < UNUSED) {
-                       /* an encoded returnAddress value - must be relocated */
-                       inline_add_blocknr_reference(iln, &(jl[i]));
-               }
-#endif
-       }
-
-       return jl;
-}
-
-
-static basicblock * create_body_block(inline_node *iln,
-                                                                         basicblock *o_bptr, s4 *varmap)
-{
-       basicblock *n_bptr;
-       s4 i;
-
-       n_bptr = create_block(iln, iln, iln,
-                                                 o_bptr->indepth + iln->n_passthroughcount);
-
-       n_bptr->type = o_bptr->type;
-       n_bptr->flags = o_bptr->flags;
-       n_bptr->bitflags = o_bptr->bitflags;
-
-       /* resolve references to this block */
-
-       inline_resolve_block_refs(&(iln->refs), o_bptr, n_bptr, false);
-
-       /* translate the invars of the original block */
-
-       for (i=0; i<o_bptr->indepth; ++i) {
-               n_bptr->invars[iln->n_passthroughcount + i] =
-                       inline_translate_variable(iln->ctx->resultjd, iln->jd,
-                               varmap,
-                               o_bptr->invars[i]);
-       }
-
-       /* translate javalocals info (not for dead code) */
-
-       if (n_bptr->flags >= BBREACHED)
-               n_bptr->javalocals = translate_javalocals(iln, o_bptr->javalocals);
-
-       return n_bptr;
-}
-
-
-static basicblock * create_epilog_block(inline_node *caller, inline_node *callee, s4 *varmap)
-{
-       basicblock *n_bptr;
-       s4 retcount;
-       s4 idx;
-
-       /* number of return variables */
-
-       retcount = (callee->n_resultlocal == -1
-                               && callee->m->parseddesc->returntype.type != TYPE_VOID) ? 1 : 0;
-
-       /* start the epilog block */
-
-       n_bptr = create_block(caller, caller, callee,
-                                                 callee->n_passthroughcount + retcount);
-
-       /* resolve references to the return block */
-
-       inline_resolve_block_refs(&(callee->refs),
-                                                         INLINE_RETURN_REFERENCE(callee),
-                                                         n_bptr,
-                                                         true);
-
-       /* return variable */
-
-       if (retcount) {
-               idx = inline_new_variable(caller->ctx->resultjd,
-                          callee->m->parseddesc->returntype.type, 0 /* XXX */);
-               n_bptr->invars[callee->n_passthroughcount] = idx;
-               varmap[callee->callerins->dst.varindex] = idx;
-       }
-
-       /* set javalocals */
-
-       n_bptr->javalocals = DMNEW(s4, caller->jd->maxlocals);
-       MCOPY(n_bptr->javalocals, caller->javalocals, s4, caller->jd->maxlocals);
-
-       /* set block flags & type */
-
-       n_bptr->flags = /* XXX original block flags */ BBFINISHED;
-       n_bptr->type = BBTYPE_STD;
-
-       return n_bptr;
-}
-
-
-static void close_block(inline_node *iln, inline_node *inner, basicblock *n_bptr, s4 outdepth)
-{
-       inline_node *outer;
-       s4           i;
-       s4           depth;
-       s4           varidx;
-
-       n_bptr->outdepth = outdepth;
-       n_bptr->outvars = DMNEW(s4, outdepth);
-
-       for (i=0; i<outdepth; ++i)
-               n_bptr->outvars[i] = 0; /* XXX debug */
-
-       if (outdepth > iln->ctx->maxinoutdepth)
-               iln->ctx->maxinoutdepth = outdepth;
-
-       /* pass-through variables leave the block */
-
-       outer = inner->parent;
-       while (outer != NULL) {
-               depth = outer->n_passthroughcount;
-
-               assert(depth + inner->n_selfpassthroughcount <= outdepth);
-
-               for (i=0; i<inner->n_selfpassthroughcount; ++i) {
-                       varidx = inner->n_passthroughvars[i];
-                       n_bptr->outvars[depth + i] =
-                               inline_translate_variable(iln->ctx->resultjd,
-                                                                                 outer->jd,
-                                                                                 outer->varmap,
-                                                                                 varidx);
-               }
-               inner = outer;
-               outer = outer->parent;
-       }
-}
-
-
-static void close_prolog_block(inline_node *iln,
-                                                          basicblock *n_bptr,
-                                                          inline_node *nextcall)
-{
-       /* XXX add original outvars! */
-       close_block(iln, nextcall, n_bptr, nextcall->n_passthroughcount);
-
-       /* pass-through variables */
-
-       DOLOG( printf("closed prolog block:\n");
-                  show_basicblock(iln->ctx->resultjd, n_bptr, SHOW_STACK); );
-}
-
-
-static void close_body_block(inline_node *iln,
-                                                        basicblock *n_bptr,
-                                                        basicblock *o_bptr,
-                                                        s4 *varmap,
-                                                        s4 retcount,
-                                                        s4 retidx)
-{
-       s4 i;
-
-       close_block(iln, iln, n_bptr, iln->n_passthroughcount + o_bptr->outdepth + retcount);
-
-       /* translate the outvars of the original block */
-
-       /* XXX reuse code */
-       for (i=0; i<o_bptr->outdepth; ++i) {
-               n_bptr->outvars[iln->n_passthroughcount + i] =
-                       inline_translate_variable(iln->ctx->resultjd, iln->jd, varmap,
-                                       o_bptr->outvars[i]);
-       }
-
-       /* set the return variable, if any */
-
-       if (retcount) {
-               assert(retidx >= 0);
-               n_bptr->outvars[iln->n_passthroughcount + o_bptr->outdepth] = retidx;
-       }
-}
-
-
-/* inlined code generation ****************************************************/
-
-static instruction * inline_instruction(inline_node *iln,
-                                                                               s4 opcode,
-                                                                               instruction *o_iptr)
-{
-       instruction *n_iptr;
-
-       n_iptr = (iln->inlined_iinstr_cursor++);
-       assert((n_iptr - iln->inlined_iinstr) < iln->cumul_instructioncount);
-
-       n_iptr->opc = opcode;
-       n_iptr->flags.bits = o_iptr->flags.bits & INS_FLAG_ID_MASK;
-       n_iptr->line = o_iptr->line;
-
-       return n_iptr;
-}
-
-static void inline_generate_sync_builtin(inline_node *iln,
-                                                                                inline_node *callee,
-                                                                                instruction *o_iptr,
-                                                                                s4 instancevar,
-                                                                                functionptr func)
-{
-       int          syncvar;
-       instruction *n_ins;
-
-       if (callee->m->flags & ACC_STATIC) {
-               /* ACONST */
-               syncvar = inline_new_temp_variable(iln->ctx->resultjd, TYPE_ADR);
-
-               n_ins = inline_instruction(iln, ICMD_ACONST, o_iptr);
-               n_ins->sx.val.c.cls = callee->m->clazz;
-               n_ins->dst.varindex = syncvar;
-               n_ins->flags.bits |= INS_FLAG_CLASS;
-       }
-       else {
-               syncvar = instancevar;
-       }
-
-       assert(syncvar != UNUSED);
-
-       /* MONITORENTER / MONITOREXIT */
-
-       n_ins = inline_instruction(iln, ICMD_BUILTIN, o_iptr);
-       n_ins->sx.s23.s3.bte = builtintable_get_internal(func);
-       n_ins->s1.argcount = 1; /* XXX add through-vars */
-       n_ins->sx.s23.s2.args = DMNEW(s4, 1);
-       n_ins->sx.s23.s2.args[0] = syncvar;
-}
-
-static s4 emit_inlining_prolog(inline_node *iln,
-                                                          inline_node *callee,
-                                                          instruction *o_iptr,
-                                                          s4 *varmap)
-{
-       methodinfo *calleem;
-       methoddesc *md;
-       int i;
-       int localindex;
-       int type;
-       instruction *n_ins;
-       insinfo_inline *insinfo;
-       s4 varindex;
-
-       assert(iln && callee && o_iptr);
-
-       calleem = callee->m;
-       md = calleem->parseddesc;
-
-       /* INLINE_START instruction */
-
-       n_ins = inline_instruction(iln, ICMD_INLINE_START, o_iptr);
-
-       insinfo = DNEW(insinfo_inline);
-       insinfo->method = callee->m;
-       insinfo->outer = iln->m;
-       insinfo->synclocal = callee->synclocal;
-       insinfo->synchronize = callee->synchronize;
-       insinfo->javalocals_start = NULL;
-       insinfo->javalocals_end = NULL;
-
-       /* info about stack vars live at the INLINE_START */
-
-       insinfo->throughcount = callee->n_passthroughcount;
-       insinfo->paramcount = md->paramcount;
-       insinfo->stackvarscount = o_iptr->s1.argcount;
-       insinfo->stackvars = DMNEW(s4, insinfo->stackvarscount);
-       for (i=0; i<insinfo->stackvarscount; ++i)
-               insinfo->stackvars[i] = iln->varmap[o_iptr->sx.s23.s2.args[i]];
-
-       /* info about the surrounding inlining */
-
-       if (iln->inline_start_instruction)
-               insinfo->parent = iln->inline_start_instruction->sx.s23.s3.inlineinfo;
-       else
-               insinfo->parent = NULL;
-
-       /* finish the INLINE_START instruction */
-
-       n_ins->sx.s23.s3.inlineinfo = insinfo;
-       callee->inline_start_instruction = n_ins;
-
-       DOLOG( printf("%sprolog: ", iln->indent);
-                  show_icmd(iln->ctx->resultjd, n_ins, false, SHOW_STACK); printf("\n"); );
-
-       /* handle parameters for the inlined callee */
-
-       localindex = callee->localsoffset + md->paramslots;
-
-       for (i=md->paramcount-1; i>=0; --i) {
-               assert(iln);
-
-               type = md->paramtypes[i].type;
-
-               localindex -= IS_2_WORD_TYPE(type) ? 2 : 1;
-               assert(callee->regdata);
-
-               /* translate the argument variable */
-
-               varindex = varmap[o_iptr->sx.s23.s2.args[i]];
-               assert(varindex != UNUSED);
-
-               /* remove preallocation from the argument variable */
-
-               iln->ctx->resultjd->var[varindex].flags &= ~(PREALLOC | INMEMORY);
-
-               /* check the instance slot against NULL */
-               /* we don't need that for <init> methods, as the verifier  */
-               /* ensures that they are only called for an uninit. object */
-               /* (which may not be NULL).                                */
-
-               if (!callee->isstatic && i == 0 && calleem->name != utf_init) {
-                       assert(type == TYPE_ADR);
-                       n_ins = inline_instruction(iln, ICMD_CHECKNULL, o_iptr);
-                       n_ins->s1.varindex = varindex;
-                       n_ins->dst.varindex = n_ins->s1.varindex;
-               }
-
-               /* store argument into local variable of inlined callee */
-
-               if (callee->jd->local_map[5*(localindex - callee->localsoffset) + type] != UNUSED)
-               {
-                       /* this value is used in the callee */
-
-                       if (i == 0 && callee->synclocal != UNUSED) {
-                               /* we also need it for synchronization, so copy it */
-                               assert(type == TYPE_ADR);
-                               n_ins = inline_instruction(iln, ICMD_COPY, o_iptr);
-                       }
-                       else {
-                               n_ins = inline_instruction(iln, ICMD_ISTORE + type, o_iptr);
-                               n_ins->sx.s23.s3.javaindex = UNUSED;
-                       }
-                       n_ins->s1.varindex = varindex;
-                       n_ins->dst.varindex = iln->ctx->resultjd->local_map[5*localindex + type];
-                       assert(n_ins->dst.varindex != UNUSED);
-               }
-               else if (i == 0 && callee->synclocal != UNUSED) {
-                       /* the value is not used inside the callee, but we need it for */
-                       /* synchronization                                             */
-                       /* XXX In this case it actually makes no sense to create a     */
-                       /*     separate synchronization variable.                      */
-
-                       n_ins = inline_instruction(iln, ICMD_NOP, o_iptr);
-               }
-               else {
-                       /* this value is not used, pop it */
-
-                       n_ins = inline_instruction(iln, ICMD_POP, o_iptr);
-                       n_ins->s1.varindex = varindex;
-               }
-
-               DOLOG( printf("%sprolog: ", iln->indent);
-                          show_icmd(iln->ctx->resultjd, n_ins, false, SHOW_STACK); printf("\n"); );
-       }
-
-       /* COPY for synchronized instance methods */
-
-       if (callee->synclocal != UNUSED) {
-               n_ins = inline_instruction(iln, ICMD_COPY, o_iptr);
-               n_ins->s1.varindex = varmap[o_iptr->sx.s23.s2.args[0]];
-               n_ins->dst.varindex = callee->synclocal;
-
-               assert(n_ins->s1.varindex != UNUSED);
-       }
-
-       if (callee->synchronize) {
-               inline_generate_sync_builtin(iln, callee, o_iptr,
-                                                                        (callee->isstatic) ? UNUSED : varmap[o_iptr->sx.s23.s2.args[0]],
-                                                                        LOCK_monitor_enter);
-       }
-
-       /* INLINE_BODY instruction */
-
-       n_ins = inline_instruction(iln, ICMD_INLINE_BODY, callee->jd->basicblocks[0].iinstr);
-       n_ins->sx.s23.s3.inlineinfo = insinfo;
-
-       return 0; /* XXX */
-}
-
-
-static void emit_inlining_epilog(inline_node *iln, inline_node *callee, instruction *o_iptr)
-{
-       instruction *n_ins;
-       s4          *jl;
-
-       assert(iln && callee && o_iptr);
-       assert(callee->inline_start_instruction);
-
-       if (callee->synchronize) {
-               inline_generate_sync_builtin(iln, callee, o_iptr,
-                                                                        callee->synclocal,
-                                                                        LOCK_monitor_exit);
-       }
-
-       /* INLINE_END instruction */
-
-       n_ins = inline_instruction(iln, ICMD_INLINE_END, o_iptr);
-       n_ins->sx.s23.s3.inlineinfo = callee->inline_start_instruction->sx.s23.s3.inlineinfo;
-
-       /* set the javalocals */
-
-       jl = DMNEW(s4, iln->jd->maxlocals);
-       MCOPY(jl, iln->javalocals, s4, iln->jd->maxlocals);
-       n_ins->sx.s23.s3.inlineinfo->javalocals_end = jl;
-
-       DOLOG( printf("%sepilog: ", iln->indent);
-                  show_icmd(iln->ctx->resultjd, n_ins, false, SHOW_STACK); printf("\n"); );
-}
-
-
-#define TRANSLATE_VAROP(vo)  \
-       n_iptr->vo.varindex = inline_translate_variable(jd, origjd, varmap, n_iptr->vo.varindex)
-
-
-static void inline_clone_instruction(inline_node *iln,
-                                                                        jitdata *jd,
-                                                                        jitdata *origjd,
-                                                                        s4 *varmap,
-                                                                        instruction *o_iptr,
-                                                                        instruction *n_iptr)
-{
-       icmdtable_entry_t *icmdt;
-       builtintable_entry *bte;
-       methoddesc *md;
-       s4 i, j;
-       branch_target_t *table;
-       lookup_target_t *lookup;
-       inline_node *scope;
-
-       *n_iptr = *o_iptr;
-
-       icmdt = &(icmd_table[o_iptr->opc]);
-
-       switch (icmdt->dataflow) {
-               case DF_0_TO_0:
-                       break;
-
-               case DF_3_TO_0:
-                       TRANSLATE_VAROP(sx.s23.s3);
-               case DF_2_TO_0:
-                       TRANSLATE_VAROP(sx.s23.s2);
-               case DF_1_TO_0:
-                       TRANSLATE_VAROP(s1);
-                       break;
-
-               case DF_2_TO_1:
-                       TRANSLATE_VAROP(sx.s23.s2);
-               case DF_1_TO_1:
-               case DF_COPY:
-               case DF_MOVE:
-                       TRANSLATE_VAROP(s1);
-               case DF_0_TO_1:
-                       TRANSLATE_VAROP(dst);
-                       break;
-
-               case DF_N_TO_1:
-                       n_iptr->sx.s23.s2.args = DMNEW(s4, n_iptr->s1.argcount);
-                       for (i=0; i<n_iptr->s1.argcount; ++i) {
-                               n_iptr->sx.s23.s2.args[i] =
-                                       inline_translate_variable(jd, origjd, varmap,
-                                                       o_iptr->sx.s23.s2.args[i]);
-                       }
-                       TRANSLATE_VAROP(dst);
-                       break;
-
-               case DF_INVOKE:
-                       INSTRUCTION_GET_METHODDESC(n_iptr, md);
-clone_call:
-                       n_iptr->s1.argcount += iln->n_passthroughcount;
-                       n_iptr->sx.s23.s2.args = DMNEW(s4, n_iptr->s1.argcount);
-                       for (i=0; i<o_iptr->s1.argcount; ++i) {
-                               n_iptr->sx.s23.s2.args[i] =
-                                       inline_translate_variable(jd, origjd, varmap,
-                                                       o_iptr->sx.s23.s2.args[i]);
-                       }
-                       for (scope = iln; scope != NULL; scope = scope->parent) {
-                               for (j = 0; j < scope->n_selfpassthroughcount; ++j) {
-                                       n_iptr->sx.s23.s2.args[i++] =
-                                               scope->parent->varmap[scope->n_passthroughvars[j]];
-                               }
-                       }
-                       if (md->returntype.type != TYPE_VOID)
-                               TRANSLATE_VAROP(dst);
-                       break;
-
-               case DF_BUILTIN:
-                       bte = n_iptr->sx.s23.s3.bte;
-                       md = bte->md;
-                       goto clone_call;
-
-               default:
-                       assert(0);
-       }
-
-       switch (icmdt->controlflow) {
-               case CF_RET:
-                       TRANSLATE_VAROP(s1); /* XXX should be handled by data-flow */
-                       /* FALLTHROUGH */
-               case CF_IF:
-               case CF_GOTO:
-                       inline_add_block_reference(iln, &(n_iptr->dst.block));
-                       break;
-
-               case CF_JSR:
-                       inline_add_block_reference(iln, &(n_iptr->sx.s23.s3.jsrtarget.block));
-                       break;
-
-               case CF_TABLE:
-                       i = n_iptr->sx.s23.s3.tablehigh - n_iptr->sx.s23.s2.tablelow + 1 + 1 /* default */;
-
-                       table = DMNEW(branch_target_t, i);
-                       MCOPY(table, o_iptr->dst.table, branch_target_t, i);
-                       n_iptr->dst.table = table;
-
-                       while (--i >= 0) {
-                               inline_add_block_reference(iln, &(table->block));
-                               table++;
-                       }
-                       break;
-
-               case CF_LOOKUP:
-                       inline_add_block_reference(iln, &(n_iptr->sx.s23.s3.lookupdefault.block));
-
-                       i = n_iptr->sx.s23.s2.lookupcount;
-                       lookup = DMNEW(lookup_target_t, i);
-                       MCOPY(lookup, o_iptr->dst.lookup, lookup_target_t, i);
-                       n_iptr->dst.lookup = lookup;
-
-                       while (--i >= 0) {
-                               inline_add_block_reference(iln, &(lookup->target.block));
-                               lookup++;
-                       }
-                       break;
-       }
-
-       /* XXX move this to dataflow section? */
-
-       switch (n_iptr->opc) {
-               case ICMD_ASTORE:
-#if 0
-                       if (n_iptr->flags.bits & INS_FLAG_RETADDR)
-                               inline_add_blocknr_reference(iln, &(n_iptr->sx.s23.s2.retaddrnr));
-#endif
-                       /* FALLTHROUGH! */
-               case ICMD_ISTORE:
-               case ICMD_LSTORE:
-               case ICMD_FSTORE:
-               case ICMD_DSTORE:
-                       stack_javalocals_store(n_iptr, iln->javalocals);
-                       break;
-       }
-}
-
-
-static void inline_rewrite_method(inline_node *iln)
-{
-       basicblock *o_bptr;
-       s4 len;
-       instruction *o_iptr;
-       instruction *n_iptr;
-       inline_node *nextcall;
-       basicblock *n_bptr;
-       inline_block_map *bm;
-       int i;
-       int icount;
-       jitdata *resultjd;
-       jitdata *origjd;
-       char indent[100]; /* XXX debug */
-       s4 retcount;
-       s4 retidx;
-
-       assert(iln);
-
-       resultjd = iln->ctx->resultjd;
-       origjd = iln->jd;
-
-       n_bptr = NULL;
-       nextcall = iln->children;
-
-       /* XXX debug */
-       for (i=0; i<iln->depth; ++i)
-               indent[i] = '\t';
-       indent[i] = 0;
-       iln->indent = indent;
-
-       DOLOG( printf("%srewriting: ", indent); method_println(iln->m);
-                  printf("%s(passthrough: %d+%d)\n",
-                               indent, iln->n_passthroughcount - iln->n_selfpassthroughcount,
-                               iln->n_passthroughcount); );
-
-       /* set memory cursors */
-
-       iln->inlined_iinstr_cursor = iln->inlined_iinstr;
-       iln->inlined_basicblocks_cursor = iln->inlined_basicblocks;
-
-       /* allocate temporary buffers */
-
-       iln->javalocals = DMNEW(s4, iln->jd->maxlocals);
-
-       /* loop over basic blocks */
-
-       o_bptr = iln->jd->basicblocks;
-       for (; o_bptr; o_bptr = o_bptr->next) {
-
-               if (o_bptr->flags < BBREACHED) {
-
-                       /* ignore the dummy end block */
-
-                       if (o_bptr->icount == 0 && o_bptr->next == NULL) {
-                               /* enter the following block as translation, for exception handler ranges */
-                               inline_block_translation(iln, o_bptr, iln->inlined_basicblocks_cursor);
-                               continue;
-                       }
-
-                       DOLOG(
-                       printf("%s* skipping old L%03d (flags=%d, type=%d, oid=%d) of ",
-                                       indent,
-                                       o_bptr->nr, o_bptr->flags, o_bptr->type,
-                                       o_bptr->indepth);
-                       method_println(iln->m);
-                       );
-
-                       n_bptr = create_body_block(iln, o_bptr, iln->varmap);
-
-                       /* enter it in the blockmap */
-
-                       inline_block_translation(iln, o_bptr, n_bptr);
-
-                       close_body_block(iln, n_bptr, o_bptr, iln->varmap, 0, -1);
-                       continue;
-               }
-
-               len = o_bptr->icount;
-               o_iptr = o_bptr->iinstr;
-
-               DOLOG(
-               printf("%s* rewriting old L%03d (flags=%d, type=%d, oid=%d) of ",
-                               indent,
-                               o_bptr->nr, o_bptr->flags, o_bptr->type,
-                               o_bptr->indepth);
-               method_println(iln->m);
-               show_basicblock(iln->jd, o_bptr, SHOW_STACK);
-               );
-
-               if (iln->blockbefore || o_bptr != iln->jd->basicblocks) {
-                       /* create an inlined clone of this block */
-
-                       n_bptr = create_body_block(iln, o_bptr, iln->varmap);
-                       icount = 0;
-
-                       /* enter it in the blockmap */
-
-                       inline_block_translation(iln, o_bptr, n_bptr);
-
-                       /* initialize the javalocals */
-
-                       MCOPY(iln->javalocals, n_bptr->javalocals, s4, iln->jd->maxlocals);
-               }
-               else {
-                       s4 *jl;
-
-                       /* continue caller block */
-
-                       n_bptr = iln->inlined_basicblocks_cursor - 1;
-                       icount = n_bptr->icount;
-
-                       /* translate the javalocals */
-
-                       jl = translate_javalocals(iln, o_bptr->javalocals);
-                       iln->inline_start_instruction->sx.s23.s3.inlineinfo->javalocals_start = jl;
-
-                       MCOPY(iln->javalocals, jl, s4, iln->jd->maxlocals);
-               }
-
-               /* iterate over the ICMDs of this block */
-
-               retcount = 0;
-               retidx = UNUSED;
-
-               while (--len >= 0) {
-
-                       DOLOG( fputs(indent, stdout); show_icmd(iln->jd, o_iptr, false,  SHOW_STACK);
-                                  printf("\n") );
-
-                       /* handle calls that will be inlined */
-
-                       if (nextcall && o_iptr == nextcall->callerins) {
-
-                               /* write the inlining prolog */
-
-                               (void) emit_inlining_prolog(iln, nextcall, o_iptr, iln->varmap);
-                               icount += nextcall->prolog_instructioncount;
-
-                               /* end current block, or glue blocks together */
-
-                               n_bptr->icount = icount;
-
-                               if (nextcall->blockbefore) {
-                                       close_prolog_block(iln, n_bptr, nextcall);
-                               }
-                               else {
-                                       /* XXX */
-                               }
-
-                               /* check if the result is a local variable */
-
-                               if (nextcall->m->parseddesc->returntype.type != TYPE_VOID
-                                               && o_iptr->dst.varindex < iln->jd->localcount)
-                               {
-                                       nextcall->n_resultlocal = iln->varmap[o_iptr->dst.varindex];
-                               }
-                               else
-                                       nextcall->n_resultlocal = -1;
-
-                               /* set memory pointers in the callee */
-
-                               nextcall->inlined_iinstr = iln->inlined_iinstr_cursor;
-                               nextcall->inlined_basicblocks = iln->inlined_basicblocks_cursor;
-
-                               /* recurse */
-
-                               DOLOG( printf("%sentering inline ", indent);
-                                          show_icmd(origjd, o_iptr, false, SHOW_STACK); printf("\n") );
-
-                               inline_rewrite_method(nextcall);
-
-                               DOLOG( printf("%sleaving inline ", indent);
-                                          show_icmd(origjd, o_iptr, false, SHOW_STACK); printf("\n") );
-
-                               /* update memory cursors */
-
-                               assert(nextcall->inlined_iinstr_cursor
-                                               <= iln->inlined_iinstr_cursor + nextcall->cumul_instructioncount);
-                               assert(nextcall->inlined_basicblocks_cursor
-                                               == iln->inlined_basicblocks_cursor + nextcall->cumul_basicblockcount);
-                               iln->inlined_iinstr_cursor = nextcall->inlined_iinstr_cursor;
-                               iln->inlined_basicblocks_cursor = nextcall->inlined_basicblocks_cursor;
-
-                               /* start new block, or glue blocks together */
-
-                               if (nextcall->blockafter) {
-                                       n_bptr = create_epilog_block(iln, nextcall, iln->varmap);
-                                       icount = 0;
-                               }
-                               else {
-                                       n_bptr = iln->inlined_basicblocks_cursor - 1;
-                                       icount = n_bptr->icount;
-                                       /* XXX */
-                               }
-
-                               /* emit inlining epilog */
-
-                               emit_inlining_epilog(iln, nextcall, o_iptr);
-                               icount += nextcall->epilog_instructioncount;
-
-                               /* proceed to next call */
-
-                               nextcall = nextcall->next;
-                       }
-                       else {
-                               n_iptr = (iln->inlined_iinstr_cursor++);
-                               assert((n_iptr - iln->inlined_iinstr) < iln->cumul_instructioncount);
-
-                               switch (o_iptr->opc) {
-                                       case ICMD_RETURN:
-                                               if (iln->depth == 0)
-                                                       goto default_clone;
-                                               goto return_tail;
-
-                                       case ICMD_IRETURN:
-                                       case ICMD_ARETURN:
-                                       case ICMD_LRETURN:
-                                       case ICMD_FRETURN:
-                                       case ICMD_DRETURN:
-                                               if (iln->depth == 0)
-                                                       goto default_clone;
-                                               retcount = 1;
-                                               retidx = iln->varmap[o_iptr->s1.varindex];
-                                               if (iln->n_resultlocal != -1) {
-                                                       /* store result in a local variable */
-
-                                                       DOLOG( printf("USING RESULTLOCAL %d\n", iln->n_resultlocal); );
-                                                       /* This relies on the same sequence of types for */
-                                                       /* ?STORE and ?RETURN opcodes.                   */
-                                                       n_iptr->opc = ICMD_ISTORE + (o_iptr->opc - ICMD_IRETURN);
-                                                       n_iptr->s1.varindex = retidx;
-                                                       n_iptr->dst.varindex = iln->n_resultlocal;
-                                                       n_iptr->sx.s23.s3.javaindex = UNUSED; /* XXX set real javaindex? */
-
-                                                       retcount = 0;
-                                                       retidx = UNUSED;
-
-                                                       n_iptr = (iln->inlined_iinstr_cursor++);
-                                                       assert((n_iptr - iln->inlined_iinstr) < iln->cumul_instructioncount);
-                                                       icount++;
-                                               }
-                                               else if ((retidx < resultjd->localcount && iln->blockafter)
-                                                               || !iln->blockafter) /* XXX do we really always need the MOVE? */
-                                               {
-                                                       /* local must not become outvar, insert a MOVE */
-
-                                                       n_iptr->opc = ICMD_MOVE;
-                                                       n_iptr->s1.varindex = retidx;
-                                                       retidx = inline_new_temp_variable(resultjd,
-                                                                                                                         resultjd->var[retidx].type);
-                                                       n_iptr->dst.varindex = retidx;
-
-                                                       n_iptr = (iln->inlined_iinstr_cursor++);
-                                                       assert((n_iptr - iln->inlined_iinstr) < iln->cumul_instructioncount);
-                                                       icount++;
-                                               }
-return_tail:
-                                               if (iln->blockafter) {
-                                                       n_iptr->opc = ICMD_GOTO;
-                                                       n_iptr->dst.block = INLINE_RETURN_REFERENCE(iln);
-                                                       inline_add_block_reference(iln, &(n_iptr->dst.block));
-                                               }
-                                               else {
-                                                       n_iptr->opc = ICMD_NOP;
-                                               }
-                                               break;
-#if 0
-                                               if (o_bptr->next == NULL || (o_bptr->next->icount==0 && o_bptr->next->next == NULL)) {
-                                                       n_iptr->opc = ICMD_NOP;
-                                                       break;
-                                               }
-                                               goto default_clone;
-                                               break;
-#endif
-
-                                       default:
-default_clone:
-                                               inline_clone_instruction(iln, resultjd, iln->jd, iln->varmap, o_iptr, n_iptr);
-                               }
-
-                               DOLOG( fputs(indent, stdout); show_icmd(resultjd, n_iptr, false, SHOW_STACK);
-                                          printf("\n"););
-
-                               icount++;
-                       }
-
-                       o_iptr++;
-               }
-
-               /* end of basic block */
-
-               if (iln->blockafter || (o_bptr->next && o_bptr->next->next)) {
-                       close_body_block(iln, n_bptr, o_bptr, iln->varmap, retcount, retidx);
-                       n_bptr->icount = icount;
-
-                       DOLOG( printf("closed body block:\n");
-                                  show_basicblock(resultjd, n_bptr, SHOW_STACK); );
-               }
-               else {
-                       n_bptr->icount = icount;
-                       assert(iln->parent);
-                       if (retidx != UNUSED)
-                               iln->parent->varmap[iln->callerins->dst.varindex] = retidx;
-               }
-       }
-
-       bm = iln->ctx->blockmap;
-       for (i=0; i<iln->ctx->blockmap_index; ++i, ++bm) {
-               assert(bm->iln && bm->o_block && bm->n_block);
-               if (bm->iln == iln)
-                       inline_resolve_block_refs(&(iln->refs), bm->o_block, bm->n_block, false);
-       }
-
-#if !defined(NDEBUG)
-       if (iln->refs) {
-               inline_target_ref *ref;
-               ref = iln->refs;
-               while (ref) {
-                       if (!iln->depth || ref->isnumber || *(ref->ref.block) != INLINE_RETURN_REFERENCE(iln)) {
-                               DOLOG( printf("XXX REMAINING REF at depth %d: %p\n", iln->depth,
-                                          (void*)*(ref->ref.block)) );
-                               assert(false);
-                       }
-                       ref = ref->next;
-               }
-       }
-#endif
-}
-
-
-static exception_entry * inline_exception_tables(inline_node *iln,
-                                                                                                exception_entry *n_extable,
-                                                                                                exception_entry **prevextable)
-{
-       inline_node *child;
-       inline_node *scope;
-       exception_entry *et;
-
-       assert(iln);
-       assert(n_extable);
-       assert(prevextable);
-
-       child = iln->children;
-       if (child) {
-               do {
-                       n_extable = inline_exception_tables(child, n_extable, prevextable);
-                       child = child->next;
-               } while (child != iln->children);
-       }
-
-       et = iln->jd->exceptiontable;
-       for (; et != NULL; et = et->down) {
-               assert(et);
-               MZERO(n_extable, exception_entry, 1);
-               n_extable->start     = inline_map_block(iln, et->start  , iln);
-               n_extable->end       = inline_map_block(iln, et->end    , iln);
-               n_extable->handler   = inline_map_block(iln, et->handler, iln);
-               n_extable->catchtype = et->catchtype;
-
-               if (*prevextable) {
-                       (*prevextable)->down = n_extable;
-               }
-               *prevextable = n_extable;
-
-               n_extable++;
-       }
-
-       if (iln->handler_monitorexit) {
-               exception_entry **activehandlers;
-
-               MZERO(n_extable, exception_entry, 1);
-               n_extable->start   = iln->inlined_basicblocks;
-               n_extable->end     = iln->inlined_basicblocks_cursor;
-               n_extable->handler = iln->handler_monitorexit;
-               n_extable->catchtype.any = NULL; /* finally */
-
-               if (*prevextable) {
-                       (*prevextable)->down = n_extable;
-               }
-               *prevextable = n_extable;
-
-               n_extable++;
-
-               /* We have to protect the created handler with the same handlers */
-               /* that protect the method body itself.                          */
-
-               for (scope = iln; scope->parent != NULL; scope = scope->parent) {
-
-                       activehandlers = scope->o_handlers;
-                       assert(activehandlers);
-
-                       while (*activehandlers) {
-
-                               assert(scope->parent);
-
-                               MZERO(n_extable, exception_entry, 1);
-                               n_extable->start     = iln->handler_monitorexit;
-                               n_extable->end       = iln->handler_monitorexit + 1; /* XXX ok in this case? */
-                               n_extable->handler   = inline_map_block(scope->parent,
-                                                                                                               (*activehandlers)->handler,
-                                                                                                               scope->parent);
-                               n_extable->catchtype = (*activehandlers)->catchtype;
-
-                               if (*prevextable) {
-                                       (*prevextable)->down = n_extable;
-                               }
-                               *prevextable = n_extable;
-
-                               n_extable++;
-                               activehandlers++;
-                       }
-               }
-       }
-
-       return n_extable;
-}
-
-
-static void inline_locals(inline_node *iln)
-{
-       inline_node *child;
-
-       assert(iln);
-
-       iln->varmap = create_variable_map(iln);
-
-       child = iln->children;
-       if (child) {
-               do {
-                       inline_locals(child);
-                       child = child->next;
-               } while (child != iln->children);
-       }
-
-       if (iln->regdata->memuse > iln->ctx->resultjd->rd->memuse)
-               iln->ctx->resultjd->rd->memuse = iln->regdata->memuse;
-       if (iln->regdata->argintreguse > iln->ctx->resultjd->rd->argintreguse)
-               iln->ctx->resultjd->rd->argintreguse = iln->regdata->argintreguse;
-       if (iln->regdata->argfltreguse > iln->ctx->resultjd->rd->argfltreguse)
-               iln->ctx->resultjd->rd->argfltreguse = iln->regdata->argfltreguse;
-}
-
-
-static void inline_interface_variables(inline_node *iln)
-{
-       basicblock *bptr;
-       jitdata *resultjd;
-       s4 i;
-       varinfo *v;
-
-       resultjd = iln->ctx->resultjd;
-
-       resultjd->interface_map = DMNEW(interface_info, 5*iln->ctx->maxinoutdepth);
-       for (i=0; i<5*iln->ctx->maxinoutdepth; ++i)
-               resultjd->interface_map[i].flags = UNUSED;
-
-       for (bptr = resultjd->basicblocks; bptr != NULL; bptr = bptr->next) {
-               assert(bptr->indepth  <= iln->ctx->maxinoutdepth);
-               assert(bptr->outdepth <= iln->ctx->maxinoutdepth);
-
-               for (i=0; i<bptr->indepth; ++i) {
-                       v = &(resultjd->var[bptr->invars[i]]);
-                       v->flags |= INOUT;
-                       if (v->type == TYPE_RET)
-                               v->flags |= PREALLOC;
-                       else
-                               v->flags &= ~PREALLOC;
-                       v->flags &= ~INMEMORY;
-                       assert(bptr->invars[i] >= resultjd->localcount);
-
-                       if (resultjd->interface_map[5*i + v->type].flags == UNUSED) {
-                               resultjd->interface_map[5*i + v->type].flags = v->flags;
-                       }
-                       else {
-                               resultjd->interface_map[5*i + v->type].flags |= v->flags;
-                       }
-               }
-
-               for (i=0; i<bptr->outdepth; ++i) {
-                       v = &(resultjd->var[bptr->outvars[i]]);
-                       v->flags |= INOUT;
-                       if (v->type == TYPE_RET)
-                               v->flags |= PREALLOC;
-                       else
-                               v->flags &= ~PREALLOC;
-                       v->flags &= ~INMEMORY;
-                       assert(bptr->outvars[i] >= resultjd->localcount);
-
-                       if (resultjd->interface_map[5*i + v->type].flags == UNUSED) {
-                               resultjd->interface_map[5*i + v->type].flags = v->flags;
-                       }
-                       else {
-                               resultjd->interface_map[5*i + v->type].flags |= v->flags;
-                       }
-               }
-       }
-}
-
-
-static void inline_write_exception_handlers(inline_node *master, inline_node *iln)
-{
-       basicblock *n_bptr;
-       instruction *n_ins;
-       inline_node *child;
-       builtintable_entry *bte;
-       s4 exvar;
-       s4 syncvar;
-       s4 i;
-
-       child = iln->children;
-       if (child) {
-               do {
-                       inline_write_exception_handlers(master, child);
-                       child = child->next;
-               } while (child != iln->children);
-       }
-
-       if (iln->synchronize) {
-               /* create the monitorexit handler */
-               n_bptr = create_block(master, iln, iln,
-                                                         iln->n_passthroughcount + 1);
-               n_bptr->type = BBTYPE_EXH;
-               n_bptr->flags = BBFINISHED;
-
-               exvar = inline_new_variable(master->ctx->resultjd, TYPE_ADR, 0);
-               n_bptr->invars[iln->n_passthroughcount] = exvar;
-
-               iln->handler_monitorexit = n_bptr;
-
-               /* ACONST / ALOAD */
-
-               n_ins = master->inlined_iinstr_cursor++;
-               if (iln->m->flags & ACC_STATIC) {
-                       n_ins->opc = ICMD_ACONST;
-                       n_ins->sx.val.c.cls = iln->m->clazz;
-                       n_ins->flags.bits = INS_FLAG_CLASS;
-               }
-               else {
-                       n_ins->opc = ICMD_ALOAD;
-                       n_ins->s1.varindex = iln->synclocal;
-                       assert(n_ins->s1.varindex != UNUSED);
-               }
-               /* XXX could be PREALLOCed for  builtin call */
-               syncvar = inline_new_variable(master->ctx->resultjd, TYPE_ADR, 0);
-               n_ins->dst.varindex = syncvar;
-               n_ins->line = 0;
-
-               /* MONITOREXIT */
-
-               bte = builtintable_get_internal(LOCK_monitor_exit);
-
-               n_ins = master->inlined_iinstr_cursor++;
-               n_ins->opc = ICMD_BUILTIN;
-               n_ins->s1.argcount = 1 + iln->n_passthroughcount + 1;
-               n_ins->sx.s23.s2.args = DMNEW(s4, n_ins->s1.argcount);
-               n_ins->sx.s23.s2.args[0] = syncvar;
-               for (i=0; i < iln->n_passthroughcount + 1; ++i) {
-                       n_ins->sx.s23.s2.args[1 + i] = n_bptr->invars[i];
-               }
-               n_ins->sx.s23.s3.bte = bte;
-               n_ins->line = 0;
-
-               /* ATHROW */
-
-               n_ins = master->inlined_iinstr_cursor++;
-               n_ins->opc = ICMD_ATHROW;
-               n_ins->flags.bits = 0;
-               n_ins->s1.varindex = exvar;
-               n_ins->line = 0;
-
-               /* close basic block */
-
-               close_block(iln, iln, n_bptr, iln->n_passthroughcount);
-               n_bptr->icount = 3;
-       }
-}
-
-
-/* second pass driver *********************************************************/
-
-static bool inline_transform(inline_node *iln, jitdata *jd)
-{
-       instruction *n_ins;
-       basicblock *n_bb;
-       basicblock *n_bptr;
-       exception_entry *n_ext;
-       exception_entry *prevext;
-       codegendata *n_cd;
-       jitdata *n_jd;
-       s4 i;
-#if defined(INLINE_VERIFY_RESULT)
-       static int debug_verify_inlined_code = 1;
-#endif
-#if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
-       static int debug_counter = 0;
-#endif
-
-       DOLOG( dump_inline_tree(iln, 0); );
-
-       assert(iln && jd);
-
-       n_ins = DMNEW(instruction, iln->cumul_instructioncount);
-       MZERO(n_ins, instruction, iln->cumul_instructioncount);
-       iln->inlined_iinstr = n_ins;
-
-       n_bb = DMNEW(basicblock, iln->cumul_basicblockcount);
-       MZERO(n_bb, basicblock, iln->cumul_basicblockcount);
-       iln->inlined_basicblocks = n_bb;
-
-       iln->ctx->blockmap = DMNEW(inline_block_map, iln->cumul_blockmapcount);
-
-       n_jd = jit_jitdata_new(iln->m);
-       n_jd->flags = jd->flags;
-       n_jd->code->optlevel = jd->code->optlevel;
-       iln->ctx->resultjd = n_jd;
-
-       reg_setup(n_jd);
-
-       /* create the local_map */
-
-       n_jd->local_map = DMNEW(s4, 5*iln->cumul_maxlocals);
-       for (i=0; i<5*iln->cumul_maxlocals; ++i)
-               n_jd->local_map[i] = UNUSED;
-
-       /* create / coalesce local variables */
-
-       n_jd->varcount = 0;
-       n_jd->vartop = 0;
-       n_jd->var = NULL;
-
-       inline_locals(iln);
-
-       n_jd->localcount = n_jd->vartop;
-
-       /* extra variables for verification (debugging) */
-
-#if defined(INLINE_VERIFY_RESULT)
-       if (debug_verify_inlined_code) {
-               n_jd->vartop   += VERIFIER_EXTRA_LOCALS + VERIFIER_EXTRA_VARS + 100 /* XXX m->maxstack */;
-               if (n_jd->vartop > n_jd->varcount) {
-                       /* XXX why? */
-                       n_jd->var = DMREALLOC(n_jd->var, varinfo, n_jd->varcount, n_jd->vartop);
-                       n_jd->varcount = n_jd->vartop;
-               }
-       }
-#endif /* defined(INLINE_VERIFY_RESULT) */
-
-       /* write inlined code */
-
-       inline_rewrite_method(iln);
-
-       /* create exception handlers */
-
-       inline_write_exception_handlers(iln, iln);
-
-       /* write the dummy end block */
-
-       n_bptr = create_block(iln, iln, iln, 0);
-       n_bptr->flags = BBUNDEF;
-       n_bptr->type = BBTYPE_STD;
-
-       /* store created code in jitdata */
-
-       n_jd->basicblocks = iln->inlined_basicblocks;
-       n_jd->instructioncount = iln->cumul_instructioncount;
-       n_jd->instructions = iln->inlined_iinstr;
-
-       /* link the basic blocks (dummy end block is not counted) */
-
-       n_jd->basicblockcount = (iln->inlined_basicblocks_cursor - iln->inlined_basicblocks) - 1;
-       for (i=0; i<n_jd->basicblockcount + 1; ++i)
-               n_jd->basicblocks[i].next = &(n_jd->basicblocks[i+1]);
-       if (i)
-               n_jd->basicblocks[i-1].next = NULL;
-
-       /* check basicblock numbers */
-
-#if !defined(NDEBUG)
-       jit_check_basicblock_numbers(n_jd);
-#endif
-
-       /* create the exception table */
-
-       if (iln->cumul_exceptiontablelength) {
-               exception_entry *tableend;
-
-               n_ext = DMNEW(exception_entry, iln->cumul_exceptiontablelength);
-               prevext = NULL;
-               tableend = inline_exception_tables(iln, n_ext, &prevext);
-               assert(tableend == n_ext + iln->cumul_exceptiontablelength);
-               if (prevext)
-                       prevext->down = NULL;
-
-               n_jd->exceptiontablelength = iln->cumul_exceptiontablelength;
-               n_jd->exceptiontable = n_ext;
-       }
-       else {
-               n_ext = NULL;
-       }
-
-       /*******************************************************************************/
-
-       n_cd = n_jd->cd;
-       memcpy(n_cd, jd->cd, sizeof(codegendata));
-
-       n_cd->method = NULL; /* XXX */
-       n_jd->maxlocals = iln->cumul_maxlocals;
-       n_jd->maxinterfaces = iln->ctx->maxinoutdepth;
-
-       inline_post_process(n_jd);
-
-       inline_interface_variables(iln);
-
-       /* for debugging, verify the inlined result */
-
-#if defined(INLINE_VERIFY_RESULT)
-       if (debug_verify_inlined_code) {
-               debug_verify_inlined_code = 0;
-               DOLOG( printf("VERIFYING INLINED RESULT...\n"); fflush(stdout); );
-               if (!typecheck(n_jd)) {
-                       exceptions_clear_exception();
-                       DOLOG( printf("XXX INLINED RESULT DID NOT PASS VERIFIER XXX\n") );
-                       return false;
-               }
-               else {
-                       DOLOG( printf("VERIFICATION PASSED.\n") );
-               }
-               debug_verify_inlined_code = 1;
-       }
-#endif /* defined(INLINE_VERIFY_RESULT) */
-
-       /* we need bigger free memory stacks (XXX these should not be allocated in reg_setup) */
-
-       n_jd->rd->freemem = DMNEW(s4, iln->ctx->maxinoutdepth + 1000) /* XXX max vars/block */;
-
-#if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
-       if (   (n_jd->instructioncount >= opt_InlineMinSize)
-               && (n_jd->instructioncount <= opt_InlineMaxSize))
-       {
-          if (debug_counter < opt_InlineCount)
-#endif /* defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG) */
-          {
-                       /* install the inlined result */
-
-                       *jd->code = *n_jd->code;
-                       n_jd->code = jd->code;
-                       *jd = *n_jd;
-
-                       /* statistics and logging */
-
-#if !defined(NDEBUG)
-                       inline_stat_roots++;
-
-                       DOLOG_SHORT(
-                       printf("==== %d.INLINE ==================================================================\n",
-                               debug_counter);
-                       printf("\ninline tree:\n");
-                       dump_inline_tree(iln, 0);
-                       n_jd->flags |= JITDATA_FLAG_SHOWINTERMEDIATE | JITDATA_FLAG_SHOWDISASSEMBLE;
-                       /* debug_dump_inlined_code(iln, n_method, n_cd, n_rd); */
-                       printf("-------- DONE -----------------------------------------------------------\n");
-                       fflush(stdout);
-                       );
-#endif
-          }
-
-#if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
-               debug_counter++;
-       }
-#endif
-       return true;
-}
-
-
-/******************************************************************************/
-/* FIRST PASS: build inlining tree                                            */
-/******************************************************************************/
-
-
-/* inline_pre_parse_heuristics *************************************************
-
-   Perform heuristic checks whether a call site should be inlined.
-   These checks are evaluated before the callee has been parsed and analysed.
-
-   IN:
-       caller...........inlining node of the caller
-          callee...........the called method
-          site.............information on the call site
-
-   RETURN VALUE:
-       true........consider for inlining
-          false.......don't inline
-
-*******************************************************************************/
-
-static bool inline_pre_parse_heuristics(const inline_node *caller,
-                                                                               const methodinfo *callee,
-                                                                               inline_site *site)
-{
-#if defined(INLINE_MAX_DEPTH)
-       if (caller->depth >= INLINE_MAX_DEPTH)
-               return false;
-#endif
-
-       return true;
-}
-
-
-/* inline_post_parse_heuristics ************************************************
-
-   Perform heuristic checks whether a call site should be inlined.
-   These checks are evaluated after the callee has been parsed and analysed.
-
-   IN:
-       caller...........inlining node of the caller (const)
-          callee...........the called method (const)
-
-   RETURN VALUE:
-          true........consider for inlining
-          false.......don't inline
-
-*******************************************************************************/
-
-static bool inline_post_parse_heuristics(const inline_node *caller,
-                                                                                const inline_node *callee)
-{
-       return true;
-}
-
-
-/* inline_afterwards_heuristics ************************************************
-
-   Perform heuristic checks whether a call site should be inlined.
-   These checks are evaluated after the inlining plan for the callee has
-   been made.
-
-   IN:
-       caller...........inlining node of the caller (const)
-          callee...........the called method (const)
-
-   RETURN VALUE:
-          true........consider for inlining
-          false.......don't inline
-
-*******************************************************************************/
-
-static bool inline_afterwards_heuristics(const inline_node *caller,
-                                                                                const inline_node *callee)
-{
-       inline_node *cumulator;
-
-#if defined(INLINE_DEPTH_FIRST)
-       cumulator = caller;
-#else
-       cumulator = caller->ctx->master;
-#endif
-
-       if (0
-#if defined(INLINE_MAX_BLOCK_EXPANSION)
-               || (cumulator->cumul_basicblockcount + callee->cumul_basicblockcount
-                       > INLINE_MAX_BLOCK_EXPANSION*caller->ctx->master->jd->basicblockcount)
-#endif
-#if defined(INLINE_MAX_ICMD_EXPANSION)
-               || (cumulator->cumul_instructioncount + callee->cumul_instructioncount
-                       > INLINE_MAX_ICMD_EXPANSION*caller->ctx->master->jd->instructioncount)
-#endif
-          )
-       {
-               return false;
-       }
-
-       return true;
-}
-
-
-/* inline_is_monomorphic *******************************************************
-
-   Check if the given call site can be proven to be monomorphic.
-
-   IN:
-          callee...........the called method
-          call.............the invocation instruction
-
-   OUT:
-       site->speculative.....flags whether the inlining is speculative
-                                (only defined if return value is true)
-
-   RETURN VALUE:
-       true if the call site is (currently) monomorphic,
-          false if not or unknown
-
-*******************************************************************************/
-
-static bool inline_is_monomorphic(const methodinfo *callee,
-                                                                 const instruction *call,
-                                                                 inline_site *site)
-{
-       if ((callee->flags & (ACC_STATIC | ACC_FINAL | ACC_PRIVATE)
-                               || call->opc == ICMD_INVOKESPECIAL))
-       {
-               site->speculative = false;
-               return true;
-       }
-
-       /* XXX search single implementation for abstract monomorphics */
-
-       if ((callee->flags & (ACC_METHOD_MONOMORPHIC | ACC_METHOD_IMPLEMENTED
-                                       | ACC_ABSTRACT))
-                       == (ACC_METHOD_MONOMORPHIC | ACC_METHOD_IMPLEMENTED))
-       {
-               if (1) {
-                       DOLOG( printf("SPECULATIVE INLINE: "); method_println((methodinfo*)callee); );
-                       site->speculative = true;
-
-                       return true;
-               }
-       }
-
-       /* possibly polymorphic call site */
-
-       return false;
-}
-
-
-/* inline_can_inline ***********************************************************
-
-   Check if inlining of the given call site is possible.
-
-   IN:
-       caller...........inlining node of the caller
-          callee...........the called method
-          call.............the invocation instruction
-
-   OUT:
-       site->speculative.....flags whether the inlining is speculative
-                                (only defined if return value is true)
-
-   RETURN VALUE:
-       true if inlining is possible, false if not
-
-*******************************************************************************/
-
-static bool inline_can_inline(const inline_node *caller,
-                                                         const methodinfo *callee,
-                                                         const instruction *call,
-                                                         inline_site *site)
-{
-       const inline_node *active;
-
-       /* cannot inline native methods */
-
-       if (callee->flags & ACC_NATIVE)
-               return false;
-
-       /* cannot inline possibly polymorphic calls */
-
-       if (!inline_is_monomorphic(callee, call, site))
-               return false;
-
-       /* cannot inline recursive calls */
-
-       for (active = caller; active; active = active->parent) {
-               if (callee == active->m) {
-                       DOLOG( printf("RECURSIVE!\n") );
-                       return false;
-               }
-       }
-
-       /* inlining is possible */
-
-       return true;
-}
-
-
-/* inline_create_callee_node ***************************************************
-
-   Create an inlining node for the given callee.
-
-   IN:
-          caller...........inlining node of the caller (const)
-          callee...........the called method
-
-   RETURN VALUE:
-       the new inlining node
-
-*******************************************************************************/
-
-static inline_node * inline_create_callee_node(const inline_node *caller,
-                                                                                          methodinfo *callee)
-{
-       inline_node *cn;              /* the callee inline_node */
-
-       cn = DNEW(inline_node);
-       MZERO(cn, inline_node, 1);
-
-       cn->depth = caller->depth + 1;
-       cn->ctx = caller->ctx;
-       cn->m = callee;
-       cn->synchronize = (callee->flags & ACC_SYNCHRONIZED);
-       cn->isstatic = (callee->flags & ACC_STATIC);
-
-       return cn;
-}
-
-
-/* inline_set_callee_properties ************************************************
-
-   Set properties of the inlined call site.
-
-   IN:
-       caller...........inlining node of the caller (const)
-          cn...............the called method
-          site.............info about the call site (const)
-
-   OUT:
-       *cn..............has the properties set
-
-*******************************************************************************/
-
-static void inline_set_callee_properties(const inline_node *caller,
-                                                                                inline_node *cn,
-                                                                                const inline_site *site)
-{
-       s4           argi;
-       s4           i, j;
-       basicblock  *bptr;
-
-       /* set info about the call site */
-
-       cn->callerblock = site->bptr;
-       cn->callerins = site->iptr;
-       cn->callerpc = site->pc;
-       cn->o_handlers = site->handlers;
-       cn->n_handlercount = caller->n_handlercount + site->nhandlers;
-
-       /* determine if we need basic block boundaries before/after */
-
-       cn->blockbefore = false;
-       cn->blockafter = false;
-
-       if (cn->jd->branchtoentry)
-               cn->blockbefore = true;
-
-       if (cn->jd->branchtoend)
-               cn->blockafter = true;
-
-       if (cn->jd->returncount > 1)
-               cn->blockafter = true;
-
-       /* XXX make safer and reusable (maybe store last real block) */
-       for (bptr = cn->jd->basicblocks; bptr && bptr->next && bptr->next->next; bptr = bptr->next)
-               ;
-
-       if (cn->jd->returnblock != bptr)
-               cn->blockafter = true;
-
-       /* info about the callee */
-
-       cn->localsoffset = caller->localsoffset + caller->m->maxlocals;
-       cn->prolog_instructioncount = cn->m->parseddesc->paramcount + 2;
-       cn->epilog_instructioncount = 1; /* INLINE_END */
-       cn->extra_instructioncount = 0;
-
-       /* we need a CHECKNULL for instance methods, except for <init> */
-
-       if (!cn->isstatic && cn->m->name != utf_init)
-               cn->prolog_instructioncount += 1;
-
-       /* deal with synchronized callees */
-
-       if (cn->synchronize) {
-               methoddesc         *md;
-               builtintable_entry *bte;
-
-               /* we need basic block boundaries because of the handler */
-
-               cn->blockbefore = true;
-               cn->blockafter = true;
-
-               /* for synchronized static methods                 */
-               /* we need an ACONST, MONITORENTER in the prolog   */
-               /* and ACONST, MONITOREXIT in the epilog           */
-
-               /* for synchronized instance methods               */
-               /* we need an COPY, MONITORENTER in the prolog     */
-               /* and MONITOREXIT in the epilog                   */
-
-               if (cn->isstatic) {
-                       cn->prolog_instructioncount += 2;
-                       cn->epilog_instructioncount += 2;
-               }
-               else {
-                       cn->prolog_instructioncount += 2;
-                       cn->epilog_instructioncount += 1;
-                       cn->localsoffset += 1;
-               }
-
-               /* and exception handler */
-               /* ALOAD, builtin_monitorexit, ATHROW */
-
-               cn->extra_instructioncount += 3;
-
-               /* exception table entries */
-
-               cn->extra_exceptiontablelength = 1 + cn->n_handlercount;
-
-               /* add exception handler block */
-
-               cn->cumul_basicblockcount_root++;
-
-               /* we must call the builtins */
-
-               bte = builtintable_get_internal(LOCK_monitor_enter);
-               md = bte->md;
-               if (md->memuse > cn->regdata->memuse)
-                       cn->regdata->memuse = md->memuse;
-               if (md->argintreguse > cn->regdata->argintreguse)
-                       cn->regdata->argintreguse = md->argintreguse;
-
-               bte = builtintable_get_internal(LOCK_monitor_exit);
-               md = bte->md;
-               if (md->memuse > cn->regdata->memuse)
-                       cn->regdata->memuse = md->memuse;
-               if (md->argintreguse > cn->regdata->argintreguse)
-                       cn->regdata->argintreguse = md->argintreguse;
-       }
-
-       /* determine pass-through variables */
-
-       i = site->iptr->s1.argcount - cn->m->parseddesc->paramcount; /* max # of pass-though vars */
-
-       cn->n_passthroughvars = DMNEW(s4, i);
-       j = 0;
-       for (argi = site->iptr->s1.argcount - 1; argi >= cn->m->parseddesc->paramcount; --argi) {
-               s4 idx = site->iptr->sx.s23.s2.args[argi];
-               if (idx >= caller->jd->localcount) {
-                       cn->n_passthroughvars[j] = idx;
-                       j++;
-               }
-               else {
-                       DOLOG( printf("PASSING THROUGH LOCAL VARIABLE %d\n", idx); );
-               }
-       }
-       assert(j <= i);
-       cn->n_selfpassthroughcount = j;
-       cn->n_passthroughcount = caller->n_passthroughcount + cn->n_selfpassthroughcount;
-}
-
-
-/* inline_cumulate_counters ****************************************************
-
-   Cumulate counters after a node has been decided to become inlined.
-
-   IN:
-       caller...........inlining node of the caller
-          callee...........inlining node of the callee (const)
-
-   OUT:
-       *caller..........gets cumulated values added
-
-*******************************************************************************/
-
-static void inline_cumulate_counters(inline_node *caller,
-                                                                        const inline_node *cn)
-{
-       caller->cumul_instructioncount += cn->prolog_instructioncount;
-       caller->cumul_instructioncount += cn->epilog_instructioncount;
-       caller->cumul_instructioncount += cn->extra_instructioncount;
-       caller->cumul_instructioncount += cn->cumul_instructioncount - 1 /*invoke*/;
-
-       caller->cumul_basicblockcount += cn->cumul_basicblockcount;
-       caller->cumul_basicblockcount_root += cn->cumul_basicblockcount_root;
-       caller->cumul_blockmapcount += cn->cumul_blockmapcount;
-       caller->cumul_exceptiontablelength += cn->cumul_exceptiontablelength;
-       caller->cumul_exceptiontablelength += cn->extra_exceptiontablelength;
-
-       if (cn->cumul_maxlocals > caller->cumul_maxlocals)
-               caller->cumul_maxlocals = cn->cumul_maxlocals;
-
-       /* XXX extra block after inlined call */
-       if (cn->blockafter) {
-               caller->cumul_basicblockcount += 1;
-               caller->cumul_blockmapcount += 1;
-       }
-}
-
-
-/* inline_analyse_callee *******************************************************
-
-   Analyse an inlining candidate callee.
-
-   IN:
-       caller...........inlining node of the caller
-          callee...........the called method
-          site.............info about the call site
-
-   OUT:
-       site->inlined....true if the callee has been selected for inlining
-
-   RETURN VALUE:
-       the inline node of the callee, or
-       NULL if an error has occurred (don't use the inlining plan in this case)
-
-*******************************************************************************/
-
-static inline_node * inline_analyse_callee(inline_node *caller,
-                                                                                  methodinfo *callee,
-                                                                                  inline_site *site)
-{
-       inline_node *cn;              /* the callee inline_node */
-
-       /* create an inline tree node */
-
-       cn = inline_create_callee_node(caller, callee);
-
-       /* get the intermediate representation of the callee */
-
-       if (!inline_jit_compile(cn))
-               return NULL;
-
-       /* evaluate heuristics after parsing the callee */
-
-       if (!inline_post_parse_heuristics(caller, cn))
-               return cn;
-
-       /* the call site will be inlined */
-
-       site->inlined = true;
-
-       /* set info about the call site */
-
-       inline_set_callee_properties(caller, cn, site);
-
-       /* insert the node into the inline tree */
-
-       inline_insert_inline_node(caller, cn);
-
-       /* analyse recursively */
-
-       if (!inline_analyse_code(cn))
-               return NULL;
-
-       if (!inline_afterwards_heuristics(caller, cn)) {
-#if defined(INLINE_CANCEL_ON_THRESHOLD)
-               return NULL;
-#else
-               inline_remove_inline_node(caller, cn);
-               caller->ctx->stopped = true;
-               site->inlined = false;
-               return cn;
-#endif
-       }
-
-       /* cumulate counters */
-
-#if defined(INLINE_DEPTH_FIRST)
-       inline_cumulate_counters(caller, cn);
-#endif
-
-#if defined(INLINE_BREADTH_FIRST)
-       while (caller) {
-               inline_cumulate_counters(caller, cn);
-               caller = caller->parent;
-       }
-#endif
-
-       return cn;
-}
-
-
-/* inline_process_candidate ****************************************************
-
-   Process a selected inlining candidate.
-
-   IN:
-       cand.............the candidate
-
-   RETURN VALUE:
-       true........everything ok
-          false.......an error has occurred, don't use the plan
-
-*******************************************************************************/
-
-static bool inline_process_candidate(inline_candidate *cand)
-{
-       inline_node *cn;
-
-       cn = inline_analyse_callee(cand->caller,
-                                                          cand->callee,
-                                                          &(cand->site));
-
-       if (!cn)
-               return false;
-
-       if (!cand->site.inlined)
-               return true;
-
-       /* store assumptions */
-
-       if (cand->site.speculative)
-               method_add_assumption_monomorphic(cand->callee, cand->caller->ctx->master->m);
-
-       return true;
-}
-
-
-/* inline_analyse_code *********************************************************
-
-   Analyse the intermediate code of the given inlining node.
-
-   IN:
-       iln..............the inlining node
-
-   OUT:
-       *iln.............the inlining plan
-
-   RETURN VALUE:
-       true........everything ok
-          false.......an error has occurred, don't use the plan
-
-*******************************************************************************/
-
-static bool inline_analyse_code(inline_node *iln)
-{
-       methodinfo *m;
-       basicblock *bptr;
-       s4 len;
-       instruction *iptr;
-       methodinfo *callee;
-       exception_entry **handlers;
-       exception_entry *ex;
-       s4 nhandlers;
-       s4 blockendpc;
-       jitdata *mjd;
-       inline_site site;
-
-       assert(iln);
-
-       m = iln->m;
-       mjd = iln->jd;
-
-       /* initialize cumulative counters */
-
-       iln->cumul_maxlocals = iln->localsoffset + m->maxlocals;
-       iln->cumul_exceptiontablelength += mjd->exceptiontablelength;
-
-       /* iterate over basic blocks */
-
-       blockendpc = 0;
-
-       for (bptr = mjd->basicblocks; bptr; bptr = bptr->next) {
-
-               /* count the block */
-               /* ignore dummy end blocks (but count them for the blockmap) */
-
-               iln->cumul_blockmapcount++;
-               if ((bptr != mjd->basicblocks || iln->blockbefore)
-                               &&
-                       (bptr->icount > 0 || bptr->next != NULL))
-                       iln->cumul_basicblockcount++;
-
-               /* skip dead code */
-
-               if (bptr->flags < BBREACHED)
-                       continue;
-
-               /* allocate the buffer of active exception handlers */
-               /* XXX this wastes some memory, but probably it does not matter */
-
-               handlers = DMNEW(exception_entry*, mjd->exceptiontablelength + 1);
-
-               /* determine the active exception handlers for this block     */
-               /* XXX maybe the handlers of a block should be part of our IR */
-               /* XXX this should share code with the type checkers          */
-               nhandlers = 0;
-               for (ex = mjd->exceptiontable; ex ; ex = ex->down) {
-                       if ((ex->start->nr <= bptr->nr) && (ex->end->nr > bptr->nr)) {
-                               handlers[nhandlers++] = ex;
-                       }
-               }
-               handlers[nhandlers] = NULL;
-
-               len = bptr->icount;
-               iptr = bptr->iinstr;
-
-               blockendpc += len;
-               iln->cumul_instructioncount += len;
-
-               /* iterate over the instructions of the block */
-
-               for (; --len >= 0; ++iptr) {
-
-                       switch (iptr->opc) {
-                               case ICMD_INVOKEVIRTUAL:
-                               case ICMD_INVOKESPECIAL:
-                               case ICMD_INVOKESTATIC:
-                               case ICMD_INVOKEINTERFACE:
-
-                                       if (!INSTRUCTION_IS_UNRESOLVED(iptr) && !iln->ctx->stopped) {
-                                               callee = iptr->sx.s23.s3.fmiref->p.method;
-
-                                               if (inline_can_inline(iln, callee, iptr, &site)) {
-                                                       site.inlined = false;
-                                                       site.bptr = bptr;
-                                                       site.iptr = iptr;
-                                                       site.pc = blockendpc - len - 1;
-                                                       site.handlers = handlers;
-                                                       site.nhandlers = nhandlers;
-
-                                                       if (inline_pre_parse_heuristics(iln, callee, &site)) {
-#if defined(INLINE_KNAPSACK) || defined(INLINE_BREADTH_FIRST)
-                                                               inline_add_candidate(iln->ctx, iln, callee, &site);
-#else
-                                                               inline_candidate cand;
-                                                               cand.caller = iln;
-                                                               cand.callee = callee;
-                                                               cand.site   = site;
-
-                                                               if (!inline_process_candidate(&cand))
-                                                                       return false;
-#endif
-                                                       }
-                                               }
-                                       }
-                                       break;
-
-                               case ICMD_RETURN:
-                               case ICMD_IRETURN:
-                               case ICMD_ARETURN:
-                               case ICMD_LRETURN:
-                               case ICMD_FRETURN:
-                               case ICMD_DRETURN:
-                                       /* extra ICMD_MOVE may be necessary */
-                                       iln->cumul_instructioncount++;
-                                       break;
-                       }
-               }
-
-               /* end of basic block */
-       }
-
-       return true;
-}
-
-
-static void inline_cumulate_counters_recursive(inline_node *iln)
-{
-       inline_node *child;
-
-       child = iln->children;
-       if (child) {
-               do {
-                       inline_cumulate_counters_recursive(child);
-                       inline_cumulate_counters(iln, child);
-                       child = child->next;
-               } while (child != iln->children);
-       }
-}
-
-
-/* inline_make_inlining_plan ***************************************************
-
-   Make an inlining plan for the given root node
-
-   IN:
-       iln..............the root node
-
-   OUT:
-       *iln.............the inlining plan
-
-   RETURN VALUE:
-       true........everything ok
-          false.......an error has occurred, don't use the plan
-
-*******************************************************************************/
-
-#if defined(INLINE_KNAPSACK)
-static bool inline_make_inlining_plan(inline_node *iln)
-{
-       inline_candidate *cand;
-#if defined(INLINE_COST_BUDGET)
-       s4 budget = INLINE_COST_BUDGET;
-#   define BUDGETMEMBER cost
-#endif
-#if defined(INLINE_WEIGHT_BUDGET)
-       double budget = INLINE_WEIGHT_BUDGET;
-#   define BUDGETMEMBER weight
-#endif
-
-       inline_analyse_code(iln);
-
-       DOLOG( printf("candidates in "); method_println(iln->m);
-                  inline_candidates_println(iln->ctx); );
-
-       while ((cand = inline_pick_best_candidate(iln->ctx)) != NULL)
-       {
-               if (cand->BUDGETMEMBER <= budget) {
-                       DOLOG( printf("    picking: "); inline_candidate_println(cand); );
-
-                       if (!inline_process_candidate(cand))
-                               return false;
-
-#if !defined(INLINE_ADD_NEGATIVE_TO_BUDGET)
-                       if (cand->BUDGETMEMBER > 0)
-#endif
-                               budget -= cand->BUDGETMEMBER;
-               }
-       }
-
-       inline_cumulate_counters_recursive(iln);
-
-       return true;
-}
-#endif /* defined(INLINE_KNAPSACK) */
-
-
-#if defined(INLINE_DEPTH_FIRST)
-static bool inline_make_inlining_plan(inline_node *iln)
-{
-       return inline_analyse_code(iln);
-}
-#endif /* defined(INLINE_DEPTH_FIRST) */
-
-
-#if defined(INLINE_BREADTH_FIRST)
-static bool inline_make_inlining_plan(inline_node *iln)
-{
-       inline_candidate *cand;
-
-       inline_analyse_code(iln);
-
-       DOLOG( printf("candidates in "); method_println(iln->m);
-                  inline_candidates_println(iln->ctx); );
-
-       while (!iln->ctx->stopped
-                  && (cand = inline_pick_best_candidate(iln->ctx)) != NULL)
-       {
-               DOLOG( printf("    picking: "); inline_candidate_println(cand); );
-
-               if (!inline_process_candidate(cand))
-                       return false;
-       }
-
-       return true;
-}
-#endif /* defined(INLINE_BREADTH_FIRST) */
-
-
-/* statistics *****************************************************************/
-
-#if defined(INLINE_STATISTICS)
-static void inline_gather_statistics_recursive(inline_node *iln)
-{
-       inline_node *child;
-
-       inline_stat_inlined_nodes++;
-
-       if (iln->depth > inline_stat_max_depth)
-               inline_stat_max_depth++;
-
-       child = iln->children;
-       if (child) {
-               do {
-                       inline_gather_statistics_recursive(child);
-                       child = child->next;
-               } while (child != iln->children);
-       }
-}
-#endif /* defined(INLINE_STATISTICS) */
-
-
-#if defined(INLINE_STATISTICS)
-static void inline_gather_statistics(inline_node *iln)
-{
-       inline_stat_roots_transformed++;
-
-       inline_gather_statistics_recursive(iln);
-}
-#endif /* defined(INLINE_STATISTICS) */
-
-
-/* post processing ************************************************************/
-
-#define POSTPROCESS_SRC(varindex)  live[varindex]--
-#define POSTPROCESS_DST(varindex)  live[varindex]++
-
-#define POSTPROCESS_SRCOP(s)  POSTPROCESS_SRC(iptr->s.varindex)
-#define POSTPROCESS_DSTOP(d)  POSTPROCESS_DST(iptr->d.varindex)
-
-#define MARKSAVED(varindex)  jd->var[varindex].flags |= SAVEDVAR
-
-#define MARK_ALL_SAVED                                               \
-    do {                                                             \
-        for (i=0; i<jd->vartop; ++i)                                 \
-            if (live[i])                                             \
-                MARKSAVED(i);                                        \
-    } while (0)
-
-static void inline_post_process(jitdata *jd)
-{
-       codeinfo   *code;
-       basicblock *bptr;
-       instruction *iptr;
-       instruction *iend;
-       s4 i;
-       icmdtable_entry_t *icmdt;
-       s4 *live;
-       methoddesc *md;
-       builtintable_entry *bte;
-
-       /* Get required compiler data. */
-
-       code = jd->code;
-
-       /* reset the SAVEDVAR flag of all variables */
-
-       for (i=0; i<jd->vartop; ++i)
-               jd->var[i].flags &= ~SAVEDVAR;
-
-       /* allocate the life counters */
-
-       live = DMNEW(s4, jd->vartop);
-       MZERO(live, s4, jd->vartop);
-
-       /* iterate over all basic blocks */
-
-       for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
-               if (bptr->flags < BBREACHED)
-                       continue;
-
-               /* make invars live */
-
-               for (i=0; i<bptr->indepth; ++i)
-                       POSTPROCESS_DST(bptr->invars[i]);
-
-               iptr = bptr->iinstr;
-               iend = iptr + bptr->icount;
-
-               for (; iptr < iend; ++iptr) {
-
-                       icmdt = &(icmd_table[iptr->opc]);
-
-                       switch (icmdt->dataflow) {
-                               case DF_3_TO_0:
-                                       POSTPROCESS_SRCOP(sx.s23.s3);
-                               case DF_2_TO_0:
-                                       POSTPROCESS_SRCOP(sx.s23.s2);
-                               case DF_1_TO_0:
-                                       POSTPROCESS_SRCOP(s1);
-                               case DF_0_TO_0:
-                                       if (icmdt->flags & ICMDTABLE_CALLS) {
-                                               code_unflag_leafmethod(code);
-                                               MARK_ALL_SAVED;
-                                       }
-                                       break;
-
-                               case DF_2_TO_1:
-                                       POSTPROCESS_SRCOP(sx.s23.s2);
-                               case DF_1_TO_1:
-                               case DF_MOVE:
-                                       POSTPROCESS_SRCOP(s1);
-                               case DF_0_TO_1:
-                                       if (icmdt->flags & ICMDTABLE_CALLS) {
-                                               code_unflag_leafmethod(code);
-                                               MARK_ALL_SAVED;
-                                       }
-                               case DF_COPY:
-                                       POSTPROCESS_DSTOP(dst);
-                                       break;
-
-                               case DF_N_TO_1:
-                                       for (i=0; i<iptr->s1.argcount; ++i) {
-                                               POSTPROCESS_SRC(iptr->sx.s23.s2.args[i]);
-                                       }
-                                       if (icmdt->flags & ICMDTABLE_CALLS) {
-                                               code_unflag_leafmethod(code);
-                                               MARK_ALL_SAVED;
-                                       }
-                                       POSTPROCESS_DSTOP(dst);
-                                       break;
-
-                               case DF_INVOKE:
-                                       INSTRUCTION_GET_METHODDESC(iptr, md);
-               post_process_call:
-                                       code_unflag_leafmethod(code);
-                                       for (i=0; i<md->paramcount; ++i) {
-                                               POSTPROCESS_SRC(iptr->sx.s23.s2.args[i]);
-                                       }
-                                       for (; i<iptr->s1.argcount; ++i) {
-                                               MARKSAVED(iptr->sx.s23.s2.args[i]);
-                                       }
-                                       if (md->returntype.type != TYPE_VOID)
-                                               POSTPROCESS_DSTOP(dst);
-                                       break;
-
-                               case DF_BUILTIN:
-                                       bte = iptr->sx.s23.s3.bte;
-                                       md = bte->md;
-                                       goto post_process_call;
-
-                               default:
-                                       assert(0);
-                       }
-
-               } /* end instruction loop */
-
-               /* consume outvars */
-
-               for (i=0; i<bptr->outdepth; ++i)
-                       POSTPROCESS_SRC(bptr->outvars[i]);
-
-#if !defined(NDEBUG)
-               for (i=jd->localcount; i < jd->vartop; ++i)
-                       assert(live[i] == 0);
-#endif
-
-       } /* end basic block loop */
-}
-
-
-/* inline_create_root_node *****************************************************
-
-   Create the root node of the inlining tree.
-
-   IN:
-          jd...............the current jitdata of the root method
-
-   RETURN VALUE:
-       the root node of the inlining tree
-
-*******************************************************************************/
-
-static inline_node * inline_create_root_node(jitdata *jd)
-{
-       inline_node *iln;
-
-       iln = DNEW(inline_node);
-       MZERO(iln, inline_node, 1);
-
-       iln->m = jd->m;
-       iln->jd = jd;
-       iln->regdata = jd->rd;
-
-       iln->blockbefore = true;
-       iln->blockafter = true;
-
-       iln->cumul_instructioncount = 0;
-       iln->cumul_basicblockcount = 1 /* dummy end block */;
-
-       /* create inlining context */
-
-       iln->ctx = DNEW(inline_context);
-       MZERO(iln->ctx, inline_context, 1);
-       iln->ctx->master = iln;
-       iln->ctx->next_debugnr = 1; /* XXX debug */
-
-       return iln;
-}
-
-
-/******************************************************************************/
-/* MAIN DRIVER FUNCTION                                                       */
-/******************************************************************************/
-
-bool inline_inline(jitdata *jd)
-{
-       inline_node *iln;
-
-       DOLOG( printf("==== INLINE ==================================================================\n");
-                  show_method(jd, SHOW_STACK); );
-
-#if defined(INLINE_STATISTICS)
-       inline_stat_roots++;
-#endif
-
-       iln = inline_create_root_node(jd);
-
-       if (inline_make_inlining_plan(iln)) {
-
-               /* add blocks to the root node */
-
-               iln->cumul_basicblockcount += iln->cumul_basicblockcount_root;
-               iln->cumul_blockmapcount   += iln->cumul_basicblockcount_root;
-
-               DOLOG( printf("==== INLINE TRANSFORM ========================================================\n"); );
-
-               if (iln->children)
-                       inline_transform(iln, jd);
-
-#if defined(INLINE_STATISTICS)
-               inline_gather_statistics(iln);
-#endif
-       }
-
-       DOLOG( printf("-------- DONE -----------------------------------------------------------\n");
-                  fflush(stdout); );
-
-       return true;
-}
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
diff --git a/src/vm/jit/inline/inline.cpp b/src/vm/jit/inline/inline.cpp
new file mode 100644 (file)
index 0000000..6ceffa0
--- /dev/null
@@ -0,0 +1,3244 @@
+/* src/vm/jit/inline/inline.c - method inlining
+
+   Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+   This file is part of CACAO.
+
+   This program 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 2, or (at
+   your option) any later version.
+
+   This program 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 this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "vm/types.h"
+
+#include "mm/memory.h"
+
+#include "threads/lock.hpp"
+#include "threads/mutex.hpp"
+#include "threads/thread.hpp"
+
+#include "toolbox/logging.h"
+
+#include "vm/jit/builtin.hpp"
+#include "vm/class.hpp"
+#include "vm/global.h"
+#include "vm/initialize.hpp"
+#include "vm/method.h"
+#include "vm/options.h"
+#include "vm/statistics.h"
+
+#include "vm/jit/jit.hpp"
+#include "vm/jit/parse.hpp"
+#include "vm/jit/reg.h"
+#include "vm/jit/show.hpp"
+#include "vm/jit/stack.h"
+
+#include "vm/jit/inline/inline.hpp"
+#include "vm/jit/loop/loop.h"
+
+#include "vm/jit/verify/typecheck.h"
+
+
+/* algorithm tuning constants *************************************************/
+
+/* Algorithm Selection                                                        */
+/* Define exactly one of the following three to select the inlining           */
+/* heuristics.                                                                */
+
+/*#define INLINE_DEPTH_FIRST*/
+/*#define INLINE_BREADTH_FIRST*/
+#define INLINE_KNAPSACK
+
+/* Parameters for knapsack heuristics:                                        */
+
+#if defined(INLINE_KNAPSACK)
+
+#define INLINE_COUNTDOWN_INIT       1000
+#define INLINE_COST_OFFSET          -16
+#define INLINE_COST_BUDGET          100
+/*#define INLINE_WEIGHT_BUDGET        5.0*/
+/*#define INLINE_ADD_NEGATIVE_TO_BUDGET*/
+/*#define INLINE_MAX_DEPTH            3*/
+/*#define INLINE_DIVIDE_COST_BY_FREQ */
+
+#endif
+
+/* Parameters for depth-first heuristics:                                     */
+
+#if defined(INLINE_DEPTH_FIRST)
+
+#define INLINE_MAX_DEPTH            3
+#define INLINE_MAX_BLOCK_EXPANSION  10
+/*#define INLINE_MAX_ICMD_EXPANSION  10*/
+/*#define INLINE_CANCEL_ON_THRESHOLD*/
+
+#endif
+
+/* Parameters for breadth-first heuristics:                                   */
+
+#if defined(INLINE_BREADTH_FIRST)
+
+/*#define INLINE_MAX_BLOCK_EXPANSION  10*/
+#define INLINE_MAX_ICMD_EXPANSION  5
+
+#endif
+
+
+/* debugging ******************************************************************/
+
+#if !defined(NDEBUG)
+#define INLINE_VERBOSE
+#define DOLOG(code)       do{ if (opt_TraceInlining >= 2) { code; } }while(0)
+#define DOLOG_SHORT(code) do{ if (opt_TraceInlining >= 1) { code; } }while(0)
+#else
+#define DOLOG(code)
+#endif
+
+#if defined(ENABLE_VERIFIER) && !defined(NDEBUG)
+/* Define this to verify the resulting code after inlining.                 */
+/* Note: This is only useful for development and may require patches to the */
+/*       verifier code.                                                     */
+/* #define INLINE_VERIFY_RESULT */
+#endif
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* types **********************************************************************/
+
+typedef struct inline_node inline_node;
+typedef struct inline_target_ref inline_target_ref;
+typedef struct inline_context inline_context;
+typedef struct inline_block_map inline_block_map;
+typedef struct inline_site inline_site;
+typedef struct inline_candidate inline_candidate;
+
+struct inline_node {
+       inline_context *ctx;
+
+       jitdata *jd;
+       methodinfo *m;
+       inline_node *children;
+       inline_node *next;                             /* next node at this depth */
+       inline_node *prev;                             /* prev node at this depth */
+       int depth;                                  /* inlining depth, 0 for root */
+
+       /* info about the call site (if depth > 0)*/
+       inline_node *parent;                /* node of the caller (NULL for root) */
+       basicblock *callerblock;         /* original block containing the INVOKE* */
+       instruction *callerins;               /* the original INVOKE* instruction */
+       s4 callerpc;
+       s4 *n_passthroughvars;
+       int n_passthroughcount;
+       int n_selfpassthroughcount;  /* # of pass-through vars of the call itself */
+       exception_entry **o_handlers;
+       int n_handlercount;                 /* # of handlers protecting this call */
+       int n_resultlocal;
+       int synclocal;                    /* variable used for synchr., or UNUSED */
+       bool isstatic;                                   /* this is a static call */
+
+       bool blockbefore;                  /* block boundary before inlined body? */
+       bool blockafter;                   /* block boundary after inlined body?  */
+
+       /* info about the callee */
+       int localsoffset;
+       int prolog_instructioncount;         /* # of ICMDs in the inlining prolog */
+       int epilog_instructioncount;         /* # of ICMDs in the inlining epilog */
+       int extra_instructioncount;
+       int extra_exceptiontablelength;   /* # of extra handlers to put in caller */
+       bool synchronize;                /* do we have to synchronize enter/exit? */
+       basicblock *handler_monitorexit;     /* handler for synchronized inlinees */
+       s4 *varmap;
+
+       /* cumulative values */
+       int cumul_instructioncount;  /* ICMDs in this node and its children       */
+       int cumul_basicblockcount;   /* BBs started by this node and its children */
+       int cumul_basicblockcount_root;  /* BBs that have to be added to the root */
+                                        /* node if this node is inlined          */
+       int cumul_blockmapcount;
+       int cumul_maxlocals;
+       int cumul_exceptiontablelength;
+
+       /* output */
+       instruction *inlined_iinstr;
+       instruction *inlined_iinstr_cursor;
+       basicblock *inlined_basicblocks;
+       basicblock *inlined_basicblocks_cursor;
+
+       /* register data */
+       registerdata *regdata;
+
+       /* temporary */
+       inline_target_ref *refs;
+       instruction *inline_start_instruction;
+       s4 *javalocals;
+
+       /* XXX debug */
+       char *indent;
+       int debugnr;
+};
+
+struct inline_target_ref {
+       inline_target_ref *next;
+       union {
+               basicblock **block;
+               s4 *nr;
+       } ref;
+       basicblock *target;
+       bool isnumber;
+};
+
+struct inline_block_map {
+       inline_node *iln;
+       basicblock *o_block;
+       basicblock *n_block;
+};
+
+struct inline_context {
+       inline_node *master;
+
+       jitdata *resultjd;
+
+       inline_candidate *candidates;
+
+       int next_block_number;
+       inline_block_map *blockmap;
+       int blockmap_index;
+
+       int maxinoutdepth;
+
+       bool stopped;
+
+       int next_debugnr; /* XXX debug */
+};
+
+struct inline_site {
+       bool              speculative;  /* true, if inlining would be speculative */
+       bool              inlined;      /* true, if this site has been inlined    */
+
+       basicblock       *bptr;         /* basic block containing the call site   */
+       instruction      *iptr;         /* the invocation instruction             */
+       exception_entry **handlers;     /* active handlers at the call site       */
+       s4                nhandlers;    /* number of active handlers              */
+       s4                pc;           /* PC of the invocation instruction       */
+};
+
+struct inline_candidate {
+       inline_candidate *next;
+       int freq;
+       int cost;
+       double weight;
+       inline_node *caller;
+       methodinfo *callee;
+       inline_site site;
+};
+
+
+/* prototypes *****************************************************************/
+
+static bool inline_analyse_code(inline_node *iln);
+static void inline_post_process(jitdata *jd);
+
+
+/* debug helpers **************************************************************/
+
+#if !defined(NDEBUG)
+#include "inline_debug.inc"
+#endif
+
+
+/* statistics *****************************************************************/
+
+/*#define INLINE_STATISTICS*/
+
+#if !defined(NDEBUG)
+#define INLINE_STATISTICS
+#endif
+
+#if defined(INLINE_STATISTICS)
+int inline_stat_roots = 0;
+int inline_stat_roots_transformed = 0;
+int inline_stat_inlined_nodes = 0;
+int inline_stat_max_depth = 0;
+
+void inline_print_stats()
+{
+       printf("inlining statistics:\n");
+       printf("    roots analysed   : %d\n", inline_stat_roots);
+       printf("    roots transformed: %d\n", inline_stat_roots_transformed);
+       printf("    inlined nodes    : %d\n", inline_stat_inlined_nodes);
+       printf("    max depth        : %d\n", inline_stat_max_depth);
+}
+#endif
+
+
+/* compilation of callees *****************************************************/
+
+static bool inline_jit_compile_intern(jitdata *jd)
+{
+       methodinfo *m;
+
+       /* XXX should share code with jit.c */
+
+       assert(jd);
+
+       /* XXX initialize the static function's class */
+
+       m = jd->m;
+
+       /* call the compiler passes ***********************************************/
+
+       /* call parse pass */
+
+       DOLOG( log_message_class("Parsing ", m->clazz) );
+       if (!parse(jd)) {
+               return false;
+       }
+
+       /* call stack analysis pass */
+
+       if (!stack_analyse(jd)) {
+               return false;
+       }
+
+       return true;
+}
+
+
+static bool inline_jit_compile(inline_node *iln)
+{
+       bool                r;
+       methodinfo         *m;
+       jitdata            *jd;
+
+       /* XXX should share code with jit.c */
+
+       assert(iln);
+       m = iln->m;
+       assert(m);
+
+       /* enter a monitor on the method */
+
+       m->mutex->lock();
+
+       /* allocate jitdata structure and fill it */
+
+       jd = jit_jitdata_new(m);
+       iln->jd = jd;
+
+       jd->flags = 0; /* XXX */
+
+       /* initialize the register allocator */
+
+       reg_setup(jd);
+
+       /* setup the codegendata memory */
+
+       /* XXX do a pseudo setup */
+       jd->cd = (codegendata*) DumpMemory::allocate(sizeof(codegendata));
+       MZERO(jd->cd, codegendata, 1);
+       jd->cd->method = m;
+       /* XXX uses too much dump memory codegen_setup(jd); */
+
+       /* now call internal compile function */
+
+       r = inline_jit_compile_intern(jd);
+
+       if (r) {
+               iln->regdata = jd->rd;
+       }
+
+       /* free some memory */
+#if 0
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+       if (!opt_intrp)
+# endif
+               codegen_free(jd);
+#endif
+
+#endif
+
+       /* leave the monitor */
+
+       m->mutex->unlock();
+
+       return r;
+}
+
+
+/* inlining tree handling *****************************************************/
+
+static void inline_insert_inline_node(inline_node *parent, inline_node *child)
+{
+       inline_node *first;
+       inline_node *succ;
+
+       assert(parent && child);
+
+       child->parent = parent;
+
+       child->debugnr = parent->ctx->next_debugnr++; /* XXX debug */
+
+       first = parent->children;
+       if (!first) {
+               /* insert as only node */
+               parent->children = child;
+               child->next = child;
+               child->prev = child;
+               return;
+       }
+
+       /* {there is at least one child already there} */
+
+       /* XXX is this search necessary, or could we always add at the end? */
+
+       succ = first;
+       while (succ->callerpc < child->callerpc) {
+               succ = succ->next;
+               if (succ == first) {
+                       /* insert as last node */
+                       child->prev = first->prev;
+                       child->next = first;
+                       child->prev->next = child;
+                       child->next->prev = child;
+                       return;
+               }
+       }
+
+       assert(succ->callerpc > child->callerpc);
+
+       /* insert before succ */
+
+       child->prev = succ->prev;
+       child->next = succ;
+       child->prev->next = child;
+       child->next->prev = child;
+
+       if (parent->children == succ)
+               parent->children = child;
+}
+
+
+static void inline_remove_inline_node(inline_node *parent, inline_node *child)
+{
+       assert(parent);
+       assert(child);
+       assert(child->parent == parent);
+
+       if (child->prev == child) {
+               /* remove the only child node */
+               parent->children = NULL;
+       }
+       else {
+               child->prev->next = child->next;
+               child->next->prev = child->prev;
+
+               if (parent->children == child)
+                       parent->children = child->next;
+       }
+}
+
+
+/* inlining candidate handling ************************************************/
+
+#if defined(INLINE_KNAPSACK) || defined(INLINE_BREADTH_FIRST)
+static void inline_add_candidate(inline_context *ctx,
+                                                                inline_node *caller,
+                                                                methodinfo *callee,
+                                                                inline_site *site)
+{
+       inline_candidate **link;
+       inline_candidate *cand;
+
+       cand = (inline_candidate*) DumpMemory::allocate(sizeof(inline_candidate));
+#if defined(INLINE_DIVIDE_COST_BY_FREQ)
+       cand->freq = INLINE_COUNTDOWN_INIT - callee->hitcountdown;
+       if (cand->freq < 1)
+#endif
+               cand->freq = 1;
+#if defined(INLINE_KNAPSACK)
+       cand->cost = callee->jcodelength + INLINE_COST_OFFSET;
+#endif
+#if defined(INLINE_BREADTH_FIRST)
+       cand->cost = caller->depth;
+#endif
+       cand->caller = caller;
+       cand->callee = callee;
+       cand->site = *site;
+
+       cand->weight = (double)cand->cost / cand->freq;
+
+       for (link = &(ctx->candidates); ; link = &((*link)->next)) {
+               if (!*link || (*link)->weight > cand->weight) {
+                       cand->next = *link;
+                       *link = cand;
+                       break;
+               }
+       }
+}
+#endif /* defined(INLINE_KNAPSACK) || defined(INLINE_BREADTH_FIRST) */
+
+#if defined(INLINE_KNAPSACK) || defined(INLINE_BREADTH_FIRST)
+static inline_candidate * inline_pick_best_candidate(inline_context *ctx)
+{
+       inline_candidate *cand;
+
+       cand = ctx->candidates;
+
+       if (cand)
+               ctx->candidates = cand->next;
+
+       return cand;
+}
+#endif /* defined(INLINE_KNAPSACK) || defined(INLINE_BREADTH_FIRST) */
+
+#if !defined(NDEBUG) && (defined(INLINE_KNAPSACK) || defined(INLINE_BREADTH_FIRST))
+static void inline_candidate_println(inline_candidate *cand)
+{
+       printf("%10g (%5d / %5d) depth %2d ",
+                       cand->weight, cand->cost, cand->freq, cand->caller->depth + 1);
+       method_println(cand->callee);
+}
+#endif /* !defined(NDEBUG) && (defined(INLINE_KNAPSACK) || defined(INLINE_BREADTH_FIRST)) */
+
+
+#if !defined(NDEBUG) && (defined(INLINE_KNAPSACK) || defined(INLINE_BREADTH_FIRST))
+static void inline_candidates_println(inline_context *ctx)
+{
+       inline_candidate *cand;
+
+       for (cand = ctx->candidates; cand != NULL; cand = cand->next) {
+               printf("    ");
+               inline_candidate_println(cand);
+       }
+}
+#endif /* !defined(NDEBUG) && (defined(INLINE_KNAPSACK) || defined(INLINE_BREADTH_FIRST)) */
+
+
+/* variable handling **********************************************************/
+
+static s4 inline_new_variable(jitdata *jd, s4 type, s4 flags)
+{
+       s4 index;
+       s4 newcount;
+
+       index = jd->vartop++;
+       if (index >= jd->varcount) {
+               newcount = jd->vartop * 2; /* XXX */
+               jd->var = (varinfo*) DumpMemory::reallocate(jd->var, sizeof(varinfo) * jd->varcount, sizeof(varinfo) * newcount);
+               MZERO(jd->var + jd->varcount, varinfo, (newcount - jd->varcount));
+               jd->varcount = newcount;
+       }
+
+       jd->var[index].type = type;
+       jd->var[index].flags = flags;
+
+       return index;
+}
+
+
+static s4 inline_new_variable_clone(jitdata *jd, jitdata *origjd, s4 origidx)
+{
+       varinfo *v;
+       s4       newidx;
+
+       v = &(origjd->var[origidx]);
+
+       newidx = inline_new_variable(jd, v->type, v->flags);
+
+       jd->var[newidx].vv = v->vv;
+
+       return newidx;
+}
+
+
+static s4 inline_new_temp_variable(jitdata *jd, s4 type)
+{
+       return inline_new_variable(jd, type, 0);
+}
+
+
+static s4 inline_translate_variable(jitdata *jd, jitdata *origjd, s4 *varmap, s4 index)
+{
+       s4 idx;
+
+       idx = varmap[index];
+
+       if (idx < 0) {
+               idx = inline_new_variable_clone(jd, origjd, index);
+               varmap[index] = idx;
+       }
+
+       return idx;
+}
+
+
+static s4 *create_variable_map(inline_node *callee)
+{
+       s4 *varmap;
+       s4 i, t;
+       s4 varindex;
+       s4 n_javaindex;
+       s4 avail;
+       varinfo *v;
+
+       /* create the variable mapping */
+
+       varmap = (s4*) DumpMemory::allocate(sizeof(s4) * callee->jd->varcount);
+       for (i=0; i<callee->jd->varcount; ++i)
+               varmap[i] = -1;
+
+       /* translate local variables */
+
+       for (i=0; i<callee->m->maxlocals; ++i) {
+               for (t=0; t<5; ++t) {
+                       varindex = callee->jd->local_map[5*i + t];
+                       if (varindex == UNUSED)
+                               continue;
+
+                       v = &(callee->jd->var[varindex]);
+                       assert(v->type == t || v->type == TYPE_VOID); /* XXX stack leaves VOID */
+                       v->type = t; /* XXX restore if it is TYPE_VOID */
+
+                       avail = callee->ctx->resultjd->local_map[5*(callee->localsoffset + i) + t];
+
+                       if (avail == UNUSED) {
+                               avail = inline_new_variable_clone(callee->ctx->resultjd, callee->jd, varindex);
+                               callee->ctx->resultjd->local_map[5*(callee->localsoffset + i) + t] = avail;
+                       }
+
+                       varmap[varindex] = avail;
+               }
+       }
+
+       /* for synchronized instance methods we need an extra local */
+
+       if (callee->synchronize && !(callee->m->flags & ACC_STATIC)) {
+               n_javaindex = callee->localsoffset - 1;
+               assert(n_javaindex >= 0);
+               assert(callee->parent);
+               assert(n_javaindex == callee->parent->localsoffset + callee->parent->m->maxlocals);
+
+               avail = callee->ctx->resultjd->local_map[5*n_javaindex + TYPE_ADR];
+
+               if (avail == UNUSED) {
+                       avail = inline_new_variable(callee->ctx->resultjd, TYPE_ADR, 0);
+                       callee->ctx->resultjd->local_map[5*n_javaindex + TYPE_ADR] = avail;
+               }
+
+               callee->synclocal = avail;
+       }
+       else {
+               callee->synclocal = UNUSED;
+       }
+
+       return varmap;
+}
+
+
+/* basic block translation ****************************************************/
+
+#define INLINE_RETURN_REFERENCE(callee)  \
+       ( (basicblock *) (ptrint) (0x333 + (callee)->depth) )
+
+
+static void inline_add_block_reference(inline_node *iln, basicblock **blockp)
+{
+       inline_target_ref *ref;
+
+       ref = (inline_target_ref*) DumpMemory::allocate(sizeof(inline_target_ref));
+       ref->ref.block = blockp;
+       ref->isnumber = false;
+       ref->next = iln->refs;
+       iln->refs = ref;
+}
+
+
+#if 0
+static void inline_add_blocknr_reference(inline_node *iln, s4 *nrp)
+{
+       inline_target_ref *ref;
+
+       ref = (inline_target_ref*) DumpMemory::allocate(inline_target_ref);
+       ref->ref.nr = nrp;
+       ref->isnumber = true;
+       ref->next = iln->refs;
+       iln->refs = ref;
+}
+#endif
+
+
+static void inline_block_translation(inline_node *iln, basicblock *o_bptr, basicblock *n_bptr)
+{
+       inline_context *ctx;
+
+       ctx = iln->ctx;
+       assert(ctx->blockmap_index < ctx->master->cumul_blockmapcount);
+
+       ctx->blockmap[ctx->blockmap_index].iln = iln;
+       ctx->blockmap[ctx->blockmap_index].o_block = o_bptr;
+       ctx->blockmap[ctx->blockmap_index].n_block = n_bptr;
+
+       ctx->blockmap_index++;
+}
+
+
+static basicblock * inline_map_block(inline_node *iln,
+                                                                        basicblock *o_block,
+                                                                        inline_node *targetiln)
+{
+       inline_block_map *bm;
+       inline_block_map *bmend;
+
+       assert(iln);
+       assert(targetiln);
+
+       if (!o_block)
+               return NULL;
+
+       bm = iln->ctx->blockmap;
+       bmend = bm + iln->ctx->blockmap_index;
+
+       while (bm < bmend) {
+               assert(bm->iln && bm->o_block && bm->n_block);
+               if (bm->o_block == o_block && bm->iln == targetiln)
+                       return bm->n_block;
+               bm++;
+       }
+
+       assert(false);
+       return NULL; /* not reached */
+}
+
+
+static void inline_resolve_block_refs(inline_target_ref **refs,
+                                                                         basicblock *o_bptr,
+                                                                         basicblock *n_bptr,
+                                                                         bool returnref)
+{
+       inline_target_ref *ref;
+       inline_target_ref *prev;
+
+       prev = NULL;
+       for (ref = *refs; ref != NULL; ref = ref->next) {
+               if (ref->isnumber && !returnref) {
+                       if (*(ref->ref.nr) == JAVALOCAL_FROM_RETADDR(o_bptr->nr)) {
+                               *(ref->ref.nr) = JAVALOCAL_FROM_RETADDR(n_bptr->nr);
+                               goto remove_ref;
+                       }
+               }
+               else {
+                       if (*(ref->ref.block) == o_bptr) {
+                               *(ref->ref.block) = n_bptr;
+                               goto remove_ref;
+                       }
+               }
+
+               /* skip this ref */
+
+               prev = ref;
+               continue;
+
+remove_ref:
+               /* remove this ref */
+
+               if (prev) {
+                       prev->next = ref->next;
+               }
+               else {
+                       *refs = ref->next;
+               }
+       }
+}
+
+
+/* basic block creation *******************************************************/
+
+static basicblock * create_block(inline_node *container,
+                                                                inline_node *iln,
+                                                                inline_node *inner,
+                                                                int indepth)
+{
+       basicblock  *n_bptr;
+       inline_node *outer;
+       s4           i;
+       s4           depth;
+       s4           varidx;
+       s4           newvaridx;
+
+       assert(container);
+       assert(iln);
+       assert(inner);
+       assert(indepth >= 0);
+
+       n_bptr = container->inlined_basicblocks_cursor++;
+       assert(n_bptr);
+       assert((n_bptr - container->inlined_basicblocks) < container->cumul_basicblockcount);
+
+       BASICBLOCK_INIT(n_bptr, iln->m);
+
+       n_bptr->iinstr = container->inlined_iinstr_cursor;
+       n_bptr->next = n_bptr + 1;
+       n_bptr->nr = container->ctx->next_block_number++;
+       n_bptr->indepth = indepth;
+       n_bptr->flags = BBFINISHED; /* XXX */
+
+       /* set the inlineinfo of the new block */
+
+       if (iln->inline_start_instruction)
+               n_bptr->inlineinfo = iln->inline_start_instruction->sx.s23.s3.inlineinfo;
+
+       if (indepth > container->ctx->maxinoutdepth)
+               container->ctx->maxinoutdepth = indepth;
+
+       if (indepth) {
+               n_bptr->invars = (s4*) DumpMemory::allocate(sizeof(s4) * indepth);
+
+
+               for (i=0; i<indepth; ++i)
+                       n_bptr->invars[i] = -1; /* XXX debug */
+
+               /* pass-through variables enter the block */
+
+               outer = inner->parent;
+               while (outer != NULL) {
+                       depth = outer->n_passthroughcount;
+
+                       assert(depth + inner->n_selfpassthroughcount <= indepth);
+
+                       for (i=0; i<inner->n_selfpassthroughcount; ++i) {
+                               varidx = inner->n_passthroughvars[i];
+                               newvaridx =
+                                       inline_new_variable_clone(container->ctx->resultjd,
+                                                                                         outer->jd,
+                                                                                         varidx);
+                               n_bptr->invars[depth + i] = newvaridx;
+                               outer->varmap[varidx] = newvaridx;
+                       }
+                       inner = outer;
+                       outer = outer->parent;
+               }
+       }
+       else {
+               n_bptr->invars = NULL;
+       }
+
+       /* XXX for the verifier. should not be here */
+
+       {
+               varinfo *dv;
+
+               dv = (varinfo*) DumpMemory::allocate(sizeof(varinfo) * (iln->ctx->resultjd->localcount + VERIFIER_EXTRA_LOCALS));
+               MZERO(dv, varinfo,  iln->ctx->resultjd->localcount + VERIFIER_EXTRA_LOCALS);
+               n_bptr->inlocals = dv;
+       }
+
+       return n_bptr;
+}
+
+
+static s4 *translate_javalocals(inline_node *iln, s4 *javalocals)
+{
+       s4 *jl;
+       s4 i, j;
+
+       jl = (s4*) DumpMemory::allocate(sizeof(s4) * iln->jd->maxlocals);
+
+       for (i=0; i<iln->jd->maxlocals; ++i) {
+               j = javalocals[i];
+               if (j > UNUSED)
+                       j = inline_translate_variable(iln->ctx->resultjd, iln->jd, iln->varmap, j);
+               jl[i] = j;
+
+#if 0
+               if (j < UNUSED) {
+                       /* an encoded returnAddress value - must be relocated */
+                       inline_add_blocknr_reference(iln, &(jl[i]));
+               }
+#endif
+       }
+
+       return jl;
+}
+
+
+static basicblock * create_body_block(inline_node *iln,
+                                                                         basicblock *o_bptr, s4 *varmap)
+{
+       basicblock *n_bptr;
+       s4 i;
+
+       n_bptr = create_block(iln, iln, iln,
+                                                 o_bptr->indepth + iln->n_passthroughcount);
+
+       n_bptr->type = o_bptr->type;
+       n_bptr->flags = o_bptr->flags;
+       n_bptr->bitflags = o_bptr->bitflags;
+
+       /* resolve references to this block */
+
+       inline_resolve_block_refs(&(iln->refs), o_bptr, n_bptr, false);
+
+       /* translate the invars of the original block */
+
+       for (i=0; i<o_bptr->indepth; ++i) {
+               n_bptr->invars[iln->n_passthroughcount + i] =
+                       inline_translate_variable(iln->ctx->resultjd, iln->jd,
+                               varmap,
+                               o_bptr->invars[i]);
+       }
+
+       /* translate javalocals info (not for dead code) */
+
+       if (n_bptr->flags >= BBREACHED)
+               n_bptr->javalocals = translate_javalocals(iln, o_bptr->javalocals);
+
+       return n_bptr;
+}
+
+
+static basicblock * create_epilog_block(inline_node *caller, inline_node *callee, s4 *varmap)
+{
+       basicblock *n_bptr;
+       s4 retcount;
+       s4 idx;
+
+       /* number of return variables */
+
+       retcount = (callee->n_resultlocal == -1
+                               && callee->m->parseddesc->returntype.type != TYPE_VOID) ? 1 : 0;
+
+       /* start the epilog block */
+
+       n_bptr = create_block(caller, caller, callee,
+                                                 callee->n_passthroughcount + retcount);
+
+       /* resolve references to the return block */
+
+       inline_resolve_block_refs(&(callee->refs),
+                                                         INLINE_RETURN_REFERENCE(callee),
+                                                         n_bptr,
+                                                         true);
+
+       /* return variable */
+
+       if (retcount) {
+               idx = inline_new_variable(caller->ctx->resultjd,
+                          callee->m->parseddesc->returntype.type, 0 /* XXX */);
+               n_bptr->invars[callee->n_passthroughcount] = idx;
+               varmap[callee->callerins->dst.varindex] = idx;
+       }
+
+       /* set javalocals */
+
+       n_bptr->javalocals = (s4*) DumpMemory::allocate(sizeof(s4) * caller->jd->maxlocals);
+       MCOPY(n_bptr->javalocals, caller->javalocals, s4, caller->jd->maxlocals);
+
+       /* set block flags & type */
+
+       n_bptr->flags = /* XXX original block flags */ BBFINISHED;
+       n_bptr->type = BBTYPE_STD;
+
+       return n_bptr;
+}
+
+
+static void close_block(inline_node *iln, inline_node *inner, basicblock *n_bptr, s4 outdepth)
+{
+       inline_node *outer;
+       s4           i;
+       s4           depth;
+       s4           varidx;
+
+       n_bptr->outdepth = outdepth;
+       n_bptr->outvars = (s4*) DumpMemory::allocate(sizeof(s4) * outdepth);
+
+       for (i=0; i<outdepth; ++i)
+               n_bptr->outvars[i] = 0; /* XXX debug */
+
+       if (outdepth > iln->ctx->maxinoutdepth)
+               iln->ctx->maxinoutdepth = outdepth;
+
+       /* pass-through variables leave the block */
+
+       outer = inner->parent;
+       while (outer != NULL) {
+               depth = outer->n_passthroughcount;
+
+               assert(depth + inner->n_selfpassthroughcount <= outdepth);
+
+               for (i=0; i<inner->n_selfpassthroughcount; ++i) {
+                       varidx = inner->n_passthroughvars[i];
+                       n_bptr->outvars[depth + i] =
+                               inline_translate_variable(iln->ctx->resultjd,
+                                                                                 outer->jd,
+                                                                                 outer->varmap,
+                                                                                 varidx);
+               }
+               inner = outer;
+               outer = outer->parent;
+       }
+}
+
+
+static void close_prolog_block(inline_node *iln,
+                                                          basicblock *n_bptr,
+                                                          inline_node *nextcall)
+{
+       /* XXX add original outvars! */
+       close_block(iln, nextcall, n_bptr, nextcall->n_passthroughcount);
+
+       /* pass-through variables */
+
+       DOLOG( printf("closed prolog block:\n");
+                  show_basicblock(iln->ctx->resultjd, n_bptr, SHOW_STACK); );
+}
+
+
+static void close_body_block(inline_node *iln,
+                                                        basicblock *n_bptr,
+                                                        basicblock *o_bptr,
+                                                        s4 *varmap,
+                                                        s4 retcount,
+                                                        s4 retidx)
+{
+       s4 i;
+
+       close_block(iln, iln, n_bptr, iln->n_passthroughcount + o_bptr->outdepth + retcount);
+
+       /* translate the outvars of the original block */
+
+       /* XXX reuse code */
+       for (i=0; i<o_bptr->outdepth; ++i) {
+               n_bptr->outvars[iln->n_passthroughcount + i] =
+                       inline_translate_variable(iln->ctx->resultjd, iln->jd, varmap,
+                                       o_bptr->outvars[i]);
+       }
+
+       /* set the return variable, if any */
+
+       if (retcount) {
+               assert(retidx >= 0);
+               n_bptr->outvars[iln->n_passthroughcount + o_bptr->outdepth] = retidx;
+       }
+}
+
+
+/* inlined code generation ****************************************************/
+
+static instruction * inline_instruction(inline_node *iln,
+                                                                               s4 opcode,
+                                                                               instruction *o_iptr)
+{
+       instruction *n_iptr;
+
+       n_iptr = (iln->inlined_iinstr_cursor++);
+       assert((n_iptr - iln->inlined_iinstr) < iln->cumul_instructioncount);
+
+       n_iptr->opc = opcode;
+       n_iptr->flags.bits = o_iptr->flags.bits & INS_FLAG_ID_MASK;
+       n_iptr->line = o_iptr->line;
+
+       return n_iptr;
+}
+
+static void inline_generate_sync_builtin(inline_node *iln,
+                                                                                inline_node *callee,
+                                                                                instruction *o_iptr,
+                                                                                s4 instancevar,
+                                                                                functionptr func)
+{
+       int          syncvar;
+       instruction *n_ins;
+
+       if (callee->m->flags & ACC_STATIC) {
+               /* ACONST */
+               syncvar = inline_new_temp_variable(iln->ctx->resultjd, TYPE_ADR);
+
+               n_ins = inline_instruction(iln, ICMD_ACONST, o_iptr);
+               n_ins->sx.val.c.cls = callee->m->clazz;
+               n_ins->dst.varindex = syncvar;
+               n_ins->flags.bits |= INS_FLAG_CLASS;
+       }
+       else {
+               syncvar = instancevar;
+       }
+
+       assert(syncvar != UNUSED);
+
+       /* MONITORENTER / MONITOREXIT */
+
+       n_ins = inline_instruction(iln, ICMD_BUILTIN, o_iptr);
+       n_ins->sx.s23.s3.bte = builtintable_get_internal(func);
+       n_ins->s1.argcount = 1; /* XXX add through-vars */
+       n_ins->sx.s23.s2.args = (s4*) DumpMemory::allocate(sizeof(s4));
+       n_ins->sx.s23.s2.args[0] = syncvar;
+}
+
+static s4 emit_inlining_prolog(inline_node *iln,
+                                                          inline_node *callee,
+                                                          instruction *o_iptr,
+                                                          s4 *varmap)
+{
+       methodinfo *calleem;
+       methoddesc *md;
+       int i;
+       int localindex;
+       int type;
+       instruction *n_ins;
+       insinfo_inline *insinfo;
+       s4 varindex;
+
+       assert(iln && callee && o_iptr);
+
+       calleem = callee->m;
+       md = calleem->parseddesc;
+
+       /* INLINE_START instruction */
+
+       n_ins = inline_instruction(iln, ICMD_INLINE_START, o_iptr);
+
+       insinfo = (insinfo_inline*) DumpMemory::allocate(sizeof(insinfo_inline));
+       insinfo->method = callee->m;
+       insinfo->outer = iln->m;
+       insinfo->synclocal = callee->synclocal;
+       insinfo->synchronize = callee->synchronize;
+       insinfo->javalocals_start = NULL;
+       insinfo->javalocals_end = NULL;
+
+       /* info about stack vars live at the INLINE_START */
+
+       insinfo->throughcount = callee->n_passthroughcount;
+       insinfo->paramcount = md->paramcount;
+       insinfo->stackvarscount = o_iptr->s1.argcount;
+       insinfo->stackvars = (s4*) DumpMemory::allocate(sizeof(s4) * insinfo->stackvarscount);
+       for (i=0; i<insinfo->stackvarscount; ++i)
+               insinfo->stackvars[i] = iln->varmap[o_iptr->sx.s23.s2.args[i]];
+
+       /* info about the surrounding inlining */
+
+       if (iln->inline_start_instruction)
+               insinfo->parent = iln->inline_start_instruction->sx.s23.s3.inlineinfo;
+       else
+               insinfo->parent = NULL;
+
+       /* finish the INLINE_START instruction */
+
+       n_ins->sx.s23.s3.inlineinfo = insinfo;
+       callee->inline_start_instruction = n_ins;
+
+       DOLOG( printf("%sprolog: ", iln->indent);
+                  show_icmd(iln->ctx->resultjd, n_ins, false, SHOW_STACK); printf("\n"); );
+
+       /* handle parameters for the inlined callee */
+
+       localindex = callee->localsoffset + md->paramslots;
+
+       for (i=md->paramcount-1; i>=0; --i) {
+               assert(iln);
+
+               type = md->paramtypes[i].type;
+
+               localindex -= IS_2_WORD_TYPE(type) ? 2 : 1;
+               assert(callee->regdata);
+
+               /* translate the argument variable */
+
+               varindex = varmap[o_iptr->sx.s23.s2.args[i]];
+               assert(varindex != UNUSED);
+
+               /* remove preallocation from the argument variable */
+
+               iln->ctx->resultjd->var[varindex].flags &= ~(PREALLOC | INMEMORY);
+
+               /* check the instance slot against NULL */
+               /* we don't need that for <init> methods, as the verifier  */
+               /* ensures that they are only called for an uninit. object */
+               /* (which may not be NULL).                                */
+
+               if (!callee->isstatic && i == 0 && calleem->name != utf_init) {
+                       assert(type == TYPE_ADR);
+                       n_ins = inline_instruction(iln, ICMD_CHECKNULL, o_iptr);
+                       n_ins->s1.varindex = varindex;
+                       n_ins->dst.varindex = n_ins->s1.varindex;
+               }
+
+               /* store argument into local variable of inlined callee */
+
+               if (callee->jd->local_map[5*(localindex - callee->localsoffset) + type] != UNUSED)
+               {
+                       /* this value is used in the callee */
+
+                       if (i == 0 && callee->synclocal != UNUSED) {
+                               /* we also need it for synchronization, so copy it */
+                               assert(type == TYPE_ADR);
+                               n_ins = inline_instruction(iln, ICMD_COPY, o_iptr);
+                       }
+                       else {
+                               n_ins = inline_instruction(iln, ICMD_ISTORE + type, o_iptr);
+                               n_ins->sx.s23.s3.javaindex = UNUSED;
+                       }
+                       n_ins->s1.varindex = varindex;
+                       n_ins->dst.varindex = iln->ctx->resultjd->local_map[5*localindex + type];
+                       assert(n_ins->dst.varindex != UNUSED);
+               }
+               else if (i == 0 && callee->synclocal != UNUSED) {
+                       /* the value is not used inside the callee, but we need it for */
+                       /* synchronization                                             */
+                       /* XXX In this case it actually makes no sense to create a     */
+                       /*     separate synchronization variable.                      */
+
+                       n_ins = inline_instruction(iln, ICMD_NOP, o_iptr);
+               }
+               else {
+                       /* this value is not used, pop it */
+
+                       n_ins = inline_instruction(iln, ICMD_POP, o_iptr);
+                       n_ins->s1.varindex = varindex;
+               }
+
+               DOLOG( printf("%sprolog: ", iln->indent);
+                          show_icmd(iln->ctx->resultjd, n_ins, false, SHOW_STACK); printf("\n"); );
+       }
+
+       /* COPY for synchronized instance methods */
+
+       if (callee->synclocal != UNUSED) {
+               n_ins = inline_instruction(iln, ICMD_COPY, o_iptr);
+               n_ins->s1.varindex = varmap[o_iptr->sx.s23.s2.args[0]];
+               n_ins->dst.varindex = callee->synclocal;
+
+               assert(n_ins->s1.varindex != UNUSED);
+       }
+
+       if (callee->synchronize) {
+               inline_generate_sync_builtin(iln, callee, o_iptr,
+                                                                        (callee->isstatic) ? UNUSED : varmap[o_iptr->sx.s23.s2.args[0]],
+                                                                        LOCK_monitor_enter);
+       }
+
+       /* INLINE_BODY instruction */
+
+       n_ins = inline_instruction(iln, ICMD_INLINE_BODY, callee->jd->basicblocks[0].iinstr);
+       n_ins->sx.s23.s3.inlineinfo = insinfo;
+
+       return 0; /* XXX */
+}
+
+
+static void emit_inlining_epilog(inline_node *iln, inline_node *callee, instruction *o_iptr)
+{
+       instruction *n_ins;
+       s4          *jl;
+
+       assert(iln && callee && o_iptr);
+       assert(callee->inline_start_instruction);
+
+       if (callee->synchronize) {
+               inline_generate_sync_builtin(iln, callee, o_iptr,
+                                                                        callee->synclocal,
+                                                                        LOCK_monitor_exit);
+       }
+
+       /* INLINE_END instruction */
+
+       n_ins = inline_instruction(iln, ICMD_INLINE_END, o_iptr);
+       n_ins->sx.s23.s3.inlineinfo = callee->inline_start_instruction->sx.s23.s3.inlineinfo;
+
+       /* set the javalocals */
+
+       jl = (s4*) DumpMemory::allocate(sizeof(s4) * iln->jd->maxlocals);
+       MCOPY(jl, iln->javalocals, s4, iln->jd->maxlocals);
+       n_ins->sx.s23.s3.inlineinfo->javalocals_end = jl;
+
+       DOLOG( printf("%sepilog: ", iln->indent);
+                  show_icmd(iln->ctx->resultjd, n_ins, false, SHOW_STACK); printf("\n"); );
+}
+
+
+#define TRANSLATE_VAROP(vo)  \
+       n_iptr->vo.varindex = inline_translate_variable(jd, origjd, varmap, n_iptr->vo.varindex)
+
+
+static void inline_clone_instruction(inline_node *iln,
+                                                                        jitdata *jd,
+                                                                        jitdata *origjd,
+                                                                        s4 *varmap,
+                                                                        instruction *o_iptr,
+                                                                        instruction *n_iptr)
+{
+       icmdtable_entry_t *icmdt;
+       builtintable_entry *bte;
+       methoddesc *md;
+       s4 i, j;
+       branch_target_t *table;
+       lookup_target_t *lookup;
+       inline_node *scope;
+
+       *n_iptr = *o_iptr;
+
+       icmdt = &(icmd_table[o_iptr->opc]);
+
+       switch (icmdt->dataflow) {
+               case DF_0_TO_0:
+                       break;
+
+               case DF_3_TO_0:
+                       TRANSLATE_VAROP(sx.s23.s3);
+               case DF_2_TO_0:
+                       TRANSLATE_VAROP(sx.s23.s2);
+               case DF_1_TO_0:
+                       TRANSLATE_VAROP(s1);
+                       break;
+
+               case DF_2_TO_1:
+                       TRANSLATE_VAROP(sx.s23.s2);
+               case DF_1_TO_1:
+               case DF_COPY:
+               case DF_MOVE:
+                       TRANSLATE_VAROP(s1);
+               case DF_0_TO_1:
+                       TRANSLATE_VAROP(dst);
+                       break;
+
+               case DF_N_TO_1:
+                       n_iptr->sx.s23.s2.args = (s4*) DumpMemory::allocate(sizeof(s4) * n_iptr->s1.argcount);
+                       for (i=0; i<n_iptr->s1.argcount; ++i) {
+                               n_iptr->sx.s23.s2.args[i] =
+                                       inline_translate_variable(jd, origjd, varmap,
+                                                       o_iptr->sx.s23.s2.args[i]);
+                       }
+                       TRANSLATE_VAROP(dst);
+                       break;
+
+               case DF_INVOKE:
+                       INSTRUCTION_GET_METHODDESC(n_iptr, md);
+clone_call:
+                       n_iptr->s1.argcount += iln->n_passthroughcount;
+                       n_iptr->sx.s23.s2.args = (s4*) DumpMemory::allocate(sizeof(s4) * n_iptr->s1.argcount);
+                       for (i=0; i<o_iptr->s1.argcount; ++i) {
+                               n_iptr->sx.s23.s2.args[i] =
+                                       inline_translate_variable(jd, origjd, varmap,
+                                                       o_iptr->sx.s23.s2.args[i]);
+                       }
+                       for (scope = iln; scope != NULL; scope = scope->parent) {
+                               for (j = 0; j < scope->n_selfpassthroughcount; ++j) {
+                                       n_iptr->sx.s23.s2.args[i++] =
+                                               scope->parent->varmap[scope->n_passthroughvars[j]];
+                               }
+                       }
+                       if (md->returntype.type != TYPE_VOID)
+                               TRANSLATE_VAROP(dst);
+                       break;
+
+               case DF_BUILTIN:
+                       bte = n_iptr->sx.s23.s3.bte;
+                       md = bte->md;
+                       goto clone_call;
+
+               default:
+                       assert(0);
+       }
+
+       switch (icmdt->controlflow) {
+               case CF_RET:
+                       TRANSLATE_VAROP(s1); /* XXX should be handled by data-flow */
+                       /* FALLTHROUGH */
+               case CF_IF:
+               case CF_GOTO:
+                       inline_add_block_reference(iln, &(n_iptr->dst.block));
+                       break;
+
+               case CF_JSR:
+                       inline_add_block_reference(iln, &(n_iptr->sx.s23.s3.jsrtarget.block));
+                       break;
+
+               case CF_TABLE:
+                       i = n_iptr->sx.s23.s3.tablehigh - n_iptr->sx.s23.s2.tablelow + 1 + 1 /* default */;
+
+                       table = (branch_target_t*) DumpMemory::allocate(sizeof(branch_target_t) *  i);
+                       MCOPY(table, o_iptr->dst.table, branch_target_t, i);
+                       n_iptr->dst.table = table;
+
+                       while (--i >= 0) {
+                               inline_add_block_reference(iln, &(table->block));
+                               table++;
+                       }
+                       break;
+
+               case CF_LOOKUP:
+                       inline_add_block_reference(iln, &(n_iptr->sx.s23.s3.lookupdefault.block));
+
+                       i = n_iptr->sx.s23.s2.lookupcount;
+                       lookup = (lookup_target_t*) DumpMemory::allocate(sizeof(lookup_target_t) * i);
+                       MCOPY(lookup, o_iptr->dst.lookup, lookup_target_t, i);
+                       n_iptr->dst.lookup = lookup;
+
+                       while (--i >= 0) {
+                               inline_add_block_reference(iln, &(lookup->target.block));
+                               lookup++;
+                       }
+                       break;
+       }
+
+       /* XXX move this to dataflow section? */
+
+       switch (n_iptr->opc) {
+               case ICMD_ASTORE:
+#if 0
+                       if (n_iptr->flags.bits & INS_FLAG_RETADDR)
+                               inline_add_blocknr_reference(iln, &(n_iptr->sx.s23.s2.retaddrnr));
+#endif
+                       /* FALLTHROUGH! */
+               case ICMD_ISTORE:
+               case ICMD_LSTORE:
+               case ICMD_FSTORE:
+               case ICMD_DSTORE:
+                       stack_javalocals_store(n_iptr, iln->javalocals);
+                       break;
+       }
+}
+
+
+static void inline_rewrite_method(inline_node *iln)
+{
+       basicblock *o_bptr;
+       s4 len;
+       instruction *o_iptr;
+       instruction *n_iptr;
+       inline_node *nextcall;
+       basicblock *n_bptr;
+       inline_block_map *bm;
+       int i;
+       int icount;
+       jitdata *resultjd;
+       jitdata *origjd;
+       char indent[100]; /* XXX debug */
+       s4 retcount;
+       s4 retidx;
+
+       assert(iln);
+
+       resultjd = iln->ctx->resultjd;
+       origjd = iln->jd;
+
+       n_bptr = NULL;
+       nextcall = iln->children;
+
+       /* XXX debug */
+       for (i=0; i<iln->depth; ++i)
+               indent[i] = '\t';
+       indent[i] = 0;
+       iln->indent = indent;
+
+       DOLOG( printf("%srewriting: ", indent); method_println(iln->m);
+                  printf("%s(passthrough: %d+%d)\n",
+                               indent, iln->n_passthroughcount - iln->n_selfpassthroughcount,
+                               iln->n_passthroughcount); );
+
+       /* set memory cursors */
+
+       iln->inlined_iinstr_cursor = iln->inlined_iinstr;
+       iln->inlined_basicblocks_cursor = iln->inlined_basicblocks;
+
+       /* allocate temporary buffers */
+
+       iln->javalocals = (s4*) DumpMemory::allocate(sizeof(s4) * iln->jd->maxlocals);
+
+       /* loop over basic blocks */
+
+       o_bptr = iln->jd->basicblocks;
+       for (; o_bptr; o_bptr = o_bptr->next) {
+
+               if (o_bptr->flags < BBREACHED) {
+
+                       /* ignore the dummy end block */
+
+                       if (o_bptr->icount == 0 && o_bptr->next == NULL) {
+                               /* enter the following block as translation, for exception handler ranges */
+                               inline_block_translation(iln, o_bptr, iln->inlined_basicblocks_cursor);
+                               continue;
+                       }
+
+                       DOLOG(
+                       printf("%s* skipping old L%03d (flags=%d, type=%d, oid=%d) of ",
+                                       indent,
+                                       o_bptr->nr, o_bptr->flags, o_bptr->type,
+                                       o_bptr->indepth);
+                       method_println(iln->m);
+                       );
+
+                       n_bptr = create_body_block(iln, o_bptr, iln->varmap);
+
+                       /* enter it in the blockmap */
+
+                       inline_block_translation(iln, o_bptr, n_bptr);
+
+                       close_body_block(iln, n_bptr, o_bptr, iln->varmap, 0, -1);
+                       continue;
+               }
+
+               len = o_bptr->icount;
+               o_iptr = o_bptr->iinstr;
+
+               DOLOG(
+               printf("%s* rewriting old L%03d (flags=%d, type=%d, oid=%d) of ",
+                               indent,
+                               o_bptr->nr, o_bptr->flags, o_bptr->type,
+                               o_bptr->indepth);
+               method_println(iln->m);
+               show_basicblock(iln->jd, o_bptr, SHOW_STACK);
+               );
+
+               if (iln->blockbefore || o_bptr != iln->jd->basicblocks) {
+                       /* create an inlined clone of this block */
+
+                       n_bptr = create_body_block(iln, o_bptr, iln->varmap);
+                       icount = 0;
+
+                       /* enter it in the blockmap */
+
+                       inline_block_translation(iln, o_bptr, n_bptr);
+
+                       /* initialize the javalocals */
+
+                       MCOPY(iln->javalocals, n_bptr->javalocals, s4, iln->jd->maxlocals);
+               }
+               else {
+                       s4 *jl;
+
+                       /* continue caller block */
+
+                       n_bptr = iln->inlined_basicblocks_cursor - 1;
+                       icount = n_bptr->icount;
+
+                       /* translate the javalocals */
+
+                       jl = translate_javalocals(iln, o_bptr->javalocals);
+                       iln->inline_start_instruction->sx.s23.s3.inlineinfo->javalocals_start = jl;
+
+                       MCOPY(iln->javalocals, jl, s4, iln->jd->maxlocals);
+               }
+
+               /* iterate over the ICMDs of this block */
+
+               retcount = 0;
+               retidx = UNUSED;
+
+               while (--len >= 0) {
+
+                       DOLOG( fputs(indent, stdout); show_icmd(iln->jd, o_iptr, false,  SHOW_STACK);
+                                  printf("\n") );
+
+                       /* handle calls that will be inlined */
+
+                       if (nextcall && o_iptr == nextcall->callerins) {
+
+                               /* write the inlining prolog */
+
+                               (void) emit_inlining_prolog(iln, nextcall, o_iptr, iln->varmap);
+                               icount += nextcall->prolog_instructioncount;
+
+                               /* end current block, or glue blocks together */
+
+                               n_bptr->icount = icount;
+
+                               if (nextcall->blockbefore) {
+                                       close_prolog_block(iln, n_bptr, nextcall);
+                               }
+                               else {
+                                       /* XXX */
+                               }
+
+                               /* check if the result is a local variable */
+
+                               if (nextcall->m->parseddesc->returntype.type != TYPE_VOID
+                                               && o_iptr->dst.varindex < iln->jd->localcount)
+                               {
+                                       nextcall->n_resultlocal = iln->varmap[o_iptr->dst.varindex];
+                               }
+                               else
+                                       nextcall->n_resultlocal = -1;
+
+                               /* set memory pointers in the callee */
+
+                               nextcall->inlined_iinstr = iln->inlined_iinstr_cursor;
+                               nextcall->inlined_basicblocks = iln->inlined_basicblocks_cursor;
+
+                               /* recurse */
+
+                               DOLOG( printf("%sentering inline ", indent);
+                                          show_icmd(origjd, o_iptr, false, SHOW_STACK); printf("\n") );
+
+                               inline_rewrite_method(nextcall);
+
+                               DOLOG( printf("%sleaving inline ", indent);
+                                          show_icmd(origjd, o_iptr, false, SHOW_STACK); printf("\n") );
+
+                               /* update memory cursors */
+
+                               assert(nextcall->inlined_iinstr_cursor
+                                               <= iln->inlined_iinstr_cursor + nextcall->cumul_instructioncount);
+                               assert(nextcall->inlined_basicblocks_cursor
+                                               == iln->inlined_basicblocks_cursor + nextcall->cumul_basicblockcount);
+                               iln->inlined_iinstr_cursor = nextcall->inlined_iinstr_cursor;
+                               iln->inlined_basicblocks_cursor = nextcall->inlined_basicblocks_cursor;
+
+                               /* start new block, or glue blocks together */
+
+                               if (nextcall->blockafter) {
+                                       n_bptr = create_epilog_block(iln, nextcall, iln->varmap);
+                                       icount = 0;
+                               }
+                               else {
+                                       n_bptr = iln->inlined_basicblocks_cursor - 1;
+                                       icount = n_bptr->icount;
+                                       /* XXX */
+                               }
+
+                               /* emit inlining epilog */
+
+                               emit_inlining_epilog(iln, nextcall, o_iptr);
+                               icount += nextcall->epilog_instructioncount;
+
+                               /* proceed to next call */
+
+                               nextcall = nextcall->next;
+                       }
+                       else {
+                               n_iptr = (iln->inlined_iinstr_cursor++);
+                               assert((n_iptr - iln->inlined_iinstr) < iln->cumul_instructioncount);
+
+                               switch (o_iptr->opc) {
+                                       case ICMD_RETURN:
+                                               if (iln->depth == 0)
+                                                       goto default_clone;
+                                               goto return_tail;
+
+                                       case ICMD_IRETURN:
+                                       case ICMD_ARETURN:
+                                       case ICMD_LRETURN:
+                                       case ICMD_FRETURN:
+                                       case ICMD_DRETURN:
+                                               if (iln->depth == 0)
+                                                       goto default_clone;
+                                               retcount = 1;
+                                               retidx = iln->varmap[o_iptr->s1.varindex];
+                                               if (iln->n_resultlocal != -1) {
+                                                       /* store result in a local variable */
+
+                                                       DOLOG( printf("USING RESULTLOCAL %d\n", iln->n_resultlocal); );
+                                                       /* This relies on the same sequence of types for */
+                                                       /* ?STORE and ?RETURN opcodes.                   */
+                                                       n_iptr->opc = ICMD_ISTORE + (o_iptr->opc - ICMD_IRETURN);
+                                                       n_iptr->s1.varindex = retidx;
+                                                       n_iptr->dst.varindex = iln->n_resultlocal;
+                                                       n_iptr->sx.s23.s3.javaindex = UNUSED; /* XXX set real javaindex? */
+
+                                                       retcount = 0;
+                                                       retidx = UNUSED;
+
+                                                       n_iptr = (iln->inlined_iinstr_cursor++);
+                                                       assert((n_iptr - iln->inlined_iinstr) < iln->cumul_instructioncount);
+                                                       icount++;
+                                               }
+                                               else if ((retidx < resultjd->localcount && iln->blockafter)
+                                                               || !iln->blockafter) /* XXX do we really always need the MOVE? */
+                                               {
+                                                       /* local must not become outvar, insert a MOVE */
+
+                                                       n_iptr->opc = ICMD_MOVE;
+                                                       n_iptr->s1.varindex = retidx;
+                                                       retidx = inline_new_temp_variable(resultjd,
+                                                                                                                         resultjd->var[retidx].type);
+                                                       n_iptr->dst.varindex = retidx;
+
+                                                       n_iptr = (iln->inlined_iinstr_cursor++);
+                                                       assert((n_iptr - iln->inlined_iinstr) < iln->cumul_instructioncount);
+                                                       icount++;
+                                               }
+return_tail:
+                                               if (iln->blockafter) {
+                                                       n_iptr->opc = ICMD_GOTO;
+                                                       n_iptr->dst.block = INLINE_RETURN_REFERENCE(iln);
+                                                       inline_add_block_reference(iln, &(n_iptr->dst.block));
+                                               }
+                                               else {
+                                                       n_iptr->opc = ICMD_NOP;
+                                               }
+                                               break;
+#if 0
+                                               if (o_bptr->next == NULL || (o_bptr->next->icount==0 && o_bptr->next->next == NULL)) {
+                                                       n_iptr->opc = ICMD_NOP;
+                                                       break;
+                                               }
+                                               goto default_clone;
+                                               break;
+#endif
+
+                                       default:
+default_clone:
+                                               inline_clone_instruction(iln, resultjd, iln->jd, iln->varmap, o_iptr, n_iptr);
+                               }
+
+                               DOLOG( fputs(indent, stdout); show_icmd(resultjd, n_iptr, false, SHOW_STACK);
+                                          printf("\n"););
+
+                               icount++;
+                       }
+
+                       o_iptr++;
+               }
+
+               /* end of basic block */
+
+               if (iln->blockafter || (o_bptr->next && o_bptr->next->next)) {
+                       close_body_block(iln, n_bptr, o_bptr, iln->varmap, retcount, retidx);
+                       n_bptr->icount = icount;
+
+                       DOLOG( printf("closed body block:\n");
+                                  show_basicblock(resultjd, n_bptr, SHOW_STACK); );
+               }
+               else {
+                       n_bptr->icount = icount;
+                       assert(iln->parent);
+                       if (retidx != UNUSED)
+                               iln->parent->varmap[iln->callerins->dst.varindex] = retidx;
+               }
+       }
+
+       bm = iln->ctx->blockmap;
+       for (i=0; i<iln->ctx->blockmap_index; ++i, ++bm) {
+               assert(bm->iln && bm->o_block && bm->n_block);
+               if (bm->iln == iln)
+                       inline_resolve_block_refs(&(iln->refs), bm->o_block, bm->n_block, false);
+       }
+
+#if !defined(NDEBUG)
+       if (iln->refs) {
+               inline_target_ref *ref;
+               ref = iln->refs;
+               while (ref) {
+                       if (!iln->depth || ref->isnumber || *(ref->ref.block) != INLINE_RETURN_REFERENCE(iln)) {
+                               DOLOG( printf("XXX REMAINING REF at depth %d: %p\n", iln->depth,
+                                          (void*)*(ref->ref.block)) );
+                               assert(false);
+                       }
+                       ref = ref->next;
+               }
+       }
+#endif
+}
+
+
+static exception_entry * inline_exception_tables(inline_node *iln,
+                                                                                                exception_entry *n_extable,
+                                                                                                exception_entry **prevextable)
+{
+       inline_node *child;
+       inline_node *scope;
+       exception_entry *et;
+
+       assert(iln);
+       assert(n_extable);
+       assert(prevextable);
+
+       child = iln->children;
+       if (child) {
+               do {
+                       n_extable = inline_exception_tables(child, n_extable, prevextable);
+                       child = child->next;
+               } while (child != iln->children);
+       }
+
+       et = iln->jd->exceptiontable;
+       for (; et != NULL; et = et->down) {
+               assert(et);
+               MZERO(n_extable, exception_entry, 1);
+               n_extable->start     = inline_map_block(iln, et->start  , iln);
+               n_extable->end       = inline_map_block(iln, et->end    , iln);
+               n_extable->handler   = inline_map_block(iln, et->handler, iln);
+               n_extable->catchtype = et->catchtype;
+
+               if (*prevextable) {
+                       (*prevextable)->down = n_extable;
+               }
+               *prevextable = n_extable;
+
+               n_extable++;
+       }
+
+       if (iln->handler_monitorexit) {
+               exception_entry **activehandlers;
+
+               MZERO(n_extable, exception_entry, 1);
+               n_extable->start   = iln->inlined_basicblocks;
+               n_extable->end     = iln->inlined_basicblocks_cursor;
+               n_extable->handler = iln->handler_monitorexit;
+               n_extable->catchtype.any = NULL; /* finally */
+
+               if (*prevextable) {
+                       (*prevextable)->down = n_extable;
+               }
+               *prevextable = n_extable;
+
+               n_extable++;
+
+               /* We have to protect the created handler with the same handlers */
+               /* that protect the method body itself.                          */
+
+               for (scope = iln; scope->parent != NULL; scope = scope->parent) {
+
+                       activehandlers = scope->o_handlers;
+                       assert(activehandlers);
+
+                       while (*activehandlers) {
+
+                               assert(scope->parent);
+
+                               MZERO(n_extable, exception_entry, 1);
+                               n_extable->start     = iln->handler_monitorexit;
+                               n_extable->end       = iln->handler_monitorexit + 1; /* XXX ok in this case? */
+                               n_extable->handler   = inline_map_block(scope->parent,
+                                                                                                               (*activehandlers)->handler,
+                                                                                                               scope->parent);
+                               n_extable->catchtype = (*activehandlers)->catchtype;
+
+                               if (*prevextable) {
+                                       (*prevextable)->down = n_extable;
+                               }
+                               *prevextable = n_extable;
+
+                               n_extable++;
+                               activehandlers++;
+                       }
+               }
+       }
+
+       return n_extable;
+}
+
+
+static void inline_locals(inline_node *iln)
+{
+       inline_node *child;
+
+       assert(iln);
+
+       iln->varmap = create_variable_map(iln);
+
+       child = iln->children;
+       if (child) {
+               do {
+                       inline_locals(child);
+                       child = child->next;
+               } while (child != iln->children);
+       }
+
+       if (iln->regdata->memuse > iln->ctx->resultjd->rd->memuse)
+               iln->ctx->resultjd->rd->memuse = iln->regdata->memuse;
+       if (iln->regdata->argintreguse > iln->ctx->resultjd->rd->argintreguse)
+               iln->ctx->resultjd->rd->argintreguse = iln->regdata->argintreguse;
+       if (iln->regdata->argfltreguse > iln->ctx->resultjd->rd->argfltreguse)
+               iln->ctx->resultjd->rd->argfltreguse = iln->regdata->argfltreguse;
+}
+
+
+static void inline_interface_variables(inline_node *iln)
+{
+       basicblock *bptr;
+       jitdata *resultjd;
+       s4 i;
+       varinfo *v;
+
+       resultjd = iln->ctx->resultjd;
+
+       resultjd->interface_map = (interface_info*) DumpMemory::allocate(sizeof(interface_info) * 5 * iln->ctx->maxinoutdepth);
+       for (i=0; i<5*iln->ctx->maxinoutdepth; ++i)
+               resultjd->interface_map[i].flags = UNUSED;
+
+       for (bptr = resultjd->basicblocks; bptr != NULL; bptr = bptr->next) {
+               assert(bptr->indepth  <= iln->ctx->maxinoutdepth);
+               assert(bptr->outdepth <= iln->ctx->maxinoutdepth);
+
+               for (i=0; i<bptr->indepth; ++i) {
+                       v = &(resultjd->var[bptr->invars[i]]);
+                       v->flags |= INOUT;
+                       if (v->type == TYPE_RET)
+                               v->flags |= PREALLOC;
+                       else
+                               v->flags &= ~PREALLOC;
+                       v->flags &= ~INMEMORY;
+                       assert(bptr->invars[i] >= resultjd->localcount);
+
+                       if (resultjd->interface_map[5*i + v->type].flags == UNUSED) {
+                               resultjd->interface_map[5*i + v->type].flags = v->flags;
+                       }
+                       else {
+                               resultjd->interface_map[5*i + v->type].flags |= v->flags;
+                       }
+               }
+
+               for (i=0; i<bptr->outdepth; ++i) {
+                       v = &(resultjd->var[bptr->outvars[i]]);
+                       v->flags |= INOUT;
+                       if (v->type == TYPE_RET)
+                               v->flags |= PREALLOC;
+                       else
+                               v->flags &= ~PREALLOC;
+                       v->flags &= ~INMEMORY;
+                       assert(bptr->outvars[i] >= resultjd->localcount);
+
+                       if (resultjd->interface_map[5*i + v->type].flags == UNUSED) {
+                               resultjd->interface_map[5*i + v->type].flags = v->flags;
+                       }
+                       else {
+                               resultjd->interface_map[5*i + v->type].flags |= v->flags;
+                       }
+               }
+       }
+}
+
+
+static void inline_write_exception_handlers(inline_node *master, inline_node *iln)
+{
+       basicblock *n_bptr;
+       instruction *n_ins;
+       inline_node *child;
+       builtintable_entry *bte;
+       s4 exvar;
+       s4 syncvar;
+       s4 i;
+
+       child = iln->children;
+       if (child) {
+               do {
+                       inline_write_exception_handlers(master, child);
+                       child = child->next;
+               } while (child != iln->children);
+       }
+
+       if (iln->synchronize) {
+               /* create the monitorexit handler */
+               n_bptr = create_block(master, iln, iln,
+                                                         iln->n_passthroughcount + 1);
+               n_bptr->type = BBTYPE_EXH;
+               n_bptr->flags = BBFINISHED;
+
+               exvar = inline_new_variable(master->ctx->resultjd, TYPE_ADR, 0);
+               n_bptr->invars[iln->n_passthroughcount] = exvar;
+
+               iln->handler_monitorexit = n_bptr;
+
+               /* ACONST / ALOAD */
+
+               n_ins = master->inlined_iinstr_cursor++;
+               if (iln->m->flags & ACC_STATIC) {
+                       n_ins->opc = ICMD_ACONST;
+                       n_ins->sx.val.c.cls = iln->m->clazz;
+                       n_ins->flags.bits = INS_FLAG_CLASS;
+               }
+               else {
+                       n_ins->opc = ICMD_ALOAD;
+                       n_ins->s1.varindex = iln->synclocal;
+                       assert(n_ins->s1.varindex != UNUSED);
+               }
+               /* XXX could be PREALLOCed for  builtin call */
+               syncvar = inline_new_variable(master->ctx->resultjd, TYPE_ADR, 0);
+               n_ins->dst.varindex = syncvar;
+               n_ins->line = 0;
+
+               /* MONITOREXIT */
+
+               bte = builtintable_get_internal(LOCK_monitor_exit);
+
+               n_ins = master->inlined_iinstr_cursor++;
+               n_ins->opc = ICMD_BUILTIN;
+               n_ins->s1.argcount = 1 + iln->n_passthroughcount + 1;
+               n_ins->sx.s23.s2.args = (s4*) DumpMemory::allocate(sizeof(s4) * n_ins->s1.argcount);
+               n_ins->sx.s23.s2.args[0] = syncvar;
+               for (i=0; i < iln->n_passthroughcount + 1; ++i) {
+                       n_ins->sx.s23.s2.args[1 + i] = n_bptr->invars[i];
+               }
+               n_ins->sx.s23.s3.bte = bte;
+               n_ins->line = 0;
+
+               /* ATHROW */
+
+               n_ins = master->inlined_iinstr_cursor++;
+               n_ins->opc = ICMD_ATHROW;
+               n_ins->flags.bits = 0;
+               n_ins->s1.varindex = exvar;
+               n_ins->line = 0;
+
+               /* close basic block */
+
+               close_block(iln, iln, n_bptr, iln->n_passthroughcount);
+               n_bptr->icount = 3;
+       }
+}
+
+
+/* second pass driver *********************************************************/
+
+static bool inline_transform(inline_node *iln, jitdata *jd)
+{
+       instruction *n_ins;
+       basicblock *n_bb;
+       basicblock *n_bptr;
+       exception_entry *n_ext;
+       exception_entry *prevext;
+       codegendata *n_cd;
+       jitdata *n_jd;
+       s4 i;
+#if defined(INLINE_VERIFY_RESULT)
+       static int debug_verify_inlined_code = 1;
+#endif
+#if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
+       static int debug_counter = 0;
+#endif
+
+       DOLOG( dump_inline_tree(iln, 0); );
+
+       assert(iln && jd);
+
+       n_ins = (instruction*) DumpMemory::allocate(sizeof(instruction) * iln->cumul_instructioncount);
+       MZERO(n_ins, instruction, iln->cumul_instructioncount);
+       iln->inlined_iinstr = n_ins;
+
+       n_bb = (basicblock*) DumpMemory::allocate(sizeof(basicblock) * iln->cumul_basicblockcount);
+       MZERO(n_bb, basicblock, iln->cumul_basicblockcount);
+       iln->inlined_basicblocks = n_bb;
+
+       iln->ctx->blockmap = (inline_block_map*) DumpMemory::allocate(sizeof(inline_block_map) * iln->cumul_blockmapcount);
+
+       n_jd = jit_jitdata_new(iln->m);
+       n_jd->flags = jd->flags;
+       n_jd->code->optlevel = jd->code->optlevel;
+       iln->ctx->resultjd = n_jd;
+
+       reg_setup(n_jd);
+
+       /* create the local_map */
+
+       n_jd->local_map = (s4*) DumpMemory::allocate(sizeof(s4) *  5 * iln->cumul_maxlocals);
+       for (i=0; i<5*iln->cumul_maxlocals; ++i)
+               n_jd->local_map[i] = UNUSED;
+
+       /* create / coalesce local variables */
+
+       n_jd->varcount = 0;
+       n_jd->vartop = 0;
+       n_jd->var = NULL;
+
+       inline_locals(iln);
+
+       n_jd->localcount = n_jd->vartop;
+
+       /* extra variables for verification (debugging) */
+
+#if defined(INLINE_VERIFY_RESULT)
+       if (debug_verify_inlined_code) {
+               n_jd->vartop   += VERIFIER_EXTRA_LOCALS + VERIFIER_EXTRA_VARS + 100 /* XXX m->maxstack */;
+               if (n_jd->vartop > n_jd->varcount) {
+                       /* XXX why? */
+                       n_jd->var = (varinfo*) DumpMemory::realloc(n_jd->var, sizeof(varinfo) * n_jd->varcount, sizeof(varinfo) * n_jd->vartop);
+                       n_jd->varcount = n_jd->vartop;
+               }
+       }
+#endif /* defined(INLINE_VERIFY_RESULT) */
+
+       /* write inlined code */
+
+       inline_rewrite_method(iln);
+
+       /* create exception handlers */
+
+       inline_write_exception_handlers(iln, iln);
+
+       /* write the dummy end block */
+
+       n_bptr = create_block(iln, iln, iln, 0);
+       n_bptr->flags = BBUNDEF;
+       n_bptr->type = BBTYPE_STD;
+
+       /* store created code in jitdata */
+
+       n_jd->basicblocks = iln->inlined_basicblocks;
+       n_jd->instructioncount = iln->cumul_instructioncount;
+       n_jd->instructions = iln->inlined_iinstr;
+
+       /* link the basic blocks (dummy end block is not counted) */
+
+       n_jd->basicblockcount = (iln->inlined_basicblocks_cursor - iln->inlined_basicblocks) - 1;
+       for (i=0; i<n_jd->basicblockcount + 1; ++i)
+               n_jd->basicblocks[i].next = &(n_jd->basicblocks[i+1]);
+       if (i)
+               n_jd->basicblocks[i-1].next = NULL;
+
+       /* check basicblock numbers */
+
+#if !defined(NDEBUG)
+       jit_check_basicblock_numbers(n_jd);
+#endif
+
+       /* create the exception table */
+
+       if (iln->cumul_exceptiontablelength) {
+               exception_entry *tableend;
+
+               n_ext = (exception_entry*) DumpMemory::allocate(sizeof(exception_entry) * iln->cumul_exceptiontablelength);
+               prevext = NULL;
+               tableend = inline_exception_tables(iln, n_ext, &prevext);
+               assert(tableend == n_ext + iln->cumul_exceptiontablelength);
+               if (prevext)
+                       prevext->down = NULL;
+
+               n_jd->exceptiontablelength = iln->cumul_exceptiontablelength;
+               n_jd->exceptiontable = n_ext;
+       }
+       else {
+               n_ext = NULL;
+       }
+
+       /*******************************************************************************/
+
+       n_cd = n_jd->cd;
+       memcpy(n_cd, jd->cd, sizeof(codegendata));
+
+       n_cd->method = NULL; /* XXX */
+       n_jd->maxlocals = iln->cumul_maxlocals;
+       n_jd->maxinterfaces = iln->ctx->maxinoutdepth;
+
+       inline_post_process(n_jd);
+
+       inline_interface_variables(iln);
+
+       /* for debugging, verify the inlined result */
+
+#if defined(INLINE_VERIFY_RESULT)
+       if (debug_verify_inlined_code) {
+               debug_verify_inlined_code = 0;
+               DOLOG( printf("VERIFYING INLINED RESULT...\n"); fflush(stdout); );
+               if (!typecheck(n_jd)) {
+                       exceptions_clear_exception();
+                       DOLOG( printf("XXX INLINED RESULT DID NOT PASS VERIFIER XXX\n") );
+                       return false;
+               }
+               else {
+                       DOLOG( printf("VERIFICATION PASSED.\n") );
+               }
+               debug_verify_inlined_code = 1;
+       }
+#endif /* defined(INLINE_VERIFY_RESULT) */
+
+       /* we need bigger free memory stacks (XXX these should not be allocated in reg_setup) */
+
+       n_jd->rd->freemem = (s4*) DumpMemory::allocate(sizeof(s4) * (iln->ctx->maxinoutdepth + 1000)) /* XXX max vars/block */;
+
+#if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
+       if (   (n_jd->instructioncount >= opt_InlineMinSize)
+               && (n_jd->instructioncount <= opt_InlineMaxSize))
+       {
+          if (debug_counter < opt_InlineCount)
+#endif /* defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG) */
+          {
+                       /* install the inlined result */
+
+                       *jd->code = *n_jd->code;
+                       n_jd->code = jd->code;
+                       *jd = *n_jd;
+
+                       /* statistics and logging */
+
+#if !defined(NDEBUG)
+                       inline_stat_roots++;
+
+                       DOLOG_SHORT(
+                       printf("==== %d.INLINE ==================================================================\n",
+                               debug_counter);
+                       printf("\ninline tree:\n");
+                       dump_inline_tree(iln, 0);
+                       n_jd->flags |= JITDATA_FLAG_SHOWINTERMEDIATE | JITDATA_FLAG_SHOWDISASSEMBLE;
+                       /* debug_dump_inlined_code(iln, n_method, n_cd, n_rd); */
+                       printf("-------- DONE -----------------------------------------------------------\n");
+                       fflush(stdout);
+                       );
+#endif
+          }
+
+#if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
+               debug_counter++;
+       }
+#endif
+       return true;
+}
+
+
+/******************************************************************************/
+/* FIRST PASS: build inlining tree                                            */
+/******************************************************************************/
+
+
+/* inline_pre_parse_heuristics *************************************************
+
+   Perform heuristic checks whether a call site should be inlined.
+   These checks are evaluated before the callee has been parsed and analysed.
+
+   IN:
+       caller...........inlining node of the caller
+          callee...........the called method
+          site.............information on the call site
+
+   RETURN VALUE:
+       true........consider for inlining
+          false.......don't inline
+
+*******************************************************************************/
+
+static bool inline_pre_parse_heuristics(const inline_node *caller,
+                                                                               const methodinfo *callee,
+                                                                               inline_site *site)
+{
+#if defined(INLINE_MAX_DEPTH)
+       if (caller->depth >= INLINE_MAX_DEPTH)
+               return false;
+#endif
+
+       return true;
+}
+
+
+/* inline_post_parse_heuristics ************************************************
+
+   Perform heuristic checks whether a call site should be inlined.
+   These checks are evaluated after the callee has been parsed and analysed.
+
+   IN:
+       caller...........inlining node of the caller (const)
+          callee...........the called method (const)
+
+   RETURN VALUE:
+          true........consider for inlining
+          false.......don't inline
+
+*******************************************************************************/
+
+static bool inline_post_parse_heuristics(const inline_node *caller,
+                                                                                const inline_node *callee)
+{
+       return true;
+}
+
+
+/* inline_afterwards_heuristics ************************************************
+
+   Perform heuristic checks whether a call site should be inlined.
+   These checks are evaluated after the inlining plan for the callee has
+   been made.
+
+   IN:
+       caller...........inlining node of the caller (const)
+          callee...........the called method (const)
+
+   RETURN VALUE:
+          true........consider for inlining
+          false.......don't inline
+
+*******************************************************************************/
+
+static bool inline_afterwards_heuristics(const inline_node *caller,
+                                                                                const inline_node *callee)
+{
+       inline_node *cumulator;
+
+#if defined(INLINE_DEPTH_FIRST)
+       cumulator = caller;
+#else
+       cumulator = caller->ctx->master;
+#endif
+
+       if (0
+#if defined(INLINE_MAX_BLOCK_EXPANSION)
+               || (cumulator->cumul_basicblockcount + callee->cumul_basicblockcount
+                       > INLINE_MAX_BLOCK_EXPANSION*caller->ctx->master->jd->basicblockcount)
+#endif
+#if defined(INLINE_MAX_ICMD_EXPANSION)
+               || (cumulator->cumul_instructioncount + callee->cumul_instructioncount
+                       > INLINE_MAX_ICMD_EXPANSION*caller->ctx->master->jd->instructioncount)
+#endif
+          )
+       {
+               return false;
+       }
+
+       return true;
+}
+
+
+/* inline_is_monomorphic *******************************************************
+
+   Check if the given call site can be proven to be monomorphic.
+
+   IN:
+          callee...........the called method
+          call.............the invocation instruction
+
+   OUT:
+       site->speculative.....flags whether the inlining is speculative
+                                (only defined if return value is true)
+
+   RETURN VALUE:
+       true if the call site is (currently) monomorphic,
+          false if not or unknown
+
+*******************************************************************************/
+
+static bool inline_is_monomorphic(const methodinfo *callee,
+                                                                 const instruction *call,
+                                                                 inline_site *site)
+{
+       if ((callee->flags & (ACC_STATIC | ACC_FINAL | ACC_PRIVATE)
+                               || call->opc == ICMD_INVOKESPECIAL))
+       {
+               site->speculative = false;
+               return true;
+       }
+
+       /* XXX search single implementation for abstract monomorphics */
+
+       if ((callee->flags & (ACC_METHOD_MONOMORPHIC | ACC_METHOD_IMPLEMENTED
+                                       | ACC_ABSTRACT))
+                       == (ACC_METHOD_MONOMORPHIC | ACC_METHOD_IMPLEMENTED))
+       {
+               if (1) {
+                       DOLOG( printf("SPECULATIVE INLINE: "); method_println((methodinfo*)callee); );
+                       site->speculative = true;
+
+                       return true;
+               }
+       }
+
+       /* possibly polymorphic call site */
+
+       return false;
+}
+
+
+/* inline_can_inline ***********************************************************
+
+   Check if inlining of the given call site is possible.
+
+   IN:
+       caller...........inlining node of the caller
+          callee...........the called method
+          call.............the invocation instruction
+
+   OUT:
+       site->speculative.....flags whether the inlining is speculative
+                                (only defined if return value is true)
+
+   RETURN VALUE:
+       true if inlining is possible, false if not
+
+*******************************************************************************/
+
+static bool inline_can_inline(const inline_node *caller,
+                                                         const methodinfo *callee,
+                                                         const instruction *call,
+                                                         inline_site *site)
+{
+       const inline_node *active;
+
+       /* cannot inline native methods */
+
+       if (callee->flags & ACC_NATIVE)
+               return false;
+
+       /* cannot inline possibly polymorphic calls */
+
+       if (!inline_is_monomorphic(callee, call, site))
+               return false;
+
+       /* cannot inline recursive calls */
+
+       for (active = caller; active; active = active->parent) {
+               if (callee == active->m) {
+                       DOLOG( printf("RECURSIVE!\n") );
+                       return false;
+               }
+       }
+
+       /* inlining is possible */
+
+       return true;
+}
+
+
+/* inline_create_callee_node ***************************************************
+
+   Create an inlining node for the given callee.
+
+   IN:
+          caller...........inlining node of the caller (const)
+          callee...........the called method
+
+   RETURN VALUE:
+       the new inlining node
+
+*******************************************************************************/
+
+static inline_node * inline_create_callee_node(const inline_node *caller,
+                                                                                          methodinfo *callee)
+{
+       inline_node *cn;              /* the callee inline_node */
+
+       cn = (inline_node*) DumpMemory::allocate(sizeof(inline_node));
+       MZERO(cn, inline_node, 1);
+
+       cn->depth = caller->depth + 1;
+       cn->ctx = caller->ctx;
+       cn->m = callee;
+       cn->synchronize = (callee->flags & ACC_SYNCHRONIZED);
+       cn->isstatic = (callee->flags & ACC_STATIC);
+
+       return cn;
+}
+
+
+/* inline_set_callee_properties ************************************************
+
+   Set properties of the inlined call site.
+
+   IN:
+       caller...........inlining node of the caller (const)
+          cn...............the called method
+          site.............info about the call site (const)
+
+   OUT:
+       *cn..............has the properties set
+
+*******************************************************************************/
+
+static void inline_set_callee_properties(const inline_node *caller,
+                                                                                inline_node *cn,
+                                                                                const inline_site *site)
+{
+       s4           argi;
+       s4           i, j;
+       basicblock  *bptr;
+
+       /* set info about the call site */
+
+       cn->callerblock = site->bptr;
+       cn->callerins = site->iptr;
+       cn->callerpc = site->pc;
+       cn->o_handlers = site->handlers;
+       cn->n_handlercount = caller->n_handlercount + site->nhandlers;
+
+       /* determine if we need basic block boundaries before/after */
+
+       cn->blockbefore = false;
+       cn->blockafter = false;
+
+       if (cn->jd->branchtoentry)
+               cn->blockbefore = true;
+
+       if (cn->jd->branchtoend)
+               cn->blockafter = true;
+
+       if (cn->jd->returncount > 1)
+               cn->blockafter = true;
+
+       /* XXX make safer and reusable (maybe store last real block) */
+       for (bptr = cn->jd->basicblocks; bptr && bptr->next && bptr->next->next; bptr = bptr->next)
+               ;
+
+       if (cn->jd->returnblock != bptr)
+               cn->blockafter = true;
+
+       /* info about the callee */
+
+       cn->localsoffset = caller->localsoffset + caller->m->maxlocals;
+       cn->prolog_instructioncount = cn->m->parseddesc->paramcount + 2;
+       cn->epilog_instructioncount = 1; /* INLINE_END */
+       cn->extra_instructioncount = 0;
+
+       /* we need a CHECKNULL for instance methods, except for <init> */
+
+       if (!cn->isstatic && cn->m->name != utf_init)
+               cn->prolog_instructioncount += 1;
+
+       /* deal with synchronized callees */
+
+       if (cn->synchronize) {
+               methoddesc         *md;
+               builtintable_entry *bte;
+
+               /* we need basic block boundaries because of the handler */
+
+               cn->blockbefore = true;
+               cn->blockafter = true;
+
+               /* for synchronized static methods                 */
+               /* we need an ACONST, MONITORENTER in the prolog   */
+               /* and ACONST, MONITOREXIT in the epilog           */
+
+               /* for synchronized instance methods               */
+               /* we need an COPY, MONITORENTER in the prolog     */
+               /* and MONITOREXIT in the epilog                   */
+
+               if (cn->isstatic) {
+                       cn->prolog_instructioncount += 2;
+                       cn->epilog_instructioncount += 2;
+               }
+               else {
+                       cn->prolog_instructioncount += 2;
+                       cn->epilog_instructioncount += 1;
+                       cn->localsoffset += 1;
+               }
+
+               /* and exception handler */
+               /* ALOAD, builtin_monitorexit, ATHROW */
+
+               cn->extra_instructioncount += 3;
+
+               /* exception table entries */
+
+               cn->extra_exceptiontablelength = 1 + cn->n_handlercount;
+
+               /* add exception handler block */
+
+               cn->cumul_basicblockcount_root++;
+
+               /* we must call the builtins */
+
+               bte = builtintable_get_internal(LOCK_monitor_enter);
+               md = bte->md;
+               if (md->memuse > cn->regdata->memuse)
+                       cn->regdata->memuse = md->memuse;
+               if (md->argintreguse > cn->regdata->argintreguse)
+                       cn->regdata->argintreguse = md->argintreguse;
+
+               bte = builtintable_get_internal(LOCK_monitor_exit);
+               md = bte->md;
+               if (md->memuse > cn->regdata->memuse)
+                       cn->regdata->memuse = md->memuse;
+               if (md->argintreguse > cn->regdata->argintreguse)
+                       cn->regdata->argintreguse = md->argintreguse;
+       }
+
+       /* determine pass-through variables */
+
+       i = site->iptr->s1.argcount - cn->m->parseddesc->paramcount; /* max # of pass-though vars */
+
+       cn->n_passthroughvars = (s4*) DumpMemory::allocate(sizeof(s4) * i);
+       j = 0;
+       for (argi = site->iptr->s1.argcount - 1; argi >= cn->m->parseddesc->paramcount; --argi) {
+               s4 idx = site->iptr->sx.s23.s2.args[argi];
+               if (idx >= caller->jd->localcount) {
+                       cn->n_passthroughvars[j] = idx;
+                       j++;
+               }
+               else {
+                       DOLOG( printf("PASSING THROUGH LOCAL VARIABLE %d\n", idx); );
+               }
+       }
+       assert(j <= i);
+       cn->n_selfpassthroughcount = j;
+       cn->n_passthroughcount = caller->n_passthroughcount + cn->n_selfpassthroughcount;
+}
+
+
+/* inline_cumulate_counters ****************************************************
+
+   Cumulate counters after a node has been decided to become inlined.
+
+   IN:
+       caller...........inlining node of the caller
+          callee...........inlining node of the callee (const)
+
+   OUT:
+       *caller..........gets cumulated values added
+
+*******************************************************************************/
+
+static void inline_cumulate_counters(inline_node *caller,
+                                                                        const inline_node *cn)
+{
+       caller->cumul_instructioncount += cn->prolog_instructioncount;
+       caller->cumul_instructioncount += cn->epilog_instructioncount;
+       caller->cumul_instructioncount += cn->extra_instructioncount;
+       caller->cumul_instructioncount += cn->cumul_instructioncount - 1 /*invoke*/;
+
+       caller->cumul_basicblockcount += cn->cumul_basicblockcount;
+       caller->cumul_basicblockcount_root += cn->cumul_basicblockcount_root;
+       caller->cumul_blockmapcount += cn->cumul_blockmapcount;
+       caller->cumul_exceptiontablelength += cn->cumul_exceptiontablelength;
+       caller->cumul_exceptiontablelength += cn->extra_exceptiontablelength;
+
+       if (cn->cumul_maxlocals > caller->cumul_maxlocals)
+               caller->cumul_maxlocals = cn->cumul_maxlocals;
+
+       /* XXX extra block after inlined call */
+       if (cn->blockafter) {
+               caller->cumul_basicblockcount += 1;
+               caller->cumul_blockmapcount += 1;
+       }
+}
+
+
+/* inline_analyse_callee *******************************************************
+
+   Analyse an inlining candidate callee.
+
+   IN:
+       caller...........inlining node of the caller
+          callee...........the called method
+          site.............info about the call site
+
+   OUT:
+       site->inlined....true if the callee has been selected for inlining
+
+   RETURN VALUE:
+       the inline node of the callee, or
+       NULL if an error has occurred (don't use the inlining plan in this case)
+
+*******************************************************************************/
+
+static inline_node * inline_analyse_callee(inline_node *caller,
+                                                                                  methodinfo *callee,
+                                                                                  inline_site *site)
+{
+       inline_node *cn;              /* the callee inline_node */
+
+       /* create an inline tree node */
+
+       cn = inline_create_callee_node(caller, callee);
+
+       /* get the intermediate representation of the callee */
+
+       if (!inline_jit_compile(cn))
+               return NULL;
+
+       /* evaluate heuristics after parsing the callee */
+
+       if (!inline_post_parse_heuristics(caller, cn))
+               return cn;
+
+       /* the call site will be inlined */
+
+       site->inlined = true;
+
+       /* set info about the call site */
+
+       inline_set_callee_properties(caller, cn, site);
+
+       /* insert the node into the inline tree */
+
+       inline_insert_inline_node(caller, cn);
+
+       /* analyse recursively */
+
+       if (!inline_analyse_code(cn))
+               return NULL;
+
+       if (!inline_afterwards_heuristics(caller, cn)) {
+#if defined(INLINE_CANCEL_ON_THRESHOLD)
+               return NULL;
+#else
+               inline_remove_inline_node(caller, cn);
+               caller->ctx->stopped = true;
+               site->inlined = false;
+               return cn;
+#endif
+       }
+
+       /* cumulate counters */
+
+#if defined(INLINE_DEPTH_FIRST)
+       inline_cumulate_counters(caller, cn);
+#endif
+
+#if defined(INLINE_BREADTH_FIRST)
+       while (caller) {
+               inline_cumulate_counters(caller, cn);
+               caller = caller->parent;
+       }
+#endif
+
+       return cn;
+}
+
+
+/* inline_process_candidate ****************************************************
+
+   Process a selected inlining candidate.
+
+   IN:
+       cand.............the candidate
+
+   RETURN VALUE:
+       true........everything ok
+          false.......an error has occurred, don't use the plan
+
+*******************************************************************************/
+
+static bool inline_process_candidate(inline_candidate *cand)
+{
+       inline_node *cn;
+
+       cn = inline_analyse_callee(cand->caller,
+                                                          cand->callee,
+                                                          &(cand->site));
+
+       if (!cn)
+               return false;
+
+       if (!cand->site.inlined)
+               return true;
+
+       /* store assumptions */
+
+       if (cand->site.speculative)
+               method_add_assumption_monomorphic(cand->callee, cand->caller->ctx->master->m);
+
+       return true;
+}
+
+
+/* inline_analyse_code *********************************************************
+
+   Analyse the intermediate code of the given inlining node.
+
+   IN:
+       iln..............the inlining node
+
+   OUT:
+       *iln.............the inlining plan
+
+   RETURN VALUE:
+       true........everything ok
+          false.......an error has occurred, don't use the plan
+
+*******************************************************************************/
+
+static bool inline_analyse_code(inline_node *iln)
+{
+       methodinfo *m;
+       basicblock *bptr;
+       s4 len;
+       instruction *iptr;
+       methodinfo *callee;
+       exception_entry **handlers;
+       exception_entry *ex;
+       s4 nhandlers;
+       s4 blockendpc;
+       jitdata *mjd;
+       inline_site site;
+
+       assert(iln);
+
+       m = iln->m;
+       mjd = iln->jd;
+
+       /* initialize cumulative counters */
+
+       iln->cumul_maxlocals = iln->localsoffset + m->maxlocals;
+       iln->cumul_exceptiontablelength += mjd->exceptiontablelength;
+
+       /* iterate over basic blocks */
+
+       blockendpc = 0;
+
+       for (bptr = mjd->basicblocks; bptr; bptr = bptr->next) {
+
+               /* count the block */
+               /* ignore dummy end blocks (but count them for the blockmap) */
+
+               iln->cumul_blockmapcount++;
+               if ((bptr != mjd->basicblocks || iln->blockbefore)
+                               &&
+                       (bptr->icount > 0 || bptr->next != NULL))
+                       iln->cumul_basicblockcount++;
+
+               /* skip dead code */
+
+               if (bptr->flags < BBREACHED)
+                       continue;
+
+               /* allocate the buffer of active exception handlers */
+               /* XXX this wastes some memory, but probably it does not matter */
+
+               handlers = (exception_entry**) DumpMemory::allocate(sizeof(exception_entry*) * (mjd->exceptiontablelength + 1));
+
+               /* determine the active exception handlers for this block     */
+               /* XXX maybe the handlers of a block should be part of our IR */
+               /* XXX this should share code with the type checkers          */
+               nhandlers = 0;
+               for (ex = mjd->exceptiontable; ex ; ex = ex->down) {
+                       if ((ex->start->nr <= bptr->nr) && (ex->end->nr > bptr->nr)) {
+                               handlers[nhandlers++] = ex;
+                       }
+               }
+               handlers[nhandlers] = NULL;
+
+               len = bptr->icount;
+               iptr = bptr->iinstr;
+
+               blockendpc += len;
+               iln->cumul_instructioncount += len;
+
+               /* iterate over the instructions of the block */
+
+               for (; --len >= 0; ++iptr) {
+
+                       switch (iptr->opc) {
+                               case ICMD_INVOKEVIRTUAL:
+                               case ICMD_INVOKESPECIAL:
+                               case ICMD_INVOKESTATIC:
+                               case ICMD_INVOKEINTERFACE:
+
+                                       if (!INSTRUCTION_IS_UNRESOLVED(iptr) && !iln->ctx->stopped) {
+                                               callee = iptr->sx.s23.s3.fmiref->p.method;
+
+                                               if (inline_can_inline(iln, callee, iptr, &site)) {
+                                                       site.inlined = false;
+                                                       site.bptr = bptr;
+                                                       site.iptr = iptr;
+                                                       site.pc = blockendpc - len - 1;
+                                                       site.handlers = handlers;
+                                                       site.nhandlers = nhandlers;
+
+                                                       if (inline_pre_parse_heuristics(iln, callee, &site)) {
+#if defined(INLINE_KNAPSACK) || defined(INLINE_BREADTH_FIRST)
+                                                               inline_add_candidate(iln->ctx, iln, callee, &site);
+#else
+                                                               inline_candidate cand;
+                                                               cand.caller = iln;
+                                                               cand.callee = callee;
+                                                               cand.site   = site;
+
+                                                               if (!inline_process_candidate(&cand))
+                                                                       return false;
+#endif
+                                                       }
+                                               }
+                                       }
+                                       break;
+
+                               case ICMD_RETURN:
+                               case ICMD_IRETURN:
+                               case ICMD_ARETURN:
+                               case ICMD_LRETURN:
+                               case ICMD_FRETURN:
+                               case ICMD_DRETURN:
+                                       /* extra ICMD_MOVE may be necessary */
+                                       iln->cumul_instructioncount++;
+                                       break;
+                       }
+               }
+
+               /* end of basic block */
+       }
+
+       return true;
+}
+
+
+static void inline_cumulate_counters_recursive(inline_node *iln)
+{
+       inline_node *child;
+
+       child = iln->children;
+       if (child) {
+               do {
+                       inline_cumulate_counters_recursive(child);
+                       inline_cumulate_counters(iln, child);
+                       child = child->next;
+               } while (child != iln->children);
+       }
+}
+
+
+/* inline_make_inlining_plan ***************************************************
+
+   Make an inlining plan for the given root node
+
+   IN:
+       iln..............the root node
+
+   OUT:
+       *iln.............the inlining plan
+
+   RETURN VALUE:
+       true........everything ok
+          false.......an error has occurred, don't use the plan
+
+*******************************************************************************/
+
+#if defined(INLINE_KNAPSACK)
+static bool inline_make_inlining_plan(inline_node *iln)
+{
+       inline_candidate *cand;
+#if defined(INLINE_COST_BUDGET)
+       s4 budget = INLINE_COST_BUDGET;
+#   define BUDGETMEMBER cost
+#endif
+#if defined(INLINE_WEIGHT_BUDGET)
+       double budget = INLINE_WEIGHT_BUDGET;
+#   define BUDGETMEMBER weight
+#endif
+
+       inline_analyse_code(iln);
+
+       DOLOG( printf("candidates in "); method_println(iln->m);
+                  inline_candidates_println(iln->ctx); );
+
+       while ((cand = inline_pick_best_candidate(iln->ctx)) != NULL)
+       {
+               if (cand->BUDGETMEMBER <= budget) {
+                       DOLOG( printf("    picking: "); inline_candidate_println(cand); );
+
+                       if (!inline_process_candidate(cand))
+                               return false;
+
+#if !defined(INLINE_ADD_NEGATIVE_TO_BUDGET)
+                       if (cand->BUDGETMEMBER > 0)
+#endif
+                               budget -= cand->BUDGETMEMBER;
+               }
+       }
+
+       inline_cumulate_counters_recursive(iln);
+
+       return true;
+}
+#endif /* defined(INLINE_KNAPSACK) */
+
+
+#if defined(INLINE_DEPTH_FIRST)
+static bool inline_make_inlining_plan(inline_node *iln)
+{
+       return inline_analyse_code(iln);
+}
+#endif /* defined(INLINE_DEPTH_FIRST) */
+
+
+#if defined(INLINE_BREADTH_FIRST)
+static bool inline_make_inlining_plan(inline_node *iln)
+{
+       inline_candidate *cand;
+
+       inline_analyse_code(iln);
+
+       DOLOG( printf("candidates in "); method_println(iln->m);
+                  inline_candidates_println(iln->ctx); );
+
+       while (!iln->ctx->stopped
+                  && (cand = inline_pick_best_candidate(iln->ctx)) != NULL)
+       {
+               DOLOG( printf("    picking: "); inline_candidate_println(cand); );
+
+               if (!inline_process_candidate(cand))
+                       return false;
+       }
+
+       return true;
+}
+#endif /* defined(INLINE_BREADTH_FIRST) */
+
+
+/* statistics *****************************************************************/
+
+#if defined(INLINE_STATISTICS)
+static void inline_gather_statistics_recursive(inline_node *iln)
+{
+       inline_node *child;
+
+       inline_stat_inlined_nodes++;
+
+       if (iln->depth > inline_stat_max_depth)
+               inline_stat_max_depth++;
+
+       child = iln->children;
+       if (child) {
+               do {
+                       inline_gather_statistics_recursive(child);
+                       child = child->next;
+               } while (child != iln->children);
+       }
+}
+#endif /* defined(INLINE_STATISTICS) */
+
+
+#if defined(INLINE_STATISTICS)
+static void inline_gather_statistics(inline_node *iln)
+{
+       inline_stat_roots_transformed++;
+
+       inline_gather_statistics_recursive(iln);
+}
+#endif /* defined(INLINE_STATISTICS) */
+
+
+/* post processing ************************************************************/
+
+#define POSTPROCESS_SRC(varindex)  live[varindex]--
+#define POSTPROCESS_DST(varindex)  live[varindex]++
+
+#define POSTPROCESS_SRCOP(s)  POSTPROCESS_SRC(iptr->s.varindex)
+#define POSTPROCESS_DSTOP(d)  POSTPROCESS_DST(iptr->d.varindex)
+
+#define MARKSAVED(varindex)  jd->var[varindex].flags |= SAVEDVAR
+
+#define MARK_ALL_SAVED                                               \
+    do {                                                             \
+        for (i=0; i<jd->vartop; ++i)                                 \
+            if (live[i])                                             \
+                MARKSAVED(i);                                        \
+    } while (0)
+
+static void inline_post_process(jitdata *jd)
+{
+       codeinfo   *code;
+       basicblock *bptr;
+       instruction *iptr;
+       instruction *iend;
+       s4 i;
+       icmdtable_entry_t *icmdt;
+       s4 *live;
+       methoddesc *md;
+       builtintable_entry *bte;
+
+       /* Get required compiler data. */
+
+       code = jd->code;
+
+       /* reset the SAVEDVAR flag of all variables */
+
+       for (i=0; i<jd->vartop; ++i)
+               jd->var[i].flags &= ~SAVEDVAR;
+
+       /* allocate the life counters */
+
+       live = (s4*) DumpMemory::allocate(sizeof(s4) * jd->vartop);
+       MZERO(live, s4, jd->vartop);
+
+       /* iterate over all basic blocks */
+
+       for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
+               if (bptr->flags < BBREACHED)
+                       continue;
+
+               /* make invars live */
+
+               for (i=0; i<bptr->indepth; ++i)
+                       POSTPROCESS_DST(bptr->invars[i]);
+
+               iptr = bptr->iinstr;
+               iend = iptr + bptr->icount;
+
+               for (; iptr < iend; ++iptr) {
+
+                       icmdt = &(icmd_table[iptr->opc]);
+
+                       switch (icmdt->dataflow) {
+                               case DF_3_TO_0:
+                                       POSTPROCESS_SRCOP(sx.s23.s3);
+                               case DF_2_TO_0:
+                                       POSTPROCESS_SRCOP(sx.s23.s2);
+                               case DF_1_TO_0:
+                                       POSTPROCESS_SRCOP(s1);
+                               case DF_0_TO_0:
+                                       if (icmdt->flags & ICMDTABLE_CALLS) {
+                                               code_unflag_leafmethod(code);
+                                               MARK_ALL_SAVED;
+                                       }
+                                       break;
+
+                               case DF_2_TO_1:
+                                       POSTPROCESS_SRCOP(sx.s23.s2);
+                               case DF_1_TO_1:
+                               case DF_MOVE:
+                                       POSTPROCESS_SRCOP(s1);
+                               case DF_0_TO_1:
+                                       if (icmdt->flags & ICMDTABLE_CALLS) {
+                                               code_unflag_leafmethod(code);
+                                               MARK_ALL_SAVED;
+                                       }
+                               case DF_COPY:
+                                       POSTPROCESS_DSTOP(dst);
+                                       break;
+
+                               case DF_N_TO_1:
+                                       for (i=0; i<iptr->s1.argcount; ++i) {
+                                               POSTPROCESS_SRC(iptr->sx.s23.s2.args[i]);
+                                       }
+                                       if (icmdt->flags & ICMDTABLE_CALLS) {
+                                               code_unflag_leafmethod(code);
+                                               MARK_ALL_SAVED;
+                                       }
+                                       POSTPROCESS_DSTOP(dst);
+                                       break;
+
+                               case DF_INVOKE:
+                                       INSTRUCTION_GET_METHODDESC(iptr, md);
+               post_process_call:
+                                       code_unflag_leafmethod(code);
+                                       for (i=0; i<md->paramcount; ++i) {
+                                               POSTPROCESS_SRC(iptr->sx.s23.s2.args[i]);
+                                       }
+                                       for (; i<iptr->s1.argcount; ++i) {
+                                               MARKSAVED(iptr->sx.s23.s2.args[i]);
+                                       }
+                                       if (md->returntype.type != TYPE_VOID)
+                                               POSTPROCESS_DSTOP(dst);
+                                       break;
+
+                               case DF_BUILTIN:
+                                       bte = iptr->sx.s23.s3.bte;
+                                       md = bte->md;
+                                       goto post_process_call;
+
+                               default:
+                                       assert(0);
+                       }
+
+               } /* end instruction loop */
+
+               /* consume outvars */
+
+               for (i=0; i<bptr->outdepth; ++i)
+                       POSTPROCESS_SRC(bptr->outvars[i]);
+
+#if !defined(NDEBUG)
+               for (i=jd->localcount; i < jd->vartop; ++i)
+                       assert(live[i] == 0);
+#endif
+
+       } /* end basic block loop */
+}
+
+
+/* inline_create_root_node *****************************************************
+
+   Create the root node of the inlining tree.
+
+   IN:
+          jd...............the current jitdata of the root method
+
+   RETURN VALUE:
+       the root node of the inlining tree
+
+*******************************************************************************/
+
+static inline_node * inline_create_root_node(jitdata *jd)
+{
+       inline_node *iln;
+
+       iln = (inline_node*) DumpMemory::allocate(sizeof(inline_node));
+       MZERO(iln, inline_node, 1);
+
+       iln->m = jd->m;
+       iln->jd = jd;
+       iln->regdata = jd->rd;
+
+       iln->blockbefore = true;
+       iln->blockafter = true;
+
+       iln->cumul_instructioncount = 0;
+       iln->cumul_basicblockcount = 1 /* dummy end block */;
+
+       /* create inlining context */
+
+       iln->ctx = (inline_context*) DumpMemory::allocate(sizeof(inline_context));
+       MZERO(iln->ctx, inline_context, 1);
+       iln->ctx->master = iln;
+       iln->ctx->next_debugnr = 1; /* XXX debug */
+
+       return iln;
+}
+
+
+/******************************************************************************/
+/* MAIN DRIVER FUNCTION                                                       */
+/******************************************************************************/
+
+bool inline_inline(jitdata *jd)
+{
+       inline_node *iln;
+
+       DOLOG( printf("==== INLINE ==================================================================\n");
+                  show_method(jd, SHOW_STACK); );
+
+#if defined(INLINE_STATISTICS)
+       inline_stat_roots++;
+#endif
+
+       iln = inline_create_root_node(jd);
+
+       if (inline_make_inlining_plan(iln)) {
+
+               /* add blocks to the root node */
+
+               iln->cumul_basicblockcount += iln->cumul_basicblockcount_root;
+               iln->cumul_blockmapcount   += iln->cumul_basicblockcount_root;
+
+               DOLOG( printf("==== INLINE TRANSFORM ========================================================\n"); );
+
+               if (iln->children)
+                       inline_transform(iln, jd);
+
+#if defined(INLINE_STATISTICS)
+               inline_gather_statistics(iln);
+#endif
+       }
+
+       DOLOG( printf("-------- DONE -----------------------------------------------------------\n");
+                  fflush(stdout); );
+
+       return true;
+}
+
+#if defined(__cplusplus)
+}
+#endif
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
diff --git a/src/vm/jit/inline/inline.h b/src/vm/jit/inline/inline.h
deleted file mode 100644 (file)
index 629f649..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/* src/vm/jit/inline/inline.h - code inliner
-
-   Copyright (C) 1996-2005, 2006, 2007, 2008
-   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
-   This file is part of CACAO.
-
-   This program 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 2, or (at
-   your option) any later version.
-
-   This program 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 this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.
-
-*/
-
-
-#ifndef _INLINE_H
-#define _INLINE_H
-
-#include "config.h"
-
-#include <stdbool.h>
-
-#include "vm/jit/jit.hpp"
-
-
-/* function prototypes ********************************************************/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-bool inline_inline(jitdata *jd);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _INLINE_H */
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
diff --git a/src/vm/jit/inline/inline.hpp b/src/vm/jit/inline/inline.hpp
new file mode 100644 (file)
index 0000000..629f649
--- /dev/null
@@ -0,0 +1,62 @@
+/* src/vm/jit/inline/inline.h - code inliner
+
+   Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+   This file is part of CACAO.
+
+   This program 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 2, or (at
+   your option) any later version.
+
+   This program 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 this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+*/
+
+
+#ifndef _INLINE_H
+#define _INLINE_H
+
+#include "config.h"
+
+#include <stdbool.h>
+
+#include "vm/jit/jit.hpp"
+
+
+/* function prototypes ********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool inline_inline(jitdata *jd);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _INLINE_H */
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index ddb68c7303ef0dc485fc3c82205b5368bdddfa23..4fbca4a70d15856dfe575b7af0675374fcef8cea 100644 (file)
@@ -58,7 +58,7 @@
 #include "vm/jit/codegen-common.hpp"
 #include "vm/jit/dseg.h"
 #include "vm/jit/jit.hpp"
-#include "vm/jit/parse.h"
+#include "vm/jit/parse.hpp"
 #include "vm/jit/patcher.h"
 #include "vm/jit/stack.h"
 #include "vm/jit/stacktrace.hpp"
index 09c9e862eb6798d7cdffc17aa234b89e7b861da2..c218f05e8d14685568a3e157b3849a05e136fd28 100644 (file)
@@ -58,7 +58,7 @@
 #include "vm/jit/disass.h"
 #include "vm/jit/dseg.h"
 #include "vm/jit/jit.hpp"
-#include "vm/jit/parse.h"
+#include "vm/jit/parse.hpp"
 #include "vm/jit/reg.h"
 
 #include "vm/jit/show.hpp"
@@ -84,7 +84,7 @@
 #endif
 
 #if defined(ENABLE_INLINING)
-# include "vm/jit/inline/inline.h"
+# include "vm/jit/inline/inline.hpp"
 #endif
 
 #include "vm/jit/ir/bytecode.h"
index 4a235519fb49e01bb1acb3b44ef847bee6ef98b0..838e330287b31000cf0ebb36a0105bf454ca5096 100644 (file)
@@ -52,7 +52,7 @@ typedef struct exception_entry exception_entry;
 #include "vm/jit/stacktrace.hpp"
 
 #if defined(ENABLE_INLINING)
-# include "vm/jit/inline/inline.h"
+# include "vm/jit/inline/inline.hpp"
 #endif
 
 #include "vm/jit/ir/bytecode.h"
index 6a0254b8c89e7f218e69e8ae4948f85521475f09..a6ad45abeef0244cfe0ed521ba3f4dd8acdce5fb 100644 (file)
@@ -57,7 +57,7 @@
 #include "vm/jit/emit-common.hpp"
 #include "vm/jit/jit.hpp"
 #include "vm/jit/abi.h"
-#include "vm/jit/parse.h"
+#include "vm/jit/parse.hpp"
 #include "vm/jit/reg.h"
 #include "vm/jit/replace.hpp"
 #include "vm/jit/stacktrace.hpp"
index ee88ea3b528dc83eab73cb310fa788b17a3c773c..e81137a706df83df1b9f9581ae93a76d7d8efd1a 100644 (file)
@@ -1403,13 +1403,13 @@ bool codegen_emit(jitdata *jd)
                        M_CMPLT(s1, s2, REG_ITMP3);
                        M_CMPLT(s2, s1, REG_ITMP1);
                        M_ISUB(REG_ITMP1, REG_ITMP3, d);
-                       M_BNEZ(d, 4);
-                       M_NOP;
+                       emit_label_bnez(cd, BRANCH_LABEL_1, d);
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
                        M_CMPULT(s1, s2, REG_ITMP3);
                        M_CMPULT(s2, s1, REG_ITMP1);
                        M_ISUB(REG_ITMP1, REG_ITMP3, d);
+                       emit_label(cd, BRANCH_LABEL_1);
 #endif
                        emit_store_dst(jd, iptr, d);
                        break;
@@ -2430,12 +2430,12 @@ bool codegen_emit(jitdata *jd)
                                ICONST(REG_ITMP2, iptr->sx.val.l >> 32);
                                M_CMPLT(s1, REG_ITMP2, REG_ITMP3);
                                emit_bnez(cd, iptr->dst.block, REG_ITMP3);
+                               emit_label_bne(cd, BRANCH_LABEL_1, s1, REG_ITMP2);
                                s2 = emit_load_s1_low(jd, iptr, REG_ITMP3);
-                               M_BNE(s1, REG_ITMP2, 5); /* XXX */
-                               M_NOP;
                                ICONST(REG_ITMP2, iptr->sx.val.l & 0xffffffff);
                                M_CMPULT(s2, REG_ITMP2, REG_ITMP3);
                                emit_bnez(cd, iptr->dst.block, REG_ITMP3);
+                               emit_label(cd, BRANCH_LABEL_1);
                        }
 #endif
                        break;
@@ -2460,22 +2460,22 @@ bool codegen_emit(jitdata *jd)
 #else
                        if (iptr->sx.val.l == 0) {
                                s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
-                               M_BGTZ(GET_HIGH_REG(s1), 5); /* XXX */
-                               M_NOP;
+                               emit_label_bgtz(cd, BRANCH_LABEL_1, GET_HIGH_REG(s1));
                                emit_bltz(cd, iptr->dst.block, GET_HIGH_REG(s1));
-                               emit_beqz(cd, iptr->dst.block, GET_LOW_REG(s1));
+                               emit_beqz(cd, iptr->dst.block, GET_LOW_REG(s1));        
+                               emit_label(cd, BRANCH_LABEL_1);
                        }
                        else {
                                s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                                ICONST(REG_ITMP2, iptr->sx.val.l >> 32);
                                M_CMPLT(s1, REG_ITMP2, REG_ITMP3);
                                emit_bnez(cd, iptr->dst.block, REG_ITMP3);
+                               emit_label_bne(cd, BRANCH_LABEL_1, s1, REG_ITMP2);
                                s2 = emit_load_s1_low(jd, iptr, REG_ITMP3);
-                               M_BNE(s1, REG_ITMP2, 5); /* XXX */
-                               M_NOP;
                                ICONST(REG_ITMP2, iptr->sx.val.l & 0xffffffff);
                                M_CMPUGT(s2, REG_ITMP2, REG_ITMP3);
                                emit_beqz(cd, iptr->dst.block, REG_ITMP3);
+                               emit_label(cd, BRANCH_LABEL_1);
                        }
 #endif
                        break;
@@ -2530,21 +2530,21 @@ bool codegen_emit(jitdata *jd)
                        if (iptr->sx.val.l == 0) {
                                s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
                                emit_bgtz(cd, iptr->dst.block, GET_HIGH_REG(s1));
-                               M_BLTZ(GET_HIGH_REG(s1), 3); /* XXX */
-                               M_NOP;
+                               emit_label_bltz(cd, BRANCH_LABEL_1, GET_HIGH_REG(s1));
                                emit_bnez(cd, iptr->dst.block, GET_LOW_REG(s1));
+                               emit_label(cd, BRANCH_LABEL_1);
                        }
                        else {
                                s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                                ICONST(REG_ITMP2, iptr->sx.val.l >> 32);
                                M_CMPGT(s1, REG_ITMP2, REG_ITMP3);
                                emit_bnez(cd, iptr->dst.block, REG_ITMP3);
+                               emit_label_bne(cd, BRANCH_LABEL_1, s1, REG_ITMP2);
                                s2 = emit_load_s1_low(jd, iptr, REG_ITMP3);
-                               M_BNE(s1, REG_ITMP2, 5); /* XXX */
-                               M_NOP;
                                ICONST(REG_ITMP2, iptr->sx.val.l & 0xffffffff);
                                M_CMPUGT(s2, REG_ITMP2, REG_ITMP3);
                                emit_bnez(cd, iptr->dst.block, REG_ITMP3);
+                               emit_label(cd, BRANCH_LABEL_1);
                        }
 #endif
                        break;
@@ -2576,12 +2576,12 @@ bool codegen_emit(jitdata *jd)
                                ICONST(REG_ITMP2, iptr->sx.val.l >> 32);
                                M_CMPGT(s1, REG_ITMP2, REG_ITMP3);
                                emit_bnez(cd, iptr->dst.block, REG_ITMP3);
+                               emit_label_bne(cd, BRANCH_LABEL_1, s1, REG_ITMP2);
                                s2 = emit_load_s1_low(jd, iptr, REG_ITMP3);
-                               M_BNE(s1, REG_ITMP2, 5); /* XXX */
-                               M_NOP;
                                ICONST(REG_ITMP2, iptr->sx.val.l & 0xffffffff);
                                M_CMPULT(s2, REG_ITMP2, REG_ITMP3);
                                emit_beqz(cd, iptr->dst.block, REG_ITMP3);
+                               emit_label(cd, BRANCH_LABEL_1);
                        }
 #endif
                        break;
@@ -2603,11 +2603,11 @@ bool codegen_emit(jitdata *jd)
 
                        s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
-                       M_BNE(s1, s2, 3); /* XXX TWISTI: uff, that is a problem */
-                       M_NOP;
+                       emit_label_bne(cd, BRANCH_LABEL_1, s1, s2);
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
                        emit_beq(cd, iptr->dst.block, s1, s2);
+                       emit_label(cd, BRANCH_LABEL_1);
                        break;
 #endif
 
@@ -2654,13 +2654,12 @@ bool codegen_emit(jitdata *jd)
                        M_CMPLT(s1, s2, REG_ITMP3);
                        emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                        M_CMPGT(s1, s2, REG_ITMP3);
-                       /* load low-bits before the branch, so we know the distance */
+                       emit_label_bnez(cd, BRANCH_LABEL_1, REG_ITMP3);
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
-                       M_BNEZ(REG_ITMP3, 4); /* XXX */
-                       M_NOP;
                        M_CMPULT(s1, s2, REG_ITMP3);
                        emit_bnez(cd, iptr->dst.block, REG_ITMP3);
+                       emit_label(cd, BRANCH_LABEL_1);
                        break;
 #endif
 
@@ -2683,13 +2682,12 @@ bool codegen_emit(jitdata *jd)
                        M_CMPGT(s1, s2, REG_ITMP3);
                        emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                        M_CMPLT(s1, s2, REG_ITMP3);
-                       /* load low-bits before the branch, so we know the distance */
+                       emit_label_bnez(cd, BRANCH_LABEL_1, REG_ITMP3);
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
-                       M_BNEZ(REG_ITMP3, 4); /* XXX */
-                       M_NOP;
                        M_CMPUGT(s1, s2, REG_ITMP3);
                        emit_bnez(cd, iptr->dst.block, REG_ITMP3);
+                       emit_label(cd, BRANCH_LABEL_1);
                        break;
 #endif
 
@@ -2712,13 +2710,12 @@ bool codegen_emit(jitdata *jd)
                        M_CMPLT(s1, s2, REG_ITMP3);
                        emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                        M_CMPGT(s1, s2, REG_ITMP3);
-                       /* load low-bits before the branch, so we know the distance */
+                       emit_label_bnez(cd, BRANCH_LABEL_1, REG_ITMP3);
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
-                       M_BNEZ(REG_ITMP3, 4); /* XXX */
-                       M_NOP;
                        M_CMPUGT(s1, s2, REG_ITMP3);
                        emit_beqz(cd, iptr->dst.block, REG_ITMP3);
+                       emit_label(cd, BRANCH_LABEL_1);
                        break;
 #endif
 
@@ -2741,13 +2738,12 @@ bool codegen_emit(jitdata *jd)
                        M_CMPGT(s1, s2, REG_ITMP3);
                        emit_bnez(cd, iptr->dst.block, REG_ITMP3);
                        M_CMPLT(s1, s2, REG_ITMP3);
-                       /* load low-bits before the branch, so we know the distance */
+                       emit_label_bnez(cd, BRANCH_LABEL_1, REG_ITMP3);
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
-                       M_BNEZ(REG_ITMP3, 4); /* XXX */
-                       M_NOP;
                        M_CMPULT(s1, s2, REG_ITMP3);
                        emit_beqz(cd, iptr->dst.block, REG_ITMP3);
+                       emit_label(cd, BRANCH_LABEL_1);
                        break;
 #endif
 
diff --git a/src/vm/jit/parse.c b/src/vm/jit/parse.c
deleted file mode 100644 (file)
index 7b1c1ac..0000000
+++ /dev/null
@@ -1,1922 +0,0 @@
-/* src/vm/jit/parse.c - parser for JavaVM to intermediate code translation
-
-   Copyright (C) 1996-2005, 2006, 2007, 2008
-   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
-   This file is part of CACAO.
-
-   This program 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 2, or (at
-   your option) any later version.
-
-   This program 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 this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-#include <string.h>
-
-#include "vm/types.h"
-
-#include "mm/memory.h"
-
-#include "native/native.hpp"
-
-#include "threads/lock.hpp"
-
-#include "toolbox/logging.h"
-
-#include "vm/jit/builtin.hpp"
-#include "vm/exceptions.hpp"
-#include "vm/global.h"
-#include "vm/linker.h"
-#include "vm/loader.hpp"
-#include "vm/options.h"
-#include "vm/resolve.hpp"
-
-#if defined(ENABLE_STATISTICS)
-# include "vm/statistics.h"
-#endif
-
-#include "vm/string.hpp"
-#include "vm/suck.hpp"
-
-#include "vm/jit/asmpart.h"
-#include "vm/jit/jit.hpp"
-#include "vm/jit/parse.h"
-#include "vm/jit/loop/loop.h"
-
-#include "vm/jit/ir/bytecode.h"
-
-
-#define INSTRUCTIONS_INCREMENT  5  /* number of additional instructions to    */
-                                   /* allocate if space runs out              */
-
-
-/* local macros ***************************************************************/
-
-#define BYTECODEINDEX_TO_BASICBLOCK(dst) \
-    do { \
-        (dst).block = \
-            parse_bytecodeindex_to_basicblock(jd, &pd, (dst).insindex); \
-    } while (0)
-
-
-/* parserdata_t ***************************************************************/
-
-typedef struct parsedata_t parsedata_t;
-
-struct parsedata_t {
-       u1          *bytecodestart;         /* start of bytecode instructions     */
-       u1          *basicblockstart;       /* start of bytecode basic-blocks     */
-
-       s4          *bytecodemap;           /* bytecode to IR mapping             */
-       
-       instruction *instructions;          /* instruction array                  */
-       s4           instructionslength;    /* length of the instruction array    */
-
-       s4          *instructionmap;        /* IR to basic-block mapping          */
-};
-
-
-/* parse_setup *****************************************************************
-
-   Fills the passed parsedata_t structure.
-
-*******************************************************************************/
-
-static void parse_setup(jitdata *jd, parsedata_t *pd)
-{
-       methodinfo *m;
-
-       /* get required compiler data */
-
-       m = jd->m;
-
-       /* bytecode start array */
-
-       pd->bytecodestart = DMNEW(u1, m->jcodelength + 1);
-       MZERO(pd->bytecodestart, u1, m->jcodelength + 1);
-
-       /* bytecode basic-block start array */
-
-       pd->basicblockstart = DMNEW(u1, m->jcodelength + 1);
-       MZERO(pd->basicblockstart, u1, m->jcodelength + 1);
-
-       /* bytecode instruction index to IR instruction mapping */
-
-       pd->bytecodemap = DMNEW(s4, m->jcodelength + 1);
-       MSET(pd->bytecodemap, -1, s4, m->jcodelength + 1);
-
-       /* allocate the instruction array */
-
-       pd->instructionslength = m->jcodelength + 1;
-       pd->instructions = DMNEW(instruction, pd->instructionslength);
-
-       /* Zero the intermediate instructions array so we don't have any
-          invalid pointers in it if we cannot finish stack_analyse(). */
-
-       MZERO(pd->instructions, instruction, pd->instructionslength);
-
-       /* The instructionmap is allocated later when we know the count of
-          instructions. */
-
-       pd->instructionmap = NULL;
-}
-
-
-/* parse_realloc_instructions **************************************************
-
-   Reallocate the instructions array so there is room for at least N 
-   additional instructions.
-
-   RETURN VALUE:
-       the new value for iptr
-
-*******************************************************************************/
-
-static instruction *parse_realloc_instructions(parsedata_t *pd, s4 icount, s4 n)
-{
-       /* increase the size of the instruction array */
-
-       pd->instructionslength += (n + INSTRUCTIONS_INCREMENT);
-
-       /* reallocate the array */
-
-       pd->instructions = DMREALLOC(pd->instructions, instruction, icount,
-                                                                pd->instructionslength);
-       MZERO(pd->instructions + icount, instruction,
-                 (pd->instructionslength - icount));
-
-       /* return the iptr */
-
-       return pd->instructions + icount;
-}
-
-
-/* parse_bytecodeindex_to_basicblock *******************************************
-
-   Resolves a bytecode index to the corresponding basic block.
-
-*******************************************************************************/
-
-static basicblock *parse_bytecodeindex_to_basicblock(jitdata *jd,
-                                                                                                        parsedata_t *pd,
-                                                                                                        s4 bcindex)
-{
-       s4          irindex;
-       basicblock *bb;
-
-       irindex = pd->bytecodemap[bcindex];
-       bb      = jd->basicblocks + pd->instructionmap[irindex];
-
-       return bb;
-}
-
-
-/* parse_mark_exception_boundaries *********************************************
-
-   Mark exception handlers and the boundaries of the handled regions as
-   basic block boundaries.
-
-   IN:
-       jd...............current jitdata
-
-   RETURN VALUE:
-       true.............everything ok
-          false............an exception has been thrown
-
-*******************************************************************************/
-
-static bool parse_mark_exception_boundaries(jitdata *jd, parsedata_t *pd)
-{
-       s4                   bcindex;
-       s4                   i;
-       s4                   len;
-       raw_exception_entry *rex;
-       methodinfo          *m;
-
-       m = jd->m;
-       
-       len = m->rawexceptiontablelength;
-
-       if (len == 0)
-               return true;
-
-       rex = m->rawexceptiontable;
-
-       for (i = 0; i < len; ++i, ++rex) {
-
-               /* the start of the handled region becomes a basic block start */
-
-               bcindex = rex->startpc;
-               CHECK_BYTECODE_INDEX(bcindex);
-               MARK_BASICBLOCK(pd, bcindex);
-               
-               bcindex = rex->endpc; /* see JVM Spec 4.7.3 */
-               CHECK_BYTECODE_INDEX_EXCLUSIVE(bcindex);
-
-               /* check that the range is valid */
-
-#if defined(ENABLE_VERIFIER)
-               if (bcindex <= rex->startpc) {
-                       exceptions_throw_verifyerror(m, "Invalid exception handler range");
-                       return false;
-               }
-#endif
-               
-               /* End of handled region becomes a basic block boundary (if it
-                  is the bytecode end, we'll use the special end block that
-                  is created anyway). */
-
-               if (bcindex < m->jcodelength)
-                       MARK_BASICBLOCK(pd, bcindex);
-               else
-                       jd->branchtoend = true;
-
-               /* the start of the handler becomes a basic block start  */
-
-               bcindex = rex->handlerpc;
-               CHECK_BYTECODE_INDEX(bcindex);
-               MARK_BASICBLOCK(pd, bcindex);
-       }
-
-       /* everything ok */
-
-       return true;
-
-#if defined(ENABLE_VERIFIER)
-throw_invalid_bytecode_index:
-       exceptions_throw_verifyerror(m,
-                                                                "Illegal bytecode index in exception table");
-       return false;
-#endif
-}
-
-
-/* parse_resolve_exception_table ***********************************************
-
-   Enter the exception handlers and their ranges, resolved to basicblock *s,
-   in the jitdata.
-
-   IN:
-       jd...............current jitdata
-
-   RETURN VALUE:
-          true.............everything ok
-          false............an exception has been thrown
-
-*******************************************************************************/
-
-static bool parse_resolve_exception_table(jitdata *jd, parsedata_t *pd)
-{
-       methodinfo          *m;
-       raw_exception_entry *rex;
-       exception_entry     *ex;
-       s4                   i;
-       s4                   len;
-       classinfo           *exclass;
-
-       m = jd->m;
-
-       len = m->rawexceptiontablelength;
-
-       /* common case: no handler entries */
-
-       if (len == 0)
-               return true;
-
-       /* allocate the exception table */
-
-       jd->exceptiontablelength = len;
-       jd->exceptiontable = DMNEW(exception_entry, len + 1); /* XXX why +1? */
-
-       /* copy and resolve the entries */
-
-       ex = jd->exceptiontable;
-       rex = m->rawexceptiontable;
-
-       for (i = 0; i < len; ++i, ++rex, ++ex) {
-               /* resolve instruction indices to basic blocks */
-
-               ex->start   = parse_bytecodeindex_to_basicblock(jd, pd, rex->startpc);
-               ex->end     = parse_bytecodeindex_to_basicblock(jd, pd, rex->endpc);
-               ex->handler = parse_bytecodeindex_to_basicblock(jd, pd, rex->handlerpc);
-
-               /* lazily resolve the catchtype */
-
-               if (rex->catchtype.any != NULL) {
-                       if (!resolve_classref_or_classinfo(m,
-                                                                                          rex->catchtype,
-                                                                                          resolveLazy, true, false,
-                                                                                          &exclass))
-                               return false;
-
-                       /* if resolved, enter the result of resolution in the table */
-
-                       if (exclass != NULL)
-                               rex->catchtype.cls = exclass;
-               }
-
-               ex->catchtype = rex->catchtype;
-               ex->next = NULL;   /* set by loop analysis */
-               ex->down = ex + 1; /* link to next exception entry */
-       }
-
-       /* terminate the ->down linked list */
-
-       assert(ex != jd->exceptiontable);
-       ex[-1].down = NULL;
-
-       return true;
-}
-
-
-/*******************************************************************************
-
-       function 'parse' scans the JavaVM code and generates intermediate code
-
-       During parsing the block index table is used to store at bit pos 0
-       a flag which marks basic block starts and at position 1 to 31 the
-       intermediate instruction index. After parsing the block index table
-       is scanned, for marked positions a block is generated and the block
-       number is stored in the block index table.
-
-*******************************************************************************/
-
-/*** macro for checking the length of the bytecode ***/
-
-#if defined(ENABLE_VERIFIER)
-#define CHECK_END_OF_BYTECODE(neededlength) \
-       do { \
-               if ((neededlength) > m->jcodelength) \
-                       goto throw_unexpected_end_of_bytecode; \
-       } while (0)
-#else /* !ENABLE_VERIFIER */
-#define CHECK_END_OF_BYTECODE(neededlength)
-#endif /* ENABLE_VERIFIER */
-
-bool parse(jitdata *jd)
-{
-       methodinfo  *m;                     /* method being parsed                */
-       codeinfo    *code;
-       parsedata_t  pd;
-       instruction *iptr;                  /* current ptr into instruction array */
-
-       s4           bcindex;               /* bytecode instruction index         */
-       s4           nextbc;                /* start of next bytecode instruction */
-       s4           opcode;                /* bytecode instruction opcode        */
-
-       s4           irindex;               /* IR instruction index               */
-       s4           ircount;               /* IR instruction count               */
-
-       s4           bbcount;               /* basic block count                  */
-
-       int  s_count = 0;             /* stack element counter                    */
-       bool blockend;                /* true if basic block end has been reached */
-       bool iswide;                  /* true if last instruction was a wide      */
-
-       constant_classref  *cr;
-       constant_classref  *compr;
-       classinfo          *c;
-       builtintable_entry *bte;
-       constant_FMIref    *fmi;
-       methoddesc         *md;
-       unresolved_method  *um;
-       unresolved_field   *uf;
-
-       resolve_result_t    result;
-       u2                  lineindex = 0;
-       u2                  currentline = 0;
-       u2                  linepcchange = 0;
-       u4                  flags;
-       basicblock         *bptr;
-
-       int                *local_map; /* local pointer to renaming map           */
-                                      /* is assigned to rd->local_map at the end */
-       branch_target_t *table;
-       lookup_target_t *lookup;
-       s4               i;
-       s4               j;
-
-       /* get required compiler data */
-
-       m    = jd->m;
-       code = jd->code;
-
-       /* allocate buffers for local variable renaming */
-
-       local_map = DMNEW(int, m->maxlocals * 5);
-
-       for (i = 0; i < m->maxlocals; i++) {
-               local_map[i * 5 + 0] = 0;
-               local_map[i * 5 + 1] = 0;
-               local_map[i * 5 + 2] = 0;
-               local_map[i * 5 + 3] = 0;
-               local_map[i * 5 + 4] = 0;
-       }
-
-       /* initialize the parse data structures */
-  
-       parse_setup(jd, &pd);
-  
-       /* initialize local variables */
-  
-       iptr     = pd.instructions;
-       ircount  = 0;
-       bbcount  = 0;
-       blockend = false;
-       iswide   = false;
-
-       /* mark basic block boundaries for exception table */
-
-       if (!parse_mark_exception_boundaries(jd, &pd))
-               return false;
-
-       /* initialize stack element counter */
-
-       s_count = 1 + m->rawexceptiontablelength;
-
-       /* setup line number info */
-
-       currentline = 0;
-       linepcchange = 0;
-
-       if (m->linenumbercount == 0) {
-               lineindex = 0;
-       }
-       else {
-               linepcchange = m->linenumbers[0].start_pc;
-       }
-
-       /*** LOOP OVER ALL BYTECODE INSTRUCTIONS **********************************/
-
-       for (bcindex = 0; bcindex < m->jcodelength; bcindex = nextbc) {
-
-               /* mark this position as a valid bytecode instruction start */
-
-               pd.bytecodestart[bcindex] = 1;
-
-               /* change the current line number, if necessary */
-
-               /* XXX rewrite this using pointer arithmetic */
-
-               if (linepcchange == bcindex) {
-                       if (m->linenumbercount > lineindex) {
-next_linenumber:
-                               currentline = m->linenumbers[lineindex].line_number;
-                               lineindex++;
-                               if (lineindex < m->linenumbercount) {
-                                       linepcchange = m->linenumbers[lineindex].start_pc;
-                                       if (linepcchange == bcindex)
-                                               goto next_linenumber;
-                               }
-                       }
-               }
-
-fetch_opcode:
-               /* fetch next opcode  */        
-
-               opcode = SUCK_BE_U1(m->jcode + bcindex);
-
-               /* If the previous instruction was a block-end instruction,
-                  mark the current bytecode instruction as basic-block
-                  starting instruction. */
-
-               /* NOTE: Some compilers put a BC_nop after a blockend
-                  instruction. */
-
-               if (blockend && (opcode != BC_nop)) {
-                       MARK_BASICBLOCK(&pd, bcindex);
-                       blockend = false;
-               }
-
-               /* If the current bytecode instruction was marked as
-                  basic-block starting instruction before (e.g. blockend,
-                  forward-branch target), mark the current IR instruction
-                  too. */
-
-               if (pd.basicblockstart[bcindex] != 0) {
-                       /* We need a NOP as last instruction in each basic block
-                          for basic block reordering (may be replaced with a GOTO
-                          later). */
-
-                       INSTRUCTIONS_CHECK(1);
-                       OP(ICMD_NOP);
-               }
-
-               /* store intermediate instruction count (bit 0 mark block starts) */
-
-               pd.bytecodemap[bcindex] = ircount;
-
-               /* compute next instruction start */
-
-               nextbc = bcindex + bytecode[opcode].length;
-
-               CHECK_END_OF_BYTECODE(nextbc);
-
-               /* add stack elements produced by this instruction */
-
-               s_count += bytecode[opcode].slots;
-
-               /* We check here for the space of 1 instruction in the
-                  instruction array.  If an opcode is converted to more than
-                  1 instruction, this is checked in the corresponding
-                  case. */
-
-               INSTRUCTIONS_CHECK(1);
-
-               /* translate this bytecode instruction */
-               switch (opcode) {
-
-               case BC_nop:
-                       break;
-
-               /* pushing constants onto the stack ***********************************/
-
-               case BC_bipush:
-                       OP_LOADCONST_I(SUCK_BE_S1(m->jcode + bcindex + 1));
-                       break;
-
-               case BC_sipush:
-                       OP_LOADCONST_I(SUCK_BE_S2(m->jcode + bcindex + 1));
-                       break;
-
-               case BC_ldc1:
-                       i = SUCK_BE_U1(m->jcode + bcindex + 1);
-                       goto pushconstantitem;
-
-               case BC_ldc2:
-               case BC_ldc2w:
-                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
-
-               pushconstantitem:
-
-#if defined(ENABLE_VERIFIER)
-                       if (i >= m->clazz->cpcount) {
-                               exceptions_throw_verifyerror(m,
-                                       "Attempt to access constant outside range");
-                               return false;
-                       }
-#endif
-
-                       switch (m->clazz->cptags[i]) {
-                       case CONSTANT_Integer:
-                               OP_LOADCONST_I(((constant_integer *) (m->clazz->cpinfos[i]))->value);
-                               break;
-                       case CONSTANT_Long:
-                               OP_LOADCONST_L(((constant_long *) (m->clazz->cpinfos[i]))->value);
-                               break;
-                       case CONSTANT_Float:
-                               OP_LOADCONST_F(((constant_float *) (m->clazz->cpinfos[i]))->value);
-                               break;
-                       case CONSTANT_Double:
-                               OP_LOADCONST_D(((constant_double *) (m->clazz->cpinfos[i]))->value);
-                               break;
-                       case CONSTANT_String:
-                               OP_LOADCONST_STRING(literalstring_new((utf *) (m->clazz->cpinfos[i])));
-                               break;
-                       case CONSTANT_Class:
-                               cr = (constant_classref *) (m->clazz->cpinfos[i]);
-
-                               if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
-                                       return false;
-
-                               /* if not resolved, c == NULL */
-
-                               OP_LOADCONST_CLASSINFO_OR_CLASSREF_CHECK(c, cr);
-
-                               break;
-
-#if defined(ENABLE_VERIFIER)
-                       default:
-                               exceptions_throw_verifyerror(m,
-                                               "Invalid constant type to push");
-                               return false;
-#endif
-                       }
-                       break;
-
-               case BC_aconst_null:
-                       OP_LOADCONST_NULL();
-                       break;
-
-               case BC_iconst_m1:
-               case BC_iconst_0:
-               case BC_iconst_1:
-               case BC_iconst_2:
-               case BC_iconst_3:
-               case BC_iconst_4:
-               case BC_iconst_5:
-                       OP_LOADCONST_I(opcode - BC_iconst_0);
-                       break;
-
-               case BC_lconst_0:
-               case BC_lconst_1:
-                       OP_LOADCONST_L(opcode - BC_lconst_0);
-                       break;
-
-               case BC_fconst_0:
-               case BC_fconst_1:
-               case BC_fconst_2:
-                       OP_LOADCONST_F(opcode - BC_fconst_0);
-                       break;
-
-               case BC_dconst_0:
-               case BC_dconst_1:
-                       OP_LOADCONST_D(opcode - BC_dconst_0);
-                       break;
-
-               /* stack operations ***************************************************/
-
-               /* We need space for additional instruction so we can
-                  translate these instructions to sequences of ICMD_COPY and
-                  ICMD_MOVE instructions. */
-
-               case BC_dup_x1:
-                       INSTRUCTIONS_CHECK(4);
-                       OP(opcode);
-                       OP(ICMD_NOP);
-                       OP(ICMD_NOP);
-                       OP(ICMD_NOP);
-                       break;
-
-               case BC_dup_x2:
-                       INSTRUCTIONS_CHECK(6);
-                       OP(opcode);
-                       OP(ICMD_NOP);
-                       OP(ICMD_NOP);
-                       OP(ICMD_NOP);
-                       OP(ICMD_NOP);
-                       OP(ICMD_NOP);
-                       break;
-
-               case BC_dup2:
-                       INSTRUCTIONS_CHECK(2);
-                       OP(opcode);
-                       OP(ICMD_NOP);
-                       break;
-
-               case BC_dup2_x1:
-                       INSTRUCTIONS_CHECK(7);
-                       OP(opcode);
-                       OP(ICMD_NOP);
-                       OP(ICMD_NOP);
-                       OP(ICMD_NOP);
-                       OP(ICMD_NOP);
-                       OP(ICMD_NOP);
-                       OP(ICMD_NOP);
-                       break;
-
-               case BC_dup2_x2:
-                       INSTRUCTIONS_CHECK(9);
-                       OP(opcode);
-                       OP(ICMD_NOP);
-                       OP(ICMD_NOP);
-                       OP(ICMD_NOP);
-                       OP(ICMD_NOP);
-                       OP(ICMD_NOP);
-                       OP(ICMD_NOP);
-                       OP(ICMD_NOP);
-                       OP(ICMD_NOP);
-                       break;
-
-               case BC_swap:
-                       INSTRUCTIONS_CHECK(3);
-                       OP(opcode);
-                       OP(ICMD_NOP);
-                       OP(ICMD_NOP);
-                       break;
-
-               /* local variable access instructions *********************************/
-
-               case BC_iload:
-               case BC_fload:
-               case BC_aload:
-                       if (iswide == false) {
-                               i = SUCK_BE_U1(m->jcode + bcindex + 1);
-                       }
-                       else {
-                               i = SUCK_BE_U2(m->jcode + bcindex + 1);
-                               nextbc = bcindex + 3;
-                               iswide = false;
-                       }
-                       OP_LOAD_ONEWORD(opcode, i, opcode - BC_iload);
-                       break;
-
-               case BC_lload:
-               case BC_dload:
-                       if (iswide == false) {
-                               i = SUCK_BE_U1(m->jcode + bcindex + 1);
-                       }
-                       else {
-                               i = SUCK_BE_U2(m->jcode + bcindex + 1);
-                               nextbc = bcindex + 3;
-                               iswide = false;
-                       }
-                       OP_LOAD_TWOWORD(opcode, i, opcode - BC_iload);
-                       break;
-
-               case BC_iload_0:
-               case BC_iload_1:
-               case BC_iload_2:
-               case BC_iload_3:
-                       OP_LOAD_ONEWORD(ICMD_ILOAD, opcode - BC_iload_0, TYPE_INT);
-                       break;
-
-               case BC_lload_0:
-               case BC_lload_1:
-               case BC_lload_2:
-               case BC_lload_3:
-                       OP_LOAD_TWOWORD(ICMD_LLOAD, opcode - BC_lload_0, TYPE_LNG);
-                       break;
-
-               case BC_fload_0:
-               case BC_fload_1:
-               case BC_fload_2:
-               case BC_fload_3:
-                       OP_LOAD_ONEWORD(ICMD_FLOAD, opcode - BC_fload_0, TYPE_FLT);
-                       break;
-
-               case BC_dload_0:
-               case BC_dload_1:
-               case BC_dload_2:
-               case BC_dload_3:
-                       OP_LOAD_TWOWORD(ICMD_DLOAD, opcode - BC_dload_0, TYPE_DBL);
-                       break;
-
-               case BC_aload_0:
-               case BC_aload_1:
-               case BC_aload_2:
-               case BC_aload_3:
-                       OP_LOAD_ONEWORD(ICMD_ALOAD, opcode - BC_aload_0, TYPE_ADR);
-                       break;
-
-               case BC_istore:
-               case BC_fstore:
-               case BC_astore:
-                       if (iswide == false) {
-                               i = SUCK_BE_U1(m->jcode + bcindex + 1);
-                       }
-                       else {
-                               i = SUCK_BE_U2(m->jcode + bcindex + 1);
-                               nextbc = bcindex + 3;
-                               iswide = false;
-                       }
-                       OP_STORE_ONEWORD(opcode, i, opcode - BC_istore);
-                       break;
-
-               case BC_lstore:
-               case BC_dstore:
-                       if (iswide == false) {
-                               i = SUCK_BE_U1(m->jcode + bcindex + 1);
-                       }
-                       else {
-                               i = SUCK_BE_U2(m->jcode + bcindex + 1);
-                               nextbc = bcindex + 3;
-                               iswide = false;
-                       }
-                       OP_STORE_TWOWORD(opcode, i, opcode - BC_istore);
-                       break;
-
-               case BC_istore_0:
-               case BC_istore_1:
-               case BC_istore_2:
-               case BC_istore_3:
-                       OP_STORE_ONEWORD(ICMD_ISTORE, opcode - BC_istore_0, TYPE_INT);
-                       break;
-
-               case BC_lstore_0:
-               case BC_lstore_1:
-               case BC_lstore_2:
-               case BC_lstore_3:
-                       OP_STORE_TWOWORD(ICMD_LSTORE, opcode - BC_lstore_0, TYPE_LNG);
-                       break;
-
-               case BC_fstore_0:
-               case BC_fstore_1:
-               case BC_fstore_2:
-               case BC_fstore_3:
-                       OP_STORE_ONEWORD(ICMD_FSTORE, opcode - BC_fstore_0, TYPE_FLT);
-                       break;
-
-               case BC_dstore_0:
-               case BC_dstore_1:
-               case BC_dstore_2:
-               case BC_dstore_3:
-                       OP_STORE_TWOWORD(ICMD_DSTORE, opcode - BC_dstore_0, TYPE_DBL);
-                       break;
-
-               case BC_astore_0:
-               case BC_astore_1:
-               case BC_astore_2:
-               case BC_astore_3:
-                       OP_STORE_ONEWORD(ICMD_ASTORE, opcode - BC_astore_0, TYPE_ADR);
-                       break;
-
-               case BC_iinc:
-                       {
-                               int v;
-
-                               if (iswide == false) {
-                                       i = SUCK_BE_U1(m->jcode + bcindex + 1);
-                                       v = SUCK_BE_S1(m->jcode + bcindex + 2);
-                               }
-                               else {
-                                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
-                                       v = SUCK_BE_S2(m->jcode + bcindex + 3);
-                                       nextbc = bcindex + 5;
-                                       iswide = false;
-                               }
-                               INDEX_ONEWORD(i);
-                               LOCALTYPE_USED(i, TYPE_INT);
-                               OP_LOCALINDEX_I(opcode, i, v);
-                       }
-                       break;
-
-               /* wider index for loading, storing and incrementing ******************/
-
-               case BC_wide:
-                       bcindex++;
-                       iswide = true;
-                       goto fetch_opcode;
-
-               /* managing arrays ****************************************************/
-
-               case BC_newarray:
-                       switch (SUCK_BE_S1(m->jcode + bcindex + 1)) {
-                       case 4:
-                               bte = builtintable_get_internal(BUILTIN_newarray_boolean);
-                               break;
-                       case 5:
-                               bte = builtintable_get_internal(BUILTIN_newarray_char);
-                               break;
-                       case 6:
-                               bte = builtintable_get_internal(BUILTIN_newarray_float);
-                               break;
-                       case 7:
-                               bte = builtintable_get_internal(BUILTIN_newarray_double);
-                               break;
-                       case 8:
-                               bte = builtintable_get_internal(BUILTIN_newarray_byte);
-                               break;
-                       case 9:
-                               bte = builtintable_get_internal(BUILTIN_newarray_short);
-                               break;
-                       case 10:
-                               bte = builtintable_get_internal(BUILTIN_newarray_int);
-                               break;
-                       case 11:
-                               bte = builtintable_get_internal(BUILTIN_newarray_long);
-                               break;
-#if defined(ENABLE_VERIFIER)
-                       default:
-                               exceptions_throw_verifyerror(m, "Invalid array-type to create");
-                               return false;
-#endif
-                       }
-                       OP_BUILTIN_CHECK_EXCEPTION(bte);
-                       break;
-
-               case BC_anewarray:
-                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
-                       compr = (constant_classref *) class_getconstant(m->clazz, i, CONSTANT_Class);
-                       if (compr == NULL)
-                               return false;
-
-                       if (!(cr = class_get_classref_multiarray_of(1, compr)))
-                               return false;
-
-                       if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
-                               return false;
-
-                       INSTRUCTIONS_CHECK(2);
-                       OP_LOADCONST_CLASSINFO_OR_CLASSREF_NOCHECK(c, cr);
-                       bte = builtintable_get_internal(BUILTIN_newarray);
-                       OP_BUILTIN_CHECK_EXCEPTION(bte);
-                       s_count++;
-                       break;
-
-               case BC_multianewarray:
-                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
-                       j = SUCK_BE_U1(m->jcode + bcindex + 3);
-  
-                       cr = (constant_classref *) class_getconstant(m->clazz, i, CONSTANT_Class);
-                       if (cr == NULL)
-                               return false;
-  
-                       if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
-                               return false;
-  
-                       /* if unresolved, c == NULL */
-  
-                       iptr->s1.argcount = j;
-                       OP_S3_CLASSINFO_OR_CLASSREF(opcode, c, cr, INS_FLAG_CHECK);
-                       code_unflag_leafmethod(code);
-                       break;
-
-               /* control flow instructions ******************************************/
-
-               case BC_ifeq:
-               case BC_iflt:
-               case BC_ifle:
-               case BC_ifne:
-               case BC_ifgt:
-               case BC_ifge:
-               case BC_ifnull:
-               case BC_ifnonnull:
-               case BC_if_icmpeq:
-               case BC_if_icmpne:
-               case BC_if_icmplt:
-               case BC_if_icmpgt:
-               case BC_if_icmple:
-               case BC_if_icmpge:
-               case BC_if_acmpeq:
-               case BC_if_acmpne:
-               case BC_goto:
-                       i = bcindex + SUCK_BE_S2(m->jcode + bcindex + 1);
-                       CHECK_BYTECODE_INDEX(i);
-                       MARK_BASICBLOCK(&pd, i);
-                       blockend = true;
-                       OP_INSINDEX(opcode, i);
-                       break;
-
-               case BC_goto_w:
-                       i = bcindex + SUCK_BE_S4(m->jcode + bcindex + 1);
-                       CHECK_BYTECODE_INDEX(i);
-                       MARK_BASICBLOCK(&pd, i);
-                       blockend = true;
-                       OP_INSINDEX(ICMD_GOTO, i);
-                       break;
-
-               case BC_jsr:
-                       i = bcindex + SUCK_BE_S2(m->jcode + bcindex + 1);
-jsr_tail:
-                       CHECK_BYTECODE_INDEX(i);
-                       MARK_BASICBLOCK(&pd, i);
-                       blockend = true;
-                       OP_PREPARE_ZEROFLAGS(BC_jsr);
-                       iptr->sx.s23.s3.jsrtarget.insindex = i;
-                       PINC;
-                       break;
-
-               case BC_jsr_w:
-                       i = bcindex + SUCK_BE_S4(m->jcode + bcindex + 1);
-                       goto jsr_tail;
-
-               case BC_ret:
-                       if (iswide == false) {
-                               i = SUCK_BE_U1(m->jcode + bcindex + 1);
-                       }
-                       else {
-                               i = SUCK_BE_U2(m->jcode + bcindex + 1);
-                               nextbc = bcindex + 3;
-                               iswide = false;
-                       }
-                       blockend = true;
-
-                       OP_LOAD_ONEWORD(opcode, i, TYPE_ADR);
-                       break;
-
-               case BC_ireturn:
-               case BC_lreturn:
-               case BC_freturn:
-               case BC_dreturn:
-               case BC_areturn:
-               case BC_return:
-                       blockend = true;
-                       /* XXX ARETURN will need a flag in the typechecker */
-                       OP(opcode);
-                       break;
-
-               case BC_athrow:
-                       blockend = true;
-                       /* XXX ATHROW will need a flag in the typechecker */
-                       OP(opcode);
-                       break;
-
-
-               /* table jumps ********************************************************/
-
-               case BC_lookupswitch:
-                       {
-                               s4 num, j;
-                               lookup_target_t *lookup;
-#if defined(ENABLE_VERIFIER)
-                               s4 prevvalue = 0;
-#endif
-                               blockend = true;
-                               nextbc = MEMORY_ALIGN((bcindex + 1), 4);
-
-                               CHECK_END_OF_BYTECODE(nextbc + 8);
-
-                               OP_PREPARE_ZEROFLAGS(opcode);
-
-                               /* default target */
-
-                               j = bcindex + SUCK_BE_S4(m->jcode + nextbc);
-                               iptr->sx.s23.s3.lookupdefault.insindex = j;
-                               nextbc += 4;
-                               CHECK_BYTECODE_INDEX(j);
-                               MARK_BASICBLOCK(&pd, j);
-
-                               /* number of pairs */
-
-                               num = SUCK_BE_U4(m->jcode + nextbc);
-                               iptr->sx.s23.s2.lookupcount = num;
-                               nextbc += 4;
-
-                               /* allocate the intermediate code table */
-
-                               lookup = DMNEW(lookup_target_t, num);
-                               iptr->dst.lookup = lookup;
-
-                               /* iterate over the lookup table */
-
-                               CHECK_END_OF_BYTECODE(nextbc + 8 * num);
-
-                               for (i = 0; i < num; i++) {
-                                       /* value */
-
-                                       j = SUCK_BE_S4(m->jcode + nextbc);
-                                       lookup->value = j;
-
-                                       nextbc += 4;
-
-#if defined(ENABLE_VERIFIER)
-                                       /* check if the lookup table is sorted correctly */
-
-                                       if (i && (j <= prevvalue)) {
-                                               exceptions_throw_verifyerror(m, "Unsorted lookup switch");
-                                               return false;
-                                       }
-                                       prevvalue = j;
-#endif
-                                       /* target */
-
-                                       j = bcindex + SUCK_BE_S4(m->jcode + nextbc);
-                                       lookup->target.insindex = j;
-                                       lookup++;
-                                       nextbc += 4;
-                                       CHECK_BYTECODE_INDEX(j);
-                                       MARK_BASICBLOCK(&pd, j);
-                               }
-
-                               PINC;
-                               break;
-                       }
-
-               case BC_tableswitch:
-                       {
-                               s4 num, j;
-                               s4 deftarget;
-                               branch_target_t *table;
-
-                               blockend = true;
-                               nextbc = MEMORY_ALIGN((bcindex + 1), 4);
-
-                               CHECK_END_OF_BYTECODE(nextbc + 12);
-
-                               OP_PREPARE_ZEROFLAGS(opcode);
-
-                               /* default target */
-
-                               deftarget = bcindex + SUCK_BE_S4(m->jcode + nextbc);
-                               nextbc += 4;
-                               CHECK_BYTECODE_INDEX(deftarget);
-                               MARK_BASICBLOCK(&pd, deftarget);
-
-                               /* lower bound */
-
-                               j = SUCK_BE_S4(m->jcode + nextbc);
-                               iptr->sx.s23.s2.tablelow = j;
-                               nextbc += 4;
-
-                               /* upper bound */
-
-                               num = SUCK_BE_S4(m->jcode + nextbc);
-                               iptr->sx.s23.s3.tablehigh = num;
-                               nextbc += 4;
-
-                               /* calculate the number of table entries */
-
-                               num = num - j + 1;
-
-#if defined(ENABLE_VERIFIER)
-                               if (num < 1) {
-                                       exceptions_throw_verifyerror(m,
-                                                       "invalid TABLESWITCH: upper bound < lower bound");
-                                       return false;
-                               }
-#endif
-                               /* create the intermediate code table */
-                               /* the first entry is the default target */
-
-                               table = DMNEW(branch_target_t, 1 + num);
-                               iptr->dst.table = table;
-                               (table++)->insindex = deftarget;
-
-                               /* iterate over the target table */
-
-                               CHECK_END_OF_BYTECODE(nextbc + 4 * num);
-
-                               for (i = 0; i < num; i++) {
-                                       j = bcindex + SUCK_BE_S4(m->jcode + nextbc);
-                                       (table++)->insindex = j;
-                                       nextbc += 4;
-                                       CHECK_BYTECODE_INDEX(j);
-                                       MARK_BASICBLOCK(&pd, j);
-                               }
-
-                               PINC;
-                               break;
-                       }
-
-
-               /* load and store of object fields ************************************/
-
-               case BC_aastore:
-                       OP(opcode);
-                       code_unflag_leafmethod(code);
-                       break;
-
-               case BC_getstatic:
-               case BC_putstatic:
-               case BC_getfield:
-               case BC_putfield:
-                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
-                       fmi = class_getconstant(m->clazz, i, CONSTANT_Fieldref);
-
-                       if (fmi == NULL)
-                               return false;
-
-                       OP_PREPARE_ZEROFLAGS(opcode);
-                       iptr->sx.s23.s3.fmiref = fmi;
-
-                       /* only with -noverify, otherwise the typechecker does this */
-
-#if defined(ENABLE_VERIFIER)
-                       if (!JITDATA_HAS_FLAG_VERIFY(jd)) {
-#endif
-                               result = resolve_field_lazy(m, fmi);
-
-                               if (result == resolveFailed)
-                                       return false;
-
-                               if (result != resolveSucceeded) {
-                                       uf = resolve_create_unresolved_field(m->clazz, m, iptr);
-
-                                       if (uf == NULL)
-                                               return false;
-
-                                       /* store the unresolved_field pointer */
-
-                                       iptr->sx.s23.s3.uf = uf;
-                                       iptr->flags.bits |= INS_FLAG_UNRESOLVED;
-                               }
-#if defined(ENABLE_VERIFIER)
-                       }
-#endif
-                       PINC;
-                       break;
-
-
-               /* method invocation **************************************************/
-
-               case BC_invokestatic:
-                       OP_PREPARE_ZEROFLAGS(opcode);
-
-                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
-                       fmi = class_getconstant(m->clazz, i, CONSTANT_Methodref);
-
-                       if (fmi == NULL)
-                               return false;
-
-                       md = fmi->parseddesc.md;
-
-                       if (md->params == NULL)
-                               if (!descriptor_params_from_paramtypes(md, ACC_STATIC))
-                                       return false;
-
-                       goto invoke_method;
-
-               case BC_invokespecial:
-                       OP_PREPARE_FLAGS(opcode, INS_FLAG_CHECK);
-
-                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
-                       fmi = class_getconstant(m->clazz, i, CONSTANT_Methodref);
-
-                       goto invoke_nonstatic_method;
-
-               case BC_invokeinterface:
-                       OP_PREPARE_ZEROFLAGS(opcode);
-
-                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
-                       fmi = class_getconstant(m->clazz, i, CONSTANT_InterfaceMethodref);
-
-                       goto invoke_nonstatic_method;
-
-               case BC_invokevirtual:
-                       OP_PREPARE_ZEROFLAGS(opcode);
-
-                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
-                       fmi = class_getconstant(m->clazz, i, CONSTANT_Methodref);
-
-invoke_nonstatic_method:
-                       if (fmi == NULL)
-                               return false;
-
-                       md = fmi->parseddesc.md;
-
-                       if (md->params == NULL)
-                               if (!descriptor_params_from_paramtypes(md, 0))
-                                       return false;
-
-invoke_method:
-                       code_unflag_leafmethod(code);
-
-                       iptr->sx.s23.s3.fmiref = fmi;
-
-                       /* only with -noverify, otherwise the typechecker does this */
-
-#if defined(ENABLE_VERIFIER)
-                       if (!JITDATA_HAS_FLAG_VERIFY(jd)) {
-#endif
-                               result = resolve_method_lazy(m, fmi, 
-                                                                                        (opcode == BC_invokespecial));
-
-                               if (result == resolveFailed)
-                                       return false;
-
-                               if (result == resolveSucceeded) {
-                                       methodinfo *mi = iptr->sx.s23.s3.fmiref->p.method;
-
-                                       /* if this call is monomorphic, turn it into an
-                                          INVOKESPECIAL */
-
-                                       assert(IS_FMIREF_RESOLVED(iptr->sx.s23.s3.fmiref));
-
-                                       if ((iptr->opc == ICMD_INVOKEVIRTUAL)
-                                               && (mi->flags & (ACC_FINAL | ACC_PRIVATE)))
-                                       {
-                                               iptr->opc         = ICMD_INVOKESPECIAL;
-                                               iptr->flags.bits |= INS_FLAG_CHECK;
-                                       }
-                               }
-                               else {
-                                       um = resolve_create_unresolved_method(m->clazz, m, fmi,
-                                                       (opcode == BC_invokestatic),
-                                                       (opcode == BC_invokespecial));
-
-                                       if (um == NULL)
-                                               return false;
-
-                                       /* store the unresolved_method pointer */
-
-                                       iptr->sx.s23.s3.um = um;
-                                       iptr->flags.bits |= INS_FLAG_UNRESOLVED;
-                               }
-#if defined(ENABLE_VERIFIER)
-                       }
-#endif
-                       PINC;
-                       break;
-
-               /* instructions taking class arguments ********************************/
-
-               case BC_new:
-                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
-                       cr = class_getconstant(m->clazz, i, CONSTANT_Class);
-
-                       if (cr == NULL)
-                               return false;
-
-                       if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
-                               return false;
-
-                       INSTRUCTIONS_CHECK(2);
-                       OP_LOADCONST_CLASSINFO_OR_CLASSREF_NOCHECK(c, cr);
-                       bte = builtintable_get_internal(BUILTIN_new);
-                       OP_BUILTIN_CHECK_EXCEPTION(bte);
-                       s_count++;
-                       break;
-
-               case BC_checkcast:
-                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
-                       cr = class_getconstant(m->clazz, i, CONSTANT_Class);
-
-                       if (cr == NULL)
-                               return false;
-
-                       if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
-                               return false;
-
-                       if (cr->name->text[0] == '[') {
-                               /* array type cast-check */
-                               flags = INS_FLAG_CHECK | INS_FLAG_ARRAY;
-                               code_unflag_leafmethod(code);
-                       }
-                       else {
-                               /* object type cast-check */
-                               flags = INS_FLAG_CHECK;
-                       }
-                       OP_S3_CLASSINFO_OR_CLASSREF(opcode, c, cr, flags);
-                       break;
-
-               case BC_instanceof:
-                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
-                       cr = class_getconstant(m->clazz, i, CONSTANT_Class);
-
-                       if (cr == NULL)
-                               return false;
-
-                       if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
-                               return false;
-
-                       if (cr->name->text[0] == '[') {
-                               /* array type cast-check */
-                               INSTRUCTIONS_CHECK(2);
-                               OP_LOADCONST_CLASSINFO_OR_CLASSREF_NOCHECK(c, cr);
-                               bte = builtintable_get_internal(BUILTIN_arrayinstanceof);
-                               OP_BUILTIN_NO_EXCEPTION(bte);
-                               s_count++;
-                       }
-                       else {
-                               /* object type cast-check */
-                               OP_S3_CLASSINFO_OR_CLASSREF(opcode, c, cr, 0 /* flags*/);
-                       }
-                       break;
-
-               /* synchronization instructions ***************************************/
-
-               case BC_monitorenter:
-#if defined(ENABLE_THREADS)
-                       if (checksync) {
-                               bte = builtintable_get_internal(LOCK_monitor_enter);
-                               OP_BUILTIN_CHECK_EXCEPTION(bte);
-                       }
-                       else
-#endif
-                       {
-                               OP_CHECK_EXCEPTION(ICMD_CHECKNULL);
-                               OP(ICMD_POP);
-                       }
-                       break;
-
-               case BC_monitorexit:
-#if defined(ENABLE_THREADS)
-                       if (checksync) {
-                               bte = builtintable_get_internal(LOCK_monitor_exit);
-                               OP_BUILTIN_CHECK_EXCEPTION(bte);
-                       }
-                       else
-#endif
-                       {
-                               OP_CHECK_EXCEPTION(ICMD_CHECKNULL);
-                               OP(ICMD_POP);
-                       }
-                       break;
-
-               /* arithmetic instructions that may become builtin functions **********/
-
-               case BC_idiv:
-#if !SUPPORT_DIVISION
-                       bte = builtintable_get_internal(BUILTIN_idiv);
-                       OP_BUILTIN_ARITHMETIC(opcode, bte);
-#else
-# if SUPPORT_HARDWARE_DIVIDE_BY_ZERO
-                       OP(opcode);
-# else
-                       OP_CHECK_EXCEPTION(opcode);
-# endif
-#endif
-                       break;
-
-               case BC_irem:
-#if !SUPPORT_DIVISION
-                       bte = builtintable_get_internal(BUILTIN_irem);
-                       OP_BUILTIN_ARITHMETIC(opcode, bte);
-#else
-# if SUPPORT_HARDWARE_DIVIDE_BY_ZERO
-                       OP(opcode);
-# else
-                       OP_CHECK_EXCEPTION(opcode);
-# endif
-#endif
-                       break;
-
-               case BC_ldiv:
-#if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
-                       bte = builtintable_get_internal(BUILTIN_ldiv);
-                       OP_BUILTIN_ARITHMETIC(opcode, bte);
-#else
-# if SUPPORT_HARDWARE_DIVIDE_BY_ZERO
-                       OP(opcode);
-# else
-                       OP_CHECK_EXCEPTION(opcode);
-# endif
-#endif
-                       break;
-
-               case BC_lrem:
-#if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
-                       bte = builtintable_get_internal(BUILTIN_lrem);
-                       OP_BUILTIN_ARITHMETIC(opcode, bte);
-#else
-# if SUPPORT_HARDWARE_DIVIDE_BY_ZERO
-                       OP(opcode);
-# else
-                       OP_CHECK_EXCEPTION(opcode);
-# endif
-#endif
-                       break;
-
-               case BC_frem:
-#if defined(__I386__)
-                       OP(opcode);
-#else
-                       bte = builtintable_get_internal(BUILTIN_frem);
-                       OP_BUILTIN_NO_EXCEPTION(bte);
-#endif
-                       break;
-
-               case BC_drem:
-#if defined(__I386__)
-                       OP(opcode);
-#else
-                       bte = builtintable_get_internal(BUILTIN_drem);
-                       OP_BUILTIN_NO_EXCEPTION(bte);
-#endif
-                       break;
-
-               case BC_f2i:
-#if defined(__ALPHA__)
-                       bte = builtintable_get_internal(BUILTIN_f2i);
-                       OP_BUILTIN_NO_EXCEPTION(bte);
-#else
-                       OP(opcode);
-#endif
-                       break;
-
-               case BC_f2l:
-#if defined(__ALPHA__)
-                       bte = builtintable_get_internal(BUILTIN_f2l);
-                       OP_BUILTIN_NO_EXCEPTION(bte);
-#else
-                       OP(opcode);
-#endif
-                       break;
-
-               case BC_d2i:
-#if defined(__ALPHA__)
-                       bte = builtintable_get_internal(BUILTIN_d2i);
-                       OP_BUILTIN_NO_EXCEPTION(bte);
-#else
-                       OP(opcode);
-#endif
-                       break;
-
-               case BC_d2l:
-#if defined(__ALPHA__)
-                       bte = builtintable_get_internal(BUILTIN_d2l);
-                       OP_BUILTIN_NO_EXCEPTION(bte);
-#else
-                       OP(opcode);
-#endif
-                       break;
-
-
-               /* invalid opcodes ****************************************************/
-
-                       /* check for invalid opcodes if the verifier is enabled */
-#if defined(ENABLE_VERIFIER)
-               case BC_breakpoint:
-                       exceptions_throw_verifyerror(m, "Quick instructions shouldn't appear, yet.");
-                       return false;
-
-
-               /* Unused opcodes ************************************************** */
-
-               case 186:
-               case 203:
-               case 204:
-               case 205:
-               case 206:
-               case 207:
-               case 208:
-               case 209:
-               case 210:
-               case 211:
-               case 212:
-               case 213:
-               case 214:
-               case 215:
-               case 216:
-               case 217:
-               case 218:
-               case 219:
-               case 220:
-               case 221:
-               case 222:
-               case 223:
-               case 224:
-               case 225:
-               case 226:
-               case 227:
-               case 228:
-               case 229:
-               case 230:
-               case 231:
-               case 232:
-               case 233:
-               case 234:
-               case 235:
-               case 236:
-               case 237:
-               case 238:
-               case 239:
-               case 240:
-               case 241:
-               case 242:
-               case 243:
-               case 244:
-               case 245:
-               case 246:
-               case 247:
-               case 248:
-               case 249:
-               case 250:
-               case 251:
-               case 252:
-               case 253:
-               case 254:
-               case 255:
-                       exceptions_throw_verifyerror(m, "Illegal opcode %d at instr %d\n",
-                                                                                opcode, ircount);
-                       return false;
-                       break;
-#endif /* defined(ENABLE_VERIFIER) */
-
-               /* opcodes that don't require translation *****************************/
-
-               default:
-                       /* Straight-forward translation to HIR. */
-                       OP(opcode);
-                       break;
-
-               } /* end switch */
-
-               /* verifier checks ****************************************************/
-
-#if defined(ENABLE_VERIFIER)
-               /* If WIDE was used correctly, iswide should have been reset by now. */
-               if (iswide) {
-                       exceptions_throw_verifyerror(m,
-                                       "Illegal instruction: WIDE before incompatible opcode");
-                       return false;
-               }
-#endif /* defined(ENABLE_VERIFIER) */
-
-       } /* end for */
-
-       if (JITDATA_HAS_FLAG_REORDER(jd)) {
-               /* add a NOP to the last basic block */
-
-               INSTRUCTIONS_CHECK(1);
-               OP(ICMD_NOP);
-       }
-
-       /*** END OF LOOP **********************************************************/
-
-       /* assert that we did not write more ICMDs than allocated */
-
-       assert(ircount <= pd.instructionslength);
-       assert(ircount == (iptr - pd.instructions));
-
-       /*** verifier checks ******************************************************/
-
-#if defined(ENABLE_VERIFIER)
-       if (bcindex != m->jcodelength) {
-               exceptions_throw_verifyerror(m,
-                               "Command-sequence crosses code-boundary");
-               return false;
-       }
-
-       if (!blockend) {
-               exceptions_throw_verifyerror(m, "Falling off the end of the code");
-               return false;
-       }
-#endif /* defined(ENABLE_VERIFIER) */
-
-       /*** setup the methodinfo, allocate stack and basic blocks ****************/
-
-       /* identify basic blocks */
-
-       /* check if first instruction is a branch target */
-
-       if (pd.basicblockstart[0] == 1) {
-               jd->branchtoentry = true;
-       }
-       else {
-               /* first instruction always starts a basic block */
-
-               iptr = pd.instructions;
-
-               iptr->flags.bits |= INS_FLAG_BASICBLOCK;
-       }
-
-       /* Iterate over all bytecode instructions and set missing
-          basic-block starts in IR instructions. */
-
-       for (bcindex = 0; bcindex < m->jcodelength; bcindex++) {
-               /* Does the current bytecode instruction start a basic
-                  block? */
-
-               if (pd.basicblockstart[bcindex] == 1) {
-#if defined(ENABLE_VERIFIER)
-                       /* Check if this bytecode basic-block start at the
-                          beginning of a bytecode instruction. */
-
-                       if (pd.bytecodestart[bcindex] == 0) {
-                               exceptions_throw_verifyerror(m,
-                                                                                "Branch into middle of instruction");
-                               return false;
-                       }
-#endif
-
-                       /* Get the IR instruction mapped to the bytecode
-                          instruction and set the basic block flag. */
-
-                       irindex = pd.bytecodemap[bcindex];
-                       iptr    = pd.instructions + irindex;
-
-                       iptr->flags.bits |= INS_FLAG_BASICBLOCK;
-               }
-       }
-
-       /* IR instruction index to basic-block index mapping */
-
-       pd.instructionmap = DMNEW(s4, ircount);
-       MZERO(pd.instructionmap, s4, ircount);
-
-       /* Iterate over all IR instructions and count the basic blocks. */
-
-       iptr = pd.instructions;
-
-       bbcount = 0;
-
-       for (i = 0; i < ircount; i++, iptr++) {
-               if (INSTRUCTION_STARTS_BASICBLOCK(iptr)) {
-                       /* store the basic-block number in the IR instruction
-                          map */
-
-                       pd.instructionmap[i] = bbcount;
-
-                       /* post-increment the basic-block count */
-
-                       bbcount++;
-               }
-       }
-
-       /* Allocate basic block array (one more for end ipc). */
-
-       jd->basicblocks = DMNEW(basicblock, bbcount + 1);
-       MZERO(jd->basicblocks, basicblock, bbcount + 1);
-
-       /* Now iterate again over all IR instructions and initialize the
-          basic block structures and, in the same loop, resolve the
-          branch-target instruction indices to basic blocks. */
-
-       iptr = pd.instructions;
-       bptr = jd->basicblocks;
-
-       bbcount = 0;
-
-       for (i = 0; i < ircount; i++, iptr++) {
-               /* check for basic block */
-
-               if (INSTRUCTION_STARTS_BASICBLOCK(iptr)) {
-                       /* intialize the basic block */
-
-                       BASICBLOCK_INIT(bptr, m);
-
-                       bptr->iinstr = iptr;
-
-                       if (bbcount > 0) {
-                               bptr[-1].icount = bptr->iinstr - bptr[-1].iinstr;
-                       }
-
-                       /* bptr->icount is set when the next block is allocated */
-
-                       bptr->nr = bbcount++;
-                       bptr++;
-                       bptr[-1].next = bptr;
-               }
-
-               /* resolve instruction indices to basic blocks */
-
-               switch (iptr->opc) {
-               case ICMD_IFEQ:
-               case ICMD_IFLT:
-               case ICMD_IFLE:
-               case ICMD_IFNE:
-               case ICMD_IFGT:
-               case ICMD_IFGE:
-               case ICMD_IFNULL:
-               case ICMD_IFNONNULL:
-               case ICMD_IF_ICMPEQ:
-               case ICMD_IF_ICMPNE:
-               case ICMD_IF_ICMPLT:
-               case ICMD_IF_ICMPGT:
-               case ICMD_IF_ICMPLE:
-               case ICMD_IF_ICMPGE:
-               case ICMD_IF_ACMPEQ:
-               case ICMD_IF_ACMPNE:
-               case ICMD_GOTO:
-                       BYTECODEINDEX_TO_BASICBLOCK(iptr->dst);
-                       break;
-
-               case ICMD_JSR:
-                       BYTECODEINDEX_TO_BASICBLOCK(iptr->sx.s23.s3.jsrtarget);
-                       break;
-
-               case ICMD_TABLESWITCH:
-                       table = iptr->dst.table;
-
-                       BYTECODEINDEX_TO_BASICBLOCK(*table);
-                       table++;
-
-                       j = iptr->sx.s23.s3.tablehigh - iptr->sx.s23.s2.tablelow + 1;
-
-                       while (--j >= 0) {
-                               BYTECODEINDEX_TO_BASICBLOCK(*table);
-                               table++;
-                       }
-                       break;
-
-               case ICMD_LOOKUPSWITCH:
-                       BYTECODEINDEX_TO_BASICBLOCK(iptr->sx.s23.s3.lookupdefault);
-
-                       lookup = iptr->dst.lookup;
-
-                       j = iptr->sx.s23.s2.lookupcount;
-
-                       while (--j >= 0) {
-                               BYTECODEINDEX_TO_BASICBLOCK(lookup->target);
-                               lookup++;
-                       }
-                       break;
-               }
-       }
-
-       /* set instruction count of last real block */
-
-       if (bbcount > 0) {
-               bptr[-1].icount = (pd.instructions + ircount) - bptr[-1].iinstr;
-       }
-
-       /* allocate additional block at end */
-
-       BASICBLOCK_INIT(bptr, m);
-       bptr->nr = bbcount;
-
-       /* set basicblock pointers in exception table */
-
-       if (!parse_resolve_exception_table(jd, &pd))
-               return false;
-
-       /* store the local map */
-
-       jd->local_map = local_map;
-
-       /* calculate local variable renaming */
-
-       {
-               s4 nlocals = 0;
-               s4 i;
-               s4 t;
-               s4 varindex;
-               s4 *mapptr;
-               s4 *reversemap;
-
-               mapptr = local_map;
-
-               /* iterate over local_map[0..m->maxlocals*5-1] and allocate a unique */
-               /* variable index for each _used_ (javaindex,type) pair.             */
-               /* (local_map[javaindex*5+type] = cacaoindex)                        */
-               /* Unused (javaindex,type) pairs are marked with UNUSED.             */
-
-               for (i = 0; i < (m->maxlocals * 5); i++, mapptr++) {
-                       if (*mapptr)
-                               *mapptr = nlocals++;
-                       else
-                               *mapptr = UNUSED;
-               }
-
-               jd->localcount = nlocals;
-
-               /* calculate the (maximum) number of variables needed */
-
-               jd->varcount = 
-                         nlocals                                      /* local variables */
-                       + bbcount * m->maxstack                                 /* invars */
-                       + s_count;         /* variables created within blocks (non-invar) */
-
-               /* reserve the first indices for local variables */
-
-               jd->vartop = nlocals;
-
-               /* reserve extra variables needed by stack analyse */
-
-               jd->varcount += STACK_EXTRA_VARS;
-               jd->vartop   += STACK_EXTRA_VARS;
-
-               /* The verifier needs space for saving invars in some cases and */
-               /* extra variables.                                             */
-
-#if defined(ENABLE_VERIFIER)
-               jd->varcount += VERIFIER_EXTRA_LOCALS + VERIFIER_EXTRA_VARS + m->maxstack;
-               jd->vartop   += VERIFIER_EXTRA_LOCALS + VERIFIER_EXTRA_VARS + m->maxstack;
-#endif
-               /* allocate and initialize the variable array */
-
-               jd->var = DMNEW(varinfo, jd->varcount);
-               MZERO(jd->var, varinfo, jd->varcount);
-
-               /* set types of all locals in jd->var */
-               /* and fill the reverselocalmap       */
-
-               reversemap = DMNEW(s4, nlocals);
-
-               for (i = 0; i < m->maxlocals; i++)
-                       for (t=0; t<5; t++) {
-                               varindex = local_map[5*i + t];
-                               if (varindex != UNUSED) {
-                                       VAR(varindex)->type = t;
-                                       reversemap[varindex] = i;
-                               }
-                       }
-
-               jd->reverselocalmap = reversemap;
-       }
-
-       /* assign local variables to method variables */
-
-       jd->instructions     = pd.instructions;
-       jd->instructioncount = ircount;
-       jd->basicblockcount  = bbcount;
-       jd->stackcount       = s_count + bbcount * m->maxstack; /* in-stacks */
-
-       /* allocate stack table */
-
-       jd->stack = DMNEW(stackelement_t, jd->stackcount);
-
-       /* everything's ok */
-
-       return true;
-
-       /*** goto labels for throwing verifier exceptions *************************/
-
-#if defined(ENABLE_VERIFIER)
-
-throw_unexpected_end_of_bytecode:
-       exceptions_throw_verifyerror(m, "Unexpected end of bytecode");
-       return false;
-
-throw_invalid_bytecode_index:
-       exceptions_throw_verifyerror(m, "Illegal target of branch instruction");
-       return false;
-
-throw_illegal_local_variable_number:
-       exceptions_throw_verifyerror(m, "Illegal local variable number");
-       return false;
-
-#endif /* ENABLE_VERIFIER */
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
diff --git a/src/vm/jit/parse.cpp b/src/vm/jit/parse.cpp
new file mode 100644 (file)
index 0000000..ddc5d9b
--- /dev/null
@@ -0,0 +1,1928 @@
+/* src/vm/jit/parse.c - parser for JavaVM to intermediate code translation
+
+   Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+   This file is part of CACAO.
+
+   This program 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 2, or (at
+   your option) any later version.
+
+   This program 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 this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+#include <string.h>
+
+#include "vm/types.h"
+
+#include "mm/memory.h"
+
+#include "native/native.hpp"
+
+#include "threads/lock.hpp"
+
+#include "toolbox/logging.h"
+
+#include "vm/jit/builtin.hpp"
+#include "vm/exceptions.hpp"
+#include "vm/global.h"
+#include "vm/linker.h"
+#include "vm/loader.hpp"
+#include "vm/options.h"
+#include "vm/resolve.hpp"
+
+#if defined(ENABLE_STATISTICS)
+# include "vm/statistics.h"
+#endif
+
+#include "vm/string.hpp"
+#include "vm/suck.hpp"
+
+#include "vm/jit/asmpart.h"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/parse.hpp"
+#include "vm/jit/loop/loop.h"
+
+#include "vm/jit/ir/bytecode.h"
+
+
+#define INSTRUCTIONS_INCREMENT  5  /* number of additional instructions to    */
+                                   /* allocate if space runs out              */
+
+
+/* local macros ***************************************************************/
+
+#define BYTECODEINDEX_TO_BASICBLOCK(dst) \
+    do { \
+        (dst).block = \
+            parse_bytecodeindex_to_basicblock(jd, &pd, (dst).insindex); \
+    } while (0)
+
+
+/* parserdata_t ***************************************************************/
+
+typedef struct parsedata_t parsedata_t;
+
+struct parsedata_t {
+       u1          *bytecodestart;         /* start of bytecode instructions     */
+       u1          *basicblockstart;       /* start of bytecode basic-blocks     */
+
+       s4          *bytecodemap;           /* bytecode to IR mapping             */
+       
+       instruction *instructions;          /* instruction array                  */
+       s4           instructionslength;    /* length of the instruction array    */
+
+       s4          *instructionmap;        /* IR to basic-block mapping          */
+};
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* parse_setup *****************************************************************
+
+   Fills the passed parsedata_t structure.
+
+*******************************************************************************/
+
+static void parse_setup(jitdata *jd, parsedata_t *pd)
+{
+       methodinfo *m;
+
+       /* get required compiler data */
+
+       m = jd->m;
+
+       /* bytecode start array */
+
+       pd->bytecodestart = (u1*) DumpMemory::allocate(sizeof(u1) * (m->jcodelength + 1));
+       MZERO(pd->bytecodestart, u1, m->jcodelength + 1);
+
+       /* bytecode basic-block start array */
+
+       pd->basicblockstart = (u1*) DumpMemory::allocate(sizeof(u1) *(m->jcodelength + 1));
+       MZERO(pd->basicblockstart, u1, m->jcodelength + 1);
+
+       /* bytecode instruction index to IR instruction mapping */
+
+       pd->bytecodemap = (s4*) DumpMemory::allocate(sizeof(s4) * (m->jcodelength + 1));
+       MSET(pd->bytecodemap, -1, s4, m->jcodelength + 1);
+
+       /* allocate the instruction array */
+
+       pd->instructionslength = m->jcodelength + 1;
+       pd->instructions = (instruction*) DumpMemory::allocate(sizeof(instruction) * pd->instructionslength);
+
+       /* Zero the intermediate instructions array so we don't have any
+          invalid pointers in it if we cannot finish stack_analyse(). */
+
+       MZERO(pd->instructions, instruction, pd->instructionslength);
+
+       /* The instructionmap is allocated later when we know the count of
+          instructions. */
+
+       pd->instructionmap = NULL;
+}
+
+
+/* parse_realloc_instructions **************************************************
+
+   Reallocate the instructions array so there is room for at least N 
+   additional instructions.
+
+   RETURN VALUE:
+       the new value for iptr
+
+*******************************************************************************/
+
+static instruction *parse_realloc_instructions(parsedata_t *pd, s4 icount, s4 n)
+{
+       /* increase the size of the instruction array */
+
+       pd->instructionslength += (n + INSTRUCTIONS_INCREMENT);
+
+       /* reallocate the array */
+
+       pd->instructions = (instruction*) DumpMemory::reallocate(pd->instructions, sizeof(instruction) * icount,
+                                                                sizeof(instruction) * pd->instructionslength);
+       MZERO(pd->instructions + icount, instruction,
+                 (pd->instructionslength - icount));
+
+       /* return the iptr */
+
+       return pd->instructions + icount;
+}
+
+
+/* parse_bytecodeindex_to_basicblock *******************************************
+
+   Resolves a bytecode index to the corresponding basic block.
+
+*******************************************************************************/
+
+static basicblock *parse_bytecodeindex_to_basicblock(jitdata *jd,
+                                                                                                        parsedata_t *pd,
+                                                                                                        s4 bcindex)
+{
+       s4          irindex;
+       basicblock *bb;
+
+       irindex = pd->bytecodemap[bcindex];
+       bb      = jd->basicblocks + pd->instructionmap[irindex];
+
+       return bb;
+}
+
+
+/* parse_mark_exception_boundaries *********************************************
+
+   Mark exception handlers and the boundaries of the handled regions as
+   basic block boundaries.
+
+   IN:
+       jd...............current jitdata
+
+   RETURN VALUE:
+       true.............everything ok
+          false............an exception has been thrown
+
+*******************************************************************************/
+
+static bool parse_mark_exception_boundaries(jitdata *jd, parsedata_t *pd)
+{
+       s4                   bcindex;
+       s4                   i;
+       s4                   len;
+       raw_exception_entry *rex;
+       methodinfo          *m;
+
+       m = jd->m;
+       
+       len = m->rawexceptiontablelength;
+
+       if (len == 0)
+               return true;
+
+       rex = m->rawexceptiontable;
+
+       for (i = 0; i < len; ++i, ++rex) {
+
+               /* the start of the handled region becomes a basic block start */
+
+               bcindex = rex->startpc;
+               CHECK_BYTECODE_INDEX(bcindex);
+               MARK_BASICBLOCK(pd, bcindex);
+               
+               bcindex = rex->endpc; /* see JVM Spec 4.7.3 */
+               CHECK_BYTECODE_INDEX_EXCLUSIVE(bcindex);
+
+               /* check that the range is valid */
+
+#if defined(ENABLE_VERIFIER)
+               if (bcindex <= rex->startpc) {
+                       exceptions_throw_verifyerror(m, "Invalid exception handler range");
+                       return false;
+               }
+#endif
+               
+               /* End of handled region becomes a basic block boundary (if it
+                  is the bytecode end, we'll use the special end block that
+                  is created anyway). */
+
+               if (bcindex < m->jcodelength)
+                       MARK_BASICBLOCK(pd, bcindex);
+               else
+                       jd->branchtoend = true;
+
+               /* the start of the handler becomes a basic block start  */
+
+               bcindex = rex->handlerpc;
+               CHECK_BYTECODE_INDEX(bcindex);
+               MARK_BASICBLOCK(pd, bcindex);
+       }
+
+       /* everything ok */
+
+       return true;
+
+#if defined(ENABLE_VERIFIER)
+throw_invalid_bytecode_index:
+       exceptions_throw_verifyerror(m,
+                                                                "Illegal bytecode index in exception table");
+       return false;
+#endif
+}
+
+
+/* parse_resolve_exception_table ***********************************************
+
+   Enter the exception handlers and their ranges, resolved to basicblock *s,
+   in the jitdata.
+
+   IN:
+       jd...............current jitdata
+
+   RETURN VALUE:
+          true.............everything ok
+          false............an exception has been thrown
+
+*******************************************************************************/
+
+static bool parse_resolve_exception_table(jitdata *jd, parsedata_t *pd)
+{
+       methodinfo          *m;
+       raw_exception_entry *rex;
+       exception_entry     *ex;
+       s4                   i;
+       s4                   len;
+       classinfo           *exclass;
+
+       m = jd->m;
+
+       len = m->rawexceptiontablelength;
+
+       /* common case: no handler entries */
+
+       if (len == 0)
+               return true;
+
+       /* allocate the exception table */
+
+       jd->exceptiontablelength = len;
+       jd->exceptiontable = (exception_entry*) DumpMemory::allocate(sizeof(exception_entry) * (len + 1)); /* XXX why +1? */
+
+       /* copy and resolve the entries */
+
+       ex = jd->exceptiontable;
+       rex = m->rawexceptiontable;
+
+       for (i = 0; i < len; ++i, ++rex, ++ex) {
+               /* resolve instruction indices to basic blocks */
+
+               ex->start   = parse_bytecodeindex_to_basicblock(jd, pd, rex->startpc);
+               ex->end     = parse_bytecodeindex_to_basicblock(jd, pd, rex->endpc);
+               ex->handler = parse_bytecodeindex_to_basicblock(jd, pd, rex->handlerpc);
+
+               /* lazily resolve the catchtype */
+
+               if (rex->catchtype.any != NULL) {
+                       if (!resolve_classref_or_classinfo(m,
+                                                                                          rex->catchtype,
+                                                                                          resolveLazy, true, false,
+                                                                                          &exclass))
+                               return false;
+
+                       /* if resolved, enter the result of resolution in the table */
+
+                       if (exclass != NULL)
+                               rex->catchtype.cls = exclass;
+               }
+
+               ex->catchtype = rex->catchtype;
+               ex->next = NULL;   /* set by loop analysis */
+               ex->down = ex + 1; /* link to next exception entry */
+       }
+
+       /* terminate the ->down linked list */
+
+       assert(ex != jd->exceptiontable);
+       ex[-1].down = NULL;
+
+       return true;
+}
+
+
+/*******************************************************************************
+
+       function 'parse' scans the JavaVM code and generates intermediate code
+
+       During parsing the block index table is used to store at bit pos 0
+       a flag which marks basic block starts and at position 1 to 31 the
+       intermediate instruction index. After parsing the block index table
+       is scanned, for marked positions a block is generated and the block
+       number is stored in the block index table.
+
+*******************************************************************************/
+
+/*** macro for checking the length of the bytecode ***/
+
+#if defined(ENABLE_VERIFIER)
+#define CHECK_END_OF_BYTECODE(neededlength) \
+       do { \
+               if ((neededlength) > m->jcodelength) \
+                       goto throw_unexpected_end_of_bytecode; \
+       } while (0)
+#else /* !ENABLE_VERIFIER */
+#define CHECK_END_OF_BYTECODE(neededlength)
+#endif /* ENABLE_VERIFIER */
+
+bool parse(jitdata *jd)
+{
+       methodinfo  *m;                     /* method being parsed                */
+       codeinfo    *code;
+       parsedata_t  pd;
+       instruction *iptr;                  /* current ptr into instruction array */
+
+       s4           bcindex;               /* bytecode instruction index         */
+       s4           nextbc;                /* start of next bytecode instruction */
+       s4           opcode;                /* bytecode instruction opcode        */
+
+       s4           irindex;               /* IR instruction index               */
+       s4           ircount;               /* IR instruction count               */
+
+       s4           bbcount;               /* basic block count                  */
+
+       int  s_count = 0;             /* stack element counter                    */
+       bool blockend;                /* true if basic block end has been reached */
+       bool iswide;                  /* true if last instruction was a wide      */
+
+       constant_classref  *cr;
+       constant_classref  *compr;
+       classinfo          *c;
+       builtintable_entry *bte;
+       constant_FMIref    *fmi;
+       methoddesc         *md;
+       unresolved_method  *um;
+       unresolved_field   *uf;
+
+       resolve_result_t    result;
+       u2                  lineindex = 0;
+       u2                  currentline = 0;
+       u2                  linepcchange = 0;
+       u4                  flags;
+       basicblock         *bptr;
+
+       int                *local_map; /* local pointer to renaming map           */
+                                      /* is assigned to rd->local_map at the end */
+       branch_target_t *table;
+       lookup_target_t *lookup;
+       s4               i;
+       s4               j;
+
+       /* get required compiler data */
+
+       m    = jd->m;
+       code = jd->code;
+
+       /* allocate buffers for local variable renaming */
+
+       local_map = (int*) DumpMemory::allocate(sizeof(int) * m->maxlocals * 5);
+
+       for (i = 0; i < m->maxlocals; i++) {
+               local_map[i * 5 + 0] = 0;
+               local_map[i * 5 + 1] = 0;
+               local_map[i * 5 + 2] = 0;
+               local_map[i * 5 + 3] = 0;
+               local_map[i * 5 + 4] = 0;
+       }
+
+       /* initialize the parse data structures */
+  
+       parse_setup(jd, &pd);
+  
+       /* initialize local variables */
+  
+       iptr     = pd.instructions;
+       ircount  = 0;
+       bbcount  = 0;
+       blockend = false;
+       iswide   = false;
+
+       /* mark basic block boundaries for exception table */
+
+       if (!parse_mark_exception_boundaries(jd, &pd))
+               return false;
+
+       /* initialize stack element counter */
+
+       s_count = 1 + m->rawexceptiontablelength;
+
+       /* setup line number info */
+
+       currentline = 0;
+       linepcchange = 0;
+
+       if (m->linenumbercount == 0) {
+               lineindex = 0;
+       }
+       else {
+               linepcchange = m->linenumbers[0].start_pc;
+       }
+
+       /*** LOOP OVER ALL BYTECODE INSTRUCTIONS **********************************/
+
+       for (bcindex = 0; bcindex < m->jcodelength; bcindex = nextbc) {
+
+               /* mark this position as a valid bytecode instruction start */
+
+               pd.bytecodestart[bcindex] = 1;
+
+               /* change the current line number, if necessary */
+
+               /* XXX rewrite this using pointer arithmetic */
+
+               if (linepcchange == bcindex) {
+                       if (m->linenumbercount > lineindex) {
+next_linenumber:
+                               currentline = m->linenumbers[lineindex].line_number;
+                               lineindex++;
+                               if (lineindex < m->linenumbercount) {
+                                       linepcchange = m->linenumbers[lineindex].start_pc;
+                                       if (linepcchange == bcindex)
+                                               goto next_linenumber;
+                               }
+                       }
+               }
+
+fetch_opcode:
+               /* fetch next opcode  */        
+
+               opcode = SUCK_BE_U1(m->jcode + bcindex);
+
+               /* If the previous instruction was a block-end instruction,
+                  mark the current bytecode instruction as basic-block
+                  starting instruction. */
+
+               /* NOTE: Some compilers put a BC_nop after a blockend
+                  instruction. */
+
+               if (blockend && (opcode != BC_nop)) {
+                       MARK_BASICBLOCK(&pd, bcindex);
+                       blockend = false;
+               }
+
+               /* If the current bytecode instruction was marked as
+                  basic-block starting instruction before (e.g. blockend,
+                  forward-branch target), mark the current IR instruction
+                  too. */
+
+               if (pd.basicblockstart[bcindex] != 0) {
+                       /* We need a NOP as last instruction in each basic block
+                          for basic block reordering (may be replaced with a GOTO
+                          later). */
+
+                       INSTRUCTIONS_CHECK(1);
+                       OP(ICMD_NOP);
+               }
+
+               /* store intermediate instruction count (bit 0 mark block starts) */
+
+               pd.bytecodemap[bcindex] = ircount;
+
+               /* compute next instruction start */
+
+               nextbc = bcindex + bytecode[opcode].length;
+
+               CHECK_END_OF_BYTECODE(nextbc);
+
+               /* add stack elements produced by this instruction */
+
+               s_count += bytecode[opcode].slots;
+
+               /* We check here for the space of 1 instruction in the
+                  instruction array.  If an opcode is converted to more than
+                  1 instruction, this is checked in the corresponding
+                  case. */
+
+               INSTRUCTIONS_CHECK(1);
+
+               /* translate this bytecode instruction */
+               switch (opcode) {
+
+               case BC_nop:
+                       break;
+
+               /* pushing constants onto the stack ***********************************/
+
+               case BC_bipush:
+                       OP_LOADCONST_I(SUCK_BE_S1(m->jcode + bcindex + 1));
+                       break;
+
+               case BC_sipush:
+                       OP_LOADCONST_I(SUCK_BE_S2(m->jcode + bcindex + 1));
+                       break;
+
+               case BC_ldc1:
+                       i = SUCK_BE_U1(m->jcode + bcindex + 1);
+                       goto pushconstantitem;
+
+               case BC_ldc2:
+               case BC_ldc2w:
+                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
+
+               pushconstantitem:
+
+#if defined(ENABLE_VERIFIER)
+                       if (i >= m->clazz->cpcount) {
+                               exceptions_throw_verifyerror(m,
+                                       "Attempt to access constant outside range");
+                               return false;
+                       }
+#endif
+
+                       switch (m->clazz->cptags[i]) {
+                       case CONSTANT_Integer:
+                               OP_LOADCONST_I(((constant_integer *) (m->clazz->cpinfos[i]))->value);
+                               break;
+                       case CONSTANT_Long:
+                               OP_LOADCONST_L(((constant_long *) (m->clazz->cpinfos[i]))->value);
+                               break;
+                       case CONSTANT_Float:
+                               OP_LOADCONST_F(((constant_float *) (m->clazz->cpinfos[i]))->value);
+                               break;
+                       case CONSTANT_Double:
+                               OP_LOADCONST_D(((constant_double *) (m->clazz->cpinfos[i]))->value);
+                               break;
+                       case CONSTANT_String:
+                               OP_LOADCONST_STRING(literalstring_new((utf *) (m->clazz->cpinfos[i])));
+                               break;
+                       case CONSTANT_Class:
+                               cr = (constant_classref *) (m->clazz->cpinfos[i]);
+
+                               if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
+                                       return false;
+
+                               /* if not resolved, c == NULL */
+
+                               OP_LOADCONST_CLASSINFO_OR_CLASSREF_CHECK(c, cr);
+
+                               break;
+
+#if defined(ENABLE_VERIFIER)
+                       default:
+                               exceptions_throw_verifyerror(m,
+                                               "Invalid constant type to push");
+                               return false;
+#endif
+                       }
+                       break;
+
+               case BC_aconst_null:
+                       OP_LOADCONST_NULL();
+                       break;
+
+               case BC_iconst_m1:
+               case BC_iconst_0:
+               case BC_iconst_1:
+               case BC_iconst_2:
+               case BC_iconst_3:
+               case BC_iconst_4:
+               case BC_iconst_5:
+                       OP_LOADCONST_I(opcode - BC_iconst_0);
+                       break;
+
+               case BC_lconst_0:
+               case BC_lconst_1:
+                       OP_LOADCONST_L(opcode - BC_lconst_0);
+                       break;
+
+               case BC_fconst_0:
+               case BC_fconst_1:
+               case BC_fconst_2:
+                       OP_LOADCONST_F(opcode - BC_fconst_0);
+                       break;
+
+               case BC_dconst_0:
+               case BC_dconst_1:
+                       OP_LOADCONST_D(opcode - BC_dconst_0);
+                       break;
+
+               /* stack operations ***************************************************/
+
+               /* We need space for additional instruction so we can
+                  translate these instructions to sequences of ICMD_COPY and
+                  ICMD_MOVE instructions. */
+
+               case BC_dup_x1:
+                       INSTRUCTIONS_CHECK(4);
+                       OP(opcode);
+                       OP(ICMD_NOP);
+                       OP(ICMD_NOP);
+                       OP(ICMD_NOP);
+                       break;
+
+               case BC_dup_x2:
+                       INSTRUCTIONS_CHECK(6);
+                       OP(opcode);
+                       OP(ICMD_NOP);
+                       OP(ICMD_NOP);
+                       OP(ICMD_NOP);
+                       OP(ICMD_NOP);
+                       OP(ICMD_NOP);
+                       break;
+
+               case BC_dup2:
+                       INSTRUCTIONS_CHECK(2);
+                       OP(opcode);
+                       OP(ICMD_NOP);
+                       break;
+
+               case BC_dup2_x1:
+                       INSTRUCTIONS_CHECK(7);
+                       OP(opcode);
+                       OP(ICMD_NOP);
+                       OP(ICMD_NOP);
+                       OP(ICMD_NOP);
+                       OP(ICMD_NOP);
+                       OP(ICMD_NOP);
+                       OP(ICMD_NOP);
+                       break;
+
+               case BC_dup2_x2:
+                       INSTRUCTIONS_CHECK(9);
+                       OP(opcode);
+                       OP(ICMD_NOP);
+                       OP(ICMD_NOP);
+                       OP(ICMD_NOP);
+                       OP(ICMD_NOP);
+                       OP(ICMD_NOP);
+                       OP(ICMD_NOP);
+                       OP(ICMD_NOP);
+                       OP(ICMD_NOP);
+                       break;
+
+               case BC_swap:
+                       INSTRUCTIONS_CHECK(3);
+                       OP(opcode);
+                       OP(ICMD_NOP);
+                       OP(ICMD_NOP);
+                       break;
+
+               /* local variable access instructions *********************************/
+
+               case BC_iload:
+               case BC_fload:
+               case BC_aload:
+                       if (iswide == false) {
+                               i = SUCK_BE_U1(m->jcode + bcindex + 1);
+                       }
+                       else {
+                               i = SUCK_BE_U2(m->jcode + bcindex + 1);
+                               nextbc = bcindex + 3;
+                               iswide = false;
+                       }
+                       OP_LOAD_ONEWORD(opcode, i, opcode - BC_iload);
+                       break;
+
+               case BC_lload:
+               case BC_dload:
+                       if (iswide == false) {
+                               i = SUCK_BE_U1(m->jcode + bcindex + 1);
+                       }
+                       else {
+                               i = SUCK_BE_U2(m->jcode + bcindex + 1);
+                               nextbc = bcindex + 3;
+                               iswide = false;
+                       }
+                       OP_LOAD_TWOWORD(opcode, i, opcode - BC_iload);
+                       break;
+
+               case BC_iload_0:
+               case BC_iload_1:
+               case BC_iload_2:
+               case BC_iload_3:
+                       OP_LOAD_ONEWORD(ICMD_ILOAD, opcode - BC_iload_0, TYPE_INT);
+                       break;
+
+               case BC_lload_0:
+               case BC_lload_1:
+               case BC_lload_2:
+               case BC_lload_3:
+                       OP_LOAD_TWOWORD(ICMD_LLOAD, opcode - BC_lload_0, TYPE_LNG);
+                       break;
+
+               case BC_fload_0:
+               case BC_fload_1:
+               case BC_fload_2:
+               case BC_fload_3:
+                       OP_LOAD_ONEWORD(ICMD_FLOAD, opcode - BC_fload_0, TYPE_FLT);
+                       break;
+
+               case BC_dload_0:
+               case BC_dload_1:
+               case BC_dload_2:
+               case BC_dload_3:
+                       OP_LOAD_TWOWORD(ICMD_DLOAD, opcode - BC_dload_0, TYPE_DBL);
+                       break;
+
+               case BC_aload_0:
+               case BC_aload_1:
+               case BC_aload_2:
+               case BC_aload_3:
+                       OP_LOAD_ONEWORD(ICMD_ALOAD, opcode - BC_aload_0, TYPE_ADR);
+                       break;
+
+               case BC_istore:
+               case BC_fstore:
+               case BC_astore:
+                       if (iswide == false) {
+                               i = SUCK_BE_U1(m->jcode + bcindex + 1);
+                       }
+                       else {
+                               i = SUCK_BE_U2(m->jcode + bcindex + 1);
+                               nextbc = bcindex + 3;
+                               iswide = false;
+                       }
+                       OP_STORE_ONEWORD(opcode, i, opcode - BC_istore);
+                       break;
+
+               case BC_lstore:
+               case BC_dstore:
+                       if (iswide == false) {
+                               i = SUCK_BE_U1(m->jcode + bcindex + 1);
+                       }
+                       else {
+                               i = SUCK_BE_U2(m->jcode + bcindex + 1);
+                               nextbc = bcindex + 3;
+                               iswide = false;
+                       }
+                       OP_STORE_TWOWORD(opcode, i, opcode - BC_istore);
+                       break;
+
+               case BC_istore_0:
+               case BC_istore_1:
+               case BC_istore_2:
+               case BC_istore_3:
+                       OP_STORE_ONEWORD(ICMD_ISTORE, opcode - BC_istore_0, TYPE_INT);
+                       break;
+
+               case BC_lstore_0:
+               case BC_lstore_1:
+               case BC_lstore_2:
+               case BC_lstore_3:
+                       OP_STORE_TWOWORD(ICMD_LSTORE, opcode - BC_lstore_0, TYPE_LNG);
+                       break;
+
+               case BC_fstore_0:
+               case BC_fstore_1:
+               case BC_fstore_2:
+               case BC_fstore_3:
+                       OP_STORE_ONEWORD(ICMD_FSTORE, opcode - BC_fstore_0, TYPE_FLT);
+                       break;
+
+               case BC_dstore_0:
+               case BC_dstore_1:
+               case BC_dstore_2:
+               case BC_dstore_3:
+                       OP_STORE_TWOWORD(ICMD_DSTORE, opcode - BC_dstore_0, TYPE_DBL);
+                       break;
+
+               case BC_astore_0:
+               case BC_astore_1:
+               case BC_astore_2:
+               case BC_astore_3:
+                       OP_STORE_ONEWORD(ICMD_ASTORE, opcode - BC_astore_0, TYPE_ADR);
+                       break;
+
+               case BC_iinc:
+                       {
+                               int v;
+
+                               if (iswide == false) {
+                                       i = SUCK_BE_U1(m->jcode + bcindex + 1);
+                                       v = SUCK_BE_S1(m->jcode + bcindex + 2);
+                               }
+                               else {
+                                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
+                                       v = SUCK_BE_S2(m->jcode + bcindex + 3);
+                                       nextbc = bcindex + 5;
+                                       iswide = false;
+                               }
+                               INDEX_ONEWORD(i);
+                               LOCALTYPE_USED(i, TYPE_INT);
+                               OP_LOCALINDEX_I(opcode, i, v);
+                       }
+                       break;
+
+               /* wider index for loading, storing and incrementing ******************/
+
+               case BC_wide:
+                       bcindex++;
+                       iswide = true;
+                       goto fetch_opcode;
+
+               /* managing arrays ****************************************************/
+
+               case BC_newarray:
+                       switch (SUCK_BE_S1(m->jcode + bcindex + 1)) {
+                       case 4:
+                               bte = builtintable_get_internal(BUILTIN_newarray_boolean);
+                               break;
+                       case 5:
+                               bte = builtintable_get_internal(BUILTIN_newarray_char);
+                               break;
+                       case 6:
+                               bte = builtintable_get_internal(BUILTIN_newarray_float);
+                               break;
+                       case 7:
+                               bte = builtintable_get_internal(BUILTIN_newarray_double);
+                               break;
+                       case 8:
+                               bte = builtintable_get_internal(BUILTIN_newarray_byte);
+                               break;
+                       case 9:
+                               bte = builtintable_get_internal(BUILTIN_newarray_short);
+                               break;
+                       case 10:
+                               bte = builtintable_get_internal(BUILTIN_newarray_int);
+                               break;
+                       case 11:
+                               bte = builtintable_get_internal(BUILTIN_newarray_long);
+                               break;
+#if defined(ENABLE_VERIFIER)
+                       default:
+                               exceptions_throw_verifyerror(m, "Invalid array-type to create");
+                               return false;
+#endif
+                       }
+                       OP_BUILTIN_CHECK_EXCEPTION(bte);
+                       break;
+
+               case BC_anewarray:
+                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
+                       compr = (constant_classref *) class_getconstant(m->clazz, i, CONSTANT_Class);
+                       if (compr == NULL)
+                               return false;
+
+                       if (!(cr = class_get_classref_multiarray_of(1, compr)))
+                               return false;
+
+                       if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
+                               return false;
+
+                       INSTRUCTIONS_CHECK(2);
+                       OP_LOADCONST_CLASSINFO_OR_CLASSREF_NOCHECK(c, cr);
+                       bte = builtintable_get_internal(BUILTIN_newarray);
+                       OP_BUILTIN_CHECK_EXCEPTION(bte);
+                       s_count++;
+                       break;
+
+               case BC_multianewarray:
+                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
+                       j = SUCK_BE_U1(m->jcode + bcindex + 3);
+  
+                       cr = (constant_classref *) class_getconstant(m->clazz, i, CONSTANT_Class);
+                       if (cr == NULL)
+                               return false;
+  
+                       if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
+                               return false;
+  
+                       /* if unresolved, c == NULL */
+  
+                       iptr->s1.argcount = j;
+                       OP_S3_CLASSINFO_OR_CLASSREF(opcode, c, cr, INS_FLAG_CHECK);
+                       code_unflag_leafmethod(code);
+                       break;
+
+               /* control flow instructions ******************************************/
+
+               case BC_ifeq:
+               case BC_iflt:
+               case BC_ifle:
+               case BC_ifne:
+               case BC_ifgt:
+               case BC_ifge:
+               case BC_ifnull:
+               case BC_ifnonnull:
+               case BC_if_icmpeq:
+               case BC_if_icmpne:
+               case BC_if_icmplt:
+               case BC_if_icmpgt:
+               case BC_if_icmple:
+               case BC_if_icmpge:
+               case BC_if_acmpeq:
+               case BC_if_acmpne:
+               case BC_goto:
+                       i = bcindex + SUCK_BE_S2(m->jcode + bcindex + 1);
+                       CHECK_BYTECODE_INDEX(i);
+                       MARK_BASICBLOCK(&pd, i);
+                       blockend = true;
+                       OP_INSINDEX(opcode, i);
+                       break;
+
+               case BC_goto_w:
+                       i = bcindex + SUCK_BE_S4(m->jcode + bcindex + 1);
+                       CHECK_BYTECODE_INDEX(i);
+                       MARK_BASICBLOCK(&pd, i);
+                       blockend = true;
+                       OP_INSINDEX(ICMD_GOTO, i);
+                       break;
+
+               case BC_jsr:
+                       i = bcindex + SUCK_BE_S2(m->jcode + bcindex + 1);
+jsr_tail:
+                       CHECK_BYTECODE_INDEX(i);
+                       MARK_BASICBLOCK(&pd, i);
+                       blockend = true;
+                       OP_PREPARE_ZEROFLAGS(BC_jsr);
+                       iptr->sx.s23.s3.jsrtarget.insindex = i;
+                       PINC;
+                       break;
+
+               case BC_jsr_w:
+                       i = bcindex + SUCK_BE_S4(m->jcode + bcindex + 1);
+                       goto jsr_tail;
+
+               case BC_ret:
+                       if (iswide == false) {
+                               i = SUCK_BE_U1(m->jcode + bcindex + 1);
+                       }
+                       else {
+                               i = SUCK_BE_U2(m->jcode + bcindex + 1);
+                               nextbc = bcindex + 3;
+                               iswide = false;
+                       }
+                       blockend = true;
+
+                       OP_LOAD_ONEWORD(opcode, i, TYPE_ADR);
+                       break;
+
+               case BC_ireturn:
+               case BC_lreturn:
+               case BC_freturn:
+               case BC_dreturn:
+               case BC_areturn:
+               case BC_return:
+                       blockend = true;
+                       /* XXX ARETURN will need a flag in the typechecker */
+                       OP(opcode);
+                       break;
+
+               case BC_athrow:
+                       blockend = true;
+                       /* XXX ATHROW will need a flag in the typechecker */
+                       OP(opcode);
+                       break;
+
+
+               /* table jumps ********************************************************/
+
+               case BC_lookupswitch:
+                       {
+                               s4 num, j;
+                               lookup_target_t *lookup;
+#if defined(ENABLE_VERIFIER)
+                               s4 prevvalue = 0;
+#endif
+                               blockend = true;
+                               nextbc = MEMORY_ALIGN((bcindex + 1), 4);
+
+                               CHECK_END_OF_BYTECODE(nextbc + 8);
+
+                               OP_PREPARE_ZEROFLAGS(opcode);
+
+                               /* default target */
+
+                               j = bcindex + SUCK_BE_S4(m->jcode + nextbc);
+                               iptr->sx.s23.s3.lookupdefault.insindex = j;
+                               nextbc += 4;
+                               CHECK_BYTECODE_INDEX(j);
+                               MARK_BASICBLOCK(&pd, j);
+
+                               /* number of pairs */
+
+                               num = SUCK_BE_U4(m->jcode + nextbc);
+                               iptr->sx.s23.s2.lookupcount = num;
+                               nextbc += 4;
+
+                               /* allocate the intermediate code table */
+
+                               lookup = (lookup_target_t*) DumpMemory::allocate(sizeof(lookup_target_t) * num);
+                               iptr->dst.lookup = lookup;
+
+                               /* iterate over the lookup table */
+
+                               CHECK_END_OF_BYTECODE(nextbc + 8 * num);
+
+                               for (i = 0; i < num; i++) {
+                                       /* value */
+
+                                       j = SUCK_BE_S4(m->jcode + nextbc);
+                                       lookup->value = j;
+
+                                       nextbc += 4;
+
+#if defined(ENABLE_VERIFIER)
+                                       /* check if the lookup table is sorted correctly */
+
+                                       if (i && (j <= prevvalue)) {
+                                               exceptions_throw_verifyerror(m, "Unsorted lookup switch");
+                                               return false;
+                                       }
+                                       prevvalue = j;
+#endif
+                                       /* target */
+
+                                       j = bcindex + SUCK_BE_S4(m->jcode + nextbc);
+                                       lookup->target.insindex = j;
+                                       lookup++;
+                                       nextbc += 4;
+                                       CHECK_BYTECODE_INDEX(j);
+                                       MARK_BASICBLOCK(&pd, j);
+                               }
+
+                               PINC;
+                               break;
+                       }
+
+               case BC_tableswitch:
+                       {
+                               s4 num, j;
+                               s4 deftarget;
+                               branch_target_t *table;
+
+                               blockend = true;
+                               nextbc = MEMORY_ALIGN((bcindex + 1), 4);
+
+                               CHECK_END_OF_BYTECODE(nextbc + 12);
+
+                               OP_PREPARE_ZEROFLAGS(opcode);
+
+                               /* default target */
+
+                               deftarget = bcindex + SUCK_BE_S4(m->jcode + nextbc);
+                               nextbc += 4;
+                               CHECK_BYTECODE_INDEX(deftarget);
+                               MARK_BASICBLOCK(&pd, deftarget);
+
+                               /* lower bound */
+
+                               j = SUCK_BE_S4(m->jcode + nextbc);
+                               iptr->sx.s23.s2.tablelow = j;
+                               nextbc += 4;
+
+                               /* upper bound */
+
+                               num = SUCK_BE_S4(m->jcode + nextbc);
+                               iptr->sx.s23.s3.tablehigh = num;
+                               nextbc += 4;
+
+                               /* calculate the number of table entries */
+
+                               num = num - j + 1;
+
+#if defined(ENABLE_VERIFIER)
+                               if (num < 1) {
+                                       exceptions_throw_verifyerror(m,
+                                                       "invalid TABLESWITCH: upper bound < lower bound");
+                                       return false;
+                               }
+#endif
+                               /* create the intermediate code table */
+                               /* the first entry is the default target */
+
+                               table = (branch_target_t*) DumpMemory::allocate(sizeof(branch_target_t) * (1 + num));
+                               iptr->dst.table = table;
+                               (table++)->insindex = deftarget;
+
+                               /* iterate over the target table */
+
+                               CHECK_END_OF_BYTECODE(nextbc + 4 * num);
+
+                               for (i = 0; i < num; i++) {
+                                       j = bcindex + SUCK_BE_S4(m->jcode + nextbc);
+                                       (table++)->insindex = j;
+                                       nextbc += 4;
+                                       CHECK_BYTECODE_INDEX(j);
+                                       MARK_BASICBLOCK(&pd, j);
+                               }
+
+                               PINC;
+                               break;
+                       }
+
+
+               /* load and store of object fields ************************************/
+
+               case BC_aastore:
+                       OP(opcode);
+                       code_unflag_leafmethod(code);
+                       break;
+
+               case BC_getstatic:
+               case BC_putstatic:
+               case BC_getfield:
+               case BC_putfield:
+                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
+                       fmi = (constant_FMIref*) class_getconstant(m->clazz, i, CONSTANT_Fieldref);
+
+                       if (fmi == NULL)
+                               return false;
+
+                       OP_PREPARE_ZEROFLAGS(opcode);
+                       iptr->sx.s23.s3.fmiref = fmi;
+
+                       /* only with -noverify, otherwise the typechecker does this */
+
+#if defined(ENABLE_VERIFIER)
+                       if (!JITDATA_HAS_FLAG_VERIFY(jd)) {
+#endif
+                               result = resolve_field_lazy(m, fmi);
+
+                               if (result == resolveFailed)
+                                       return false;
+
+                               if (result != resolveSucceeded) {
+                                       uf = resolve_create_unresolved_field(m->clazz, m, iptr);
+
+                                       if (uf == NULL)
+                                               return false;
+
+                                       /* store the unresolved_field pointer */
+
+                                       iptr->sx.s23.s3.uf = uf;
+                                       iptr->flags.bits |= INS_FLAG_UNRESOLVED;
+                               }
+#if defined(ENABLE_VERIFIER)
+                       }
+#endif
+                       PINC;
+                       break;
+
+
+               /* method invocation **************************************************/
+
+               case BC_invokestatic:
+                       OP_PREPARE_ZEROFLAGS(opcode);
+
+                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
+                       fmi = (constant_FMIref*) class_getconstant(m->clazz, i, CONSTANT_Methodref);
+
+                       if (fmi == NULL)
+                               return false;
+
+                       md = fmi->parseddesc.md;
+
+                       if (md->params == NULL)
+                               if (!descriptor_params_from_paramtypes(md, ACC_STATIC))
+                                       return false;
+
+                       goto invoke_method;
+
+               case BC_invokespecial:
+                       OP_PREPARE_FLAGS(opcode, INS_FLAG_CHECK);
+
+                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
+                       fmi = (constant_FMIref*) class_getconstant(m->clazz, i, CONSTANT_Methodref);
+
+                       goto invoke_nonstatic_method;
+
+               case BC_invokeinterface:
+                       OP_PREPARE_ZEROFLAGS(opcode);
+
+                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
+                       fmi = (constant_FMIref*) class_getconstant(m->clazz, i, CONSTANT_InterfaceMethodref);
+
+                       goto invoke_nonstatic_method;
+
+               case BC_invokevirtual:
+                       OP_PREPARE_ZEROFLAGS(opcode);
+
+                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
+                       fmi = (constant_FMIref*) class_getconstant(m->clazz, i, CONSTANT_Methodref);
+
+invoke_nonstatic_method:
+                       if (fmi == NULL)
+                               return false;
+
+                       md = fmi->parseddesc.md;
+
+                       if (md->params == NULL)
+                               if (!descriptor_params_from_paramtypes(md, 0))
+                                       return false;
+
+invoke_method:
+                       code_unflag_leafmethod(code);
+
+                       iptr->sx.s23.s3.fmiref = fmi;
+
+                       /* only with -noverify, otherwise the typechecker does this */
+
+#if defined(ENABLE_VERIFIER)
+                       if (!JITDATA_HAS_FLAG_VERIFY(jd)) {
+#endif
+                               result = resolve_method_lazy(m, fmi, 
+                                                                                        (opcode == BC_invokespecial));
+
+                               if (result == resolveFailed)
+                                       return false;
+
+                               if (result == resolveSucceeded) {
+                                       methodinfo *mi = iptr->sx.s23.s3.fmiref->p.method;
+
+                                       /* if this call is monomorphic, turn it into an
+                                          INVOKESPECIAL */
+
+                                       assert(IS_FMIREF_RESOLVED(iptr->sx.s23.s3.fmiref));
+
+                                       if ((iptr->opc == ICMD_INVOKEVIRTUAL)
+                                               && (mi->flags & (ACC_FINAL | ACC_PRIVATE)))
+                                       {
+                                               iptr->opc         = ICMD_INVOKESPECIAL;
+                                               iptr->flags.bits |= INS_FLAG_CHECK;
+                                       }
+                               }
+                               else {
+                                       um = resolve_create_unresolved_method(m->clazz, m, fmi,
+                                                       (opcode == BC_invokestatic),
+                                                       (opcode == BC_invokespecial));
+
+                                       if (um == NULL)
+                                               return false;
+
+                                       /* store the unresolved_method pointer */
+
+                                       iptr->sx.s23.s3.um = um;
+                                       iptr->flags.bits |= INS_FLAG_UNRESOLVED;
+                               }
+#if defined(ENABLE_VERIFIER)
+                       }
+#endif
+                       PINC;
+                       break;
+
+               /* instructions taking class arguments ********************************/
+
+               case BC_new:
+                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
+                       cr = (constant_classref*) class_getconstant(m->clazz, i, CONSTANT_Class);
+
+                       if (cr == NULL)
+                               return false;
+
+                       if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
+                               return false;
+
+                       INSTRUCTIONS_CHECK(2);
+                       OP_LOADCONST_CLASSINFO_OR_CLASSREF_NOCHECK(c, cr);
+                       bte = builtintable_get_internal(BUILTIN_new);
+                       OP_BUILTIN_CHECK_EXCEPTION(bte);
+                       s_count++;
+                       break;
+
+               case BC_checkcast:
+                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
+                       cr = (constant_classref*) class_getconstant(m->clazz, i, CONSTANT_Class);
+
+                       if (cr == NULL)
+                               return false;
+
+                       if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
+                               return false;
+
+                       if (cr->name->text[0] == '[') {
+                               /* array type cast-check */
+                               flags = INS_FLAG_CHECK | INS_FLAG_ARRAY;
+                               code_unflag_leafmethod(code);
+                       }
+                       else {
+                               /* object type cast-check */
+                               flags = INS_FLAG_CHECK;
+                       }
+                       OP_S3_CLASSINFO_OR_CLASSREF(opcode, c, cr, flags);
+                       break;
+
+               case BC_instanceof:
+                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
+                       cr = (constant_classref*) class_getconstant(m->clazz, i, CONSTANT_Class);
+
+                       if (cr == NULL)
+                               return false;
+
+                       if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
+                               return false;
+
+                       if (cr->name->text[0] == '[') {
+                               /* array type cast-check */
+                               INSTRUCTIONS_CHECK(2);
+                               OP_LOADCONST_CLASSINFO_OR_CLASSREF_NOCHECK(c, cr);
+                               bte = builtintable_get_internal(BUILTIN_arrayinstanceof);
+                               OP_BUILTIN_NO_EXCEPTION(bte);
+                               s_count++;
+                       }
+                       else {
+                               /* object type cast-check */
+                               OP_S3_CLASSINFO_OR_CLASSREF(opcode, c, cr, 0 /* flags*/);
+                       }
+                       break;
+
+               /* synchronization instructions ***************************************/
+
+               case BC_monitorenter:
+#if defined(ENABLE_THREADS)
+                       if (checksync) {
+                               bte = builtintable_get_internal(LOCK_monitor_enter);
+                               OP_BUILTIN_CHECK_EXCEPTION(bte);
+                       }
+                       else
+#endif
+                       {
+                               OP_CHECK_EXCEPTION(ICMD_CHECKNULL);
+                               OP(ICMD_POP);
+                       }
+                       break;
+
+               case BC_monitorexit:
+#if defined(ENABLE_THREADS)
+                       if (checksync) {
+                               bte = builtintable_get_internal(LOCK_monitor_exit);
+                               OP_BUILTIN_CHECK_EXCEPTION(bte);
+                       }
+                       else
+#endif
+                       {
+                               OP_CHECK_EXCEPTION(ICMD_CHECKNULL);
+                               OP(ICMD_POP);
+                       }
+                       break;
+
+               /* arithmetic instructions that may become builtin functions **********/
+
+               case BC_idiv:
+#if !SUPPORT_DIVISION
+                       bte = builtintable_get_internal(BUILTIN_idiv);
+                       OP_BUILTIN_ARITHMETIC(opcode, bte);
+#else
+# if SUPPORT_HARDWARE_DIVIDE_BY_ZERO
+                       OP(opcode);
+# else
+                       OP_CHECK_EXCEPTION(opcode);
+# endif
+#endif
+                       break;
+
+               case BC_irem:
+#if !SUPPORT_DIVISION
+                       bte = builtintable_get_internal(BUILTIN_irem);
+                       OP_BUILTIN_ARITHMETIC(opcode, bte);
+#else
+# if SUPPORT_HARDWARE_DIVIDE_BY_ZERO
+                       OP(opcode);
+# else
+                       OP_CHECK_EXCEPTION(opcode);
+# endif
+#endif
+                       break;
+
+               case BC_ldiv:
+#if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
+                       bte = builtintable_get_internal(BUILTIN_ldiv);
+                       OP_BUILTIN_ARITHMETIC(opcode, bte);
+#else
+# if SUPPORT_HARDWARE_DIVIDE_BY_ZERO
+                       OP(opcode);
+# else
+                       OP_CHECK_EXCEPTION(opcode);
+# endif
+#endif
+                       break;
+
+               case BC_lrem:
+#if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
+                       bte = builtintable_get_internal(BUILTIN_lrem);
+                       OP_BUILTIN_ARITHMETIC(opcode, bte);
+#else
+# if SUPPORT_HARDWARE_DIVIDE_BY_ZERO
+                       OP(opcode);
+# else
+                       OP_CHECK_EXCEPTION(opcode);
+# endif
+#endif
+                       break;
+
+               case BC_frem:
+#if defined(__I386__)
+                       OP(opcode);
+#else
+                       bte = builtintable_get_internal(BUILTIN_frem);
+                       OP_BUILTIN_NO_EXCEPTION(bte);
+#endif
+                       break;
+
+               case BC_drem:
+#if defined(__I386__)
+                       OP(opcode);
+#else
+                       bte = builtintable_get_internal(BUILTIN_drem);
+                       OP_BUILTIN_NO_EXCEPTION(bte);
+#endif
+                       break;
+
+               case BC_f2i:
+#if defined(__ALPHA__)
+                       bte = builtintable_get_internal(BUILTIN_f2i);
+                       OP_BUILTIN_NO_EXCEPTION(bte);
+#else
+                       OP(opcode);
+#endif
+                       break;
+
+               case BC_f2l:
+#if defined(__ALPHA__)
+                       bte = builtintable_get_internal(BUILTIN_f2l);
+                       OP_BUILTIN_NO_EXCEPTION(bte);
+#else
+                       OP(opcode);
+#endif
+                       break;
+
+               case BC_d2i:
+#if defined(__ALPHA__)
+                       bte = builtintable_get_internal(BUILTIN_d2i);
+                       OP_BUILTIN_NO_EXCEPTION(bte);
+#else
+                       OP(opcode);
+#endif
+                       break;
+
+               case BC_d2l:
+#if defined(__ALPHA__)
+                       bte = builtintable_get_internal(BUILTIN_d2l);
+                       OP_BUILTIN_NO_EXCEPTION(bte);
+#else
+                       OP(opcode);
+#endif
+                       break;
+
+
+               /* invalid opcodes ****************************************************/
+
+                       /* check for invalid opcodes if the verifier is enabled */
+#if defined(ENABLE_VERIFIER)
+               case BC_breakpoint:
+                       exceptions_throw_verifyerror(m, "Quick instructions shouldn't appear, yet.");
+                       return false;
+
+
+               /* Unused opcodes ************************************************** */
+
+               case 186:
+               case 203:
+               case 204:
+               case 205:
+               case 206:
+               case 207:
+               case 208:
+               case 209:
+               case 210:
+               case 211:
+               case 212:
+               case 213:
+               case 214:
+               case 215:
+               case 216:
+               case 217:
+               case 218:
+               case 219:
+               case 220:
+               case 221:
+               case 222:
+               case 223:
+               case 224:
+               case 225:
+               case 226:
+               case 227:
+               case 228:
+               case 229:
+               case 230:
+               case 231:
+               case 232:
+               case 233:
+               case 234:
+               case 235:
+               case 236:
+               case 237:
+               case 238:
+               case 239:
+               case 240:
+               case 241:
+               case 242:
+               case 243:
+               case 244:
+               case 245:
+               case 246:
+               case 247:
+               case 248:
+               case 249:
+               case 250:
+               case 251:
+               case 252:
+               case 253:
+               case 254:
+               case 255:
+                       exceptions_throw_verifyerror(m, "Illegal opcode %d at instr %d\n",
+                                                                                opcode, ircount);
+                       return false;
+                       break;
+#endif /* defined(ENABLE_VERIFIER) */
+
+               /* opcodes that don't require translation *****************************/
+
+               default:
+                       /* Straight-forward translation to HIR. */
+                       OP(opcode);
+                       break;
+
+               } /* end switch */
+
+               /* verifier checks ****************************************************/
+
+#if defined(ENABLE_VERIFIER)
+               /* If WIDE was used correctly, iswide should have been reset by now. */
+               if (iswide) {
+                       exceptions_throw_verifyerror(m,
+                                       "Illegal instruction: WIDE before incompatible opcode");
+                       return false;
+               }
+#endif /* defined(ENABLE_VERIFIER) */
+
+       } /* end for */
+
+       if (JITDATA_HAS_FLAG_REORDER(jd)) {
+               /* add a NOP to the last basic block */
+
+               INSTRUCTIONS_CHECK(1);
+               OP(ICMD_NOP);
+       }
+
+       /*** END OF LOOP **********************************************************/
+
+       /* assert that we did not write more ICMDs than allocated */
+
+       assert(ircount <= pd.instructionslength);
+       assert(ircount == (iptr - pd.instructions));
+
+       /*** verifier checks ******************************************************/
+
+#if defined(ENABLE_VERIFIER)
+       if (bcindex != m->jcodelength) {
+               exceptions_throw_verifyerror(m,
+                               "Command-sequence crosses code-boundary");
+               return false;
+       }
+
+       if (!blockend) {
+               exceptions_throw_verifyerror(m, "Falling off the end of the code");
+               return false;
+       }
+#endif /* defined(ENABLE_VERIFIER) */
+
+       /*** setup the methodinfo, allocate stack and basic blocks ****************/
+
+       /* identify basic blocks */
+
+       /* check if first instruction is a branch target */
+
+       if (pd.basicblockstart[0] == 1) {
+               jd->branchtoentry = true;
+       }
+       else {
+               /* first instruction always starts a basic block */
+
+               iptr = pd.instructions;
+
+               iptr->flags.bits |= INS_FLAG_BASICBLOCK;
+       }
+
+       /* Iterate over all bytecode instructions and set missing
+          basic-block starts in IR instructions. */
+
+       for (bcindex = 0; bcindex < m->jcodelength; bcindex++) {
+               /* Does the current bytecode instruction start a basic
+                  block? */
+
+               if (pd.basicblockstart[bcindex] == 1) {
+#if defined(ENABLE_VERIFIER)
+                       /* Check if this bytecode basic-block start at the
+                          beginning of a bytecode instruction. */
+
+                       if (pd.bytecodestart[bcindex] == 0) {
+                               exceptions_throw_verifyerror(m,
+                                                                                "Branch into middle of instruction");
+                               return false;
+                       }
+#endif
+
+                       /* Get the IR instruction mapped to the bytecode
+                          instruction and set the basic block flag. */
+
+                       irindex = pd.bytecodemap[bcindex];
+                       iptr    = pd.instructions + irindex;
+
+                       iptr->flags.bits |= INS_FLAG_BASICBLOCK;
+               }
+       }
+
+       /* IR instruction index to basic-block index mapping */
+
+       pd.instructionmap = (s4*) DumpMemory::allocate(sizeof(s4) * ircount);
+       MZERO(pd.instructionmap, s4, ircount);
+
+       /* Iterate over all IR instructions and count the basic blocks. */
+
+       iptr = pd.instructions;
+
+       bbcount = 0;
+
+       for (i = 0; i < ircount; i++, iptr++) {
+               if (INSTRUCTION_STARTS_BASICBLOCK(iptr)) {
+                       /* store the basic-block number in the IR instruction
+                          map */
+
+                       pd.instructionmap[i] = bbcount;
+
+                       /* post-increment the basic-block count */
+
+                       bbcount++;
+               }
+       }
+
+       /* Allocate basic block array (one more for end ipc). */
+
+       jd->basicblocks = (basicblock*) DumpMemory::allocate(sizeof(basicblock) * (bbcount + 1));
+       MZERO(jd->basicblocks, basicblock, bbcount + 1);
+
+       /* Now iterate again over all IR instructions and initialize the
+          basic block structures and, in the same loop, resolve the
+          branch-target instruction indices to basic blocks. */
+
+       iptr = pd.instructions;
+       bptr = jd->basicblocks;
+
+       bbcount = 0;
+
+       for (i = 0; i < ircount; i++, iptr++) {
+               /* check for basic block */
+
+               if (INSTRUCTION_STARTS_BASICBLOCK(iptr)) {
+                       /* intialize the basic block */
+
+                       BASICBLOCK_INIT(bptr, m);
+
+                       bptr->iinstr = iptr;
+
+                       if (bbcount > 0) {
+                               bptr[-1].icount = bptr->iinstr - bptr[-1].iinstr;
+                       }
+
+                       /* bptr->icount is set when the next block is allocated */
+
+                       bptr->nr = bbcount++;
+                       bptr++;
+                       bptr[-1].next = bptr;
+               }
+
+               /* resolve instruction indices to basic blocks */
+
+               switch (iptr->opc) {
+               case ICMD_IFEQ:
+               case ICMD_IFLT:
+               case ICMD_IFLE:
+               case ICMD_IFNE:
+               case ICMD_IFGT:
+               case ICMD_IFGE:
+               case ICMD_IFNULL:
+               case ICMD_IFNONNULL:
+               case ICMD_IF_ICMPEQ:
+               case ICMD_IF_ICMPNE:
+               case ICMD_IF_ICMPLT:
+               case ICMD_IF_ICMPGT:
+               case ICMD_IF_ICMPLE:
+               case ICMD_IF_ICMPGE:
+               case ICMD_IF_ACMPEQ:
+               case ICMD_IF_ACMPNE:
+               case ICMD_GOTO:
+                       BYTECODEINDEX_TO_BASICBLOCK(iptr->dst);
+                       break;
+
+               case ICMD_JSR:
+                       BYTECODEINDEX_TO_BASICBLOCK(iptr->sx.s23.s3.jsrtarget);
+                       break;
+
+               case ICMD_TABLESWITCH:
+                       table = iptr->dst.table;
+
+                       BYTECODEINDEX_TO_BASICBLOCK(*table);
+                       table++;
+
+                       j = iptr->sx.s23.s3.tablehigh - iptr->sx.s23.s2.tablelow + 1;
+
+                       while (--j >= 0) {
+                               BYTECODEINDEX_TO_BASICBLOCK(*table);
+                               table++;
+                       }
+                       break;
+
+               case ICMD_LOOKUPSWITCH:
+                       BYTECODEINDEX_TO_BASICBLOCK(iptr->sx.s23.s3.lookupdefault);
+
+                       lookup = iptr->dst.lookup;
+
+                       j = iptr->sx.s23.s2.lookupcount;
+
+                       while (--j >= 0) {
+                               BYTECODEINDEX_TO_BASICBLOCK(lookup->target);
+                               lookup++;
+                       }
+                       break;
+               }
+       }
+
+       /* set instruction count of last real block */
+
+       if (bbcount > 0) {
+               bptr[-1].icount = (pd.instructions + ircount) - bptr[-1].iinstr;
+       }
+
+       /* allocate additional block at end */
+
+       BASICBLOCK_INIT(bptr, m);
+       bptr->nr = bbcount;
+
+       /* set basicblock pointers in exception table */
+
+       if (!parse_resolve_exception_table(jd, &pd))
+               return false;
+
+       /* store the local map */
+
+       jd->local_map = local_map;
+
+       /* calculate local variable renaming */
+
+       {
+               s4 nlocals = 0;
+               s4 i;
+               s4 t;
+               s4 varindex;
+               s4 *mapptr;
+               s4 *reversemap;
+
+               mapptr = local_map;
+
+               /* iterate over local_map[0..m->maxlocals*5-1] and allocate a unique */
+               /* variable index for each _used_ (javaindex,type) pair.             */
+               /* (local_map[javaindex*5+type] = cacaoindex)                        */
+               /* Unused (javaindex,type) pairs are marked with UNUSED.             */
+
+               for (i = 0; i < (m->maxlocals * 5); i++, mapptr++) {
+                       if (*mapptr)
+                               *mapptr = nlocals++;
+                       else
+                               *mapptr = UNUSED;
+               }
+
+               jd->localcount = nlocals;
+
+               /* calculate the (maximum) number of variables needed */
+
+               jd->varcount = 
+                         nlocals                                      /* local variables */
+                       + bbcount * m->maxstack                                 /* invars */
+                       + s_count;         /* variables created within blocks (non-invar) */
+
+               /* reserve the first indices for local variables */
+
+               jd->vartop = nlocals;
+
+               /* reserve extra variables needed by stack analyse */
+
+               jd->varcount += STACK_EXTRA_VARS;
+               jd->vartop   += STACK_EXTRA_VARS;
+
+               /* The verifier needs space for saving invars in some cases and */
+               /* extra variables.                                             */
+
+#if defined(ENABLE_VERIFIER)
+               jd->varcount += VERIFIER_EXTRA_LOCALS + VERIFIER_EXTRA_VARS + m->maxstack;
+               jd->vartop   += VERIFIER_EXTRA_LOCALS + VERIFIER_EXTRA_VARS + m->maxstack;
+#endif
+               /* allocate and initialize the variable array */
+
+               jd->var = (varinfo*) DumpMemory::allocate(sizeof(varinfo) * jd->varcount);
+               MZERO(jd->var, varinfo, jd->varcount);
+
+               /* set types of all locals in jd->var */
+               /* and fill the reverselocalmap       */
+
+               reversemap = (s4*) DumpMemory::allocate(sizeof(s4) * nlocals);
+
+               for (i = 0; i < m->maxlocals; i++)
+                       for (t=0; t<5; t++) {
+                               varindex = local_map[5*i + t];
+                               if (varindex != UNUSED) {
+                                       VAR(varindex)->type = t;
+                                       reversemap[varindex] = i;
+                               }
+                       }
+
+               jd->reverselocalmap = reversemap;
+       }
+
+       /* assign local variables to method variables */
+
+       jd->instructions     = pd.instructions;
+       jd->instructioncount = ircount;
+       jd->basicblockcount  = bbcount;
+       jd->stackcount       = s_count + bbcount * m->maxstack; /* in-stacks */
+
+       /* allocate stack table */
+
+       jd->stack = (stackelement_t*) DumpMemory::allocate(sizeof(stackelement_t) * jd->stackcount);
+
+       /* everything's ok */
+
+       return true;
+
+       /*** goto labels for throwing verifier exceptions *************************/
+
+#if defined(ENABLE_VERIFIER)
+
+throw_unexpected_end_of_bytecode:
+       exceptions_throw_verifyerror(m, "Unexpected end of bytecode");
+       return false;
+
+throw_invalid_bytecode_index:
+       exceptions_throw_verifyerror(m, "Illegal target of branch instruction");
+       return false;
+
+throw_illegal_local_variable_number:
+       exceptions_throw_verifyerror(m, "Illegal local variable number");
+       return false;
+
+#endif /* ENABLE_VERIFIER */
+}
+
+#if defined(__cplusplus)
+}
+#endif
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
diff --git a/src/vm/jit/parse.h b/src/vm/jit/parse.h
deleted file mode 100644 (file)
index b10d7da..0000000
+++ /dev/null
@@ -1,298 +0,0 @@
-/* src/vm/jit/parse.h - parser header
-
-   Copyright (C) 1996-2005, 2006, 2008
-   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
-   This file is part of CACAO.
-
-   This program 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 2, or (at
-   your option) any later version.
-
-   This program 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 this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.
-
-*/
-
-
-#ifndef _PARSE_H
-#define _PARSE_H
-
-#include "config.h"
-#include "vm/types.h"
-
-#include "vm/global.h"
-#include "vm/jit/codegen-common.hpp"
-
-
-/* macros for verifier checks during parsing **********************************/
-
-#if defined(ENABLE_VERIFIER)
-
-/* We have to check local variables indices here because they are             */
-/* used in stack.c to index the locals array.                                 */
-
-#define INDEX_ONEWORD(num) \
-    do { \
-        if (((num) < 0) || ((num) >= m->maxlocals)) \
-            goto throw_illegal_local_variable_number; \
-    } while (0)
-
-#define INDEX_TWOWORD(num) \
-    do { \
-        if (((num) < 0) || (((num) + 1) >= m->maxlocals)) \
-            goto throw_illegal_local_variable_number; \
-    } while (0)
-
-/* CHECK_BYTECODE_INDEX(i) checks whether i is a valid bytecode index.        */
-/* The end of the bytecode (i == m->jcodelength) is considered valid.         */
-
-#define CHECK_BYTECODE_INDEX(i) \
-    do { \
-        if (((i) < 0) || ((i) >= m->jcodelength)) \
-                       goto throw_invalid_bytecode_index; \
-    } while (0)
-
-/* CHECK_BYTECODE_INDEX_EXCLUSIVE is used for the exclusive ends               */
-/* of exception handler ranges.                                                */
-#define CHECK_BYTECODE_INDEX_EXCLUSIVE(i) \
-    do { \
-        if ((i) < 0 || (i) > m->jcodelength) \
-                       goto throw_invalid_bytecode_index; \
-    } while (0)
-
-#else /* !defined(ENABLE_VERIFIER) */
-
-#define INDEX_ONEWORD(num)
-#define INDEX_TWOWORD(num)
-#define CHECK_BYTECODE_INDEX(i)
-#define CHECK_BYTECODE_INDEX_EXCLUSIVE(i)
-
-#endif /* defined(ENABLE_VERIFIER) */
-
-
-/* basic block generating macro ***********************************************/
-
-#define MARK_BASICBLOCK(pd, i)                                       \
-    do {                                                             \
-        (pd)->basicblockstart[(i)] = 1;                              \
-    } while (0)
-
-#define INSTRUCTIONS_CHECK(i)                                        \
-    if ((ircount + (i)) > pd.instructionslength)                     \
-        iptr = parse_realloc_instructions(&pd, ircount, (i))
-
-
-/* intermediate code generating macros ****************************************/
-
-/* These macros ALWAYS set the following fields of *iptr to valid values:     */
-/*     iptr->opc                                                              */
-/*     iptr->flags                                                            */
-/*     iptr->line                                                             */
-
-/* These macros do NOT touch the following fields of *iptr, unless a value is */
-/* given for them:                                                            */
-/*     iptr->s1                                                               */
-/*     iptr->sx                                                               */
-/*     iptr->dst                                                              */
-
-/* The _PREPARE macros omit the PINC, so you can set additional fields        */
-/* afterwards.                                                                */
-
-#define PINC                                                         \
-    iptr++; ircount++
-
-#define OP_PREPARE_FLAGS(o, f)                                       \
-    iptr->opc         = (o);                                         \
-    iptr->line        = currentline;                                 \
-    iptr->flags.bits |= (f) | (ircount << INS_FLAG_ID_SHIFT);
-
-#define OP_PREPARE_ZEROFLAGS(o)                                      \
-    OP_PREPARE_FLAGS(o, 0)
-
-#define OP_PREPARE(o)                                                \
-    OP_PREPARE_ZEROFLAGS(o)
-
-#define OP(o)                                                        \
-    OP_PREPARE_ZEROFLAGS(o);                                         \
-    PINC
-
-#define OP_CHECK_EXCEPTION(o)                                        \
-    OP_PREPARE_FLAGS(o, INS_FLAG_CHECK);                             \
-    PINC
-
-#define OP_LOADCONST_I(v)                                            \
-    OP_PREPARE_ZEROFLAGS(ICMD_ICONST);                               \
-    iptr->sx.val.i           = (v);                                  \
-    PINC
-
-#define OP_LOADCONST_L(v)                                            \
-    OP_PREPARE_ZEROFLAGS(ICMD_LCONST);                               \
-    iptr->sx.val.l           = (v);                                  \
-    PINC
-
-#define OP_LOADCONST_F(v)                                            \
-    OP_PREPARE_ZEROFLAGS(ICMD_FCONST);                               \
-    iptr->sx.val.f           = (v);                                  \
-    PINC
-
-#define OP_LOADCONST_D(v)                                            \
-    OP_PREPARE_ZEROFLAGS(ICMD_DCONST);                               \
-    iptr->sx.val.d           = (v);                                  \
-    PINC
-
-#define OP_LOADCONST_NULL()                                          \
-    OP_PREPARE_FLAGS(ICMD_ACONST, INS_FLAG_CHECK);                   \
-    iptr->sx.val.anyptr      = NULL;                                 \
-    PINC
-
-#define OP_LOADCONST_STRING(v)                                       \
-    OP_PREPARE_FLAGS(ICMD_ACONST, INS_FLAG_CHECK);                   \
-    iptr->sx.val.stringconst = (v);                                  \
-    PINC
-
-#define OP_LOADCONST_CLASSINFO_OR_CLASSREF_FLAGS(cl, cr, extraflags) \
-    OP_PREPARE(ICMD_ACONST);                                         \
-    if (cl) {                                                        \
-        iptr->sx.val.c.cls   = (cl);                                 \
-        iptr->flags.bits     |= INS_FLAG_CLASS | (extraflags);       \
-    }                                                                \
-    else {                                                           \
-        iptr->sx.val.c.ref   = (cr);                                 \
-        iptr->flags.bits     |= INS_FLAG_CLASS | INS_FLAG_UNRESOLVED \
-                             | (extraflags);                         \
-    }                                                                \
-    PINC
-
-#define OP_LOADCONST_CLASSINFO_OR_CLASSREF_CHECK(c, cr)              \
-    OP_LOADCONST_CLASSINFO_OR_CLASSREF_FLAGS((c), (cr), INS_FLAG_CHECK)
-
-#define OP_LOADCONST_CLASSINFO_OR_CLASSREF_NOCHECK(c, cr)            \
-    OP_LOADCONST_CLASSINFO_OR_CLASSREF_FLAGS((c), (cr), 0)
-
-#define OP_S3_CLASSINFO_OR_CLASSREF(o, c, cr, extraflags)            \
-    OP_PREPARE(o);                                                   \
-    if (c) {                                                         \
-        iptr->sx.s23.s3.c.cls= (c);                                  \
-        iptr->flags.bits     |= (extraflags);                        \
-    }                                                                \
-    else {                                                           \
-        iptr->sx.s23.s3.c.ref= (cr);                                 \
-        iptr->flags.bits     |= INS_FLAG_UNRESOLVED | (extraflags);  \
-    }                                                                \
-    PINC
-
-#define OP_INSINDEX(o, iindex)                                       \
-    OP_PREPARE_ZEROFLAGS(o);                                         \
-    iptr->dst.insindex       = (iindex);                             \
-    PINC
-
-# define OP_LOCALINDEX(o,index)                                      \
-    OP_PREPARE_ZEROFLAGS(o);                                         \
-    iptr->s1.varindex      = (index);                                \
-    PINC
-
-# define OP_LOCALINDEX_I(o,index,v)                                  \
-    OP_PREPARE_ZEROFLAGS(o);                                         \
-    iptr->s1.varindex      = (index);                                \
-    iptr->sx.val.i           = (v);                                  \
-    PINC
-
-# define LOCALTYPE_USED(index,type)                                  \
-    do {                                                             \
-        local_map[(index) * 5 + (type)] = 1;                         \
-    } while (0)
-
-#define OP_LOAD_ONEWORD(o,index,type)                                \
-    do {                                                             \
-        INDEX_ONEWORD(index);                                        \
-        OP_LOCALINDEX(o,index);                                      \
-        LOCALTYPE_USED(index,type);                                  \
-    } while (0)
-
-#define OP_LOAD_TWOWORD(o,index,type)                                \
-    do {                                                             \
-        INDEX_TWOWORD(index);                                        \
-        OP_LOCALINDEX(o,index);                                      \
-        LOCALTYPE_USED(index,type);                                  \
-    } while (0)
-
-# define OP_STORE_ONEWORD(o,index,type)                              \
-    do {                                                             \
-        INDEX_ONEWORD(index);                                        \
-        OP_PREPARE_ZEROFLAGS(o);                                     \
-        iptr->dst.varindex = (index);                                \
-        LOCALTYPE_USED(index,type);                                  \
-        PINC;                                                        \
-    } while (0)
-
-# define OP_STORE_TWOWORD(o,index,type)                              \
-    do {                                                             \
-        INDEX_TWOWORD(index);                                        \
-        OP_PREPARE_ZEROFLAGS(o);                                     \
-        iptr->dst.varindex = (index);                                \
-        LOCALTYPE_USED(index,type);                                  \
-        PINC;                                                        \
-    } while (0)
-
-#define OP_BUILTIN_CHECK_EXCEPTION(bte)                              \
-    code_unflag_leafmethod(code);                                    \
-    OP_PREPARE_FLAGS(ICMD_BUILTIN, INS_FLAG_CHECK);                  \
-    iptr->sx.s23.s3.bte      = (bte);                                \
-    PINC
-
-#define OP_BUILTIN_NO_EXCEPTION(bte)                                 \
-    code_unflag_leafmethod(code);                                    \
-    OP_PREPARE_ZEROFLAGS(ICMD_BUILTIN);                              \
-    iptr->sx.s23.s3.bte      = (bte);                                \
-    PINC
-
-#define OP_BUILTIN_ARITHMETIC(opcode, bte)                           \
-    code_unflag_leafmethod(code);                                    \
-    OP_PREPARE_FLAGS(opcode, INS_FLAG_CHECK);                        \
-    iptr->sx.s23.s3.bte      = (bte);                                \
-    PINC
-
-/* CAUTION: You must set iptr->flags yourself when using this!                */
-#define OP_FMIREF_PREPARE(o, fmiref)                                 \
-    OP_PREPARE(o);                                                   \
-    iptr->sx.s23.s3.fmiref   = (fmiref);
-
-
-/* function prototypes ********************************************************/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-bool parse(jitdata *jd);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _PARSE_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
-
diff --git a/src/vm/jit/parse.hpp b/src/vm/jit/parse.hpp
new file mode 100644 (file)
index 0000000..b10d7da
--- /dev/null
@@ -0,0 +1,298 @@
+/* src/vm/jit/parse.h - parser header
+
+   Copyright (C) 1996-2005, 2006, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+   This file is part of CACAO.
+
+   This program 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 2, or (at
+   your option) any later version.
+
+   This program 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 this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+*/
+
+
+#ifndef _PARSE_H
+#define _PARSE_H
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "vm/global.h"
+#include "vm/jit/codegen-common.hpp"
+
+
+/* macros for verifier checks during parsing **********************************/
+
+#if defined(ENABLE_VERIFIER)
+
+/* We have to check local variables indices here because they are             */
+/* used in stack.c to index the locals array.                                 */
+
+#define INDEX_ONEWORD(num) \
+    do { \
+        if (((num) < 0) || ((num) >= m->maxlocals)) \
+            goto throw_illegal_local_variable_number; \
+    } while (0)
+
+#define INDEX_TWOWORD(num) \
+    do { \
+        if (((num) < 0) || (((num) + 1) >= m->maxlocals)) \
+            goto throw_illegal_local_variable_number; \
+    } while (0)
+
+/* CHECK_BYTECODE_INDEX(i) checks whether i is a valid bytecode index.        */
+/* The end of the bytecode (i == m->jcodelength) is considered valid.         */
+
+#define CHECK_BYTECODE_INDEX(i) \
+    do { \
+        if (((i) < 0) || ((i) >= m->jcodelength)) \
+                       goto throw_invalid_bytecode_index; \
+    } while (0)
+
+/* CHECK_BYTECODE_INDEX_EXCLUSIVE is used for the exclusive ends               */
+/* of exception handler ranges.                                                */
+#define CHECK_BYTECODE_INDEX_EXCLUSIVE(i) \
+    do { \
+        if ((i) < 0 || (i) > m->jcodelength) \
+                       goto throw_invalid_bytecode_index; \
+    } while (0)
+
+#else /* !defined(ENABLE_VERIFIER) */
+
+#define INDEX_ONEWORD(num)
+#define INDEX_TWOWORD(num)
+#define CHECK_BYTECODE_INDEX(i)
+#define CHECK_BYTECODE_INDEX_EXCLUSIVE(i)
+
+#endif /* defined(ENABLE_VERIFIER) */
+
+
+/* basic block generating macro ***********************************************/
+
+#define MARK_BASICBLOCK(pd, i)                                       \
+    do {                                                             \
+        (pd)->basicblockstart[(i)] = 1;                              \
+    } while (0)
+
+#define INSTRUCTIONS_CHECK(i)                                        \
+    if ((ircount + (i)) > pd.instructionslength)                     \
+        iptr = parse_realloc_instructions(&pd, ircount, (i))
+
+
+/* intermediate code generating macros ****************************************/
+
+/* These macros ALWAYS set the following fields of *iptr to valid values:     */
+/*     iptr->opc                                                              */
+/*     iptr->flags                                                            */
+/*     iptr->line                                                             */
+
+/* These macros do NOT touch the following fields of *iptr, unless a value is */
+/* given for them:                                                            */
+/*     iptr->s1                                                               */
+/*     iptr->sx                                                               */
+/*     iptr->dst                                                              */
+
+/* The _PREPARE macros omit the PINC, so you can set additional fields        */
+/* afterwards.                                                                */
+
+#define PINC                                                         \
+    iptr++; ircount++
+
+#define OP_PREPARE_FLAGS(o, f)                                       \
+    iptr->opc         = (o);                                         \
+    iptr->line        = currentline;                                 \
+    iptr->flags.bits |= (f) | (ircount << INS_FLAG_ID_SHIFT);
+
+#define OP_PREPARE_ZEROFLAGS(o)                                      \
+    OP_PREPARE_FLAGS(o, 0)
+
+#define OP_PREPARE(o)                                                \
+    OP_PREPARE_ZEROFLAGS(o)
+
+#define OP(o)                                                        \
+    OP_PREPARE_ZEROFLAGS(o);                                         \
+    PINC
+
+#define OP_CHECK_EXCEPTION(o)                                        \
+    OP_PREPARE_FLAGS(o, INS_FLAG_CHECK);                             \
+    PINC
+
+#define OP_LOADCONST_I(v)                                            \
+    OP_PREPARE_ZEROFLAGS(ICMD_ICONST);                               \
+    iptr->sx.val.i           = (v);                                  \
+    PINC
+
+#define OP_LOADCONST_L(v)                                            \
+    OP_PREPARE_ZEROFLAGS(ICMD_LCONST);                               \
+    iptr->sx.val.l           = (v);                                  \
+    PINC
+
+#define OP_LOADCONST_F(v)                                            \
+    OP_PREPARE_ZEROFLAGS(ICMD_FCONST);                               \
+    iptr->sx.val.f           = (v);                                  \
+    PINC
+
+#define OP_LOADCONST_D(v)                                            \
+    OP_PREPARE_ZEROFLAGS(ICMD_DCONST);                               \
+    iptr->sx.val.d           = (v);                                  \
+    PINC
+
+#define OP_LOADCONST_NULL()                                          \
+    OP_PREPARE_FLAGS(ICMD_ACONST, INS_FLAG_CHECK);                   \
+    iptr->sx.val.anyptr      = NULL;                                 \
+    PINC
+
+#define OP_LOADCONST_STRING(v)                                       \
+    OP_PREPARE_FLAGS(ICMD_ACONST, INS_FLAG_CHECK);                   \
+    iptr->sx.val.stringconst = (v);                                  \
+    PINC
+
+#define OP_LOADCONST_CLASSINFO_OR_CLASSREF_FLAGS(cl, cr, extraflags) \
+    OP_PREPARE(ICMD_ACONST);                                         \
+    if (cl) {                                                        \
+        iptr->sx.val.c.cls   = (cl);                                 \
+        iptr->flags.bits     |= INS_FLAG_CLASS | (extraflags);       \
+    }                                                                \
+    else {                                                           \
+        iptr->sx.val.c.ref   = (cr);                                 \
+        iptr->flags.bits     |= INS_FLAG_CLASS | INS_FLAG_UNRESOLVED \
+                             | (extraflags);                         \
+    }                                                                \
+    PINC
+
+#define OP_LOADCONST_CLASSINFO_OR_CLASSREF_CHECK(c, cr)              \
+    OP_LOADCONST_CLASSINFO_OR_CLASSREF_FLAGS((c), (cr), INS_FLAG_CHECK)
+
+#define OP_LOADCONST_CLASSINFO_OR_CLASSREF_NOCHECK(c, cr)            \
+    OP_LOADCONST_CLASSINFO_OR_CLASSREF_FLAGS((c), (cr), 0)
+
+#define OP_S3_CLASSINFO_OR_CLASSREF(o, c, cr, extraflags)            \
+    OP_PREPARE(o);                                                   \
+    if (c) {                                                         \
+        iptr->sx.s23.s3.c.cls= (c);                                  \
+        iptr->flags.bits     |= (extraflags);                        \
+    }                                                                \
+    else {                                                           \
+        iptr->sx.s23.s3.c.ref= (cr);                                 \
+        iptr->flags.bits     |= INS_FLAG_UNRESOLVED | (extraflags);  \
+    }                                                                \
+    PINC
+
+#define OP_INSINDEX(o, iindex)                                       \
+    OP_PREPARE_ZEROFLAGS(o);                                         \
+    iptr->dst.insindex       = (iindex);                             \
+    PINC
+
+# define OP_LOCALINDEX(o,index)                                      \
+    OP_PREPARE_ZEROFLAGS(o);                                         \
+    iptr->s1.varindex      = (index);                                \
+    PINC
+
+# define OP_LOCALINDEX_I(o,index,v)                                  \
+    OP_PREPARE_ZEROFLAGS(o);                                         \
+    iptr->s1.varindex      = (index);                                \
+    iptr->sx.val.i           = (v);                                  \
+    PINC
+
+# define LOCALTYPE_USED(index,type)                                  \
+    do {                                                             \
+        local_map[(index) * 5 + (type)] = 1;                         \
+    } while (0)
+
+#define OP_LOAD_ONEWORD(o,index,type)                                \
+    do {                                                             \
+        INDEX_ONEWORD(index);                                        \
+        OP_LOCALINDEX(o,index);                                      \
+        LOCALTYPE_USED(index,type);                                  \
+    } while (0)
+
+#define OP_LOAD_TWOWORD(o,index,type)                                \
+    do {                                                             \
+        INDEX_TWOWORD(index);                                        \
+        OP_LOCALINDEX(o,index);                                      \
+        LOCALTYPE_USED(index,type);                                  \
+    } while (0)
+
+# define OP_STORE_ONEWORD(o,index,type)                              \
+    do {                                                             \
+        INDEX_ONEWORD(index);                                        \
+        OP_PREPARE_ZEROFLAGS(o);                                     \
+        iptr->dst.varindex = (index);                                \
+        LOCALTYPE_USED(index,type);                                  \
+        PINC;                                                        \
+    } while (0)
+
+# define OP_STORE_TWOWORD(o,index,type)                              \
+    do {                                                             \
+        INDEX_TWOWORD(index);                                        \
+        OP_PREPARE_ZEROFLAGS(o);                                     \
+        iptr->dst.varindex = (index);                                \
+        LOCALTYPE_USED(index,type);                                  \
+        PINC;                                                        \
+    } while (0)
+
+#define OP_BUILTIN_CHECK_EXCEPTION(bte)                              \
+    code_unflag_leafmethod(code);                                    \
+    OP_PREPARE_FLAGS(ICMD_BUILTIN, INS_FLAG_CHECK);                  \
+    iptr->sx.s23.s3.bte      = (bte);                                \
+    PINC
+
+#define OP_BUILTIN_NO_EXCEPTION(bte)                                 \
+    code_unflag_leafmethod(code);                                    \
+    OP_PREPARE_ZEROFLAGS(ICMD_BUILTIN);                              \
+    iptr->sx.s23.s3.bte      = (bte);                                \
+    PINC
+
+#define OP_BUILTIN_ARITHMETIC(opcode, bte)                           \
+    code_unflag_leafmethod(code);                                    \
+    OP_PREPARE_FLAGS(opcode, INS_FLAG_CHECK);                        \
+    iptr->sx.s23.s3.bte      = (bte);                                \
+    PINC
+
+/* CAUTION: You must set iptr->flags yourself when using this!                */
+#define OP_FMIREF_PREPARE(o, fmiref)                                 \
+    OP_PREPARE(o);                                                   \
+    iptr->sx.s23.s3.fmiref   = (fmiref);
+
+
+/* function prototypes ********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool parse(jitdata *jd);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PARSE_H */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
+
index c7431f8093f8e55f21936929a789a482a51a3352..dcfc0482e276bfe38417c7cbebd7ecc8ca58ab41 100644 (file)
@@ -59,7 +59,7 @@
 #include "vm/jit/jit.hpp"
 #include "vm/jit/linenumbertable.hpp"
 #include "vm/jit/methodheader.h"
-#include "vm/jit/parse.h"
+#include "vm/jit/parse.hpp"
 #include "vm/jit/patcher-common.hpp"
 #include "vm/jit/reg.h"
 #include "vm/jit/replace.hpp"
index 64855d6dd251ea2f17006d65f4b63c5df5890590..6de89aaf0b6c5c16d65127a5f882d02e4e68a968 100644 (file)
@@ -59,7 +59,7 @@
 #include "vm/jit/emit-common.hpp"
 #include "vm/jit/jit.hpp"
 #include "vm/jit/linenumbertable.hpp"
-#include "vm/jit/parse.h"
+#include "vm/jit/parse.hpp"
 #include "vm/jit/patcher-common.hpp"
 #include "vm/jit/reg.h"
 #include "vm/jit/replace.hpp"
index 7db818cadc79711f99fd64de3a56a1a58bc99968..f69e661fb8f8a64fc5a4d8cccc5442923820b369 100644 (file)
@@ -61,7 +61,7 @@
 #include "vm/jit/jit.hpp"
 #include "vm/jit/linenumbertable.hpp"
 #include "vm/jit/methodheader.h"
-#include "vm/jit/parse.h"
+#include "vm/jit/parse.hpp"
 #include "vm/jit/patcher-common.hpp"
 #include "vm/jit/reg.h"
 #include "vm/jit/replace.hpp"
index d4dad98c7c069427575e10ea835afc917db2e0b7..e0ba2a3cfaa9de1257e145af3606709e6216a40f 100644 (file)
@@ -45,7 +45,7 @@
 #include "vm/jit/show.hpp"
 #include "vm/jit/disass.h"
 #include "vm/jit/stack.h"
-#include "vm/jit/parse.h"
+#include "vm/jit/parse.hpp"
 
 #if defined(ENABLE_DEBUG_FILTER)
 # include <sys/types.h>
index dc0533c2f168d57ad763271470760dc948e16f50..b048fbe3272e933413752b0fe8aa8da7966f299d 100644 (file)
@@ -55,7 +55,7 @@
 #include "vm/jit/emit-common.hpp"
 #include "vm/jit/jit.hpp"
 #include "vm/jit/linenumbertable.hpp"
-#include "vm/jit/parse.h"
+#include "vm/jit/parse.hpp"
 #include "vm/jit/patcher.h"
 #include "vm/jit/reg.h"
 #include "vm/jit/replace.hpp"
index 2420c649f79d1b71c6623dcc486eeffdc7692436..8c7ad97c3c9bab8c95dca5327998f05532f08eeb 100644 (file)
@@ -54,7 +54,7 @@
 #include "vm/jit/abi.h"
 #include "vm/jit/cfg.h"
 #include "vm/jit/codegen-common.hpp"
-#include "vm/jit/parse.h"
+#include "vm/jit/parse.hpp"
 #include "vm/jit/show.hpp"
 
 #if defined(ENABLE_DISASSEMBLER)
index b978516b5f6a33422dbcbfab09b5c6b62908d07b..7056142f0d24768e7846255d313c05861ac32209 100644 (file)
@@ -38,7 +38,7 @@
 #include "vm/globals.hpp"
 #include "vm/primitive.hpp"
 
-#include "vm/jit/parse.h"
+#include "vm/jit/parse.hpp"
 #include "vm/jit/show.hpp"
 #include "vm/jit/stack.h"
 #include "vm/jit/verify/typecheck-common.h"
index 8dfbd4f747ae4e9669836b2334cbc6ef72d3393b..60af00882e08f5cf3055db0d986147fd107380ab 100644 (file)
@@ -48,7 +48,7 @@
 
 #include "vm/jit/jit.hpp"
 #include "vm/jit/show.hpp"
-#include "vm/jit/parse.h"
+#include "vm/jit/parse.hpp"
 
 #include "vm/jit/verify/typecheck-typeinferer.h"
 
index 842f89f16eb2927b608bb9be83505e432777c613..00e3cfdea6226839a867092752a4ba86cf93d906 100644 (file)
@@ -159,7 +159,7 @@ error reporting.
 #include "vm/resolve.hpp"
 
 #include "vm/jit/jit.hpp"
-#include "vm/jit/parse.h"
+#include "vm/jit/parse.hpp"
 #include "vm/jit/show.hpp"
 
 #include <typecheck-common.h>
index ff7bf884adf8c04bf84fa4e75f8dba34c68e03af..96f4967bc9f052f7a74ea741adf8dee33a2389bd 100644 (file)
@@ -63,7 +63,7 @@
 #include "vm/jit/jit.hpp"
 #include "vm/jit/linenumbertable.hpp"
 #include "vm/jit/methodheader.h"
-#include "vm/jit/parse.h"
+#include "vm/jit/parse.hpp"
 #include "vm/jit/patcher-common.hpp"
 #include "vm/jit/reg.h"
 #include "vm/jit/replace.hpp"