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 4993 2006-05-30 23:38:32Z 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 /* 1 additional for TRACEBUILTIN and 4 for MONITORENTER/EXIT */
194 /* additional MONITOREXITS are reached by branches which are 3 bytes */
196 iptr = jd->new_instructions = DMNEW(new_instruction, m->jcodelength + 5);
198 /* Zero the intermediate instructions array so we don't have any
199 * invalid pointers in it if we cannot finish analyse_stack(). */
201 memset(iptr, 0, sizeof(new_instruction) * (m->jcodelength + 5)); /* XXX remove this? */
203 /* compute branch targets of exception table */
206 &(cd->exceptiontable[cd->exceptiontablelength-1]),
208 m->exceptiontablelength,
214 s_count = 1 + m->exceptiontablelength; /* initialize stack element counter */
216 #if defined(ENABLE_THREADS)
217 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
218 m->isleafmethod = false;
222 /* scan all java instructions */
226 if (m->linenumbercount == 0) {
230 linepcchange = m->linenumbers[0].start_pc;
233 /*** LOOP OVER ALL BYTECODE INSTRUCTIONS **********************************/
235 for (p = 0; p < m->jcodelength; p = nextp) {
237 /* mark this position as a valid instruction start */
239 instructionstart[p] = 1;
241 /* change the current line number, if necessary */
243 if (linepcchange == p) {
244 if (m->linenumbercount > lineindex) {
246 currentline = m->linenumbers[lineindex].line_number;
248 if (lineindex < m->linenumbercount) {
249 linepcchange = m->linenumbers[lineindex].start_pc;
250 if (linepcchange == p)
251 goto next_linenumber;
256 /* fetch next opcode */
258 opcode = code_get_u1(p, m);
260 /* store intermediate instruction count (bit 0 mark block starts) */
262 m->basicblockindex[p] |= (ipc << 1);
264 /* some compilers put a JAVA_NOP after a blockend instruction */
266 if (blockend && (opcode != JAVA_NOP)) {
267 /* start new block */
273 /* compute next instruction start */
275 nextp = p + jcommandsize[opcode];
277 CHECK_END_OF_BYTECODE(nextp);
279 /* add stack elements produced by this instruction */
281 s_count += stackreq[opcode];
283 /* translate this bytecode instruction */
290 /* pushing constants onto the stack ***********************************/
293 NEW_OP_LOADCONST_I(code_get_s1(p+1,m));
297 NEW_OP_LOADCONST_I(code_get_s2(p+1,m));
301 i = code_get_u1(p + 1, m);
302 goto pushconstantitem;
306 i = code_get_u2(p + 1, m);
310 #if defined(ENABLE_VERIFIER)
311 if (i >= m->class->cpcount) {
312 *exceptionptr = new_verifyerror(m,
313 "Attempt to access constant outside range");
318 switch (m->class->cptags[i]) {
319 case CONSTANT_Integer:
320 NEW_OP_LOADCONST_I(((constant_integer *) (m->class->cpinfos[i]))->value);
323 NEW_OP_LOADCONST_L(((constant_long *) (m->class->cpinfos[i]))->value);
326 NEW_OP_LOADCONST_F(((constant_float *) (m->class->cpinfos[i]))->value);
328 case CONSTANT_Double:
329 NEW_OP_LOADCONST_D(((constant_double *) (m->class->cpinfos[i]))->value);
331 case CONSTANT_String:
332 NEW_OP_LOADCONST_STRING(literalstring_new((utf *) (m->class->cpinfos[i])));
335 cr = (constant_classref *) (m->class->cpinfos[i]);
337 if (!resolve_classref(m, cr, resolveLazy, true,
341 /* if not resolved, c == NULL */
343 NEW_OP_LOADCONST_CLASSINFO_OR_CLASSREF(c, cr, 0 /* no extra flags */);
347 #if defined(ENABLE_VERIFIER)
349 *exceptionptr = new_verifyerror(m,
350 "Invalid constant type to push");
356 case JAVA_ACONST_NULL:
357 NEW_OP_LOADCONST_NULL();
367 NEW_OP_LOADCONST_I(opcode - JAVA_ICONST_0);
372 NEW_OP_LOADCONST_L(opcode - JAVA_LCONST_0);
378 NEW_OP_LOADCONST_F(opcode - JAVA_FCONST_0);
383 NEW_OP_LOADCONST_D(opcode - JAVA_DCONST_0);
386 /* local variable access instructions *********************************/
392 i = code_get_u1(p + 1,m);
395 i = code_get_u2(p + 1,m);
399 NEW_OP_LOAD_ONEWORD(opcode, i);
405 i = code_get_u1(p + 1,m);
408 i = code_get_u2(p + 1,m);
412 NEW_OP_LOAD_TWOWORD(opcode, i);
419 NEW_OP_LOAD_ONEWORD(ICMD_ILOAD, opcode - JAVA_ILOAD_0);
426 NEW_OP_LOAD_TWOWORD(ICMD_LLOAD, opcode - JAVA_LLOAD_0);
433 NEW_OP_LOAD_ONEWORD(ICMD_FLOAD, opcode - JAVA_FLOAD_0);
440 NEW_OP_LOAD_TWOWORD(ICMD_DLOAD, opcode - JAVA_DLOAD_0);
447 NEW_OP_LOAD_ONEWORD(ICMD_ALOAD, opcode - JAVA_ALOAD_0);
454 i = code_get_u1(p + 1,m);
457 i = code_get_u2(p + 1,m);
461 NEW_OP_STORE_ONEWORD(opcode, i);
467 i = code_get_u1(p + 1,m);
470 i = code_get_u2(p + 1,m);
474 NEW_OP_STORE_TWOWORD(opcode, i);
481 NEW_OP_STORE_ONEWORD(ICMD_ISTORE, opcode - JAVA_ISTORE_0);
488 NEW_OP_STORE_TWOWORD(ICMD_LSTORE, opcode - JAVA_LSTORE_0);
495 NEW_OP_STORE_ONEWORD(ICMD_FSTORE, opcode - JAVA_FSTORE_0);
502 NEW_OP_STORE_TWOWORD(ICMD_DSTORE, opcode - JAVA_DSTORE_0);
509 NEW_OP_STORE_ONEWORD(ICMD_ASTORE, opcode - JAVA_ASTORE_0);
517 i = code_get_u1(p + 1,m);
518 v = code_get_s1(p + 2,m);
522 i = code_get_u2(p + 1,m);
523 v = code_get_s2(p + 3,m);
528 NEW_OP_LOCALINDEX_I(opcode, i, v);
532 /* wider index for loading, storing and incrementing ******************/
539 /* managing arrays ****************************************************/
542 switch (code_get_s1(p + 1, m)) {
544 bte = builtintable_get_internal(BUILTIN_newarray_boolean);
547 bte = builtintable_get_internal(BUILTIN_newarray_char);
550 bte = builtintable_get_internal(BUILTIN_newarray_float);
553 bte = builtintable_get_internal(BUILTIN_newarray_double);
556 bte = builtintable_get_internal(BUILTIN_newarray_byte);
559 bte = builtintable_get_internal(BUILTIN_newarray_short);
562 bte = builtintable_get_internal(BUILTIN_newarray_int);
565 bte = builtintable_get_internal(BUILTIN_newarray_long);
567 #if defined(ENABLE_VERIFIER)
569 *exceptionptr = new_verifyerror(m,
570 "Invalid array-type to create");
574 NEW_OP_BUILTIN_CHECK_EXCEPTION(bte);
578 i = code_get_u2(p + 1, m);
579 compr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
583 if (!(cr = class_get_classref_multiarray_of(1, compr)))
586 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
589 NEW_OP_LOADCONST_CLASSINFO_OR_CLASSREF(c, cr, INS_FLAG_NOCHECK);
590 bte = builtintable_get_internal(BUILTIN_newarray);
591 NEW_OP_BUILTIN_CHECK_EXCEPTION(bte);
595 case JAVA_MULTIANEWARRAY:
596 m->isleafmethod = false;
597 i = code_get_u2(p + 1, m);
599 s4 v = code_get_u1(p + 3, m);
601 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
605 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
608 /* if unresolved, c == NULL */
610 iptr->s1.argcount = v; /* XXX */
611 NEW_OP_S3_CLASSINFO_OR_CLASSREF(opcode, c, cr, 0 /* flags */);
615 /* control flow instructions ******************************************/
635 i = p + code_get_s2(p + 1,m);
636 CHECK_BYTECODE_INDEX(i);
639 NEW_OP_INSINDEX(opcode, i);
644 i = p + code_get_s4(p + 1,m);
645 CHECK_BYTECODE_INDEX(i);
648 NEW_OP_INSINDEX(opcode, i);
653 i = code_get_u1(p + 1,m);
656 i = code_get_u2(p + 1,m);
662 NEW_OP_LOAD_ONEWORD(opcode, i);
672 /* XXX ARETURN will need a flag in the typechecker */
678 /* XXX ATHROW will need a flag in the typechecker */
683 /* table jumps ********************************************************/
685 case JAVA_LOOKUPSWITCH: /* XXX */
689 #if defined(ENABLE_VERIFIER)
694 nextp = ALIGN((p + 1), 4);
696 CHECK_END_OF_BYTECODE(nextp + 8);
698 tablep = (s4 *) (m->jcode + nextp);
700 NEW_OP_PREPARE(opcode);
701 iptr->dst.lookuptable = (void**) tablep; /* XXX */
706 j = p + code_get_s4(nextp, m);
707 *tablep = j; /* restore for little endian */
710 CHECK_BYTECODE_INDEX(j);
713 /* number of pairs */
715 num = code_get_u4(nextp, m);
720 CHECK_END_OF_BYTECODE(nextp + 8 * num);
722 for (i = 0; i < num; i++) {
725 j = code_get_s4(nextp, m);
726 *tablep = j; /* restore for little endian */
730 #if defined(ENABLE_VERIFIER)
731 /* check if the lookup table is sorted correctly */
733 if (i && (j <= prevvalue)) {
734 *exceptionptr = new_verifyerror(m, "Unsorted lookup switch");
741 j = p + code_get_s4(nextp,m);
742 *tablep = j; /* restore for little endian */
745 CHECK_BYTECODE_INDEX(j);
753 case JAVA_TABLESWITCH: /*XXX*/
759 nextp = ALIGN((p + 1), 4);
761 CHECK_END_OF_BYTECODE(nextp + 12);
763 tablep = (s4 *) (m->jcode + nextp);
765 NEW_OP_PREPARE(opcode);
766 iptr->dst.targettable = (basicblock **) tablep; /* XXX */
771 j = p + code_get_s4(nextp, m);
772 *tablep = j; /* restore for little endian */
775 CHECK_BYTECODE_INDEX(j);
780 j = code_get_s4(nextp, m);
781 *tablep = j; /* restore for little endian */
787 num = code_get_s4(nextp, m);
788 *tablep = num; /* restore for little endian */
792 num -= j; /* difference of upper - lower */
794 #if defined(ENABLE_VERIFIER)
796 *exceptionptr = new_verifyerror(m,
797 "invalid TABLESWITCH: upper bound < lower bound");
801 CHECK_END_OF_BYTECODE(nextp + 4 * (num + 1));
803 for (i = 0; i <= num; i++) {
804 j = p + code_get_s4(nextp,m);
805 *tablep = j; /* restore for little endian */
808 CHECK_BYTECODE_INDEX(j);
816 /* load and store of object fields ************************************/
820 m->isleafmethod = false;
829 unresolved_field *uf;
831 i = code_get_u2(p + 1, m);
832 fr = class_getconstant(m->class, i, CONSTANT_Fieldref);
836 NEW_OP_PREPARE(opcode);
837 iptr->sx.s23.s3.fmiref = fr;
839 /* only with -noverify, otherwise the typechecker does this */
841 #if defined(ENABLE_VERIFIER)
844 result = resolve_field_lazy(/* XXX */(instruction *)iptr, NULL, m);
845 if (result == resolveFailed)
848 if (result != resolveSucceeded) {
849 uf = create_unresolved_field(m->class, m, /* XXX */(instruction *)iptr);
854 /* store the unresolved_field pointer */
856 iptr->sx.s23.s3.uf = uf;
857 iptr->flags.bits = INS_FLAG_UNRESOLVED;
859 #if defined(ENABLE_VERIFIER)
867 /* method invocation **************************************************/
869 case JAVA_INVOKESTATIC:
870 i = code_get_u2(p + 1, m);
871 mr = class_getconstant(m->class, i, CONSTANT_Methodref);
875 md = mr->parseddesc.md;
878 if (!descriptor_params_from_paramtypes(md, ACC_STATIC))
883 case JAVA_INVOKEINTERFACE:
884 i = code_get_u2(p + 1, m);
886 mr = class_getconstant(m->class, i,
887 CONSTANT_InterfaceMethodref);
889 goto invoke_nonstatic_method;
891 case JAVA_INVOKESPECIAL:
892 case JAVA_INVOKEVIRTUAL:
893 i = code_get_u2(p + 1, m);
894 mr = class_getconstant(m->class, i, CONSTANT_Methodref);
896 invoke_nonstatic_method:
900 md = mr->parseddesc.md;
903 if (!descriptor_params_from_paramtypes(md, 0))
907 m->isleafmethod = false;
909 NEW_OP_PREPARE(opcode);
910 iptr->sx.s23.s3.fmiref = mr;
912 /* only with -noverify, otherwise the typechecker does this */
914 #if defined(ENABLE_VERIFIER)
917 result = resolve_method_lazy(/* XXX */(instruction *)iptr, NULL, m);
918 if (result == resolveFailed)
921 if (result != resolveSucceeded) {
922 um = create_unresolved_method(m->class, m, /* XXX */(instruction *)iptr);
927 /* store the unresolved_method pointer */
929 iptr->sx.s23.s3.um = um;
930 iptr->flags.bits = INS_FLAG_UNRESOLVED;
932 #if defined(ENABLE_VERIFIER)
938 /* instructions taking class arguments ********************************/
941 i = code_get_u2(p + 1, m);
942 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
946 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
949 NEW_OP_LOADCONST_CLASSINFO_OR_CLASSREF(c, cr, INS_FLAG_NOCHECK);
950 bte = builtintable_get_internal(BUILTIN_new);
951 NEW_OP_BUILTIN_CHECK_EXCEPTION(bte);
956 i = code_get_u2(p + 1, m);
957 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
961 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
964 if (cr->name->text[0] == '[') {
965 /* array type cast-check */
966 flags = INS_FLAG_ARRAY;
967 m->isleafmethod = false;
970 /* object type cast-check */
973 NEW_OP_S3_CLASSINFO_OR_CLASSREF(opcode, c, cr, flags);
976 case JAVA_INSTANCEOF:
977 i = code_get_u2(p + 1,m);
978 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
982 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
985 if (cr->name->text[0] == '[') {
986 /* array type cast-check */
987 NEW_OP_LOADCONST_CLASSINFO_OR_CLASSREF(c, cr, INS_FLAG_NOCHECK);
988 bte = builtintable_get_internal(BUILTIN_arrayinstanceof);
989 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
993 /* object type cast-check */
994 NEW_OP_S3_CLASSINFO_OR_CLASSREF(opcode, c, cr, 0 /* flags*/);
998 /* synchronization instructions ***************************************/
1000 case JAVA_MONITORENTER:
1001 #if defined(ENABLE_THREADS)
1003 NEW_OP(ICMD_CHECKNULL);
1004 bte = builtintable_get_internal(BUILTIN_monitorenter);
1005 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1010 NEW_OP(ICMD_CHECKNULL);
1015 case JAVA_MONITOREXIT:
1016 #if defined(ENABLE_THREADS)
1018 bte = builtintable_get_internal(BUILTIN_monitorexit);
1019 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1028 /* arithmetic instructions they may become builtin functions **********/
1031 #if !SUPPORT_DIVISION
1032 bte = builtintable_get_internal(BUILTIN_idiv);
1033 NEW_OP_BUILTIN_ARITHMETIC(opcode, bte);
1040 #if !SUPPORT_DIVISION
1041 bte = builtintable_get_internal(BUILTIN_irem);
1042 NEW_OP_BUILTIN_ARITHMETIC(opcode, bte);
1049 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1050 bte = builtintable_get_internal(BUILTIN_ldiv);
1051 NEW_OP_BUILTIN_ARITHMETIC(opcode, bte);
1058 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1059 bte = builtintable_get_internal(BUILTIN_lrem);
1060 NEW_OP_BUILTIN_ARITHMETIC(opcode, bte);
1067 #if defined(__I386__)
1070 bte = builtintable_get_internal(BUILTIN_frem);
1071 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1076 #if defined(__I386__)
1079 bte = builtintable_get_internal(BUILTIN_drem);
1080 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1085 #if defined(__ALPHA__)
1087 bte = builtintable_get_internal(BUILTIN_f2i);
1088 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1098 #if defined(__ALPHA__)
1100 bte = builtintable_get_internal(BUILTIN_f2l);
1101 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1111 #if defined(__ALPHA__)
1113 bte = builtintable_get_internal(BUILTIN_d2i);
1114 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1124 #if defined(__ALPHA__)
1126 bte = builtintable_get_internal(BUILTIN_d2l);
1127 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1136 /* invalid opcodes ****************************************************/
1138 /* check for invalid opcodes if the verifier is enabled */
1139 #if defined(ENABLE_VERIFIER)
1140 case JAVA_BREAKPOINT:
1142 new_verifyerror(m, "Quick instructions shouldn't appear yet.");
1145 case 186: /* unused opcode */
1200 new_verifyerror(m,"Illegal opcode %d at instr %d\n",
1204 #endif /* defined(ENABLE_VERIFIER) */
1206 /* opcodes that don't require translation *****************************/
1209 /* straight-forward translation to ICMD */
1215 #if defined(ENABLE_VERIFIER)
1216 /* If WIDE was used correctly, iswide should have been reset by now. */
1218 *exceptionptr = new_verifyerror(m,
1219 "Illegal instruction: WIDE before incompatible opcode");
1222 #endif /* defined(ENABLE_VERIFIER) */
1226 /*** END OF LOOP **********************************************************/
1228 #if defined(ENABLE_VERIFIER)
1229 if (p != m->jcodelength) {
1230 *exceptionptr = new_verifyerror(m,
1231 "Command-sequence crosses code-boundary");
1236 *exceptionptr = new_verifyerror(m, "Falling off the end of the code");
1239 #endif /* defined(ENABLE_VERIFIER) */
1241 /* adjust block count if target 0 is not first intermediate instruction */
1243 if (!m->basicblockindex[0] || (m->basicblockindex[0] > 1))
1246 /* copy local to method variables */
1248 m->instructioncount = ipc;
1249 m->basicblockcount = b_count;
1250 m->stackcount = s_count + m->basicblockcount * m->maxstack;
1252 /* allocate stack table */
1254 m->stack = DMNEW(stackelement, m->stackcount);
1259 bptr = m->basicblocks = DMNEW(basicblock, b_count + 1); /* one more for end ipc */
1264 /* additional block if target 0 is not first intermediate instruction */
1266 if (!m->basicblockindex[0] || (m->basicblockindex[0] > 1)) {
1267 BASICBLOCK_INIT(bptr,m);
1269 bptr->iinstr = m->instructions;
1270 /* bptr->icount is set when the next block is allocated */
1274 bptr[-1].next = bptr;
1277 /* allocate blocks */
1279 for (p = 0; p < m->jcodelength; p++) {
1280 if (m->basicblockindex[p] & 1) {
1281 /* Check if this block starts at the beginning of an */
1283 #if defined(ENABLE_VERIFIER)
1284 if (!instructionstart[p]) {
1285 *exceptionptr = new_verifyerror(m,
1286 "Branch into middle of instruction");
1291 /* allocate the block */
1293 BASICBLOCK_INIT(bptr,m);
1295 bptr->iinstr = m->instructions + (m->basicblockindex[p] >> 1);
1297 bptr[-1].icount = bptr->iinstr - bptr[-1].iinstr;
1299 /* bptr->icount is set when the next block is allocated */
1301 m->basicblockindex[p] = b_count;
1305 bptr[-1].next = bptr;
1309 /* set instruction count of last real block */
1312 bptr[-1].icount = (m->instructions + m->instructioncount) - bptr[-1].iinstr;
1315 /* allocate additional block at end */
1317 BASICBLOCK_INIT(bptr,m);
1319 bptr->instack = bptr->outstack = NULL;
1320 bptr->indepth = bptr->outdepth = 0;
1321 bptr->iinstr = NULL;
1325 /* set basicblock pointers in exception table */
1327 if (cd->exceptiontablelength > 0) {
1328 cd->exceptiontable[cd->exceptiontablelength - 1].down = NULL;
1331 for (i = 0; i < cd->exceptiontablelength; ++i) {
1332 p = cd->exceptiontable[i].startpc;
1333 cd->exceptiontable[i].start = m->basicblocks + m->basicblockindex[p];
1335 p = cd->exceptiontable[i].endpc;
1336 cd->exceptiontable[i].end = (p == m->jcodelength) ? (m->basicblocks + m->basicblockcount /*+ 1*/) : (m->basicblocks + m->basicblockindex[p]);
1338 p = cd->exceptiontable[i].handlerpc;
1339 cd->exceptiontable[i].handler = m->basicblocks + m->basicblockindex[p];
1342 /* XXX activate this if you want to try inlining */
1344 for (i = 0; i < m->exceptiontablelength; ++i) {
1345 p = m->exceptiontable[i].startpc;
1346 m->exceptiontable[i].start = m->basicblocks + m->basicblockindex[p];
1348 p = m->exceptiontable[i].endpc;
1349 m->exceptiontable[i].end = (p == m->jcodelength) ? (m->basicblocks + m->basicblockcount /*+ 1*/) : (m->basicblocks + m->basicblockindex[p]);
1351 p = m->exceptiontable[i].handlerpc;
1352 m->exceptiontable[i].handler = m->basicblocks + m->basicblockindex[p];
1358 /* everything's ok */
1362 #if defined(ENABLE_VERIFIER)
1364 throw_unexpected_end_of_bytecode:
1365 *exceptionptr = new_verifyerror(m, "Unexpected end of bytecode");
1368 throw_invalid_bytecode_index:
1370 new_verifyerror(m, "Illegal target of branch instruction");
1373 throw_illegal_local_variable_number:
1375 new_verifyerror(m, "Illegal local variable number");
1378 #endif /* ENABLE_VERIFIER */
1382 bool parse(jitdata *jd)
1386 int p; /* java instruction counter */
1387 int nextp; /* start of next java instruction */
1388 int opcode; /* java opcode */
1389 int i; /* temporary for different uses (ctrs)*/
1390 int ipc = 0; /* intermediate instruction counter */
1391 int b_count = 0; /* basic block counter */
1392 int s_count = 0; /* stack element counter */
1393 bool blockend = false; /* true if basic block end has been reached */
1394 bool iswide = false; /* true if last instruction was a wide*/
1395 instruction *iptr; /* current ptr into instruction array */
1397 u1 *instructionstart; /* 1 for pcs which are valid instr. starts */
1399 constant_classref *cr;
1400 constant_classref *compr;
1402 builtintable_entry *bte;
1404 constant_FMIref *mr;
1406 unresolved_method *um;
1407 resolve_result_t result;
1411 u2 linepcchange = 0;
1413 /* get required compiler data */
1418 /* allocate instruction array and block index table */
1420 /* 1 additional for end ipc */
1421 m->basicblockindex = DMNEW(s4, m->jcodelength + 1);
1422 memset(m->basicblockindex, 0, sizeof(s4) * (m->jcodelength + 1));
1424 instructionstart = DMNEW(u1, m->jcodelength + 1);
1425 memset(instructionstart, 0, sizeof(u1) * (m->jcodelength + 1));
1427 /* 1 additional for TRACEBUILTIN and 4 for MONITORENTER/EXIT */
1428 /* additional MONITOREXITS are reached by branches which are 3 bytes */
1430 iptr = m->instructions = DMNEW(instruction, m->jcodelength + 5);
1432 /* Zero the intermediate instructions array so we don't have any
1433 * invalid pointers in it if we cannot finish analyse_stack(). */
1435 memset(iptr, 0, sizeof(instruction) * (m->jcodelength + 5));
1437 /* compute branch targets of exception table */
1440 &(cd->exceptiontable[cd->exceptiontablelength-1]),
1442 m->exceptiontablelength,
1448 s_count = 1 + m->exceptiontablelength; /* initialize stack element counter */
1450 #if defined(ENABLE_THREADS)
1451 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
1452 m->isleafmethod = false;
1456 /* scan all java instructions */
1460 if (m->linenumbercount == 0) {
1464 linepcchange = m->linenumbers[0].start_pc;
1467 for (p = 0; p < m->jcodelength; p = nextp) {
1469 /* mark this position as a valid instruction start */
1470 instructionstart[p] = 1;
1471 if (linepcchange == p) {
1472 if (m->linenumbercount > lineindex) {
1474 currentline = m->linenumbers[lineindex].line_number;
1476 if (lineindex < m->linenumbercount) {
1477 linepcchange = m->linenumbers[lineindex].start_pc;
1478 if (linepcchange == p)
1479 goto next_linenumber;
1484 /* fetch next opcode */
1486 opcode = code_get_u1(p, m);
1488 m->basicblockindex[p] |= (ipc << 1); /*store intermed cnt*/
1490 /* some compilers put a JAVA_NOP after a blockend instruction */
1492 if (blockend && (opcode != JAVA_NOP)) {
1493 /* start new block */
1499 nextp = p + jcommandsize[opcode]; /* compute next instruction start */
1501 CHECK_END_OF_BYTECODE(nextp);
1503 s_count += stackreq[opcode]; /* compute stack element count */
1508 /* pushing constants onto the stack p */
1511 LOADCONST_I(code_get_s1(p+1,m));
1515 LOADCONST_I(code_get_s2(p+1,m));
1519 i = code_get_u1(p + 1, m);
1520 goto pushconstantitem;
1524 i = code_get_u2(p + 1, m);
1528 #if defined(ENABLE_VERIFIER)
1529 if (i >= m->class->cpcount) {
1530 *exceptionptr = new_verifyerror(m,
1531 "Attempt to access constant outside range");
1536 switch (m->class->cptags[i]) {
1537 case CONSTANT_Integer:
1538 LOADCONST_I(((constant_integer *) (m->class->cpinfos[i]))->value);
1541 LOADCONST_L(((constant_long *) (m->class->cpinfos[i]))->value);
1543 case CONSTANT_Float:
1544 LOADCONST_F(((constant_float *) (m->class->cpinfos[i]))->value);
1546 case CONSTANT_Double:
1547 LOADCONST_D(((constant_double *) (m->class->cpinfos[i]))->value);
1549 case CONSTANT_String:
1550 LOADCONST_A(literalstring_new((utf *) (m->class->cpinfos[i])));
1552 case CONSTANT_Class:
1553 cr = (constant_classref *) (m->class->cpinfos[i]);
1555 if (!resolve_classref(m, cr, resolveLazy, true,
1559 /* if not resolved, c == NULL */
1562 iptr->target = (void*) 0x02; /* XXX target used temporarily as flag */
1566 iptr->target = (void*) 0x03; /* XXX target used temporarily as flag */
1571 #if defined(ENABLE_VERIFIER)
1573 *exceptionptr = new_verifyerror(m,
1574 "Invalid constant type to push");
1580 case JAVA_ACONST_NULL:
1584 case JAVA_ICONST_M1:
1591 LOADCONST_I(opcode - JAVA_ICONST_0);
1596 LOADCONST_L(opcode - JAVA_LCONST_0);
1602 LOADCONST_F(opcode - JAVA_FCONST_0);
1607 LOADCONST_D(opcode - JAVA_DCONST_0);
1610 /* loading variables onto the stack */
1616 i = code_get_u1(p + 1,m);
1619 i = code_get_u2(p + 1,m);
1623 OP1LOAD_ONEWORD(opcode, i);
1629 i = code_get_u1(p + 1,m);
1632 i = code_get_u2(p + 1,m);
1636 OP1LOAD_TWOWORD(opcode, i);
1643 OP1LOAD_ONEWORD(ICMD_ILOAD, opcode - JAVA_ILOAD_0);
1650 OP1LOAD_TWOWORD(ICMD_LLOAD, opcode - JAVA_LLOAD_0);
1657 OP1LOAD_ONEWORD(ICMD_FLOAD, opcode - JAVA_FLOAD_0);
1664 OP1LOAD_TWOWORD(ICMD_DLOAD, opcode - JAVA_DLOAD_0);
1671 OP1LOAD_ONEWORD(ICMD_ALOAD, opcode - JAVA_ALOAD_0);
1674 /* storing stack values into local variables */
1680 i = code_get_u1(p + 1,m);
1683 i = code_get_u2(p + 1,m);
1687 OP1STORE_ONEWORD(opcode, i);
1693 i = code_get_u1(p + 1,m);
1696 i = code_get_u2(p + 1,m);
1700 OP1STORE_TWOWORD(opcode, i);
1707 OP1STORE_ONEWORD(ICMD_ISTORE, opcode - JAVA_ISTORE_0);
1714 OP1STORE_TWOWORD(ICMD_LSTORE, opcode - JAVA_LSTORE_0);
1721 OP1STORE_ONEWORD(ICMD_FSTORE, opcode - JAVA_FSTORE_0);
1728 OP1STORE_TWOWORD(ICMD_DSTORE, opcode - JAVA_DSTORE_0);
1735 OP1STORE_ONEWORD(ICMD_ASTORE, opcode - JAVA_ASTORE_0);
1743 i = code_get_u1(p + 1,m);
1744 v = code_get_s1(p + 2,m);
1748 i = code_get_u2(p + 1,m);
1749 v = code_get_s2(p + 3,m);
1758 /* wider index for loading, storing and incrementing */
1765 /* managing arrays ****************************************************/
1768 switch (code_get_s1(p + 1, m)) {
1770 bte = builtintable_get_internal(BUILTIN_newarray_boolean);
1773 bte = builtintable_get_internal(BUILTIN_newarray_char);
1776 bte = builtintable_get_internal(BUILTIN_newarray_float);
1779 bte = builtintable_get_internal(BUILTIN_newarray_double);
1782 bte = builtintable_get_internal(BUILTIN_newarray_byte);
1785 bte = builtintable_get_internal(BUILTIN_newarray_short);
1788 bte = builtintable_get_internal(BUILTIN_newarray_int);
1791 bte = builtintable_get_internal(BUILTIN_newarray_long);
1793 #if defined(ENABLE_VERIFIER)
1795 *exceptionptr = new_verifyerror(m,
1796 "Invalid array-type to create");
1800 BUILTIN(bte, true, NULL, currentline);
1803 case JAVA_ANEWARRAY:
1804 i = code_get_u2(p + 1, m);
1805 compr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
1809 if (!(cr = class_get_classref_multiarray_of(1, compr)))
1812 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
1815 LOADCONST_A_BUILTIN(c, cr);
1816 bte = builtintable_get_internal(BUILTIN_newarray);
1817 BUILTIN(bte, true, NULL, currentline);
1821 case JAVA_MULTIANEWARRAY:
1822 m->isleafmethod = false;
1823 i = code_get_u2(p + 1, m);
1825 s4 v = code_get_u1(p + 3, m);
1827 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
1831 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
1834 /* if unresolved, c == NULL */
1835 OP2AT(opcode, v, c, cr, currentline);
1846 case JAVA_IFNONNULL:
1847 case JAVA_IF_ICMPEQ:
1848 case JAVA_IF_ICMPNE:
1849 case JAVA_IF_ICMPLT:
1850 case JAVA_IF_ICMPGT:
1851 case JAVA_IF_ICMPLE:
1852 case JAVA_IF_ICMPGE:
1853 case JAVA_IF_ACMPEQ:
1854 case JAVA_IF_ACMPNE:
1857 i = p + code_get_s2(p + 1,m);
1858 CHECK_BYTECODE_INDEX(i);
1866 i = p + code_get_s4(p + 1,m);
1867 CHECK_BYTECODE_INDEX(i);
1875 i = code_get_u1(p + 1,m);
1878 i = code_get_u2(p + 1,m);
1884 OP1LOAD_ONEWORD(opcode, i);
1894 /* zero val.a so no patcher is inserted */
1895 /* the type checker may set this later */
1902 /* zero val.a so no patcher is inserted */
1903 /* the type checker may set this later */
1909 /* table jumps ********************************************************/
1911 case JAVA_LOOKUPSWITCH:
1915 #if defined(ENABLE_VERIFIER)
1920 nextp = ALIGN((p + 1), 4);
1922 CHECK_END_OF_BYTECODE(nextp + 8);
1924 tablep = (s4 *) (m->jcode + nextp);
1926 OP2A(opcode, 0, tablep, currentline);
1928 /* default target */
1930 j = p + code_get_s4(nextp, m);
1931 *tablep = j; /* restore for little endian */
1934 CHECK_BYTECODE_INDEX(j);
1937 /* number of pairs */
1939 num = code_get_u4(nextp, m);
1944 CHECK_END_OF_BYTECODE(nextp + 8 * num);
1946 for (i = 0; i < num; i++) {
1949 j = code_get_s4(nextp, m);
1950 *tablep = j; /* restore for little endian */
1954 #if defined(ENABLE_VERIFIER)
1955 /* check if the lookup table is sorted correctly */
1957 if (i && (j <= prevvalue)) {
1958 *exceptionptr = new_verifyerror(m, "Unsorted lookup switch");
1966 j = p + code_get_s4(nextp,m);
1967 *tablep = j; /* restore for little endian */
1970 CHECK_BYTECODE_INDEX(j);
1978 case JAVA_TABLESWITCH:
1984 nextp = ALIGN((p + 1), 4);
1986 CHECK_END_OF_BYTECODE(nextp + 12);
1988 tablep = (s4 *) (m->jcode + nextp);
1990 OP2A(opcode, 0, tablep, currentline);
1992 /* default target */
1994 j = p + code_get_s4(nextp, m);
1995 *tablep = j; /* restore for little endian */
1998 CHECK_BYTECODE_INDEX(j);
2003 j = code_get_s4(nextp, m);
2004 *tablep = j; /* restore for little endian */
2010 num = code_get_s4(nextp, m);
2011 *tablep = num; /* restore for little endian */
2015 num -= j; /* difference of upper - lower */
2017 #if defined(ENABLE_VERIFIER)
2019 *exceptionptr = new_verifyerror(m,
2020 "invalid TABLESWITCH: upper bound < lower bound");
2025 CHECK_END_OF_BYTECODE(nextp + 4 * (num + 1));
2027 for (i = 0; i <= num; i++) {
2028 j = p + code_get_s4(nextp,m);
2029 *tablep = j; /* restore for little endian */
2032 CHECK_BYTECODE_INDEX(j);
2040 /* load and store of object fields ************************************/
2044 m->isleafmethod = false;
2047 case JAVA_GETSTATIC:
2048 case JAVA_PUTSTATIC:
2052 constant_FMIref *fr;
2053 unresolved_field *uf;
2055 i = code_get_u2(p + 1, m);
2056 fr = class_getconstant(m->class, i,
2061 OP2A_NOINC(opcode, fr->parseddesc.fd->type, fr, currentline);
2063 /* only with -noverify, otherwise the typechecker does this */
2065 #if defined(ENABLE_VERIFIER)
2068 result = resolve_field_lazy(iptr,NULL,m);
2069 if (result == resolveFailed)
2072 if (result != resolveSucceeded) {
2073 uf = create_unresolved_field(m->class,
2079 /* store the unresolved_field pointer */
2081 /* XXX this will be changed */
2083 iptr->target = (void*) 0x01; /* XXX target temporarily used as flag */
2086 iptr->target = NULL;
2088 #if defined(ENABLE_VERIFIER)
2091 iptr->target = NULL;
2099 /* method invocation **************************************************/
2101 case JAVA_INVOKESTATIC:
2102 i = code_get_u2(p + 1, m);
2103 mr = class_getconstant(m->class, i,
2104 CONSTANT_Methodref);
2108 md = mr->parseddesc.md;
2111 if (!descriptor_params_from_paramtypes(md, ACC_STATIC))
2116 case JAVA_INVOKEINTERFACE:
2117 i = code_get_u2(p + 1, m);
2119 mr = class_getconstant(m->class, i,
2120 CONSTANT_InterfaceMethodref);
2122 goto invoke_nonstatic_method;
2124 case JAVA_INVOKESPECIAL:
2125 case JAVA_INVOKEVIRTUAL:
2126 i = code_get_u2(p + 1, m);
2127 mr = class_getconstant(m->class, i,
2128 CONSTANT_Methodref);
2130 invoke_nonstatic_method:
2134 md = mr->parseddesc.md;
2137 if (!descriptor_params_from_paramtypes(md, 0))
2141 m->isleafmethod = false;
2143 OP2A_NOINC(opcode, 0, mr, currentline);
2145 /* only with -noverify, otherwise the typechecker does this */
2147 #if defined(ENABLE_VERIFIER)
2150 result = resolve_method_lazy(iptr,NULL,m);
2151 if (result == resolveFailed)
2154 if (result != resolveSucceeded) {
2155 um = create_unresolved_method(m->class,
2161 /* store the unresolved_method pointer */
2163 /* XXX this will be changed */
2165 iptr->target = (void*) 0x01; /* XXX target temporarily used as flag */
2168 /* the method could be resolved */
2169 iptr->target = NULL;
2171 #if defined(ENABLE_VERIFIER)
2174 iptr->target = NULL;
2180 /* miscellaneous object operations ************************************/
2183 i = code_get_u2(p + 1, m);
2184 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
2188 if (!resolve_classref(m, cr, resolveLazy, true, true,
2192 LOADCONST_A_BUILTIN(c, cr);
2193 bte = builtintable_get_internal(BUILTIN_new);
2194 BUILTIN(bte, true, NULL, currentline);
2198 case JAVA_CHECKCAST:
2199 i = code_get_u2(p + 1, m);
2200 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
2204 if (!resolve_classref(m, cr, resolveLazy, true,
2208 if (cr->name->text[0] == '[') {
2209 /* array type cast-check */
2210 OP2AT(opcode, 0, c, cr, currentline);
2211 m->isleafmethod = false;
2215 /* object type cast-check */
2216 OP2AT(opcode, 1, c, cr, currentline);
2220 case JAVA_INSTANCEOF:
2221 i = code_get_u2(p + 1,m);
2222 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
2226 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
2229 if (cr->name->text[0] == '[') {
2230 /* array type cast-check */
2231 LOADCONST_A_BUILTIN(c, cr);
2232 bte = builtintable_get_internal(BUILTIN_arrayinstanceof);
2233 BUILTIN(bte, false, NULL, currentline);
2238 /* object type cast-check */
2239 OP2AT(opcode, 1, c, cr, currentline);
2243 case JAVA_MONITORENTER:
2244 #if defined(ENABLE_THREADS)
2247 bte = builtintable_get_internal(BUILTIN_monitorenter);
2248 BUILTIN(bte, false, NULL, currentline);
2258 case JAVA_MONITOREXIT:
2259 #if defined(ENABLE_THREADS)
2261 bte = builtintable_get_internal(BUILTIN_monitorexit);
2262 BUILTIN(bte, false, NULL, currentline);
2271 /* any other basic operation ******************************************/
2274 #if !SUPPORT_DIVISION
2275 bte = builtintable_get_internal(BUILTIN_idiv);
2276 OP2A(opcode, bte->md->paramcount, bte, currentline);
2277 m->isleafmethod = false;
2284 #if !SUPPORT_DIVISION
2285 bte = builtintable_get_internal(BUILTIN_irem);
2286 OP2A(opcode, bte->md->paramcount, bte, currentline);
2287 m->isleafmethod = false;
2294 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
2295 bte = builtintable_get_internal(BUILTIN_ldiv);
2296 OP2A(opcode, bte->md->paramcount, bte, currentline);
2297 m->isleafmethod = false;
2304 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
2305 bte = builtintable_get_internal(BUILTIN_lrem);
2306 OP2A(opcode, bte->md->paramcount, bte, currentline);
2307 m->isleafmethod = false;
2314 #if defined(__I386__)
2317 bte = builtintable_get_internal(BUILTIN_frem);
2318 BUILTIN(bte, false, NULL, currentline);
2323 #if defined(__I386__)
2326 bte = builtintable_get_internal(BUILTIN_drem);
2327 BUILTIN(bte, false, NULL, currentline);
2332 #if defined(__ALPHA__)
2334 bte = builtintable_get_internal(BUILTIN_f2i);
2335 BUILTIN(bte, false, NULL, currentline);
2345 #if defined(__ALPHA__)
2347 bte = builtintable_get_internal(BUILTIN_f2l);
2348 BUILTIN(bte, false, NULL, currentline);
2358 #if defined(__ALPHA__)
2360 bte = builtintable_get_internal(BUILTIN_d2i);
2361 BUILTIN(bte, false, NULL, currentline);
2371 #if defined(__ALPHA__)
2373 bte = builtintable_get_internal(BUILTIN_d2l);
2374 BUILTIN(bte, false, NULL, currentline);
2383 /* check for invalid opcodes if the verifier is enabled */
2384 #if defined(ENABLE_VERIFIER)
2385 case JAVA_BREAKPOINT:
2387 new_verifyerror(m, "Quick instructions shouldn't appear yet.");
2390 case 186: /* unused opcode */
2445 new_verifyerror(m,"Illegal opcode %d at instr %d\n",
2449 #endif /* defined(ENABLE_VERIFIER) */
2452 /* straight-forward translation to ICMD */
2458 #if defined(ENABLE_VERIFIER)
2459 /* If WIDE was used correctly, iswide should have been reset by now. */
2461 *exceptionptr = new_verifyerror(m,
2462 "Illegal instruction: WIDE before incompatible opcode");
2465 #endif /* defined(ENABLE_VERIFIER) */
2469 #if defined(ENABLE_VERIFIER)
2470 if (p != m->jcodelength) {
2471 *exceptionptr = new_verifyerror(m,
2472 "Command-sequence crosses code-boundary");
2477 *exceptionptr = new_verifyerror(m, "Falling off the end of the code");
2480 #endif /* defined(ENABLE_VERIFIER) */
2482 /* adjust block count if target 0 is not first intermediate instruction */
2484 if (!m->basicblockindex[0] || (m->basicblockindex[0] > 1))
2487 /* copy local to method variables */
2489 m->instructioncount = ipc;
2490 m->basicblockcount = b_count;
2491 m->stackcount = s_count + m->basicblockcount * m->maxstack;
2493 /* allocate stack table */
2495 m->stack = DMNEW(stackelement, m->stackcount);
2500 bptr = m->basicblocks = DMNEW(basicblock, b_count + 1); /* one more for end ipc */
2505 /* additional block if target 0 is not first intermediate instruction */
2507 if (!m->basicblockindex[0] || (m->basicblockindex[0] > 1)) {
2508 BASICBLOCK_INIT(bptr,m);
2510 bptr->iinstr = m->instructions;
2511 /* bptr->icount is set when the next block is allocated */
2515 bptr[-1].next = bptr;
2518 /* allocate blocks */
2520 for (p = 0; p < m->jcodelength; p++) {
2521 if (m->basicblockindex[p] & 1) {
2522 /* Check if this block starts at the beginning of an */
2524 #if defined(ENABLE_VERIFIER)
2525 if (!instructionstart[p]) {
2526 *exceptionptr = new_verifyerror(m,
2527 "Branch into middle of instruction");
2532 /* allocate the block */
2534 BASICBLOCK_INIT(bptr,m);
2536 bptr->iinstr = m->instructions + (m->basicblockindex[p] >> 1);
2538 bptr[-1].icount = bptr->iinstr - bptr[-1].iinstr;
2540 /* bptr->icount is set when the next block is allocated */
2542 m->basicblockindex[p] = b_count;
2546 bptr[-1].next = bptr;
2550 /* set instruction count of last real block */
2553 bptr[-1].icount = (m->instructions + m->instructioncount) - bptr[-1].iinstr;
2556 /* allocate additional block at end */
2558 BASICBLOCK_INIT(bptr,m);
2560 bptr->instack = bptr->outstack = NULL;
2561 bptr->indepth = bptr->outdepth = 0;
2562 bptr->iinstr = NULL;
2566 /* set basicblock pointers in exception table */
2568 if (cd->exceptiontablelength > 0) {
2569 cd->exceptiontable[cd->exceptiontablelength - 1].down = NULL;
2572 for (i = 0; i < cd->exceptiontablelength; ++i) {
2573 p = cd->exceptiontable[i].startpc;
2574 cd->exceptiontable[i].start = m->basicblocks + m->basicblockindex[p];
2576 p = cd->exceptiontable[i].endpc;
2577 cd->exceptiontable[i].end = (p == m->jcodelength) ? (m->basicblocks + m->basicblockcount /*+ 1*/) : (m->basicblocks + m->basicblockindex[p]);
2579 p = cd->exceptiontable[i].handlerpc;
2580 cd->exceptiontable[i].handler = m->basicblocks + m->basicblockindex[p];
2583 /* XXX activate this if you want to try inlining */
2585 for (i = 0; i < m->exceptiontablelength; ++i) {
2586 p = m->exceptiontable[i].startpc;
2587 m->exceptiontable[i].start = m->basicblocks + m->basicblockindex[p];
2589 p = m->exceptiontable[i].endpc;
2590 m->exceptiontable[i].end = (p == m->jcodelength) ? (m->basicblocks + m->basicblockcount /*+ 1*/) : (m->basicblocks + m->basicblockindex[p]);
2592 p = m->exceptiontable[i].handlerpc;
2593 m->exceptiontable[i].handler = m->basicblocks + m->basicblockindex[p];
2599 /* everything's ok */
2603 #if defined(ENABLE_VERIFIER)
2605 throw_unexpected_end_of_bytecode:
2606 *exceptionptr = new_verifyerror(m, "Unexpected end of bytecode");
2609 throw_invalid_bytecode_index:
2611 new_verifyerror(m, "Illegal target of branch instruction");
2614 throw_illegal_local_variable_number:
2616 new_verifyerror(m, "Illegal local variable number");
2619 #endif /* ENABLE_VERIFIER */
2624 * These are local overrides for various environment variables in Emacs.
2625 * Please do not remove this and leave it at the end of the file, where
2626 * Emacs will automagically detect them.
2627 * ---------------------------------------------------------------------
2630 * indent-tabs-mode: t
2634 * vim:noexpandtab:sw=4:ts=4: