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: 1998/05/07
13 *******************************************************************************/
18 /* macros for byte code fetching ***********************************************
20 fetch a byte code of given size from position pos
22 *******************************************************************************/
24 #define code_get_u1(pos) jcode[pos]
25 #define code_get_s1(pos) ((s1)jcode[pos])
26 #define code_get_u2(pos) ((((u2)jcode[pos])<<8)+jcode[pos+1])
27 #define code_get_s2(pos) ((s2)((((u2)jcode[pos])<<8)+jcode[pos+1]))
28 #define code_get_u4(pos) ((((u4)jcode[pos])<<24)+(((u4)jcode[pos+1])<<16)+\
29 (((u4)jcode[pos+2])<<8)+jcode[pos+3])
30 #define code_get_s4(pos) ((s4)((((u4)jcode[pos])<<24)+(((u4)jcode[pos+1])<<16)+\
31 (((u4)jcode[pos+2])<<8)+jcode[pos+3]))
34 /* functionc compiler_addinitclass *********************************************
36 add class into the list of classes to initialize
38 *******************************************************************************/
40 static void compiler_addinitclass (classinfo *c)
44 if (c->initialized) return;
46 cl = chain_first(uninitializedclasses);
51 cl = chain_next(uninitializedclasses);
57 sprintf(logtext, "compiler_addinitclass: ");
58 unicode_sprint(logtext+strlen(logtext), c->name);
61 chain_addlast(uninitializedclasses, c);
66 sprintf(logtext, "compiler_addinitclass: ");
67 unicode_sprint(logtext+strlen(logtext), c->name);
70 chain_addbefore(uninitializedclasses, c);
73 cl = chain_next(uninitializedclasses);
78 /* function descriptor2types ***************************************************
80 decodes a already checked method descriptor. The parameter count, the
81 return type and the argument types are stored in the passed methodinfo.
83 *******************************************************************************/
85 static void descriptor2types (methodinfo *m)
92 types = DMNEW (u1, m->descriptor->length);
95 if (!(m->flags & ACC_STATIC)) {
100 cptr = m->descriptor->text;
102 while ((c = *cptr++) != ')') {
109 case 'Z': *tptr++ = TYPE_INT;
111 case 'J': *tptr++ = TYPE_LNG;
113 case 'F': *tptr++ = TYPE_FLT;
115 case 'D': *tptr++ = TYPE_DBL;
117 case 'L': *tptr++ = TYPE_ADR;
118 while (*cptr++ != ';');
120 case '[': *tptr++ = TYPE_ADR;
124 while (*cptr++ != ';') /* skip */;
126 default: panic ("Ill formed methodtype-descriptor");
130 /* compute return type */
137 case 'Z': m->returntype = TYPE_INT;
139 case 'J': m->returntype = TYPE_LNG;
141 case 'F': m->returntype = TYPE_FLT;
143 case 'D': m->returntype = TYPE_DBL;
146 case 'L': m->returntype = TYPE_ADR;
148 case 'V': m->returntype = TYPE_VOID;
151 default: panic ("Ill formed methodtype-descriptor");
154 m->paramcount = pcount;
155 m->paramtypes = types;
159 /* function allocate_literals **************************************************
161 Scans the JavaVM code of a method and allocates string literals. Needed
162 to generate the same addresses as the old JIT compiler.
164 *******************************************************************************/
166 static void allocate_literals()
173 for (p = 0; p < jcodelength; p = nextp) {
176 nextp = p + jcommandsize[opcode];
180 if (code_get_u1(p + 1) == JAVA_IINC)
186 case JAVA_LOOKUPSWITCH:
187 nextp = ALIGN((p + 1), 4);
188 num = code_get_u4(nextp + 4);
189 nextp = nextp + 8 + 8 * num;
192 case JAVA_TABLESWITCH:
193 nextp = ALIGN ((p + 1),4);
194 num = code_get_s4(nextp + 4);
195 num = code_get_s4(nextp + 8) - num;
196 nextp = nextp + 16 + 4 * num;
200 i = code_get_u1(p+1);
201 goto pushconstantitem;
204 i = code_get_u2(p + 1);
206 if (class_constanttype(class, i) == CONSTANT_String) {
207 s = class_getconstant(class, i, CONSTANT_String);
208 (void) literalstring_new(s);
217 /*******************************************************************************
219 function 'parse' scans the JavaVM code and generates intermediate code
221 During parsing the block index table is used to store at bit pos 0
222 a flag which marks basic block starts and at position 1 to 31 the
223 intermediate instruction index. After parsing the block index table
224 is scanned, for marked positions a block is generated and the block
225 number is stored in the block index table.
227 *******************************************************************************/
229 /* intermediate code generating macros */
231 #define PINC iptr++;ipc++
232 #define LOADCONST_I(v) iptr->opc=ICMD_ICONST;iptr->op1=0;iptr->val.i=(v);PINC
233 #define LOADCONST_L(v) iptr->opc=ICMD_LCONST;iptr->op1=0;iptr->val.l=(v);PINC
234 #define LOADCONST_F(v) iptr->opc=ICMD_FCONST;iptr->op1=0;iptr->val.f=(v);PINC
235 #define LOADCONST_D(v) iptr->opc=ICMD_DCONST;iptr->op1=0;iptr->val.d=(v);PINC
236 #define LOADCONST_A(v) iptr->opc=ICMD_ACONST;iptr->op1=0;iptr->val.a=(v);PINC
237 #define OP(o) iptr->opc=(o);iptr->op1=0;iptr->val.l=0;PINC
238 #define OP1(o,o1) iptr->opc=(o);iptr->op1=(o1);iptr->val.l=(0);PINC
239 #define OP2I(o,o1,v) iptr->opc=(o);iptr->op1=(o1);iptr->val.i=(v);PINC
240 #define OP2A(o,o1,v) iptr->opc=(o);iptr->op1=(o1);iptr->val.a=(v);PINC
241 #define BUILTIN1(v,t) isleafmethod=false;iptr->opc=ICMD_BUILTIN1;iptr->op1=t;\
243 #define BUILTIN2(v,t) isleafmethod=false;iptr->opc=ICMD_BUILTIN2;iptr->op1=t;\
245 #define BUILTIN3(v,t) isleafmethod=false;iptr->opc=ICMD_BUILTIN3;iptr->op1=t;\
249 /* block generating and checking macros */
251 #define block_insert(i) {if(!(block_index[i]&1))\
252 {b_count++;block_index[i] |= 1;}}
253 #define bound_check(i) {if((i< 0) || (i>=jcodelength)) \
254 panic("branch target out of code-boundary");}
255 #define bound_check1(i) {if((i< 0) || (i>jcodelength)) \
256 panic("branch target out of code-boundary");}
261 int p; /* java instruction counter */
262 int nextp; /* start of next java instruction */
263 int opcode; /* java opcode */
264 int i; /* temporary for different uses (counters) */
265 int ipc = 0; /* intermediate instruction counter */
266 int b_count = 0; /* basic block counter */
267 int s_count = 0; /* stack element counter */
268 bool blockend = false; /* true if basic block end has reached */
269 bool iswide = false; /* true if last instruction was a wide */
270 instruction *iptr; /* current pointer into instruction array */
273 /* allocate instruction array and block index table */
275 /* 1 additional for end ipc and 3 for loop unrolling */
277 block_index = DMNEW(int, jcodelength + 3);
279 /* 1 additional for TRACEBUILTIN and 4 for MONITORENTER/EXIT */
280 /* additional MONITOREXITS are reached by branches which are 3 bytes */
282 iptr = instr = DMNEW(instruction, jcodelength + 5);
284 /* initialize block_index table (unrolled four times) */
289 for (i = 0, ip = block_index; i <= jcodelength; i += 4, ip += 4) {
297 /* compute branch targets of exception table */
299 for (i = 0; i < exceptiontablelength; i++) {
300 p = extable[i].startpc;
303 p = extable[i].endpc;
307 p = extable[i].handlerpc;
312 s_count = 1 + exceptiontablelength; /* initialize stack element counter */
315 /* isleafmethod=false; */
319 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
324 /* scan all java instructions */
326 for (p = 0; p < jcodelength; p = nextp) {
328 opcode = code_get_u1 (p); /* fetch op code */
330 block_index[p] |= (ipc << 1); /* store intermediate count */
333 block_insert(p); /* start new block */
337 nextp = p + jcommandsize[opcode]; /* compute next instruction start */
338 s_count += stackreq[opcode]; /* compute stack element count */
345 /* pushing constants onto the stack p */
348 LOADCONST_I(code_get_s1(p+1));
352 LOADCONST_I(code_get_s2(p+1));
356 i = code_get_u1(p+1);
357 goto pushconstantitem;
360 i = code_get_u2(p + 1);
364 if (i >= class->cpcount)
365 panic ("Attempt to access constant outside range");
367 switch (class->cptags[i]) {
368 case CONSTANT_Integer:
369 LOADCONST_I(((constant_integer*)
370 (class->cpinfos[i]))->value);
373 LOADCONST_L(((constant_long*)
374 (class->cpinfos[i]))->value);
377 LOADCONST_F(((constant_float*)
378 (class->cpinfos[i]))->value);
380 case CONSTANT_Double:
381 LOADCONST_D(((constant_double*)
382 (class->cpinfos[i]))->value);
384 case CONSTANT_String:
385 LOADCONST_A(literalstring_new((unicode*)
386 (class->cpinfos[i])));
388 default: panic("Invalid constant type to push");
392 case JAVA_ACONST_NULL:
403 LOADCONST_I(opcode - JAVA_ICONST_0);
408 LOADCONST_L(opcode - JAVA_LCONST_0);
414 LOADCONST_F(opcode - JAVA_FCONST_0);
419 LOADCONST_D(opcode - JAVA_DCONST_0);
422 /* loading variables onto the stack */
430 i = code_get_u1(p+1);
432 i = code_get_u2(p+1);
443 OP1(ICMD_ILOAD, opcode - JAVA_ILOAD_0);
450 OP1(ICMD_LLOAD, opcode - JAVA_LLOAD_0);
457 OP1(ICMD_FLOAD, opcode - JAVA_FLOAD_0);
464 OP1(ICMD_DLOAD, opcode - JAVA_DLOAD_0);
471 OP1(ICMD_ALOAD, opcode - JAVA_ALOAD_0);
474 /* storing stack values into local variables */
482 i = code_get_u1(p+1);
484 i = code_get_u2(p+1);
495 OP1(ICMD_ISTORE, opcode - JAVA_ISTORE_0);
502 OP1(ICMD_LSTORE, opcode - JAVA_LSTORE_0);
509 OP1(ICMD_FSTORE, opcode - JAVA_FSTORE_0);
516 OP1(ICMD_DSTORE, opcode - JAVA_DSTORE_0);
523 OP1(ICMD_ASTORE, opcode - JAVA_ASTORE_0);
531 i = code_get_u1(p + 1);
532 v = code_get_s1(p + 2);
535 i = code_get_u2(p + 1);
536 v = code_get_s2(p + 3);
544 /* wider index for loading, storing and incrementing */
551 /* managing arrays ************************************************/
554 OP2I(ICMD_CHECKASIZE, 0, 0);
555 switch (code_get_s1(p+1)) {
557 BUILTIN1((functionptr)builtin_newarray_boolean, TYPE_ADR);
560 BUILTIN1((functionptr)builtin_newarray_char, TYPE_ADR);
563 BUILTIN1((functionptr)builtin_newarray_float, TYPE_ADR);
566 BUILTIN1((functionptr)builtin_newarray_double, TYPE_ADR);
569 BUILTIN1((functionptr)builtin_newarray_byte, TYPE_ADR);
572 BUILTIN1((functionptr)builtin_newarray_short, TYPE_ADR);
575 BUILTIN1((functionptr)builtin_newarray_int, TYPE_ADR);
578 BUILTIN1((functionptr)builtin_newarray_long, TYPE_ADR);
580 default: panic("Invalid array-type to create");
585 OP2I(ICMD_CHECKASIZE, 0, 0);
586 i = code_get_u2(p+1);
587 /* array or class type ? */
588 if (class_constanttype (class, i) == CONSTANT_Arraydescriptor) {
589 LOADCONST_A(class_getconstant(class, i,
590 CONSTANT_Arraydescriptor));
591 BUILTIN2((functionptr)builtin_newarray_array, TYPE_ADR);
594 LOADCONST_A(class_getconstant(class, i, CONSTANT_Class));
595 BUILTIN2((functionptr)builtin_anewarray, TYPE_ADR);
599 case JAVA_MULTIANEWARRAY:
601 i = code_get_u2(p+1);
603 int v = code_get_u1(p+3);
604 constant_arraydescriptor *desc =
605 class_getconstant (class, i, CONSTANT_Arraydescriptor);
606 OP2A(opcode, v, desc);
628 i = p + code_get_s2(p+1);
636 i = p + code_get_s4(p+1);
645 i = code_get_u1(p+1);
647 i = code_get_u2(p+1);
671 /* table jumps ********************************/
673 case JAVA_LOOKUPSWITCH:
678 nextp = ALIGN((p + 1), 4);
679 OP2A(opcode, 0, jcode + nextp);
683 j = p + code_get_s4(nextp);
684 *((s4*)(jcode + nextp)) = j; /* restore for little endian */
689 /* number of pairs */
691 num = code_get_u4(nextp);
692 *((s4*)(jcode + nextp)) = num;
695 for (i = 0; i < num; i++) {
699 j = code_get_s4(nextp);
700 *((s4*)(jcode + nextp)) = j; /* restore for little endian */
705 j = p + code_get_s4(nextp);
706 *((s4*)(jcode + nextp)) = j; /* restore for little endian */
716 case JAVA_TABLESWITCH:
721 nextp = ALIGN((p + 1), 4);
722 OP2A(opcode, 0, jcode + nextp);
726 j = p + code_get_s4(nextp);
727 *((s4*)(jcode + nextp)) = j; /* restore for little endian */
734 j = code_get_s4(nextp);
735 *((s4*)(jcode + nextp)) = j; /* restore for little endian */
740 num = code_get_s4(nextp);
741 *((s4*)(jcode + nextp)) = num; /* restore for little endian */
746 for (i = 0; i <= num; i++) {
747 j = p + code_get_s4(nextp);
748 *((s4*)(jcode + nextp)) = j; /* restore for little endian */
758 /* load and store of object fields *******************/
761 BUILTIN3((functionptr) asm_builtin_aastore, TYPE_VOID);
766 i = code_get_u2(p + 1);
770 fr = class_getconstant (class, i, CONSTANT_Fieldref);
771 fi = class_findfield (fr->class, fr->name, fr->descriptor);
772 compiler_addinitclass (fr->class);
773 OP2A(opcode, fi->type, fi);
778 i = code_get_u2(p + 1);
782 fr = class_getconstant (class, i, CONSTANT_Fieldref);
783 fi = class_findfield (fr->class, fr->name, fr->descriptor);
784 OP2A(opcode, fi->type, fi);
789 /* method invocation *****/
791 case JAVA_INVOKESTATIC:
792 i = code_get_u2(p + 1);
797 mr = class_getconstant (class, i, CONSTANT_Methodref);
798 mi = class_findmethod (mr->class, mr->name, mr->descriptor);
799 if (! (mi->flags & ACC_STATIC))
800 panic ("Static/Nonstatic mismatch calling static method");
801 descriptor2types(mi);
803 OP2A(opcode, mi->paramcount, mi);
806 case JAVA_INVOKESPECIAL:
807 case JAVA_INVOKEVIRTUAL:
808 i = code_get_u2(p + 1);
813 mr = class_getconstant (class, i, CONSTANT_Methodref);
814 mi = class_findmethod (mr->class, mr->name, mr->descriptor);
815 if (mi->flags & ACC_STATIC)
816 panic ("Static/Nonstatic mismatch calling static method");
817 descriptor2types(mi);
819 OP2A(opcode, mi->paramcount, mi);
822 case JAVA_INVOKEINTERFACE:
823 i = code_get_u2(p + 1);
828 mr = class_getconstant (class, i, CONSTANT_InterfaceMethodref);
829 mi = class_findmethod (mr->class, mr->name, mr->descriptor);
830 if (mi->flags & ACC_STATIC)
831 panic ("Static/Nonstatic mismatch calling static method");
832 descriptor2types(mi);
834 OP2A(opcode, mi->paramcount, mi);
838 /* miscellaneous object operations *******/
841 i = code_get_u2 (p+1);
842 LOADCONST_A(class_getconstant(class, i, CONSTANT_Class));
843 BUILTIN1((functionptr) builtin_new, TYPE_ADR);
847 i = code_get_u2(p+1);
849 /* array type cast-check */
850 if (class_constanttype (class, i) == CONSTANT_Arraydescriptor) {
851 LOADCONST_A(class_getconstant(class, i, CONSTANT_Arraydescriptor));
852 BUILTIN2((functionptr) asm_builtin_checkarraycast, TYPE_ADR);
854 else { /* object type cast-check */
855 OP2A(opcode, 1, (class_getconstant(class, i, CONSTANT_Class)));
859 case JAVA_INSTANCEOF:
860 i = code_get_u2(p+1);
862 /* array type cast-check */
863 if (class_constanttype (class, i) == CONSTANT_Arraydescriptor) {
864 LOADCONST_A(class_getconstant(class, i, CONSTANT_Arraydescriptor));
865 BUILTIN2((functionptr) builtin_arrayinstanceof, TYPE_INT);
867 else { /* object type cast-check */
868 OP2A(opcode, 1, (class_getconstant(class, i, CONSTANT_Class)));
872 case JAVA_MONITORENTER:
875 #ifdef SOFTNULLPTRCHECK
877 BUILTIN1((functionptr) asm_builtin_monitorenter, TYPE_VOID);
880 /* BUILTIN1((functionptr) builtin_monitorenter, TYPE_VOID); */
881 BUILTIN1((functionptr) asm_builtin_monitorenter, TYPE_VOID);
884 BUILTIN1((functionptr) builtin_monitorenter, TYPE_VOID);
890 OP(ICMD_NULLCHECKPOP);
894 case JAVA_MONITOREXIT:
897 BUILTIN1((functionptr) builtin_monitorexit, TYPE_VOID);
906 /* any other basic operation **************************************/
925 BUILTIN2((functionptr) builtin_frem, TYPE_FLOAT);
929 BUILTIN2((functionptr) builtin_drem, TYPE_DOUBLE);
934 BUILTIN1((functionptr) builtin_f2i, TYPE_INT);
943 BUILTIN1((functionptr) builtin_f2l, TYPE_LONG);
952 BUILTIN1((functionptr) builtin_d2i, TYPE_INT);
961 BUILTIN1((functionptr) builtin_d2l, TYPE_LONG);
968 case JAVA_BREAKPOINT:
969 panic("Illegal opcode Breakpoint encountered");
1025 printf("Illegal opcode %d at instr %d", opcode, ipc);
1026 panic("encountered");
1037 if (p != jcodelength)
1038 panic("Command-sequence crosses code-boundary");
1041 panic("Code does not end with branch/return/athrow - stmt");
1043 /* adjust block count if target 0 is not first intermediate instruction */
1045 if (!block_index[0] || (block_index[0] > 1))
1048 /* copy local to global variables */
1051 block_count = b_count;
1052 stack_count = s_count + block_count * maxstack;
1054 /* allocate stack table */
1056 stack = DMNEW(stackelement, stack_count);
1061 bptr = block = DMNEW(basicblock, b_count + 1); /* one more for end ipc */
1065 /* additional block if target 0 is not first intermediate instruction */
1067 if (!block_index[0] || (block_index[0] > 1)) {
1068 bptr->iinstr = instr;
1071 bptr->type = BBTYPE_STD;
1072 bptr->branchrefs = NULL;
1073 bptr->pre_count = 0;
1078 /* allocate blocks */
1080 for (p = 0; p < jcodelength; p++)
1081 if (block_index[p] & 1) {
1082 bptr->iinstr = instr + (block_index[p] >> 1);
1084 (bptr - 1)->icount = bptr->iinstr - (bptr - 1)->iinstr;
1087 bptr->type = BBTYPE_STD;
1088 bptr->branchrefs = NULL;
1089 block_index[p] = b_count;
1090 bptr->pre_count = 0;
1095 /* allocate additional block at end */
1097 bptr->iinstr = NULL;
1098 (bptr - 1)->icount = (instr + instr_count) - (bptr - 1)->iinstr;
1102 bptr->type = BBTYPE_STD;
1103 bptr->branchrefs = NULL;
1104 bptr->pre_count = 0;
1110 * These are local overrides for various environment variables in Emacs.
1111 * Please do not remove this and leave it at the end of the file, where
1112 * Emacs will automagically detect them.
1113 * ---------------------------------------------------------------------
1116 * indent-tabs-mode: t