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 5134 2006-07-14 17:02:24Z 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"
63 #include "vm/jit/asmpart.h"
64 #include "vm/jit/jit.h"
65 #include "vm/jit/parse.h"
66 #include "vm/jit/patcher.h"
67 #include "vm/jit/loop/loop.h"
69 /*******************************************************************************
71 function 'parse' scans the JavaVM code and generates intermediate code
73 During parsing the block index table is used to store at bit pos 0
74 a flag which marks basic block starts and at position 1 to 31 the
75 intermediate instruction index. After parsing the block index table
76 is scanned, for marked positions a block is generated and the block
77 number is stored in the block index table.
79 *******************************************************************************/
81 static exceptiontable * new_fillextable(
84 exceptiontable *extable,
85 exceptiontable *raw_extable,
86 int exceptiontablelength,
91 if (exceptiontablelength == 0)
94 b_count = *block_count;
96 for (src = exceptiontablelength-1; src >=0; src--) {
97 /* the start of the handled region becomes a basic block start */
98 p = raw_extable[src].startpc;
99 CHECK_BYTECODE_INDEX(p);
100 extable->startpc = p;
103 p = raw_extable[src].endpc; /* see JVM Spec 4.7.3 */
104 CHECK_BYTECODE_INDEX_EXCLUSIVE(p);
106 #if defined(ENABLE_VERIFIER)
107 if (p <= raw_extable[src].startpc) {
108 *exceptionptr = new_verifyerror(m,
109 "Invalid exception handler range");
115 /* end of handled region becomes a basic block boundary */
116 /* (If it is the bytecode end, we'll use the special */
117 /* end block that is created anyway.) */
118 if (p < m->jcodelength)
121 /* the start of the handler becomes a basic block start */
122 p = raw_extable[src].handlerpc;
123 CHECK_BYTECODE_INDEX(p);
124 extable->handlerpc = p;
127 extable->catchtype = raw_extable[src].catchtype;
128 extable->next = NULL;
129 extable->down = &extable[1];
133 *block_count = b_count;
138 #if defined(ENABLE_VERIFIER)
139 throw_invalid_bytecode_index:
141 new_verifyerror(m, "Illegal bytecode index in exception table");
146 static exceptiontable * fillextable(methodinfo *m,
147 exceptiontable *extable,
148 exceptiontable *raw_extable,
149 int exceptiontablelength,
154 if (exceptiontablelength == 0)
157 b_count = *block_count;
159 for (src = exceptiontablelength-1; src >=0; src--) {
160 /* the start of the handled region becomes a basic block start */
161 p = raw_extable[src].startpc;
162 CHECK_BYTECODE_INDEX(p);
163 extable->startpc = p;
166 p = raw_extable[src].endpc; /* see JVM Spec 4.7.3 */
167 CHECK_BYTECODE_INDEX_EXCLUSIVE(p);
169 #if defined(ENABLE_VERIFIER)
170 if (p <= raw_extable[src].startpc) {
171 *exceptionptr = new_verifyerror(m,
172 "Invalid exception handler range");
178 /* end of handled region becomes a basic block boundary */
179 /* (If it is the bytecode end, we'll use the special */
180 /* end block that is created anyway.) */
181 if (p < m->jcodelength)
184 /* the start of the handler becomes a basic block start */
185 p = raw_extable[src].handlerpc;
186 CHECK_BYTECODE_INDEX(p);
187 extable->handlerpc = p;
190 extable->catchtype = raw_extable[src].catchtype;
191 extable->next = NULL;
192 extable->down = &extable[1];
196 *block_count = b_count;
201 #if defined(ENABLE_VERIFIER)
202 throw_invalid_bytecode_index:
204 new_verifyerror(m, "Illegal bytecode index in exception table");
209 /*** macro for checking the length of the bytecode ***/
211 #if defined(ENABLE_VERIFIER)
212 #define CHECK_END_OF_BYTECODE(neededlength) \
214 if ((neededlength) > m->jcodelength) \
215 goto throw_unexpected_end_of_bytecode; \
217 #else /* !ENABLE_VERIFIER */
218 #define CHECK_END_OF_BYTECODE(neededlength)
219 #endif /* ENABLE_VERIFIER */
221 bool new_parse(jitdata *jd)
223 methodinfo *m; /* method being parsed */
226 int p; /* java instruction counter */
227 int nextp; /* start of next java instruction */
228 int opcode; /* java opcode */
229 int i; /* temporary for different uses (ctrs) */
230 int ipc = 0; /* intermediate instruction counter */
231 int b_count = 0; /* basic block counter */
232 int s_count = 0; /* stack element counter */
233 bool blockend = false; /* true if basic block end has been reached */
234 bool iswide = false; /* true if last instruction was a wide */
235 new_instruction *iptr; /* current ptr into instruction array */
236 u1 *instructionstart; /* 1 for pcs which are valid instr. starts */
237 constant_classref *cr;
238 constant_classref *compr;
240 builtintable_entry *bte;
243 unresolved_method *um;
244 resolve_result_t result;
251 /* get required compiler data */
257 /* allocate instruction array and block index table */
259 /* 1 additional for end ipc */
260 jd->new_basicblockindex = DMNEW(s4, m->jcodelength + 1);
261 memset(jd->new_basicblockindex, 0, sizeof(s4) * (m->jcodelength + 1));
263 instructionstart = DMNEW(u1, m->jcodelength + 1);
264 memset(instructionstart, 0, sizeof(u1) * (m->jcodelength + 1));
266 /* IMPORTANT: We assume that parsing creates at most one instruction per */
267 /* byte of original bytecode! */
269 iptr = jd->new_instructions = DMNEW(new_instruction, m->jcodelength);
271 /* compute branch targets of exception table */
273 if (!new_fillextable(jd, m,
274 &(cd->exceptiontable[cd->exceptiontablelength-1]),
276 m->exceptiontablelength,
282 s_count = 1 + m->exceptiontablelength; /* initialize stack element counter */
284 #if defined(ENABLE_THREADS)
285 if (checksync && (m->flags & ACC_SYNCHRONIZED))
286 jd->isleafmethod = false;
289 /* setup line number info */
294 if (m->linenumbercount == 0) {
298 linepcchange = m->linenumbers[0].start_pc;
301 /*** LOOP OVER ALL BYTECODE INSTRUCTIONS **********************************/
303 for (p = 0; p < m->jcodelength; p = nextp) {
305 /* mark this position as a valid instruction start */
307 instructionstart[p] = 1;
309 /* change the current line number, if necessary */
311 /* XXX rewrite this using pointer arithmetic */
313 if (linepcchange == p) {
314 if (m->linenumbercount > lineindex) {
316 currentline = m->linenumbers[lineindex].line_number;
318 if (lineindex < m->linenumbercount) {
319 linepcchange = m->linenumbers[lineindex].start_pc;
320 if (linepcchange == p)
321 goto next_linenumber;
326 /* fetch next opcode */
328 opcode = code_get_u1(p, m);
330 /* store intermediate instruction count (bit 0 mark block starts) */
332 jd->new_basicblockindex[p] |= (ipc << 1);
334 /* some compilers put a JAVA_NOP after a blockend instruction */
336 if (blockend && (opcode != JAVA_NOP)) {
337 /* start new block */
343 /* compute next instruction start */
345 nextp = p + jcommandsize[opcode];
347 CHECK_END_OF_BYTECODE(nextp);
349 /* add stack elements produced by this instruction */
351 s_count += stackreq[opcode];
353 /* translate this bytecode instruction */
360 /* pushing constants onto the stack ***********************************/
363 NEW_OP_LOADCONST_I(code_get_s1(p+1,m));
367 NEW_OP_LOADCONST_I(code_get_s2(p+1,m));
371 i = code_get_u1(p + 1, m);
372 goto pushconstantitem;
376 i = code_get_u2(p + 1, m);
380 #if defined(ENABLE_VERIFIER)
381 if (i >= m->class->cpcount) {
382 *exceptionptr = new_verifyerror(m,
383 "Attempt to access constant outside range");
388 switch (m->class->cptags[i]) {
389 case CONSTANT_Integer:
390 NEW_OP_LOADCONST_I(((constant_integer *) (m->class->cpinfos[i]))->value);
393 NEW_OP_LOADCONST_L(((constant_long *) (m->class->cpinfos[i]))->value);
396 NEW_OP_LOADCONST_F(((constant_float *) (m->class->cpinfos[i]))->value);
398 case CONSTANT_Double:
399 NEW_OP_LOADCONST_D(((constant_double *) (m->class->cpinfos[i]))->value);
401 case CONSTANT_String:
402 NEW_OP_LOADCONST_STRING(literalstring_new((utf *) (m->class->cpinfos[i])));
405 cr = (constant_classref *) (m->class->cpinfos[i]);
407 if (!resolve_classref(m, cr, resolveLazy, true,
411 /* if not resolved, c == NULL */
413 NEW_OP_LOADCONST_CLASSINFO_OR_CLASSREF(c, cr, 0 /* no extra flags */);
417 #if defined(ENABLE_VERIFIER)
419 *exceptionptr = new_verifyerror(m,
420 "Invalid constant type to push");
426 case JAVA_ACONST_NULL:
427 NEW_OP_LOADCONST_NULL();
437 NEW_OP_LOADCONST_I(opcode - JAVA_ICONST_0);
442 NEW_OP_LOADCONST_L(opcode - JAVA_LCONST_0);
448 NEW_OP_LOADCONST_F(opcode - JAVA_FCONST_0);
453 NEW_OP_LOADCONST_D(opcode - JAVA_DCONST_0);
456 /* local variable access instructions *********************************/
462 i = code_get_u1(p + 1,m);
465 i = code_get_u2(p + 1,m);
469 NEW_OP_LOAD_ONEWORD(opcode, i);
475 i = code_get_u1(p + 1,m);
478 i = code_get_u2(p + 1,m);
482 NEW_OP_LOAD_TWOWORD(opcode, i);
489 NEW_OP_LOAD_ONEWORD(ICMD_ILOAD, opcode - JAVA_ILOAD_0);
496 NEW_OP_LOAD_TWOWORD(ICMD_LLOAD, opcode - JAVA_LLOAD_0);
503 NEW_OP_LOAD_ONEWORD(ICMD_FLOAD, opcode - JAVA_FLOAD_0);
510 NEW_OP_LOAD_TWOWORD(ICMD_DLOAD, opcode - JAVA_DLOAD_0);
517 NEW_OP_LOAD_ONEWORD(ICMD_ALOAD, opcode - JAVA_ALOAD_0);
524 i = code_get_u1(p + 1,m);
527 i = code_get_u2(p + 1,m);
531 NEW_OP_STORE_ONEWORD(opcode, i);
537 i = code_get_u1(p + 1,m);
540 i = code_get_u2(p + 1,m);
544 NEW_OP_STORE_TWOWORD(opcode, i);
551 NEW_OP_STORE_ONEWORD(ICMD_ISTORE, opcode - JAVA_ISTORE_0);
558 NEW_OP_STORE_TWOWORD(ICMD_LSTORE, opcode - JAVA_LSTORE_0);
565 NEW_OP_STORE_ONEWORD(ICMD_FSTORE, opcode - JAVA_FSTORE_0);
572 NEW_OP_STORE_TWOWORD(ICMD_DSTORE, opcode - JAVA_DSTORE_0);
579 NEW_OP_STORE_ONEWORD(ICMD_ASTORE, opcode - JAVA_ASTORE_0);
587 i = code_get_u1(p + 1,m);
588 v = code_get_s1(p + 2,m);
592 i = code_get_u2(p + 1,m);
593 v = code_get_s2(p + 3,m);
598 NEW_OP_LOCALINDEX_I(opcode, i, v);
602 /* wider index for loading, storing and incrementing ******************/
609 /* managing arrays ****************************************************/
612 switch (code_get_s1(p + 1, m)) {
614 bte = builtintable_get_internal(BUILTIN_newarray_boolean);
617 bte = builtintable_get_internal(BUILTIN_newarray_char);
620 bte = builtintable_get_internal(BUILTIN_newarray_float);
623 bte = builtintable_get_internal(BUILTIN_newarray_double);
626 bte = builtintable_get_internal(BUILTIN_newarray_byte);
629 bte = builtintable_get_internal(BUILTIN_newarray_short);
632 bte = builtintable_get_internal(BUILTIN_newarray_int);
635 bte = builtintable_get_internal(BUILTIN_newarray_long);
637 #if defined(ENABLE_VERIFIER)
639 *exceptionptr = new_verifyerror(m,
640 "Invalid array-type to create");
644 NEW_OP_BUILTIN_CHECK_EXCEPTION(bte);
648 i = code_get_u2(p + 1, m);
649 compr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
653 if (!(cr = class_get_classref_multiarray_of(1, compr)))
656 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
659 NEW_OP_LOADCONST_CLASSINFO_OR_CLASSREF(c, cr, INS_FLAG_NOCHECK);
660 bte = builtintable_get_internal(BUILTIN_newarray);
661 NEW_OP_BUILTIN_CHECK_EXCEPTION(bte);
665 case JAVA_MULTIANEWARRAY:
666 jd->isleafmethod = false;
667 i = code_get_u2(p + 1, m);
669 s4 v = code_get_u1(p + 3, m);
671 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
675 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
678 /* if unresolved, c == NULL */
680 iptr->s1.argcount = v;
681 NEW_OP_S3_CLASSINFO_OR_CLASSREF(opcode, c, cr, 0 /* flags */);
685 /* control flow instructions ******************************************/
704 i = p + code_get_s2(p + 1,m);
705 CHECK_BYTECODE_INDEX(i);
708 NEW_OP_INSINDEX(opcode, i);
712 i = p + code_get_s4(p + 1,m);
713 CHECK_BYTECODE_INDEX(i);
716 NEW_OP_INSINDEX(opcode, i);
720 i = p + code_get_s2(p + 1,m);
722 CHECK_BYTECODE_INDEX(i);
725 NEW_OP_PREPARE_ZEROFLAGS(JAVA_JSR);
726 iptr->sx.s23.s3.jsrtarget.insindex = i;
731 i = p + code_get_s4(p + 1,m);
736 i = code_get_u1(p + 1,m);
739 i = code_get_u2(p + 1,m);
745 NEW_OP_LOAD_ONEWORD(opcode, i);
755 /* XXX ARETURN will need a flag in the typechecker */
761 /* XXX ATHROW will need a flag in the typechecker */
766 /* table jumps ********************************************************/
768 case JAVA_LOOKUPSWITCH:
771 lookup_target_t *lookup;
772 #if defined(ENABLE_VERIFIER)
776 nextp = ALIGN((p + 1), 4);
778 CHECK_END_OF_BYTECODE(nextp + 8);
780 NEW_OP_PREPARE_ZEROFLAGS(opcode);
784 j = p + code_get_s4(nextp, m);
785 iptr->sx.s23.s3.lookupdefault.insindex = j;
787 CHECK_BYTECODE_INDEX(j);
790 /* number of pairs */
792 num = code_get_u4(nextp, m);
793 iptr->sx.s23.s2.lookupcount = num;
796 /* allocate the intermediate code table */
798 lookup = DMNEW(lookup_target_t, num);
799 iptr->dst.lookup = lookup;
801 /* iterate over the lookup table */
803 CHECK_END_OF_BYTECODE(nextp + 8 * num);
805 for (i = 0; i < num; i++) {
808 j = code_get_s4(nextp, m);
813 #if defined(ENABLE_VERIFIER)
814 /* check if the lookup table is sorted correctly */
816 if (i && (j <= prevvalue)) {
817 *exceptionptr = new_verifyerror(m, "Unsorted lookup switch");
824 j = p + code_get_s4(nextp,m);
825 lookup->target.insindex = j;
828 CHECK_BYTECODE_INDEX(j);
837 case JAVA_TABLESWITCH:
841 branch_target_t *table;
844 nextp = ALIGN((p + 1), 4);
846 CHECK_END_OF_BYTECODE(nextp + 12);
848 NEW_OP_PREPARE_ZEROFLAGS(opcode);
852 deftarget = p + code_get_s4(nextp, m);
854 CHECK_BYTECODE_INDEX(deftarget);
855 new_block_insert(deftarget);
859 j = code_get_s4(nextp, m);
860 iptr->sx.s23.s2.tablelow = j;
865 num = code_get_s4(nextp, m);
866 iptr->sx.s23.s3.tablehigh = num;
869 /* calculate the number of table entries */
873 #if defined(ENABLE_VERIFIER)
875 *exceptionptr = new_verifyerror(m,
876 "invalid TABLESWITCH: upper bound < lower bound");
880 /* create the intermediate code table */
881 /* the first entry is the default target */
883 table = MNEW(branch_target_t, 1 + num);
884 iptr->dst.table = table;
885 (table++)->insindex = deftarget;
887 /* iterate over the target table */
889 CHECK_END_OF_BYTECODE(nextp + 4 * num);
891 for (i = 0; i < num; i++) {
892 j = p + code_get_s4(nextp,m);
893 (table++)->insindex = j;
895 CHECK_BYTECODE_INDEX(j);
904 /* load and store of object fields ************************************/
908 jd->isleafmethod = false;
917 unresolved_field *uf;
919 i = code_get_u2(p + 1, m);
920 fr = class_getconstant(m->class, i, CONSTANT_Fieldref);
924 NEW_OP_PREPARE_ZEROFLAGS(opcode);
925 iptr->sx.s23.s3.fmiref = fr;
927 /* only with -noverify, otherwise the typechecker does this */
929 #if defined(ENABLE_VERIFIER)
932 result = new_resolve_field_lazy(iptr, NULL, m);
933 if (result == resolveFailed)
936 if (result != resolveSucceeded) {
937 uf = new_create_unresolved_field(m->class, m, iptr);
942 /* store the unresolved_field pointer */
944 iptr->sx.s23.s3.uf = uf;
945 iptr->flags.bits = INS_FLAG_UNRESOLVED;
947 #if defined(ENABLE_VERIFIER)
955 /* method invocation **************************************************/
957 case JAVA_INVOKESTATIC:
958 i = code_get_u2(p + 1, m);
959 mr = class_getconstant(m->class, i, CONSTANT_Methodref);
963 md = mr->parseddesc.md;
966 if (!descriptor_params_from_paramtypes(md, ACC_STATIC))
971 case JAVA_INVOKEINTERFACE:
972 i = code_get_u2(p + 1, m);
974 mr = class_getconstant(m->class, i,
975 CONSTANT_InterfaceMethodref);
977 goto invoke_nonstatic_method;
979 case JAVA_INVOKESPECIAL:
980 case JAVA_INVOKEVIRTUAL:
981 i = code_get_u2(p + 1, m);
982 mr = class_getconstant(m->class, i, CONSTANT_Methodref);
984 invoke_nonstatic_method:
988 md = mr->parseddesc.md;
991 if (!descriptor_params_from_paramtypes(md, 0))
995 jd->isleafmethod = false;
997 NEW_OP_PREPARE_ZEROFLAGS(opcode);
998 iptr->sx.s23.s3.fmiref = mr;
1000 /* only with -noverify, otherwise the typechecker does this */
1002 #if defined(ENABLE_VERIFIER)
1005 result = new_resolve_method_lazy(iptr, NULL, m);
1006 if (result == resolveFailed)
1009 if (result != resolveSucceeded) {
1010 um = new_create_unresolved_method(m->class, m, iptr);
1015 /* store the unresolved_method pointer */
1017 iptr->sx.s23.s3.um = um;
1018 iptr->flags.bits = INS_FLAG_UNRESOLVED;
1020 #if defined(ENABLE_VERIFIER)
1026 /* instructions taking class arguments ********************************/
1029 i = code_get_u2(p + 1, m);
1030 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
1034 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
1037 NEW_OP_LOADCONST_CLASSINFO_OR_CLASSREF(c, cr, INS_FLAG_NOCHECK);
1038 bte = builtintable_get_internal(BUILTIN_new);
1039 NEW_OP_BUILTIN_CHECK_EXCEPTION(bte);
1043 case JAVA_CHECKCAST:
1044 i = code_get_u2(p + 1, m);
1045 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
1049 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
1052 if (cr->name->text[0] == '[') {
1053 /* array type cast-check */
1054 flags = INS_FLAG_ARRAY;
1055 jd->isleafmethod = false;
1058 /* object type cast-check */
1061 NEW_OP_S3_CLASSINFO_OR_CLASSREF(opcode, c, cr, flags);
1064 case JAVA_INSTANCEOF:
1065 i = code_get_u2(p + 1,m);
1066 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
1070 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
1073 if (cr->name->text[0] == '[') {
1074 /* array type cast-check */
1075 NEW_OP_LOADCONST_CLASSINFO_OR_CLASSREF(c, cr, INS_FLAG_NOCHECK);
1076 bte = builtintable_get_internal(BUILTIN_arrayinstanceof);
1077 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1081 /* object type cast-check */
1082 NEW_OP_S3_CLASSINFO_OR_CLASSREF(opcode, c, cr, 0 /* flags*/);
1086 /* synchronization instructions ***************************************/
1088 case JAVA_MONITORENTER:
1089 #if defined(ENABLE_THREADS)
1091 /* XXX null check */
1092 bte = builtintable_get_internal(LOCK_monitor_enter);
1093 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1098 NEW_OP(ICMD_CHECKNULL_POP);
1102 case JAVA_MONITOREXIT:
1103 #if defined(ENABLE_THREADS)
1105 /* XXX null check */
1106 bte = builtintable_get_internal(LOCK_monitor_exit);
1107 NEW_OP_BUILTIN_CHECK_EXCEPTION(bte);
1112 NEW_OP(ICMD_CHECKNULL_POP);
1116 /* arithmetic instructions that may become builtin functions **********/
1119 #if !SUPPORT_DIVISION
1120 bte = builtintable_get_internal(BUILTIN_idiv);
1121 NEW_OP_BUILTIN_ARITHMETIC(opcode, bte);
1128 #if !SUPPORT_DIVISION
1129 bte = builtintable_get_internal(BUILTIN_irem);
1130 NEW_OP_BUILTIN_ARITHMETIC(opcode, bte);
1137 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1138 bte = builtintable_get_internal(BUILTIN_ldiv);
1139 NEW_OP_BUILTIN_ARITHMETIC(opcode, bte);
1146 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1147 bte = builtintable_get_internal(BUILTIN_lrem);
1148 NEW_OP_BUILTIN_ARITHMETIC(opcode, bte);
1155 #if defined(__I386__)
1158 bte = builtintable_get_internal(BUILTIN_frem);
1159 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1164 #if defined(__I386__)
1167 bte = builtintable_get_internal(BUILTIN_drem);
1168 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1173 #if defined(__ALPHA__)
1175 bte = builtintable_get_internal(BUILTIN_f2i);
1176 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1186 #if defined(__ALPHA__)
1188 bte = builtintable_get_internal(BUILTIN_f2l);
1189 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1199 #if defined(__ALPHA__)
1201 bte = builtintable_get_internal(BUILTIN_d2i);
1202 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1212 #if defined(__ALPHA__)
1214 bte = builtintable_get_internal(BUILTIN_d2l);
1215 NEW_OP_BUILTIN_NO_EXCEPTION(bte);
1224 /* invalid opcodes ****************************************************/
1226 /* check for invalid opcodes if the verifier is enabled */
1227 #if defined(ENABLE_VERIFIER)
1228 case JAVA_BREAKPOINT:
1230 new_verifyerror(m, "Quick instructions shouldn't appear, yet.");
1233 case 186: /* unused opcode */
1288 new_verifyerror(m,"Illegal opcode %d at instr %d\n",
1292 #endif /* defined(ENABLE_VERIFIER) */
1294 /* opcodes that don't require translation *****************************/
1297 /* straight-forward translation to ICMD */
1303 /* verifier checks ****************************************************/
1305 #if defined(ENABLE_VERIFIER)
1306 /* If WIDE was used correctly, iswide should have been reset by now. */
1308 *exceptionptr = new_verifyerror(m,
1309 "Illegal instruction: WIDE before incompatible opcode");
1312 #endif /* defined(ENABLE_VERIFIER) */
1316 /*** END OF LOOP **********************************************************/
1318 /* assert that we did not write more ICMDs than allocated */
1320 assert(ipc == (iptr - jd->new_instructions));
1321 assert(ipc <= m->jcodelength);
1323 /*** verifier checks ******************************************************/
1325 #if defined(ENABLE_VERIFIER)
1326 if (p != m->jcodelength) {
1327 *exceptionptr = new_verifyerror(m,
1328 "Command-sequence crosses code-boundary");
1333 *exceptionptr = new_verifyerror(m, "Falling off the end of the code");
1336 #endif /* defined(ENABLE_VERIFIER) */
1338 /*** setup the methodinfo, allocate stack and basic blocks ****************/
1340 /* adjust block count if target 0 is not first intermediate instruction */
1342 if (!jd->new_basicblockindex[0] || (jd->new_basicblockindex[0] > 1))
1345 /* copy local to method variables */
1347 jd->new_instructioncount = ipc;
1348 jd->new_basicblockcount = b_count;
1349 jd->new_stackcount = s_count + jd->new_basicblockcount * m->maxstack; /* in-stacks */
1351 /* allocate stack table */
1353 jd->new_stack = DMNEW(stackelement, jd->new_stackcount);
1355 /* build basic block list */
1357 bptr = jd->new_basicblocks = DMNEW(basicblock, b_count + 1); /* one more for end ipc */
1360 jd->new_c_debug_nr = 0;
1362 /* additional block if target 0 is not first intermediate instruction */
1364 if (!jd->new_basicblockindex[0] || (jd->new_basicblockindex[0] > 1)) {
1365 BASICBLOCK_INIT(bptr, m);
1367 bptr->iinstr = /* XXX */ (instruction *) jd->new_instructions;
1368 /* bptr->icount is set when the next block is allocated */
1372 bptr[-1].next = bptr;
1375 /* allocate blocks */
1377 for (p = 0; p < m->jcodelength; p++) {
1378 if (jd->new_basicblockindex[p] & 1) {
1379 /* Check if this block starts at the beginning of an */
1381 #if defined(ENABLE_VERIFIER)
1382 if (!instructionstart[p]) {
1383 *exceptionptr = new_verifyerror(m,
1384 "Branch into middle of instruction");
1389 /* allocate the block */
1391 BASICBLOCK_INIT(bptr, m);
1393 bptr->iinstr = /* XXX */ (instruction *) (jd->new_instructions + (jd->new_basicblockindex[p] >> 1));
1395 bptr[-1].icount = /*XXX*/ (new_instruction *)bptr->iinstr - (new_instruction*) bptr[-1].iinstr;
1397 /* bptr->icount is set when the next block is allocated */
1399 jd->new_basicblockindex[p] = b_count;
1403 bptr[-1].next = bptr;
1407 /* set instruction count of last real block */
1410 bptr[-1].icount = (jd->new_instructions + jd->new_instructioncount) - /* XXX */ (new_instruction *) bptr[-1].iinstr;
1413 /* allocate additional block at end */
1415 BASICBLOCK_INIT(bptr,m);
1417 bptr->instack = bptr->outstack = NULL;
1418 bptr->indepth = bptr->outdepth = 0;
1419 bptr->iinstr = NULL;
1423 /* set basicblock pointers in exception table */
1425 if (cd->exceptiontablelength > 0) {
1426 cd->exceptiontable[cd->exceptiontablelength - 1].down = NULL;
1429 for (i = 0; i < cd->exceptiontablelength; ++i) {
1430 p = cd->exceptiontable[i].startpc;
1431 cd->exceptiontable[i].start = jd->new_basicblocks + jd->new_basicblockindex[p];
1433 p = cd->exceptiontable[i].endpc;
1434 cd->exceptiontable[i].end = (p == m->jcodelength) ? (jd->new_basicblocks + jd->new_basicblockcount /*+ 1*/) : (jd->new_basicblocks + jd->new_basicblockindex[p]);
1436 p = cd->exceptiontable[i].handlerpc;
1437 cd->exceptiontable[i].handler = jd->new_basicblocks + jd->new_basicblockindex[p];
1440 /* XXX activate this if you want to try inlining */
1442 for (i = 0; i < m->exceptiontablelength; ++i) {
1443 p = m->exceptiontable[i].startpc;
1444 m->exceptiontable[i].start = jd->new_basicblocks + jd->new_basicblockindex[p];
1446 p = m->exceptiontable[i].endpc;
1447 m->exceptiontable[i].end = (p == m->jcodelength) ? (jd->new_basicblocks + jd->new_basicblockcount /*+ 1*/) : (jd->new_basicblocks + jd->new_basicblockindex[p]);
1449 p = m->exceptiontable[i].handlerpc;
1450 m->exceptiontable[i].handler = jd->new_basicblocks + jd->new_basicblockindex[p];
1454 /* everything's ok */
1458 /*** goto labels for throwing verifier exceptions *************************/
1460 #if defined(ENABLE_VERIFIER)
1462 throw_unexpected_end_of_bytecode:
1463 *exceptionptr = new_verifyerror(m, "Unexpected end of bytecode");
1466 throw_invalid_bytecode_index:
1468 new_verifyerror(m, "Illegal target of branch instruction");
1471 throw_illegal_local_variable_number:
1473 new_verifyerror(m, "Illegal local variable number");
1476 #endif /* ENABLE_VERIFIER */
1480 bool parse(jitdata *jd)
1485 int p; /* java instruction counter */
1486 int nextp; /* start of next java instruction */
1487 int opcode; /* java opcode */
1488 int i; /* temporary for different uses (ctrs)*/
1489 int ipc = 0; /* intermediate instruction counter */
1490 int b_count = 0; /* basic block counter */
1491 int s_count = 0; /* stack element counter */
1492 bool blockend = false; /* true if basic block end has been reached */
1493 bool iswide = false; /* true if last instruction was a wide*/
1494 instruction *iptr; /* current ptr into instruction array */
1496 u1 *instructionstart; /* 1 for pcs which are valid instr. starts */
1498 constant_classref *cr;
1499 constant_classref *compr;
1501 builtintable_entry *bte;
1503 constant_FMIref *mr;
1505 unresolved_method *um;
1506 resolve_result_t result;
1510 u2 linepcchange = 0;
1512 /* get required compiler data */
1518 /* allocate instruction array and block index table */
1520 /* 1 additional for end ipc */
1521 m->basicblockindex = DMNEW(s4, m->jcodelength + 1);
1522 memset(m->basicblockindex, 0, sizeof(s4) * (m->jcodelength + 1));
1524 instructionstart = DMNEW(u1, m->jcodelength + 1);
1525 memset(instructionstart, 0, sizeof(u1) * (m->jcodelength + 1));
1527 /* 1 additional for TRACEBUILTIN and 4 for MONITORENTER/EXIT */
1528 /* additional MONITOREXITS are reached by branches which are 3 bytes */
1530 iptr = m->instructions = DMNEW(instruction, m->jcodelength + 5);
1532 /* Zero the intermediate instructions array so we don't have any
1533 * invalid pointers in it if we cannot finish analyse_stack(). */
1535 memset(iptr, 0, sizeof(instruction) * (m->jcodelength + 5));
1537 /* compute branch targets of exception table */
1540 &(cd->exceptiontable[cd->exceptiontablelength-1]),
1542 m->exceptiontablelength,
1548 s_count = 1 + m->exceptiontablelength; /* initialize stack element counter */
1550 #if defined(ENABLE_THREADS)
1551 if (checksync && (m->flags & ACC_SYNCHRONIZED))
1552 jd->isleafmethod = false;
1555 /* scan all java instructions */
1559 if (m->linenumbercount == 0) {
1563 linepcchange = m->linenumbers[0].start_pc;
1566 for (p = 0; p < m->jcodelength; p = nextp) {
1568 /* mark this position as a valid instruction start */
1569 instructionstart[p] = 1;
1570 if (linepcchange == p) {
1571 if (m->linenumbercount > lineindex) {
1573 currentline = m->linenumbers[lineindex].line_number;
1575 if (lineindex < m->linenumbercount) {
1576 linepcchange = m->linenumbers[lineindex].start_pc;
1577 if (linepcchange == p)
1578 goto next_linenumber;
1583 /* fetch next opcode */
1585 opcode = code_get_u1(p, m);
1587 m->basicblockindex[p] |= (ipc << 1); /*store intermed cnt*/
1589 /* some compilers put a JAVA_NOP after a blockend instruction */
1591 if (blockend && (opcode != JAVA_NOP)) {
1592 /* start new block */
1598 nextp = p + jcommandsize[opcode]; /* compute next instruction start */
1600 CHECK_END_OF_BYTECODE(nextp);
1602 s_count += stackreq[opcode]; /* compute stack element count */
1607 /* pushing constants onto the stack p */
1610 LOADCONST_I(code_get_s1(p+1,m));
1614 LOADCONST_I(code_get_s2(p+1,m));
1618 i = code_get_u1(p + 1, m);
1619 goto pushconstantitem;
1623 i = code_get_u2(p + 1, m);
1627 #if defined(ENABLE_VERIFIER)
1628 if (i >= m->class->cpcount) {
1629 *exceptionptr = new_verifyerror(m,
1630 "Attempt to access constant outside range");
1635 switch (m->class->cptags[i]) {
1636 case CONSTANT_Integer:
1637 LOADCONST_I(((constant_integer *) (m->class->cpinfos[i]))->value);
1640 LOADCONST_L(((constant_long *) (m->class->cpinfos[i]))->value);
1642 case CONSTANT_Float:
1643 LOADCONST_F(((constant_float *) (m->class->cpinfos[i]))->value);
1645 case CONSTANT_Double:
1646 LOADCONST_D(((constant_double *) (m->class->cpinfos[i]))->value);
1648 case CONSTANT_String:
1649 LOADCONST_A(literalstring_new((utf *) (m->class->cpinfos[i])));
1651 case CONSTANT_Class:
1652 cr = (constant_classref *) (m->class->cpinfos[i]);
1654 if (!resolve_classref(m, cr, resolveLazy, true,
1658 /* if not resolved, c == NULL */
1661 iptr->target = (void*) 0x02; /* XXX target used temporarily as flag */
1665 iptr->target = (void*) 0x03; /* XXX target used temporarily as flag */
1670 #if defined(ENABLE_VERIFIER)
1672 *exceptionptr = new_verifyerror(m,
1673 "Invalid constant type to push");
1679 case JAVA_ACONST_NULL:
1683 case JAVA_ICONST_M1:
1690 LOADCONST_I(opcode - JAVA_ICONST_0);
1695 LOADCONST_L(opcode - JAVA_LCONST_0);
1701 LOADCONST_F(opcode - JAVA_FCONST_0);
1706 LOADCONST_D(opcode - JAVA_DCONST_0);
1709 /* loading variables onto the stack */
1715 i = code_get_u1(p + 1,m);
1718 i = code_get_u2(p + 1,m);
1722 OP1LOAD_ONEWORD(opcode, i);
1728 i = code_get_u1(p + 1,m);
1731 i = code_get_u2(p + 1,m);
1735 OP1LOAD_TWOWORD(opcode, i);
1742 OP1LOAD_ONEWORD(ICMD_ILOAD, opcode - JAVA_ILOAD_0);
1749 OP1LOAD_TWOWORD(ICMD_LLOAD, opcode - JAVA_LLOAD_0);
1756 OP1LOAD_ONEWORD(ICMD_FLOAD, opcode - JAVA_FLOAD_0);
1763 OP1LOAD_TWOWORD(ICMD_DLOAD, opcode - JAVA_DLOAD_0);
1770 OP1LOAD_ONEWORD(ICMD_ALOAD, opcode - JAVA_ALOAD_0);
1773 /* storing stack values into local variables */
1779 i = code_get_u1(p + 1,m);
1782 i = code_get_u2(p + 1,m);
1786 OP1STORE_ONEWORD(opcode, i);
1792 i = code_get_u1(p + 1,m);
1795 i = code_get_u2(p + 1,m);
1799 OP1STORE_TWOWORD(opcode, i);
1806 OP1STORE_ONEWORD(ICMD_ISTORE, opcode - JAVA_ISTORE_0);
1813 OP1STORE_TWOWORD(ICMD_LSTORE, opcode - JAVA_LSTORE_0);
1820 OP1STORE_ONEWORD(ICMD_FSTORE, opcode - JAVA_FSTORE_0);
1827 OP1STORE_TWOWORD(ICMD_DSTORE, opcode - JAVA_DSTORE_0);
1834 OP1STORE_ONEWORD(ICMD_ASTORE, opcode - JAVA_ASTORE_0);
1842 i = code_get_u1(p + 1,m);
1843 v = code_get_s1(p + 2,m);
1847 i = code_get_u2(p + 1,m);
1848 v = code_get_s2(p + 3,m);
1857 /* wider index for loading, storing and incrementing */
1864 /* managing arrays ****************************************************/
1867 switch (code_get_s1(p + 1, m)) {
1869 bte = builtintable_get_internal(BUILTIN_newarray_boolean);
1872 bte = builtintable_get_internal(BUILTIN_newarray_char);
1875 bte = builtintable_get_internal(BUILTIN_newarray_float);
1878 bte = builtintable_get_internal(BUILTIN_newarray_double);
1881 bte = builtintable_get_internal(BUILTIN_newarray_byte);
1884 bte = builtintable_get_internal(BUILTIN_newarray_short);
1887 bte = builtintable_get_internal(BUILTIN_newarray_int);
1890 bte = builtintable_get_internal(BUILTIN_newarray_long);
1892 #if defined(ENABLE_VERIFIER)
1894 *exceptionptr = new_verifyerror(m,
1895 "Invalid array-type to create");
1899 BUILTIN(bte, true, NULL, currentline);
1902 case JAVA_ANEWARRAY:
1903 i = code_get_u2(p + 1, m);
1904 compr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
1908 if (!(cr = class_get_classref_multiarray_of(1, compr)))
1911 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
1914 LOADCONST_A_BUILTIN(c, cr);
1915 bte = builtintable_get_internal(BUILTIN_newarray);
1916 BUILTIN(bte, true, NULL, currentline);
1920 case JAVA_MULTIANEWARRAY:
1921 jd->isleafmethod = false;
1922 i = code_get_u2(p + 1, m);
1924 s4 v = code_get_u1(p + 3, m);
1926 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
1930 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
1933 /* if unresolved, c == NULL */
1934 OP2AT(opcode, v, c, cr, currentline);
1945 case JAVA_IFNONNULL:
1946 case JAVA_IF_ICMPEQ:
1947 case JAVA_IF_ICMPNE:
1948 case JAVA_IF_ICMPLT:
1949 case JAVA_IF_ICMPGT:
1950 case JAVA_IF_ICMPLE:
1951 case JAVA_IF_ICMPGE:
1952 case JAVA_IF_ACMPEQ:
1953 case JAVA_IF_ACMPNE:
1956 i = p + code_get_s2(p + 1,m);
1957 CHECK_BYTECODE_INDEX(i);
1965 i = p + code_get_s4(p + 1,m);
1966 CHECK_BYTECODE_INDEX(i);
1974 i = code_get_u1(p + 1,m);
1977 i = code_get_u2(p + 1,m);
1983 OP1LOAD_ONEWORD(opcode, i);
1993 /* zero val.a so no patcher is inserted */
1994 /* the type checker may set this later */
2001 /* zero val.a so no patcher is inserted */
2002 /* the type checker may set this later */
2008 /* table jumps ********************************************************/
2010 case JAVA_LOOKUPSWITCH:
2014 #if defined(ENABLE_VERIFIER)
2019 nextp = ALIGN((p + 1), 4);
2021 CHECK_END_OF_BYTECODE(nextp + 8);
2023 tablep = (s4 *) (m->jcode + nextp);
2025 OP2A(opcode, 0, tablep, currentline);
2027 /* default target */
2029 j = p + code_get_s4(nextp, m);
2030 *tablep = j; /* restore for little endian */
2033 CHECK_BYTECODE_INDEX(j);
2036 /* number of pairs */
2038 num = code_get_u4(nextp, m);
2043 CHECK_END_OF_BYTECODE(nextp + 8 * num);
2045 for (i = 0; i < num; i++) {
2048 j = code_get_s4(nextp, m);
2049 *tablep = j; /* restore for little endian */
2053 #if defined(ENABLE_VERIFIER)
2054 /* check if the lookup table is sorted correctly */
2056 if (i && (j <= prevvalue)) {
2057 *exceptionptr = new_verifyerror(m, "Unsorted lookup switch");
2065 j = p + code_get_s4(nextp,m);
2066 *tablep = j; /* restore for little endian */
2069 CHECK_BYTECODE_INDEX(j);
2077 case JAVA_TABLESWITCH:
2083 nextp = ALIGN((p + 1), 4);
2085 CHECK_END_OF_BYTECODE(nextp + 12);
2087 tablep = (s4 *) (m->jcode + nextp);
2089 OP2A(opcode, 0, tablep, currentline);
2091 /* default target */
2093 j = p + code_get_s4(nextp, m);
2094 *tablep = j; /* restore for little endian */
2097 CHECK_BYTECODE_INDEX(j);
2102 j = code_get_s4(nextp, m);
2103 *tablep = j; /* restore for little endian */
2109 num = code_get_s4(nextp, m);
2110 *tablep = num; /* restore for little endian */
2114 num -= j; /* difference of upper - lower */
2116 #if defined(ENABLE_VERIFIER)
2118 *exceptionptr = new_verifyerror(m,
2119 "invalid TABLESWITCH: upper bound < lower bound");
2124 CHECK_END_OF_BYTECODE(nextp + 4 * (num + 1));
2126 for (i = 0; i <= num; i++) {
2127 j = p + code_get_s4(nextp,m);
2128 *tablep = j; /* restore for little endian */
2131 CHECK_BYTECODE_INDEX(j);
2139 /* load and store of object fields ************************************/
2143 jd->isleafmethod = false;
2146 case JAVA_GETSTATIC:
2147 case JAVA_PUTSTATIC:
2151 constant_FMIref *fr;
2152 unresolved_field *uf;
2154 i = code_get_u2(p + 1, m);
2155 fr = class_getconstant(m->class, i,
2160 OP2A_NOINC(opcode, fr->parseddesc.fd->type, fr, currentline);
2162 /* only with -noverify, otherwise the typechecker does this */
2164 #if defined(ENABLE_VERIFIER)
2167 result = resolve_field_lazy(iptr,NULL,m);
2168 if (result == resolveFailed)
2171 if (result != resolveSucceeded) {
2172 uf = create_unresolved_field(m->class,
2178 /* store the unresolved_field pointer */
2180 /* XXX this will be changed */
2182 iptr->target = (void*) 0x01; /* XXX target temporarily used as flag */
2185 iptr->target = NULL;
2187 #if defined(ENABLE_VERIFIER)
2190 iptr->target = NULL;
2198 /* method invocation **************************************************/
2200 case JAVA_INVOKESTATIC:
2201 i = code_get_u2(p + 1, m);
2202 mr = class_getconstant(m->class, i,
2203 CONSTANT_Methodref);
2207 md = mr->parseddesc.md;
2210 if (!descriptor_params_from_paramtypes(md, ACC_STATIC))
2215 case JAVA_INVOKEINTERFACE:
2216 i = code_get_u2(p + 1, m);
2218 mr = class_getconstant(m->class, i,
2219 CONSTANT_InterfaceMethodref);
2221 goto invoke_nonstatic_method;
2223 case JAVA_INVOKESPECIAL:
2224 case JAVA_INVOKEVIRTUAL:
2225 i = code_get_u2(p + 1, m);
2226 mr = class_getconstant(m->class, i,
2227 CONSTANT_Methodref);
2229 invoke_nonstatic_method:
2233 md = mr->parseddesc.md;
2236 if (!descriptor_params_from_paramtypes(md, 0))
2240 jd->isleafmethod = false;
2242 OP2A_NOINC(opcode, 0, mr, currentline);
2244 /* only with -noverify, otherwise the typechecker does this */
2246 #if defined(ENABLE_VERIFIER)
2249 result = resolve_method_lazy(iptr,NULL,m);
2250 if (result == resolveFailed)
2253 if (result != resolveSucceeded) {
2254 um = create_unresolved_method(m->class,
2260 /* store the unresolved_method pointer */
2262 /* XXX this will be changed */
2264 iptr->target = (void*) 0x01; /* XXX target temporarily used as flag */
2267 /* the method could be resolved */
2268 iptr->target = NULL;
2270 #if defined(ENABLE_VERIFIER)
2273 iptr->target = NULL;
2279 /* miscellaneous object operations ************************************/
2282 i = code_get_u2(p + 1, m);
2283 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
2287 if (!resolve_classref(m, cr, resolveLazy, true, true,
2291 LOADCONST_A_BUILTIN(c, cr);
2292 bte = builtintable_get_internal(BUILTIN_new);
2293 BUILTIN(bte, true, NULL, currentline);
2297 case JAVA_CHECKCAST:
2298 i = code_get_u2(p + 1, m);
2299 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
2303 if (!resolve_classref(m, cr, resolveLazy, true,
2307 if (cr->name->text[0] == '[') {
2308 /* array type cast-check */
2309 OP2AT(opcode, 0, c, cr, currentline);
2310 jd->isleafmethod = false;
2314 /* object type cast-check */
2315 OP2AT(opcode, 1, c, cr, currentline);
2319 case JAVA_INSTANCEOF:
2320 i = code_get_u2(p + 1,m);
2321 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
2325 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
2328 if (cr->name->text[0] == '[') {
2329 /* array type cast-check */
2330 LOADCONST_A_BUILTIN(c, cr);
2331 bte = builtintable_get_internal(BUILTIN_arrayinstanceof);
2332 BUILTIN(bte, false, NULL, currentline);
2337 /* object type cast-check */
2338 OP2AT(opcode, 1, c, cr, currentline);
2342 case JAVA_MONITORENTER:
2343 #if defined(ENABLE_THREADS)
2346 bte = builtintable_get_internal(LOCK_monitor_enter);
2347 BUILTIN(bte, false, NULL, currentline);
2357 case JAVA_MONITOREXIT:
2358 #if defined(ENABLE_THREADS)
2360 bte = builtintable_get_internal(LOCK_monitor_exit);
2361 BUILTIN(bte, false, NULL, currentline);
2370 /* any other basic operation ******************************************/
2373 #if !SUPPORT_DIVISION
2374 bte = builtintable_get_internal(BUILTIN_idiv);
2375 OP2A(opcode, bte->md->paramcount, bte, currentline);
2376 jd->isleafmethod = false;
2383 #if !SUPPORT_DIVISION
2384 bte = builtintable_get_internal(BUILTIN_irem);
2385 OP2A(opcode, bte->md->paramcount, bte, currentline);
2386 jd->isleafmethod = false;
2393 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
2394 bte = builtintable_get_internal(BUILTIN_ldiv);
2395 OP2A(opcode, bte->md->paramcount, bte, currentline);
2396 jd->isleafmethod = false;
2403 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
2404 bte = builtintable_get_internal(BUILTIN_lrem);
2405 OP2A(opcode, bte->md->paramcount, bte, currentline);
2406 jd->isleafmethod = false;
2413 #if defined(__I386__)
2416 bte = builtintable_get_internal(BUILTIN_frem);
2417 BUILTIN(bte, false, NULL, currentline);
2422 #if defined(__I386__)
2425 bte = builtintable_get_internal(BUILTIN_drem);
2426 BUILTIN(bte, false, NULL, currentline);
2431 #if defined(__ALPHA__)
2433 bte = builtintable_get_internal(BUILTIN_f2i);
2434 BUILTIN(bte, false, NULL, currentline);
2444 #if defined(__ALPHA__)
2446 bte = builtintable_get_internal(BUILTIN_f2l);
2447 BUILTIN(bte, false, NULL, currentline);
2457 #if defined(__ALPHA__)
2459 bte = builtintable_get_internal(BUILTIN_d2i);
2460 BUILTIN(bte, false, NULL, currentline);
2470 #if defined(__ALPHA__)
2472 bte = builtintable_get_internal(BUILTIN_d2l);
2473 BUILTIN(bte, false, NULL, currentline);
2482 /* check for invalid opcodes if the verifier is enabled */
2483 #if defined(ENABLE_VERIFIER)
2484 case JAVA_BREAKPOINT:
2486 new_verifyerror(m, "Quick instructions shouldn't appear yet.");
2489 case 186: /* unused opcode */
2544 new_verifyerror(m,"Illegal opcode %d at instr %d\n",
2548 #endif /* defined(ENABLE_VERIFIER) */
2551 /* straight-forward translation to ICMD */
2557 #if defined(ENABLE_VERIFIER)
2558 /* If WIDE was used correctly, iswide should have been reset by now. */
2560 *exceptionptr = new_verifyerror(m,
2561 "Illegal instruction: WIDE before incompatible opcode");
2564 #endif /* defined(ENABLE_VERIFIER) */
2568 #if defined(ENABLE_VERIFIER)
2569 if (p != m->jcodelength) {
2570 *exceptionptr = new_verifyerror(m,
2571 "Command-sequence crosses code-boundary");
2576 *exceptionptr = new_verifyerror(m, "Falling off the end of the code");
2579 #endif /* defined(ENABLE_VERIFIER) */
2581 /* adjust block count if target 0 is not first intermediate instruction */
2583 if (!m->basicblockindex[0] || (m->basicblockindex[0] > 1))
2586 /* copy local to method variables */
2588 m->instructioncount = ipc;
2589 m->basicblockcount = b_count;
2590 m->stackcount = s_count + m->basicblockcount * m->maxstack;
2592 /* allocate stack table */
2594 m->stack = DMNEW(stackelement, m->stackcount);
2599 bptr = m->basicblocks = DMNEW(basicblock, b_count + 1); /* one more for end ipc */
2604 /* additional block if target 0 is not first intermediate instruction */
2606 if (!m->basicblockindex[0] || (m->basicblockindex[0] > 1)) {
2607 BASICBLOCK_INIT(bptr,m);
2609 bptr->iinstr = m->instructions;
2610 /* bptr->icount is set when the next block is allocated */
2614 bptr[-1].next = bptr;
2617 /* allocate blocks */
2619 for (p = 0; p < m->jcodelength; p++) {
2620 if (m->basicblockindex[p] & 1) {
2621 /* Check if this block starts at the beginning of an */
2623 #if defined(ENABLE_VERIFIER)
2624 if (!instructionstart[p]) {
2625 *exceptionptr = new_verifyerror(m,
2626 "Branch into middle of instruction");
2631 /* allocate the block */
2633 BASICBLOCK_INIT(bptr,m);
2635 bptr->iinstr = m->instructions + (m->basicblockindex[p] >> 1);
2637 bptr[-1].icount = bptr->iinstr - bptr[-1].iinstr;
2639 /* bptr->icount is set when the next block is allocated */
2641 m->basicblockindex[p] = b_count;
2645 bptr[-1].next = bptr;
2649 /* set instruction count of last real block */
2652 bptr[-1].icount = (m->instructions + m->instructioncount) - bptr[-1].iinstr;
2655 /* allocate additional block at end */
2657 BASICBLOCK_INIT(bptr,m);
2659 bptr->instack = bptr->outstack = NULL;
2660 bptr->indepth = bptr->outdepth = 0;
2661 bptr->iinstr = NULL;
2665 /* set basicblock pointers in exception table */
2667 if (cd->exceptiontablelength > 0) {
2668 cd->exceptiontable[cd->exceptiontablelength - 1].down = NULL;
2671 for (i = 0; i < cd->exceptiontablelength; ++i) {
2672 p = cd->exceptiontable[i].startpc;
2673 cd->exceptiontable[i].start = m->basicblocks + m->basicblockindex[p];
2675 p = cd->exceptiontable[i].endpc;
2676 cd->exceptiontable[i].end = (p == m->jcodelength) ? (m->basicblocks + m->basicblockcount /*+ 1*/) : (m->basicblocks + m->basicblockindex[p]);
2678 p = cd->exceptiontable[i].handlerpc;
2679 cd->exceptiontable[i].handler = m->basicblocks + m->basicblockindex[p];
2682 /* XXX activate this if you want to try inlining */
2684 for (i = 0; i < m->exceptiontablelength; ++i) {
2685 p = m->exceptiontable[i].startpc;
2686 m->exceptiontable[i].start = m->basicblocks + m->basicblockindex[p];
2688 p = m->exceptiontable[i].endpc;
2689 m->exceptiontable[i].end = (p == m->jcodelength) ? (m->basicblocks + m->basicblockcount /*+ 1*/) : (m->basicblocks + m->basicblockindex[p]);
2691 p = m->exceptiontable[i].handlerpc;
2692 m->exceptiontable[i].handler = m->basicblocks + m->basicblockindex[p];
2698 /* everything's ok */
2702 #if defined(ENABLE_VERIFIER)
2704 throw_unexpected_end_of_bytecode:
2705 *exceptionptr = new_verifyerror(m, "Unexpected end of bytecode");
2708 throw_invalid_bytecode_index:
2710 new_verifyerror(m, "Illegal target of branch instruction");
2713 throw_illegal_local_variable_number:
2715 new_verifyerror(m, "Illegal local variable number");
2718 #endif /* ENABLE_VERIFIER */
2723 * These are local overrides for various environment variables in Emacs.
2724 * Please do not remove this and leave it at the end of the file, where
2725 * Emacs will automagically detect them.
2726 * ---------------------------------------------------------------------
2729 * indent-tabs-mode: t
2733 * vim:noexpandtab:sw=4:ts=4: