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 5008 2006-06-01 16:00:18Z 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 * fillextable(methodinfo *m,
77 exceptiontable *extable,
78 exceptiontable *raw_extable,
79 int exceptiontablelength,
84 if (exceptiontablelength == 0)
87 b_count = *block_count;
89 for (src = exceptiontablelength-1; src >=0; src--) {
90 /* the start of the handled region becomes a basic block start */
91 p = raw_extable[src].startpc;
92 CHECK_BYTECODE_INDEX(p);
96 p = raw_extable[src].endpc; /* see JVM Spec 4.7.3 */
97 CHECK_BYTECODE_INDEX_EXCLUSIVE(p);
99 #if defined(ENABLE_VERIFIER)
100 if (p <= raw_extable[src].startpc) {
101 *exceptionptr = new_verifyerror(m,
102 "Invalid exception handler range");
108 /* end of handled region becomes a basic block boundary */
109 /* (If it is the bytecode end, we'll use the special */
110 /* end block that is created anyway.) */
111 if (p < m->jcodelength)
114 /* the start of the handler becomes a basic block start */
115 p = raw_extable[src].handlerpc;
116 CHECK_BYTECODE_INDEX(p);
117 extable->handlerpc = p;
120 extable->catchtype = raw_extable[src].catchtype;
121 extable->next = NULL;
122 extable->down = &extable[1];
126 *block_count = b_count;
131 #if defined(ENABLE_VERIFIER)
132 throw_invalid_bytecode_index:
134 new_verifyerror(m, "Illegal bytecode index in exception table");
139 /*** macro for checking the length of the bytecode ***/
141 #if defined(ENABLE_VERIFIER)
142 #define CHECK_END_OF_BYTECODE(neededlength) \
144 if ((neededlength) > m->jcodelength) \
145 goto throw_unexpected_end_of_bytecode; \
147 #else /* !ENABLE_VERIFIER */
148 #define CHECK_END_OF_BYTECODE(neededlength)
149 #endif /* ENABLE_VERIFIER */
151 bool new_parse(jitdata *jd)
153 methodinfo *m; /* method being parsed */
155 int p; /* java instruction counter */
156 int nextp; /* start of next java instruction */
157 int opcode; /* java opcode */
158 int i; /* temporary for different uses (ctrs) */
159 int ipc = 0; /* intermediate instruction counter */
160 int b_count = 0; /* basic block counter */
161 int s_count = 0; /* stack element counter */
162 bool blockend = false; /* true if basic block end has been reached */
163 bool iswide = false; /* true if last instruction was a wide */
164 new_instruction *iptr; /* current ptr into instruction array */
165 u1 *instructionstart; /* 1 for pcs which are valid instr. starts */
166 constant_classref *cr;
167 constant_classref *compr;
169 builtintable_entry *bte;
172 unresolved_method *um;
173 resolve_result_t result;
179 /* get required compiler data */
184 /* allocate instruction array and block index table */
186 /* 1 additional for end ipc */
187 m->basicblockindex = DMNEW(s4, m->jcodelength + 1);
188 memset(m->basicblockindex, 0, sizeof(s4) * (m->jcodelength + 1));
190 instructionstart = DMNEW(u1, m->jcodelength + 1);
191 memset(instructionstart, 0, sizeof(u1) * (m->jcodelength + 1));
193 /* IMPORTANT: We assume that parsing creates at most one instruction per */
194 /* byte of original bytecode! */
195 /* XXX add an assertion checking this at the end */
197 iptr = jd->new_instructions = DMNEW(new_instruction, m->jcodelength);
199 /* compute branch targets of exception table */
202 &(cd->exceptiontable[cd->exceptiontablelength-1]),
204 m->exceptiontablelength,
210 s_count = 1 + m->exceptiontablelength; /* initialize stack element counter */
212 #if defined(ENABLE_THREADS)
213 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
214 m->isleafmethod = false;
218 /* scan all java instructions */
222 if (m->linenumbercount == 0) {
226 linepcchange = m->linenumbers[0].start_pc;
229 /*** LOOP OVER ALL BYTECODE INSTRUCTIONS **********************************/
231 for (p = 0; p < m->jcodelength; p = nextp) {
233 /* mark this position as a valid instruction start */
235 instructionstart[p] = 1;
237 /* change the current line number, if necessary */
239 /* XXX rewrite this using pointer arithmetic */
241 if (linepcchange == p) {
242 if (m->linenumbercount > lineindex) {
244 currentline = m->linenumbers[lineindex].line_number;
246 if (lineindex < m->linenumbercount) {
247 linepcchange = m->linenumbers[lineindex].start_pc;
248 if (linepcchange == p)
249 goto next_linenumber;
254 /* fetch next opcode */
256 opcode = code_get_u1(p, m);
258 /* store intermediate instruction count (bit 0 mark block starts) */
260 m->basicblockindex[p] |= (ipc << 1);
262 /* some compilers put a JAVA_NOP after a blockend instruction */
264 if (blockend && (opcode != JAVA_NOP)) {
265 /* start new block */
271 /* compute next instruction start */
273 nextp = p + jcommandsize[opcode];
275 CHECK_END_OF_BYTECODE(nextp);
277 /* add stack elements produced by this instruction */
279 s_count += stackreq[opcode];
281 /* translate this bytecode instruction */
288 /* pushing constants onto the stack ***********************************/
291 NEW_OP_LOADCONST_I(code_get_s1(p+1,m));
295 NEW_OP_LOADCONST_I(code_get_s2(p+1,m));
299 i = code_get_u1(p + 1, m);
300 goto pushconstantitem;
304 i = code_get_u2(p + 1, m);
308 #if defined(ENABLE_VERIFIER)
309 if (i >= m->class->cpcount) {
310 *exceptionptr = new_verifyerror(m,
311 "Attempt to access constant outside range");
316 switch (m->class->cptags[i]) {
317 case CONSTANT_Integer:
318 NEW_OP_LOADCONST_I(((constant_integer *) (m->class->cpinfos[i]))->value);
321 NEW_OP_LOADCONST_L(((constant_long *) (m->class->cpinfos[i]))->value);
324 NEW_OP_LOADCONST_F(((constant_float *) (m->class->cpinfos[i]))->value);
326 case CONSTANT_Double:
327 NEW_OP_LOADCONST_D(((constant_double *) (m->class->cpinfos[i]))->value);
329 case CONSTANT_String:
330 NEW_OP_LOADCONST_STRING(literalstring_new((utf *) (m->class->cpinfos[i])));
333 cr = (constant_classref *) (m->class->cpinfos[i]);
335 if (!resolve_classref(m, cr, resolveLazy, true,
339 /* if not resolved, c == NULL */
341 NEW_OP_LOADCONST_CLASSINFO_OR_CLASSREF(c, cr, 0 /* no extra flags */);
345 #if defined(ENABLE_VERIFIER)
347 *exceptionptr = new_verifyerror(m,
348 "Invalid constant type to push");
354 case JAVA_ACONST_NULL:
355 NEW_OP_LOADCONST_NULL();
365 NEW_OP_LOADCONST_I(opcode - JAVA_ICONST_0);
370 NEW_OP_LOADCONST_L(opcode - JAVA_LCONST_0);
376 NEW_OP_LOADCONST_F(opcode - JAVA_FCONST_0);
381 NEW_OP_LOADCONST_D(opcode - JAVA_DCONST_0);
384 /* local variable access instructions *********************************/
390 i = code_get_u1(p + 1,m);
393 i = code_get_u2(p + 1,m);
397 NEW_OP_LOAD_ONEWORD(opcode, i);
403 i = code_get_u1(p + 1,m);
406 i = code_get_u2(p + 1,m);
410 NEW_OP_LOAD_TWOWORD(opcode, i);
417 NEW_OP_LOAD_ONEWORD(ICMD_ILOAD, opcode - JAVA_ILOAD_0);
424 NEW_OP_LOAD_TWOWORD(ICMD_LLOAD, opcode - JAVA_LLOAD_0);
431 NEW_OP_LOAD_ONEWORD(ICMD_FLOAD, opcode - JAVA_FLOAD_0);
438 NEW_OP_LOAD_TWOWORD(ICMD_DLOAD, opcode - JAVA_DLOAD_0);
445 NEW_OP_LOAD_ONEWORD(ICMD_ALOAD, opcode - JAVA_ALOAD_0);
452 i = code_get_u1(p + 1,m);
455 i = code_get_u2(p + 1,m);
459 NEW_OP_STORE_ONEWORD(opcode, i);
465 i = code_get_u1(p + 1,m);
468 i = code_get_u2(p + 1,m);
472 NEW_OP_STORE_TWOWORD(opcode, i);
479 NEW_OP_STORE_ONEWORD(ICMD_ISTORE, opcode - JAVA_ISTORE_0);
486 NEW_OP_STORE_TWOWORD(ICMD_LSTORE, opcode - JAVA_LSTORE_0);
493 NEW_OP_STORE_ONEWORD(ICMD_FSTORE, opcode - JAVA_FSTORE_0);
500 NEW_OP_STORE_TWOWORD(ICMD_DSTORE, opcode - JAVA_DSTORE_0);
507 NEW_OP_STORE_ONEWORD(ICMD_ASTORE, opcode - JAVA_ASTORE_0);
515 i = code_get_u1(p + 1,m);
516 v = code_get_s1(p + 2,m);
520 i = code_get_u2(p + 1,m);
521 v = code_get_s2(p + 3,m);
526 NEW_OP_LOCALINDEX_I(opcode, i, v);
530 /* wider index for loading, storing and incrementing ******************/
537 /* managing arrays ****************************************************/
540 switch (code_get_s1(p + 1, m)) {
542 bte = builtintable_get_internal(BUILTIN_newarray_boolean);
545 bte = builtintable_get_internal(BUILTIN_newarray_char);
548 bte = builtintable_get_internal(BUILTIN_newarray_float);
551 bte = builtintable_get_internal(BUILTIN_newarray_double);
554 bte = builtintable_get_internal(BUILTIN_newarray_byte);
557 bte = builtintable_get_internal(BUILTIN_newarray_short);
560 bte = builtintable_get_internal(BUILTIN_newarray_int);
563 bte = builtintable_get_internal(BUILTIN_newarray_long);
565 #if defined(ENABLE_VERIFIER)
567 *exceptionptr = new_verifyerror(m,
568 "Invalid array-type to create");
572 NEW_OP_BUILTIN_CHECK_EXCEPTION(bte);
576 i = code_get_u2(p + 1, m);
577 compr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
581 if (!(cr = class_get_classref_multiarray_of(1, compr)))
584 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
587 NEW_OP_LOADCONST_CLASSINFO_OR_CLASSREF(c, cr, INS_FLAG_NOCHECK);
588 bte = builtintable_get_internal(BUILTIN_newarray);
589 NEW_OP_BUILTIN_CHECK_EXCEPTION(bte);
593 case JAVA_MULTIANEWARRAY:
594 m->isleafmethod = false;
595 i = code_get_u2(p + 1, m);
597 s4 v = code_get_u1(p + 3, m);
599 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
603 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
606 /* if unresolved, c == NULL */
608 iptr->s1.argcount = v;
609 NEW_OP_S3_CLASSINFO_OR_CLASSREF(opcode, c, cr, 0 /* flags */);
613 /* control flow instructions ******************************************/
633 i = p + code_get_s2(p + 1,m);
634 CHECK_BYTECODE_INDEX(i);
637 NEW_OP_INSINDEX(opcode, i);
642 i = p + code_get_s4(p + 1,m);
643 CHECK_BYTECODE_INDEX(i);
646 NEW_OP_INSINDEX(opcode, i);
651 i = code_get_u1(p + 1,m);
654 i = code_get_u2(p + 1,m);
660 NEW_OP_LOAD_ONEWORD(opcode, i);
670 /* XXX ARETURN will need a flag in the typechecker */
676 /* XXX ATHROW will need a flag in the typechecker */
681 /* table jumps ********************************************************/
683 case JAVA_LOOKUPSWITCH:
686 lookup_target_t *lookup;
687 #if defined(ENABLE_VERIFIER)
691 nextp = ALIGN((p + 1), 4);
693 CHECK_END_OF_BYTECODE(nextp + 8);
695 NEW_OP_PREPARE_ZEROFLAGS(opcode);
699 j = p + code_get_s4(nextp, m);
700 iptr->sx.s23.s3.lookupdefault.insindex = j;
702 CHECK_BYTECODE_INDEX(j);
705 /* number of pairs */
707 num = code_get_u4(nextp, m);
708 iptr->sx.s23.s2.lookupcount = num;
711 /* allocate the intermediate code table */
713 lookup = DMNEW(lookup_target_t, num);
714 iptr->dst.lookup = lookup;
716 /* iterate over the lookup table */
718 CHECK_END_OF_BYTECODE(nextp + 8 * num);
720 for (i = 0; i < num; i++) {
723 j = code_get_s4(nextp, m);
728 #if defined(ENABLE_VERIFIER)
729 /* check if the lookup table is sorted correctly */
731 if (i && (j <= prevvalue)) {
732 *exceptionptr = new_verifyerror(m, "Unsorted lookup switch");
739 j = p + code_get_s4(nextp,m);
740 lookup->target.insindex = j;
743 CHECK_BYTECODE_INDEX(j);
752 case JAVA_TABLESWITCH:
756 branch_target_t *table;
759 nextp = ALIGN((p + 1), 4);
761 CHECK_END_OF_BYTECODE(nextp + 12);
763 NEW_OP_PREPARE_ZEROFLAGS(opcode);
767 deftarget = p + code_get_s4(nextp, m);
769 CHECK_BYTECODE_INDEX(deftarget);
770 block_insert(deftarget);
774 j = code_get_s4(nextp, m);
775 iptr->sx.s23.s2.tablelow = j;
780 num = code_get_s4(nextp, m);
781 iptr->sx.s23.s3.tablehigh = num;
784 /* calculate the number of table entries */
788 #if defined(ENABLE_VERIFIER)
790 *exceptionptr = new_verifyerror(m,
791 "invalid TABLESWITCH: upper bound < lower bound");
795 /* create the intermediate code table */
796 /* the first entry is the default target */
798 table = MNEW(branch_target_t, 1 + num);
799 iptr->dst.table = table;
800 (table++)->insindex = deftarget;
802 /* iterate over the target table */
804 CHECK_END_OF_BYTECODE(nextp + 4 * num);
806 for (i = 0; i < num; i++) {
807 j = p + code_get_s4(nextp,m);
808 (table++)->insindex = j;
810 CHECK_BYTECODE_INDEX(j);
819 /* load and store of object fields ************************************/
823 m->isleafmethod = false;
832 unresolved_field *uf;
834 i = code_get_u2(p + 1, m);
835 fr = class_getconstant(m->class, i, CONSTANT_Fieldref);
839 NEW_OP_PREPARE_ZEROFLAGS(opcode);
840 iptr->sx.s23.s3.fmiref = fr;
842 /* only with -noverify, otherwise the typechecker does this */
844 #if defined(ENABLE_VERIFIER)
847 result = new_resolve_field_lazy(iptr, NULL, m);
848 if (result == resolveFailed)
851 if (result != resolveSucceeded) {
852 uf = new_create_unresolved_field(m->class, m, iptr);
857 /* store the unresolved_field pointer */
859 iptr->sx.s23.s3.uf = uf;
860 iptr->flags.bits = INS_FLAG_UNRESOLVED;
862 #if defined(ENABLE_VERIFIER)
870 /* method invocation **************************************************/
872 case JAVA_INVOKESTATIC:
873 i = code_get_u2(p + 1, m);
874 mr = class_getconstant(m->class, i, CONSTANT_Methodref);
878 md = mr->parseddesc.md;
881 if (!descriptor_params_from_paramtypes(md, ACC_STATIC))
886 case JAVA_INVOKEINTERFACE:
887 i = code_get_u2(p + 1, m);
889 mr = class_getconstant(m->class, i,
890 CONSTANT_InterfaceMethodref);
892 goto invoke_nonstatic_method;
894 case JAVA_INVOKESPECIAL:
895 case JAVA_INVOKEVIRTUAL:
896 i = code_get_u2(p + 1, m);
897 mr = class_getconstant(m->class, i, CONSTANT_Methodref);
899 invoke_nonstatic_method:
903 md = mr->parseddesc.md;
906 if (!descriptor_params_from_paramtypes(md, 0))
910 m->isleafmethod = false;
912 NEW_OP_PREPARE_ZEROFLAGS(opcode);
913 iptr->sx.s23.s3.fmiref = mr;
915 /* only with -noverify, otherwise the typechecker does this */
917 #if defined(ENABLE_VERIFIER)
920 result = new_resolve_method_lazy(iptr, NULL, m);
921 if (result == resolveFailed)
924 if (result != resolveSucceeded) {
925 um = new_create_unresolved_method(m->class, m, iptr);
930 /* store the unresolved_method pointer */
932 iptr->sx.s23.s3.um = um;
933 iptr->flags.bits = INS_FLAG_UNRESOLVED;
935 #if defined(ENABLE_VERIFIER)
941 /* instructions taking class arguments ********************************/
944 i = code_get_u2(p + 1, m);
945 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
949 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
952 NEW_OP_LOADCONST_CLASSINFO_OR_CLASSREF(c, cr, INS_FLAG_NOCHECK);
953 bte = builtintable_get_internal(BUILTIN_new);
954 NEW_OP_BUILTIN_CHECK_EXCEPTION(bte);
959 i = code_get_u2(p + 1, m);
960 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
964 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
967 if (cr->name->text[0] == '[') {
968 /* array type cast-check */
969 flags = INS_FLAG_ARRAY;
970 m->isleafmethod = false;
973 /* object type cast-check */
976 NEW_OP_S3_CLASSINFO_OR_CLASSREF(opcode, c, cr, flags);
979 case JAVA_INSTANCEOF:
980 i = code_get_u2(p + 1,m);
981 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
985 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
988 if (cr->name->text[0] == '[') {
989 /* array type cast-check */
990 NEW_OP_LOADCONST_CLASSINFO_OR_CLASSREF(c, cr, INS_FLAG_NOCHECK);
991 bte = builtintable_get_internal(BUILTIN_arrayinstanceof);
992 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
996 /* object type cast-check */
997 NEW_OP_S3_CLASSINFO_OR_CLASSREF(opcode, c, cr, 0 /* flags*/);
1001 /* synchronization instructions ***************************************/
1003 case JAVA_MONITORENTER:
1004 #if defined(ENABLE_THREADS)
1006 /* XXX null check */
1007 bte = builtintable_get_internal(BUILTIN_monitorenter);
1008 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1013 NEW_OP(ICMD_CHECKNULL_POP);
1017 case JAVA_MONITOREXIT:
1018 #if defined(ENABLE_THREADS)
1020 /* XXX null check */
1021 bte = builtintable_get_internal(BUILTIN_monitorexit);
1022 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1027 NEW_OP(ICMD_CHECKNULL_POP);
1031 /* arithmetic instructions they may become builtin functions **********/
1034 #if !SUPPORT_DIVISION
1035 bte = builtintable_get_internal(BUILTIN_idiv);
1036 NEW_OP_BUILTIN_ARITHMETIC(opcode, bte);
1043 #if !SUPPORT_DIVISION
1044 bte = builtintable_get_internal(BUILTIN_irem);
1045 NEW_OP_BUILTIN_ARITHMETIC(opcode, bte);
1052 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1053 bte = builtintable_get_internal(BUILTIN_ldiv);
1054 NEW_OP_BUILTIN_ARITHMETIC(opcode, bte);
1061 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1062 bte = builtintable_get_internal(BUILTIN_lrem);
1063 NEW_OP_BUILTIN_ARITHMETIC(opcode, bte);
1070 #if defined(__I386__)
1073 bte = builtintable_get_internal(BUILTIN_frem);
1074 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1079 #if defined(__I386__)
1082 bte = builtintable_get_internal(BUILTIN_drem);
1083 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1088 #if defined(__ALPHA__)
1090 bte = builtintable_get_internal(BUILTIN_f2i);
1091 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1101 #if defined(__ALPHA__)
1103 bte = builtintable_get_internal(BUILTIN_f2l);
1104 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1114 #if defined(__ALPHA__)
1116 bte = builtintable_get_internal(BUILTIN_d2i);
1117 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1127 #if defined(__ALPHA__)
1129 bte = builtintable_get_internal(BUILTIN_d2l);
1130 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1139 /* invalid opcodes ****************************************************/
1141 /* check for invalid opcodes if the verifier is enabled */
1142 #if defined(ENABLE_VERIFIER)
1143 case JAVA_BREAKPOINT:
1145 new_verifyerror(m, "Quick instructions shouldn't appear yet.");
1148 case 186: /* unused opcode */
1203 new_verifyerror(m,"Illegal opcode %d at instr %d\n",
1207 #endif /* defined(ENABLE_VERIFIER) */
1209 /* opcodes that don't require translation *****************************/
1212 /* straight-forward translation to ICMD */
1218 #if defined(ENABLE_VERIFIER)
1219 /* If WIDE was used correctly, iswide should have been reset by now. */
1221 *exceptionptr = new_verifyerror(m,
1222 "Illegal instruction: WIDE before incompatible opcode");
1225 #endif /* defined(ENABLE_VERIFIER) */
1229 /*** END OF LOOP **********************************************************/
1231 #if defined(ENABLE_VERIFIER)
1232 if (p != m->jcodelength) {
1233 *exceptionptr = new_verifyerror(m,
1234 "Command-sequence crosses code-boundary");
1239 *exceptionptr = new_verifyerror(m, "Falling off the end of the code");
1242 #endif /* defined(ENABLE_VERIFIER) */
1244 /* adjust block count if target 0 is not first intermediate instruction */
1246 if (!m->basicblockindex[0] || (m->basicblockindex[0] > 1))
1249 /* copy local to method variables */
1251 m->instructioncount = ipc;
1252 m->basicblockcount = b_count;
1253 m->stackcount = s_count + m->basicblockcount * m->maxstack;
1255 /* allocate stack table */
1257 m->stack = DMNEW(stackelement, m->stackcount);
1262 bptr = m->basicblocks = DMNEW(basicblock, b_count + 1); /* one more for end ipc */
1267 /* additional block if target 0 is not first intermediate instruction */
1269 if (!m->basicblockindex[0] || (m->basicblockindex[0] > 1)) {
1270 BASICBLOCK_INIT(bptr,m);
1272 bptr->iinstr = m->instructions;
1273 /* bptr->icount is set when the next block is allocated */
1277 bptr[-1].next = bptr;
1280 /* allocate blocks */
1282 for (p = 0; p < m->jcodelength; p++) {
1283 if (m->basicblockindex[p] & 1) {
1284 /* Check if this block starts at the beginning of an */
1286 #if defined(ENABLE_VERIFIER)
1287 if (!instructionstart[p]) {
1288 *exceptionptr = new_verifyerror(m,
1289 "Branch into middle of instruction");
1294 /* allocate the block */
1296 BASICBLOCK_INIT(bptr,m);
1298 bptr->iinstr = m->instructions + (m->basicblockindex[p] >> 1);
1300 bptr[-1].icount = bptr->iinstr - bptr[-1].iinstr;
1302 /* bptr->icount is set when the next block is allocated */
1304 m->basicblockindex[p] = b_count;
1308 bptr[-1].next = bptr;
1312 /* set instruction count of last real block */
1315 bptr[-1].icount = (m->instructions + m->instructioncount) - bptr[-1].iinstr;
1318 /* allocate additional block at end */
1320 BASICBLOCK_INIT(bptr,m);
1322 bptr->instack = bptr->outstack = NULL;
1323 bptr->indepth = bptr->outdepth = 0;
1324 bptr->iinstr = NULL;
1328 /* set basicblock pointers in exception table */
1330 if (cd->exceptiontablelength > 0) {
1331 cd->exceptiontable[cd->exceptiontablelength - 1].down = NULL;
1334 for (i = 0; i < cd->exceptiontablelength; ++i) {
1335 p = cd->exceptiontable[i].startpc;
1336 cd->exceptiontable[i].start = m->basicblocks + m->basicblockindex[p];
1338 p = cd->exceptiontable[i].endpc;
1339 cd->exceptiontable[i].end = (p == m->jcodelength) ? (m->basicblocks + m->basicblockcount /*+ 1*/) : (m->basicblocks + m->basicblockindex[p]);
1341 p = cd->exceptiontable[i].handlerpc;
1342 cd->exceptiontable[i].handler = m->basicblocks + m->basicblockindex[p];
1345 /* XXX activate this if you want to try inlining */
1347 for (i = 0; i < m->exceptiontablelength; ++i) {
1348 p = m->exceptiontable[i].startpc;
1349 m->exceptiontable[i].start = m->basicblocks + m->basicblockindex[p];
1351 p = m->exceptiontable[i].endpc;
1352 m->exceptiontable[i].end = (p == m->jcodelength) ? (m->basicblocks + m->basicblockcount /*+ 1*/) : (m->basicblocks + m->basicblockindex[p]);
1354 p = m->exceptiontable[i].handlerpc;
1355 m->exceptiontable[i].handler = m->basicblocks + m->basicblockindex[p];
1361 /* everything's ok */
1365 #if defined(ENABLE_VERIFIER)
1367 throw_unexpected_end_of_bytecode:
1368 *exceptionptr = new_verifyerror(m, "Unexpected end of bytecode");
1371 throw_invalid_bytecode_index:
1373 new_verifyerror(m, "Illegal target of branch instruction");
1376 throw_illegal_local_variable_number:
1378 new_verifyerror(m, "Illegal local variable number");
1381 #endif /* ENABLE_VERIFIER */
1385 bool parse(jitdata *jd)
1389 int p; /* java instruction counter */
1390 int nextp; /* start of next java instruction */
1391 int opcode; /* java opcode */
1392 int i; /* temporary for different uses (ctrs)*/
1393 int ipc = 0; /* intermediate instruction counter */
1394 int b_count = 0; /* basic block counter */
1395 int s_count = 0; /* stack element counter */
1396 bool blockend = false; /* true if basic block end has been reached */
1397 bool iswide = false; /* true if last instruction was a wide*/
1398 instruction *iptr; /* current ptr into instruction array */
1400 u1 *instructionstart; /* 1 for pcs which are valid instr. starts */
1402 constant_classref *cr;
1403 constant_classref *compr;
1405 builtintable_entry *bte;
1407 constant_FMIref *mr;
1409 unresolved_method *um;
1410 resolve_result_t result;
1414 u2 linepcchange = 0;
1416 /* get required compiler data */
1421 /* allocate instruction array and block index table */
1423 /* 1 additional for end ipc */
1424 m->basicblockindex = DMNEW(s4, m->jcodelength + 1);
1425 memset(m->basicblockindex, 0, sizeof(s4) * (m->jcodelength + 1));
1427 instructionstart = DMNEW(u1, m->jcodelength + 1);
1428 memset(instructionstart, 0, sizeof(u1) * (m->jcodelength + 1));
1430 /* 1 additional for TRACEBUILTIN and 4 for MONITORENTER/EXIT */
1431 /* additional MONITOREXITS are reached by branches which are 3 bytes */
1433 iptr = m->instructions = DMNEW(instruction, m->jcodelength + 5);
1435 /* Zero the intermediate instructions array so we don't have any
1436 * invalid pointers in it if we cannot finish analyse_stack(). */
1438 memset(iptr, 0, sizeof(instruction) * (m->jcodelength + 5));
1440 /* compute branch targets of exception table */
1443 &(cd->exceptiontable[cd->exceptiontablelength-1]),
1445 m->exceptiontablelength,
1451 s_count = 1 + m->exceptiontablelength; /* initialize stack element counter */
1453 #if defined(ENABLE_THREADS)
1454 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
1455 m->isleafmethod = false;
1459 /* scan all java instructions */
1463 if (m->linenumbercount == 0) {
1467 linepcchange = m->linenumbers[0].start_pc;
1470 for (p = 0; p < m->jcodelength; p = nextp) {
1472 /* mark this position as a valid instruction start */
1473 instructionstart[p] = 1;
1474 if (linepcchange == p) {
1475 if (m->linenumbercount > lineindex) {
1477 currentline = m->linenumbers[lineindex].line_number;
1479 if (lineindex < m->linenumbercount) {
1480 linepcchange = m->linenumbers[lineindex].start_pc;
1481 if (linepcchange == p)
1482 goto next_linenumber;
1487 /* fetch next opcode */
1489 opcode = code_get_u1(p, m);
1491 m->basicblockindex[p] |= (ipc << 1); /*store intermed cnt*/
1493 /* some compilers put a JAVA_NOP after a blockend instruction */
1495 if (blockend && (opcode != JAVA_NOP)) {
1496 /* start new block */
1502 nextp = p + jcommandsize[opcode]; /* compute next instruction start */
1504 CHECK_END_OF_BYTECODE(nextp);
1506 s_count += stackreq[opcode]; /* compute stack element count */
1511 /* pushing constants onto the stack p */
1514 LOADCONST_I(code_get_s1(p+1,m));
1518 LOADCONST_I(code_get_s2(p+1,m));
1522 i = code_get_u1(p + 1, m);
1523 goto pushconstantitem;
1527 i = code_get_u2(p + 1, m);
1531 #if defined(ENABLE_VERIFIER)
1532 if (i >= m->class->cpcount) {
1533 *exceptionptr = new_verifyerror(m,
1534 "Attempt to access constant outside range");
1539 switch (m->class->cptags[i]) {
1540 case CONSTANT_Integer:
1541 LOADCONST_I(((constant_integer *) (m->class->cpinfos[i]))->value);
1544 LOADCONST_L(((constant_long *) (m->class->cpinfos[i]))->value);
1546 case CONSTANT_Float:
1547 LOADCONST_F(((constant_float *) (m->class->cpinfos[i]))->value);
1549 case CONSTANT_Double:
1550 LOADCONST_D(((constant_double *) (m->class->cpinfos[i]))->value);
1552 case CONSTANT_String:
1553 LOADCONST_A(literalstring_new((utf *) (m->class->cpinfos[i])));
1555 case CONSTANT_Class:
1556 cr = (constant_classref *) (m->class->cpinfos[i]);
1558 if (!resolve_classref(m, cr, resolveLazy, true,
1562 /* if not resolved, c == NULL */
1565 iptr->target = (void*) 0x02; /* XXX target used temporarily as flag */
1569 iptr->target = (void*) 0x03; /* XXX target used temporarily as flag */
1574 #if defined(ENABLE_VERIFIER)
1576 *exceptionptr = new_verifyerror(m,
1577 "Invalid constant type to push");
1583 case JAVA_ACONST_NULL:
1587 case JAVA_ICONST_M1:
1594 LOADCONST_I(opcode - JAVA_ICONST_0);
1599 LOADCONST_L(opcode - JAVA_LCONST_0);
1605 LOADCONST_F(opcode - JAVA_FCONST_0);
1610 LOADCONST_D(opcode - JAVA_DCONST_0);
1613 /* loading variables onto the stack */
1619 i = code_get_u1(p + 1,m);
1622 i = code_get_u2(p + 1,m);
1626 OP1LOAD_ONEWORD(opcode, i);
1632 i = code_get_u1(p + 1,m);
1635 i = code_get_u2(p + 1,m);
1639 OP1LOAD_TWOWORD(opcode, i);
1646 OP1LOAD_ONEWORD(ICMD_ILOAD, opcode - JAVA_ILOAD_0);
1653 OP1LOAD_TWOWORD(ICMD_LLOAD, opcode - JAVA_LLOAD_0);
1660 OP1LOAD_ONEWORD(ICMD_FLOAD, opcode - JAVA_FLOAD_0);
1667 OP1LOAD_TWOWORD(ICMD_DLOAD, opcode - JAVA_DLOAD_0);
1674 OP1LOAD_ONEWORD(ICMD_ALOAD, opcode - JAVA_ALOAD_0);
1677 /* storing stack values into local variables */
1683 i = code_get_u1(p + 1,m);
1686 i = code_get_u2(p + 1,m);
1690 OP1STORE_ONEWORD(opcode, i);
1696 i = code_get_u1(p + 1,m);
1699 i = code_get_u2(p + 1,m);
1703 OP1STORE_TWOWORD(opcode, i);
1710 OP1STORE_ONEWORD(ICMD_ISTORE, opcode - JAVA_ISTORE_0);
1717 OP1STORE_TWOWORD(ICMD_LSTORE, opcode - JAVA_LSTORE_0);
1724 OP1STORE_ONEWORD(ICMD_FSTORE, opcode - JAVA_FSTORE_0);
1731 OP1STORE_TWOWORD(ICMD_DSTORE, opcode - JAVA_DSTORE_0);
1738 OP1STORE_ONEWORD(ICMD_ASTORE, opcode - JAVA_ASTORE_0);
1746 i = code_get_u1(p + 1,m);
1747 v = code_get_s1(p + 2,m);
1751 i = code_get_u2(p + 1,m);
1752 v = code_get_s2(p + 3,m);
1761 /* wider index for loading, storing and incrementing */
1768 /* managing arrays ****************************************************/
1771 switch (code_get_s1(p + 1, m)) {
1773 bte = builtintable_get_internal(BUILTIN_newarray_boolean);
1776 bte = builtintable_get_internal(BUILTIN_newarray_char);
1779 bte = builtintable_get_internal(BUILTIN_newarray_float);
1782 bte = builtintable_get_internal(BUILTIN_newarray_double);
1785 bte = builtintable_get_internal(BUILTIN_newarray_byte);
1788 bte = builtintable_get_internal(BUILTIN_newarray_short);
1791 bte = builtintable_get_internal(BUILTIN_newarray_int);
1794 bte = builtintable_get_internal(BUILTIN_newarray_long);
1796 #if defined(ENABLE_VERIFIER)
1798 *exceptionptr = new_verifyerror(m,
1799 "Invalid array-type to create");
1803 BUILTIN(bte, true, NULL, currentline);
1806 case JAVA_ANEWARRAY:
1807 i = code_get_u2(p + 1, m);
1808 compr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
1812 if (!(cr = class_get_classref_multiarray_of(1, compr)))
1815 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
1818 LOADCONST_A_BUILTIN(c, cr);
1819 bte = builtintable_get_internal(BUILTIN_newarray);
1820 BUILTIN(bte, true, NULL, currentline);
1824 case JAVA_MULTIANEWARRAY:
1825 m->isleafmethod = false;
1826 i = code_get_u2(p + 1, m);
1828 s4 v = code_get_u1(p + 3, m);
1830 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
1834 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
1837 /* if unresolved, c == NULL */
1838 OP2AT(opcode, v, c, cr, currentline);
1849 case JAVA_IFNONNULL:
1850 case JAVA_IF_ICMPEQ:
1851 case JAVA_IF_ICMPNE:
1852 case JAVA_IF_ICMPLT:
1853 case JAVA_IF_ICMPGT:
1854 case JAVA_IF_ICMPLE:
1855 case JAVA_IF_ICMPGE:
1856 case JAVA_IF_ACMPEQ:
1857 case JAVA_IF_ACMPNE:
1860 i = p + code_get_s2(p + 1,m);
1861 CHECK_BYTECODE_INDEX(i);
1869 i = p + code_get_s4(p + 1,m);
1870 CHECK_BYTECODE_INDEX(i);
1878 i = code_get_u1(p + 1,m);
1881 i = code_get_u2(p + 1,m);
1887 OP1LOAD_ONEWORD(opcode, i);
1897 /* zero val.a so no patcher is inserted */
1898 /* the type checker may set this later */
1905 /* zero val.a so no patcher is inserted */
1906 /* the type checker may set this later */
1912 /* table jumps ********************************************************/
1914 case JAVA_LOOKUPSWITCH:
1918 #if defined(ENABLE_VERIFIER)
1923 nextp = ALIGN((p + 1), 4);
1925 CHECK_END_OF_BYTECODE(nextp + 8);
1927 tablep = (s4 *) (m->jcode + nextp);
1929 OP2A(opcode, 0, tablep, currentline);
1931 /* default target */
1933 j = p + code_get_s4(nextp, m);
1934 *tablep = j; /* restore for little endian */
1937 CHECK_BYTECODE_INDEX(j);
1940 /* number of pairs */
1942 num = code_get_u4(nextp, m);
1947 CHECK_END_OF_BYTECODE(nextp + 8 * num);
1949 for (i = 0; i < num; i++) {
1952 j = code_get_s4(nextp, m);
1953 *tablep = j; /* restore for little endian */
1957 #if defined(ENABLE_VERIFIER)
1958 /* check if the lookup table is sorted correctly */
1960 if (i && (j <= prevvalue)) {
1961 *exceptionptr = new_verifyerror(m, "Unsorted lookup switch");
1969 j = p + code_get_s4(nextp,m);
1970 *tablep = j; /* restore for little endian */
1973 CHECK_BYTECODE_INDEX(j);
1981 case JAVA_TABLESWITCH:
1987 nextp = ALIGN((p + 1), 4);
1989 CHECK_END_OF_BYTECODE(nextp + 12);
1991 tablep = (s4 *) (m->jcode + nextp);
1993 OP2A(opcode, 0, tablep, currentline);
1995 /* default target */
1997 j = p + code_get_s4(nextp, m);
1998 *tablep = j; /* restore for little endian */
2001 CHECK_BYTECODE_INDEX(j);
2006 j = code_get_s4(nextp, m);
2007 *tablep = j; /* restore for little endian */
2013 num = code_get_s4(nextp, m);
2014 *tablep = num; /* restore for little endian */
2018 num -= j; /* difference of upper - lower */
2020 #if defined(ENABLE_VERIFIER)
2022 *exceptionptr = new_verifyerror(m,
2023 "invalid TABLESWITCH: upper bound < lower bound");
2028 CHECK_END_OF_BYTECODE(nextp + 4 * (num + 1));
2030 for (i = 0; i <= num; i++) {
2031 j = p + code_get_s4(nextp,m);
2032 *tablep = j; /* restore for little endian */
2035 CHECK_BYTECODE_INDEX(j);
2043 /* load and store of object fields ************************************/
2047 m->isleafmethod = false;
2050 case JAVA_GETSTATIC:
2051 case JAVA_PUTSTATIC:
2055 constant_FMIref *fr;
2056 unresolved_field *uf;
2058 i = code_get_u2(p + 1, m);
2059 fr = class_getconstant(m->class, i,
2064 OP2A_NOINC(opcode, fr->parseddesc.fd->type, fr, currentline);
2066 /* only with -noverify, otherwise the typechecker does this */
2068 #if defined(ENABLE_VERIFIER)
2071 result = resolve_field_lazy(iptr,NULL,m);
2072 if (result == resolveFailed)
2075 if (result != resolveSucceeded) {
2076 uf = create_unresolved_field(m->class,
2082 /* store the unresolved_field pointer */
2084 /* XXX this will be changed */
2086 iptr->target = (void*) 0x01; /* XXX target temporarily used as flag */
2089 iptr->target = NULL;
2091 #if defined(ENABLE_VERIFIER)
2094 iptr->target = NULL;
2102 /* method invocation **************************************************/
2104 case JAVA_INVOKESTATIC:
2105 i = code_get_u2(p + 1, m);
2106 mr = class_getconstant(m->class, i,
2107 CONSTANT_Methodref);
2111 md = mr->parseddesc.md;
2114 if (!descriptor_params_from_paramtypes(md, ACC_STATIC))
2119 case JAVA_INVOKEINTERFACE:
2120 i = code_get_u2(p + 1, m);
2122 mr = class_getconstant(m->class, i,
2123 CONSTANT_InterfaceMethodref);
2125 goto invoke_nonstatic_method;
2127 case JAVA_INVOKESPECIAL:
2128 case JAVA_INVOKEVIRTUAL:
2129 i = code_get_u2(p + 1, m);
2130 mr = class_getconstant(m->class, i,
2131 CONSTANT_Methodref);
2133 invoke_nonstatic_method:
2137 md = mr->parseddesc.md;
2140 if (!descriptor_params_from_paramtypes(md, 0))
2144 m->isleafmethod = false;
2146 OP2A_NOINC(opcode, 0, mr, currentline);
2148 /* only with -noverify, otherwise the typechecker does this */
2150 #if defined(ENABLE_VERIFIER)
2153 result = resolve_method_lazy(iptr,NULL,m);
2154 if (result == resolveFailed)
2157 if (result != resolveSucceeded) {
2158 um = create_unresolved_method(m->class,
2164 /* store the unresolved_method pointer */
2166 /* XXX this will be changed */
2168 iptr->target = (void*) 0x01; /* XXX target temporarily used as flag */
2171 /* the method could be resolved */
2172 iptr->target = NULL;
2174 #if defined(ENABLE_VERIFIER)
2177 iptr->target = NULL;
2183 /* miscellaneous object operations ************************************/
2186 i = code_get_u2(p + 1, m);
2187 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
2191 if (!resolve_classref(m, cr, resolveLazy, true, true,
2195 LOADCONST_A_BUILTIN(c, cr);
2196 bte = builtintable_get_internal(BUILTIN_new);
2197 BUILTIN(bte, true, NULL, currentline);
2201 case JAVA_CHECKCAST:
2202 i = code_get_u2(p + 1, m);
2203 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
2207 if (!resolve_classref(m, cr, resolveLazy, true,
2211 if (cr->name->text[0] == '[') {
2212 /* array type cast-check */
2213 OP2AT(opcode, 0, c, cr, currentline);
2214 m->isleafmethod = false;
2218 /* object type cast-check */
2219 OP2AT(opcode, 1, c, cr, currentline);
2223 case JAVA_INSTANCEOF:
2224 i = code_get_u2(p + 1,m);
2225 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
2229 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
2232 if (cr->name->text[0] == '[') {
2233 /* array type cast-check */
2234 LOADCONST_A_BUILTIN(c, cr);
2235 bte = builtintable_get_internal(BUILTIN_arrayinstanceof);
2236 BUILTIN(bte, false, NULL, currentline);
2241 /* object type cast-check */
2242 OP2AT(opcode, 1, c, cr, currentline);
2246 case JAVA_MONITORENTER:
2247 #if defined(ENABLE_THREADS)
2250 bte = builtintable_get_internal(BUILTIN_monitorenter);
2251 BUILTIN(bte, false, NULL, currentline);
2261 case JAVA_MONITOREXIT:
2262 #if defined(ENABLE_THREADS)
2264 bte = builtintable_get_internal(BUILTIN_monitorexit);
2265 BUILTIN(bte, false, NULL, currentline);
2274 /* any other basic operation ******************************************/
2277 #if !SUPPORT_DIVISION
2278 bte = builtintable_get_internal(BUILTIN_idiv);
2279 OP2A(opcode, bte->md->paramcount, bte, currentline);
2280 m->isleafmethod = false;
2287 #if !SUPPORT_DIVISION
2288 bte = builtintable_get_internal(BUILTIN_irem);
2289 OP2A(opcode, bte->md->paramcount, bte, currentline);
2290 m->isleafmethod = false;
2297 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
2298 bte = builtintable_get_internal(BUILTIN_ldiv);
2299 OP2A(opcode, bte->md->paramcount, bte, currentline);
2300 m->isleafmethod = false;
2307 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
2308 bte = builtintable_get_internal(BUILTIN_lrem);
2309 OP2A(opcode, bte->md->paramcount, bte, currentline);
2310 m->isleafmethod = false;
2317 #if defined(__I386__)
2320 bte = builtintable_get_internal(BUILTIN_frem);
2321 BUILTIN(bte, false, NULL, currentline);
2326 #if defined(__I386__)
2329 bte = builtintable_get_internal(BUILTIN_drem);
2330 BUILTIN(bte, false, NULL, currentline);
2335 #if defined(__ALPHA__)
2337 bte = builtintable_get_internal(BUILTIN_f2i);
2338 BUILTIN(bte, false, NULL, currentline);
2348 #if defined(__ALPHA__)
2350 bte = builtintable_get_internal(BUILTIN_f2l);
2351 BUILTIN(bte, false, NULL, currentline);
2361 #if defined(__ALPHA__)
2363 bte = builtintable_get_internal(BUILTIN_d2i);
2364 BUILTIN(bte, false, NULL, currentline);
2374 #if defined(__ALPHA__)
2376 bte = builtintable_get_internal(BUILTIN_d2l);
2377 BUILTIN(bte, false, NULL, currentline);
2386 /* check for invalid opcodes if the verifier is enabled */
2387 #if defined(ENABLE_VERIFIER)
2388 case JAVA_BREAKPOINT:
2390 new_verifyerror(m, "Quick instructions shouldn't appear yet.");
2393 case 186: /* unused opcode */
2448 new_verifyerror(m,"Illegal opcode %d at instr %d\n",
2452 #endif /* defined(ENABLE_VERIFIER) */
2455 /* straight-forward translation to ICMD */
2461 #if defined(ENABLE_VERIFIER)
2462 /* If WIDE was used correctly, iswide should have been reset by now. */
2464 *exceptionptr = new_verifyerror(m,
2465 "Illegal instruction: WIDE before incompatible opcode");
2468 #endif /* defined(ENABLE_VERIFIER) */
2472 #if defined(ENABLE_VERIFIER)
2473 if (p != m->jcodelength) {
2474 *exceptionptr = new_verifyerror(m,
2475 "Command-sequence crosses code-boundary");
2480 *exceptionptr = new_verifyerror(m, "Falling off the end of the code");
2483 #endif /* defined(ENABLE_VERIFIER) */
2485 /* adjust block count if target 0 is not first intermediate instruction */
2487 if (!m->basicblockindex[0] || (m->basicblockindex[0] > 1))
2490 /* copy local to method variables */
2492 m->instructioncount = ipc;
2493 m->basicblockcount = b_count;
2494 m->stackcount = s_count + m->basicblockcount * m->maxstack;
2496 /* allocate stack table */
2498 m->stack = DMNEW(stackelement, m->stackcount);
2503 bptr = m->basicblocks = DMNEW(basicblock, b_count + 1); /* one more for end ipc */
2508 /* additional block if target 0 is not first intermediate instruction */
2510 if (!m->basicblockindex[0] || (m->basicblockindex[0] > 1)) {
2511 BASICBLOCK_INIT(bptr,m);
2513 bptr->iinstr = m->instructions;
2514 /* bptr->icount is set when the next block is allocated */
2518 bptr[-1].next = bptr;
2521 /* allocate blocks */
2523 for (p = 0; p < m->jcodelength; p++) {
2524 if (m->basicblockindex[p] & 1) {
2525 /* Check if this block starts at the beginning of an */
2527 #if defined(ENABLE_VERIFIER)
2528 if (!instructionstart[p]) {
2529 *exceptionptr = new_verifyerror(m,
2530 "Branch into middle of instruction");
2535 /* allocate the block */
2537 BASICBLOCK_INIT(bptr,m);
2539 bptr->iinstr = m->instructions + (m->basicblockindex[p] >> 1);
2541 bptr[-1].icount = bptr->iinstr - bptr[-1].iinstr;
2543 /* bptr->icount is set when the next block is allocated */
2545 m->basicblockindex[p] = b_count;
2549 bptr[-1].next = bptr;
2553 /* set instruction count of last real block */
2556 bptr[-1].icount = (m->instructions + m->instructioncount) - bptr[-1].iinstr;
2559 /* allocate additional block at end */
2561 BASICBLOCK_INIT(bptr,m);
2563 bptr->instack = bptr->outstack = NULL;
2564 bptr->indepth = bptr->outdepth = 0;
2565 bptr->iinstr = NULL;
2569 /* set basicblock pointers in exception table */
2571 if (cd->exceptiontablelength > 0) {
2572 cd->exceptiontable[cd->exceptiontablelength - 1].down = NULL;
2575 for (i = 0; i < cd->exceptiontablelength; ++i) {
2576 p = cd->exceptiontable[i].startpc;
2577 cd->exceptiontable[i].start = m->basicblocks + m->basicblockindex[p];
2579 p = cd->exceptiontable[i].endpc;
2580 cd->exceptiontable[i].end = (p == m->jcodelength) ? (m->basicblocks + m->basicblockcount /*+ 1*/) : (m->basicblocks + m->basicblockindex[p]);
2582 p = cd->exceptiontable[i].handlerpc;
2583 cd->exceptiontable[i].handler = m->basicblocks + m->basicblockindex[p];
2586 /* XXX activate this if you want to try inlining */
2588 for (i = 0; i < m->exceptiontablelength; ++i) {
2589 p = m->exceptiontable[i].startpc;
2590 m->exceptiontable[i].start = m->basicblocks + m->basicblockindex[p];
2592 p = m->exceptiontable[i].endpc;
2593 m->exceptiontable[i].end = (p == m->jcodelength) ? (m->basicblocks + m->basicblockcount /*+ 1*/) : (m->basicblocks + m->basicblockindex[p]);
2595 p = m->exceptiontable[i].handlerpc;
2596 m->exceptiontable[i].handler = m->basicblocks + m->basicblockindex[p];
2602 /* everything's ok */
2606 #if defined(ENABLE_VERIFIER)
2608 throw_unexpected_end_of_bytecode:
2609 *exceptionptr = new_verifyerror(m, "Unexpected end of bytecode");
2612 throw_invalid_bytecode_index:
2614 new_verifyerror(m, "Illegal target of branch instruction");
2617 throw_illegal_local_variable_number:
2619 new_verifyerror(m, "Illegal local variable number");
2622 #endif /* ENABLE_VERIFIER */
2627 * These are local overrides for various environment variables in Emacs.
2628 * Please do not remove this and leave it at the end of the file, where
2629 * Emacs will automagically detect them.
2630 * ---------------------------------------------------------------------
2633 * indent-tabs-mode: t
2637 * vim:noexpandtab:sw=4:ts=4: