src/vm/jit/parse.hpp: Moved to C++.
--HG--
rename : src/vm/jit/parse.c => src/vm/jit/parse.cpp
rename : src/vm/jit/parse.h => src/vm/jit/parse.hpp
-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'.
linenumbertable.hpp \
methodtree.c \
methodtree.h \
- parse.c \
- parse.h \
+ parse.cpp \
+ parse.hpp \
patcher-common.cpp \
patcher-common.hpp \
$(RECOMPILE_SOURCES) \
#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"
#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"
#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"
#include "vm/statistics.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"
#include "vm/jit/stack.h"
#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"
#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"
#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"
+++ /dev/null
-/* 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:
- */
--- /dev/null
+/* 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:
+ */
+++ /dev/null
-/* 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:
- */
-
--- /dev/null
+/* 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:
+ */
+
#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"
#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"
#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"
#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>
#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"
#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)
#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"
#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"
#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>
#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"