1 /* jit/parse.c *****************************************************************
3 Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
5 See file COPYRIGHT for information on usage and disclaimer of warranties
7 Parser for JavaVM to intermediate code translation
9 Author: Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
11 Last Change: $Id: parse.c 139 1999-11-11 19:21:30Z andi $
13 *******************************************************************************/
17 /* macros for byte code fetching ***********************************************
19 fetch a byte code of given size from position p in code array jcode
21 *******************************************************************************/
23 #define code_get_u1(p) jcode[p]
24 #define code_get_s1(p) ((s1)jcode[p])
25 #define code_get_u2(p) ((((u2)jcode[p])<<8)+jcode[p+1])
26 #define code_get_s2(p) ((s2)((((u2)jcode[p])<<8)+jcode[p+1]))
27 #define code_get_u4(p) ((((u4)jcode[p])<<24)+(((u4)jcode[p+1])<<16)\
28 +(((u4)jcode[p+2])<<8)+jcode[p+3])
29 #define code_get_s4(p) ((s4)((((u4)jcode[p])<<24)+(((u4)jcode[p+1])<<16)\
30 +(((u4)jcode[p+2])<<8)+jcode[p+3]))
33 /* functionc compiler_addinitclass *********************************************
35 add class into the list of classes to initialize
37 *******************************************************************************/
39 static void compiler_addinitclass (classinfo *c)
43 if (c->initialized) return;
45 cl = chain_first(uninitializedclasses);
50 cl = chain_next(uninitializedclasses);
56 sprintf(logtext, "compiler_addinitclass: ");
57 utf_sprint(logtext+strlen(logtext), c->name);
60 chain_addlast(uninitializedclasses, c);
65 sprintf(logtext, "compiler_addinitclass: ");
66 utf_sprint(logtext+strlen(logtext), c->name);
69 chain_addbefore(uninitializedclasses, c);
72 cl = chain_next(uninitializedclasses);
77 /* function descriptor2types ***************************************************
79 decodes a already checked method descriptor. The parameter count, the
80 return type and the argument types are stored in the passed methodinfo.
82 *******************************************************************************/
84 static void descriptor2types (methodinfo *m)
90 types = DMNEW (u1, m->descriptor->blength);
93 if (!(m->flags & ACC_STATIC)) {
98 utf_ptr = m->descriptor->text + 1;
100 while ((c = *utf_ptr++) != ')') {
107 case 'Z': *tptr++ = TYPE_INT;
109 case 'J': *tptr++ = TYPE_LNG;
111 case 'F': *tptr++ = TYPE_FLT;
113 case 'D': *tptr++ = TYPE_DBL;
115 case 'L': *tptr++ = TYPE_ADR;
116 while (*utf_ptr++ != ';');
118 case '[': *tptr++ = TYPE_ADR;
122 while (*utf_ptr++ != ';') /* skip */;
124 default: panic ("Ill formed methodtype-descriptor");
128 /* compute return type */
130 switch (*utf_ptr++) {
135 case 'Z': m->returntype = TYPE_INT;
137 case 'J': m->returntype = TYPE_LNG;
139 case 'F': m->returntype = TYPE_FLT;
141 case 'D': m->returntype = TYPE_DBL;
144 case 'L': m->returntype = TYPE_ADR;
146 case 'V': m->returntype = TYPE_VOID;
149 default: panic ("Ill formed methodtype-descriptor");
152 m->paramcount = pcount;
153 m->paramtypes = types;
159 /* function allocate_literals **************************************************
161 Scans the JavaVM code of a method and allocates string literals (in the
162 same order as the old JIT). Needed to generate the same addresses as the
165 *******************************************************************************/
167 static void allocate_literals()
174 for (p = 0; p < jcodelength; p = nextp) {
177 nextp = p + jcommandsize[opcode];
181 if (code_get_u1(p + 1) == JAVA_IINC)
187 case JAVA_LOOKUPSWITCH:
188 nextp = ALIGN((p + 1), 4);
189 num = code_get_u4(nextp + 4);
190 nextp = nextp + 8 + 8 * num;
193 case JAVA_TABLESWITCH:
194 nextp = ALIGN ((p + 1),4);
195 num = code_get_s4(nextp + 4);
196 num = code_get_s4(nextp + 8) - num;
197 nextp = nextp + 16 + 4 * num;
201 i = code_get_u1(p+1);
202 goto pushconstantitem;
205 i = code_get_u2(p + 1);
207 if (class_constanttype(class, i) == CONSTANT_String) {
208 s = class_getconstant(class, i, CONSTANT_String);
209 (void) literalstring_new(s);
218 /*******************************************************************************
220 function 'parse' scans the JavaVM code and generates intermediate code
222 During parsing the block index table is used to store at bit pos 0
223 a flag which marks basic block starts and at position 1 to 31 the
224 intermediate instruction index. After parsing the block index table
225 is scanned, for marked positions a block is generated and the block
226 number is stored in the block index table.
228 *******************************************************************************/
230 /* intermediate code generating macros */
232 #define PINC iptr++;ipc++
233 #define LOADCONST_I(v) iptr->opc=ICMD_ICONST;iptr->op1=0;iptr->val.i=(v);PINC
234 #define LOADCONST_L(v) iptr->opc=ICMD_LCONST;iptr->op1=0;iptr->val.l=(v);PINC
235 #define LOADCONST_F(v) iptr->opc=ICMD_FCONST;iptr->op1=0;iptr->val.f=(v);PINC
236 #define LOADCONST_D(v) iptr->opc=ICMD_DCONST;iptr->op1=0;iptr->val.d=(v);PINC
237 #define LOADCONST_A(v) iptr->opc=ICMD_ACONST;iptr->op1=0;iptr->val.a=(v);PINC
238 #define OP(o) iptr->opc=(o);iptr->op1=0;iptr->val.l=0;PINC
239 #define OP1(o,o1) iptr->opc=(o);iptr->op1=(o1);iptr->val.l=(0);PINC
240 #define OP2I(o,o1,v) iptr->opc=(o);iptr->op1=(o1);iptr->val.i=(v);PINC
241 #define OP2A(o,o1,v) iptr->opc=(o);iptr->op1=(o1);iptr->val.a=(v);PINC
242 #define BUILTIN1(v,t) isleafmethod=false;iptr->opc=ICMD_BUILTIN1;iptr->op1=t;\
244 #define BUILTIN2(v,t) isleafmethod=false;iptr->opc=ICMD_BUILTIN2;iptr->op1=t;\
246 #define BUILTIN3(v,t) isleafmethod=false;iptr->opc=ICMD_BUILTIN3;iptr->op1=t;\
250 /* block generating and checking macros */
252 #define block_insert(i) {if(!(block_index[i]&1))\
253 {b_count++;block_index[i] |= 1;}}
254 #define bound_check(i) {if((i< 0) || (i>=jcodelength)) \
255 panic("branch target out of code-boundary");}
256 #define bound_check1(i) {if((i< 0) || (i>jcodelength)) \
257 panic("branch target out of code-boundary");}
262 int p; /* java instruction counter */
263 int nextp; /* start of next java instruction */
264 int opcode; /* java opcode */
265 int i; /* temporary for different uses (counters) */
266 int ipc = 0; /* intermediate instruction counter */
267 int b_count = 0; /* basic block counter */
268 int s_count = 0; /* stack element counter */
269 bool blockend = false; /* true if basic block end has been reached */
270 bool iswide = false; /* true if last instruction was a wide */
271 instruction *iptr; /* current pointer into instruction array */
275 /* generate the same addresses as the old JIT compiler */
281 /* allocate instruction array and block index table */
283 /* 1 additional for end ipc and 3 for loop unrolling */
285 block_index = DMNEW(int, jcodelength + 3);
287 /* 1 additional for TRACEBUILTIN and 4 for MONITORENTER/EXIT */
288 /* additional MONITOREXITS are reached by branches which are 3 bytes */
290 iptr = instr = DMNEW(instruction, jcodelength + 5);
292 /* initialize block_index table (unrolled four times) */
297 for (i = 0, ip = block_index; i <= jcodelength; i += 4, ip += 4) {
305 /* compute branch targets of exception table */
307 extable = DMNEW(xtable, exceptiontablelength + 1);
309 for (i = 0; i < exceptiontablelength; i++) {
311 p = extable[i].startpc = raw_extable[i].startpc;
315 p = extable[i].endpc = raw_extable[i].endpc;
320 p = extable[i].handlerpc = raw_extable[i].handlerpc;
324 extable[i].catchtype = raw_extable[i].catchtype;
326 extable[i].next = NULL;
327 extable[i].down = &extable[i+1];
330 if (exceptiontablelength > 0)
331 extable[exceptiontablelength-1].down = NULL;
335 s_count = 1 + exceptiontablelength; /* initialize stack element counter */
338 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
343 /* scan all java instructions */
345 for (p = 0; p < jcodelength; p = nextp) {
347 opcode = code_get_u1 (p); /* fetch op code */
349 block_index[p] |= (ipc << 1); /* store intermediate count */
352 block_insert(p); /* start new block */
356 nextp = p + jcommandsize[opcode]; /* compute next instruction start */
357 s_count += stackreq[opcode]; /* compute stack element count */
364 /* pushing constants onto the stack p */
367 LOADCONST_I(code_get_s1(p+1));
371 LOADCONST_I(code_get_s2(p+1));
375 i = code_get_u1(p+1);
376 goto pushconstantitem;
379 i = code_get_u2(p + 1);
383 if (i >= class->cpcount)
384 panic ("Attempt to access constant outside range");
386 switch (class->cptags[i]) {
387 case CONSTANT_Integer:
388 LOADCONST_I(((constant_integer*)
389 (class->cpinfos[i]))->value);
392 LOADCONST_L(((constant_long*)
393 (class->cpinfos[i]))->value);
396 LOADCONST_F(((constant_float*)
397 (class->cpinfos[i]))->value);
399 case CONSTANT_Double:
400 LOADCONST_D(((constant_double*)
401 (class->cpinfos[i]))->value);
403 case CONSTANT_String:
404 LOADCONST_A(literalstring_new((utf*)
405 (class->cpinfos[i])));
407 default: panic("Invalid constant type to push");
411 case JAVA_ACONST_NULL:
422 LOADCONST_I(opcode - JAVA_ICONST_0);
427 LOADCONST_L(opcode - JAVA_LCONST_0);
433 LOADCONST_F(opcode - JAVA_FCONST_0);
438 LOADCONST_D(opcode - JAVA_DCONST_0);
441 /* loading variables onto the stack */
449 i = code_get_u1(p+1);
451 i = code_get_u2(p+1);
462 OP1(ICMD_ILOAD, opcode - JAVA_ILOAD_0);
469 OP1(ICMD_LLOAD, opcode - JAVA_LLOAD_0);
476 OP1(ICMD_FLOAD, opcode - JAVA_FLOAD_0);
483 OP1(ICMD_DLOAD, opcode - JAVA_DLOAD_0);
490 OP1(ICMD_ALOAD, opcode - JAVA_ALOAD_0);
493 /* storing stack values into local variables */
501 i = code_get_u1(p+1);
503 i = code_get_u2(p+1);
514 OP1(ICMD_ISTORE, opcode - JAVA_ISTORE_0);
521 OP1(ICMD_LSTORE, opcode - JAVA_LSTORE_0);
528 OP1(ICMD_FSTORE, opcode - JAVA_FSTORE_0);
535 OP1(ICMD_DSTORE, opcode - JAVA_DSTORE_0);
542 OP1(ICMD_ASTORE, opcode - JAVA_ASTORE_0);
550 i = code_get_u1(p + 1);
551 v = code_get_s1(p + 2);
554 i = code_get_u2(p + 1);
555 v = code_get_s2(p + 3);
563 /* wider index for loading, storing and incrementing */
570 /* managing arrays ************************************************/
573 OP2I(ICMD_CHECKASIZE, 0, 0);
574 switch (code_get_s1(p+1)) {
576 BUILTIN1((functionptr)builtin_newarray_boolean, TYPE_ADR);
579 BUILTIN1((functionptr)builtin_newarray_char, TYPE_ADR);
582 BUILTIN1((functionptr)builtin_newarray_float, TYPE_ADR);
585 BUILTIN1((functionptr)builtin_newarray_double, TYPE_ADR);
588 BUILTIN1((functionptr)builtin_newarray_byte, TYPE_ADR);
591 BUILTIN1((functionptr)builtin_newarray_short, TYPE_ADR);
594 BUILTIN1((functionptr)builtin_newarray_int, TYPE_ADR);
597 BUILTIN1((functionptr)builtin_newarray_long, TYPE_ADR);
599 default: panic("Invalid array-type to create");
604 OP2I(ICMD_CHECKASIZE, 0, 0);
605 i = code_get_u2(p+1);
606 /* array or class type ? */
607 if (class_constanttype (class, i) == CONSTANT_Arraydescriptor) {
609 LOADCONST_A(class_getconstant(class, i,
610 CONSTANT_Arraydescriptor));
611 BUILTIN2((functionptr)builtin_newarray_array, TYPE_ADR);
614 LOADCONST_A(class_getconstant(class, i, CONSTANT_Class));
616 BUILTIN2((functionptr)builtin_anewarray, TYPE_ADR);
620 case JAVA_MULTIANEWARRAY:
622 i = code_get_u2(p+1);
624 int v = code_get_u1(p+3);
625 constant_arraydescriptor *desc =
626 class_getconstant (class, i, CONSTANT_Arraydescriptor);
627 OP2A(opcode, v, desc);
649 i = p + code_get_s2(p+1);
657 i = p + code_get_s4(p+1);
666 i = code_get_u1(p+1);
668 i = code_get_u2(p+1);
692 /* table jumps ********************************/
694 case JAVA_LOOKUPSWITCH:
699 nextp = ALIGN((p + 1), 4);
700 OP2A(opcode, 0, jcode + nextp);
704 j = p + code_get_s4(nextp);
705 *((s4*)(jcode + nextp)) = j; /* restore for little endian */
710 /* number of pairs */
712 num = code_get_u4(nextp);
713 *((s4*)(jcode + nextp)) = num;
716 for (i = 0; i < num; i++) {
720 j = code_get_s4(nextp);
721 *((s4*)(jcode + nextp)) = j; /* restore for little endian */
726 j = p + code_get_s4(nextp);
727 *((s4*)(jcode + nextp)) = j; /* restore for little endian */
737 case JAVA_TABLESWITCH:
742 nextp = ALIGN((p + 1), 4);
743 OP2A(opcode, 0, jcode + nextp);
747 j = p + code_get_s4(nextp);
748 *((s4*)(jcode + nextp)) = j; /* restore for little endian */
755 j = code_get_s4(nextp);
756 *((s4*)(jcode + nextp)) = j; /* restore for little endian */
761 num = code_get_s4(nextp);
762 *((s4*)(jcode + nextp)) = num; /* restore for little endian */
767 for (i = 0; i <= num; i++) {
768 j = p + code_get_s4(nextp);
769 *((s4*)(jcode + nextp)) = j; /* restore for little endian */
779 /* load and store of object fields *******************/
782 BUILTIN3((functionptr) asm_builtin_aastore, TYPE_VOID);
787 i = code_get_u2(p + 1);
791 fr = class_getconstant (class, i, CONSTANT_Fieldref);
792 fi = class_findfield (fr->class, fr->name, fr->descriptor);
793 compiler_addinitclass (fr->class);
794 OP2A(opcode, fi->type, fi);
799 i = code_get_u2(p + 1);
803 fr = class_getconstant (class, i, CONSTANT_Fieldref);
804 fi = class_findfield (fr->class, fr->name, fr->descriptor);
805 OP2A(opcode, fi->type, fi);
810 /* method invocation *****/
812 case JAVA_INVOKESTATIC:
813 i = code_get_u2(p + 1);
818 mr = class_getconstant (class, i, CONSTANT_Methodref);
819 mi = class_findmethod (mr->class, mr->name, mr->descriptor);
820 if (! (mi->flags & ACC_STATIC))
821 panic ("Static/Nonstatic mismatch calling static method");
822 descriptor2types(mi);
824 OP2A(opcode, mi->paramcount, mi);
827 case JAVA_INVOKESPECIAL:
828 case JAVA_INVOKEVIRTUAL:
829 i = code_get_u2(p + 1);
834 mr = class_getconstant (class, i, CONSTANT_Methodref);
835 mi = class_findmethod (mr->class, mr->name, mr->descriptor);
836 if (mi->flags & ACC_STATIC)
837 panic ("Static/Nonstatic mismatch calling static method");
838 descriptor2types(mi);
840 OP2A(opcode, mi->paramcount, mi);
843 case JAVA_INVOKEINTERFACE:
844 i = code_get_u2(p + 1);
849 mr = class_getconstant (class, i, CONSTANT_InterfaceMethodref);
850 mi = class_findmethod (mr->class, mr->name, mr->descriptor);
851 if (mi->flags & ACC_STATIC)
852 panic ("Static/Nonstatic mismatch calling static method");
853 descriptor2types(mi);
855 OP2A(opcode, mi->paramcount, mi);
859 /* miscellaneous object operations *******/
862 i = code_get_u2 (p+1);
863 LOADCONST_A(class_getconstant(class, i, CONSTANT_Class));
865 BUILTIN1((functionptr) builtin_new, TYPE_ADR);
869 i = code_get_u2(p+1);
871 /* array type cast-check */
872 if (class_constanttype (class, i) == CONSTANT_Arraydescriptor) {
873 LOADCONST_A(class_getconstant(class, i, CONSTANT_Arraydescriptor));
875 BUILTIN2((functionptr) asm_builtin_checkarraycast, TYPE_ADR);
877 else { /* object type cast-check */
879 LOADCONST_A(class_getconstant(class, i, CONSTANT_Class));
881 BUILTIN2((functionptr) asm_builtin_checkcast, TYPE_ADR);
883 OP2A(opcode, 1, (class_getconstant(class, i, CONSTANT_Class)));
887 case JAVA_INSTANCEOF:
888 i = code_get_u2(p+1);
890 /* array type cast-check */
891 if (class_constanttype (class, i) == CONSTANT_Arraydescriptor) {
892 LOADCONST_A(class_getconstant(class, i, CONSTANT_Arraydescriptor));
894 BUILTIN2((functionptr) builtin_arrayinstanceof, TYPE_INT);
896 else { /* object type cast-check */
898 LOADCONST_A(class_getconstant(class, i, CONSTANT_Class));
900 BUILTIN2((functionptr) builtin_instanceof, TYPE_INT);
902 OP2A(opcode, 1, (class_getconstant(class, i, CONSTANT_Class)));
906 case JAVA_MONITORENTER:
909 #ifdef SOFTNULLPTRCHECK
911 BUILTIN1((functionptr) asm_builtin_monitorenter, TYPE_VOID);
914 /* BUILTIN1((functionptr) builtin_monitorenter, TYPE_VOID); */
915 BUILTIN1((functionptr) asm_builtin_monitorenter, TYPE_VOID);
918 BUILTIN1((functionptr) builtin_monitorenter, TYPE_VOID);
924 OP(ICMD_NULLCHECKPOP);
928 case JAVA_MONITOREXIT:
931 BUILTIN1((functionptr) builtin_monitorexit, TYPE_VOID);
940 /* any other basic operation **************************************/
959 BUILTIN2((functionptr) builtin_frem, TYPE_FLOAT);
963 BUILTIN2((functionptr) builtin_drem, TYPE_DOUBLE);
968 BUILTIN1((functionptr) builtin_f2i, TYPE_INT);
977 BUILTIN1((functionptr) builtin_f2l, TYPE_LONG);
986 BUILTIN1((functionptr) builtin_d2i, TYPE_INT);
995 BUILTIN1((functionptr) builtin_d2l, TYPE_LONG);
1002 case JAVA_BREAKPOINT:
1003 panic("Illegal opcode Breakpoint encountered");
1059 printf("Illegal opcode %d at instr %d", opcode, ipc);
1060 panic("encountered");
1071 if (p != jcodelength)
1072 panic("Command-sequence crosses code-boundary");
1075 panic("Code does not end with branch/return/athrow - stmt");
1077 /* adjust block count if target 0 is not first intermediate instruction */
1079 if (!block_index[0] || (block_index[0] > 1))
1082 /* copy local to global variables */
1085 block_count = b_count;
1086 stack_count = s_count + block_count * maxstack;
1088 /* allocate stack table */
1090 stack = DMNEW(stackelement, stack_count);
1095 bptr = block = DMNEW(basicblock, b_count + 1); /* one more for end ipc */
1100 /* additional block if target 0 is not first intermediate instruction */
1102 if (!block_index[0] || (block_index[0] > 1)) {
1103 bptr->iinstr = instr;
1106 bptr->type = BBTYPE_STD;
1107 bptr->branchrefs = NULL;
1108 bptr->pre_count = 0;
1109 bptr->debug_nr = c_debug_nr++;
1112 (bptr - 1)->next = bptr;
1116 /* allocate blocks */
1119 for (p = 0; p < jcodelength; p++)
1121 if (block_index[p] & 1) {
1122 bptr->iinstr = instr + (block_index[p] >> 1);
1123 bptr->debug_nr = c_debug_nr++;
1125 (bptr - 1)->icount = bptr->iinstr - (bptr - 1)->iinstr;
1129 bptr->type = BBTYPE_STD;
1130 bptr->branchrefs = NULL;
1131 block_index[p] = b_count;
1132 bptr->pre_count = 0;
1136 (bptr - 1)->next = bptr;
1139 /* allocate additional block at end */
1142 bptr->instack = bptr->outstack = NULL;
1143 bptr->indepth = bptr->outdepth = 0;
1144 bptr->iinstr = NULL;
1145 (bptr - 1)->icount = (instr + instr_count) - (bptr - 1)->iinstr;
1150 bptr->type = BBTYPE_STD;
1151 bptr->branchrefs = NULL;
1152 bptr->pre_count = 0;
1153 bptr->debug_nr = c_debug_nr++;
1155 (bptr - 1)->next = bptr;
1162 for (i = 0; i < exceptiontablelength; ++i) {
1163 p = extable[i].startpc;
1164 extable[i].start = block + block_index[p];
1166 p = extable[i].endpc;
1167 extable[i].end = block + block_index[p];
1169 p = extable[i].handlerpc;
1170 extable[i].handler = block + block_index[p];
1177 * These are local overrides for various environment variables in Emacs.
1178 * Please do not remove this and leave it at the end of the file, where
1179 * Emacs will automagically detect them.
1180 * ---------------------------------------------------------------------
1183 * indent-tabs-mode: t