1 /* src/vm/jit/parse.c - parser for JavaVM to intermediate code translation
3 Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 Contact: cacao@cacaojvm.org
29 Changes: Carolyn Oates
34 $Id: parse.c 5024 2006-06-10 14:53:54Z edwin $
46 #include "mm/memory.h"
47 #include "native/native.h"
48 #include "toolbox/logging.h"
49 #include "vm/builtin.h"
50 #include "vm/exceptions.h"
51 #include "vm/global.h"
52 #include "vm/linker.h"
53 #include "vm/loader.h"
54 #include "vm/resolve.h"
55 #include "vm/options.h"
56 #include "vm/statistics.h"
57 #include "vm/stringlocal.h"
58 #include "vm/jit/asmpart.h"
59 #include "vm/jit/jit.h"
60 #include "vm/jit/parse.h"
61 #include "vm/jit/patcher.h"
62 #include "vm/jit/loop/loop.h"
64 /*******************************************************************************
66 function 'parse' scans the JavaVM code and generates intermediate code
68 During parsing the block index table is used to store at bit pos 0
69 a flag which marks basic block starts and at position 1 to 31 the
70 intermediate instruction index. After parsing the block index table
71 is scanned, for marked positions a block is generated and the block
72 number is stored in the block index table.
74 *******************************************************************************/
76 static exceptiontable * new_fillextable(
79 exceptiontable *extable,
80 exceptiontable *raw_extable,
81 int exceptiontablelength,
86 if (exceptiontablelength == 0)
89 b_count = *block_count;
91 for (src = exceptiontablelength-1; src >=0; src--) {
92 /* the start of the handled region becomes a basic block start */
93 p = raw_extable[src].startpc;
94 CHECK_BYTECODE_INDEX(p);
98 p = raw_extable[src].endpc; /* see JVM Spec 4.7.3 */
99 CHECK_BYTECODE_INDEX_EXCLUSIVE(p);
101 #if defined(ENABLE_VERIFIER)
102 if (p <= raw_extable[src].startpc) {
103 *exceptionptr = new_verifyerror(m,
104 "Invalid exception handler range");
110 /* end of handled region becomes a basic block boundary */
111 /* (If it is the bytecode end, we'll use the special */
112 /* end block that is created anyway.) */
113 if (p < m->jcodelength)
116 /* the start of the handler becomes a basic block start */
117 p = raw_extable[src].handlerpc;
118 CHECK_BYTECODE_INDEX(p);
119 extable->handlerpc = p;
122 extable->catchtype = raw_extable[src].catchtype;
123 extable->next = NULL;
124 extable->down = &extable[1];
128 *block_count = b_count;
133 #if defined(ENABLE_VERIFIER)
134 throw_invalid_bytecode_index:
136 new_verifyerror(m, "Illegal bytecode index in exception table");
141 static exceptiontable * fillextable(methodinfo *m,
142 exceptiontable *extable,
143 exceptiontable *raw_extable,
144 int exceptiontablelength,
149 if (exceptiontablelength == 0)
152 b_count = *block_count;
154 for (src = exceptiontablelength-1; src >=0; src--) {
155 /* the start of the handled region becomes a basic block start */
156 p = raw_extable[src].startpc;
157 CHECK_BYTECODE_INDEX(p);
158 extable->startpc = p;
161 p = raw_extable[src].endpc; /* see JVM Spec 4.7.3 */
162 CHECK_BYTECODE_INDEX_EXCLUSIVE(p);
164 #if defined(ENABLE_VERIFIER)
165 if (p <= raw_extable[src].startpc) {
166 *exceptionptr = new_verifyerror(m,
167 "Invalid exception handler range");
173 /* end of handled region becomes a basic block boundary */
174 /* (If it is the bytecode end, we'll use the special */
175 /* end block that is created anyway.) */
176 if (p < m->jcodelength)
179 /* the start of the handler becomes a basic block start */
180 p = raw_extable[src].handlerpc;
181 CHECK_BYTECODE_INDEX(p);
182 extable->handlerpc = p;
185 extable->catchtype = raw_extable[src].catchtype;
186 extable->next = NULL;
187 extable->down = &extable[1];
191 *block_count = b_count;
196 #if defined(ENABLE_VERIFIER)
197 throw_invalid_bytecode_index:
199 new_verifyerror(m, "Illegal bytecode index in exception table");
204 /*** macro for checking the length of the bytecode ***/
206 #if defined(ENABLE_VERIFIER)
207 #define CHECK_END_OF_BYTECODE(neededlength) \
209 if ((neededlength) > m->jcodelength) \
210 goto throw_unexpected_end_of_bytecode; \
212 #else /* !ENABLE_VERIFIER */
213 #define CHECK_END_OF_BYTECODE(neededlength)
214 #endif /* ENABLE_VERIFIER */
216 bool new_parse(jitdata *jd)
218 methodinfo *m; /* method being parsed */
220 int p; /* java instruction counter */
221 int nextp; /* start of next java instruction */
222 int opcode; /* java opcode */
223 int i; /* temporary for different uses (ctrs) */
224 int ipc = 0; /* intermediate instruction counter */
225 int b_count = 0; /* basic block counter */
226 int s_count = 0; /* stack element counter */
227 bool blockend = false; /* true if basic block end has been reached */
228 bool iswide = false; /* true if last instruction was a wide */
229 new_instruction *iptr; /* current ptr into instruction array */
230 u1 *instructionstart; /* 1 for pcs which are valid instr. starts */
231 constant_classref *cr;
232 constant_classref *compr;
234 builtintable_entry *bte;
237 unresolved_method *um;
238 resolve_result_t result;
245 /* get required compiler data */
250 /* allocate instruction array and block index table */
252 /* 1 additional for end ipc */
253 jd->new_basicblockindex = DMNEW(s4, m->jcodelength + 1);
254 memset(jd->new_basicblockindex, 0, sizeof(s4) * (m->jcodelength + 1));
256 instructionstart = DMNEW(u1, m->jcodelength + 1);
257 memset(instructionstart, 0, sizeof(u1) * (m->jcodelength + 1));
259 /* IMPORTANT: We assume that parsing creates at most one instruction per */
260 /* byte of original bytecode! */
262 iptr = jd->new_instructions = DMNEW(new_instruction, m->jcodelength);
264 /* compute branch targets of exception table */
266 if (!new_fillextable(jd, m,
267 &(cd->exceptiontable[cd->exceptiontablelength-1]),
269 m->exceptiontablelength,
275 s_count = 1 + m->exceptiontablelength; /* initialize stack element counter */
277 #if defined(ENABLE_THREADS)
278 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
279 m->isleafmethod = false;
283 /* setup line number info */
288 if (m->linenumbercount == 0) {
292 linepcchange = m->linenumbers[0].start_pc;
295 /*** LOOP OVER ALL BYTECODE INSTRUCTIONS **********************************/
297 for (p = 0; p < m->jcodelength; p = nextp) {
299 /* mark this position as a valid instruction start */
301 instructionstart[p] = 1;
303 /* change the current line number, if necessary */
305 /* XXX rewrite this using pointer arithmetic */
307 if (linepcchange == p) {
308 if (m->linenumbercount > lineindex) {
310 currentline = m->linenumbers[lineindex].line_number;
312 if (lineindex < m->linenumbercount) {
313 linepcchange = m->linenumbers[lineindex].start_pc;
314 if (linepcchange == p)
315 goto next_linenumber;
320 /* fetch next opcode */
322 opcode = code_get_u1(p, m);
324 /* store intermediate instruction count (bit 0 mark block starts) */
326 jd->new_basicblockindex[p] |= (ipc << 1);
328 /* some compilers put a JAVA_NOP after a blockend instruction */
330 if (blockend && (opcode != JAVA_NOP)) {
331 /* start new block */
337 /* compute next instruction start */
339 nextp = p + jcommandsize[opcode];
341 CHECK_END_OF_BYTECODE(nextp);
343 /* add stack elements produced by this instruction */
345 s_count += stackreq[opcode];
347 /* translate this bytecode instruction */
354 /* pushing constants onto the stack ***********************************/
357 NEW_OP_LOADCONST_I(code_get_s1(p+1,m));
361 NEW_OP_LOADCONST_I(code_get_s2(p+1,m));
365 i = code_get_u1(p + 1, m);
366 goto pushconstantitem;
370 i = code_get_u2(p + 1, m);
374 #if defined(ENABLE_VERIFIER)
375 if (i >= m->class->cpcount) {
376 *exceptionptr = new_verifyerror(m,
377 "Attempt to access constant outside range");
382 switch (m->class->cptags[i]) {
383 case CONSTANT_Integer:
384 NEW_OP_LOADCONST_I(((constant_integer *) (m->class->cpinfos[i]))->value);
387 NEW_OP_LOADCONST_L(((constant_long *) (m->class->cpinfos[i]))->value);
390 NEW_OP_LOADCONST_F(((constant_float *) (m->class->cpinfos[i]))->value);
392 case CONSTANT_Double:
393 NEW_OP_LOADCONST_D(((constant_double *) (m->class->cpinfos[i]))->value);
395 case CONSTANT_String:
396 NEW_OP_LOADCONST_STRING(literalstring_new((utf *) (m->class->cpinfos[i])));
399 cr = (constant_classref *) (m->class->cpinfos[i]);
401 if (!resolve_classref(m, cr, resolveLazy, true,
405 /* if not resolved, c == NULL */
407 NEW_OP_LOADCONST_CLASSINFO_OR_CLASSREF(c, cr, 0 /* no extra flags */);
411 #if defined(ENABLE_VERIFIER)
413 *exceptionptr = new_verifyerror(m,
414 "Invalid constant type to push");
420 case JAVA_ACONST_NULL:
421 NEW_OP_LOADCONST_NULL();
431 NEW_OP_LOADCONST_I(opcode - JAVA_ICONST_0);
436 NEW_OP_LOADCONST_L(opcode - JAVA_LCONST_0);
442 NEW_OP_LOADCONST_F(opcode - JAVA_FCONST_0);
447 NEW_OP_LOADCONST_D(opcode - JAVA_DCONST_0);
450 /* local variable access instructions *********************************/
456 i = code_get_u1(p + 1,m);
459 i = code_get_u2(p + 1,m);
463 NEW_OP_LOAD_ONEWORD(opcode, i);
469 i = code_get_u1(p + 1,m);
472 i = code_get_u2(p + 1,m);
476 NEW_OP_LOAD_TWOWORD(opcode, i);
483 NEW_OP_LOAD_ONEWORD(ICMD_ILOAD, opcode - JAVA_ILOAD_0);
490 NEW_OP_LOAD_TWOWORD(ICMD_LLOAD, opcode - JAVA_LLOAD_0);
497 NEW_OP_LOAD_ONEWORD(ICMD_FLOAD, opcode - JAVA_FLOAD_0);
504 NEW_OP_LOAD_TWOWORD(ICMD_DLOAD, opcode - JAVA_DLOAD_0);
511 NEW_OP_LOAD_ONEWORD(ICMD_ALOAD, opcode - JAVA_ALOAD_0);
518 i = code_get_u1(p + 1,m);
521 i = code_get_u2(p + 1,m);
525 NEW_OP_STORE_ONEWORD(opcode, i);
531 i = code_get_u1(p + 1,m);
534 i = code_get_u2(p + 1,m);
538 NEW_OP_STORE_TWOWORD(opcode, i);
545 NEW_OP_STORE_ONEWORD(ICMD_ISTORE, opcode - JAVA_ISTORE_0);
552 NEW_OP_STORE_TWOWORD(ICMD_LSTORE, opcode - JAVA_LSTORE_0);
559 NEW_OP_STORE_ONEWORD(ICMD_FSTORE, opcode - JAVA_FSTORE_0);
566 NEW_OP_STORE_TWOWORD(ICMD_DSTORE, opcode - JAVA_DSTORE_0);
573 NEW_OP_STORE_ONEWORD(ICMD_ASTORE, opcode - JAVA_ASTORE_0);
581 i = code_get_u1(p + 1,m);
582 v = code_get_s1(p + 2,m);
586 i = code_get_u2(p + 1,m);
587 v = code_get_s2(p + 3,m);
592 NEW_OP_LOCALINDEX_I(opcode, i, v);
596 /* wider index for loading, storing and incrementing ******************/
603 /* managing arrays ****************************************************/
606 switch (code_get_s1(p + 1, m)) {
608 bte = builtintable_get_internal(BUILTIN_newarray_boolean);
611 bte = builtintable_get_internal(BUILTIN_newarray_char);
614 bte = builtintable_get_internal(BUILTIN_newarray_float);
617 bte = builtintable_get_internal(BUILTIN_newarray_double);
620 bte = builtintable_get_internal(BUILTIN_newarray_byte);
623 bte = builtintable_get_internal(BUILTIN_newarray_short);
626 bte = builtintable_get_internal(BUILTIN_newarray_int);
629 bte = builtintable_get_internal(BUILTIN_newarray_long);
631 #if defined(ENABLE_VERIFIER)
633 *exceptionptr = new_verifyerror(m,
634 "Invalid array-type to create");
638 NEW_OP_BUILTIN_CHECK_EXCEPTION(bte);
642 i = code_get_u2(p + 1, m);
643 compr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
647 if (!(cr = class_get_classref_multiarray_of(1, compr)))
650 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
653 NEW_OP_LOADCONST_CLASSINFO_OR_CLASSREF(c, cr, INS_FLAG_NOCHECK);
654 bte = builtintable_get_internal(BUILTIN_newarray);
655 NEW_OP_BUILTIN_CHECK_EXCEPTION(bte);
659 case JAVA_MULTIANEWARRAY:
660 m->isleafmethod = false;
661 i = code_get_u2(p + 1, m);
663 s4 v = code_get_u1(p + 3, m);
665 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
669 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
672 /* if unresolved, c == NULL */
674 iptr->s1.argcount = v;
675 NEW_OP_S3_CLASSINFO_OR_CLASSREF(opcode, c, cr, 0 /* flags */);
679 /* control flow instructions ******************************************/
698 i = p + code_get_s2(p + 1,m);
699 CHECK_BYTECODE_INDEX(i);
702 NEW_OP_INSINDEX(opcode, i);
706 i = p + code_get_s4(p + 1,m);
707 CHECK_BYTECODE_INDEX(i);
710 NEW_OP_INSINDEX(opcode, i);
714 i = p + code_get_s2(p + 1,m);
716 CHECK_BYTECODE_INDEX(i);
719 NEW_OP_PREPARE_ZEROFLAGS(JAVA_JSR);
720 iptr->sx.s23.s3.jsrtarget.insindex = i;
725 i = p + code_get_s4(p + 1,m);
730 i = code_get_u1(p + 1,m);
733 i = code_get_u2(p + 1,m);
739 NEW_OP_LOAD_ONEWORD(opcode, i);
749 /* XXX ARETURN will need a flag in the typechecker */
755 /* XXX ATHROW will need a flag in the typechecker */
760 /* table jumps ********************************************************/
762 case JAVA_LOOKUPSWITCH:
765 lookup_target_t *lookup;
766 #if defined(ENABLE_VERIFIER)
770 nextp = ALIGN((p + 1), 4);
772 CHECK_END_OF_BYTECODE(nextp + 8);
774 NEW_OP_PREPARE_ZEROFLAGS(opcode);
778 j = p + code_get_s4(nextp, m);
779 iptr->sx.s23.s3.lookupdefault.insindex = j;
781 CHECK_BYTECODE_INDEX(j);
784 /* number of pairs */
786 num = code_get_u4(nextp, m);
787 iptr->sx.s23.s2.lookupcount = num;
790 /* allocate the intermediate code table */
792 lookup = DMNEW(lookup_target_t, num);
793 iptr->dst.lookup = lookup;
795 /* iterate over the lookup table */
797 CHECK_END_OF_BYTECODE(nextp + 8 * num);
799 for (i = 0; i < num; i++) {
802 j = code_get_s4(nextp, m);
807 #if defined(ENABLE_VERIFIER)
808 /* check if the lookup table is sorted correctly */
810 if (i && (j <= prevvalue)) {
811 *exceptionptr = new_verifyerror(m, "Unsorted lookup switch");
818 j = p + code_get_s4(nextp,m);
819 lookup->target.insindex = j;
822 CHECK_BYTECODE_INDEX(j);
831 case JAVA_TABLESWITCH:
835 branch_target_t *table;
838 nextp = ALIGN((p + 1), 4);
840 CHECK_END_OF_BYTECODE(nextp + 12);
842 NEW_OP_PREPARE_ZEROFLAGS(opcode);
846 deftarget = p + code_get_s4(nextp, m);
848 CHECK_BYTECODE_INDEX(deftarget);
849 new_block_insert(deftarget);
853 j = code_get_s4(nextp, m);
854 iptr->sx.s23.s2.tablelow = j;
859 num = code_get_s4(nextp, m);
860 iptr->sx.s23.s3.tablehigh = num;
863 /* calculate the number of table entries */
867 #if defined(ENABLE_VERIFIER)
869 *exceptionptr = new_verifyerror(m,
870 "invalid TABLESWITCH: upper bound < lower bound");
874 /* create the intermediate code table */
875 /* the first entry is the default target */
877 table = MNEW(branch_target_t, 1 + num);
878 iptr->dst.table = table;
879 (table++)->insindex = deftarget;
881 /* iterate over the target table */
883 CHECK_END_OF_BYTECODE(nextp + 4 * num);
885 for (i = 0; i < num; i++) {
886 j = p + code_get_s4(nextp,m);
887 (table++)->insindex = j;
889 CHECK_BYTECODE_INDEX(j);
898 /* load and store of object fields ************************************/
902 m->isleafmethod = false;
911 unresolved_field *uf;
913 i = code_get_u2(p + 1, m);
914 fr = class_getconstant(m->class, i, CONSTANT_Fieldref);
918 NEW_OP_PREPARE_ZEROFLAGS(opcode);
919 iptr->sx.s23.s3.fmiref = fr;
921 /* only with -noverify, otherwise the typechecker does this */
923 #if defined(ENABLE_VERIFIER)
926 result = new_resolve_field_lazy(iptr, NULL, m);
927 if (result == resolveFailed)
930 if (result != resolveSucceeded) {
931 uf = new_create_unresolved_field(m->class, m, iptr);
936 /* store the unresolved_field pointer */
938 iptr->sx.s23.s3.uf = uf;
939 iptr->flags.bits = INS_FLAG_UNRESOLVED;
941 #if defined(ENABLE_VERIFIER)
949 /* method invocation **************************************************/
951 case JAVA_INVOKESTATIC:
952 i = code_get_u2(p + 1, m);
953 mr = class_getconstant(m->class, i, CONSTANT_Methodref);
957 md = mr->parseddesc.md;
960 if (!descriptor_params_from_paramtypes(md, ACC_STATIC))
965 case JAVA_INVOKEINTERFACE:
966 i = code_get_u2(p + 1, m);
968 mr = class_getconstant(m->class, i,
969 CONSTANT_InterfaceMethodref);
971 goto invoke_nonstatic_method;
973 case JAVA_INVOKESPECIAL:
974 case JAVA_INVOKEVIRTUAL:
975 i = code_get_u2(p + 1, m);
976 mr = class_getconstant(m->class, i, CONSTANT_Methodref);
978 invoke_nonstatic_method:
982 md = mr->parseddesc.md;
985 if (!descriptor_params_from_paramtypes(md, 0))
989 m->isleafmethod = false;
991 NEW_OP_PREPARE_ZEROFLAGS(opcode);
992 iptr->sx.s23.s3.fmiref = mr;
994 /* only with -noverify, otherwise the typechecker does this */
996 #if defined(ENABLE_VERIFIER)
999 result = new_resolve_method_lazy(iptr, NULL, m);
1000 if (result == resolveFailed)
1003 if (result != resolveSucceeded) {
1004 um = new_create_unresolved_method(m->class, m, iptr);
1009 /* store the unresolved_method pointer */
1011 iptr->sx.s23.s3.um = um;
1012 iptr->flags.bits = INS_FLAG_UNRESOLVED;
1014 #if defined(ENABLE_VERIFIER)
1020 /* instructions taking class arguments ********************************/
1023 i = code_get_u2(p + 1, m);
1024 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
1028 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
1031 NEW_OP_LOADCONST_CLASSINFO_OR_CLASSREF(c, cr, INS_FLAG_NOCHECK);
1032 bte = builtintable_get_internal(BUILTIN_new);
1033 NEW_OP_BUILTIN_CHECK_EXCEPTION(bte);
1037 case JAVA_CHECKCAST:
1038 i = code_get_u2(p + 1, m);
1039 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
1043 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
1046 if (cr->name->text[0] == '[') {
1047 /* array type cast-check */
1048 flags = INS_FLAG_ARRAY;
1049 m->isleafmethod = false;
1052 /* object type cast-check */
1055 NEW_OP_S3_CLASSINFO_OR_CLASSREF(opcode, c, cr, flags);
1058 case JAVA_INSTANCEOF:
1059 i = code_get_u2(p + 1,m);
1060 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
1064 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
1067 if (cr->name->text[0] == '[') {
1068 /* array type cast-check */
1069 NEW_OP_LOADCONST_CLASSINFO_OR_CLASSREF(c, cr, INS_FLAG_NOCHECK);
1070 bte = builtintable_get_internal(BUILTIN_arrayinstanceof);
1071 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1075 /* object type cast-check */
1076 NEW_OP_S3_CLASSINFO_OR_CLASSREF(opcode, c, cr, 0 /* flags*/);
1080 /* synchronization instructions ***************************************/
1082 case JAVA_MONITORENTER:
1083 #if defined(ENABLE_THREADS)
1085 /* XXX null check */
1086 bte = builtintable_get_internal(BUILTIN_monitorenter);
1087 NEW_OP_BUILTIN_CHECK_EXCEPTION(bte);
1092 NEW_OP(ICMD_CHECKNULL_POP);
1096 case JAVA_MONITOREXIT:
1097 #if defined(ENABLE_THREADS)
1099 /* XXX null check */
1100 bte = builtintable_get_internal(BUILTIN_monitorexit);
1101 NEW_OP_BUILTIN_CHECK_EXCEPTION(bte);
1106 NEW_OP(ICMD_CHECKNULL_POP);
1110 /* arithmetic instructions that may become builtin functions **********/
1113 #if !SUPPORT_DIVISION
1114 bte = builtintable_get_internal(BUILTIN_idiv);
1115 NEW_OP_BUILTIN_ARITHMETIC(opcode, bte);
1122 #if !SUPPORT_DIVISION
1123 bte = builtintable_get_internal(BUILTIN_irem);
1124 NEW_OP_BUILTIN_ARITHMETIC(opcode, bte);
1131 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1132 bte = builtintable_get_internal(BUILTIN_ldiv);
1133 NEW_OP_BUILTIN_ARITHMETIC(opcode, bte);
1140 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1141 bte = builtintable_get_internal(BUILTIN_lrem);
1142 NEW_OP_BUILTIN_ARITHMETIC(opcode, bte);
1149 #if defined(__I386__)
1152 bte = builtintable_get_internal(BUILTIN_frem);
1153 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1158 #if defined(__I386__)
1161 bte = builtintable_get_internal(BUILTIN_drem);
1162 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1167 #if defined(__ALPHA__)
1169 bte = builtintable_get_internal(BUILTIN_f2i);
1170 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1180 #if defined(__ALPHA__)
1182 bte = builtintable_get_internal(BUILTIN_f2l);
1183 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1193 #if defined(__ALPHA__)
1195 bte = builtintable_get_internal(BUILTIN_d2i);
1196 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1206 #if defined(__ALPHA__)
1208 bte = builtintable_get_internal(BUILTIN_d2l);
1209 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1218 /* invalid opcodes ****************************************************/
1220 /* check for invalid opcodes if the verifier is enabled */
1221 #if defined(ENABLE_VERIFIER)
1222 case JAVA_BREAKPOINT:
1224 new_verifyerror(m, "Quick instructions shouldn't appear, yet.");
1227 case 186: /* unused opcode */
1282 new_verifyerror(m,"Illegal opcode %d at instr %d\n",
1286 #endif /* defined(ENABLE_VERIFIER) */
1288 /* opcodes that don't require translation *****************************/
1291 /* straight-forward translation to ICMD */
1297 /* verifier checks ****************************************************/
1299 #if defined(ENABLE_VERIFIER)
1300 /* If WIDE was used correctly, iswide should have been reset by now. */
1302 *exceptionptr = new_verifyerror(m,
1303 "Illegal instruction: WIDE before incompatible opcode");
1306 #endif /* defined(ENABLE_VERIFIER) */
1310 /*** END OF LOOP **********************************************************/
1312 /* assert that we did not write more ICMDs than allocated */
1314 assert(ipc == (iptr - jd->new_instructions));
1315 assert(ipc <= m->jcodelength);
1317 /*** verifier checks ******************************************************/
1319 #if defined(ENABLE_VERIFIER)
1320 if (p != m->jcodelength) {
1321 *exceptionptr = new_verifyerror(m,
1322 "Command-sequence crosses code-boundary");
1327 *exceptionptr = new_verifyerror(m, "Falling off the end of the code");
1330 #endif /* defined(ENABLE_VERIFIER) */
1332 /*** setup the methodinfo, allocate stack and basic blocks ****************/
1334 /* adjust block count if target 0 is not first intermediate instruction */
1336 if (!jd->new_basicblockindex[0] || (jd->new_basicblockindex[0] > 1))
1339 /* copy local to method variables */
1341 jd->new_instructioncount = ipc;
1342 jd->new_basicblockcount = b_count;
1343 jd->new_stackcount = s_count + jd->new_basicblockcount * m->maxstack; /* in-stacks */
1345 /* allocate stack table */
1347 jd->new_stack = DMNEW(stackelement, jd->new_stackcount);
1349 /* build basic block list */
1351 bptr = jd->new_basicblocks = DMNEW(basicblock, b_count + 1); /* one more for end ipc */
1354 jd->new_c_debug_nr = 0;
1356 /* additional block if target 0 is not first intermediate instruction */
1358 if (!jd->new_basicblockindex[0] || (jd->new_basicblockindex[0] > 1)) {
1359 BASICBLOCK_INIT(bptr, m);
1361 bptr->iinstr = /* XXX */ (instruction *) jd->new_instructions;
1362 /* bptr->icount is set when the next block is allocated */
1366 bptr[-1].next = bptr;
1369 /* allocate blocks */
1371 for (p = 0; p < m->jcodelength; p++) {
1372 if (jd->new_basicblockindex[p] & 1) {
1373 /* Check if this block starts at the beginning of an */
1375 #if defined(ENABLE_VERIFIER)
1376 if (!instructionstart[p]) {
1377 *exceptionptr = new_verifyerror(m,
1378 "Branch into middle of instruction");
1383 /* allocate the block */
1385 BASICBLOCK_INIT(bptr, m);
1387 bptr->iinstr = /* XXX */ (instruction *) (jd->new_instructions + (jd->new_basicblockindex[p] >> 1));
1389 bptr[-1].icount = /*XXX*/ (new_instruction *)bptr->iinstr - (new_instruction*) bptr[-1].iinstr;
1391 /* bptr->icount is set when the next block is allocated */
1393 jd->new_basicblockindex[p] = b_count;
1397 bptr[-1].next = bptr;
1401 /* set instruction count of last real block */
1404 bptr[-1].icount = (jd->new_instructions + jd->new_instructioncount) - /* XXX */ (new_instruction *) bptr[-1].iinstr;
1407 /* allocate additional block at end */
1409 BASICBLOCK_INIT(bptr,m);
1411 bptr->instack = bptr->outstack = NULL;
1412 bptr->indepth = bptr->outdepth = 0;
1413 bptr->iinstr = NULL;
1417 /* set basicblock pointers in exception table */
1419 if (cd->exceptiontablelength > 0) {
1420 cd->exceptiontable[cd->exceptiontablelength - 1].down = NULL;
1423 for (i = 0; i < cd->exceptiontablelength; ++i) {
1424 p = cd->exceptiontable[i].startpc;
1425 cd->exceptiontable[i].start = jd->new_basicblocks + jd->new_basicblockindex[p];
1427 p = cd->exceptiontable[i].endpc;
1428 cd->exceptiontable[i].end = (p == m->jcodelength) ? (jd->new_basicblocks + jd->new_basicblockcount /*+ 1*/) : (jd->new_basicblocks + jd->new_basicblockindex[p]);
1430 p = cd->exceptiontable[i].handlerpc;
1431 cd->exceptiontable[i].handler = jd->new_basicblocks + jd->new_basicblockindex[p];
1434 /* XXX activate this if you want to try inlining */
1436 for (i = 0; i < m->exceptiontablelength; ++i) {
1437 p = m->exceptiontable[i].startpc;
1438 m->exceptiontable[i].start = jd->new_basicblocks + jd->new_basicblockindex[p];
1440 p = m->exceptiontable[i].endpc;
1441 m->exceptiontable[i].end = (p == m->jcodelength) ? (jd->new_basicblocks + jd->new_basicblockcount /*+ 1*/) : (jd->new_basicblocks + jd->new_basicblockindex[p]);
1443 p = m->exceptiontable[i].handlerpc;
1444 m->exceptiontable[i].handler = jd->new_basicblocks + jd->new_basicblockindex[p];
1448 /* everything's ok */
1452 /*** goto labels for throwing verifier exceptions *************************/
1454 #if defined(ENABLE_VERIFIER)
1456 throw_unexpected_end_of_bytecode:
1457 *exceptionptr = new_verifyerror(m, "Unexpected end of bytecode");
1460 throw_invalid_bytecode_index:
1462 new_verifyerror(m, "Illegal target of branch instruction");
1465 throw_illegal_local_variable_number:
1467 new_verifyerror(m, "Illegal local variable number");
1470 #endif /* ENABLE_VERIFIER */
1474 bool parse(jitdata *jd)
1478 int p; /* java instruction counter */
1479 int nextp; /* start of next java instruction */
1480 int opcode; /* java opcode */
1481 int i; /* temporary for different uses (ctrs)*/
1482 int ipc = 0; /* intermediate instruction counter */
1483 int b_count = 0; /* basic block counter */
1484 int s_count = 0; /* stack element counter */
1485 bool blockend = false; /* true if basic block end has been reached */
1486 bool iswide = false; /* true if last instruction was a wide*/
1487 instruction *iptr; /* current ptr into instruction array */
1489 u1 *instructionstart; /* 1 for pcs which are valid instr. starts */
1491 constant_classref *cr;
1492 constant_classref *compr;
1494 builtintable_entry *bte;
1496 constant_FMIref *mr;
1498 unresolved_method *um;
1499 resolve_result_t result;
1503 u2 linepcchange = 0;
1505 /* get required compiler data */
1510 /* allocate instruction array and block index table */
1512 /* 1 additional for end ipc */
1513 m->basicblockindex = DMNEW(s4, m->jcodelength + 1);
1514 memset(m->basicblockindex, 0, sizeof(s4) * (m->jcodelength + 1));
1516 instructionstart = DMNEW(u1, m->jcodelength + 1);
1517 memset(instructionstart, 0, sizeof(u1) * (m->jcodelength + 1));
1519 /* 1 additional for TRACEBUILTIN and 4 for MONITORENTER/EXIT */
1520 /* additional MONITOREXITS are reached by branches which are 3 bytes */
1522 iptr = m->instructions = DMNEW(instruction, m->jcodelength + 5);
1524 /* Zero the intermediate instructions array so we don't have any
1525 * invalid pointers in it if we cannot finish analyse_stack(). */
1527 memset(iptr, 0, sizeof(instruction) * (m->jcodelength + 5));
1529 /* compute branch targets of exception table */
1532 &(cd->exceptiontable[cd->exceptiontablelength-1]),
1534 m->exceptiontablelength,
1540 s_count = 1 + m->exceptiontablelength; /* initialize stack element counter */
1542 #if defined(ENABLE_THREADS)
1543 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
1544 m->isleafmethod = false;
1548 /* scan all java instructions */
1552 if (m->linenumbercount == 0) {
1556 linepcchange = m->linenumbers[0].start_pc;
1559 for (p = 0; p < m->jcodelength; p = nextp) {
1561 /* mark this position as a valid instruction start */
1562 instructionstart[p] = 1;
1563 if (linepcchange == p) {
1564 if (m->linenumbercount > lineindex) {
1566 currentline = m->linenumbers[lineindex].line_number;
1568 if (lineindex < m->linenumbercount) {
1569 linepcchange = m->linenumbers[lineindex].start_pc;
1570 if (linepcchange == p)
1571 goto next_linenumber;
1576 /* fetch next opcode */
1578 opcode = code_get_u1(p, m);
1580 m->basicblockindex[p] |= (ipc << 1); /*store intermed cnt*/
1582 /* some compilers put a JAVA_NOP after a blockend instruction */
1584 if (blockend && (opcode != JAVA_NOP)) {
1585 /* start new block */
1591 nextp = p + jcommandsize[opcode]; /* compute next instruction start */
1593 CHECK_END_OF_BYTECODE(nextp);
1595 s_count += stackreq[opcode]; /* compute stack element count */
1600 /* pushing constants onto the stack p */
1603 LOADCONST_I(code_get_s1(p+1,m));
1607 LOADCONST_I(code_get_s2(p+1,m));
1611 i = code_get_u1(p + 1, m);
1612 goto pushconstantitem;
1616 i = code_get_u2(p + 1, m);
1620 #if defined(ENABLE_VERIFIER)
1621 if (i >= m->class->cpcount) {
1622 *exceptionptr = new_verifyerror(m,
1623 "Attempt to access constant outside range");
1628 switch (m->class->cptags[i]) {
1629 case CONSTANT_Integer:
1630 LOADCONST_I(((constant_integer *) (m->class->cpinfos[i]))->value);
1633 LOADCONST_L(((constant_long *) (m->class->cpinfos[i]))->value);
1635 case CONSTANT_Float:
1636 LOADCONST_F(((constant_float *) (m->class->cpinfos[i]))->value);
1638 case CONSTANT_Double:
1639 LOADCONST_D(((constant_double *) (m->class->cpinfos[i]))->value);
1641 case CONSTANT_String:
1642 LOADCONST_A(literalstring_new((utf *) (m->class->cpinfos[i])));
1644 case CONSTANT_Class:
1645 cr = (constant_classref *) (m->class->cpinfos[i]);
1647 if (!resolve_classref(m, cr, resolveLazy, true,
1651 /* if not resolved, c == NULL */
1654 iptr->target = (void*) 0x02; /* XXX target used temporarily as flag */
1658 iptr->target = (void*) 0x03; /* XXX target used temporarily as flag */
1663 #if defined(ENABLE_VERIFIER)
1665 *exceptionptr = new_verifyerror(m,
1666 "Invalid constant type to push");
1672 case JAVA_ACONST_NULL:
1676 case JAVA_ICONST_M1:
1683 LOADCONST_I(opcode - JAVA_ICONST_0);
1688 LOADCONST_L(opcode - JAVA_LCONST_0);
1694 LOADCONST_F(opcode - JAVA_FCONST_0);
1699 LOADCONST_D(opcode - JAVA_DCONST_0);
1702 /* loading variables onto the stack */
1708 i = code_get_u1(p + 1,m);
1711 i = code_get_u2(p + 1,m);
1715 OP1LOAD_ONEWORD(opcode, i);
1721 i = code_get_u1(p + 1,m);
1724 i = code_get_u2(p + 1,m);
1728 OP1LOAD_TWOWORD(opcode, i);
1735 OP1LOAD_ONEWORD(ICMD_ILOAD, opcode - JAVA_ILOAD_0);
1742 OP1LOAD_TWOWORD(ICMD_LLOAD, opcode - JAVA_LLOAD_0);
1749 OP1LOAD_ONEWORD(ICMD_FLOAD, opcode - JAVA_FLOAD_0);
1756 OP1LOAD_TWOWORD(ICMD_DLOAD, opcode - JAVA_DLOAD_0);
1763 OP1LOAD_ONEWORD(ICMD_ALOAD, opcode - JAVA_ALOAD_0);
1766 /* storing stack values into local variables */
1772 i = code_get_u1(p + 1,m);
1775 i = code_get_u2(p + 1,m);
1779 OP1STORE_ONEWORD(opcode, i);
1785 i = code_get_u1(p + 1,m);
1788 i = code_get_u2(p + 1,m);
1792 OP1STORE_TWOWORD(opcode, i);
1799 OP1STORE_ONEWORD(ICMD_ISTORE, opcode - JAVA_ISTORE_0);
1806 OP1STORE_TWOWORD(ICMD_LSTORE, opcode - JAVA_LSTORE_0);
1813 OP1STORE_ONEWORD(ICMD_FSTORE, opcode - JAVA_FSTORE_0);
1820 OP1STORE_TWOWORD(ICMD_DSTORE, opcode - JAVA_DSTORE_0);
1827 OP1STORE_ONEWORD(ICMD_ASTORE, opcode - JAVA_ASTORE_0);
1835 i = code_get_u1(p + 1,m);
1836 v = code_get_s1(p + 2,m);
1840 i = code_get_u2(p + 1,m);
1841 v = code_get_s2(p + 3,m);
1850 /* wider index for loading, storing and incrementing */
1857 /* managing arrays ****************************************************/
1860 switch (code_get_s1(p + 1, m)) {
1862 bte = builtintable_get_internal(BUILTIN_newarray_boolean);
1865 bte = builtintable_get_internal(BUILTIN_newarray_char);
1868 bte = builtintable_get_internal(BUILTIN_newarray_float);
1871 bte = builtintable_get_internal(BUILTIN_newarray_double);
1874 bte = builtintable_get_internal(BUILTIN_newarray_byte);
1877 bte = builtintable_get_internal(BUILTIN_newarray_short);
1880 bte = builtintable_get_internal(BUILTIN_newarray_int);
1883 bte = builtintable_get_internal(BUILTIN_newarray_long);
1885 #if defined(ENABLE_VERIFIER)
1887 *exceptionptr = new_verifyerror(m,
1888 "Invalid array-type to create");
1892 BUILTIN(bte, true, NULL, currentline);
1895 case JAVA_ANEWARRAY:
1896 i = code_get_u2(p + 1, m);
1897 compr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
1901 if (!(cr = class_get_classref_multiarray_of(1, compr)))
1904 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
1907 LOADCONST_A_BUILTIN(c, cr);
1908 bte = builtintable_get_internal(BUILTIN_newarray);
1909 BUILTIN(bte, true, NULL, currentline);
1913 case JAVA_MULTIANEWARRAY:
1914 m->isleafmethod = false;
1915 i = code_get_u2(p + 1, m);
1917 s4 v = code_get_u1(p + 3, m);
1919 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
1923 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
1926 /* if unresolved, c == NULL */
1927 OP2AT(opcode, v, c, cr, currentline);
1938 case JAVA_IFNONNULL:
1939 case JAVA_IF_ICMPEQ:
1940 case JAVA_IF_ICMPNE:
1941 case JAVA_IF_ICMPLT:
1942 case JAVA_IF_ICMPGT:
1943 case JAVA_IF_ICMPLE:
1944 case JAVA_IF_ICMPGE:
1945 case JAVA_IF_ACMPEQ:
1946 case JAVA_IF_ACMPNE:
1949 i = p + code_get_s2(p + 1,m);
1950 CHECK_BYTECODE_INDEX(i);
1958 i = p + code_get_s4(p + 1,m);
1959 CHECK_BYTECODE_INDEX(i);
1967 i = code_get_u1(p + 1,m);
1970 i = code_get_u2(p + 1,m);
1976 OP1LOAD_ONEWORD(opcode, i);
1986 /* zero val.a so no patcher is inserted */
1987 /* the type checker may set this later */
1994 /* zero val.a so no patcher is inserted */
1995 /* the type checker may set this later */
2001 /* table jumps ********************************************************/
2003 case JAVA_LOOKUPSWITCH:
2007 #if defined(ENABLE_VERIFIER)
2012 nextp = ALIGN((p + 1), 4);
2014 CHECK_END_OF_BYTECODE(nextp + 8);
2016 tablep = (s4 *) (m->jcode + nextp);
2018 OP2A(opcode, 0, tablep, currentline);
2020 /* default target */
2022 j = p + code_get_s4(nextp, m);
2023 *tablep = j; /* restore for little endian */
2026 CHECK_BYTECODE_INDEX(j);
2029 /* number of pairs */
2031 num = code_get_u4(nextp, m);
2036 CHECK_END_OF_BYTECODE(nextp + 8 * num);
2038 for (i = 0; i < num; i++) {
2041 j = code_get_s4(nextp, m);
2042 *tablep = j; /* restore for little endian */
2046 #if defined(ENABLE_VERIFIER)
2047 /* check if the lookup table is sorted correctly */
2049 if (i && (j <= prevvalue)) {
2050 *exceptionptr = new_verifyerror(m, "Unsorted lookup switch");
2058 j = p + code_get_s4(nextp,m);
2059 *tablep = j; /* restore for little endian */
2062 CHECK_BYTECODE_INDEX(j);
2070 case JAVA_TABLESWITCH:
2076 nextp = ALIGN((p + 1), 4);
2078 CHECK_END_OF_BYTECODE(nextp + 12);
2080 tablep = (s4 *) (m->jcode + nextp);
2082 OP2A(opcode, 0, tablep, currentline);
2084 /* default target */
2086 j = p + code_get_s4(nextp, m);
2087 *tablep = j; /* restore for little endian */
2090 CHECK_BYTECODE_INDEX(j);
2095 j = code_get_s4(nextp, m);
2096 *tablep = j; /* restore for little endian */
2102 num = code_get_s4(nextp, m);
2103 *tablep = num; /* restore for little endian */
2107 num -= j; /* difference of upper - lower */
2109 #if defined(ENABLE_VERIFIER)
2111 *exceptionptr = new_verifyerror(m,
2112 "invalid TABLESWITCH: upper bound < lower bound");
2117 CHECK_END_OF_BYTECODE(nextp + 4 * (num + 1));
2119 for (i = 0; i <= num; i++) {
2120 j = p + code_get_s4(nextp,m);
2121 *tablep = j; /* restore for little endian */
2124 CHECK_BYTECODE_INDEX(j);
2132 /* load and store of object fields ************************************/
2136 m->isleafmethod = false;
2139 case JAVA_GETSTATIC:
2140 case JAVA_PUTSTATIC:
2144 constant_FMIref *fr;
2145 unresolved_field *uf;
2147 i = code_get_u2(p + 1, m);
2148 fr = class_getconstant(m->class, i,
2153 OP2A_NOINC(opcode, fr->parseddesc.fd->type, fr, currentline);
2155 /* only with -noverify, otherwise the typechecker does this */
2157 #if defined(ENABLE_VERIFIER)
2160 result = resolve_field_lazy(iptr,NULL,m);
2161 if (result == resolveFailed)
2164 if (result != resolveSucceeded) {
2165 uf = create_unresolved_field(m->class,
2171 /* store the unresolved_field pointer */
2173 /* XXX this will be changed */
2175 iptr->target = (void*) 0x01; /* XXX target temporarily used as flag */
2178 iptr->target = NULL;
2180 #if defined(ENABLE_VERIFIER)
2183 iptr->target = NULL;
2191 /* method invocation **************************************************/
2193 case JAVA_INVOKESTATIC:
2194 i = code_get_u2(p + 1, m);
2195 mr = class_getconstant(m->class, i,
2196 CONSTANT_Methodref);
2200 md = mr->parseddesc.md;
2203 if (!descriptor_params_from_paramtypes(md, ACC_STATIC))
2208 case JAVA_INVOKEINTERFACE:
2209 i = code_get_u2(p + 1, m);
2211 mr = class_getconstant(m->class, i,
2212 CONSTANT_InterfaceMethodref);
2214 goto invoke_nonstatic_method;
2216 case JAVA_INVOKESPECIAL:
2217 case JAVA_INVOKEVIRTUAL:
2218 i = code_get_u2(p + 1, m);
2219 mr = class_getconstant(m->class, i,
2220 CONSTANT_Methodref);
2222 invoke_nonstatic_method:
2226 md = mr->parseddesc.md;
2229 if (!descriptor_params_from_paramtypes(md, 0))
2233 m->isleafmethod = false;
2235 OP2A_NOINC(opcode, 0, mr, currentline);
2237 /* only with -noverify, otherwise the typechecker does this */
2239 #if defined(ENABLE_VERIFIER)
2242 result = resolve_method_lazy(iptr,NULL,m);
2243 if (result == resolveFailed)
2246 if (result != resolveSucceeded) {
2247 um = create_unresolved_method(m->class,
2253 /* store the unresolved_method pointer */
2255 /* XXX this will be changed */
2257 iptr->target = (void*) 0x01; /* XXX target temporarily used as flag */
2260 /* the method could be resolved */
2261 iptr->target = NULL;
2263 #if defined(ENABLE_VERIFIER)
2266 iptr->target = NULL;
2272 /* miscellaneous object operations ************************************/
2275 i = code_get_u2(p + 1, m);
2276 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
2280 if (!resolve_classref(m, cr, resolveLazy, true, true,
2284 LOADCONST_A_BUILTIN(c, cr);
2285 bte = builtintable_get_internal(BUILTIN_new);
2286 BUILTIN(bte, true, NULL, currentline);
2290 case JAVA_CHECKCAST:
2291 i = code_get_u2(p + 1, m);
2292 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
2296 if (!resolve_classref(m, cr, resolveLazy, true,
2300 if (cr->name->text[0] == '[') {
2301 /* array type cast-check */
2302 OP2AT(opcode, 0, c, cr, currentline);
2303 m->isleafmethod = false;
2307 /* object type cast-check */
2308 OP2AT(opcode, 1, c, cr, currentline);
2312 case JAVA_INSTANCEOF:
2313 i = code_get_u2(p + 1,m);
2314 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
2318 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
2321 if (cr->name->text[0] == '[') {
2322 /* array type cast-check */
2323 LOADCONST_A_BUILTIN(c, cr);
2324 bte = builtintable_get_internal(BUILTIN_arrayinstanceof);
2325 BUILTIN(bte, false, NULL, currentline);
2330 /* object type cast-check */
2331 OP2AT(opcode, 1, c, cr, currentline);
2335 case JAVA_MONITORENTER:
2336 #if defined(ENABLE_THREADS)
2339 bte = builtintable_get_internal(BUILTIN_monitorenter);
2340 BUILTIN(bte, false, NULL, currentline);
2350 case JAVA_MONITOREXIT:
2351 #if defined(ENABLE_THREADS)
2353 bte = builtintable_get_internal(BUILTIN_monitorexit);
2354 BUILTIN(bte, false, NULL, currentline);
2363 /* any other basic operation ******************************************/
2366 #if !SUPPORT_DIVISION
2367 bte = builtintable_get_internal(BUILTIN_idiv);
2368 OP2A(opcode, bte->md->paramcount, bte, currentline);
2369 m->isleafmethod = false;
2376 #if !SUPPORT_DIVISION
2377 bte = builtintable_get_internal(BUILTIN_irem);
2378 OP2A(opcode, bte->md->paramcount, bte, currentline);
2379 m->isleafmethod = false;
2386 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
2387 bte = builtintable_get_internal(BUILTIN_ldiv);
2388 OP2A(opcode, bte->md->paramcount, bte, currentline);
2389 m->isleafmethod = false;
2396 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
2397 bte = builtintable_get_internal(BUILTIN_lrem);
2398 OP2A(opcode, bte->md->paramcount, bte, currentline);
2399 m->isleafmethod = false;
2406 #if defined(__I386__)
2409 bte = builtintable_get_internal(BUILTIN_frem);
2410 BUILTIN(bte, false, NULL, currentline);
2415 #if defined(__I386__)
2418 bte = builtintable_get_internal(BUILTIN_drem);
2419 BUILTIN(bte, false, NULL, currentline);
2424 #if defined(__ALPHA__)
2426 bte = builtintable_get_internal(BUILTIN_f2i);
2427 BUILTIN(bte, false, NULL, currentline);
2437 #if defined(__ALPHA__)
2439 bte = builtintable_get_internal(BUILTIN_f2l);
2440 BUILTIN(bte, false, NULL, currentline);
2450 #if defined(__ALPHA__)
2452 bte = builtintable_get_internal(BUILTIN_d2i);
2453 BUILTIN(bte, false, NULL, currentline);
2463 #if defined(__ALPHA__)
2465 bte = builtintable_get_internal(BUILTIN_d2l);
2466 BUILTIN(bte, false, NULL, currentline);
2475 /* check for invalid opcodes if the verifier is enabled */
2476 #if defined(ENABLE_VERIFIER)
2477 case JAVA_BREAKPOINT:
2479 new_verifyerror(m, "Quick instructions shouldn't appear yet.");
2482 case 186: /* unused opcode */
2537 new_verifyerror(m,"Illegal opcode %d at instr %d\n",
2541 #endif /* defined(ENABLE_VERIFIER) */
2544 /* straight-forward translation to ICMD */
2550 #if defined(ENABLE_VERIFIER)
2551 /* If WIDE was used correctly, iswide should have been reset by now. */
2553 *exceptionptr = new_verifyerror(m,
2554 "Illegal instruction: WIDE before incompatible opcode");
2557 #endif /* defined(ENABLE_VERIFIER) */
2561 #if defined(ENABLE_VERIFIER)
2562 if (p != m->jcodelength) {
2563 *exceptionptr = new_verifyerror(m,
2564 "Command-sequence crosses code-boundary");
2569 *exceptionptr = new_verifyerror(m, "Falling off the end of the code");
2572 #endif /* defined(ENABLE_VERIFIER) */
2574 /* adjust block count if target 0 is not first intermediate instruction */
2576 if (!m->basicblockindex[0] || (m->basicblockindex[0] > 1))
2579 /* copy local to method variables */
2581 m->instructioncount = ipc;
2582 m->basicblockcount = b_count;
2583 m->stackcount = s_count + m->basicblockcount * m->maxstack;
2585 /* allocate stack table */
2587 m->stack = DMNEW(stackelement, m->stackcount);
2592 bptr = m->basicblocks = DMNEW(basicblock, b_count + 1); /* one more for end ipc */
2597 /* additional block if target 0 is not first intermediate instruction */
2599 if (!m->basicblockindex[0] || (m->basicblockindex[0] > 1)) {
2600 BASICBLOCK_INIT(bptr,m);
2602 bptr->iinstr = m->instructions;
2603 /* bptr->icount is set when the next block is allocated */
2607 bptr[-1].next = bptr;
2610 /* allocate blocks */
2612 for (p = 0; p < m->jcodelength; p++) {
2613 if (m->basicblockindex[p] & 1) {
2614 /* Check if this block starts at the beginning of an */
2616 #if defined(ENABLE_VERIFIER)
2617 if (!instructionstart[p]) {
2618 *exceptionptr = new_verifyerror(m,
2619 "Branch into middle of instruction");
2624 /* allocate the block */
2626 BASICBLOCK_INIT(bptr,m);
2628 bptr->iinstr = m->instructions + (m->basicblockindex[p] >> 1);
2630 bptr[-1].icount = bptr->iinstr - bptr[-1].iinstr;
2632 /* bptr->icount is set when the next block is allocated */
2634 m->basicblockindex[p] = b_count;
2638 bptr[-1].next = bptr;
2642 /* set instruction count of last real block */
2645 bptr[-1].icount = (m->instructions + m->instructioncount) - bptr[-1].iinstr;
2648 /* allocate additional block at end */
2650 BASICBLOCK_INIT(bptr,m);
2652 bptr->instack = bptr->outstack = NULL;
2653 bptr->indepth = bptr->outdepth = 0;
2654 bptr->iinstr = NULL;
2658 /* set basicblock pointers in exception table */
2660 if (cd->exceptiontablelength > 0) {
2661 cd->exceptiontable[cd->exceptiontablelength - 1].down = NULL;
2664 for (i = 0; i < cd->exceptiontablelength; ++i) {
2665 p = cd->exceptiontable[i].startpc;
2666 cd->exceptiontable[i].start = m->basicblocks + m->basicblockindex[p];
2668 p = cd->exceptiontable[i].endpc;
2669 cd->exceptiontable[i].end = (p == m->jcodelength) ? (m->basicblocks + m->basicblockcount /*+ 1*/) : (m->basicblocks + m->basicblockindex[p]);
2671 p = cd->exceptiontable[i].handlerpc;
2672 cd->exceptiontable[i].handler = m->basicblocks + m->basicblockindex[p];
2675 /* XXX activate this if you want to try inlining */
2677 for (i = 0; i < m->exceptiontablelength; ++i) {
2678 p = m->exceptiontable[i].startpc;
2679 m->exceptiontable[i].start = m->basicblocks + m->basicblockindex[p];
2681 p = m->exceptiontable[i].endpc;
2682 m->exceptiontable[i].end = (p == m->jcodelength) ? (m->basicblocks + m->basicblockcount /*+ 1*/) : (m->basicblocks + m->basicblockindex[p]);
2684 p = m->exceptiontable[i].handlerpc;
2685 m->exceptiontable[i].handler = m->basicblocks + m->basicblockindex[p];
2691 /* everything's ok */
2695 #if defined(ENABLE_VERIFIER)
2697 throw_unexpected_end_of_bytecode:
2698 *exceptionptr = new_verifyerror(m, "Unexpected end of bytecode");
2701 throw_invalid_bytecode_index:
2703 new_verifyerror(m, "Illegal target of branch instruction");
2706 throw_illegal_local_variable_number:
2708 new_verifyerror(m, "Illegal local variable number");
2711 #endif /* ENABLE_VERIFIER */
2716 * These are local overrides for various environment variables in Emacs.
2717 * Please do not remove this and leave it at the end of the file, where
2718 * Emacs will automagically detect them.
2719 * ---------------------------------------------------------------------
2722 * indent-tabs-mode: t
2726 * vim:noexpandtab:sw=4:ts=4: