/* src/vm/jit/parse.c - parser for JavaVM to intermediate code translation
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- $Id: parse.c 7629 2007-04-02 19:45:20Z twisti $
-
*/
#include "vm/types.h"
#include "mm/memory.h"
-#include "native/native.h"
-#if defined(ENABLE_THREADS)
-# include "threads/native/lock.h"
-#endif
+#include "native/native.hpp"
+
+#include "threads/lock.hpp"
#include "toolbox/logging.h"
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
+#include "vm/jit/builtin.hpp"
+#include "vm/exceptions.hpp"
#include "vm/global.h"
-#include "vm/stringlocal.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.h"
+#include "vm/jit/jit.hpp"
#include "vm/jit/parse.h"
-#include "vm/jit/patcher.h"
#include "vm/jit/loop/loop.h"
-#include "vmcore/linker.h"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-#include "vm/resolve.h"
-
-#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
-#endif
+#include "vm/jit/ir/bytecode.h"
-#include "vmcore/suck.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 */
- u1 *instructionstart;
+
+ s4 *instructionmap; /* IR to basic-block mapping */
};
m = jd->m;
- /* Allocate instruction array and block index table (1 additional
- for end ipc). */
+ /* bytecode start array */
- jd->basicblockindex = DMNEW(s4, m->jcodelength + 1);
- pd->instructionstart = DMNEW(u1, m->jcodelength + 1);
+ pd->bytecodestart = DMNEW(u1, m->jcodelength + 1);
+ MZERO(pd->bytecodestart, u1, m->jcodelength + 1);
- MZERO(jd->basicblockindex, s4, m->jcodelength + 1);
- MZERO(pd->instructionstart, u1, m->jcodelength + 1);
+ /* bytecode basic-block start array */
- /* Set the length of the instruction array. We simply add 5 more
- instruction, as this seems to be a reasonable value. */
+ pd->basicblockstart = DMNEW(u1, m->jcodelength + 1);
+ MZERO(pd->basicblockstart, u1, m->jcodelength + 1);
- pd->instructionslength = 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_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
jd...............current jitdata
RETURN VALUE:
- >= 0.............the number of new basic blocks marked
- -1...............an exception has been thrown
+ true.............everything ok
+ false............an exception has been thrown
*******************************************************************************/
-static int parse_mark_exception_boundaries(jitdata *jd)
+static bool parse_mark_exception_boundaries(jitdata *jd, parsedata_t *pd)
{
- s4 b_count;
- s4 pc;
+ s4 bcindex;
s4 i;
s4 len;
raw_exception_entry *rex;
len = m->rawexceptiontablelength;
if (len == 0)
- return 0;
+ return true;
- b_count = 0;
rex = m->rawexceptiontable;
for (i = 0; i < len; ++i, ++rex) {
/* the start of the handled region becomes a basic block start */
- pc = rex->startpc;
- CHECK_BYTECODE_INDEX(pc);
- MARK_BASICBLOCK(pc);
+ bcindex = rex->startpc;
+ CHECK_BYTECODE_INDEX(bcindex);
+ MARK_BASICBLOCK(pd, bcindex);
- pc = rex->endpc; /* see JVM Spec 4.7.3 */
- CHECK_BYTECODE_INDEX_EXCLUSIVE(pc);
+ 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 (pc <= rex->startpc) {
- exceptions_throw_verifyerror(m,
- "Invalid exception handler range");
- return -1;
+ 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.) */
+ /* 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 (pc < m->jcodelength)
- MARK_BASICBLOCK(pc);
+ if (bcindex < m->jcodelength)
+ MARK_BASICBLOCK(pd, bcindex);
else
jd->branchtoend = true;
/* the start of the handler becomes a basic block start */
- pc = rex->handlerpc;
- CHECK_BYTECODE_INDEX(pc);
- MARK_BASICBLOCK(pc);
+ bcindex = rex->handlerpc;
+ CHECK_BYTECODE_INDEX(bcindex);
+ MARK_BASICBLOCK(pd, bcindex);
}
/* everything ok */
- return b_count;
+ return true;
#if defined(ENABLE_VERIFIER)
throw_invalid_bytecode_index:
exceptions_throw_verifyerror(m,
"Illegal bytecode index in exception table");
- return -1;
+ return false;
#endif
}
*******************************************************************************/
-static bool parse_resolve_exception_table(jitdata *jd)
+static bool parse_resolve_exception_table(jitdata *jd, parsedata_t *pd)
{
methodinfo *m;
raw_exception_entry *rex;
for (i = 0; i < len; ++i, ++rex, ++ex) {
/* resolve instruction indices to basic blocks */
- ex->start = BLOCK_OF(rex->startpc);
- ex->end = BLOCK_OF(rex->endpc);
- ex->handler = BLOCK_OF(rex->handlerpc);
+ 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 */
bool parse(jitdata *jd)
{
methodinfo *m; /* method being parsed */
+ codeinfo *code;
parsedata_t pd;
instruction *iptr; /* current ptr into instruction array */
- s4 icount; /* intermediate instruction counter */
- s4 p; /* java instruction counter */
- s4 nextp; /* start of next java instruction */
- s4 opcode; /* java opcode */
- s4 i;
- s4 j;
- int b_count; /* basic block counter */
- int s_count = 0; /* stack element counter */
- bool blockend = false; /* true if basic block end has been reached */
- bool iswide = false; /* true if last instruction was a wide */
+
+ 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 *mr;
+ constant_FMIref *fmi;
methoddesc *md;
unresolved_method *um;
+ unresolved_field *uf;
+
resolve_result_t result;
u2 lineindex = 0;
u2 currentline = 0;
u4 flags;
basicblock *bptr;
- int *local_map; /* local pointer to renaming structore */
+ 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;
/* initialize local variables */
- iptr = pd.instructions;
- icount = 0;
-
+ iptr = pd.instructions;
+ ircount = 0;
+ bbcount = 0;
+ blockend = false;
+ iswide = false;
+
/* mark basic block boundaries for exception table */
- b_count = parse_mark_exception_boundaries(jd);
- if (b_count < 0)
+ if (!parse_mark_exception_boundaries(jd, &pd))
return false;
/* initialize stack element counter */
/*** LOOP OVER ALL BYTECODE INSTRUCTIONS **********************************/
- for (p = 0; p < m->jcodelength; p = nextp) {
+ for (bcindex = 0; bcindex < m->jcodelength; bcindex = nextbc) {
- /* mark this position as a valid instruction start */
+ /* mark this position as a valid bytecode instruction start */
- pd.instructionstart[p] = 1;
+ pd.bytecodestart[bcindex] = 1;
/* change the current line number, if necessary */
/* XXX rewrite this using pointer arithmetic */
- if (linepcchange == p) {
+ 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 == p)
+ if (linepcchange == bcindex)
goto next_linenumber;
}
}
fetch_opcode:
/* fetch next opcode */
- opcode = SUCK_BE_U1(m->jcode + p);
+ opcode = SUCK_BE_U1(m->jcode + bcindex);
- /* some compilers put a JAVA_NOP after a blockend instruction */
+ /* If the previous instruction was a block-end instruction,
+ mark the current bytecode instruction as basic-block
+ starting instruction. */
- if (blockend && (opcode != JAVA_NOP)) {
- /* start new block */
+ /* NOTE: Some compilers put a BC_nop after a blockend
+ instruction. */
- MARK_BASICBLOCK(p);
+ if (blockend && (opcode != BC_nop)) {
+ MARK_BASICBLOCK(&pd, bcindex);
blockend = false;
}
- /* We need a NOP as last instruction in each basic block
- for basic block reordering (may be replaced with a GOTO
- later). */
+ /* 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). */
- if (jd->basicblockindex[p] & 1) {
INSTRUCTIONS_CHECK(1);
OP(ICMD_NOP);
}
/* store intermediate instruction count (bit 0 mark block starts) */
- jd->basicblockindex[p] |= (icount << 1);
+ pd.bytecodemap[bcindex] = ircount;
/* compute next instruction start */
- nextp = p + jcommandsize[opcode];
+ nextbc = bcindex + bytecode[opcode].length;
- CHECK_END_OF_BYTECODE(nextp);
+ CHECK_END_OF_BYTECODE(nextbc);
/* add stack elements produced by this instruction */
- s_count += stackreq[opcode];
+ 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
/* translate this bytecode instruction */
switch (opcode) {
- case JAVA_NOP:
+ case BC_nop:
break;
/* pushing constants onto the stack ***********************************/
- case JAVA_BIPUSH:
- OP_LOADCONST_I(SUCK_BE_S1(m->jcode + p + 1));
+ case BC_bipush:
+ OP_LOADCONST_I(SUCK_BE_S1(m->jcode + bcindex + 1));
break;
- case JAVA_SIPUSH:
- OP_LOADCONST_I(SUCK_BE_S2(m->jcode + p + 1));
+ case BC_sipush:
+ OP_LOADCONST_I(SUCK_BE_S2(m->jcode + bcindex + 1));
break;
- case JAVA_LDC1:
- i = SUCK_BE_U1(m->jcode + p + 1);
+ case BC_ldc1:
+ i = SUCK_BE_U1(m->jcode + bcindex + 1);
goto pushconstantitem;
- case JAVA_LDC2:
- case JAVA_LDC2W:
- i = SUCK_BE_U2(m->jcode + p + 1);
+ case BC_ldc2:
+ case BC_ldc2w:
+ i = SUCK_BE_U2(m->jcode + bcindex + 1);
pushconstantitem:
#if defined(ENABLE_VERIFIER)
- if (i >= m->class->cpcount) {
+ if (i >= m->clazz->cpcount) {
exceptions_throw_verifyerror(m,
"Attempt to access constant outside range");
return false;
}
#endif
- switch (m->class->cptags[i]) {
+ switch (m->clazz->cptags[i]) {
case CONSTANT_Integer:
- OP_LOADCONST_I(((constant_integer *) (m->class->cpinfos[i]))->value);
+ OP_LOADCONST_I(((constant_integer *) (m->clazz->cpinfos[i]))->value);
break;
case CONSTANT_Long:
- OP_LOADCONST_L(((constant_long *) (m->class->cpinfos[i]))->value);
+ OP_LOADCONST_L(((constant_long *) (m->clazz->cpinfos[i]))->value);
break;
case CONSTANT_Float:
- OP_LOADCONST_F(((constant_float *) (m->class->cpinfos[i]))->value);
+ OP_LOADCONST_F(((constant_float *) (m->clazz->cpinfos[i]))->value);
break;
case CONSTANT_Double:
- OP_LOADCONST_D(((constant_double *) (m->class->cpinfos[i]))->value);
+ OP_LOADCONST_D(((constant_double *) (m->clazz->cpinfos[i]))->value);
break;
case CONSTANT_String:
- OP_LOADCONST_STRING(literalstring_new((utf *) (m->class->cpinfos[i])));
+ OP_LOADCONST_STRING(literalstring_new((utf *) (m->clazz->cpinfos[i])));
break;
case CONSTANT_Class:
- cr = (constant_classref *) (m->class->cpinfos[i]);
+ cr = (constant_classref *) (m->clazz->cpinfos[i]);
if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
return false;
}
break;
- case JAVA_ACONST_NULL:
+ case BC_aconst_null:
OP_LOADCONST_NULL();
break;
- case JAVA_ICONST_M1:
- case JAVA_ICONST_0:
- case JAVA_ICONST_1:
- case JAVA_ICONST_2:
- case JAVA_ICONST_3:
- case JAVA_ICONST_4:
- case JAVA_ICONST_5:
- OP_LOADCONST_I(opcode - JAVA_ICONST_0);
+ 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 JAVA_LCONST_0:
- case JAVA_LCONST_1:
- OP_LOADCONST_L(opcode - JAVA_LCONST_0);
+ case BC_lconst_0:
+ case BC_lconst_1:
+ OP_LOADCONST_L(opcode - BC_lconst_0);
break;
- case JAVA_FCONST_0:
- case JAVA_FCONST_1:
- case JAVA_FCONST_2:
- OP_LOADCONST_F(opcode - JAVA_FCONST_0);
+ case BC_fconst_0:
+ case BC_fconst_1:
+ case BC_fconst_2:
+ OP_LOADCONST_F(opcode - BC_fconst_0);
break;
- case JAVA_DCONST_0:
- case JAVA_DCONST_1:
- OP_LOADCONST_D(opcode - JAVA_DCONST_0);
+ case BC_dconst_0:
+ case BC_dconst_1:
+ OP_LOADCONST_D(opcode - BC_dconst_0);
break;
/* stack operations ***************************************************/
- /* We need space for additional ICMDs so we can translate these */
- /* instructions to sequences of ICMD_COPY and ICMD_MOVE instructions. */
+ /* We need space for additional instruction so we can
+ translate these instructions to sequences of ICMD_COPY and
+ ICMD_MOVE instructions. */
- case JAVA_DUP_X1:
+ case BC_dup_x1:
INSTRUCTIONS_CHECK(4);
OP(opcode);
OP(ICMD_NOP);
OP(ICMD_NOP);
break;
- case JAVA_DUP_X2:
+ case BC_dup_x2:
INSTRUCTIONS_CHECK(6);
OP(opcode);
OP(ICMD_NOP);
OP(ICMD_NOP);
break;
- case JAVA_DUP2:
+ case BC_dup2:
INSTRUCTIONS_CHECK(2);
OP(opcode);
OP(ICMD_NOP);
break;
- case JAVA_DUP2_X1:
+ case BC_dup2_x1:
INSTRUCTIONS_CHECK(7);
OP(opcode);
OP(ICMD_NOP);
OP(ICMD_NOP);
break;
- case JAVA_DUP2_X2:
+ case BC_dup2_x2:
INSTRUCTIONS_CHECK(9);
OP(opcode);
OP(ICMD_NOP);
OP(ICMD_NOP);
break;
- case JAVA_SWAP:
+ case BC_swap:
INSTRUCTIONS_CHECK(3);
OP(opcode);
OP(ICMD_NOP);
/* local variable access instructions *********************************/
- case JAVA_ILOAD:
- case JAVA_FLOAD:
- case JAVA_ALOAD:
+ case BC_iload:
+ case BC_fload:
+ case BC_aload:
if (iswide == false) {
- i = SUCK_BE_U1(m->jcode + p + 1);
+ i = SUCK_BE_U1(m->jcode + bcindex + 1);
}
else {
- i = SUCK_BE_U2(m->jcode + p + 1);
- nextp = p + 3;
+ i = SUCK_BE_U2(m->jcode + bcindex + 1);
+ nextbc = bcindex + 3;
iswide = false;
}
- OP_LOAD_ONEWORD(opcode, i, opcode - JAVA_ILOAD);
+ OP_LOAD_ONEWORD(opcode, i, opcode - BC_iload);
break;
- case JAVA_LLOAD:
- case JAVA_DLOAD:
+ case BC_lload:
+ case BC_dload:
if (iswide == false) {
- i = SUCK_BE_U1(m->jcode + p + 1);
+ i = SUCK_BE_U1(m->jcode + bcindex + 1);
}
else {
- i = SUCK_BE_U2(m->jcode + p + 1);
- nextp = p + 3;
+ i = SUCK_BE_U2(m->jcode + bcindex + 1);
+ nextbc = bcindex + 3;
iswide = false;
}
- OP_LOAD_TWOWORD(opcode, i, opcode - JAVA_ILOAD);
+ OP_LOAD_TWOWORD(opcode, i, opcode - BC_iload);
break;
- case JAVA_ILOAD_0:
- case JAVA_ILOAD_1:
- case JAVA_ILOAD_2:
- case JAVA_ILOAD_3:
- OP_LOAD_ONEWORD(ICMD_ILOAD, opcode - JAVA_ILOAD_0, TYPE_INT);
+ 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 JAVA_LLOAD_0:
- case JAVA_LLOAD_1:
- case JAVA_LLOAD_2:
- case JAVA_LLOAD_3:
- OP_LOAD_TWOWORD(ICMD_LLOAD, opcode - JAVA_LLOAD_0, TYPE_LNG);
+ 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 JAVA_FLOAD_0:
- case JAVA_FLOAD_1:
- case JAVA_FLOAD_2:
- case JAVA_FLOAD_3:
- OP_LOAD_ONEWORD(ICMD_FLOAD, opcode - JAVA_FLOAD_0, TYPE_FLT);
+ 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 JAVA_DLOAD_0:
- case JAVA_DLOAD_1:
- case JAVA_DLOAD_2:
- case JAVA_DLOAD_3:
- OP_LOAD_TWOWORD(ICMD_DLOAD, opcode - JAVA_DLOAD_0, TYPE_DBL);
+ 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 JAVA_ALOAD_0:
- case JAVA_ALOAD_1:
- case JAVA_ALOAD_2:
- case JAVA_ALOAD_3:
- OP_LOAD_ONEWORD(ICMD_ALOAD, opcode - JAVA_ALOAD_0, TYPE_ADR);
+ 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 JAVA_ISTORE:
- case JAVA_FSTORE:
- case JAVA_ASTORE:
+ case BC_istore:
+ case BC_fstore:
+ case BC_astore:
if (iswide == false) {
- i = SUCK_BE_U1(m->jcode + p + 1);
+ i = SUCK_BE_U1(m->jcode + bcindex + 1);
}
else {
- i = SUCK_BE_U2(m->jcode + p + 1);
+ i = SUCK_BE_U2(m->jcode + bcindex + 1);
+ nextbc = bcindex + 3;
iswide = false;
- nextp = p + 3;
}
- OP_STORE_ONEWORD(opcode, i, opcode - JAVA_ISTORE);
+ OP_STORE_ONEWORD(opcode, i, opcode - BC_istore);
break;
- case JAVA_LSTORE:
- case JAVA_DSTORE:
+ case BC_lstore:
+ case BC_dstore:
if (iswide == false) {
- i = SUCK_BE_U1(m->jcode + p + 1);
+ i = SUCK_BE_U1(m->jcode + bcindex + 1);
}
else {
- i = SUCK_BE_U2(m->jcode + p + 1);
+ i = SUCK_BE_U2(m->jcode + bcindex + 1);
+ nextbc = bcindex + 3;
iswide = false;
- nextp = p + 3;
}
- OP_STORE_TWOWORD(opcode, i, opcode - JAVA_ISTORE);
+ OP_STORE_TWOWORD(opcode, i, opcode - BC_istore);
break;
- case JAVA_ISTORE_0:
- case JAVA_ISTORE_1:
- case JAVA_ISTORE_2:
- case JAVA_ISTORE_3:
- OP_STORE_ONEWORD(ICMD_ISTORE, opcode - JAVA_ISTORE_0, TYPE_INT);
+ 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 JAVA_LSTORE_0:
- case JAVA_LSTORE_1:
- case JAVA_LSTORE_2:
- case JAVA_LSTORE_3:
- OP_STORE_TWOWORD(ICMD_LSTORE, opcode - JAVA_LSTORE_0, TYPE_LNG);
+ 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 JAVA_FSTORE_0:
- case JAVA_FSTORE_1:
- case JAVA_FSTORE_2:
- case JAVA_FSTORE_3:
- OP_STORE_ONEWORD(ICMD_FSTORE, opcode - JAVA_FSTORE_0, TYPE_FLT);
+ 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 JAVA_DSTORE_0:
- case JAVA_DSTORE_1:
- case JAVA_DSTORE_2:
- case JAVA_DSTORE_3:
- OP_STORE_TWOWORD(ICMD_DSTORE, opcode - JAVA_DSTORE_0, TYPE_DBL);
+ 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 JAVA_ASTORE_0:
- case JAVA_ASTORE_1:
- case JAVA_ASTORE_2:
- case JAVA_ASTORE_3:
- OP_STORE_ONEWORD(ICMD_ASTORE, opcode - JAVA_ASTORE_0, TYPE_ADR);
+ 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 JAVA_IINC:
+ case BC_iinc:
{
int v;
if (iswide == false) {
- i = SUCK_BE_U1(m->jcode + p + 1);
- v = SUCK_BE_S1(m->jcode + p + 2);
-
+ i = SUCK_BE_U1(m->jcode + bcindex + 1);
+ v = SUCK_BE_S1(m->jcode + bcindex + 2);
}
else {
- i = SUCK_BE_U2(m->jcode + p + 1);
- v = SUCK_BE_S2(m->jcode + p + 3);
+ i = SUCK_BE_U2(m->jcode + bcindex + 1);
+ v = SUCK_BE_S2(m->jcode + bcindex + 3);
+ nextbc = bcindex + 5;
iswide = false;
- nextp = p + 5;
}
INDEX_ONEWORD(i);
LOCALTYPE_USED(i, TYPE_INT);
/* wider index for loading, storing and incrementing ******************/
- case JAVA_WIDE:
+ case BC_wide:
+ bcindex++;
iswide = true;
- p++;
goto fetch_opcode;
/* managing arrays ****************************************************/
- case JAVA_NEWARRAY:
- switch (SUCK_BE_S1(m->jcode + p + 1)) {
+ case BC_newarray:
+ switch (SUCK_BE_S1(m->jcode + bcindex + 1)) {
case 4:
bte = builtintable_get_internal(BUILTIN_newarray_boolean);
break;
OP_BUILTIN_CHECK_EXCEPTION(bte);
break;
- case JAVA_ANEWARRAY:
- i = SUCK_BE_U2(m->jcode + p + 1);
- compr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
- if (!compr)
+ 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)))
s_count++;
break;
- case JAVA_MULTIANEWARRAY:
- jd->isleafmethod = false;
- i = SUCK_BE_U2(m->jcode + p + 1);
- j = SUCK_BE_U1(m->jcode + p + 3);
+ 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->class, i, CONSTANT_Class);
+ cr = (constant_classref *) class_getconstant(m->clazz, i, CONSTANT_Class);
if (cr == NULL)
return false;
iptr->s1.argcount = j;
OP_S3_CLASSINFO_OR_CLASSREF(opcode, c, cr, INS_FLAG_CHECK);
+ code_unflag_leafmethod(code);
break;
/* control flow instructions ******************************************/
- case JAVA_IFEQ:
- case JAVA_IFLT:
- case JAVA_IFLE:
- case JAVA_IFNE:
- case JAVA_IFGT:
- case JAVA_IFGE:
- case JAVA_IFNULL:
- case JAVA_IFNONNULL:
- case JAVA_IF_ICMPEQ:
- case JAVA_IF_ICMPNE:
- case JAVA_IF_ICMPLT:
- case JAVA_IF_ICMPGT:
- case JAVA_IF_ICMPLE:
- case JAVA_IF_ICMPGE:
- case JAVA_IF_ACMPEQ:
- case JAVA_IF_ACMPNE:
- case JAVA_GOTO:
- i = p + SUCK_BE_S2(m->jcode + p + 1);
+ 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(i);
+ MARK_BASICBLOCK(&pd, i);
blockend = true;
OP_INSINDEX(opcode, i);
break;
- case JAVA_GOTO_W:
- i = p + SUCK_BE_S4(m->jcode + p + 1);
+ case BC_goto_w:
+ i = bcindex + SUCK_BE_S4(m->jcode + bcindex + 1);
CHECK_BYTECODE_INDEX(i);
- MARK_BASICBLOCK(i);
+ MARK_BASICBLOCK(&pd, i);
blockend = true;
OP_INSINDEX(ICMD_GOTO, i);
break;
- case JAVA_JSR:
- i = p + SUCK_BE_S2(m->jcode + p + 1);
+ case BC_jsr:
+ i = bcindex + SUCK_BE_S2(m->jcode + bcindex + 1);
jsr_tail:
CHECK_BYTECODE_INDEX(i);
- MARK_BASICBLOCK(i);
+ MARK_BASICBLOCK(&pd, i);
blockend = true;
- OP_PREPARE_ZEROFLAGS(JAVA_JSR);
+ OP_PREPARE_ZEROFLAGS(BC_jsr);
iptr->sx.s23.s3.jsrtarget.insindex = i;
PINC;
break;
- case JAVA_JSR_W:
- i = p + SUCK_BE_S4(m->jcode + p + 1);
+ case BC_jsr_w:
+ i = bcindex + SUCK_BE_S4(m->jcode + bcindex + 1);
goto jsr_tail;
- case JAVA_RET:
+ case BC_ret:
if (iswide == false) {
- i = SUCK_BE_U1(m->jcode + p + 1);
+ i = SUCK_BE_U1(m->jcode + bcindex + 1);
}
else {
- i = SUCK_BE_U2(m->jcode + p + 1);
- nextp = p + 3;
+ i = SUCK_BE_U2(m->jcode + bcindex + 1);
+ nextbc = bcindex + 3;
iswide = false;
}
blockend = true;
OP_LOAD_ONEWORD(opcode, i, TYPE_ADR);
break;
- case JAVA_IRETURN:
- case JAVA_LRETURN:
- case JAVA_FRETURN:
- case JAVA_DRETURN:
- case JAVA_ARETURN:
- case JAVA_RETURN:
+ 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 JAVA_ATHROW:
+ case BC_athrow:
blockend = true;
/* XXX ATHROW will need a flag in the typechecker */
OP(opcode);
/* table jumps ********************************************************/
- case JAVA_LOOKUPSWITCH:
+ case BC_lookupswitch:
{
s4 num, j;
lookup_target_t *lookup;
s4 prevvalue = 0;
#endif
blockend = true;
- nextp = MEMORY_ALIGN((p + 1), 4);
+ nextbc = MEMORY_ALIGN((bcindex + 1), 4);
- CHECK_END_OF_BYTECODE(nextp + 8);
+ CHECK_END_OF_BYTECODE(nextbc + 8);
OP_PREPARE_ZEROFLAGS(opcode);
/* default target */
- j = p + SUCK_BE_S4(m->jcode + nextp);
+ j = bcindex + SUCK_BE_S4(m->jcode + nextbc);
iptr->sx.s23.s3.lookupdefault.insindex = j;
- nextp += 4;
+ nextbc += 4;
CHECK_BYTECODE_INDEX(j);
- MARK_BASICBLOCK(j);
+ MARK_BASICBLOCK(&pd, j);
/* number of pairs */
- num = SUCK_BE_U4(m->jcode + nextp);
+ num = SUCK_BE_U4(m->jcode + nextbc);
iptr->sx.s23.s2.lookupcount = num;
- nextp += 4;
+ nextbc += 4;
/* allocate the intermediate code table */
/* iterate over the lookup table */
- CHECK_END_OF_BYTECODE(nextp + 8 * num);
+ CHECK_END_OF_BYTECODE(nextbc + 8 * num);
for (i = 0; i < num; i++) {
/* value */
- j = SUCK_BE_S4(m->jcode + nextp);
+ j = SUCK_BE_S4(m->jcode + nextbc);
lookup->value = j;
- nextp += 4;
+ nextbc += 4;
#if defined(ENABLE_VERIFIER)
/* check if the lookup table is sorted correctly */
#endif
/* target */
- j = p + SUCK_BE_S4(m->jcode + nextp);
+ j = bcindex + SUCK_BE_S4(m->jcode + nextbc);
lookup->target.insindex = j;
lookup++;
- nextp += 4;
+ nextbc += 4;
CHECK_BYTECODE_INDEX(j);
- MARK_BASICBLOCK(j);
+ MARK_BASICBLOCK(&pd, j);
}
PINC;
break;
}
-
- case JAVA_TABLESWITCH:
+ case BC_tableswitch:
{
s4 num, j;
s4 deftarget;
branch_target_t *table;
blockend = true;
- nextp = MEMORY_ALIGN((p + 1), 4);
+ nextbc = MEMORY_ALIGN((bcindex + 1), 4);
- CHECK_END_OF_BYTECODE(nextp + 12);
+ CHECK_END_OF_BYTECODE(nextbc + 12);
OP_PREPARE_ZEROFLAGS(opcode);
/* default target */
- deftarget = p + SUCK_BE_S4(m->jcode + nextp);
- nextp += 4;
+ deftarget = bcindex + SUCK_BE_S4(m->jcode + nextbc);
+ nextbc += 4;
CHECK_BYTECODE_INDEX(deftarget);
- MARK_BASICBLOCK(deftarget);
+ MARK_BASICBLOCK(&pd, deftarget);
/* lower bound */
- j = SUCK_BE_S4(m->jcode + nextp);
+ j = SUCK_BE_S4(m->jcode + nextbc);
iptr->sx.s23.s2.tablelow = j;
- nextp += 4;
+ nextbc += 4;
/* upper bound */
- num = SUCK_BE_S4(m->jcode + nextp);
+ num = SUCK_BE_S4(m->jcode + nextbc);
iptr->sx.s23.s3.tablehigh = num;
- nextp += 4;
+ nextbc += 4;
/* calculate the number of table entries */
/* iterate over the target table */
- CHECK_END_OF_BYTECODE(nextp + 4 * num);
+ CHECK_END_OF_BYTECODE(nextbc + 4 * num);
for (i = 0; i < num; i++) {
- j = p + SUCK_BE_S4(m->jcode + nextp);
+ j = bcindex + SUCK_BE_S4(m->jcode + nextbc);
(table++)->insindex = j;
- nextp += 4;
+ nextbc += 4;
CHECK_BYTECODE_INDEX(j);
- MARK_BASICBLOCK(j);
+ MARK_BASICBLOCK(&pd, j);
}
PINC;
/* load and store of object fields ************************************/
- case JAVA_AASTORE:
+ case BC_aastore:
OP(opcode);
- jd->isleafmethod = false;
+ code_unflag_leafmethod(code);
break;
- case JAVA_GETSTATIC:
- case JAVA_PUTSTATIC:
- case JAVA_GETFIELD:
- case JAVA_PUTFIELD:
- {
- constant_FMIref *fr;
- unresolved_field *uf;
+ 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);
- i = SUCK_BE_U2(m->jcode + p + 1);
- fr = class_getconstant(m->class, i, CONSTANT_Fieldref);
- if (!fr)
- return false;
+ if (fmi == NULL)
+ return false;
- OP_PREPARE_ZEROFLAGS(opcode);
- iptr->sx.s23.s3.fmiref = fr;
+ OP_PREPARE_ZEROFLAGS(opcode);
+ iptr->sx.s23.s3.fmiref = fmi;
- /* only with -noverify, otherwise the typechecker does this */
+ /* only with -noverify, otherwise the typechecker does this */
#if defined(ENABLE_VERIFIER)
- if (!JITDATA_HAS_FLAG_VERIFY(jd)) {
+ if (!JITDATA_HAS_FLAG_VERIFY(jd)) {
#endif
- result = resolve_field_lazy(m, fr);
- if (result == resolveFailed)
- return false;
+ result = resolve_field_lazy(m, fmi);
- if (result != resolveSucceeded) {
- uf = resolve_create_unresolved_field(m->class, m, iptr);
+ if (result == resolveFailed)
+ return false;
- if (uf == NULL)
- return false;
+ if (result != resolveSucceeded) {
+ uf = resolve_create_unresolved_field(m->clazz, m, iptr);
- /* store the unresolved_field pointer */
+ if (uf == NULL)
+ return false;
- iptr->sx.s23.s3.uf = uf;
- iptr->flags.bits |= INS_FLAG_UNRESOLVED;
- }
-#if defined(ENABLE_VERIFIER)
+ /* store the unresolved_field pointer */
+
+ iptr->sx.s23.s3.uf = uf;
+ iptr->flags.bits |= INS_FLAG_UNRESOLVED;
}
-#endif
- PINC;
+#if defined(ENABLE_VERIFIER)
}
+#endif
+ PINC;
break;
/* method invocation **************************************************/
- case JAVA_INVOKESTATIC:
+ case BC_invokestatic:
OP_PREPARE_ZEROFLAGS(opcode);
- i = SUCK_BE_U2(m->jcode + p + 1);
- mr = class_getconstant(m->class, i, CONSTANT_Methodref);
+ i = SUCK_BE_U2(m->jcode + bcindex + 1);
+ fmi = class_getconstant(m->clazz, i, CONSTANT_Methodref);
- if (mr == NULL)
+ if (fmi == NULL)
return false;
- md = mr->parseddesc.md;
+ md = fmi->parseddesc.md;
if (md->params == NULL)
if (!descriptor_params_from_paramtypes(md, ACC_STATIC))
goto invoke_method;
- case JAVA_INVOKESPECIAL:
+ case BC_invokespecial:
OP_PREPARE_FLAGS(opcode, INS_FLAG_CHECK);
- i = SUCK_BE_U2(m->jcode + p + 1);
- mr = class_getconstant(m->class, i, CONSTANT_Methodref);
+ i = SUCK_BE_U2(m->jcode + bcindex + 1);
+ fmi = class_getconstant(m->clazz, i, CONSTANT_Methodref);
goto invoke_nonstatic_method;
- case JAVA_INVOKEINTERFACE:
+ case BC_invokeinterface:
OP_PREPARE_ZEROFLAGS(opcode);
- i = SUCK_BE_U2(m->jcode + p + 1);
- mr = class_getconstant(m->class, i, CONSTANT_InterfaceMethodref);
+ i = SUCK_BE_U2(m->jcode + bcindex + 1);
+ fmi = class_getconstant(m->clazz, i, CONSTANT_InterfaceMethodref);
goto invoke_nonstatic_method;
- case JAVA_INVOKEVIRTUAL:
+ case BC_invokevirtual:
OP_PREPARE_ZEROFLAGS(opcode);
- i = SUCK_BE_U2(m->jcode + p + 1);
- mr = class_getconstant(m->class, i, CONSTANT_Methodref);
+ i = SUCK_BE_U2(m->jcode + bcindex + 1);
+ fmi = class_getconstant(m->clazz, i, CONSTANT_Methodref);
invoke_nonstatic_method:
- if (mr == NULL)
+ if (fmi == NULL)
return false;
- md = mr->parseddesc.md;
+ md = fmi->parseddesc.md;
if (md->params == NULL)
if (!descriptor_params_from_paramtypes(md, 0))
return false;
invoke_method:
- jd->isleafmethod = false;
+ code_unflag_leafmethod(code);
- iptr->sx.s23.s3.fmiref = mr;
+ 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, mr,
- (opcode == JAVA_INVOKESPECIAL));
+ result = resolve_method_lazy(m, fmi,
+ (opcode == BC_invokespecial));
+
if (result == resolveFailed)
return false;
}
}
else {
- um = resolve_create_unresolved_method(m->class, m, mr,
- (opcode == JAVA_INVOKESTATIC),
- (opcode == JAVA_INVOKESPECIAL));
+ um = resolve_create_unresolved_method(m->clazz, m, fmi,
+ (opcode == BC_invokestatic),
+ (opcode == BC_invokespecial));
- if (!um)
+ if (um == NULL)
return false;
/* store the unresolved_method pointer */
/* instructions taking class arguments ********************************/
- case JAVA_NEW:
- i = SUCK_BE_U2(m->jcode + p + 1);
- cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
- if (!cr)
+ 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))
s_count++;
break;
- case JAVA_CHECKCAST:
- i = SUCK_BE_U2(m->jcode + p + 1);
- cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
+ 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 (cr->name->text[0] == '[') {
/* array type cast-check */
flags = INS_FLAG_CHECK | INS_FLAG_ARRAY;
- jd->isleafmethod = false;
+ code_unflag_leafmethod(code);
}
else {
/* object type cast-check */
OP_S3_CLASSINFO_OR_CLASSREF(opcode, c, cr, flags);
break;
- case JAVA_INSTANCEOF:
- i = SUCK_BE_U2(m->jcode + p + 1);
- cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
+ case BC_instanceof:
+ i = SUCK_BE_U2(m->jcode + bcindex + 1);
+ cr = class_getconstant(m->clazz, i, CONSTANT_Class);
+
if (cr == NULL)
return false;
/* synchronization instructions ***************************************/
- case JAVA_MONITORENTER:
+ case BC_monitorenter:
#if defined(ENABLE_THREADS)
if (checksync) {
bte = builtintable_get_internal(LOCK_monitor_enter);
}
break;
- case JAVA_MONITOREXIT:
+ case BC_monitorexit:
#if defined(ENABLE_THREADS)
if (checksync) {
bte = builtintable_get_internal(LOCK_monitor_exit);
/* arithmetic instructions that may become builtin functions **********/
- case JAVA_IDIV:
+ case BC_idiv:
#if !SUPPORT_DIVISION
bte = builtintable_get_internal(BUILTIN_idiv);
OP_BUILTIN_ARITHMETIC(opcode, bte);
#endif
break;
- case JAVA_IREM:
+ case BC_irem:
#if !SUPPORT_DIVISION
bte = builtintable_get_internal(BUILTIN_irem);
OP_BUILTIN_ARITHMETIC(opcode, bte);
#endif
break;
- case JAVA_LDIV:
+ case BC_ldiv:
#if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
bte = builtintable_get_internal(BUILTIN_ldiv);
OP_BUILTIN_ARITHMETIC(opcode, bte);
#endif
break;
- case JAVA_LREM:
+ case BC_lrem:
#if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
bte = builtintable_get_internal(BUILTIN_lrem);
OP_BUILTIN_ARITHMETIC(opcode, bte);
#endif
break;
- case JAVA_FREM:
+ case BC_frem:
#if defined(__I386__)
OP(opcode);
#else
#endif
break;
- case JAVA_DREM:
+ case BC_drem:
#if defined(__I386__)
OP(opcode);
#else
#endif
break;
- case JAVA_F2I:
+ case BC_f2i:
#if defined(__ALPHA__)
- if (!opt_noieee) {
- bte = builtintable_get_internal(BUILTIN_f2i);
- OP_BUILTIN_NO_EXCEPTION(bte);
- }
- else
+ bte = builtintable_get_internal(BUILTIN_f2i);
+ OP_BUILTIN_NO_EXCEPTION(bte);
+#else
+ OP(opcode);
#endif
- {
- OP(opcode);
- }
break;
- case JAVA_F2L:
+ case BC_f2l:
#if defined(__ALPHA__)
- if (!opt_noieee) {
- bte = builtintable_get_internal(BUILTIN_f2l);
- OP_BUILTIN_NO_EXCEPTION(bte);
- }
- else
+ bte = builtintable_get_internal(BUILTIN_f2l);
+ OP_BUILTIN_NO_EXCEPTION(bte);
+#else
+ OP(opcode);
#endif
- {
- OP(opcode);
- }
break;
- case JAVA_D2I:
+ case BC_d2i:
#if defined(__ALPHA__)
- if (!opt_noieee) {
- bte = builtintable_get_internal(BUILTIN_d2i);
- OP_BUILTIN_NO_EXCEPTION(bte);
- }
- else
+ bte = builtintable_get_internal(BUILTIN_d2i);
+ OP_BUILTIN_NO_EXCEPTION(bte);
+#else
+ OP(opcode);
#endif
- {
- OP(opcode);
- }
break;
- case JAVA_D2L:
+ case BC_d2l:
#if defined(__ALPHA__)
- if (!opt_noieee) {
- bte = builtintable_get_internal(BUILTIN_d2l);
- OP_BUILTIN_NO_EXCEPTION(bte);
- }
- else
+ bte = builtintable_get_internal(BUILTIN_d2l);
+ OP_BUILTIN_NO_EXCEPTION(bte);
+#else
+ OP(opcode);
#endif
- {
- OP(opcode);
- }
break;
+
/* invalid opcodes ****************************************************/
/* check for invalid opcodes if the verifier is enabled */
#if defined(ENABLE_VERIFIER)
- case JAVA_BREAKPOINT:
+ case BC_breakpoint:
exceptions_throw_verifyerror(m, "Quick instructions shouldn't appear, yet.");
return false;
- case 186: /* unused opcode */
+
+ /* Unused opcodes ************************************************** */
+
+ case 186:
case 203:
case 204:
case 205:
case 254:
case 255:
exceptions_throw_verifyerror(m, "Illegal opcode %d at instr %d\n",
- opcode, icount);
+ opcode, ircount);
return false;
break;
#endif /* defined(ENABLE_VERIFIER) */
/* opcodes that don't require translation *****************************/
default:
- /* straight-forward translation to ICMD */
+ /* Straight-forward translation to HIR. */
OP(opcode);
break;
/* assert that we did not write more ICMDs than allocated */
- assert(icount <= pd.instructionslength);
- assert(icount == (iptr - pd.instructions));
+ assert(ircount <= pd.instructionslength);
+ assert(ircount == (iptr - pd.instructions));
/*** verifier checks ******************************************************/
#if defined(ENABLE_VERIFIER)
- if (p != m->jcodelength) {
+ if (bcindex != m->jcodelength) {
exceptions_throw_verifyerror(m,
"Command-sequence crosses code-boundary");
return false;
/* identify basic blocks */
- /* First instruction always starts a basic block, but check if it
- is already a branch target. */
-
- if ((jd->basicblockindex[0] == 0) || (jd->basicblockindex[0] > 1)) {
- iptr = pd.instructions;
-
- iptr->flags.bits |= INS_FLAG_BASICBLOCK;
-
- /* This is the first basic block. */
+ /* check if first instruction is a branch target */
- b_count = 1;
+ if (pd.basicblockstart[0] == 1) {
+ jd->branchtoentry = true;
}
else {
- jd->branchtoentry = true;
+ /* first instruction always starts a basic block */
- /* In this case the loop below counts the first basic
- block. */
+ iptr = pd.instructions;
- b_count = 0;
+ iptr->flags.bits |= INS_FLAG_BASICBLOCK;
}
- /* Iterate over all bytecode instructions and mark the
- corresponding IR instruction as basic block starting
- instruction. */
+ /* 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? */
- for (i = 0; i < m->jcodelength; i++) {
- if (jd->basicblockindex[i] & 0x1) {
+ if (pd.basicblockstart[bcindex] == 1) {
#if defined(ENABLE_VERIFIER)
- /* Check if this block starts at the beginning of an
- instruction. */
+ /* Check if this bytecode basic-block start at the
+ beginning of a bytecode instruction. */
- if (pd.instructionstart[i] == 0) {
+ if (pd.bytecodestart[bcindex] == 0) {
exceptions_throw_verifyerror(m,
- "Branch into middle of instruction");
+ "Branch into middle of instruction");
return false;
}
#endif
- /* Mark the IR instruction as basic block starting
- instruction. */
+ /* Get the IR instruction mapped to the bytecode
+ instruction and set the basic block flag. */
- iptr = pd.instructions + (jd->basicblockindex[i] >> 1);
+ irindex = pd.bytecodemap[bcindex];
+ iptr = pd.instructions + irindex;
iptr->flags.bits |= INS_FLAG_BASICBLOCK;
-
- /* Store te basic block number in the array. We need this
- information during stack analysis. */
-
- jd->basicblockindex[i] = b_count;
-
- /* basic block indices of course start with 0 */
-
- b_count++;
}
}
+ /* 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;
- b_count = 0;
+ bbcount = 0;
- for (i = 0; i < icount; i++, iptr++) {
+ for (i = 0; i < ircount; i++, iptr++) {
if (INSTRUCTION_STARTS_BASICBLOCK(iptr)) {
- b_count++;
+ /* 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, b_count + 1);
-
- /* zero out all basic block structures */
-
- MZERO(jd->basicblocks, basicblock, b_count + 1);
+ 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. */
+ basic block structures and, in the same loop, resolve the
+ branch-target instruction indices to basic blocks. */
iptr = pd.instructions;
bptr = jd->basicblocks;
- b_count = 0;
+ bbcount = 0;
+
+ for (i = 0; i < ircount; i++, iptr++) {
+ /* check for basic block */
- for (i = 0; i < icount; i++, iptr++) {
if (INSTRUCTION_STARTS_BASICBLOCK(iptr)) {
/* intialize the basic block */
bptr->iinstr = iptr;
- if (b_count > 0) {
+ if (bbcount > 0) {
bptr[-1].icount = bptr->iinstr - bptr[-1].iinstr;
}
/* bptr->icount is set when the next block is allocated */
- bptr->nr = b_count++;
+ 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 (b_count > 0) {
- bptr[-1].icount = (pd.instructions + icount) - bptr[-1].iinstr;
+ if (bbcount > 0) {
+ bptr[-1].icount = (pd.instructions + ircount) - bptr[-1].iinstr;
}
/* allocate additional block at end */
BASICBLOCK_INIT(bptr, m);
- bptr->nr = b_count;
-
- jd->basicblockindex[m->jcodelength] = b_count;
+ bptr->nr = bbcount;
/* set basicblock pointers in exception table */
- if (!parse_resolve_exception_table(jd))
+ if (!parse_resolve_exception_table(jd, &pd))
return false;
/* store the local map */
{
s4 nlocals = 0;
s4 i;
-
+ s4 t;
+ s4 varindex;
s4 *mapptr;
+ s4 *reversemap;
mapptr = local_map;
- /* iterate over local_map[0..m->maxlocals*5] and set all existing */
- /* index,type pairs (local_map[index*5+type]==1) to an unique value */
- /* -> == new local var index */
- for(i = 0; i < (m->maxlocals * 5); i++, mapptr++) {
+ /* 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
jd->varcount =
nlocals /* local variables */
- + b_count * m->maxstack /* invars */
+ + bbcount * m->maxstack /* invars */
+ s_count; /* variables created within blocks (non-invar) */
/* reserve the first indices for local variables */
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;
+ }
+ }
- for(mapptr = local_map, i = 0; i < (m->maxlocals * 5); i++, mapptr++)
- if (*mapptr != UNUSED)
- VAR(*mapptr)->type = i%5;
+ jd->reverselocalmap = reversemap;
}
/* assign local variables to method variables */
jd->instructions = pd.instructions;
- jd->instructioncount = icount;
- jd->basicblockcount = b_count;
- jd->stackcount = s_count + b_count * m->maxstack; /* in-stacks */
+ jd->instructioncount = ircount;
+ jd->basicblockcount = bbcount;
+ jd->stackcount = s_count + bbcount * m->maxstack; /* in-stacks */
/* allocate stack table */
- jd->stack = DMNEW(stackelement, jd->stackcount);
+ jd->stack = DMNEW(stackelement_t, jd->stackcount);
/* everything's ok */