Author: Andreas Krall
Changes: Carolyn Oates
+ Edwin Steiner
- $Id: parse.c 655 2003-11-20 14:52:00Z carolyn $
+ $Id: parse.c 843 2004-01-05 00:50:24Z twisti $
*/
#include <string.h>
#include "parse.h"
#include "global.h"
+#include "main.h"
#include "jit.h"
#include "parseRT.h"
#include "inline.h"
#define debug_writebranch
-
-/* functionc compiler_addinitclass *********************************************
-
- add class into the list of classes to initialize
-
-*******************************************************************************/
-
-void compiler_addinitclass(classinfo *c)
-{
- classinfo *cl;
-
- if (c->initialized) return;
-
- cl = chain_first(uninitializedclasses);
- if (cl == c)
- return;
-
- if (cl == class)
- cl = chain_next(uninitializedclasses);
- for (;;) {
- if (cl == c)
- return;
- if (cl == NULL) {
- if (runverbose) {
- sprintf(logtext, "compiler_addinitclass: ");
- utf_sprint(logtext+strlen(logtext), c->name);
- dolog();
- }
- chain_addlast(uninitializedclasses, c);
- return;
- }
- if (c < cl) {
- if (runverbose) {
- sprintf(logtext, "compiler_addinitclass: ");
- utf_sprint(logtext+strlen(logtext), c->name);
- dolog();
- }
- chain_addbefore(uninitializedclasses, c);
- return;
- }
- cl = chain_next(uninitializedclasses);
- }
-}
-
-
-
/* function descriptor2typesL ***************************************************
decodes a already checked method descriptor. The parameter count, the
#define BUILTIN3(v,t) isleafmethod=false;iptr->opc=ICMD_BUILTIN3;iptr->op1=t;\
iptr->val.a=(v);PINC
+#define INDEX_ONEWORD(num) \
+ do { if((num)<0 || (num)>=maxlocals) \
+ panic("Invalid local variable index"); } while (0)
+#define INDEX_TWOWORD(num) \
+ do { if((num)<0 || ((num)+1)>=maxlocals) \
+ panic("Invalid local variable index"); } while (0)
+
+#define OP1LOAD(o,o1) \
+ do {if (o == ICMD_LLOAD || o == ICMD_DLOAD) \
+ INDEX_TWOWORD(o1); \
+ else \
+ INDEX_ONEWORD(o1); \
+ OP1(o,o1);} while(0)
+
+#define OP1STORE(o,o1) \
+ do {if (o == ICMD_LSTORE || o == ICMD_DSTORE) \
+ INDEX_TWOWORD(o1); \
+ else \
+ INDEX_ONEWORD(o1); \
+ OP1(o,o1);} while(0)
/* block generating and checking macros */
} \
} while (0)
+/* bound_check1 is used for the inclusive ends of exception handler ranges */
#define bound_check1(i) \
do { \
if (i < 0 || i > cumjcodelength) { \
return extable;
b_count = *block_count;
+
for (i = 0; i < exceptiontablelength; i++) {
-
p = raw_extable[i].startpc;
if (label_index != NULL) p = label_index[p];
extable[i].startpc = p;
block_insert(p);
p = raw_extable[i].endpc;
+ if (p <= raw_extable[i].startpc)
+ panic("Invalid exception handler range");
if (label_index != NULL) p = label_index[p];
extable[i].endpc = p;
bound_check1(p);
extable[i].catchtype = raw_extable[i].catchtype;
extable[i].next = NULL;
- extable[i].down = &extable[i+1];
- }
+ extable[i].down = &extable[i + 1];
+ }
+
*block_count = b_count;
return &extable[i]; /* return the next free xtable* */
}
int *label_index = NULL; /* label redirection table */
int firstlocal = 0; /* first local variable of method */
xtable* nextex; /* points next free entry in extable */
+ u1 *instructionstart; /* 1 for pcs which are valid instr. starts */
bool useinltmp;
+ if (compileverbose) {
+ char logtext[MAXLOGTEXT];
+ sprintf(logtext, "Parsing: ");
+ utf_sprint(logtext+strlen(logtext), method->class->name);
+ strcpy(logtext+strlen(logtext), ".");
+ utf_sprint(logtext+strlen(logtext), method->name);
+ utf_sprint(logtext+strlen(logtext), method->descriptor);
+ log_text(logtext);
+ }
+
/* INLINING */
if (useinlining) {
label_index = inlinfo->label_index;
/* 1 additional for end ipc and 3 for loop unrolling */
block_index = DMNEW(int, cumjcodelength + 4);
+ instructionstart = DMNEW(u1, cumjcodelength + 4);
+ memset(instructionstart,0,sizeof(u1) * (cumjcodelength + 4));
/* 1 additional for TRACEBUILTIN and 4 for MONITORENTER/EXIT */
/* additional MONITOREXITS are reached by branches which are 3 bytes */
iptr = instr = DMNEW(instruction, cumjcodelength + 5);
+
+ /* XXX zero fields in the instructions loop? */
+ memset(iptr,0,sizeof(instruction) * (cumjcodelength + 5));
/* initialize block_index table (unrolled four times) */
for (p = 0, gp = 0; p < jcodelength; gp += (nextp - p), p = nextp) {
- /* DEBUG printf("p:%d gp:%d ",p,gp); */
+ /* DEBUG XXX */ /*printf("p:%d gp:%d ",p,gp);*/
+
+ /* mark this position as a valid instruction start */
+ if (!iswide)
+ instructionstart[p] = 1;
/*INLINING*/
if ((useinlining) && (gp == nextgp)) {
opcode = code_get_u1(p);
nextp = p += jcommandsize[opcode];
+ if (nextp > jcodelength)
+ panic("Unexpected end of bytecode");
tmpinlinf = list_first(inlinfo->inlinedmethods);
firstlocal = tmpinlinf->firstlocal;
label_index = tmpinlinf->label_index;
}
nextp = p + jcommandsize[opcode]; /* compute next instruction start */
+ if (nextp > jcodelength)
+ panic("Unexpected end of bytecode");
s_count += stackreq[opcode]; /* compute stack element count */
switch (opcode) {
nextp = p + 3;
iswide = false;
}
- OP1(opcode, i + firstlocal);
+ OP1LOAD(opcode, i + firstlocal);
break;
case JAVA_ILOAD_0:
case JAVA_ILOAD_1:
case JAVA_ILOAD_2:
case JAVA_ILOAD_3:
- OP1(ICMD_ILOAD, opcode - JAVA_ILOAD_0 + firstlocal);
+ OP1LOAD(ICMD_ILOAD, opcode - JAVA_ILOAD_0 + firstlocal);
break;
case JAVA_LLOAD_0:
case JAVA_LLOAD_1:
case JAVA_LLOAD_2:
case JAVA_LLOAD_3:
- OP1(ICMD_LLOAD, opcode - JAVA_LLOAD_0 + firstlocal);
+ OP1LOAD(ICMD_LLOAD, opcode - JAVA_LLOAD_0 + firstlocal);
break;
case JAVA_FLOAD_0:
case JAVA_FLOAD_1:
case JAVA_FLOAD_2:
case JAVA_FLOAD_3:
- OP1(ICMD_FLOAD, opcode - JAVA_FLOAD_0 + firstlocal);
+ OP1LOAD(ICMD_FLOAD, opcode - JAVA_FLOAD_0 + firstlocal);
break;
case JAVA_DLOAD_0:
case JAVA_DLOAD_1:
case JAVA_DLOAD_2:
case JAVA_DLOAD_3:
- OP1(ICMD_DLOAD, opcode - JAVA_DLOAD_0 + firstlocal);
+ OP1LOAD(ICMD_DLOAD, opcode - JAVA_DLOAD_0 + firstlocal);
break;
case JAVA_ALOAD_0:
case JAVA_ALOAD_1:
case JAVA_ALOAD_2:
case JAVA_ALOAD_3:
- OP1(ICMD_ALOAD, opcode - JAVA_ALOAD_0 + firstlocal);
+ OP1LOAD(ICMD_ALOAD, opcode - JAVA_ALOAD_0 + firstlocal);
break;
/* storing stack values into local variables */
iswide = false;
nextp = p + 3;
}
- OP1(opcode, i + firstlocal);
+ OP1STORE(opcode, i + firstlocal);
break;
case JAVA_ISTORE_0:
case JAVA_ISTORE_1:
case JAVA_ISTORE_2:
case JAVA_ISTORE_3:
- OP1(ICMD_ISTORE, opcode - JAVA_ISTORE_0 + firstlocal);
+ OP1STORE(ICMD_ISTORE, opcode - JAVA_ISTORE_0 + firstlocal);
break;
case JAVA_LSTORE_0:
case JAVA_LSTORE_1:
case JAVA_LSTORE_2:
case JAVA_LSTORE_3:
- OP1(ICMD_LSTORE, opcode - JAVA_LSTORE_0 + firstlocal);
+ OP1STORE(ICMD_LSTORE, opcode - JAVA_LSTORE_0 + firstlocal);
break;
case JAVA_FSTORE_0:
case JAVA_FSTORE_1:
case JAVA_FSTORE_2:
case JAVA_FSTORE_3:
- OP1(ICMD_FSTORE, opcode - JAVA_FSTORE_0 + firstlocal);
+ OP1STORE(ICMD_FSTORE, opcode - JAVA_FSTORE_0 + firstlocal);
break;
case JAVA_DSTORE_0:
case JAVA_DSTORE_1:
case JAVA_DSTORE_2:
case JAVA_DSTORE_3:
- OP1(ICMD_DSTORE, opcode - JAVA_DSTORE_0 + firstlocal);
+ OP1STORE(ICMD_DSTORE, opcode - JAVA_DSTORE_0 + firstlocal);
break;
case JAVA_ASTORE_0:
case JAVA_ASTORE_1:
case JAVA_ASTORE_2:
case JAVA_ASTORE_3:
- OP1(ICMD_ASTORE, opcode - JAVA_ASTORE_0 + firstlocal);
+ OP1STORE(ICMD_ASTORE, opcode - JAVA_ASTORE_0 + firstlocal);
break;
case JAVA_IINC:
iswide = false;
nextp = p + 5;
}
+ INDEX_ONEWORD(i + firstlocal);
OP2I(opcode, i + firstlocal, v);
}
break;
OP2I(ICMD_CHECKASIZE, 0, 0);
switch (code_get_s1(p + 1)) {
case 4:
- BUILTIN1((functionptr) builtin_newarray_boolean, TYPE_ADR);
+ BUILTIN1(BUILTIN_newarray_boolean, TYPE_ADR);
break;
case 5:
- BUILTIN1((functionptr) builtin_newarray_char, TYPE_ADR);
+ BUILTIN1(BUILTIN_newarray_char, TYPE_ADR);
break;
case 6:
- BUILTIN1((functionptr) builtin_newarray_float, TYPE_ADR);
+ BUILTIN1(BUILTIN_newarray_float, TYPE_ADR);
break;
case 7:
- BUILTIN1((functionptr) builtin_newarray_double, TYPE_ADR);
+ BUILTIN1(BUILTIN_newarray_double, TYPE_ADR);
break;
case 8:
- BUILTIN1((functionptr) builtin_newarray_byte, TYPE_ADR);
+ BUILTIN1(BUILTIN_newarray_byte, TYPE_ADR);
break;
case 9:
- BUILTIN1((functionptr) builtin_newarray_short, TYPE_ADR);
+ BUILTIN1(BUILTIN_newarray_short, TYPE_ADR);
break;
case 10:
- BUILTIN1((functionptr) builtin_newarray_int, TYPE_ADR);
+ BUILTIN1(BUILTIN_newarray_int, TYPE_ADR);
break;
case 11:
- BUILTIN1((functionptr) builtin_newarray_long, TYPE_ADR);
+ BUILTIN1(BUILTIN_newarray_long, TYPE_ADR);
break;
default: panic("Invalid array-type to create");
}
case JAVA_ANEWARRAY:
OP2I(ICMD_CHECKASIZE, 0, 0);
i = code_get_u2(p + 1);
- /* array or class type ? */
- if (class_constanttype (class, i) == CONSTANT_Arraydescriptor) {
- s_count++;
- LOADCONST_A(class_getconstant(class, i,
- CONSTANT_Arraydescriptor));
-#if defined(__I386__)
- BUILTIN2((functionptr) asm_builtin_newarray_array, TYPE_ADR);
-#else
- BUILTIN2((functionptr) builtin_newarray_array, TYPE_ADR);
-#endif
- }
- else {
- LOADCONST_A(class_getconstant(class, i, CONSTANT_Class));
+ {
+ classinfo *component = (classinfo*)class_getconstant(class, i, CONSTANT_Class);
+ LOADCONST_A(class_array_of(component)->vftbl);
+
s_count++;
-#if defined(__I386__)
- BUILTIN2((functionptr) asm_builtin_anewarray, TYPE_ADR);
-#else
- BUILTIN2((functionptr) builtin_anewarray, TYPE_ADR);
-#endif
+
+ BUILTIN2(BUILTIN_newarray, TYPE_ADR);
}
break;
i = code_get_u2(p + 1);
{
int v = code_get_u1(p + 3);
- constant_arraydescriptor *desc =
- class_getconstant (class, i, CONSTANT_Arraydescriptor);
- OP2A(opcode, v, desc);
+ vftbl *arrayvftbl = ((classinfo*)class_getconstant (class, i, CONSTANT_Class))->vftbl;
+ OP2A(opcode, v, arrayvftbl);
}
break;
break;
}*/
- OP1(opcode, i + firstlocal);
+ OP1LOAD(opcode, i + firstlocal);
break;
case JAVA_IRETURN:
{
s4 num, j;
s4 *tablep;
+ s4 prevvalue;
blockend = true;
nextp = ALIGN((p + 1), 4);
+ if (nextp + 8 > jcodelength)
+ panic("Unexpected end of bytecode");
if (!useinlining) {
tablep = (s4*)(jcode + nextp);
tablep++;
nextp += 4;
+ if (nextp + 8*(num) > jcodelength)
+ panic("Unexpected end of bytecode");
+
for (i = 0; i < num; i++) {
/* value */
tablep++;
nextp += 4;
+ /* check if the lookup table is sorted correctly */
+
+ if (i && (j <= prevvalue))
+ panic("invalid LOOKUPSWITCH: table not sorted");
+ prevvalue = j;
+
/* target */
j = p + code_get_s4(nextp);
blockend = true;
nextp = ALIGN((p + 1), 4);
+ if (nextp + 12 > jcodelength)
+ panic("Unexpected end of bytecode");
if (!useinlining) {
tablep = (s4*)(jcode + nextp);
tablep++;
nextp += 4;
- num -= j;
+ num -= j; /* difference of upper - lower */
+ if (num < 0)
+ panic("invalid TABLESWITCH: upper bound < lower bound");
+
+ if (nextp + 4*(num+1) > jcodelength)
+ panic("Unexpected end of bytecode");
for (i = 0; i <= num; i++) {
j = p + code_get_s4(nextp);
/* load and store of object fields *******************/
case JAVA_AASTORE:
- BUILTIN3((functionptr) asm_builtin_aastore, TYPE_VOID);
+ BUILTIN3(BUILTIN_aastore, TYPE_VOID);
break;
case JAVA_PUTSTATIC:
{
constant_FMIref *fr;
fieldinfo *fi;
- fr = class_getconstant (class, i, CONSTANT_Fieldref);
- fi = class_findfield (fr->class, fr->name, fr->descriptor);
- compiler_addinitclass (fr->class);
+ fr = class_getconstant(class, i, CONSTANT_Fieldref);
+ fi = class_findfield(fr->class, fr->name, fr->descriptor);
OP2A(opcode, fi->type, fi);
}
break;
methodinfo *mi;
mr = class_getconstant (class, i, CONSTANT_Methodref);
- mi = class_findmethod (mr->class, mr->name, mr->descriptor);
+ mi = class_fetchmethod (mr->class, mr->name, mr->descriptor);
/*RTAprint*/ if (((pOpcodes == 2) || (pOpcodes == 3)) && opt_rt)
/*RTAprint*/ {printf(" method name =");
/*RTAprint*/ utf_display(mi->class->name); printf(".");
{
constant_FMIref *mr;
methodinfo *mi;
-
+
mr = class_getconstant (class, i, CONSTANT_Methodref);
- mi = class_findmethod (mr->class, mr->name, mr->descriptor);
+ mi = class_fetchmethod (mr->class, mr->name, mr->descriptor);
/*RTAprint*/ if (((pOpcodes == 2) || (pOpcodes == 3)) && opt_rt)
/*RTAprint*/ {printf(" method name =");
method_display(mi);
methodinfo *mi;
mr = class_getconstant (class, i, CONSTANT_InterfaceMethodref);
- mi = class_findmethod (mr->class, mr->name, mr->descriptor);
+ mi = class_fetchmethod (mr->class, mr->name, mr->descriptor);
if (mi->flags & ACC_STATIC)
panic ("Static/Nonstatic mismatch calling static method");
descriptor2types(mi);
LOADCONST_A(class_getconstant(class, i, CONSTANT_Class));
s_count++;
- BUILTIN1((functionptr) builtin_new, TYPE_ADR);
+ BUILTIN1(BUILTIN_new, TYPE_ADR);
break;
case JAVA_CHECKCAST:
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ isleafmethod = false;
+#endif
i = code_get_u2(p+1);
+ {
+ classinfo *cls = (classinfo*)class_getconstant(class, i, CONSTANT_Class);
+ if (cls->vftbl->arraydesc) {
+ /* array type cast-check */
+ LOADCONST_A(cls->vftbl);
+ s_count++;
+ BUILTIN2(BUILTIN_checkarraycast, TYPE_ADR);
+ }
+ else { /* object type cast-check */
+ /*
++ LOADCONST_A(class_getconstant(class, i, CONSTANT_Class));
++ s_count++;
++ BUILTIN2(BUILTIN_checkcast, TYPE_ADR);
++ */
+ OP2A(opcode, 1, cls);
+ }
+ }
- /* array type cast-check */
- if (class_constanttype (class, i) == CONSTANT_Arraydescriptor) {
- LOADCONST_A(class_getconstant(class, i, CONSTANT_Arraydescriptor));
- s_count++;
- BUILTIN2((functionptr) asm_builtin_checkarraycast, TYPE_ADR);
- }
- else { /* object type cast-check */
- /*
- LOADCONST_A(class_getconstant(class, i, CONSTANT_Class));
- s_count++;
- BUILTIN2((functionptr) asm_builtin_checkcast, TYPE_ADR);
- */
- OP2A(opcode, 1, (class_getconstant(class, i, CONSTANT_Class)));
- }
break;
case JAVA_INSTANCEOF:
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ isleafmethod = false;
+#endif
i = code_get_u2(p+1);
- /* array type cast-check */
- if (class_constanttype (class, i) == CONSTANT_Arraydescriptor) {
- LOADCONST_A(class_getconstant(class, i, CONSTANT_Arraydescriptor));
- s_count++;
-#if defined(__I386__)
- BUILTIN2((functionptr) asm_builtin_arrayinstanceof, TYPE_INT);
-#else
- BUILTIN2((functionptr) builtin_arrayinstanceof, TYPE_INT);
-#endif
- }
- else { /* object type cast-check */
- /*
- LOADCONST_A(class_getconstant(class, i, CONSTANT_Class));
- s_count++;
- BUILTIN2((functionptr) builtin_instanceof, TYPE_INT);
- */
- OP2A(opcode, 1, (class_getconstant(class, i, CONSTANT_Class)));
- }
+ {
+ classinfo *cls = (classinfo*)class_getconstant(class, i, CONSTANT_Class);
+ if (cls->vftbl->arraydesc) {
+ /* array type cast-check */
+ LOADCONST_A(cls->vftbl);
+ s_count++;
+ BUILTIN2(BUILTIN_arrayinstanceof, TYPE_INT);
+ }
+ else { /* object type cast-check */
+ /*
+ LOADCONST_A(class_getconstant(class, i, CONSTANT_Class));
+ s_count++;
+ BUILTIN2(BUILTIN_instanceof, TYPE_INT);
++ */
+ OP2A(opcode, 1, cls);
+ }
+ }
break;
case JAVA_MONITORENTER:
#ifdef USE_THREADS
if (checksync) {
- BUILTIN1((functionptr) asm_builtin_monitorenter, TYPE_VOID);
+ BUILTIN1(BUILTIN_monitorenter, TYPE_VOID);
} else
#endif
{
case JAVA_MONITOREXIT:
#ifdef USE_THREADS
if (checksync) {
- BUILTIN1((functionptr) asm_builtin_monitorexit, TYPE_VOID);
+ BUILTIN1(BUILTIN_monitorexit, TYPE_VOID);
}
else
#endif
#if defined(__I386__)
OP(opcode);
#else
- BUILTIN2((functionptr) builtin_frem, TYPE_FLOAT);
+ BUILTIN2(BUILTIN_frem, TYPE_FLOAT);
#endif
break;
#if defined(__I386__)
OP(opcode);
#else
- BUILTIN2((functionptr) builtin_drem, TYPE_DOUBLE);
+ BUILTIN2(BUILTIN_drem, TYPE_DOUBLE);
#endif
break;
case JAVA_F2I:
#if defined(__ALPHA__)
if (!opt_noieee) {
- BUILTIN1((functionptr) builtin_f2i, TYPE_INT);
+ BUILTIN1(BUILTIN_f2i, TYPE_INT);
} else
#endif
{
case JAVA_F2L:
#if defined(__ALPHA__)
if (!opt_noieee) {
- BUILTIN1((functionptr) builtin_f2l, TYPE_LONG);
+ BUILTIN1(BUILTIN_f2l, TYPE_LONG);
} else
#endif
{
case JAVA_D2I:
#if defined(__ALPHA__)
if (!opt_noieee) {
- BUILTIN1((functionptr) builtin_d2i, TYPE_INT);
+ BUILTIN1(BUILTIN_d2i, TYPE_INT);
} else
#endif
{
case JAVA_D2L:
#if defined(__ALPHA__)
if (!opt_noieee) {
- BUILTIN1((functionptr) builtin_d2l, TYPE_LONG);
+ BUILTIN1(BUILTIN_d2l, TYPE_LONG);
} else
#endif
{
panic("Illegal opcode Breakpoint encountered");
break;
+ case 186: /* unused opcode */
case 203:
case 204:
case 205:
case 253:
case 254:
case 255:
- printf("Illegal opcode %d at instr %d", opcode, ipc);
- panic("encountered");
+ printf("Illegal opcode %d at instr %d\n", opcode, ipc);
+ panic("Illegal opcode encountered");
break;
default:
break;
} /* end switch */
+
+ /* If WIDE was used correctly, iswide should have been reset by now. */
+ if (iswide && opcode != JAVA_WIDE)
+ panic("Illegal instruction: WIDE before incompatible opcode");
/* INLINING */
} /* end for */
if (p != jcodelength)
- panic("Command-sequence crosses code-boundary");
+ panic("Command-sequence crosses code-boundary"); /* XXX change message */
if (!blockend)
panic("Code does not end with branch/return/athrow - stmt");
for (p = 0; p < cumjcodelength; p++) {
if (block_index[p] & 1) {
+ /* check if this block starts at the beginning of an instruction */
+ if (!instructionstart[p])
+ panic("Branch into middle of instruction");
+ /* allocate the block */
bptr->iinstr = instr + (block_index[p] >> 1);
bptr->debug_nr = c_debug_nr++;
if (b_count != 0)