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 4988 2006-05-29 21:48:50Z 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 instruction *iptr; /* current ptr into instruction array */
165 u1 *instructionstart; /* 1 for pcs which are valid instr. starts */
167 constant_classref *cr;
168 constant_classref *compr;
170 builtintable_entry *bte;
174 unresolved_method *um;
175 resolve_result_t result;
181 /* get required compiler data */
186 /* allocate instruction array and block index table */
188 /* 1 additional for end ipc */
189 m->basicblockindex = DMNEW(s4, m->jcodelength + 1);
190 memset(m->basicblockindex, 0, sizeof(s4) * (m->jcodelength + 1));
192 instructionstart = DMNEW(u1, m->jcodelength + 1);
193 memset(instructionstart, 0, sizeof(u1) * (m->jcodelength + 1));
195 /* 1 additional for TRACEBUILTIN and 4 for MONITORENTER/EXIT */
196 /* additional MONITOREXITS are reached by branches which are 3 bytes */
198 iptr = m->instructions = DMNEW(instruction, m->jcodelength + 5);
200 /* Zero the intermediate instructions array so we don't have any
201 * invalid pointers in it if we cannot finish analyse_stack(). */
203 memset(iptr, 0, sizeof(instruction) * (m->jcodelength + 5));
205 /* compute branch targets of exception table */
208 &(cd->exceptiontable[cd->exceptiontablelength-1]),
210 m->exceptiontablelength,
216 s_count = 1 + m->exceptiontablelength; /* initialize stack element counter */
218 #if defined(ENABLE_THREADS)
219 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
220 m->isleafmethod = false;
224 /* scan all java instructions */
228 if (m->linenumbercount == 0) {
232 linepcchange = m->linenumbers[0].start_pc;
235 for (p = 0; p < m->jcodelength; p = nextp) {
237 /* mark this position as a valid instruction start */
238 instructionstart[p] = 1;
239 if (linepcchange == p) {
240 if (m->linenumbercount > lineindex) {
242 currentline = m->linenumbers[lineindex].line_number;
244 if (lineindex < m->linenumbercount) {
245 linepcchange = m->linenumbers[lineindex].start_pc;
246 if (linepcchange == p)
247 goto next_linenumber;
252 /* fetch next opcode */
254 opcode = code_get_u1(p, m);
256 m->basicblockindex[p] |= (ipc << 1); /*store intermed cnt*/
258 /* some compilers put a JAVA_NOP after a blockend instruction */
260 if (blockend && (opcode != JAVA_NOP)) {
261 /* start new block */
267 nextp = p + jcommandsize[opcode]; /* compute next instruction start */
269 CHECK_END_OF_BYTECODE(nextp);
271 s_count += stackreq[opcode]; /* compute stack element count */
276 /* pushing constants onto the stack p */
279 LOADCONST_I(code_get_s1(p+1,m));
283 LOADCONST_I(code_get_s2(p+1,m));
287 i = code_get_u1(p + 1, m);
288 goto pushconstantitem;
292 i = code_get_u2(p + 1, m);
296 #if defined(ENABLE_VERIFIER)
297 if (i >= m->class->cpcount) {
298 *exceptionptr = new_verifyerror(m,
299 "Attempt to access constant outside range");
304 switch (m->class->cptags[i]) {
305 case CONSTANT_Integer:
306 LOADCONST_I(((constant_integer *) (m->class->cpinfos[i]))->value);
309 LOADCONST_L(((constant_long *) (m->class->cpinfos[i]))->value);
312 LOADCONST_F(((constant_float *) (m->class->cpinfos[i]))->value);
314 case CONSTANT_Double:
315 LOADCONST_D(((constant_double *) (m->class->cpinfos[i]))->value);
317 case CONSTANT_String:
318 LOADCONST_A(literalstring_new((utf *) (m->class->cpinfos[i])));
321 cr = (constant_classref *) (m->class->cpinfos[i]);
323 if (!resolve_classref(m, cr, resolveLazy, true,
327 /* if not resolved, c == NULL */
330 iptr->target = (void*) 0x02; /* XXX target used temporarily as flag */
334 iptr->target = (void*) 0x03; /* XXX target used temporarily as flag */
339 #if defined(ENABLE_VERIFIER)
341 *exceptionptr = new_verifyerror(m,
342 "Invalid constant type to push");
348 case JAVA_ACONST_NULL:
359 LOADCONST_I(opcode - JAVA_ICONST_0);
364 LOADCONST_L(opcode - JAVA_LCONST_0);
370 LOADCONST_F(opcode - JAVA_FCONST_0);
375 LOADCONST_D(opcode - JAVA_DCONST_0);
378 /* loading variables onto the stack */
384 i = code_get_u1(p + 1,m);
387 i = code_get_u2(p + 1,m);
391 OP1LOAD_ONEWORD(opcode, i);
397 i = code_get_u1(p + 1,m);
400 i = code_get_u2(p + 1,m);
404 OP1LOAD_TWOWORD(opcode, i);
411 OP1LOAD_ONEWORD(ICMD_ILOAD, opcode - JAVA_ILOAD_0);
418 OP1LOAD_TWOWORD(ICMD_LLOAD, opcode - JAVA_LLOAD_0);
425 OP1LOAD_ONEWORD(ICMD_FLOAD, opcode - JAVA_FLOAD_0);
432 OP1LOAD_TWOWORD(ICMD_DLOAD, opcode - JAVA_DLOAD_0);
439 OP1LOAD_ONEWORD(ICMD_ALOAD, opcode - JAVA_ALOAD_0);
442 /* storing stack values into local variables */
448 i = code_get_u1(p + 1,m);
451 i = code_get_u2(p + 1,m);
455 OP1STORE_ONEWORD(opcode, i);
461 i = code_get_u1(p + 1,m);
464 i = code_get_u2(p + 1,m);
468 OP1STORE_TWOWORD(opcode, i);
475 OP1STORE_ONEWORD(ICMD_ISTORE, opcode - JAVA_ISTORE_0);
482 OP1STORE_TWOWORD(ICMD_LSTORE, opcode - JAVA_LSTORE_0);
489 OP1STORE_ONEWORD(ICMD_FSTORE, opcode - JAVA_FSTORE_0);
496 OP1STORE_TWOWORD(ICMD_DSTORE, opcode - JAVA_DSTORE_0);
503 OP1STORE_ONEWORD(ICMD_ASTORE, opcode - JAVA_ASTORE_0);
511 i = code_get_u1(p + 1,m);
512 v = code_get_s1(p + 2,m);
516 i = code_get_u2(p + 1,m);
517 v = code_get_s2(p + 3,m);
526 /* wider index for loading, storing and incrementing */
533 /* managing arrays ****************************************************/
536 switch (code_get_s1(p + 1, m)) {
538 bte = builtintable_get_internal(BUILTIN_newarray_boolean);
541 bte = builtintable_get_internal(BUILTIN_newarray_char);
544 bte = builtintable_get_internal(BUILTIN_newarray_float);
547 bte = builtintable_get_internal(BUILTIN_newarray_double);
550 bte = builtintable_get_internal(BUILTIN_newarray_byte);
553 bte = builtintable_get_internal(BUILTIN_newarray_short);
556 bte = builtintable_get_internal(BUILTIN_newarray_int);
559 bte = builtintable_get_internal(BUILTIN_newarray_long);
561 #if defined(ENABLE_VERIFIER)
563 *exceptionptr = new_verifyerror(m,
564 "Invalid array-type to create");
568 BUILTIN(bte, true, NULL, currentline);
572 i = code_get_u2(p + 1, m);
573 compr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
577 if (!(cr = class_get_classref_multiarray_of(1, compr)))
580 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
583 LOADCONST_A_BUILTIN(c, cr);
584 bte = builtintable_get_internal(BUILTIN_newarray);
585 BUILTIN(bte, true, NULL, currentline);
589 case JAVA_MULTIANEWARRAY:
590 m->isleafmethod = false;
591 i = code_get_u2(p + 1, m);
593 s4 v = code_get_u1(p + 3, m);
595 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
599 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
602 /* if unresolved, c == NULL */
603 OP2AT(opcode, v, c, cr, currentline);
625 i = p + code_get_s2(p + 1,m);
626 CHECK_BYTECODE_INDEX(i);
634 i = p + code_get_s4(p + 1,m);
635 CHECK_BYTECODE_INDEX(i);
643 i = code_get_u1(p + 1,m);
646 i = code_get_u2(p + 1,m);
652 OP1LOAD_ONEWORD(opcode, i);
662 /* zero val.a so no patcher is inserted */
663 /* the type checker may set this later */
670 /* zero val.a so no patcher is inserted */
671 /* the type checker may set this later */
677 /* table jumps ********************************************************/
679 case JAVA_LOOKUPSWITCH:
683 #if defined(ENABLE_VERIFIER)
688 nextp = ALIGN((p + 1), 4);
690 CHECK_END_OF_BYTECODE(nextp + 8);
692 tablep = (s4 *) (m->jcode + nextp);
694 OP2A(opcode, 0, tablep, currentline);
698 j = p + code_get_s4(nextp, m);
699 *tablep = j; /* restore for little endian */
702 CHECK_BYTECODE_INDEX(j);
705 /* number of pairs */
707 num = code_get_u4(nextp, m);
712 CHECK_END_OF_BYTECODE(nextp + 8 * num);
714 for (i = 0; i < num; i++) {
717 j = code_get_s4(nextp, m);
718 *tablep = j; /* restore for little endian */
722 #if defined(ENABLE_VERIFIER)
723 /* check if the lookup table is sorted correctly */
725 if (i && (j <= prevvalue)) {
726 *exceptionptr = new_verifyerror(m, "Unsorted lookup switch");
734 j = p + code_get_s4(nextp,m);
735 *tablep = j; /* restore for little endian */
738 CHECK_BYTECODE_INDEX(j);
746 case JAVA_TABLESWITCH:
752 nextp = ALIGN((p + 1), 4);
754 CHECK_END_OF_BYTECODE(nextp + 12);
756 tablep = (s4 *) (m->jcode + nextp);
758 OP2A(opcode, 0, tablep, currentline);
762 j = p + code_get_s4(nextp, m);
763 *tablep = j; /* restore for little endian */
766 CHECK_BYTECODE_INDEX(j);
771 j = code_get_s4(nextp, m);
772 *tablep = j; /* restore for little endian */
778 num = code_get_s4(nextp, m);
779 *tablep = num; /* restore for little endian */
783 num -= j; /* difference of upper - lower */
785 #if defined(ENABLE_VERIFIER)
787 *exceptionptr = new_verifyerror(m,
788 "invalid TABLESWITCH: upper bound < lower bound");
793 CHECK_END_OF_BYTECODE(nextp + 4 * (num + 1));
795 for (i = 0; i <= num; i++) {
796 j = p + code_get_s4(nextp,m);
797 *tablep = j; /* restore for little endian */
800 CHECK_BYTECODE_INDEX(j);
808 /* load and store of object fields ************************************/
812 m->isleafmethod = false;
821 unresolved_field *uf;
823 i = code_get_u2(p + 1, m);
824 fr = class_getconstant(m->class, i,
829 OP2A_NOINC(opcode, fr->parseddesc.fd->type, fr, currentline);
831 /* only with -noverify, otherwise the typechecker does this */
833 #if defined(ENABLE_VERIFIER)
836 result = resolve_field_lazy(iptr,NULL,m);
837 if (result == resolveFailed)
840 if (result != resolveSucceeded) {
841 uf = create_unresolved_field(m->class,
847 /* store the unresolved_field pointer */
849 /* XXX this will be changed */
851 iptr->target = (void*) 0x01; /* XXX target temporarily used as flag */
856 #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,
876 md = mr->parseddesc.md;
879 if (!descriptor_params_from_paramtypes(md, ACC_STATIC))
884 case JAVA_INVOKEINTERFACE:
885 i = code_get_u2(p + 1, m);
887 mr = class_getconstant(m->class, i,
888 CONSTANT_InterfaceMethodref);
890 goto invoke_nonstatic_method;
892 case JAVA_INVOKESPECIAL:
893 case JAVA_INVOKEVIRTUAL:
894 i = code_get_u2(p + 1, m);
895 mr = class_getconstant(m->class, i,
898 invoke_nonstatic_method:
902 md = mr->parseddesc.md;
905 if (!descriptor_params_from_paramtypes(md, 0))
909 m->isleafmethod = false;
911 OP2A_NOINC(opcode, 0, mr, currentline);
913 /* only with -noverify, otherwise the typechecker does this */
915 #if defined(ENABLE_VERIFIER)
918 result = resolve_method_lazy(iptr,NULL,m);
919 if (result == resolveFailed)
922 if (result != resolveSucceeded) {
923 um = create_unresolved_method(m->class,
929 /* store the unresolved_method pointer */
931 /* XXX this will be changed */
933 iptr->target = (void*) 0x01; /* XXX target temporarily used as flag */
936 /* the method could be resolved */
939 #if defined(ENABLE_VERIFIER)
948 /* miscellaneous object operations ************************************/
951 i = code_get_u2(p + 1, m);
952 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
956 if (!resolve_classref(m, cr, resolveLazy, true, true,
960 LOADCONST_A_BUILTIN(c, cr);
961 bte = builtintable_get_internal(BUILTIN_new);
962 BUILTIN(bte, true, NULL, currentline);
967 i = code_get_u2(p + 1, m);
968 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
972 if (!resolve_classref(m, cr, resolveLazy, true,
976 if (cr->name->text[0] == '[') {
977 /* array type cast-check */
978 OP2AT(opcode, 0, c, cr, currentline);
979 m->isleafmethod = false;
983 /* object type cast-check */
984 OP2AT(opcode, 1, c, cr, currentline);
988 case JAVA_INSTANCEOF:
989 i = code_get_u2(p + 1,m);
990 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
994 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
997 if (cr->name->text[0] == '[') {
998 /* array type cast-check */
999 LOADCONST_A_BUILTIN(c, cr);
1000 bte = builtintable_get_internal(BUILTIN_arrayinstanceof);
1001 BUILTIN(bte, false, NULL, currentline);
1006 /* object type cast-check */
1007 OP2AT(opcode, 1, c, cr, currentline);
1011 case JAVA_MONITORENTER:
1012 #if defined(ENABLE_THREADS)
1015 bte = builtintable_get_internal(BUILTIN_monitorenter);
1016 BUILTIN(bte, false, NULL, currentline);
1026 case JAVA_MONITOREXIT:
1027 #if defined(ENABLE_THREADS)
1029 bte = builtintable_get_internal(BUILTIN_monitorexit);
1030 BUILTIN(bte, false, NULL, currentline);
1039 /* any other basic operation ******************************************/
1042 #if !SUPPORT_DIVISION
1043 bte = builtintable_get_internal(BUILTIN_idiv);
1044 OP2A(opcode, bte->md->paramcount, bte, currentline);
1045 m->isleafmethod = false;
1052 #if !SUPPORT_DIVISION
1053 bte = builtintable_get_internal(BUILTIN_irem);
1054 OP2A(opcode, bte->md->paramcount, bte, currentline);
1055 m->isleafmethod = false;
1062 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1063 bte = builtintable_get_internal(BUILTIN_ldiv);
1064 OP2A(opcode, bte->md->paramcount, bte, currentline);
1065 m->isleafmethod = false;
1072 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1073 bte = builtintable_get_internal(BUILTIN_lrem);
1074 OP2A(opcode, bte->md->paramcount, bte, currentline);
1075 m->isleafmethod = false;
1082 #if defined(__I386__)
1085 bte = builtintable_get_internal(BUILTIN_frem);
1086 BUILTIN(bte, false, NULL, currentline);
1091 #if defined(__I386__)
1094 bte = builtintable_get_internal(BUILTIN_drem);
1095 BUILTIN(bte, false, NULL, currentline);
1100 #if defined(__ALPHA__)
1102 bte = builtintable_get_internal(BUILTIN_f2i);
1103 BUILTIN(bte, false, NULL, currentline);
1113 #if defined(__ALPHA__)
1115 bte = builtintable_get_internal(BUILTIN_f2l);
1116 BUILTIN(bte, false, NULL, currentline);
1126 #if defined(__ALPHA__)
1128 bte = builtintable_get_internal(BUILTIN_d2i);
1129 BUILTIN(bte, false, NULL, currentline);
1139 #if defined(__ALPHA__)
1141 bte = builtintable_get_internal(BUILTIN_d2l);
1142 BUILTIN(bte, false, NULL, currentline);
1151 /* check for invalid opcodes if the verifier is enabled */
1152 #if defined(ENABLE_VERIFIER)
1153 case JAVA_BREAKPOINT:
1155 new_verifyerror(m, "Quick instructions shouldn't appear yet.");
1158 case 186: /* unused opcode */
1213 new_verifyerror(m,"Illegal opcode %d at instr %d\n",
1217 #endif /* defined(ENABLE_VERIFIER) */
1220 /* straight-forward translation to ICMD */
1226 #if defined(ENABLE_VERIFIER)
1227 /* If WIDE was used correctly, iswide should have been reset by now. */
1229 *exceptionptr = new_verifyerror(m,
1230 "Illegal instruction: WIDE before incompatible opcode");
1233 #endif /* defined(ENABLE_VERIFIER) */
1237 #if defined(ENABLE_VERIFIER)
1238 if (p != m->jcodelength) {
1239 *exceptionptr = new_verifyerror(m,
1240 "Command-sequence crosses code-boundary");
1245 *exceptionptr = new_verifyerror(m, "Falling off the end of the code");
1248 #endif /* defined(ENABLE_VERIFIER) */
1250 /* adjust block count if target 0 is not first intermediate instruction */
1252 if (!m->basicblockindex[0] || (m->basicblockindex[0] > 1))
1255 /* copy local to method variables */
1257 m->instructioncount = ipc;
1258 m->basicblockcount = b_count;
1259 m->stackcount = s_count + m->basicblockcount * m->maxstack;
1261 /* allocate stack table */
1263 m->stack = DMNEW(stackelement, m->stackcount);
1268 bptr = m->basicblocks = DMNEW(basicblock, b_count + 1); /* one more for end ipc */
1273 /* additional block if target 0 is not first intermediate instruction */
1275 if (!m->basicblockindex[0] || (m->basicblockindex[0] > 1)) {
1276 BASICBLOCK_INIT(bptr,m);
1278 bptr->iinstr = m->instructions;
1279 /* bptr->icount is set when the next block is allocated */
1283 bptr[-1].next = bptr;
1286 /* allocate blocks */
1288 for (p = 0; p < m->jcodelength; p++) {
1289 if (m->basicblockindex[p] & 1) {
1290 /* Check if this block starts at the beginning of an */
1292 #if defined(ENABLE_VERIFIER)
1293 if (!instructionstart[p]) {
1294 *exceptionptr = new_verifyerror(m,
1295 "Branch into middle of instruction");
1300 /* allocate the block */
1302 BASICBLOCK_INIT(bptr,m);
1304 bptr->iinstr = m->instructions + (m->basicblockindex[p] >> 1);
1306 bptr[-1].icount = bptr->iinstr - bptr[-1].iinstr;
1308 /* bptr->icount is set when the next block is allocated */
1310 m->basicblockindex[p] = b_count;
1314 bptr[-1].next = bptr;
1318 /* set instruction count of last real block */
1321 bptr[-1].icount = (m->instructions + m->instructioncount) - bptr[-1].iinstr;
1324 /* allocate additional block at end */
1326 BASICBLOCK_INIT(bptr,m);
1328 bptr->instack = bptr->outstack = NULL;
1329 bptr->indepth = bptr->outdepth = 0;
1330 bptr->iinstr = NULL;
1334 /* set basicblock pointers in exception table */
1336 if (cd->exceptiontablelength > 0) {
1337 cd->exceptiontable[cd->exceptiontablelength - 1].down = NULL;
1340 for (i = 0; i < cd->exceptiontablelength; ++i) {
1341 p = cd->exceptiontable[i].startpc;
1342 cd->exceptiontable[i].start = m->basicblocks + m->basicblockindex[p];
1344 p = cd->exceptiontable[i].endpc;
1345 cd->exceptiontable[i].end = (p == m->jcodelength) ? (m->basicblocks + m->basicblockcount /*+ 1*/) : (m->basicblocks + m->basicblockindex[p]);
1347 p = cd->exceptiontable[i].handlerpc;
1348 cd->exceptiontable[i].handler = m->basicblocks + m->basicblockindex[p];
1351 /* XXX activate this if you want to try inlining */
1353 for (i = 0; i < m->exceptiontablelength; ++i) {
1354 p = m->exceptiontable[i].startpc;
1355 m->exceptiontable[i].start = m->basicblocks + m->basicblockindex[p];
1357 p = m->exceptiontable[i].endpc;
1358 m->exceptiontable[i].end = (p == m->jcodelength) ? (m->basicblocks + m->basicblockcount /*+ 1*/) : (m->basicblocks + m->basicblockindex[p]);
1360 p = m->exceptiontable[i].handlerpc;
1361 m->exceptiontable[i].handler = m->basicblocks + m->basicblockindex[p];
1367 /* everything's ok */
1371 #if defined(ENABLE_VERIFIER)
1373 throw_unexpected_end_of_bytecode:
1374 *exceptionptr = new_verifyerror(m, "Unexpected end of bytecode");
1377 throw_invalid_bytecode_index:
1379 new_verifyerror(m, "Illegal target of branch instruction");
1382 throw_illegal_local_variable_number:
1384 new_verifyerror(m, "Illegal local variable number");
1387 #endif /* ENABLE_VERIFIER */
1391 bool parse(jitdata *jd)
1395 int p; /* java instruction counter */
1396 int nextp; /* start of next java instruction */
1397 int opcode; /* java opcode */
1398 int i; /* temporary for different uses (ctrs)*/
1399 int ipc = 0; /* intermediate instruction counter */
1400 int b_count = 0; /* basic block counter */
1401 int s_count = 0; /* stack element counter */
1402 bool blockend = false; /* true if basic block end has been reached */
1403 bool iswide = false; /* true if last instruction was a wide*/
1404 instruction *iptr; /* current ptr into instruction array */
1406 u1 *instructionstart; /* 1 for pcs which are valid instr. starts */
1408 constant_classref *cr;
1409 constant_classref *compr;
1411 builtintable_entry *bte;
1413 constant_FMIref *mr;
1415 unresolved_method *um;
1416 resolve_result_t result;
1420 u2 linepcchange = 0;
1422 /* get required compiler data */
1427 /* allocate instruction array and block index table */
1429 /* 1 additional for end ipc */
1430 m->basicblockindex = DMNEW(s4, m->jcodelength + 1);
1431 memset(m->basicblockindex, 0, sizeof(s4) * (m->jcodelength + 1));
1433 instructionstart = DMNEW(u1, m->jcodelength + 1);
1434 memset(instructionstart, 0, sizeof(u1) * (m->jcodelength + 1));
1436 /* 1 additional for TRACEBUILTIN and 4 for MONITORENTER/EXIT */
1437 /* additional MONITOREXITS are reached by branches which are 3 bytes */
1439 iptr = m->instructions = DMNEW(instruction, m->jcodelength + 5);
1441 /* Zero the intermediate instructions array so we don't have any
1442 * invalid pointers in it if we cannot finish analyse_stack(). */
1444 memset(iptr, 0, sizeof(instruction) * (m->jcodelength + 5));
1446 /* compute branch targets of exception table */
1449 &(cd->exceptiontable[cd->exceptiontablelength-1]),
1451 m->exceptiontablelength,
1457 s_count = 1 + m->exceptiontablelength; /* initialize stack element counter */
1459 #if defined(ENABLE_THREADS)
1460 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
1461 m->isleafmethod = false;
1465 /* scan all java instructions */
1469 if (m->linenumbercount == 0) {
1473 linepcchange = m->linenumbers[0].start_pc;
1476 for (p = 0; p < m->jcodelength; p = nextp) {
1478 /* mark this position as a valid instruction start */
1479 instructionstart[p] = 1;
1480 if (linepcchange == p) {
1481 if (m->linenumbercount > lineindex) {
1483 currentline = m->linenumbers[lineindex].line_number;
1485 if (lineindex < m->linenumbercount) {
1486 linepcchange = m->linenumbers[lineindex].start_pc;
1487 if (linepcchange == p)
1488 goto next_linenumber;
1493 /* fetch next opcode */
1495 opcode = code_get_u1(p, m);
1497 m->basicblockindex[p] |= (ipc << 1); /*store intermed cnt*/
1499 /* some compilers put a JAVA_NOP after a blockend instruction */
1501 if (blockend && (opcode != JAVA_NOP)) {
1502 /* start new block */
1508 nextp = p + jcommandsize[opcode]; /* compute next instruction start */
1510 CHECK_END_OF_BYTECODE(nextp);
1512 s_count += stackreq[opcode]; /* compute stack element count */
1517 /* pushing constants onto the stack p */
1520 LOADCONST_I(code_get_s1(p+1,m));
1524 LOADCONST_I(code_get_s2(p+1,m));
1528 i = code_get_u1(p + 1, m);
1529 goto pushconstantitem;
1533 i = code_get_u2(p + 1, m);
1537 #if defined(ENABLE_VERIFIER)
1538 if (i >= m->class->cpcount) {
1539 *exceptionptr = new_verifyerror(m,
1540 "Attempt to access constant outside range");
1545 switch (m->class->cptags[i]) {
1546 case CONSTANT_Integer:
1547 LOADCONST_I(((constant_integer *) (m->class->cpinfos[i]))->value);
1550 LOADCONST_L(((constant_long *) (m->class->cpinfos[i]))->value);
1552 case CONSTANT_Float:
1553 LOADCONST_F(((constant_float *) (m->class->cpinfos[i]))->value);
1555 case CONSTANT_Double:
1556 LOADCONST_D(((constant_double *) (m->class->cpinfos[i]))->value);
1558 case CONSTANT_String:
1559 LOADCONST_A(literalstring_new((utf *) (m->class->cpinfos[i])));
1561 case CONSTANT_Class:
1562 cr = (constant_classref *) (m->class->cpinfos[i]);
1564 if (!resolve_classref(m, cr, resolveLazy, true,
1568 /* if not resolved, c == NULL */
1571 iptr->target = (void*) 0x02; /* XXX target used temporarily as flag */
1575 iptr->target = (void*) 0x03; /* XXX target used temporarily as flag */
1580 #if defined(ENABLE_VERIFIER)
1582 *exceptionptr = new_verifyerror(m,
1583 "Invalid constant type to push");
1589 case JAVA_ACONST_NULL:
1593 case JAVA_ICONST_M1:
1600 LOADCONST_I(opcode - JAVA_ICONST_0);
1605 LOADCONST_L(opcode - JAVA_LCONST_0);
1611 LOADCONST_F(opcode - JAVA_FCONST_0);
1616 LOADCONST_D(opcode - JAVA_DCONST_0);
1619 /* loading variables onto the stack */
1625 i = code_get_u1(p + 1,m);
1628 i = code_get_u2(p + 1,m);
1632 OP1LOAD_ONEWORD(opcode, i);
1638 i = code_get_u1(p + 1,m);
1641 i = code_get_u2(p + 1,m);
1645 OP1LOAD_TWOWORD(opcode, i);
1652 OP1LOAD_ONEWORD(ICMD_ILOAD, opcode - JAVA_ILOAD_0);
1659 OP1LOAD_TWOWORD(ICMD_LLOAD, opcode - JAVA_LLOAD_0);
1666 OP1LOAD_ONEWORD(ICMD_FLOAD, opcode - JAVA_FLOAD_0);
1673 OP1LOAD_TWOWORD(ICMD_DLOAD, opcode - JAVA_DLOAD_0);
1680 OP1LOAD_ONEWORD(ICMD_ALOAD, opcode - JAVA_ALOAD_0);
1683 /* storing stack values into local variables */
1689 i = code_get_u1(p + 1,m);
1692 i = code_get_u2(p + 1,m);
1696 OP1STORE_ONEWORD(opcode, i);
1702 i = code_get_u1(p + 1,m);
1705 i = code_get_u2(p + 1,m);
1709 OP1STORE_TWOWORD(opcode, i);
1716 OP1STORE_ONEWORD(ICMD_ISTORE, opcode - JAVA_ISTORE_0);
1723 OP1STORE_TWOWORD(ICMD_LSTORE, opcode - JAVA_LSTORE_0);
1730 OP1STORE_ONEWORD(ICMD_FSTORE, opcode - JAVA_FSTORE_0);
1737 OP1STORE_TWOWORD(ICMD_DSTORE, opcode - JAVA_DSTORE_0);
1744 OP1STORE_ONEWORD(ICMD_ASTORE, opcode - JAVA_ASTORE_0);
1752 i = code_get_u1(p + 1,m);
1753 v = code_get_s1(p + 2,m);
1757 i = code_get_u2(p + 1,m);
1758 v = code_get_s2(p + 3,m);
1767 /* wider index for loading, storing and incrementing */
1774 /* managing arrays ****************************************************/
1777 switch (code_get_s1(p + 1, m)) {
1779 bte = builtintable_get_internal(BUILTIN_newarray_boolean);
1782 bte = builtintable_get_internal(BUILTIN_newarray_char);
1785 bte = builtintable_get_internal(BUILTIN_newarray_float);
1788 bte = builtintable_get_internal(BUILTIN_newarray_double);
1791 bte = builtintable_get_internal(BUILTIN_newarray_byte);
1794 bte = builtintable_get_internal(BUILTIN_newarray_short);
1797 bte = builtintable_get_internal(BUILTIN_newarray_int);
1800 bte = builtintable_get_internal(BUILTIN_newarray_long);
1802 #if defined(ENABLE_VERIFIER)
1804 *exceptionptr = new_verifyerror(m,
1805 "Invalid array-type to create");
1809 BUILTIN(bte, true, NULL, currentline);
1812 case JAVA_ANEWARRAY:
1813 i = code_get_u2(p + 1, m);
1814 compr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
1818 if (!(cr = class_get_classref_multiarray_of(1, compr)))
1821 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
1824 LOADCONST_A_BUILTIN(c, cr);
1825 bte = builtintable_get_internal(BUILTIN_newarray);
1826 BUILTIN(bte, true, NULL, currentline);
1830 case JAVA_MULTIANEWARRAY:
1831 m->isleafmethod = false;
1832 i = code_get_u2(p + 1, m);
1834 s4 v = code_get_u1(p + 3, m);
1836 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
1840 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
1843 /* if unresolved, c == NULL */
1844 OP2AT(opcode, v, c, cr, currentline);
1855 case JAVA_IFNONNULL:
1856 case JAVA_IF_ICMPEQ:
1857 case JAVA_IF_ICMPNE:
1858 case JAVA_IF_ICMPLT:
1859 case JAVA_IF_ICMPGT:
1860 case JAVA_IF_ICMPLE:
1861 case JAVA_IF_ICMPGE:
1862 case JAVA_IF_ACMPEQ:
1863 case JAVA_IF_ACMPNE:
1866 i = p + code_get_s2(p + 1,m);
1867 CHECK_BYTECODE_INDEX(i);
1875 i = p + code_get_s4(p + 1,m);
1876 CHECK_BYTECODE_INDEX(i);
1884 i = code_get_u1(p + 1,m);
1887 i = code_get_u2(p + 1,m);
1893 OP1LOAD_ONEWORD(opcode, i);
1903 /* zero val.a so no patcher is inserted */
1904 /* the type checker may set this later */
1911 /* zero val.a so no patcher is inserted */
1912 /* the type checker may set this later */
1918 /* table jumps ********************************************************/
1920 case JAVA_LOOKUPSWITCH:
1924 #if defined(ENABLE_VERIFIER)
1929 nextp = ALIGN((p + 1), 4);
1931 CHECK_END_OF_BYTECODE(nextp + 8);
1933 tablep = (s4 *) (m->jcode + nextp);
1935 OP2A(opcode, 0, tablep, currentline);
1937 /* default target */
1939 j = p + code_get_s4(nextp, m);
1940 *tablep = j; /* restore for little endian */
1943 CHECK_BYTECODE_INDEX(j);
1946 /* number of pairs */
1948 num = code_get_u4(nextp, m);
1953 CHECK_END_OF_BYTECODE(nextp + 8 * num);
1955 for (i = 0; i < num; i++) {
1958 j = code_get_s4(nextp, m);
1959 *tablep = j; /* restore for little endian */
1963 #if defined(ENABLE_VERIFIER)
1964 /* check if the lookup table is sorted correctly */
1966 if (i && (j <= prevvalue)) {
1967 *exceptionptr = new_verifyerror(m, "Unsorted lookup switch");
1975 j = p + code_get_s4(nextp,m);
1976 *tablep = j; /* restore for little endian */
1979 CHECK_BYTECODE_INDEX(j);
1987 case JAVA_TABLESWITCH:
1993 nextp = ALIGN((p + 1), 4);
1995 CHECK_END_OF_BYTECODE(nextp + 12);
1997 tablep = (s4 *) (m->jcode + nextp);
1999 OP2A(opcode, 0, tablep, currentline);
2001 /* default target */
2003 j = p + code_get_s4(nextp, m);
2004 *tablep = j; /* restore for little endian */
2007 CHECK_BYTECODE_INDEX(j);
2012 j = code_get_s4(nextp, m);
2013 *tablep = j; /* restore for little endian */
2019 num = code_get_s4(nextp, m);
2020 *tablep = num; /* restore for little endian */
2024 num -= j; /* difference of upper - lower */
2026 #if defined(ENABLE_VERIFIER)
2028 *exceptionptr = new_verifyerror(m,
2029 "invalid TABLESWITCH: upper bound < lower bound");
2034 CHECK_END_OF_BYTECODE(nextp + 4 * (num + 1));
2036 for (i = 0; i <= num; i++) {
2037 j = p + code_get_s4(nextp,m);
2038 *tablep = j; /* restore for little endian */
2041 CHECK_BYTECODE_INDEX(j);
2049 /* load and store of object fields ************************************/
2053 m->isleafmethod = false;
2056 case JAVA_GETSTATIC:
2057 case JAVA_PUTSTATIC:
2061 constant_FMIref *fr;
2062 unresolved_field *uf;
2064 i = code_get_u2(p + 1, m);
2065 fr = class_getconstant(m->class, i,
2070 OP2A_NOINC(opcode, fr->parseddesc.fd->type, fr, currentline);
2072 /* only with -noverify, otherwise the typechecker does this */
2074 #if defined(ENABLE_VERIFIER)
2077 result = resolve_field_lazy(iptr,NULL,m);
2078 if (result == resolveFailed)
2081 if (result != resolveSucceeded) {
2082 uf = create_unresolved_field(m->class,
2088 /* store the unresolved_field pointer */
2090 /* XXX this will be changed */
2092 iptr->target = (void*) 0x01; /* XXX target temporarily used as flag */
2095 iptr->target = NULL;
2097 #if defined(ENABLE_VERIFIER)
2100 iptr->target = NULL;
2108 /* method invocation **************************************************/
2110 case JAVA_INVOKESTATIC:
2111 i = code_get_u2(p + 1, m);
2112 mr = class_getconstant(m->class, i,
2113 CONSTANT_Methodref);
2117 md = mr->parseddesc.md;
2120 if (!descriptor_params_from_paramtypes(md, ACC_STATIC))
2125 case JAVA_INVOKEINTERFACE:
2126 i = code_get_u2(p + 1, m);
2128 mr = class_getconstant(m->class, i,
2129 CONSTANT_InterfaceMethodref);
2131 goto invoke_nonstatic_method;
2133 case JAVA_INVOKESPECIAL:
2134 case JAVA_INVOKEVIRTUAL:
2135 i = code_get_u2(p + 1, m);
2136 mr = class_getconstant(m->class, i,
2137 CONSTANT_Methodref);
2139 invoke_nonstatic_method:
2143 md = mr->parseddesc.md;
2146 if (!descriptor_params_from_paramtypes(md, 0))
2150 m->isleafmethod = false;
2152 OP2A_NOINC(opcode, 0, mr, currentline);
2154 /* only with -noverify, otherwise the typechecker does this */
2156 #if defined(ENABLE_VERIFIER)
2159 result = resolve_method_lazy(iptr,NULL,m);
2160 if (result == resolveFailed)
2163 if (result != resolveSucceeded) {
2164 um = create_unresolved_method(m->class,
2170 /* store the unresolved_method pointer */
2172 /* XXX this will be changed */
2174 iptr->target = (void*) 0x01; /* XXX target temporarily used as flag */
2177 /* the method could be resolved */
2178 iptr->target = NULL;
2180 #if defined(ENABLE_VERIFIER)
2183 iptr->target = NULL;
2189 /* miscellaneous object operations ************************************/
2192 i = code_get_u2(p + 1, m);
2193 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
2197 if (!resolve_classref(m, cr, resolveLazy, true, true,
2201 LOADCONST_A_BUILTIN(c, cr);
2202 bte = builtintable_get_internal(BUILTIN_new);
2203 BUILTIN(bte, true, NULL, currentline);
2207 case JAVA_CHECKCAST:
2208 i = code_get_u2(p + 1, m);
2209 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
2213 if (!resolve_classref(m, cr, resolveLazy, true,
2217 if (cr->name->text[0] == '[') {
2218 /* array type cast-check */
2219 OP2AT(opcode, 0, c, cr, currentline);
2220 m->isleafmethod = false;
2224 /* object type cast-check */
2225 OP2AT(opcode, 1, c, cr, currentline);
2229 case JAVA_INSTANCEOF:
2230 i = code_get_u2(p + 1,m);
2231 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
2235 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
2238 if (cr->name->text[0] == '[') {
2239 /* array type cast-check */
2240 LOADCONST_A_BUILTIN(c, cr);
2241 bte = builtintable_get_internal(BUILTIN_arrayinstanceof);
2242 BUILTIN(bte, false, NULL, currentline);
2247 /* object type cast-check */
2248 OP2AT(opcode, 1, c, cr, currentline);
2252 case JAVA_MONITORENTER:
2253 #if defined(ENABLE_THREADS)
2256 bte = builtintable_get_internal(BUILTIN_monitorenter);
2257 BUILTIN(bte, false, NULL, currentline);
2267 case JAVA_MONITOREXIT:
2268 #if defined(ENABLE_THREADS)
2270 bte = builtintable_get_internal(BUILTIN_monitorexit);
2271 BUILTIN(bte, false, NULL, currentline);
2280 /* any other basic operation ******************************************/
2283 #if !SUPPORT_DIVISION
2284 bte = builtintable_get_internal(BUILTIN_idiv);
2285 OP2A(opcode, bte->md->paramcount, bte, currentline);
2286 m->isleafmethod = false;
2293 #if !SUPPORT_DIVISION
2294 bte = builtintable_get_internal(BUILTIN_irem);
2295 OP2A(opcode, bte->md->paramcount, bte, currentline);
2296 m->isleafmethod = false;
2303 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
2304 bte = builtintable_get_internal(BUILTIN_ldiv);
2305 OP2A(opcode, bte->md->paramcount, bte, currentline);
2306 m->isleafmethod = false;
2313 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
2314 bte = builtintable_get_internal(BUILTIN_lrem);
2315 OP2A(opcode, bte->md->paramcount, bte, currentline);
2316 m->isleafmethod = false;
2323 #if defined(__I386__)
2326 bte = builtintable_get_internal(BUILTIN_frem);
2327 BUILTIN(bte, false, NULL, currentline);
2332 #if defined(__I386__)
2335 bte = builtintable_get_internal(BUILTIN_drem);
2336 BUILTIN(bte, false, NULL, currentline);
2341 #if defined(__ALPHA__)
2343 bte = builtintable_get_internal(BUILTIN_f2i);
2344 BUILTIN(bte, false, NULL, currentline);
2354 #if defined(__ALPHA__)
2356 bte = builtintable_get_internal(BUILTIN_f2l);
2357 BUILTIN(bte, false, NULL, currentline);
2367 #if defined(__ALPHA__)
2369 bte = builtintable_get_internal(BUILTIN_d2i);
2370 BUILTIN(bte, false, NULL, currentline);
2380 #if defined(__ALPHA__)
2382 bte = builtintable_get_internal(BUILTIN_d2l);
2383 BUILTIN(bte, false, NULL, currentline);
2392 /* check for invalid opcodes if the verifier is enabled */
2393 #if defined(ENABLE_VERIFIER)
2394 case JAVA_BREAKPOINT:
2396 new_verifyerror(m, "Quick instructions shouldn't appear yet.");
2399 case 186: /* unused opcode */
2454 new_verifyerror(m,"Illegal opcode %d at instr %d\n",
2458 #endif /* defined(ENABLE_VERIFIER) */
2461 /* straight-forward translation to ICMD */
2467 #if defined(ENABLE_VERIFIER)
2468 /* If WIDE was used correctly, iswide should have been reset by now. */
2470 *exceptionptr = new_verifyerror(m,
2471 "Illegal instruction: WIDE before incompatible opcode");
2474 #endif /* defined(ENABLE_VERIFIER) */
2478 #if defined(ENABLE_VERIFIER)
2479 if (p != m->jcodelength) {
2480 *exceptionptr = new_verifyerror(m,
2481 "Command-sequence crosses code-boundary");
2486 *exceptionptr = new_verifyerror(m, "Falling off the end of the code");
2489 #endif /* defined(ENABLE_VERIFIER) */
2491 /* adjust block count if target 0 is not first intermediate instruction */
2493 if (!m->basicblockindex[0] || (m->basicblockindex[0] > 1))
2496 /* copy local to method variables */
2498 m->instructioncount = ipc;
2499 m->basicblockcount = b_count;
2500 m->stackcount = s_count + m->basicblockcount * m->maxstack;
2502 /* allocate stack table */
2504 m->stack = DMNEW(stackelement, m->stackcount);
2509 bptr = m->basicblocks = DMNEW(basicblock, b_count + 1); /* one more for end ipc */
2514 /* additional block if target 0 is not first intermediate instruction */
2516 if (!m->basicblockindex[0] || (m->basicblockindex[0] > 1)) {
2517 BASICBLOCK_INIT(bptr,m);
2519 bptr->iinstr = m->instructions;
2520 /* bptr->icount is set when the next block is allocated */
2524 bptr[-1].next = bptr;
2527 /* allocate blocks */
2529 for (p = 0; p < m->jcodelength; p++) {
2530 if (m->basicblockindex[p] & 1) {
2531 /* Check if this block starts at the beginning of an */
2533 #if defined(ENABLE_VERIFIER)
2534 if (!instructionstart[p]) {
2535 *exceptionptr = new_verifyerror(m,
2536 "Branch into middle of instruction");
2541 /* allocate the block */
2543 BASICBLOCK_INIT(bptr,m);
2545 bptr->iinstr = m->instructions + (m->basicblockindex[p] >> 1);
2547 bptr[-1].icount = bptr->iinstr - bptr[-1].iinstr;
2549 /* bptr->icount is set when the next block is allocated */
2551 m->basicblockindex[p] = b_count;
2555 bptr[-1].next = bptr;
2559 /* set instruction count of last real block */
2562 bptr[-1].icount = (m->instructions + m->instructioncount) - bptr[-1].iinstr;
2565 /* allocate additional block at end */
2567 BASICBLOCK_INIT(bptr,m);
2569 bptr->instack = bptr->outstack = NULL;
2570 bptr->indepth = bptr->outdepth = 0;
2571 bptr->iinstr = NULL;
2575 /* set basicblock pointers in exception table */
2577 if (cd->exceptiontablelength > 0) {
2578 cd->exceptiontable[cd->exceptiontablelength - 1].down = NULL;
2581 for (i = 0; i < cd->exceptiontablelength; ++i) {
2582 p = cd->exceptiontable[i].startpc;
2583 cd->exceptiontable[i].start = m->basicblocks + m->basicblockindex[p];
2585 p = cd->exceptiontable[i].endpc;
2586 cd->exceptiontable[i].end = (p == m->jcodelength) ? (m->basicblocks + m->basicblockcount /*+ 1*/) : (m->basicblocks + m->basicblockindex[p]);
2588 p = cd->exceptiontable[i].handlerpc;
2589 cd->exceptiontable[i].handler = m->basicblocks + m->basicblockindex[p];
2592 /* XXX activate this if you want to try inlining */
2594 for (i = 0; i < m->exceptiontablelength; ++i) {
2595 p = m->exceptiontable[i].startpc;
2596 m->exceptiontable[i].start = m->basicblocks + m->basicblockindex[p];
2598 p = m->exceptiontable[i].endpc;
2599 m->exceptiontable[i].end = (p == m->jcodelength) ? (m->basicblocks + m->basicblockcount /*+ 1*/) : (m->basicblocks + m->basicblockindex[p]);
2601 p = m->exceptiontable[i].handlerpc;
2602 m->exceptiontable[i].handler = m->basicblocks + m->basicblockindex[p];
2608 /* everything's ok */
2612 #if defined(ENABLE_VERIFIER)
2614 throw_unexpected_end_of_bytecode:
2615 *exceptionptr = new_verifyerror(m, "Unexpected end of bytecode");
2618 throw_invalid_bytecode_index:
2620 new_verifyerror(m, "Illegal target of branch instruction");
2623 throw_illegal_local_variable_number:
2625 new_verifyerror(m, "Illegal local variable number");
2628 #endif /* ENABLE_VERIFIER */
2633 * These are local overrides for various environment variables in Emacs.
2634 * Please do not remove this and leave it at the end of the file, where
2635 * Emacs will automagically detect them.
2636 * ---------------------------------------------------------------------
2639 * indent-tabs-mode: t
2643 * vim:noexpandtab:sw=4:ts=4: