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 5096 2006-07-10 14:02:25Z twisti $
46 #include "mm/memory.h"
47 #include "native/native.h"
48 #include "toolbox/logging.h"
49 #include "vm/builtin.h"
50 #include "vm/exceptions.h"
51 #include "vm/global.h"
52 #include "vm/linker.h"
53 #include "vm/loader.h"
54 #include "vm/resolve.h"
55 #include "vm/options.h"
56 #include "vm/statistics.h"
57 #include "vm/stringlocal.h"
58 #include "vm/jit/asmpart.h"
59 #include "vm/jit/jit.h"
60 #include "vm/jit/parse.h"
61 #include "vm/jit/patcher.h"
62 #include "vm/jit/loop/loop.h"
64 /*******************************************************************************
66 function 'parse' scans the JavaVM code and generates intermediate code
68 During parsing the block index table is used to store at bit pos 0
69 a flag which marks basic block starts and at position 1 to 31 the
70 intermediate instruction index. After parsing the block index table
71 is scanned, for marked positions a block is generated and the block
72 number is stored in the block index table.
74 *******************************************************************************/
76 static exceptiontable * new_fillextable(
79 exceptiontable *extable,
80 exceptiontable *raw_extable,
81 int exceptiontablelength,
86 if (exceptiontablelength == 0)
89 b_count = *block_count;
91 for (src = exceptiontablelength-1; src >=0; src--) {
92 /* the start of the handled region becomes a basic block start */
93 p = raw_extable[src].startpc;
94 CHECK_BYTECODE_INDEX(p);
98 p = raw_extable[src].endpc; /* see JVM Spec 4.7.3 */
99 CHECK_BYTECODE_INDEX_EXCLUSIVE(p);
101 #if defined(ENABLE_VERIFIER)
102 if (p <= raw_extable[src].startpc) {
103 *exceptionptr = new_verifyerror(m,
104 "Invalid exception handler range");
110 /* end of handled region becomes a basic block boundary */
111 /* (If it is the bytecode end, we'll use the special */
112 /* end block that is created anyway.) */
113 if (p < m->jcodelength)
116 /* the start of the handler becomes a basic block start */
117 p = raw_extable[src].handlerpc;
118 CHECK_BYTECODE_INDEX(p);
119 extable->handlerpc = p;
122 extable->catchtype = raw_extable[src].catchtype;
123 extable->next = NULL;
124 extable->down = &extable[1];
128 *block_count = b_count;
133 #if defined(ENABLE_VERIFIER)
134 throw_invalid_bytecode_index:
136 new_verifyerror(m, "Illegal bytecode index in exception table");
141 static exceptiontable * fillextable(methodinfo *m,
142 exceptiontable *extable,
143 exceptiontable *raw_extable,
144 int exceptiontablelength,
149 if (exceptiontablelength == 0)
152 b_count = *block_count;
154 for (src = exceptiontablelength-1; src >=0; src--) {
155 /* the start of the handled region becomes a basic block start */
156 p = raw_extable[src].startpc;
157 CHECK_BYTECODE_INDEX(p);
158 extable->startpc = p;
161 p = raw_extable[src].endpc; /* see JVM Spec 4.7.3 */
162 CHECK_BYTECODE_INDEX_EXCLUSIVE(p);
164 #if defined(ENABLE_VERIFIER)
165 if (p <= raw_extable[src].startpc) {
166 *exceptionptr = new_verifyerror(m,
167 "Invalid exception handler range");
173 /* end of handled region becomes a basic block boundary */
174 /* (If it is the bytecode end, we'll use the special */
175 /* end block that is created anyway.) */
176 if (p < m->jcodelength)
179 /* the start of the handler becomes a basic block start */
180 p = raw_extable[src].handlerpc;
181 CHECK_BYTECODE_INDEX(p);
182 extable->handlerpc = p;
185 extable->catchtype = raw_extable[src].catchtype;
186 extable->next = NULL;
187 extable->down = &extable[1];
191 *block_count = b_count;
196 #if defined(ENABLE_VERIFIER)
197 throw_invalid_bytecode_index:
199 new_verifyerror(m, "Illegal bytecode index in exception table");
204 /*** macro for checking the length of the bytecode ***/
206 #if defined(ENABLE_VERIFIER)
207 #define CHECK_END_OF_BYTECODE(neededlength) \
209 if ((neededlength) > m->jcodelength) \
210 goto throw_unexpected_end_of_bytecode; \
212 #else /* !ENABLE_VERIFIER */
213 #define CHECK_END_OF_BYTECODE(neededlength)
214 #endif /* ENABLE_VERIFIER */
216 bool new_parse(jitdata *jd)
218 methodinfo *m; /* method being parsed */
221 int p; /* java instruction counter */
222 int nextp; /* start of next java instruction */
223 int opcode; /* java opcode */
224 int i; /* temporary for different uses (ctrs) */
225 int ipc = 0; /* intermediate instruction counter */
226 int b_count = 0; /* basic block counter */
227 int s_count = 0; /* stack element counter */
228 bool blockend = false; /* true if basic block end has been reached */
229 bool iswide = false; /* true if last instruction was a wide */
230 new_instruction *iptr; /* current ptr into instruction array */
231 u1 *instructionstart; /* 1 for pcs which are valid instr. starts */
232 constant_classref *cr;
233 constant_classref *compr;
235 builtintable_entry *bte;
238 unresolved_method *um;
239 resolve_result_t result;
246 /* get required compiler data */
252 /* allocate instruction array and block index table */
254 /* 1 additional for end ipc */
255 jd->new_basicblockindex = DMNEW(s4, m->jcodelength + 1);
256 memset(jd->new_basicblockindex, 0, sizeof(s4) * (m->jcodelength + 1));
258 instructionstart = DMNEW(u1, m->jcodelength + 1);
259 memset(instructionstart, 0, sizeof(u1) * (m->jcodelength + 1));
261 /* IMPORTANT: We assume that parsing creates at most one instruction per */
262 /* byte of original bytecode! */
264 iptr = jd->new_instructions = DMNEW(new_instruction, m->jcodelength);
266 /* compute branch targets of exception table */
268 if (!new_fillextable(jd, m,
269 &(cd->exceptiontable[cd->exceptiontablelength-1]),
271 m->exceptiontablelength,
277 s_count = 1 + m->exceptiontablelength; /* initialize stack element counter */
279 #if defined(ENABLE_THREADS)
280 if (checksync && (m->flags & ACC_SYNCHRONIZED))
281 jd->isleafmethod = false;
284 /* setup line number info */
289 if (m->linenumbercount == 0) {
293 linepcchange = m->linenumbers[0].start_pc;
296 /*** LOOP OVER ALL BYTECODE INSTRUCTIONS **********************************/
298 for (p = 0; p < m->jcodelength; p = nextp) {
300 /* mark this position as a valid instruction start */
302 instructionstart[p] = 1;
304 /* change the current line number, if necessary */
306 /* XXX rewrite this using pointer arithmetic */
308 if (linepcchange == p) {
309 if (m->linenumbercount > lineindex) {
311 currentline = m->linenumbers[lineindex].line_number;
313 if (lineindex < m->linenumbercount) {
314 linepcchange = m->linenumbers[lineindex].start_pc;
315 if (linepcchange == p)
316 goto next_linenumber;
321 /* fetch next opcode */
323 opcode = code_get_u1(p, m);
325 /* store intermediate instruction count (bit 0 mark block starts) */
327 jd->new_basicblockindex[p] |= (ipc << 1);
329 /* some compilers put a JAVA_NOP after a blockend instruction */
331 if (blockend && (opcode != JAVA_NOP)) {
332 /* start new block */
338 /* compute next instruction start */
340 nextp = p + jcommandsize[opcode];
342 CHECK_END_OF_BYTECODE(nextp);
344 /* add stack elements produced by this instruction */
346 s_count += stackreq[opcode];
348 /* translate this bytecode instruction */
355 /* pushing constants onto the stack ***********************************/
358 NEW_OP_LOADCONST_I(code_get_s1(p+1,m));
362 NEW_OP_LOADCONST_I(code_get_s2(p+1,m));
366 i = code_get_u1(p + 1, m);
367 goto pushconstantitem;
371 i = code_get_u2(p + 1, m);
375 #if defined(ENABLE_VERIFIER)
376 if (i >= m->class->cpcount) {
377 *exceptionptr = new_verifyerror(m,
378 "Attempt to access constant outside range");
383 switch (m->class->cptags[i]) {
384 case CONSTANT_Integer:
385 NEW_OP_LOADCONST_I(((constant_integer *) (m->class->cpinfos[i]))->value);
388 NEW_OP_LOADCONST_L(((constant_long *) (m->class->cpinfos[i]))->value);
391 NEW_OP_LOADCONST_F(((constant_float *) (m->class->cpinfos[i]))->value);
393 case CONSTANT_Double:
394 NEW_OP_LOADCONST_D(((constant_double *) (m->class->cpinfos[i]))->value);
396 case CONSTANT_String:
397 NEW_OP_LOADCONST_STRING(literalstring_new((utf *) (m->class->cpinfos[i])));
400 cr = (constant_classref *) (m->class->cpinfos[i]);
402 if (!resolve_classref(m, cr, resolveLazy, true,
406 /* if not resolved, c == NULL */
408 NEW_OP_LOADCONST_CLASSINFO_OR_CLASSREF(c, cr, 0 /* no extra flags */);
412 #if defined(ENABLE_VERIFIER)
414 *exceptionptr = new_verifyerror(m,
415 "Invalid constant type to push");
421 case JAVA_ACONST_NULL:
422 NEW_OP_LOADCONST_NULL();
432 NEW_OP_LOADCONST_I(opcode - JAVA_ICONST_0);
437 NEW_OP_LOADCONST_L(opcode - JAVA_LCONST_0);
443 NEW_OP_LOADCONST_F(opcode - JAVA_FCONST_0);
448 NEW_OP_LOADCONST_D(opcode - JAVA_DCONST_0);
451 /* local variable access instructions *********************************/
457 i = code_get_u1(p + 1,m);
460 i = code_get_u2(p + 1,m);
464 NEW_OP_LOAD_ONEWORD(opcode, i);
470 i = code_get_u1(p + 1,m);
473 i = code_get_u2(p + 1,m);
477 NEW_OP_LOAD_TWOWORD(opcode, i);
484 NEW_OP_LOAD_ONEWORD(ICMD_ILOAD, opcode - JAVA_ILOAD_0);
491 NEW_OP_LOAD_TWOWORD(ICMD_LLOAD, opcode - JAVA_LLOAD_0);
498 NEW_OP_LOAD_ONEWORD(ICMD_FLOAD, opcode - JAVA_FLOAD_0);
505 NEW_OP_LOAD_TWOWORD(ICMD_DLOAD, opcode - JAVA_DLOAD_0);
512 NEW_OP_LOAD_ONEWORD(ICMD_ALOAD, opcode - JAVA_ALOAD_0);
519 i = code_get_u1(p + 1,m);
522 i = code_get_u2(p + 1,m);
526 NEW_OP_STORE_ONEWORD(opcode, i);
532 i = code_get_u1(p + 1,m);
535 i = code_get_u2(p + 1,m);
539 NEW_OP_STORE_TWOWORD(opcode, i);
546 NEW_OP_STORE_ONEWORD(ICMD_ISTORE, opcode - JAVA_ISTORE_0);
553 NEW_OP_STORE_TWOWORD(ICMD_LSTORE, opcode - JAVA_LSTORE_0);
560 NEW_OP_STORE_ONEWORD(ICMD_FSTORE, opcode - JAVA_FSTORE_0);
567 NEW_OP_STORE_TWOWORD(ICMD_DSTORE, opcode - JAVA_DSTORE_0);
574 NEW_OP_STORE_ONEWORD(ICMD_ASTORE, opcode - JAVA_ASTORE_0);
582 i = code_get_u1(p + 1,m);
583 v = code_get_s1(p + 2,m);
587 i = code_get_u2(p + 1,m);
588 v = code_get_s2(p + 3,m);
593 NEW_OP_LOCALINDEX_I(opcode, i, v);
597 /* wider index for loading, storing and incrementing ******************/
604 /* managing arrays ****************************************************/
607 switch (code_get_s1(p + 1, m)) {
609 bte = builtintable_get_internal(BUILTIN_newarray_boolean);
612 bte = builtintable_get_internal(BUILTIN_newarray_char);
615 bte = builtintable_get_internal(BUILTIN_newarray_float);
618 bte = builtintable_get_internal(BUILTIN_newarray_double);
621 bte = builtintable_get_internal(BUILTIN_newarray_byte);
624 bte = builtintable_get_internal(BUILTIN_newarray_short);
627 bte = builtintable_get_internal(BUILTIN_newarray_int);
630 bte = builtintable_get_internal(BUILTIN_newarray_long);
632 #if defined(ENABLE_VERIFIER)
634 *exceptionptr = new_verifyerror(m,
635 "Invalid array-type to create");
639 NEW_OP_BUILTIN_CHECK_EXCEPTION(bte);
643 i = code_get_u2(p + 1, m);
644 compr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
648 if (!(cr = class_get_classref_multiarray_of(1, compr)))
651 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
654 NEW_OP_LOADCONST_CLASSINFO_OR_CLASSREF(c, cr, INS_FLAG_NOCHECK);
655 bte = builtintable_get_internal(BUILTIN_newarray);
656 NEW_OP_BUILTIN_CHECK_EXCEPTION(bte);
660 case JAVA_MULTIANEWARRAY:
661 jd->isleafmethod = false;
662 i = code_get_u2(p + 1, m);
664 s4 v = code_get_u1(p + 3, m);
666 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
670 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
673 /* if unresolved, c == NULL */
675 iptr->s1.argcount = v;
676 NEW_OP_S3_CLASSINFO_OR_CLASSREF(opcode, c, cr, 0 /* flags */);
680 /* control flow instructions ******************************************/
699 i = p + code_get_s2(p + 1,m);
700 CHECK_BYTECODE_INDEX(i);
703 NEW_OP_INSINDEX(opcode, i);
707 i = p + code_get_s4(p + 1,m);
708 CHECK_BYTECODE_INDEX(i);
711 NEW_OP_INSINDEX(opcode, i);
715 i = p + code_get_s2(p + 1,m);
717 CHECK_BYTECODE_INDEX(i);
720 NEW_OP_PREPARE_ZEROFLAGS(JAVA_JSR);
721 iptr->sx.s23.s3.jsrtarget.insindex = i;
726 i = p + code_get_s4(p + 1,m);
731 i = code_get_u1(p + 1,m);
734 i = code_get_u2(p + 1,m);
740 NEW_OP_LOAD_ONEWORD(opcode, i);
750 /* XXX ARETURN will need a flag in the typechecker */
756 /* XXX ATHROW will need a flag in the typechecker */
761 /* table jumps ********************************************************/
763 case JAVA_LOOKUPSWITCH:
766 lookup_target_t *lookup;
767 #if defined(ENABLE_VERIFIER)
771 nextp = ALIGN((p + 1), 4);
773 CHECK_END_OF_BYTECODE(nextp + 8);
775 NEW_OP_PREPARE_ZEROFLAGS(opcode);
779 j = p + code_get_s4(nextp, m);
780 iptr->sx.s23.s3.lookupdefault.insindex = j;
782 CHECK_BYTECODE_INDEX(j);
785 /* number of pairs */
787 num = code_get_u4(nextp, m);
788 iptr->sx.s23.s2.lookupcount = num;
791 /* allocate the intermediate code table */
793 lookup = DMNEW(lookup_target_t, num);
794 iptr->dst.lookup = lookup;
796 /* iterate over the lookup table */
798 CHECK_END_OF_BYTECODE(nextp + 8 * num);
800 for (i = 0; i < num; i++) {
803 j = code_get_s4(nextp, m);
808 #if defined(ENABLE_VERIFIER)
809 /* check if the lookup table is sorted correctly */
811 if (i && (j <= prevvalue)) {
812 *exceptionptr = new_verifyerror(m, "Unsorted lookup switch");
819 j = p + code_get_s4(nextp,m);
820 lookup->target.insindex = j;
823 CHECK_BYTECODE_INDEX(j);
832 case JAVA_TABLESWITCH:
836 branch_target_t *table;
839 nextp = ALIGN((p + 1), 4);
841 CHECK_END_OF_BYTECODE(nextp + 12);
843 NEW_OP_PREPARE_ZEROFLAGS(opcode);
847 deftarget = p + code_get_s4(nextp, m);
849 CHECK_BYTECODE_INDEX(deftarget);
850 new_block_insert(deftarget);
854 j = code_get_s4(nextp, m);
855 iptr->sx.s23.s2.tablelow = j;
860 num = code_get_s4(nextp, m);
861 iptr->sx.s23.s3.tablehigh = num;
864 /* calculate the number of table entries */
868 #if defined(ENABLE_VERIFIER)
870 *exceptionptr = new_verifyerror(m,
871 "invalid TABLESWITCH: upper bound < lower bound");
875 /* create the intermediate code table */
876 /* the first entry is the default target */
878 table = MNEW(branch_target_t, 1 + num);
879 iptr->dst.table = table;
880 (table++)->insindex = deftarget;
882 /* iterate over the target table */
884 CHECK_END_OF_BYTECODE(nextp + 4 * num);
886 for (i = 0; i < num; i++) {
887 j = p + code_get_s4(nextp,m);
888 (table++)->insindex = j;
890 CHECK_BYTECODE_INDEX(j);
899 /* load and store of object fields ************************************/
903 jd->isleafmethod = false;
912 unresolved_field *uf;
914 i = code_get_u2(p + 1, m);
915 fr = class_getconstant(m->class, i, CONSTANT_Fieldref);
919 NEW_OP_PREPARE_ZEROFLAGS(opcode);
920 iptr->sx.s23.s3.fmiref = fr;
922 /* only with -noverify, otherwise the typechecker does this */
924 #if defined(ENABLE_VERIFIER)
927 result = new_resolve_field_lazy(iptr, NULL, m);
928 if (result == resolveFailed)
931 if (result != resolveSucceeded) {
932 uf = new_create_unresolved_field(m->class, m, iptr);
937 /* store the unresolved_field pointer */
939 iptr->sx.s23.s3.uf = uf;
940 iptr->flags.bits = INS_FLAG_UNRESOLVED;
942 #if defined(ENABLE_VERIFIER)
950 /* method invocation **************************************************/
952 case JAVA_INVOKESTATIC:
953 i = code_get_u2(p + 1, m);
954 mr = class_getconstant(m->class, i, CONSTANT_Methodref);
958 md = mr->parseddesc.md;
961 if (!descriptor_params_from_paramtypes(md, ACC_STATIC))
966 case JAVA_INVOKEINTERFACE:
967 i = code_get_u2(p + 1, m);
969 mr = class_getconstant(m->class, i,
970 CONSTANT_InterfaceMethodref);
972 goto invoke_nonstatic_method;
974 case JAVA_INVOKESPECIAL:
975 case JAVA_INVOKEVIRTUAL:
976 i = code_get_u2(p + 1, m);
977 mr = class_getconstant(m->class, i, CONSTANT_Methodref);
979 invoke_nonstatic_method:
983 md = mr->parseddesc.md;
986 if (!descriptor_params_from_paramtypes(md, 0))
990 jd->isleafmethod = false;
992 NEW_OP_PREPARE_ZEROFLAGS(opcode);
993 iptr->sx.s23.s3.fmiref = mr;
995 /* only with -noverify, otherwise the typechecker does this */
997 #if defined(ENABLE_VERIFIER)
1000 result = new_resolve_method_lazy(iptr, NULL, m);
1001 if (result == resolveFailed)
1004 if (result != resolveSucceeded) {
1005 um = new_create_unresolved_method(m->class, m, iptr);
1010 /* store the unresolved_method pointer */
1012 iptr->sx.s23.s3.um = um;
1013 iptr->flags.bits = INS_FLAG_UNRESOLVED;
1015 #if defined(ENABLE_VERIFIER)
1021 /* instructions taking class arguments ********************************/
1024 i = code_get_u2(p + 1, m);
1025 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
1029 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
1032 NEW_OP_LOADCONST_CLASSINFO_OR_CLASSREF(c, cr, INS_FLAG_NOCHECK);
1033 bte = builtintable_get_internal(BUILTIN_new);
1034 NEW_OP_BUILTIN_CHECK_EXCEPTION(bte);
1038 case JAVA_CHECKCAST:
1039 i = code_get_u2(p + 1, m);
1040 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
1044 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
1047 if (cr->name->text[0] == '[') {
1048 /* array type cast-check */
1049 flags = INS_FLAG_ARRAY;
1050 jd->isleafmethod = false;
1053 /* object type cast-check */
1056 NEW_OP_S3_CLASSINFO_OR_CLASSREF(opcode, c, cr, flags);
1059 case JAVA_INSTANCEOF:
1060 i = code_get_u2(p + 1,m);
1061 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
1065 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
1068 if (cr->name->text[0] == '[') {
1069 /* array type cast-check */
1070 NEW_OP_LOADCONST_CLASSINFO_OR_CLASSREF(c, cr, INS_FLAG_NOCHECK);
1071 bte = builtintable_get_internal(BUILTIN_arrayinstanceof);
1072 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1076 /* object type cast-check */
1077 NEW_OP_S3_CLASSINFO_OR_CLASSREF(opcode, c, cr, 0 /* flags*/);
1081 /* synchronization instructions ***************************************/
1083 case JAVA_MONITORENTER:
1084 #if defined(ENABLE_THREADS)
1086 /* XXX null check */
1087 bte = builtintable_get_internal(BUILTIN_monitorenter);
1088 NEW_OP_BUILTIN_CHECK_EXCEPTION(bte);
1093 NEW_OP(ICMD_CHECKNULL_POP);
1097 case JAVA_MONITOREXIT:
1098 #if defined(ENABLE_THREADS)
1100 /* XXX null check */
1101 bte = builtintable_get_internal(BUILTIN_monitorexit);
1102 NEW_OP_BUILTIN_CHECK_EXCEPTION(bte);
1107 NEW_OP(ICMD_CHECKNULL_POP);
1111 /* arithmetic instructions that may become builtin functions **********/
1114 #if !SUPPORT_DIVISION
1115 bte = builtintable_get_internal(BUILTIN_idiv);
1116 NEW_OP_BUILTIN_ARITHMETIC(opcode, bte);
1123 #if !SUPPORT_DIVISION
1124 bte = builtintable_get_internal(BUILTIN_irem);
1125 NEW_OP_BUILTIN_ARITHMETIC(opcode, bte);
1132 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1133 bte = builtintable_get_internal(BUILTIN_ldiv);
1134 NEW_OP_BUILTIN_ARITHMETIC(opcode, bte);
1141 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1142 bte = builtintable_get_internal(BUILTIN_lrem);
1143 NEW_OP_BUILTIN_ARITHMETIC(opcode, bte);
1150 #if defined(__I386__)
1153 bte = builtintable_get_internal(BUILTIN_frem);
1154 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1159 #if defined(__I386__)
1162 bte = builtintable_get_internal(BUILTIN_drem);
1163 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1168 #if defined(__ALPHA__)
1170 bte = builtintable_get_internal(BUILTIN_f2i);
1171 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1181 #if defined(__ALPHA__)
1183 bte = builtintable_get_internal(BUILTIN_f2l);
1184 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1194 #if defined(__ALPHA__)
1196 bte = builtintable_get_internal(BUILTIN_d2i);
1197 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1207 #if defined(__ALPHA__)
1209 bte = builtintable_get_internal(BUILTIN_d2l);
1210 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1219 /* invalid opcodes ****************************************************/
1221 /* check for invalid opcodes if the verifier is enabled */
1222 #if defined(ENABLE_VERIFIER)
1223 case JAVA_BREAKPOINT:
1225 new_verifyerror(m, "Quick instructions shouldn't appear, yet.");
1228 case 186: /* unused opcode */
1283 new_verifyerror(m,"Illegal opcode %d at instr %d\n",
1287 #endif /* defined(ENABLE_VERIFIER) */
1289 /* opcodes that don't require translation *****************************/
1292 /* straight-forward translation to ICMD */
1298 /* verifier checks ****************************************************/
1300 #if defined(ENABLE_VERIFIER)
1301 /* If WIDE was used correctly, iswide should have been reset by now. */
1303 *exceptionptr = new_verifyerror(m,
1304 "Illegal instruction: WIDE before incompatible opcode");
1307 #endif /* defined(ENABLE_VERIFIER) */
1311 /*** END OF LOOP **********************************************************/
1313 /* assert that we did not write more ICMDs than allocated */
1315 assert(ipc == (iptr - jd->new_instructions));
1316 assert(ipc <= m->jcodelength);
1318 /*** verifier checks ******************************************************/
1320 #if defined(ENABLE_VERIFIER)
1321 if (p != m->jcodelength) {
1322 *exceptionptr = new_verifyerror(m,
1323 "Command-sequence crosses code-boundary");
1328 *exceptionptr = new_verifyerror(m, "Falling off the end of the code");
1331 #endif /* defined(ENABLE_VERIFIER) */
1333 /*** setup the methodinfo, allocate stack and basic blocks ****************/
1335 /* adjust block count if target 0 is not first intermediate instruction */
1337 if (!jd->new_basicblockindex[0] || (jd->new_basicblockindex[0] > 1))
1340 /* copy local to method variables */
1342 jd->new_instructioncount = ipc;
1343 jd->new_basicblockcount = b_count;
1344 jd->new_stackcount = s_count + jd->new_basicblockcount * m->maxstack; /* in-stacks */
1346 /* allocate stack table */
1348 jd->new_stack = DMNEW(stackelement, jd->new_stackcount);
1350 /* build basic block list */
1352 bptr = jd->new_basicblocks = DMNEW(basicblock, b_count + 1); /* one more for end ipc */
1355 jd->new_c_debug_nr = 0;
1357 /* additional block if target 0 is not first intermediate instruction */
1359 if (!jd->new_basicblockindex[0] || (jd->new_basicblockindex[0] > 1)) {
1360 BASICBLOCK_INIT(bptr, m);
1362 bptr->iinstr = /* XXX */ (instruction *) jd->new_instructions;
1363 /* bptr->icount is set when the next block is allocated */
1367 bptr[-1].next = bptr;
1370 /* allocate blocks */
1372 for (p = 0; p < m->jcodelength; p++) {
1373 if (jd->new_basicblockindex[p] & 1) {
1374 /* Check if this block starts at the beginning of an */
1376 #if defined(ENABLE_VERIFIER)
1377 if (!instructionstart[p]) {
1378 *exceptionptr = new_verifyerror(m,
1379 "Branch into middle of instruction");
1384 /* allocate the block */
1386 BASICBLOCK_INIT(bptr, m);
1388 bptr->iinstr = /* XXX */ (instruction *) (jd->new_instructions + (jd->new_basicblockindex[p] >> 1));
1390 bptr[-1].icount = /*XXX*/ (new_instruction *)bptr->iinstr - (new_instruction*) bptr[-1].iinstr;
1392 /* bptr->icount is set when the next block is allocated */
1394 jd->new_basicblockindex[p] = b_count;
1398 bptr[-1].next = bptr;
1402 /* set instruction count of last real block */
1405 bptr[-1].icount = (jd->new_instructions + jd->new_instructioncount) - /* XXX */ (new_instruction *) bptr[-1].iinstr;
1408 /* allocate additional block at end */
1410 BASICBLOCK_INIT(bptr,m);
1412 bptr->instack = bptr->outstack = NULL;
1413 bptr->indepth = bptr->outdepth = 0;
1414 bptr->iinstr = NULL;
1418 /* set basicblock pointers in exception table */
1420 if (cd->exceptiontablelength > 0) {
1421 cd->exceptiontable[cd->exceptiontablelength - 1].down = NULL;
1424 for (i = 0; i < cd->exceptiontablelength; ++i) {
1425 p = cd->exceptiontable[i].startpc;
1426 cd->exceptiontable[i].start = jd->new_basicblocks + jd->new_basicblockindex[p];
1428 p = cd->exceptiontable[i].endpc;
1429 cd->exceptiontable[i].end = (p == m->jcodelength) ? (jd->new_basicblocks + jd->new_basicblockcount /*+ 1*/) : (jd->new_basicblocks + jd->new_basicblockindex[p]);
1431 p = cd->exceptiontable[i].handlerpc;
1432 cd->exceptiontable[i].handler = jd->new_basicblocks + jd->new_basicblockindex[p];
1435 /* XXX activate this if you want to try inlining */
1437 for (i = 0; i < m->exceptiontablelength; ++i) {
1438 p = m->exceptiontable[i].startpc;
1439 m->exceptiontable[i].start = jd->new_basicblocks + jd->new_basicblockindex[p];
1441 p = m->exceptiontable[i].endpc;
1442 m->exceptiontable[i].end = (p == m->jcodelength) ? (jd->new_basicblocks + jd->new_basicblockcount /*+ 1*/) : (jd->new_basicblocks + jd->new_basicblockindex[p]);
1444 p = m->exceptiontable[i].handlerpc;
1445 m->exceptiontable[i].handler = jd->new_basicblocks + jd->new_basicblockindex[p];
1449 /* everything's ok */
1453 /*** goto labels for throwing verifier exceptions *************************/
1455 #if defined(ENABLE_VERIFIER)
1457 throw_unexpected_end_of_bytecode:
1458 *exceptionptr = new_verifyerror(m, "Unexpected end of bytecode");
1461 throw_invalid_bytecode_index:
1463 new_verifyerror(m, "Illegal target of branch instruction");
1466 throw_illegal_local_variable_number:
1468 new_verifyerror(m, "Illegal local variable number");
1471 #endif /* ENABLE_VERIFIER */
1475 bool parse(jitdata *jd)
1480 int p; /* java instruction counter */
1481 int nextp; /* start of next java instruction */
1482 int opcode; /* java opcode */
1483 int i; /* temporary for different uses (ctrs)*/
1484 int ipc = 0; /* intermediate instruction counter */
1485 int b_count = 0; /* basic block counter */
1486 int s_count = 0; /* stack element counter */
1487 bool blockend = false; /* true if basic block end has been reached */
1488 bool iswide = false; /* true if last instruction was a wide*/
1489 instruction *iptr; /* current ptr into instruction array */
1491 u1 *instructionstart; /* 1 for pcs which are valid instr. starts */
1493 constant_classref *cr;
1494 constant_classref *compr;
1496 builtintable_entry *bte;
1498 constant_FMIref *mr;
1500 unresolved_method *um;
1501 resolve_result_t result;
1505 u2 linepcchange = 0;
1507 /* get required compiler data */
1513 /* allocate instruction array and block index table */
1515 /* 1 additional for end ipc */
1516 m->basicblockindex = DMNEW(s4, m->jcodelength + 1);
1517 memset(m->basicblockindex, 0, sizeof(s4) * (m->jcodelength + 1));
1519 instructionstart = DMNEW(u1, m->jcodelength + 1);
1520 memset(instructionstart, 0, sizeof(u1) * (m->jcodelength + 1));
1522 /* 1 additional for TRACEBUILTIN and 4 for MONITORENTER/EXIT */
1523 /* additional MONITOREXITS are reached by branches which are 3 bytes */
1525 iptr = m->instructions = DMNEW(instruction, m->jcodelength + 5);
1527 /* Zero the intermediate instructions array so we don't have any
1528 * invalid pointers in it if we cannot finish analyse_stack(). */
1530 memset(iptr, 0, sizeof(instruction) * (m->jcodelength + 5));
1532 /* compute branch targets of exception table */
1535 &(cd->exceptiontable[cd->exceptiontablelength-1]),
1537 m->exceptiontablelength,
1543 s_count = 1 + m->exceptiontablelength; /* initialize stack element counter */
1545 #if defined(ENABLE_THREADS)
1546 if (checksync && (m->flags & ACC_SYNCHRONIZED))
1547 jd->isleafmethod = false;
1550 /* scan all java instructions */
1554 if (m->linenumbercount == 0) {
1558 linepcchange = m->linenumbers[0].start_pc;
1561 for (p = 0; p < m->jcodelength; p = nextp) {
1563 /* mark this position as a valid instruction start */
1564 instructionstart[p] = 1;
1565 if (linepcchange == p) {
1566 if (m->linenumbercount > lineindex) {
1568 currentline = m->linenumbers[lineindex].line_number;
1570 if (lineindex < m->linenumbercount) {
1571 linepcchange = m->linenumbers[lineindex].start_pc;
1572 if (linepcchange == p)
1573 goto next_linenumber;
1578 /* fetch next opcode */
1580 opcode = code_get_u1(p, m);
1582 m->basicblockindex[p] |= (ipc << 1); /*store intermed cnt*/
1584 /* some compilers put a JAVA_NOP after a blockend instruction */
1586 if (blockend && (opcode != JAVA_NOP)) {
1587 /* start new block */
1593 nextp = p + jcommandsize[opcode]; /* compute next instruction start */
1595 CHECK_END_OF_BYTECODE(nextp);
1597 s_count += stackreq[opcode]; /* compute stack element count */
1602 /* pushing constants onto the stack p */
1605 LOADCONST_I(code_get_s1(p+1,m));
1609 LOADCONST_I(code_get_s2(p+1,m));
1613 i = code_get_u1(p + 1, m);
1614 goto pushconstantitem;
1618 i = code_get_u2(p + 1, m);
1622 #if defined(ENABLE_VERIFIER)
1623 if (i >= m->class->cpcount) {
1624 *exceptionptr = new_verifyerror(m,
1625 "Attempt to access constant outside range");
1630 switch (m->class->cptags[i]) {
1631 case CONSTANT_Integer:
1632 LOADCONST_I(((constant_integer *) (m->class->cpinfos[i]))->value);
1635 LOADCONST_L(((constant_long *) (m->class->cpinfos[i]))->value);
1637 case CONSTANT_Float:
1638 LOADCONST_F(((constant_float *) (m->class->cpinfos[i]))->value);
1640 case CONSTANT_Double:
1641 LOADCONST_D(((constant_double *) (m->class->cpinfos[i]))->value);
1643 case CONSTANT_String:
1644 LOADCONST_A(literalstring_new((utf *) (m->class->cpinfos[i])));
1646 case CONSTANT_Class:
1647 cr = (constant_classref *) (m->class->cpinfos[i]);
1649 if (!resolve_classref(m, cr, resolveLazy, true,
1653 /* if not resolved, c == NULL */
1656 iptr->target = (void*) 0x02; /* XXX target used temporarily as flag */
1660 iptr->target = (void*) 0x03; /* XXX target used temporarily as flag */
1665 #if defined(ENABLE_VERIFIER)
1667 *exceptionptr = new_verifyerror(m,
1668 "Invalid constant type to push");
1674 case JAVA_ACONST_NULL:
1678 case JAVA_ICONST_M1:
1685 LOADCONST_I(opcode - JAVA_ICONST_0);
1690 LOADCONST_L(opcode - JAVA_LCONST_0);
1696 LOADCONST_F(opcode - JAVA_FCONST_0);
1701 LOADCONST_D(opcode - JAVA_DCONST_0);
1704 /* loading variables onto the stack */
1710 i = code_get_u1(p + 1,m);
1713 i = code_get_u2(p + 1,m);
1717 OP1LOAD_ONEWORD(opcode, i);
1723 i = code_get_u1(p + 1,m);
1726 i = code_get_u2(p + 1,m);
1730 OP1LOAD_TWOWORD(opcode, i);
1737 OP1LOAD_ONEWORD(ICMD_ILOAD, opcode - JAVA_ILOAD_0);
1744 OP1LOAD_TWOWORD(ICMD_LLOAD, opcode - JAVA_LLOAD_0);
1751 OP1LOAD_ONEWORD(ICMD_FLOAD, opcode - JAVA_FLOAD_0);
1758 OP1LOAD_TWOWORD(ICMD_DLOAD, opcode - JAVA_DLOAD_0);
1765 OP1LOAD_ONEWORD(ICMD_ALOAD, opcode - JAVA_ALOAD_0);
1768 /* storing stack values into local variables */
1774 i = code_get_u1(p + 1,m);
1777 i = code_get_u2(p + 1,m);
1781 OP1STORE_ONEWORD(opcode, i);
1787 i = code_get_u1(p + 1,m);
1790 i = code_get_u2(p + 1,m);
1794 OP1STORE_TWOWORD(opcode, i);
1801 OP1STORE_ONEWORD(ICMD_ISTORE, opcode - JAVA_ISTORE_0);
1808 OP1STORE_TWOWORD(ICMD_LSTORE, opcode - JAVA_LSTORE_0);
1815 OP1STORE_ONEWORD(ICMD_FSTORE, opcode - JAVA_FSTORE_0);
1822 OP1STORE_TWOWORD(ICMD_DSTORE, opcode - JAVA_DSTORE_0);
1829 OP1STORE_ONEWORD(ICMD_ASTORE, opcode - JAVA_ASTORE_0);
1837 i = code_get_u1(p + 1,m);
1838 v = code_get_s1(p + 2,m);
1842 i = code_get_u2(p + 1,m);
1843 v = code_get_s2(p + 3,m);
1852 /* wider index for loading, storing and incrementing */
1859 /* managing arrays ****************************************************/
1862 switch (code_get_s1(p + 1, m)) {
1864 bte = builtintable_get_internal(BUILTIN_newarray_boolean);
1867 bte = builtintable_get_internal(BUILTIN_newarray_char);
1870 bte = builtintable_get_internal(BUILTIN_newarray_float);
1873 bte = builtintable_get_internal(BUILTIN_newarray_double);
1876 bte = builtintable_get_internal(BUILTIN_newarray_byte);
1879 bte = builtintable_get_internal(BUILTIN_newarray_short);
1882 bte = builtintable_get_internal(BUILTIN_newarray_int);
1885 bte = builtintable_get_internal(BUILTIN_newarray_long);
1887 #if defined(ENABLE_VERIFIER)
1889 *exceptionptr = new_verifyerror(m,
1890 "Invalid array-type to create");
1894 BUILTIN(bte, true, NULL, currentline);
1897 case JAVA_ANEWARRAY:
1898 i = code_get_u2(p + 1, m);
1899 compr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
1903 if (!(cr = class_get_classref_multiarray_of(1, compr)))
1906 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
1909 LOADCONST_A_BUILTIN(c, cr);
1910 bte = builtintable_get_internal(BUILTIN_newarray);
1911 BUILTIN(bte, true, NULL, currentline);
1915 case JAVA_MULTIANEWARRAY:
1916 jd->isleafmethod = false;
1917 i = code_get_u2(p + 1, m);
1919 s4 v = code_get_u1(p + 3, m);
1921 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
1925 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
1928 /* if unresolved, c == NULL */
1929 OP2AT(opcode, v, c, cr, currentline);
1940 case JAVA_IFNONNULL:
1941 case JAVA_IF_ICMPEQ:
1942 case JAVA_IF_ICMPNE:
1943 case JAVA_IF_ICMPLT:
1944 case JAVA_IF_ICMPGT:
1945 case JAVA_IF_ICMPLE:
1946 case JAVA_IF_ICMPGE:
1947 case JAVA_IF_ACMPEQ:
1948 case JAVA_IF_ACMPNE:
1951 i = p + code_get_s2(p + 1,m);
1952 CHECK_BYTECODE_INDEX(i);
1960 i = p + code_get_s4(p + 1,m);
1961 CHECK_BYTECODE_INDEX(i);
1969 i = code_get_u1(p + 1,m);
1972 i = code_get_u2(p + 1,m);
1978 OP1LOAD_ONEWORD(opcode, i);
1988 /* zero val.a so no patcher is inserted */
1989 /* the type checker may set this later */
1996 /* zero val.a so no patcher is inserted */
1997 /* the type checker may set this later */
2003 /* table jumps ********************************************************/
2005 case JAVA_LOOKUPSWITCH:
2009 #if defined(ENABLE_VERIFIER)
2014 nextp = ALIGN((p + 1), 4);
2016 CHECK_END_OF_BYTECODE(nextp + 8);
2018 tablep = (s4 *) (m->jcode + nextp);
2020 OP2A(opcode, 0, tablep, currentline);
2022 /* default target */
2024 j = p + code_get_s4(nextp, m);
2025 *tablep = j; /* restore for little endian */
2028 CHECK_BYTECODE_INDEX(j);
2031 /* number of pairs */
2033 num = code_get_u4(nextp, m);
2038 CHECK_END_OF_BYTECODE(nextp + 8 * num);
2040 for (i = 0; i < num; i++) {
2043 j = code_get_s4(nextp, m);
2044 *tablep = j; /* restore for little endian */
2048 #if defined(ENABLE_VERIFIER)
2049 /* check if the lookup table is sorted correctly */
2051 if (i && (j <= prevvalue)) {
2052 *exceptionptr = new_verifyerror(m, "Unsorted lookup switch");
2060 j = p + code_get_s4(nextp,m);
2061 *tablep = j; /* restore for little endian */
2064 CHECK_BYTECODE_INDEX(j);
2072 case JAVA_TABLESWITCH:
2078 nextp = ALIGN((p + 1), 4);
2080 CHECK_END_OF_BYTECODE(nextp + 12);
2082 tablep = (s4 *) (m->jcode + nextp);
2084 OP2A(opcode, 0, tablep, currentline);
2086 /* default target */
2088 j = p + code_get_s4(nextp, m);
2089 *tablep = j; /* restore for little endian */
2092 CHECK_BYTECODE_INDEX(j);
2097 j = code_get_s4(nextp, m);
2098 *tablep = j; /* restore for little endian */
2104 num = code_get_s4(nextp, m);
2105 *tablep = num; /* restore for little endian */
2109 num -= j; /* difference of upper - lower */
2111 #if defined(ENABLE_VERIFIER)
2113 *exceptionptr = new_verifyerror(m,
2114 "invalid TABLESWITCH: upper bound < lower bound");
2119 CHECK_END_OF_BYTECODE(nextp + 4 * (num + 1));
2121 for (i = 0; i <= num; i++) {
2122 j = p + code_get_s4(nextp,m);
2123 *tablep = j; /* restore for little endian */
2126 CHECK_BYTECODE_INDEX(j);
2134 /* load and store of object fields ************************************/
2138 jd->isleafmethod = false;
2141 case JAVA_GETSTATIC:
2142 case JAVA_PUTSTATIC:
2146 constant_FMIref *fr;
2147 unresolved_field *uf;
2149 i = code_get_u2(p + 1, m);
2150 fr = class_getconstant(m->class, i,
2155 OP2A_NOINC(opcode, fr->parseddesc.fd->type, fr, currentline);
2157 /* only with -noverify, otherwise the typechecker does this */
2159 #if defined(ENABLE_VERIFIER)
2162 result = resolve_field_lazy(iptr,NULL,m);
2163 if (result == resolveFailed)
2166 if (result != resolveSucceeded) {
2167 uf = create_unresolved_field(m->class,
2173 /* store the unresolved_field pointer */
2175 /* XXX this will be changed */
2177 iptr->target = (void*) 0x01; /* XXX target temporarily used as flag */
2180 iptr->target = NULL;
2182 #if defined(ENABLE_VERIFIER)
2185 iptr->target = NULL;
2193 /* method invocation **************************************************/
2195 case JAVA_INVOKESTATIC:
2196 i = code_get_u2(p + 1, m);
2197 mr = class_getconstant(m->class, i,
2198 CONSTANT_Methodref);
2202 md = mr->parseddesc.md;
2205 if (!descriptor_params_from_paramtypes(md, ACC_STATIC))
2210 case JAVA_INVOKEINTERFACE:
2211 i = code_get_u2(p + 1, m);
2213 mr = class_getconstant(m->class, i,
2214 CONSTANT_InterfaceMethodref);
2216 goto invoke_nonstatic_method;
2218 case JAVA_INVOKESPECIAL:
2219 case JAVA_INVOKEVIRTUAL:
2220 i = code_get_u2(p + 1, m);
2221 mr = class_getconstant(m->class, i,
2222 CONSTANT_Methodref);
2224 invoke_nonstatic_method:
2228 md = mr->parseddesc.md;
2231 if (!descriptor_params_from_paramtypes(md, 0))
2235 jd->isleafmethod = false;
2237 OP2A_NOINC(opcode, 0, mr, currentline);
2239 /* only with -noverify, otherwise the typechecker does this */
2241 #if defined(ENABLE_VERIFIER)
2244 result = resolve_method_lazy(iptr,NULL,m);
2245 if (result == resolveFailed)
2248 if (result != resolveSucceeded) {
2249 um = create_unresolved_method(m->class,
2255 /* store the unresolved_method pointer */
2257 /* XXX this will be changed */
2259 iptr->target = (void*) 0x01; /* XXX target temporarily used as flag */
2262 /* the method could be resolved */
2263 iptr->target = NULL;
2265 #if defined(ENABLE_VERIFIER)
2268 iptr->target = NULL;
2274 /* miscellaneous object operations ************************************/
2277 i = code_get_u2(p + 1, m);
2278 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
2282 if (!resolve_classref(m, cr, resolveLazy, true, true,
2286 LOADCONST_A_BUILTIN(c, cr);
2287 bte = builtintable_get_internal(BUILTIN_new);
2288 BUILTIN(bte, true, NULL, currentline);
2292 case JAVA_CHECKCAST:
2293 i = code_get_u2(p + 1, m);
2294 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
2298 if (!resolve_classref(m, cr, resolveLazy, true,
2302 if (cr->name->text[0] == '[') {
2303 /* array type cast-check */
2304 OP2AT(opcode, 0, c, cr, currentline);
2305 jd->isleafmethod = false;
2309 /* object type cast-check */
2310 OP2AT(opcode, 1, c, cr, currentline);
2314 case JAVA_INSTANCEOF:
2315 i = code_get_u2(p + 1,m);
2316 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
2320 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
2323 if (cr->name->text[0] == '[') {
2324 /* array type cast-check */
2325 LOADCONST_A_BUILTIN(c, cr);
2326 bte = builtintable_get_internal(BUILTIN_arrayinstanceof);
2327 BUILTIN(bte, false, NULL, currentline);
2332 /* object type cast-check */
2333 OP2AT(opcode, 1, c, cr, currentline);
2337 case JAVA_MONITORENTER:
2338 #if defined(ENABLE_THREADS)
2341 bte = builtintable_get_internal(BUILTIN_monitorenter);
2342 BUILTIN(bte, false, NULL, currentline);
2352 case JAVA_MONITOREXIT:
2353 #if defined(ENABLE_THREADS)
2355 bte = builtintable_get_internal(BUILTIN_monitorexit);
2356 BUILTIN(bte, false, NULL, currentline);
2365 /* any other basic operation ******************************************/
2368 #if !SUPPORT_DIVISION
2369 bte = builtintable_get_internal(BUILTIN_idiv);
2370 OP2A(opcode, bte->md->paramcount, bte, currentline);
2371 jd->isleafmethod = false;
2378 #if !SUPPORT_DIVISION
2379 bte = builtintable_get_internal(BUILTIN_irem);
2380 OP2A(opcode, bte->md->paramcount, bte, currentline);
2381 jd->isleafmethod = false;
2388 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
2389 bte = builtintable_get_internal(BUILTIN_ldiv);
2390 OP2A(opcode, bte->md->paramcount, bte, currentline);
2391 jd->isleafmethod = false;
2398 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
2399 bte = builtintable_get_internal(BUILTIN_lrem);
2400 OP2A(opcode, bte->md->paramcount, bte, currentline);
2401 jd->isleafmethod = false;
2408 #if defined(__I386__)
2411 bte = builtintable_get_internal(BUILTIN_frem);
2412 BUILTIN(bte, false, NULL, currentline);
2417 #if defined(__I386__)
2420 bte = builtintable_get_internal(BUILTIN_drem);
2421 BUILTIN(bte, false, NULL, currentline);
2426 #if defined(__ALPHA__)
2428 bte = builtintable_get_internal(BUILTIN_f2i);
2429 BUILTIN(bte, false, NULL, currentline);
2439 #if defined(__ALPHA__)
2441 bte = builtintable_get_internal(BUILTIN_f2l);
2442 BUILTIN(bte, false, NULL, currentline);
2452 #if defined(__ALPHA__)
2454 bte = builtintable_get_internal(BUILTIN_d2i);
2455 BUILTIN(bte, false, NULL, currentline);
2465 #if defined(__ALPHA__)
2467 bte = builtintable_get_internal(BUILTIN_d2l);
2468 BUILTIN(bte, false, NULL, currentline);
2477 /* check for invalid opcodes if the verifier is enabled */
2478 #if defined(ENABLE_VERIFIER)
2479 case JAVA_BREAKPOINT:
2481 new_verifyerror(m, "Quick instructions shouldn't appear yet.");
2484 case 186: /* unused opcode */
2539 new_verifyerror(m,"Illegal opcode %d at instr %d\n",
2543 #endif /* defined(ENABLE_VERIFIER) */
2546 /* straight-forward translation to ICMD */
2552 #if defined(ENABLE_VERIFIER)
2553 /* If WIDE was used correctly, iswide should have been reset by now. */
2555 *exceptionptr = new_verifyerror(m,
2556 "Illegal instruction: WIDE before incompatible opcode");
2559 #endif /* defined(ENABLE_VERIFIER) */
2563 #if defined(ENABLE_VERIFIER)
2564 if (p != m->jcodelength) {
2565 *exceptionptr = new_verifyerror(m,
2566 "Command-sequence crosses code-boundary");
2571 *exceptionptr = new_verifyerror(m, "Falling off the end of the code");
2574 #endif /* defined(ENABLE_VERIFIER) */
2576 /* adjust block count if target 0 is not first intermediate instruction */
2578 if (!m->basicblockindex[0] || (m->basicblockindex[0] > 1))
2581 /* copy local to method variables */
2583 m->instructioncount = ipc;
2584 m->basicblockcount = b_count;
2585 m->stackcount = s_count + m->basicblockcount * m->maxstack;
2587 /* allocate stack table */
2589 m->stack = DMNEW(stackelement, m->stackcount);
2594 bptr = m->basicblocks = DMNEW(basicblock, b_count + 1); /* one more for end ipc */
2599 /* additional block if target 0 is not first intermediate instruction */
2601 if (!m->basicblockindex[0] || (m->basicblockindex[0] > 1)) {
2602 BASICBLOCK_INIT(bptr,m);
2604 bptr->iinstr = m->instructions;
2605 /* bptr->icount is set when the next block is allocated */
2609 bptr[-1].next = bptr;
2612 /* allocate blocks */
2614 for (p = 0; p < m->jcodelength; p++) {
2615 if (m->basicblockindex[p] & 1) {
2616 /* Check if this block starts at the beginning of an */
2618 #if defined(ENABLE_VERIFIER)
2619 if (!instructionstart[p]) {
2620 *exceptionptr = new_verifyerror(m,
2621 "Branch into middle of instruction");
2626 /* allocate the block */
2628 BASICBLOCK_INIT(bptr,m);
2630 bptr->iinstr = m->instructions + (m->basicblockindex[p] >> 1);
2632 bptr[-1].icount = bptr->iinstr - bptr[-1].iinstr;
2634 /* bptr->icount is set when the next block is allocated */
2636 m->basicblockindex[p] = b_count;
2640 bptr[-1].next = bptr;
2644 /* set instruction count of last real block */
2647 bptr[-1].icount = (m->instructions + m->instructioncount) - bptr[-1].iinstr;
2650 /* allocate additional block at end */
2652 BASICBLOCK_INIT(bptr,m);
2654 bptr->instack = bptr->outstack = NULL;
2655 bptr->indepth = bptr->outdepth = 0;
2656 bptr->iinstr = NULL;
2660 /* set basicblock pointers in exception table */
2662 if (cd->exceptiontablelength > 0) {
2663 cd->exceptiontable[cd->exceptiontablelength - 1].down = NULL;
2666 for (i = 0; i < cd->exceptiontablelength; ++i) {
2667 p = cd->exceptiontable[i].startpc;
2668 cd->exceptiontable[i].start = m->basicblocks + m->basicblockindex[p];
2670 p = cd->exceptiontable[i].endpc;
2671 cd->exceptiontable[i].end = (p == m->jcodelength) ? (m->basicblocks + m->basicblockcount /*+ 1*/) : (m->basicblocks + m->basicblockindex[p]);
2673 p = cd->exceptiontable[i].handlerpc;
2674 cd->exceptiontable[i].handler = m->basicblocks + m->basicblockindex[p];
2677 /* XXX activate this if you want to try inlining */
2679 for (i = 0; i < m->exceptiontablelength; ++i) {
2680 p = m->exceptiontable[i].startpc;
2681 m->exceptiontable[i].start = m->basicblocks + m->basicblockindex[p];
2683 p = m->exceptiontable[i].endpc;
2684 m->exceptiontable[i].end = (p == m->jcodelength) ? (m->basicblocks + m->basicblockcount /*+ 1*/) : (m->basicblocks + m->basicblockindex[p]);
2686 p = m->exceptiontable[i].handlerpc;
2687 m->exceptiontable[i].handler = m->basicblocks + m->basicblockindex[p];
2693 /* everything's ok */
2697 #if defined(ENABLE_VERIFIER)
2699 throw_unexpected_end_of_bytecode:
2700 *exceptionptr = new_verifyerror(m, "Unexpected end of bytecode");
2703 throw_invalid_bytecode_index:
2705 new_verifyerror(m, "Illegal target of branch instruction");
2708 throw_illegal_local_variable_number:
2710 new_verifyerror(m, "Illegal local variable number");
2713 #endif /* ENABLE_VERIFIER */
2718 * These are local overrides for various environment variables in Emacs.
2719 * Please do not remove this and leave it at the end of the file, where
2720 * Emacs will automagically detect them.
2721 * ---------------------------------------------------------------------
2724 * indent-tabs-mode: t
2728 * vim:noexpandtab:sw=4:ts=4: