-/* 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:
- */