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 5435 2006-09-08 18:14:50Z edwin $
46 #include "mm/memory.h"
47 #include "native/native.h"
49 #if defined(ENABLE_THREADS)
50 # include "threads/native/lock.h"
53 #include "toolbox/logging.h"
54 #include "vm/builtin.h"
55 #include "vm/exceptions.h"
56 #include "vm/global.h"
57 #include "vm/linker.h"
58 #include "vm/loader.h"
59 #include "vm/resolve.h"
60 #include "vm/options.h"
61 #include "vm/statistics.h"
62 #include "vm/stringlocal.h"
64 #include "vm/jit/asmpart.h"
65 #include "vm/jit/jit.h"
66 #include "vm/jit/parse.h"
67 #include "vm/jit/patcher.h"
68 #include "vm/jit/loop/loop.h"
70 #define INSTRUCTIONS_INCREMENT 5 /* number of additional instructions to */
71 /* allocate if space runs out */
74 /* parserdata_t ***************************************************************/
76 typedef struct parsedata_t parsedata_t;
79 instruction *instructions; /* instruction array */
80 s4 instructionslength; /* length of the instruction array */
85 /* parse_setup *****************************************************************
87 Fills the passed parsedata_t structure.
89 *******************************************************************************/
91 static void parse_setup(jitdata *jd, parsedata_t *pd)
95 /* get required compiler data */
99 /* Allocate instruction array and block index table (1 additional
102 jd->new_basicblockindex = DMNEW(s4, m->jcodelength + 1);
103 pd->instructionstart = DMNEW(u1, m->jcodelength + 1);
105 MZERO(jd->new_basicblockindex, s4, m->jcodelength + 1);
106 MZERO(pd->instructionstart, u1, m->jcodelength + 1);
108 /* Set the length of the instruction array. We simply add 5 more
109 instruction, as this seems to be a reasonable value. */
111 pd->instructionslength = m->jcodelength + 1;
113 /* allocate the instruction array */
115 pd->instructions = DMNEW(instruction, pd->instructionslength);
117 /* Zero the intermediate instructions array so we don't have any
118 invalid pointers in it if we cannot finish stack_analyse(). */
120 MZERO(pd->instructions, instruction, pd->instructionslength);
124 /* parse_check_instructions ****************************************************
126 Checks if there's enough room in the instructions array for the
127 required instructions. If not, reallocate the data structures.
129 *******************************************************************************/
131 static instruction *parse_check_instructions(parsedata_t *pd, s4 ipc)
133 /* increase the size of the instruction array */
135 pd->instructionslength += INSTRUCTIONS_INCREMENT;
137 /* reallocate the array */
139 pd->instructions = DMREALLOC(pd->instructions, instruction, ipc,
140 pd->instructionslength);
142 /* return the iptr */
144 return pd->instructions + ipc;
148 /*******************************************************************************
150 function 'parse' scans the JavaVM code and generates intermediate code
152 During parsing the block index table is used to store at bit pos 0
153 a flag which marks basic block starts and at position 1 to 31 the
154 intermediate instruction index. After parsing the block index table
155 is scanned, for marked positions a block is generated and the block
156 number is stored in the block index table.
158 *******************************************************************************/
160 static exceptiontable * new_fillextable(
163 exceptiontable *extable,
164 exceptiontable *raw_extable,
165 int exceptiontablelength,
170 if (exceptiontablelength == 0)
173 b_count = *block_count;
175 for (src = exceptiontablelength-1; src >=0; src--) {
176 /* the start of the handled region becomes a basic block start */
177 p = raw_extable[src].startpc;
178 CHECK_BYTECODE_INDEX(p);
179 extable->startpc = p;
182 p = raw_extable[src].endpc; /* see JVM Spec 4.7.3 */
183 CHECK_BYTECODE_INDEX_EXCLUSIVE(p);
185 #if defined(ENABLE_VERIFIER)
186 if (p <= raw_extable[src].startpc) {
187 exceptions_throw_verifyerror(m,
188 "Invalid exception handler range");
194 /* end of handled region becomes a basic block boundary */
195 /* (If it is the bytecode end, we'll use the special */
196 /* end block that is created anyway.) */
197 if (p < m->jcodelength)
200 /* the start of the handler becomes a basic block start */
201 p = raw_extable[src].handlerpc;
202 CHECK_BYTECODE_INDEX(p);
203 extable->handlerpc = p;
206 extable->catchtype = raw_extable[src].catchtype;
207 extable->next = NULL;
208 extable->down = &extable[1];
212 *block_count = b_count;
217 #if defined(ENABLE_VERIFIER)
218 throw_invalid_bytecode_index:
219 exceptions_throw_verifyerror(m,
220 "Illegal bytecode index in exception table");
225 /*** macro for checking the length of the bytecode ***/
227 #if defined(ENABLE_VERIFIER)
228 #define CHECK_END_OF_BYTECODE(neededlength) \
230 if ((neededlength) > m->jcodelength) \
231 goto throw_unexpected_end_of_bytecode; \
233 #else /* !ENABLE_VERIFIER */
234 #define CHECK_END_OF_BYTECODE(neededlength)
235 #endif /* ENABLE_VERIFIER */
237 bool new_parse(jitdata *jd)
239 methodinfo *m; /* method being parsed */
243 instruction *iptr; /* current ptr into instruction array */
244 s4 ipc; /* intermediate instruction counter */
245 s4 p; /* java instruction counter */
246 s4 nextp; /* start of next java instruction */
247 s4 opcode; /* java opcode */
250 int b_count = 0; /* basic block counter */
251 int s_count = 0; /* stack element counter */
252 bool blockend = false; /* true if basic block end has been reached */
253 bool iswide = false; /* true if last instruction was a wide */
254 constant_classref *cr;
255 constant_classref *compr;
257 builtintable_entry *bte;
260 unresolved_method *um;
261 resolve_result_t result;
268 int *local_map; /* local pointer to renaming structore */
269 /* is assigned to rd->local_map at the end */
270 /* get required compiler data */
276 /* allocate buffers for local variable renaming */
277 local_map = DMNEW(int, cd->maxlocals * 5);
278 for (i = 0; i < cd->maxlocals; i++) {
279 local_map[i * 5 + 0] = 0;
280 local_map[i * 5 + 1] = 0;
281 local_map[i * 5 + 2] = 0;
282 local_map[i * 5 + 3] = 0;
283 local_map[i * 5 + 4] = 0;
286 /* initialize the parse data structures */
288 parse_setup(jd, &pd);
290 /* initialize local variables */
292 iptr = pd.instructions;
295 /* compute branch targets of exception table */
297 if (!new_fillextable(jd, m,
298 &(cd->exceptiontable[cd->exceptiontablelength-1]),
300 m->exceptiontablelength,
306 s_count = 1 + m->exceptiontablelength; /* initialize stack element counter */
308 #if defined(ENABLE_THREADS)
309 if (checksync && (m->flags & ACC_SYNCHRONIZED))
310 jd->isleafmethod = false;
313 /* setup line number info */
318 if (m->linenumbercount == 0) {
322 linepcchange = m->linenumbers[0].start_pc;
325 /*** LOOP OVER ALL BYTECODE INSTRUCTIONS **********************************/
327 for (p = 0; p < m->jcodelength; p = nextp) {
329 /* mark this position as a valid instruction start */
331 pd.instructionstart[p] = 1;
333 /* change the current line number, if necessary */
335 /* XXX rewrite this using pointer arithmetic */
337 if (linepcchange == p) {
338 if (m->linenumbercount > lineindex) {
340 currentline = m->linenumbers[lineindex].line_number;
342 if (lineindex < m->linenumbercount) {
343 linepcchange = m->linenumbers[lineindex].start_pc;
344 if (linepcchange == p)
345 goto next_linenumber;
351 /* fetch next opcode */
353 opcode = SUCK_BE_U1(m->jcode + p);
355 /* some compilers put a JAVA_NOP after a blockend instruction */
357 if (blockend && (opcode != JAVA_NOP)) {
358 /* start new block */
364 /* store intermediate instruction count (bit 0 mark block starts) */
366 jd->new_basicblockindex[p] |= (ipc << 1);
368 /* compute next instruction start */
370 nextp = p + jcommandsize[opcode];
372 CHECK_END_OF_BYTECODE(nextp);
374 /* add stack elements produced by this instruction */
376 s_count += stackreq[opcode];
378 /* We check here for the space of 1 instruction in the
379 instruction array. If an opcode is converted to more than
380 1 instruction, this is checked in the corresponding
383 INSTRUCTIONS_CHECK(1);
385 /* translate this bytecode instruction */
391 /* pushing constants onto the stack ***********************************/
394 OP_LOADCONST_I(SUCK_BE_S1(m->jcode + p + 1));
398 OP_LOADCONST_I(SUCK_BE_S2(m->jcode + p + 1));
402 i = SUCK_BE_U1(m->jcode + p + 1);
403 goto pushconstantitem;
407 i = SUCK_BE_U2(m->jcode + p + 1);
411 #if defined(ENABLE_VERIFIER)
412 if (i >= m->class->cpcount) {
413 exceptions_throw_verifyerror(m,
414 "Attempt to access constant outside range");
419 switch (m->class->cptags[i]) {
420 case CONSTANT_Integer:
421 OP_LOADCONST_I(((constant_integer *) (m->class->cpinfos[i]))->value);
424 OP_LOADCONST_L(((constant_long *) (m->class->cpinfos[i]))->value);
427 OP_LOADCONST_F(((constant_float *) (m->class->cpinfos[i]))->value);
429 case CONSTANT_Double:
430 OP_LOADCONST_D(((constant_double *) (m->class->cpinfos[i]))->value);
432 case CONSTANT_String:
433 OP_LOADCONST_STRING(literalstring_new((utf *) (m->class->cpinfos[i])));
436 cr = (constant_classref *) (m->class->cpinfos[i]);
438 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
441 /* if not resolved, c == NULL */
443 OP_LOADCONST_CLASSINFO_OR_CLASSREF_CHECK(c, cr);
447 #if defined(ENABLE_VERIFIER)
449 exceptions_throw_verifyerror(m,
450 "Invalid constant type to push");
456 case JAVA_ACONST_NULL:
467 OP_LOADCONST_I(opcode - JAVA_ICONST_0);
472 OP_LOADCONST_L(opcode - JAVA_LCONST_0);
478 OP_LOADCONST_F(opcode - JAVA_FCONST_0);
483 OP_LOADCONST_D(opcode - JAVA_DCONST_0);
486 /* stack operations ***************************************************/
488 /* We need space for additional ICMDs so we can translate these */
489 /* instructions to sequences of ICMD_COPY and ICMD_MOVE instructions. */
492 INSTRUCTIONS_CHECK(3);
499 INSTRUCTIONS_CHECK(4);
507 INSTRUCTIONS_CHECK(2);
513 INSTRUCTIONS_CHECK(5);
522 INSTRUCTIONS_CHECK(6);
532 INSTRUCTIONS_CHECK(2);
537 /* local variable access instructions *********************************/
542 if (iswide == false) {
543 i = SUCK_BE_U1(m->jcode + p + 1);
546 i = SUCK_BE_U2(m->jcode + p + 1);
550 OP_LOAD_ONEWORD(opcode, i, opcode - JAVA_ILOAD);
555 if (iswide == false) {
556 i = SUCK_BE_U1(m->jcode + p + 1);
559 i = SUCK_BE_U2(m->jcode + p + 1);
563 OP_LOAD_TWOWORD(opcode, i, opcode - JAVA_ILOAD);
570 OP_LOAD_ONEWORD(ICMD_ILOAD, opcode - JAVA_ILOAD_0, TYPE_INT);
577 OP_LOAD_TWOWORD(ICMD_LLOAD, opcode - JAVA_LLOAD_0, TYPE_LNG);
584 OP_LOAD_ONEWORD(ICMD_FLOAD, opcode - JAVA_FLOAD_0, TYPE_FLT);
591 OP_LOAD_TWOWORD(ICMD_DLOAD, opcode - JAVA_DLOAD_0, TYPE_DBL);
598 OP_LOAD_ONEWORD(ICMD_ALOAD, opcode - JAVA_ALOAD_0, TYPE_ADR);
604 if (iswide == false) {
605 i = SUCK_BE_U1(m->jcode + p + 1);
608 i = SUCK_BE_U2(m->jcode + p + 1);
612 OP_STORE_ONEWORD(opcode, i, opcode - JAVA_ISTORE);
617 if (iswide == false) {
618 i = SUCK_BE_U1(m->jcode + p + 1);
621 i = SUCK_BE_U2(m->jcode + p + 1);
625 OP_STORE_TWOWORD(opcode, i, opcode - JAVA_ISTORE);
632 OP_STORE_ONEWORD(ICMD_ISTORE, opcode - JAVA_ISTORE_0, TYPE_INT);
639 OP_STORE_TWOWORD(ICMD_LSTORE, opcode - JAVA_LSTORE_0, TYPE_LNG);
646 OP_STORE_ONEWORD(ICMD_FSTORE, opcode - JAVA_FSTORE_0, TYPE_FLT);
653 OP_STORE_TWOWORD(ICMD_DSTORE, opcode - JAVA_DSTORE_0, TYPE_DBL);
660 OP_STORE_ONEWORD(ICMD_ASTORE, opcode - JAVA_ASTORE_0, TYPE_ADR);
667 if (iswide == false) {
668 i = SUCK_BE_U1(m->jcode + p + 1);
669 v = SUCK_BE_S1(m->jcode + p + 2);
673 i = SUCK_BE_U2(m->jcode + p + 1);
674 v = SUCK_BE_S2(m->jcode + p + 3);
679 LOCALTYPE_USED(i, TYPE_INT);
680 OP_LOCALINDEX_I(opcode, i, v);
684 /* wider index for loading, storing and incrementing ******************/
691 /* managing arrays ****************************************************/
694 switch (SUCK_BE_S1(m->jcode + p + 1)) {
696 bte = builtintable_get_internal(BUILTIN_newarray_boolean);
699 bte = builtintable_get_internal(BUILTIN_newarray_char);
702 bte = builtintable_get_internal(BUILTIN_newarray_float);
705 bte = builtintable_get_internal(BUILTIN_newarray_double);
708 bte = builtintable_get_internal(BUILTIN_newarray_byte);
711 bte = builtintable_get_internal(BUILTIN_newarray_short);
714 bte = builtintable_get_internal(BUILTIN_newarray_int);
717 bte = builtintable_get_internal(BUILTIN_newarray_long);
719 #if defined(ENABLE_VERIFIER)
721 exceptions_throw_verifyerror(m, "Invalid array-type to create");
725 OP_BUILTIN_CHECK_EXCEPTION(bte);
729 i = SUCK_BE_U2(m->jcode + p + 1);
730 compr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
734 if (!(cr = class_get_classref_multiarray_of(1, compr)))
737 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
740 INSTRUCTIONS_CHECK(2);
741 OP_LOADCONST_CLASSINFO_OR_CLASSREF_NOCHECK(c, cr);
742 bte = builtintable_get_internal(BUILTIN_newarray);
743 OP_BUILTIN_CHECK_EXCEPTION(bte);
747 case JAVA_MULTIANEWARRAY:
748 jd->isleafmethod = false;
749 i = SUCK_BE_U2(m->jcode + p + 1);
750 j = SUCK_BE_U1(m->jcode + p + 3);
752 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
756 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
759 /* if unresolved, c == NULL */
761 iptr->s1.argcount = j;
762 OP_S3_CLASSINFO_OR_CLASSREF(opcode, c, cr, 0 /* flags */);
765 /* control flow instructions ******************************************/
784 i = p + SUCK_BE_S2(m->jcode + p + 1);
785 CHECK_BYTECODE_INDEX(i);
788 OP_INSINDEX(opcode, i);
792 i = p + SUCK_BE_S4(m->jcode + p + 1);
793 CHECK_BYTECODE_INDEX(i);
796 OP_INSINDEX(opcode, i);
800 i = p + SUCK_BE_S2(m->jcode + p + 1);
802 CHECK_BYTECODE_INDEX(i);
805 OP_PREPARE_ZEROFLAGS(JAVA_JSR);
806 iptr->sx.s23.s3.jsrtarget.insindex = i;
811 i = p + SUCK_BE_S4(m->jcode + p + 1);
815 if (iswide == false) {
816 i = SUCK_BE_U1(m->jcode + p + 1);
819 i = SUCK_BE_U2(m->jcode + p + 1);
825 OP_LOAD_ONEWORD(opcode, i, TYPE_ADR);
835 /* XXX ARETURN will need a flag in the typechecker */
841 /* XXX ATHROW will need a flag in the typechecker */
846 /* table jumps ********************************************************/
848 case JAVA_LOOKUPSWITCH:
851 lookup_target_t *lookup;
852 #if defined(ENABLE_VERIFIER)
856 nextp = ALIGN((p + 1), 4);
858 CHECK_END_OF_BYTECODE(nextp + 8);
860 OP_PREPARE_ZEROFLAGS(opcode);
864 j = p + SUCK_BE_S4(m->jcode + nextp);
865 iptr->sx.s23.s3.lookupdefault.insindex = j;
867 CHECK_BYTECODE_INDEX(j);
870 /* number of pairs */
872 num = SUCK_BE_U4(m->jcode + nextp);
873 iptr->sx.s23.s2.lookupcount = num;
876 /* allocate the intermediate code table */
878 lookup = DMNEW(lookup_target_t, num);
879 iptr->dst.lookup = lookup;
881 /* iterate over the lookup table */
883 CHECK_END_OF_BYTECODE(nextp + 8 * num);
885 for (i = 0; i < num; i++) {
888 j = SUCK_BE_S4(m->jcode + nextp);
893 #if defined(ENABLE_VERIFIER)
894 /* check if the lookup table is sorted correctly */
896 if (i && (j <= prevvalue)) {
897 exceptions_throw_verifyerror(m, "Unsorted lookup switch");
904 j = p + SUCK_BE_S4(m->jcode + nextp);
905 lookup->target.insindex = j;
908 CHECK_BYTECODE_INDEX(j);
917 case JAVA_TABLESWITCH:
921 branch_target_t *table;
924 nextp = ALIGN((p + 1), 4);
926 CHECK_END_OF_BYTECODE(nextp + 12);
928 OP_PREPARE_ZEROFLAGS(opcode);
932 deftarget = p + SUCK_BE_S4(m->jcode + nextp);
934 CHECK_BYTECODE_INDEX(deftarget);
935 MARK_BASICBLOCK(deftarget);
939 j = SUCK_BE_S4(m->jcode + nextp);
940 iptr->sx.s23.s2.tablelow = j;
945 num = SUCK_BE_S4(m->jcode + nextp);
946 iptr->sx.s23.s3.tablehigh = num;
949 /* calculate the number of table entries */
953 #if defined(ENABLE_VERIFIER)
955 exceptions_throw_verifyerror(m,
956 "invalid TABLESWITCH: upper bound < lower bound");
960 /* create the intermediate code table */
961 /* the first entry is the default target */
963 table = MNEW(branch_target_t, 1 + num);
964 iptr->dst.table = table;
965 (table++)->insindex = deftarget;
967 /* iterate over the target table */
969 CHECK_END_OF_BYTECODE(nextp + 4 * num);
971 for (i = 0; i < num; i++) {
972 j = p + SUCK_BE_S4(m->jcode + nextp);
973 (table++)->insindex = j;
975 CHECK_BYTECODE_INDEX(j);
984 /* load and store of object fields ************************************/
988 jd->isleafmethod = false;
997 unresolved_field *uf;
999 i = SUCK_BE_U2(m->jcode + p + 1);
1000 fr = class_getconstant(m->class, i, CONSTANT_Fieldref);
1004 OP_PREPARE_ZEROFLAGS(opcode);
1005 iptr->sx.s23.s3.fmiref = fr;
1007 /* only with -noverify, otherwise the typechecker does this */
1009 #if defined(ENABLE_VERIFIER)
1010 if (!JITDATA_HAS_FLAG_VERIFY(jd)) {
1012 result = new_resolve_field_lazy(iptr, m);
1013 if (result == resolveFailed)
1016 if (result != resolveSucceeded) {
1017 uf = new_create_unresolved_field(m->class, m, iptr);
1022 /* store the unresolved_field pointer */
1024 iptr->sx.s23.s3.uf = uf;
1025 iptr->flags.bits = INS_FLAG_UNRESOLVED;
1027 #if defined(ENABLE_VERIFIER)
1035 /* method invocation **************************************************/
1037 case JAVA_INVOKESTATIC:
1038 i = SUCK_BE_U2(m->jcode + p + 1);
1039 mr = class_getconstant(m->class, i, CONSTANT_Methodref);
1044 md = mr->parseddesc.md;
1046 if (md->params == NULL)
1047 if (!descriptor_params_from_paramtypes(md, ACC_STATIC))
1052 case JAVA_INVOKEINTERFACE:
1053 i = SUCK_BE_U2(m->jcode + p + 1);
1055 mr = class_getconstant(m->class, i, CONSTANT_InterfaceMethodref);
1057 goto invoke_nonstatic_method;
1059 case JAVA_INVOKESPECIAL:
1060 case JAVA_INVOKEVIRTUAL:
1061 i = SUCK_BE_U2(m->jcode + p + 1);
1062 mr = class_getconstant(m->class, i, CONSTANT_Methodref);
1064 invoke_nonstatic_method:
1068 md = mr->parseddesc.md;
1070 if (md->params == NULL)
1071 if (!descriptor_params_from_paramtypes(md, 0))
1075 jd->isleafmethod = false;
1077 OP_PREPARE_ZEROFLAGS(opcode);
1078 iptr->sx.s23.s3.fmiref = mr;
1080 /* only with -noverify, otherwise the typechecker does this */
1082 #if defined(ENABLE_VERIFIER)
1083 if (!JITDATA_HAS_FLAG_VERIFY(jd)) {
1085 result = new_resolve_method_lazy(iptr, m);
1086 if (result == resolveFailed)
1089 if (result != resolveSucceeded) {
1090 um = new_create_unresolved_method(m->class, m, iptr);
1095 /* store the unresolved_method pointer */
1097 iptr->sx.s23.s3.um = um;
1098 iptr->flags.bits = INS_FLAG_UNRESOLVED;
1100 #if defined(ENABLE_VERIFIER)
1106 /* instructions taking class arguments ********************************/
1109 i = SUCK_BE_U2(m->jcode + p + 1);
1110 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
1114 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
1117 INSTRUCTIONS_CHECK(2);
1118 OP_LOADCONST_CLASSINFO_OR_CLASSREF_NOCHECK(c, cr);
1119 bte = builtintable_get_internal(BUILTIN_new);
1120 OP_BUILTIN_CHECK_EXCEPTION(bte);
1124 case JAVA_CHECKCAST:
1125 i = SUCK_BE_U2(m->jcode + p + 1);
1126 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
1130 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
1133 if (cr->name->text[0] == '[') {
1134 /* array type cast-check */
1135 flags = INS_FLAG_ARRAY;
1136 jd->isleafmethod = false;
1139 /* object type cast-check */
1142 OP_S3_CLASSINFO_OR_CLASSREF(opcode, c, cr, flags);
1145 case JAVA_INSTANCEOF:
1146 i = SUCK_BE_U2(m->jcode + p + 1);
1147 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
1151 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
1154 if (cr->name->text[0] == '[') {
1155 /* array type cast-check */
1156 INSTRUCTIONS_CHECK(2);
1157 OP_LOADCONST_CLASSINFO_OR_CLASSREF_NOCHECK(c, cr);
1158 bte = builtintable_get_internal(BUILTIN_arrayinstanceof);
1159 OP_BUILTIN_NO_EXCEPTION(bte);
1163 /* object type cast-check */
1164 OP_S3_CLASSINFO_OR_CLASSREF(opcode, c, cr, 0 /* flags*/);
1168 /* synchronization instructions ***************************************/
1170 case JAVA_MONITORENTER:
1171 #if defined(ENABLE_THREADS)
1173 bte = builtintable_get_internal(LOCK_monitor_enter);
1174 OP_BUILTIN_CHECK_EXCEPTION(bte);
1179 OP(ICMD_CHECKNULL_POP);
1183 case JAVA_MONITOREXIT:
1184 #if defined(ENABLE_THREADS)
1186 bte = builtintable_get_internal(LOCK_monitor_exit);
1187 OP_BUILTIN_CHECK_EXCEPTION(bte);
1192 OP(ICMD_CHECKNULL_POP);
1196 /* arithmetic instructions that may become builtin functions **********/
1199 #if !SUPPORT_DIVISION
1200 bte = builtintable_get_internal(BUILTIN_idiv);
1201 OP_BUILTIN_ARITHMETIC(opcode, bte);
1208 #if !SUPPORT_DIVISION
1209 bte = builtintable_get_internal(BUILTIN_irem);
1210 OP_BUILTIN_ARITHMETIC(opcode, bte);
1217 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1218 bte = builtintable_get_internal(BUILTIN_ldiv);
1219 OP_BUILTIN_ARITHMETIC(opcode, bte);
1226 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1227 bte = builtintable_get_internal(BUILTIN_lrem);
1228 OP_BUILTIN_ARITHMETIC(opcode, bte);
1235 #if defined(__I386__)
1238 bte = builtintable_get_internal(BUILTIN_frem);
1239 OP_BUILTIN_NO_EXCEPTION(bte);
1244 #if defined(__I386__)
1247 bte = builtintable_get_internal(BUILTIN_drem);
1248 OP_BUILTIN_NO_EXCEPTION(bte);
1253 #if defined(__ALPHA__)
1255 bte = builtintable_get_internal(BUILTIN_f2i);
1256 OP_BUILTIN_NO_EXCEPTION(bte);
1266 #if defined(__ALPHA__)
1268 bte = builtintable_get_internal(BUILTIN_f2l);
1269 OP_BUILTIN_NO_EXCEPTION(bte);
1279 #if defined(__ALPHA__)
1281 bte = builtintable_get_internal(BUILTIN_d2i);
1282 OP_BUILTIN_NO_EXCEPTION(bte);
1292 #if defined(__ALPHA__)
1294 bte = builtintable_get_internal(BUILTIN_d2l);
1295 OP_BUILTIN_NO_EXCEPTION(bte);
1304 /* invalid opcodes ****************************************************/
1306 /* check for invalid opcodes if the verifier is enabled */
1307 #if defined(ENABLE_VERIFIER)
1308 case JAVA_BREAKPOINT:
1309 exceptions_throw_verifyerror(m, "Quick instructions shouldn't appear, yet.");
1312 case 186: /* unused opcode */
1366 exceptions_throw_verifyerror(m, "Illegal opcode %d at instr %d\n",
1370 #endif /* defined(ENABLE_VERIFIER) */
1372 /* opcodes that don't require translation *****************************/
1375 /* straight-forward translation to ICMD */
1381 /* verifier checks ****************************************************/
1383 #if defined(ENABLE_VERIFIER)
1384 /* If WIDE was used correctly, iswide should have been reset by now. */
1386 exceptions_throw_verifyerror(m,
1387 "Illegal instruction: WIDE before incompatible opcode");
1390 #endif /* defined(ENABLE_VERIFIER) */
1394 /* add a NOP to the last basic block */
1396 INSTRUCTIONS_CHECK(1);
1399 /*** END OF LOOP **********************************************************/
1401 /* assert that we did not write more ICMDs than allocated */
1403 assert(ipc <= pd.instructionslength);
1404 assert(ipc == (iptr - pd.instructions));
1406 /*** verifier checks ******************************************************/
1408 #if defined(ENABLE_VERIFIER)
1409 if (p != m->jcodelength) {
1410 exceptions_throw_verifyerror(m,
1411 "Command-sequence crosses code-boundary");
1416 exceptions_throw_verifyerror(m, "Falling off the end of the code");
1419 #endif /* defined(ENABLE_VERIFIER) */
1421 /*** setup the methodinfo, allocate stack and basic blocks ****************/
1423 /* adjust block count if target 0 is not first intermediate instruction */
1425 if (!jd->new_basicblockindex[0] || (jd->new_basicblockindex[0] > 1))
1428 /* copy local to method variables */
1430 jd->new_instructions = pd.instructions;
1431 jd->new_instructioncount = ipc;
1432 jd->new_basicblockcount = b_count;
1433 jd->new_stackcount = s_count + jd->new_basicblockcount * m->maxstack; /* in-stacks */
1435 /* allocate stack table */
1437 jd->new_stack = DMNEW(stackelement, jd->new_stackcount);
1439 /* build basic block list */
1441 bptr = jd->new_basicblocks = DMNEW(basicblock, b_count + 1); /* one more for end ipc */
1443 /* zero out all basic block structures */
1445 MZERO(bptr, basicblock, b_count + 1);
1448 jd->new_c_debug_nr = 0;
1450 /* additional block if target 0 is not first intermediate instruction */
1452 if (!jd->new_basicblockindex[0] || (jd->new_basicblockindex[0] > 1)) {
1453 BASICBLOCK_INIT(bptr, m);
1455 bptr->iinstr = jd->new_instructions;
1456 /* bptr->icount is set when the next block is allocated */
1460 bptr[-1].next = bptr;
1463 /* allocate blocks */
1465 for (p = 0; p < m->jcodelength; p++) {
1466 if (jd->new_basicblockindex[p] & 1) {
1467 #if defined(ENABLE_VERIFIER)
1468 /* Check if this block starts at the beginning of an
1471 if (!pd.instructionstart[p]) {
1472 exceptions_throw_verifyerror(m,
1473 "Branch into middle of instruction");
1478 /* allocate the block */
1480 BASICBLOCK_INIT(bptr, m);
1482 bptr->iinstr = jd->new_instructions + (jd->new_basicblockindex[p] >> 1);
1484 bptr[-1].icount = bptr->iinstr - bptr[-1].iinstr;
1486 /* bptr->icount is set when the next block is allocated */
1488 jd->new_basicblockindex[p] = b_count;
1492 bptr[-1].next = bptr;
1496 /* set instruction count of last real block */
1499 bptr[-1].icount = (jd->new_instructions + jd->new_instructioncount) - bptr[-1].iinstr;
1502 /* allocate additional block at end */
1504 BASICBLOCK_INIT(bptr,m);
1506 /* set basicblock pointers in exception table */
1508 if (cd->exceptiontablelength > 0) {
1509 cd->exceptiontable[cd->exceptiontablelength - 1].down = NULL;
1512 for (i = 0; i < cd->exceptiontablelength; ++i) {
1513 p = cd->exceptiontable[i].startpc;
1514 cd->exceptiontable[i].start = jd->new_basicblocks + jd->new_basicblockindex[p];
1516 p = cd->exceptiontable[i].endpc;
1517 cd->exceptiontable[i].end = (p == m->jcodelength) ? (jd->new_basicblocks + jd->new_basicblockcount /*+ 1*/) : (jd->new_basicblocks + jd->new_basicblockindex[p]);
1519 p = cd->exceptiontable[i].handlerpc;
1520 cd->exceptiontable[i].handler = jd->new_basicblocks + jd->new_basicblockindex[p];
1523 /* XXX activate this if you want to try inlining */
1525 for (i = 0; i < m->exceptiontablelength; ++i) {
1526 p = m->exceptiontable[i].startpc;
1527 m->exceptiontable[i].start = jd->new_basicblocks + jd->new_basicblockindex[p];
1529 p = m->exceptiontable[i].endpc;
1530 m->exceptiontable[i].end = (p == m->jcodelength) ? (jd->new_basicblocks + jd->new_basicblockcount /*+ 1*/) : (jd->new_basicblocks + jd->new_basicblockindex[p]);
1532 p = m->exceptiontable[i].handlerpc;
1533 m->exceptiontable[i].handler = jd->new_basicblocks + jd->new_basicblockindex[p];
1537 jd->local_map = local_map;
1539 /* calculate local variable renaming */
1549 /* iterate over local_map[0..m->maxlocals*5] and set all existing */
1550 /* index,type pairs (localmap[index*5+type]==1) to an unique value */
1551 /* -> == new local var index */
1552 for(i = 0; i < (cd->maxlocals * 5); i++, mapptr++) {
1554 *mapptr = nlocals++;
1559 jd->localcount = nlocals;
1560 /* if dropped varindices for temp stackslots get reused(?max 2* */
1561 /* m->maxstack elements for stack), nlocals + s_count would be */
1563 jd->varcount = nlocals + s_count +
1564 jd->new_basicblockcount * m->maxstack; /* out-stacks */
1566 jd->vartop = nlocals;
1567 jd->var = DMNEW(varinfo, jd->varcount);
1568 MZERO(jd->var, varinfo, jd->varcount);
1570 /* set types of all Locals in jd->var */
1571 for(mapptr = local_map, i = 0; i < (cd->maxlocals * 5); i++, mapptr++)
1572 if (*mapptr != UNUSED)
1573 jd->var[*mapptr].type = i%5;
1576 /* everything's ok */
1580 /*** goto labels for throwing verifier exceptions *************************/
1582 #if defined(ENABLE_VERIFIER)
1584 throw_unexpected_end_of_bytecode:
1585 exceptions_throw_verifyerror(m, "Unexpected end of bytecode");
1588 throw_invalid_bytecode_index:
1589 exceptions_throw_verifyerror(m, "Illegal target of branch instruction");
1592 throw_illegal_local_variable_number:
1593 exceptions_throw_verifyerror(m, "Illegal local variable number");
1596 #endif /* ENABLE_VERIFIER */
1601 * These are local overrides for various environment variables in Emacs.
1602 * Please do not remove this and leave it at the end of the file, where
1603 * Emacs will automagically detect them.
1604 * ---------------------------------------------------------------------
1607 * indent-tabs-mode: t
1611 * vim:noexpandtab:sw=4:ts=4: