IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+* contrib/vmlog
+
+Copyright (C) 2006 Edwin Steiner <edwin.steiner@gmx.net>
+
+ 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 of the License, or
+ (at your option) any later version.
+
+See contrib/vmlog/COPYING for the full text of the license.
+
#define asm_vm_call_method_long _asm_vm_call_method_long
#define asm_vm_call_method_float _asm_vm_call_method_float
#define asm_vm_call_method_double _asm_vm_call_method_double
+#define asm_vm_call_method_end _asm_vm_call_method_end
#define asm_vm_call_method_exception_handler _asm_vm_call_method_exception_handler
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- $Id: jit.h 7596 2007-03-28 21:05:53Z twisti $
+ $Id: jit.h 7627 2007-04-02 18:56:59Z twisti $
*/
/*** flags (32 bits) ***/
-#define INS_FLAG_UNRESOLVED 0x01 /* contains unresolved field/meth/class*/
-#define INS_FLAG_CLASS 0x02 /* for ACONST, PUT*CONST with class */
-#define INS_FLAG_ARRAY 0x04 /* for CHECKCAST/INSTANCEOF with array */
-#define INS_FLAG_CHECK 0x08 /* for *ALOAD|*ASTORE: check index */
+#define INS_FLAG_BASICBLOCK 0x01 /* marks a basic block start */
+#define INS_FLAG_UNRESOLVED 0x02 /* contains unresolved field/meth/class*/
+#define INS_FLAG_CLASS 0x04 /* for ACONST, PUT*CONST with class */
+#define INS_FLAG_ARRAY 0x08 /* for CHECKCAST/INSTANCEOF with array */
+#define INS_FLAG_CHECK 0x10 /* for *ALOAD|*ASTORE: check index */
/* for BUILTIN: check exception */
-#define INS_FLAG_KILL_PREV 0x02 /* for *STORE, invalidate prev local */
-#define INS_FLAG_KILL_NEXT 0x04 /* for *STORE, invalidate next local */
-#define INS_FLAG_RETADDR 0x08 /* for ASTORE: op is a returnAddress */
+#define INS_FLAG_KILL_PREV 0x04 /* for *STORE, invalidate prev local */
+#define INS_FLAG_KILL_NEXT 0x08 /* for *STORE, invalidate next local */
+#define INS_FLAG_RETADDR 0x10 /* for ASTORE: op is a returnAddress */
-#define INS_FLAG_ID_SHIFT 4
+#define INS_FLAG_ID_SHIFT 5
#define INS_FLAG_ID_MASK (~0 << INS_FLAG_ID_SHIFT)
typedef union {
};
+#define INSTRUCTION_STARTS_BASICBLOCK(iptr) \
+ ((iptr)->flags.bits & INS_FLAG_BASICBLOCK)
+
#define INSTRUCTION_IS_RESOLVED(iptr) \
(!((iptr)->flags.bits & INS_FLAG_UNRESOLVED))
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- $Id: parse.c 7601 2007-03-28 23:02:50Z michi $
+ $Id: parse.c 7627 2007-04-02 18:56:59Z twisti $
*/
*******************************************************************************/
-static instruction *parse_realloc_instructions(parsedata_t *pd, s4 ipc, s4 n)
+static instruction *parse_realloc_instructions(parsedata_t *pd, s4 icount, s4 n)
{
/* increase the size of the instruction array */
/* reallocate the array */
- pd->instructions = DMREALLOC(pd->instructions, instruction, ipc,
+ pd->instructions = DMREALLOC(pd->instructions, instruction, icount,
pd->instructionslength);
- MZERO(pd->instructions + ipc, instruction, (pd->instructionslength - ipc));
+ MZERO(pd->instructions + icount, instruction,
+ (pd->instructionslength - icount));
/* return the iptr */
- return pd->instructions + ipc;
+ return pd->instructions + icount;
}
methodinfo *m; /* method being parsed */
parsedata_t pd;
instruction *iptr; /* current ptr into instruction array */
- s4 ipc; /* intermediate instruction counter */
+ s4 icount; /* intermediate instruction counter */
s4 p; /* java instruction counter */
s4 nextp; /* start of next java instruction */
s4 opcode; /* java opcode */
/* initialize local variables */
- iptr = pd.instructions;
- ipc = 0;
+ iptr = pd.instructions;
+ icount = 0;
/* mark basic block boundaries for exception table */
/* store intermediate instruction count (bit 0 mark block starts) */
- jd->basicblockindex[p] |= (ipc << 1);
+ jd->basicblockindex[p] |= (icount << 1);
/* compute next instruction start */
case 254:
case 255:
exceptions_throw_verifyerror(m, "Illegal opcode %d at instr %d\n",
- opcode, ipc);
+ opcode, icount);
return false;
break;
#endif /* defined(ENABLE_VERIFIER) */
/* assert that we did not write more ICMDs than allocated */
- assert(ipc <= pd.instructionslength);
- assert(ipc == (iptr - pd.instructions));
+ assert(icount <= pd.instructionslength);
+ assert(icount == (iptr - pd.instructions));
/*** verifier checks ******************************************************/
/*** setup the methodinfo, allocate stack and basic blocks ****************/
- /* adjust block count if target 0 is not first intermediate instruction */
+ /* identify basic blocks */
- if (!jd->basicblockindex[0] || (jd->basicblockindex[0] > 1))
- b_count++;
- else
- jd->branchtoentry = true;
-
- /* copy local to method variables */
+ /* First instruction always starts a basic block, but check if it
+ is already a branch target. */
- jd->instructions = pd.instructions;
- jd->instructioncount = ipc;
- jd->basicblockcount = b_count;
- jd->stackcount = s_count + jd->basicblockcount * m->maxstack; /* in-stacks */
+ if ((jd->basicblockindex[0] == 0) || (jd->basicblockindex[0] > 1)) {
+ iptr = pd.instructions;
- /* allocate stack table */
+ iptr->flags.bits |= INS_FLAG_BASICBLOCK;
- jd->stack = DMNEW(stackelement, jd->stackcount);
+ /* This is the first basic block. */
- /* build basic block list */
-
- bptr = jd->basicblocks = DMNEW(basicblock, b_count + 1); /* one more for end ipc */
-
- /* zero out all basic block structures */
-
- MZERO(bptr, basicblock, b_count + 1);
-
- b_count = 0;
-
- /* additional block if target 0 is not first intermediate instruction */
-
- if (!jd->basicblockindex[0] || (jd->basicblockindex[0] > 1)) {
- BASICBLOCK_INIT(bptr, m);
+ b_count = 1;
+ }
+ else {
+ jd->branchtoentry = true;
- bptr->iinstr = jd->instructions;
- /* bptr->icount is set when the next block is allocated */
+ /* In this case the loop below counts the first basic
+ block. */
- bptr->nr = b_count++;
- bptr++;
- bptr[-1].next = bptr;
+ b_count = 0;
}
- /* allocate blocks */
+ /* Iterate over all bytecode instructions and mark the
+ corresponding IR instruction as basic block starting
+ instruction. */
- for (p = 0; p < m->jcodelength; p++) {
- if (jd->basicblockindex[p] & 1) {
+ for (i = 0; i < m->jcodelength; i++) {
+ if (jd->basicblockindex[i] & 0x1) {
#if defined(ENABLE_VERIFIER)
/* Check if this block starts at the beginning of an
instruction. */
- if (!pd.instructionstart[p]) {
+ if (pd.instructionstart[i] == 0) {
exceptions_throw_verifyerror(m,
"Branch into middle of instruction");
return false;
}
#endif
- /* allocate the block */
+ /* Mark the IR instruction as basic block starting
+ instruction. */
+
+ iptr = pd.instructions + (jd->basicblockindex[i] >> 1);
+
+ 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++;
+ }
+ }
+
+ /* Iterate over all IR instructions and count the basic blocks. */
+
+ iptr = pd.instructions;
+
+ b_count = 0;
+
+ for (i = 0; i < icount; i++, iptr++) {
+ if (INSTRUCTION_STARTS_BASICBLOCK(iptr)) {
+ b_count++;
+ }
+ }
+
+ /* 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);
+
+ /* Now iterate again over all IR instructions and initialize the
+ basic block structures. */
+
+ iptr = pd.instructions;
+ bptr = jd->basicblocks;
+
+ b_count = 0;
+
+ for (i = 0; i < icount; i++, iptr++) {
+ if (INSTRUCTION_STARTS_BASICBLOCK(iptr)) {
+ /* intialize the basic block */
BASICBLOCK_INIT(bptr, m);
- bptr->iinstr = jd->instructions + (jd->basicblockindex[p] >> 1);
- if (b_count) {
+ bptr->iinstr = iptr;
+
+ if (b_count > 0) {
bptr[-1].icount = bptr->iinstr - bptr[-1].iinstr;
}
- /* bptr->icount is set when the next block is allocated */
- jd->basicblockindex[p] = b_count;
+ /* bptr->icount is set when the next block is allocated */
bptr->nr = b_count++;
bptr++;
/* set instruction count of last real block */
- if (b_count) {
- bptr[-1].icount = (jd->instructions + jd->instructioncount) - bptr[-1].iinstr;
+ if (b_count > 0) {
+ bptr[-1].icount = (pd.instructions + icount) - bptr[-1].iinstr;
}
/* allocate additional block at end */
- BASICBLOCK_INIT(bptr,m);
+ BASICBLOCK_INIT(bptr, m);
bptr->nr = b_count;
+
jd->basicblockindex[m->jcodelength] = b_count;
/* set basicblock pointers in exception table */
jd->varcount =
nlocals /* local variables */
- + jd->basicblockcount * m->maxstack /* invars */
+ + b_count * m->maxstack /* invars */
+ s_count; /* variables created within blocks (non-invar) */
/* reserve the first indices for local variables */
VAR(*mapptr)->type = i%5;
}
+ /* 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 */
+
+ /* allocate stack table */
+
+ jd->stack = DMNEW(stackelement, jd->stackcount);
+
/* everything's ok */
return true;
Author: Christian Thalinger
Edwin Steiner
- $Id: parse.h 6162 2006-12-10 21:27:07Z twisti $
+ $Id: parse.h 7619 2007-03-30 11:41:27Z twisti $
*/
} while (0)
#define INSTRUCTIONS_CHECK(i) \
- if ((ipc + (i)) > pd.instructionslength) \
- iptr = parse_realloc_instructions(&pd, ipc, (i))
+ if ((icount + (i)) > pd.instructionslength) \
+ iptr = parse_realloc_instructions(&pd, icount, (i))
/* intermediate code generating macros ****************************************/
/* afterwards. */
#define PINC \
- iptr++; ipc++
+ iptr++; icount++
#define OP_PREPARE_FLAGS(o, f) \
iptr->opc = (o); \
iptr->line = currentline; \
- iptr->flags.bits = (f) | (ipc << INS_FLAG_ID_SHIFT);
+ iptr->flags.bits = (f) | (icount << INS_FLAG_ID_SHIFT);
#define OP_PREPARE_ZEROFLAGS(o) \
OP_PREPARE_FLAGS(o, 0)
Changes:
- $Id: md-asm.h 6182 2006-12-12 21:12:23Z twisti $
+ $Id: md-asm.h 7621 2007-04-01 16:18:16Z stefan $
*/
#define asm_vm_call_method_long _asm_vm_call_method_long
#define asm_vm_call_method_float _asm_vm_call_method_float
#define asm_vm_call_method_double _asm_vm_call_method_double
+#define asm_vm_call_method_end _asm_vm_call_method_end
#define asm_vm_call_method_exception_handler _asm_vm_call_method_exception_handler
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- $Id: md-os.c 7616 2007-03-29 23:21:50Z michi $
+ $Id: md-os.c 7617 2007-03-29 23:22:07Z twisti $
*/
define is 0. */
addr = _mc->gregs[s1];
+ type = EXCEPTION_HARDWARE_NULLPOINTER;
- if (addr == 0)
+ if (addr != 0)
vm_abort("md_signal_handler_sigsegv: faulting address is not NULL: addr=%p", addr);
-
- type = (s4) addr;
}
/* generate appropriate exception */
bte = iptr->sx.s23.s3.bte;
md = bte->md;
- /* XXX: proper builtin calling and float args are so not implemented */
- assert(md->paramcount <= 5 && md->argfltreguse < 1);
+ /* XXX: builtin calling with stack arguments not implemented */
+ assert(md->paramcount <= 5 && md->argfltreguse <= 16);
+
+ s3 = md->paramcount;
+
+ MCODECHECK((s3 << 1) + 64);
+
+ /* copy float arguments according to ABI convention */
+
+ int num_fltregargs = 0;
+ int fltregarg_inswap[16];
+
+ for (s3 = s3 - 1; s3 >= 0; s3--) {
+ var = VAR(iptr->sx.s23.s2.args[s3]);
+
+ if (var->flags & PREALLOC)
+ continue;
+
+ if (IS_FLT_DBL_TYPE(var->type)) {
+ if (!md->params[s3].inmemory) {
+ s1 = md->params[s3].regoff; /*native flt args use regoff directly*/
+ d = emit_load(jd, iptr, var, REG_FTMP1);
+
+ M_DMOV(d, s1 + 16);
+ fltregarg_inswap[num_fltregargs] = s1;
+ num_fltregargs++;
+ /*printf("builtin: flt arg swap to %d\n", s1 + 16);*/
+ }
+ else {
+ assert(0);
+ }
+ }
+ }
+
+ int i;
+ /* move swapped float args to target regs */
+ for (i = 0; i < num_fltregargs; i++) {
+ s1 = fltregarg_inswap[i];
+ M_DMOV(s1 + 16, s1);
+ /*printf("builtin float arg to target reg: %d ==> %d\n", s1+16, s1);*/
+ }
goto gen_method;
}
}
else {
+ if (iptr->opc == ICMD_BUILTIN)
+ continue;
+
if (!md->params[s3].inmemory) {
s1 = rd->argfltregs[md->params[s3].regoff];
d = emit_load(jd, iptr, var, s1);
M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
emit_exception_check(cd, iptr);
+ if (md->returntype.type == TYPE_FLT) {
+ /* special handling for float return value in %f0 */
+ M_FMOV_INTERN(0,1);
+ }
break;
case ICMD_INVOKESPECIAL:
M_DMOV(s1, s2 + 16);
fltregarg_inswap[num_fltregargs] = s2;
num_fltregargs++;
- printf("flt arg swap to %d\n", s2 + 16);
+ /*printf("flt arg swap to %d\n", s2 + 16);*/
} else {
s2 = nmd->params[j].regoff;
for (i = 0; i < num_fltregargs; i++) {
s1 = fltregarg_inswap[i];
M_DMOV(s1 + 16, s1);
- printf("float arg to target reg: %d ==> %d\n", s1+16, s1);
+ /*printf("float arg to target reg: %d ==> %d\n", s1+16, s1);*/
}
#define M_DMOV(rs,rd) M_FOP3_DX(0x02,0x34,0x02,rd,-1,rs) /* rd = rs */
-#define M_FMOV(rs,rd) M_FOP3_FX(0x02,0x34,0x01,rd,-1,rs) /* rd = rs */
+#define M_FMOV(rs,rd) M_FOP3_FX(0x02,0x34,0x01,rd,-1,rs) /* rd = rs */
+
+#define M_FMOV_INTERN(rs,rd) M_FOP3(0x02,0x34,0x01,rd,-1,rs) /* rd = rs */
#define M_FNEG(rs,rd) M_FOP3_FX(0x02,0x34,0x05,rd,-1,rs) /* rd = -rs */
#define M_DNEG(rs,rd) M_FOP3_DX(0x02,0x34,0x06,rd,-1,rs) /* rd = -rs */
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- $Id: stack.c 7483 2007-03-08 13:17:40Z michi $
+ $Id: stack.c 7624 2007-04-02 16:09:44Z twisti $
*/
static basicblock *stack_mark_reached(stackdata_t *sd, basicblock *b, stackptr curstack, int stackdepth)
{
+ assert(b != NULL);
+
#if defined(STACK_VERBOSE)
printf("stack_mark_reached(L%03d from L%03d)\n", b->nr, sd->bptr->nr);
#endif
+
/* mark targets of backward branches */
+
if (b->nr <= sd->bptr->nr)
b->bitflags |= BBFLAG_REPLACEMENT;
static basicblock *stack_mark_reached_from_outvars(stackdata_t *sd, basicblock *b)
{
+ assert(b != NULL);
+
#if defined(STACK_VERBOSE)
printf("stack_mark_reached_from_outvars(L%03d from L%03d)\n", b->nr, sd->bptr->nr);
#endif
+
/* mark targets of backward branches */
+
if (b->nr <= sd->bptr->nr)
b->bitflags |= BBFLAG_REPLACEMENT;
/* stack_reach_next_block ******************************************************
- Mark the following block reached and propagate the outvars of the current block
- and the current locals to it. This function specializes the target block,
- if necessary, and returns a pointer to the specialized target.
+ Mark the following block reached and propagate the outvars of the
+ current block and the current locals to it. This function
+ specializes the target block, if necessary, and returns a pointer
+ to the specialized target.
IN:
sd...........stack analysis data
tbptr = (sd->bptr->original) ? sd->bptr->original : sd->bptr;
tbptr = stack_mark_reached_from_outvars(sd, tbptr->next);
- if (!tbptr)
+
+ if (tbptr == NULL)
return false;
if (tbptr != sd->bptr->next) {
/* initialize loop over basic blocks */
- sd.bptr = jd->basicblocks;
+ sd.bptr = jd->basicblocks;
superblockend = true;
- sd.repeat = false;
- curstack = NULL; stackdepth = 0;
- deadcode = true;
+ sd.repeat = false;
+ curstack = NULL;
+ stackdepth = 0;
+ deadcode = true;
/* iterate over basic blocks *****************************************/
if (sd.bptr->flags == BBTYPECHECK_REACHED) {
/* re-analyse a block because its input changed */
+
deadcode = false;
+
if (!stack_reanalyse_block(&sd))
return false;
+
superblockend = true; /* XXX */
continue;
}
if (superblockend && (sd.bptr->flags < BBREACHED)) {
- /* This block has not been reached so far, and we */
- /* don't fall into it, so we'll have to iterate again. */
+ /* This block has not been reached so far, and we
+ don't fall into it, so we'll have to iterate
+ again. */
sd.repeat = true;
continue;
}
if (sd.bptr->original && sd.bptr->original->flags < BBFINISHED) {
- /* This block is a clone and the original has not been */
- /* analysed, yet. Analyse it on the next iteration. */
+ /* This block is a clone and the original has not been
+ analysed, yet. Analyse it on the next
+ iteration. */
sd.repeat = true;
/* XXX superblockend? */