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 5202 2006-08-01 13:10:48Z twisti $
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 /*******************************************************************************
72 function 'parse' scans the JavaVM code and generates intermediate code
74 During parsing the block index table is used to store at bit pos 0
75 a flag which marks basic block starts and at position 1 to 31 the
76 intermediate instruction index. After parsing the block index table
77 is scanned, for marked positions a block is generated and the block
78 number is stored in the block index table.
80 *******************************************************************************/
82 static exceptiontable * new_fillextable(
85 exceptiontable *extable,
86 exceptiontable *raw_extable,
87 int exceptiontablelength,
92 if (exceptiontablelength == 0)
95 b_count = *block_count;
97 for (src = exceptiontablelength-1; src >=0; src--) {
98 /* the start of the handled region becomes a basic block start */
99 p = raw_extable[src].startpc;
100 CHECK_BYTECODE_INDEX(p);
101 extable->startpc = p;
104 p = raw_extable[src].endpc; /* see JVM Spec 4.7.3 */
105 CHECK_BYTECODE_INDEX_EXCLUSIVE(p);
107 #if defined(ENABLE_VERIFIER)
108 if (p <= raw_extable[src].startpc) {
109 exceptions_throw_verifyerror(m,
110 "Invalid exception handler range");
116 /* end of handled region becomes a basic block boundary */
117 /* (If it is the bytecode end, we'll use the special */
118 /* end block that is created anyway.) */
119 if (p < m->jcodelength)
122 /* the start of the handler becomes a basic block start */
123 p = raw_extable[src].handlerpc;
124 CHECK_BYTECODE_INDEX(p);
125 extable->handlerpc = p;
128 extable->catchtype = raw_extable[src].catchtype;
129 extable->next = NULL;
130 extable->down = &extable[1];
134 *block_count = b_count;
139 #if defined(ENABLE_VERIFIER)
140 throw_invalid_bytecode_index:
141 exceptions_throw_verifyerror(m,
142 "Illegal bytecode index in exception table");
147 static exceptiontable * fillextable(methodinfo *m,
148 exceptiontable *extable,
149 exceptiontable *raw_extable,
150 int exceptiontablelength,
155 if (exceptiontablelength == 0)
158 b_count = *block_count;
160 for (src = exceptiontablelength-1; src >=0; src--) {
161 /* the start of the handled region becomes a basic block start */
162 p = raw_extable[src].startpc;
163 CHECK_BYTECODE_INDEX(p);
164 extable->startpc = p;
167 p = raw_extable[src].endpc; /* see JVM Spec 4.7.3 */
168 CHECK_BYTECODE_INDEX_EXCLUSIVE(p);
170 #if defined(ENABLE_VERIFIER)
171 if (p <= raw_extable[src].startpc) {
172 exceptions_throw_verifyerror(m,
173 "Invalid exception handler range");
179 /* end of handled region becomes a basic block boundary */
180 /* (If it is the bytecode end, we'll use the special */
181 /* end block that is created anyway.) */
182 if (p < m->jcodelength)
185 /* the start of the handler becomes a basic block start */
186 p = raw_extable[src].handlerpc;
187 CHECK_BYTECODE_INDEX(p);
188 extable->handlerpc = p;
191 extable->catchtype = raw_extable[src].catchtype;
192 extable->next = NULL;
193 extable->down = &extable[1];
197 *block_count = b_count;
202 #if defined(ENABLE_VERIFIER)
203 throw_invalid_bytecode_index:
204 exceptions_throw_verifyerror(m,
205 "Illegal bytecode index in exception table");
210 /*** macro for checking the length of the bytecode ***/
212 #if defined(ENABLE_VERIFIER)
213 #define CHECK_END_OF_BYTECODE(neededlength) \
215 if ((neededlength) > m->jcodelength) \
216 goto throw_unexpected_end_of_bytecode; \
218 #else /* !ENABLE_VERIFIER */
219 #define CHECK_END_OF_BYTECODE(neededlength)
220 #endif /* ENABLE_VERIFIER */
222 bool new_parse(jitdata *jd)
224 methodinfo *m; /* method being parsed */
227 int p; /* java instruction counter */
228 int nextp; /* start of next java instruction */
229 int opcode; /* java opcode */
230 int i; /* temporary for different uses (ctrs) */
231 int ipc = 0; /* intermediate instruction counter */
232 int b_count = 0; /* basic block counter */
233 int s_count = 0; /* stack element counter */
234 bool blockend = false; /* true if basic block end has been reached */
235 bool iswide = false; /* true if last instruction was a wide */
236 new_instruction *iptr; /* current ptr into instruction array */
237 u1 *instructionstart; /* 1 for pcs which are valid instr. starts */
238 constant_classref *cr;
239 constant_classref *compr;
241 builtintable_entry *bte;
244 unresolved_method *um;
245 resolve_result_t result;
252 /* get required compiler data */
258 /* allocate instruction array and block index table */
260 /* 1 additional for end ipc */
261 jd->new_basicblockindex = DMNEW(s4, m->jcodelength + 1);
262 memset(jd->new_basicblockindex, 0, sizeof(s4) * (m->jcodelength + 1));
264 instructionstart = DMNEW(u1, m->jcodelength + 1);
265 memset(instructionstart, 0, sizeof(u1) * (m->jcodelength + 1));
267 /* IMPORTANT: We assume that parsing creates at most one instruction per */
268 /* byte of original bytecode! */
270 iptr = jd->new_instructions = DMNEW(new_instruction, m->jcodelength);
272 /* compute branch targets of exception table */
274 if (!new_fillextable(jd, m,
275 &(cd->exceptiontable[cd->exceptiontablelength-1]),
277 m->exceptiontablelength,
283 s_count = 1 + m->exceptiontablelength; /* initialize stack element counter */
285 #if defined(ENABLE_THREADS)
286 if (checksync && (m->flags & ACC_SYNCHRONIZED))
287 jd->isleafmethod = false;
290 /* setup line number info */
295 if (m->linenumbercount == 0) {
299 linepcchange = m->linenumbers[0].start_pc;
302 /*** LOOP OVER ALL BYTECODE INSTRUCTIONS **********************************/
304 for (p = 0; p < m->jcodelength; p = nextp) {
306 /* mark this position as a valid instruction start */
308 instructionstart[p] = 1;
310 /* change the current line number, if necessary */
312 /* XXX rewrite this using pointer arithmetic */
314 if (linepcchange == p) {
315 if (m->linenumbercount > lineindex) {
317 currentline = m->linenumbers[lineindex].line_number;
319 if (lineindex < m->linenumbercount) {
320 linepcchange = m->linenumbers[lineindex].start_pc;
321 if (linepcchange == p)
322 goto next_linenumber;
327 /* fetch next opcode */
329 opcode = SUCK_BE_U1(m->jcode + p);
331 /* store intermediate instruction count (bit 0 mark block starts) */
333 jd->new_basicblockindex[p] |= (ipc << 1);
335 /* some compilers put a JAVA_NOP after a blockend instruction */
337 if (blockend && (opcode != JAVA_NOP)) {
338 /* start new block */
344 /* compute next instruction start */
346 nextp = p + jcommandsize[opcode];
348 CHECK_END_OF_BYTECODE(nextp);
350 /* add stack elements produced by this instruction */
352 s_count += stackreq[opcode];
354 /* translate this bytecode instruction */
361 /* pushing constants onto the stack ***********************************/
364 NEW_OP_LOADCONST_I(SUCK_BE_S1(m->jcode + p + 1));
368 NEW_OP_LOADCONST_I(SUCK_BE_S2(m->jcode + p + 1));
372 i = SUCK_BE_U1(m->jcode + p + 1);
373 goto pushconstantitem;
377 i = SUCK_BE_U2(m->jcode + p + 1);
381 #if defined(ENABLE_VERIFIER)
382 if (i >= m->class->cpcount) {
383 exceptions_throw_verifyerror(m,
384 "Attempt to access constant outside range");
389 switch (m->class->cptags[i]) {
390 case CONSTANT_Integer:
391 NEW_OP_LOADCONST_I(((constant_integer *) (m->class->cpinfos[i]))->value);
394 NEW_OP_LOADCONST_L(((constant_long *) (m->class->cpinfos[i]))->value);
397 NEW_OP_LOADCONST_F(((constant_float *) (m->class->cpinfos[i]))->value);
399 case CONSTANT_Double:
400 NEW_OP_LOADCONST_D(((constant_double *) (m->class->cpinfos[i]))->value);
402 case CONSTANT_String:
403 NEW_OP_LOADCONST_STRING(literalstring_new((utf *) (m->class->cpinfos[i])));
406 cr = (constant_classref *) (m->class->cpinfos[i]);
408 if (!resolve_classref(m, cr, resolveLazy, true,
412 /* if not resolved, c == NULL */
414 NEW_OP_LOADCONST_CLASSINFO_OR_CLASSREF(c, cr, 0 /* no extra flags */);
418 #if defined(ENABLE_VERIFIER)
420 exceptions_throw_verifyerror(m,
421 "Invalid constant type to push");
427 case JAVA_ACONST_NULL:
428 NEW_OP_LOADCONST_NULL();
438 NEW_OP_LOADCONST_I(opcode - JAVA_ICONST_0);
443 NEW_OP_LOADCONST_L(opcode - JAVA_LCONST_0);
449 NEW_OP_LOADCONST_F(opcode - JAVA_FCONST_0);
454 NEW_OP_LOADCONST_D(opcode - JAVA_DCONST_0);
457 /* local variable access instructions *********************************/
462 if (iswide == false) {
463 i = SUCK_BE_U1(m->jcode + p + 1);
466 i = SUCK_BE_U2(m->jcode + p + 1);
470 NEW_OP_LOAD_ONEWORD(opcode, i);
475 if (iswide == false) {
476 i = SUCK_BE_U1(m->jcode + p + 1);
479 i = SUCK_BE_U2(m->jcode + p + 1);
483 NEW_OP_LOAD_TWOWORD(opcode, i);
490 NEW_OP_LOAD_ONEWORD(ICMD_ILOAD, opcode - JAVA_ILOAD_0);
497 NEW_OP_LOAD_TWOWORD(ICMD_LLOAD, opcode - JAVA_LLOAD_0);
504 NEW_OP_LOAD_ONEWORD(ICMD_FLOAD, opcode - JAVA_FLOAD_0);
511 NEW_OP_LOAD_TWOWORD(ICMD_DLOAD, opcode - JAVA_DLOAD_0);
518 NEW_OP_LOAD_ONEWORD(ICMD_ALOAD, opcode - JAVA_ALOAD_0);
524 if (iswide == false) {
525 i = SUCK_BE_U1(m->jcode + p + 1);
528 i = SUCK_BE_U2(m->jcode + p + 1);
532 NEW_OP_STORE_ONEWORD(opcode, i);
537 if (iswide == false) {
538 i = SUCK_BE_U1(m->jcode + p + 1);
541 i = SUCK_BE_U2(m->jcode + p + 1);
545 NEW_OP_STORE_TWOWORD(opcode, i);
552 NEW_OP_STORE_ONEWORD(ICMD_ISTORE, opcode - JAVA_ISTORE_0);
559 NEW_OP_STORE_TWOWORD(ICMD_LSTORE, opcode - JAVA_LSTORE_0);
566 NEW_OP_STORE_ONEWORD(ICMD_FSTORE, opcode - JAVA_FSTORE_0);
573 NEW_OP_STORE_TWOWORD(ICMD_DSTORE, opcode - JAVA_DSTORE_0);
580 NEW_OP_STORE_ONEWORD(ICMD_ASTORE, opcode - JAVA_ASTORE_0);
587 if (iswide == false) {
588 i = SUCK_BE_U1(m->jcode + p + 1);
589 v = SUCK_BE_S1(m->jcode + p + 2);
593 i = SUCK_BE_U2(m->jcode + p + 1);
594 v = SUCK_BE_S2(m->jcode + p + 3);
599 NEW_OP_LOCALINDEX_I(opcode, i, v);
603 /* wider index for loading, storing and incrementing ******************/
610 /* managing arrays ****************************************************/
613 switch (SUCK_BE_S1(m->jcode + p + 1)) {
615 bte = builtintable_get_internal(BUILTIN_newarray_boolean);
618 bte = builtintable_get_internal(BUILTIN_newarray_char);
621 bte = builtintable_get_internal(BUILTIN_newarray_float);
624 bte = builtintable_get_internal(BUILTIN_newarray_double);
627 bte = builtintable_get_internal(BUILTIN_newarray_byte);
630 bte = builtintable_get_internal(BUILTIN_newarray_short);
633 bte = builtintable_get_internal(BUILTIN_newarray_int);
636 bte = builtintable_get_internal(BUILTIN_newarray_long);
638 #if defined(ENABLE_VERIFIER)
640 exceptions_throw_verifyerror(m, "Invalid array-type to create");
644 NEW_OP_BUILTIN_CHECK_EXCEPTION(bte);
648 i = SUCK_BE_U2(m->jcode + p + 1);
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 = SUCK_BE_U2(m->jcode + p + 1);
669 s4 v = SUCK_BE_U1(m->jcode + p + 3);
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 + SUCK_BE_S2(m->jcode + p + 1);
705 CHECK_BYTECODE_INDEX(i);
708 NEW_OP_INSINDEX(opcode, i);
712 i = p + SUCK_BE_S4(m->jcode + p + 1);
713 CHECK_BYTECODE_INDEX(i);
716 NEW_OP_INSINDEX(opcode, i);
720 i = p + SUCK_BE_S2(m->jcode + p + 1);
722 CHECK_BYTECODE_INDEX(i);
725 NEW_OP_PREPARE_ZEROFLAGS(JAVA_JSR);
726 iptr->sx.s23.s3.jsrtarget.insindex = i;
731 i = p + SUCK_BE_S4(m->jcode + p + 1);
735 if (iswide == false) {
736 i = SUCK_BE_U1(m->jcode + p + 1);
739 i = SUCK_BE_U2(m->jcode + p + 1);
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 + SUCK_BE_S4(m->jcode + nextp);
785 iptr->sx.s23.s3.lookupdefault.insindex = j;
787 CHECK_BYTECODE_INDEX(j);
790 /* number of pairs */
792 num = SUCK_BE_U4(m->jcode + nextp);
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 = SUCK_BE_S4(m->jcode + nextp);
813 #if defined(ENABLE_VERIFIER)
814 /* check if the lookup table is sorted correctly */
816 if (i && (j <= prevvalue)) {
817 exceptions_throw_verifyerror(m, "Unsorted lookup switch");
824 j = p + SUCK_BE_S4(m->jcode + nextp);
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 + SUCK_BE_S4(m->jcode + nextp);
854 CHECK_BYTECODE_INDEX(deftarget);
855 new_block_insert(deftarget);
859 j = SUCK_BE_S4(m->jcode + nextp);
860 iptr->sx.s23.s2.tablelow = j;
865 num = SUCK_BE_S4(m->jcode + nextp);
866 iptr->sx.s23.s3.tablehigh = num;
869 /* calculate the number of table entries */
873 #if defined(ENABLE_VERIFIER)
875 exceptions_throw_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 + SUCK_BE_S4(m->jcode + nextp);
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 = SUCK_BE_U2(m->jcode + p + 1);
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)
930 if (!JITDATA_HAS_FLAG_VERIFY(jd)) {
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 = SUCK_BE_U2(m->jcode + p + 1);
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 = SUCK_BE_U2(m->jcode + p + 1);
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 = SUCK_BE_U2(m->jcode + p + 1);
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)
1003 if (!JITDATA_HAS_FLAG_VERIFY(jd)) {
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 = SUCK_BE_U2(m->jcode + p + 1);
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 = SUCK_BE_U2(m->jcode + p + 1);
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 = SUCK_BE_U2(m->jcode + p + 1);
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:
1229 exceptions_throw_verifyerror(m, "Quick instructions shouldn't appear, yet.");
1232 case 186: /* unused opcode */
1286 exceptions_throw_verifyerror(m, "Illegal opcode %d at instr %d\n",
1290 #endif /* defined(ENABLE_VERIFIER) */
1292 /* opcodes that don't require translation *****************************/
1295 /* straight-forward translation to ICMD */
1301 /* verifier checks ****************************************************/
1303 #if defined(ENABLE_VERIFIER)
1304 /* If WIDE was used correctly, iswide should have been reset by now. */
1306 exceptions_throw_verifyerror(m,
1307 "Illegal instruction: WIDE before incompatible opcode");
1310 #endif /* defined(ENABLE_VERIFIER) */
1314 /*** END OF LOOP **********************************************************/
1316 /* assert that we did not write more ICMDs than allocated */
1318 assert(ipc == (iptr - jd->new_instructions));
1319 assert(ipc <= m->jcodelength);
1321 /*** verifier checks ******************************************************/
1323 #if defined(ENABLE_VERIFIER)
1324 if (p != m->jcodelength) {
1325 exceptions_throw_verifyerror(m,
1326 "Command-sequence crosses code-boundary");
1331 exceptions_throw_verifyerror(m, "Falling off the end of the code");
1334 #endif /* defined(ENABLE_VERIFIER) */
1336 /*** setup the methodinfo, allocate stack and basic blocks ****************/
1338 /* adjust block count if target 0 is not first intermediate instruction */
1340 if (!jd->new_basicblockindex[0] || (jd->new_basicblockindex[0] > 1))
1343 /* copy local to method variables */
1345 jd->new_instructioncount = ipc;
1346 jd->new_basicblockcount = b_count;
1347 jd->new_stackcount = s_count + jd->new_basicblockcount * m->maxstack; /* in-stacks */
1349 /* allocate stack table */
1351 jd->new_stack = DMNEW(stackelement, jd->new_stackcount);
1353 /* build basic block list */
1355 bptr = jd->new_basicblocks = DMNEW(basicblock, b_count + 1); /* one more for end ipc */
1358 jd->new_c_debug_nr = 0;
1360 /* additional block if target 0 is not first intermediate instruction */
1362 if (!jd->new_basicblockindex[0] || (jd->new_basicblockindex[0] > 1)) {
1363 BASICBLOCK_INIT(bptr, m);
1365 bptr->iinstr = /* XXX */ (instruction *) jd->new_instructions;
1366 /* bptr->icount is set when the next block is allocated */
1370 bptr[-1].next = bptr;
1373 /* allocate blocks */
1375 for (p = 0; p < m->jcodelength; p++) {
1376 if (jd->new_basicblockindex[p] & 1) {
1377 /* Check if this block starts at the beginning of an */
1379 #if defined(ENABLE_VERIFIER)
1380 if (!instructionstart[p]) {
1381 exceptions_throw_verifyerror(m,
1382 "Branch into middle of instruction");
1387 /* allocate the block */
1389 BASICBLOCK_INIT(bptr, m);
1391 bptr->iinstr = /* XXX */ (instruction *) (jd->new_instructions + (jd->new_basicblockindex[p] >> 1));
1393 bptr[-1].icount = /*XXX*/ (new_instruction *)bptr->iinstr - (new_instruction*) bptr[-1].iinstr;
1395 /* bptr->icount is set when the next block is allocated */
1397 jd->new_basicblockindex[p] = b_count;
1401 bptr[-1].next = bptr;
1405 /* set instruction count of last real block */
1408 bptr[-1].icount = (jd->new_instructions + jd->new_instructioncount) - /* XXX */ (new_instruction *) bptr[-1].iinstr;
1411 /* allocate additional block at end */
1413 BASICBLOCK_INIT(bptr,m);
1415 bptr->instack = bptr->outstack = NULL;
1416 bptr->indepth = bptr->outdepth = 0;
1417 bptr->iinstr = NULL;
1421 /* set basicblock pointers in exception table */
1423 if (cd->exceptiontablelength > 0) {
1424 cd->exceptiontable[cd->exceptiontablelength - 1].down = NULL;
1427 for (i = 0; i < cd->exceptiontablelength; ++i) {
1428 p = cd->exceptiontable[i].startpc;
1429 cd->exceptiontable[i].start = jd->new_basicblocks + jd->new_basicblockindex[p];
1431 p = cd->exceptiontable[i].endpc;
1432 cd->exceptiontable[i].end = (p == m->jcodelength) ? (jd->new_basicblocks + jd->new_basicblockcount /*+ 1*/) : (jd->new_basicblocks + jd->new_basicblockindex[p]);
1434 p = cd->exceptiontable[i].handlerpc;
1435 cd->exceptiontable[i].handler = jd->new_basicblocks + jd->new_basicblockindex[p];
1438 /* XXX activate this if you want to try inlining */
1440 for (i = 0; i < m->exceptiontablelength; ++i) {
1441 p = m->exceptiontable[i].startpc;
1442 m->exceptiontable[i].start = jd->new_basicblocks + jd->new_basicblockindex[p];
1444 p = m->exceptiontable[i].endpc;
1445 m->exceptiontable[i].end = (p == m->jcodelength) ? (jd->new_basicblocks + jd->new_basicblockcount /*+ 1*/) : (jd->new_basicblocks + jd->new_basicblockindex[p]);
1447 p = m->exceptiontable[i].handlerpc;
1448 m->exceptiontable[i].handler = jd->new_basicblocks + jd->new_basicblockindex[p];
1452 /* everything's ok */
1456 /*** goto labels for throwing verifier exceptions *************************/
1458 #if defined(ENABLE_VERIFIER)
1460 throw_unexpected_end_of_bytecode:
1461 exceptions_throw_verifyerror(m, "Unexpected end of bytecode");
1464 throw_invalid_bytecode_index:
1465 exceptions_throw_verifyerror(m, "Illegal target of branch instruction");
1468 throw_illegal_local_variable_number:
1469 exceptions_throw_verifyerror(m, "Illegal local variable number");
1472 #endif /* ENABLE_VERIFIER */
1476 bool parse(jitdata *jd)
1481 int p; /* java instruction counter */
1482 int nextp; /* start of next java instruction */
1483 int opcode; /* java opcode */
1484 int i; /* temporary for different uses (ctrs)*/
1485 int ipc = 0; /* intermediate instruction counter */
1486 int b_count = 0; /* basic block counter */
1487 int s_count = 0; /* stack element counter */
1488 bool blockend = false; /* true if basic block end has been reached */
1489 bool iswide = false; /* true if last instruction was a wide*/
1490 instruction *iptr; /* current ptr into instruction array */
1492 u1 *instructionstart; /* 1 for pcs which are valid instr. starts */
1494 constant_classref *cr;
1495 constant_classref *compr;
1497 builtintable_entry *bte;
1499 constant_FMIref *mr;
1501 unresolved_method *um;
1502 resolve_result_t result;
1506 u2 linepcchange = 0;
1508 /* get required compiler data */
1514 /* allocate instruction array and block index table */
1516 /* 1 additional for end ipc */
1517 m->basicblockindex = DMNEW(s4, m->jcodelength + 1);
1518 memset(m->basicblockindex, 0, sizeof(s4) * (m->jcodelength + 1));
1520 instructionstart = DMNEW(u1, m->jcodelength + 1);
1521 memset(instructionstart, 0, sizeof(u1) * (m->jcodelength + 1));
1523 /* 1 additional for TRACEBUILTIN and 4 for MONITORENTER/EXIT */
1524 /* additional MONITOREXITS are reached by branches which are 3 bytes */
1526 iptr = m->instructions = DMNEW(instruction, m->jcodelength + 5);
1528 /* Zero the intermediate instructions array so we don't have any
1529 * invalid pointers in it if we cannot finish analyse_stack(). */
1531 memset(iptr, 0, sizeof(instruction) * (m->jcodelength + 5));
1533 /* compute branch targets of exception table */
1536 &(cd->exceptiontable[cd->exceptiontablelength-1]),
1538 m->exceptiontablelength,
1544 s_count = 1 + m->exceptiontablelength; /* initialize stack element counter */
1546 #if defined(ENABLE_THREADS)
1547 if (checksync && (m->flags & ACC_SYNCHRONIZED))
1548 jd->isleafmethod = false;
1551 /* scan all java instructions */
1555 if (m->linenumbercount == 0) {
1559 linepcchange = m->linenumbers[0].start_pc;
1562 for (p = 0; p < m->jcodelength; p = nextp) {
1564 /* mark this position as a valid instruction start */
1565 instructionstart[p] = 1;
1566 if (linepcchange == p) {
1567 if (m->linenumbercount > lineindex) {
1569 currentline = m->linenumbers[lineindex].line_number;
1571 if (lineindex < m->linenumbercount) {
1572 linepcchange = m->linenumbers[lineindex].start_pc;
1573 if (linepcchange == p)
1574 goto next_linenumber;
1579 /* fetch next opcode */
1581 opcode = SUCK_BE_U1(m->jcode + p);
1583 m->basicblockindex[p] |= (ipc << 1); /*store intermed cnt*/
1585 /* some compilers put a JAVA_NOP after a blockend instruction */
1587 if (blockend && (opcode != JAVA_NOP)) {
1588 /* start new block */
1594 nextp = p + jcommandsize[opcode]; /* compute next instruction start */
1596 CHECK_END_OF_BYTECODE(nextp);
1598 s_count += stackreq[opcode]; /* compute stack element count */
1603 /* pushing constants onto the stack p */
1606 LOADCONST_I(SUCK_BE_S1(m->jcode + p + 1));
1610 LOADCONST_I(SUCK_BE_S2(m->jcode + p + 1));
1614 i = SUCK_BE_U1(m->jcode + p + 1);
1615 goto pushconstantitem;
1619 i = SUCK_BE_U2(m->jcode + p + 1);
1623 #if defined(ENABLE_VERIFIER)
1624 if (i >= m->class->cpcount) {
1625 exceptions_throw_verifyerror(m,
1626 "Attempt to access constant outside range");
1631 switch (m->class->cptags[i]) {
1632 case CONSTANT_Integer:
1633 LOADCONST_I(((constant_integer *) (m->class->cpinfos[i]))->value);
1636 LOADCONST_L(((constant_long *) (m->class->cpinfos[i]))->value);
1638 case CONSTANT_Float:
1639 LOADCONST_F(((constant_float *) (m->class->cpinfos[i]))->value);
1641 case CONSTANT_Double:
1642 LOADCONST_D(((constant_double *) (m->class->cpinfos[i]))->value);
1644 case CONSTANT_String:
1645 LOADCONST_A(literalstring_new((utf *) (m->class->cpinfos[i])));
1647 case CONSTANT_Class:
1648 cr = (constant_classref *) (m->class->cpinfos[i]);
1650 if (!resolve_classref(m, cr, resolveLazy, true,
1654 /* if not resolved, c == NULL */
1657 iptr->target = (void*) 0x02; /* XXX target used temporarily as flag */
1661 iptr->target = (void*) 0x03; /* XXX target used temporarily as flag */
1666 #if defined(ENABLE_VERIFIER)
1668 exceptions_throw_verifyerror(m,
1669 "Invalid constant type to push");
1675 case JAVA_ACONST_NULL:
1679 case JAVA_ICONST_M1:
1686 LOADCONST_I(opcode - JAVA_ICONST_0);
1691 LOADCONST_L(opcode - JAVA_LCONST_0);
1697 LOADCONST_F(opcode - JAVA_FCONST_0);
1702 LOADCONST_D(opcode - JAVA_DCONST_0);
1705 /* loading variables onto the stack */
1710 if (iswide == false) {
1711 i = SUCK_BE_U1(m->jcode + p + 1);
1714 i = SUCK_BE_U2(m->jcode + p + 1);
1718 OP1LOAD_ONEWORD(opcode, i);
1723 if (iswide == false) {
1724 i = SUCK_BE_U1(m->jcode + p + 1);
1727 i = SUCK_BE_U2(m->jcode + p + 1);
1731 OP1LOAD_TWOWORD(opcode, i);
1738 OP1LOAD_ONEWORD(ICMD_ILOAD, opcode - JAVA_ILOAD_0);
1745 OP1LOAD_TWOWORD(ICMD_LLOAD, opcode - JAVA_LLOAD_0);
1752 OP1LOAD_ONEWORD(ICMD_FLOAD, opcode - JAVA_FLOAD_0);
1759 OP1LOAD_TWOWORD(ICMD_DLOAD, opcode - JAVA_DLOAD_0);
1766 OP1LOAD_ONEWORD(ICMD_ALOAD, opcode - JAVA_ALOAD_0);
1769 /* storing stack values into local variables */
1774 if (iswide == false) {
1775 i = SUCK_BE_U1(m->jcode + p + 1);
1778 i = SUCK_BE_U2(m->jcode + p + 1);
1782 OP1STORE_ONEWORD(opcode, i);
1787 if (iswide == false) {
1788 i = SUCK_BE_U1(m->jcode + p + 1);
1791 i = SUCK_BE_U2(m->jcode + p + 1);
1795 OP1STORE_TWOWORD(opcode, i);
1802 OP1STORE_ONEWORD(ICMD_ISTORE, opcode - JAVA_ISTORE_0);
1809 OP1STORE_TWOWORD(ICMD_LSTORE, opcode - JAVA_LSTORE_0);
1816 OP1STORE_ONEWORD(ICMD_FSTORE, opcode - JAVA_FSTORE_0);
1823 OP1STORE_TWOWORD(ICMD_DSTORE, opcode - JAVA_DSTORE_0);
1830 OP1STORE_ONEWORD(ICMD_ASTORE, opcode - JAVA_ASTORE_0);
1837 if (iswide == false) {
1838 i = SUCK_BE_U1(m->jcode + p + 1);
1839 v = SUCK_BE_S1(m->jcode + p + 2);
1843 i = SUCK_BE_U2(m->jcode + p + 1);
1844 v = SUCK_BE_S2(m->jcode + p + 3);
1853 /* wider index for loading, storing and incrementing */
1860 /* managing arrays ****************************************************/
1863 switch (SUCK_BE_S1(m->jcode + p + 1)) {
1865 bte = builtintable_get_internal(BUILTIN_newarray_boolean);
1868 bte = builtintable_get_internal(BUILTIN_newarray_char);
1871 bte = builtintable_get_internal(BUILTIN_newarray_float);
1874 bte = builtintable_get_internal(BUILTIN_newarray_double);
1877 bte = builtintable_get_internal(BUILTIN_newarray_byte);
1880 bte = builtintable_get_internal(BUILTIN_newarray_short);
1883 bte = builtintable_get_internal(BUILTIN_newarray_int);
1886 bte = builtintable_get_internal(BUILTIN_newarray_long);
1888 #if defined(ENABLE_VERIFIER)
1890 exceptions_throw_verifyerror(m,
1891 "Invalid array-type to create");
1895 BUILTIN(bte, true, NULL, currentline);
1898 case JAVA_ANEWARRAY:
1899 i = SUCK_BE_U2(m->jcode + p + 1);
1900 compr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
1904 if (!(cr = class_get_classref_multiarray_of(1, compr)))
1907 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
1910 LOADCONST_A_BUILTIN(c, cr);
1911 bte = builtintable_get_internal(BUILTIN_newarray);
1912 BUILTIN(bte, true, NULL, currentline);
1916 case JAVA_MULTIANEWARRAY:
1917 jd->isleafmethod = false;
1918 i = SUCK_BE_U2(m->jcode + p + 1);
1920 s4 v = SUCK_BE_U1(m->jcode + p + 3);
1922 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
1926 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
1929 /* if unresolved, c == NULL */
1930 OP2AT(opcode, v, c, cr, currentline);
1941 case JAVA_IFNONNULL:
1942 case JAVA_IF_ICMPEQ:
1943 case JAVA_IF_ICMPNE:
1944 case JAVA_IF_ICMPLT:
1945 case JAVA_IF_ICMPGT:
1946 case JAVA_IF_ICMPLE:
1947 case JAVA_IF_ICMPGE:
1948 case JAVA_IF_ACMPEQ:
1949 case JAVA_IF_ACMPNE:
1952 i = p + SUCK_BE_S2(m->jcode + p + 1);
1953 CHECK_BYTECODE_INDEX(i);
1961 i = p + SUCK_BE_S4(m->jcode + p + 1);
1962 CHECK_BYTECODE_INDEX(i);
1969 if (iswide == false) {
1970 i = SUCK_BE_U1(m->jcode + p + 1);
1973 i = SUCK_BE_U2(m->jcode + p + 1);
1979 OP1LOAD_ONEWORD(opcode, i);
1989 /* zero val.a so no patcher is inserted */
1990 /* the type checker may set this later */
1997 /* zero val.a so no patcher is inserted */
1998 /* the type checker may set this later */
2004 /* table jumps ********************************************************/
2006 case JAVA_LOOKUPSWITCH:
2010 #if defined(ENABLE_VERIFIER)
2015 nextp = ALIGN((p + 1), 4);
2017 CHECK_END_OF_BYTECODE(nextp + 8);
2019 tablep = (s4 *) (m->jcode + nextp);
2021 OP2A(opcode, 0, tablep, currentline);
2023 /* default target */
2025 j = p + SUCK_BE_S4(m->jcode + nextp);
2026 *tablep = j; /* restore for little endian */
2029 CHECK_BYTECODE_INDEX(j);
2032 /* number of pairs */
2034 num = SUCK_BE_U4(m->jcode + nextp);
2039 CHECK_END_OF_BYTECODE(nextp + 8 * num);
2041 for (i = 0; i < num; i++) {
2044 j = SUCK_BE_S4(m->jcode + nextp);
2045 *tablep = j; /* restore for little endian */
2049 #if defined(ENABLE_VERIFIER)
2050 /* check if the lookup table is sorted correctly */
2052 if (i && (j <= prevvalue)) {
2053 exceptions_throw_verifyerror(m, "Unsorted lookup switch");
2061 j = p + SUCK_BE_S4(m->jcode + nextp);
2062 *tablep = j; /* restore for little endian */
2065 CHECK_BYTECODE_INDEX(j);
2073 case JAVA_TABLESWITCH:
2079 nextp = ALIGN((p + 1), 4);
2081 CHECK_END_OF_BYTECODE(nextp + 12);
2083 tablep = (s4 *) (m->jcode + nextp);
2085 OP2A(opcode, 0, tablep, currentline);
2087 /* default target */
2089 j = p + SUCK_BE_S4(m->jcode + nextp);
2090 *tablep = j; /* restore for little endian */
2093 CHECK_BYTECODE_INDEX(j);
2098 j = SUCK_BE_S4(m->jcode + nextp);
2099 *tablep = j; /* restore for little endian */
2105 num = SUCK_BE_S4(m->jcode + nextp);
2106 *tablep = num; /* restore for little endian */
2110 num -= j; /* difference of upper - lower */
2112 #if defined(ENABLE_VERIFIER)
2114 exceptions_throw_verifyerror(m,
2115 "invalid TABLESWITCH: upper bound < lower bound");
2120 CHECK_END_OF_BYTECODE(nextp + 4 * (num + 1));
2122 for (i = 0; i <= num; i++) {
2123 j = p + SUCK_BE_S4(m->jcode + nextp);
2124 *tablep = j; /* restore for little endian */
2127 CHECK_BYTECODE_INDEX(j);
2135 /* load and store of object fields ************************************/
2139 jd->isleafmethod = false;
2142 case JAVA_GETSTATIC:
2143 case JAVA_PUTSTATIC:
2147 constant_FMIref *fr;
2148 unresolved_field *uf;
2150 i = SUCK_BE_U2(m->jcode + p + 1);
2151 fr = class_getconstant(m->class, i, CONSTANT_Fieldref);
2155 OP2A_NOINC(opcode, fr->parseddesc.fd->type, fr, currentline);
2157 /* only with -noverify, otherwise the typechecker does this */
2159 #if defined(ENABLE_VERIFIER)
2160 if (!JITDATA_HAS_FLAG_VERIFY(jd)) {
2162 result = resolve_field_lazy(iptr, NULL, m);
2163 if (result == resolveFailed)
2166 if (result != resolveSucceeded) {
2167 uf = create_unresolved_field(m->class, m, iptr);
2172 /* store the unresolved_field pointer */
2174 /* XXX this will be changed */
2176 iptr->target = (void*) 0x01; /* XXX target temporarily used as flag */
2179 iptr->target = NULL;
2181 #if defined(ENABLE_VERIFIER)
2184 iptr->target = NULL;
2192 /* method invocation **************************************************/
2194 case JAVA_INVOKESTATIC:
2195 i = SUCK_BE_U2(m->jcode + p + 1);
2196 mr = class_getconstant(m->class, i, CONSTANT_Methodref);
2200 md = mr->parseddesc.md;
2203 if (!descriptor_params_from_paramtypes(md, ACC_STATIC))
2208 case JAVA_INVOKEINTERFACE:
2209 i = SUCK_BE_U2(m->jcode + p + 1);
2210 mr = class_getconstant(m->class, i, CONSTANT_InterfaceMethodref);
2212 goto invoke_nonstatic_method;
2214 case JAVA_INVOKESPECIAL:
2215 case JAVA_INVOKEVIRTUAL:
2216 i = SUCK_BE_U2(m->jcode + p + 1);
2217 mr = class_getconstant(m->class, i, CONSTANT_Methodref);
2219 invoke_nonstatic_method:
2223 md = mr->parseddesc.md;
2226 if (!descriptor_params_from_paramtypes(md, 0))
2230 jd->isleafmethod = false;
2232 OP2A_NOINC(opcode, 0, mr, currentline);
2234 /* only with -noverify, otherwise the typechecker does this */
2236 #if defined(ENABLE_VERIFIER)
2237 if (!JITDATA_HAS_FLAG_VERIFY(jd)) {
2239 result = resolve_method_lazy(iptr, NULL, m);
2240 if (result == resolveFailed)
2243 if (result != resolveSucceeded) {
2244 um = create_unresolved_method(m->class, m, iptr);
2249 /* store the unresolved_method pointer */
2251 /* XXX this will be changed */
2253 iptr->target = (void*) 0x01; /* XXX target temporarily used as flag */
2256 /* the method could be resolved */
2257 iptr->target = NULL;
2259 #if defined(ENABLE_VERIFIER)
2262 iptr->target = NULL;
2268 /* miscellaneous object operations ************************************/
2271 i = SUCK_BE_U2(m->jcode + p + 1);
2272 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
2276 if (!resolve_classref(m, cr, resolveLazy, true, true,
2280 LOADCONST_A_BUILTIN(c, cr);
2281 bte = builtintable_get_internal(BUILTIN_new);
2282 BUILTIN(bte, true, NULL, currentline);
2286 case JAVA_CHECKCAST:
2287 i = SUCK_BE_U2(m->jcode + p + 1);
2288 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
2292 if (!resolve_classref(m, cr, resolveLazy, true,
2296 if (cr->name->text[0] == '[') {
2297 /* array type cast-check */
2298 OP2AT(opcode, 0, c, cr, currentline);
2299 jd->isleafmethod = false;
2303 /* object type cast-check */
2304 OP2AT(opcode, 1, c, cr, currentline);
2308 case JAVA_INSTANCEOF:
2309 i = SUCK_BE_U2(m->jcode + p + 1);
2310 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
2314 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
2317 if (cr->name->text[0] == '[') {
2318 /* array type cast-check */
2319 LOADCONST_A_BUILTIN(c, cr);
2320 bte = builtintable_get_internal(BUILTIN_arrayinstanceof);
2321 BUILTIN(bte, false, NULL, currentline);
2326 /* object type cast-check */
2327 OP2AT(opcode, 1, c, cr, currentline);
2331 case JAVA_MONITORENTER:
2332 #if defined(ENABLE_THREADS)
2335 bte = builtintable_get_internal(LOCK_monitor_enter);
2336 BUILTIN(bte, false, NULL, currentline);
2346 case JAVA_MONITOREXIT:
2347 #if defined(ENABLE_THREADS)
2349 bte = builtintable_get_internal(LOCK_monitor_exit);
2350 BUILTIN(bte, false, NULL, currentline);
2359 /* any other basic operation ******************************************/
2362 #if !SUPPORT_DIVISION
2363 bte = builtintable_get_internal(BUILTIN_idiv);
2364 OP2A(opcode, bte->md->paramcount, bte, currentline);
2365 jd->isleafmethod = false;
2372 #if !SUPPORT_DIVISION
2373 bte = builtintable_get_internal(BUILTIN_irem);
2374 OP2A(opcode, bte->md->paramcount, bte, currentline);
2375 jd->isleafmethod = false;
2382 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
2383 bte = builtintable_get_internal(BUILTIN_ldiv);
2384 OP2A(opcode, bte->md->paramcount, bte, currentline);
2385 jd->isleafmethod = false;
2392 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
2393 bte = builtintable_get_internal(BUILTIN_lrem);
2394 OP2A(opcode, bte->md->paramcount, bte, currentline);
2395 jd->isleafmethod = false;
2402 #if defined(__I386__)
2405 bte = builtintable_get_internal(BUILTIN_frem);
2406 BUILTIN(bte, false, NULL, currentline);
2411 #if defined(__I386__)
2414 bte = builtintable_get_internal(BUILTIN_drem);
2415 BUILTIN(bte, false, NULL, currentline);
2420 #if defined(__ALPHA__)
2422 bte = builtintable_get_internal(BUILTIN_f2i);
2423 BUILTIN(bte, false, NULL, currentline);
2433 #if defined(__ALPHA__)
2435 bte = builtintable_get_internal(BUILTIN_f2l);
2436 BUILTIN(bte, false, NULL, currentline);
2446 #if defined(__ALPHA__)
2448 bte = builtintable_get_internal(BUILTIN_d2i);
2449 BUILTIN(bte, false, NULL, currentline);
2459 #if defined(__ALPHA__)
2461 bte = builtintable_get_internal(BUILTIN_d2l);
2462 BUILTIN(bte, false, NULL, currentline);
2471 /* check for invalid opcodes if the verifier is enabled */
2472 #if defined(ENABLE_VERIFIER)
2473 case JAVA_BREAKPOINT:
2474 exceptions_throw_verifyerror(m, "Quick instructions shouldn't appear yet.");
2477 case 186: /* unused opcode */
2531 exceptions_throw_verifyerror(m, "Illegal opcode %d at instr %d\n",
2535 #endif /* defined(ENABLE_VERIFIER) */
2538 /* straight-forward translation to ICMD */
2544 #if defined(ENABLE_VERIFIER)
2545 /* If WIDE was used correctly, iswide should have been reset by now. */
2547 exceptions_throw_verifyerror(m,
2548 "Illegal instruction: WIDE before incompatible opcode");
2551 #endif /* defined(ENABLE_VERIFIER) */
2555 #if defined(ENABLE_VERIFIER)
2556 if (p != m->jcodelength) {
2557 exceptions_throw_verifyerror(m,
2558 "Command-sequence crosses code-boundary");
2563 exceptions_throw_verifyerror(m, "Falling off the end of the code");
2566 #endif /* defined(ENABLE_VERIFIER) */
2568 /* adjust block count if target 0 is not first intermediate instruction */
2570 if (!m->basicblockindex[0] || (m->basicblockindex[0] > 1))
2573 /* copy local to method variables */
2575 m->instructioncount = ipc;
2576 m->basicblockcount = b_count;
2577 m->stackcount = s_count + m->basicblockcount * m->maxstack;
2579 /* allocate stack table */
2581 m->stack = DMNEW(stackelement, m->stackcount);
2586 bptr = m->basicblocks = DMNEW(basicblock, b_count + 1); /* one more for end ipc */
2591 /* additional block if target 0 is not first intermediate instruction */
2593 if (!m->basicblockindex[0] || (m->basicblockindex[0] > 1)) {
2594 BASICBLOCK_INIT(bptr,m);
2596 bptr->iinstr = m->instructions;
2597 /* bptr->icount is set when the next block is allocated */
2601 bptr[-1].next = bptr;
2604 /* allocate blocks */
2606 for (p = 0; p < m->jcodelength; p++) {
2607 if (m->basicblockindex[p] & 1) {
2608 /* Check if this block starts at the beginning of an */
2610 #if defined(ENABLE_VERIFIER)
2611 if (!instructionstart[p]) {
2612 exceptions_throw_verifyerror(m,
2613 "Branch into middle of instruction");
2618 /* allocate the block */
2620 BASICBLOCK_INIT(bptr,m);
2622 bptr->iinstr = m->instructions + (m->basicblockindex[p] >> 1);
2624 bptr[-1].icount = bptr->iinstr - bptr[-1].iinstr;
2626 /* bptr->icount is set when the next block is allocated */
2628 m->basicblockindex[p] = b_count;
2632 bptr[-1].next = bptr;
2636 /* set instruction count of last real block */
2639 bptr[-1].icount = (m->instructions + m->instructioncount) - bptr[-1].iinstr;
2642 /* allocate additional block at end */
2644 BASICBLOCK_INIT(bptr,m);
2646 bptr->instack = bptr->outstack = NULL;
2647 bptr->indepth = bptr->outdepth = 0;
2648 bptr->iinstr = NULL;
2652 /* set basicblock pointers in exception table */
2654 if (cd->exceptiontablelength > 0) {
2655 cd->exceptiontable[cd->exceptiontablelength - 1].down = NULL;
2658 for (i = 0; i < cd->exceptiontablelength; ++i) {
2659 p = cd->exceptiontable[i].startpc;
2660 cd->exceptiontable[i].start = m->basicblocks + m->basicblockindex[p];
2662 p = cd->exceptiontable[i].endpc;
2663 cd->exceptiontable[i].end = (p == m->jcodelength) ? (m->basicblocks + m->basicblockcount /*+ 1*/) : (m->basicblocks + m->basicblockindex[p]);
2665 p = cd->exceptiontable[i].handlerpc;
2666 cd->exceptiontable[i].handler = m->basicblocks + m->basicblockindex[p];
2669 /* XXX activate this if you want to try inlining */
2671 for (i = 0; i < m->exceptiontablelength; ++i) {
2672 p = m->exceptiontable[i].startpc;
2673 m->exceptiontable[i].start = m->basicblocks + m->basicblockindex[p];
2675 p = m->exceptiontable[i].endpc;
2676 m->exceptiontable[i].end = (p == m->jcodelength) ? (m->basicblocks + m->basicblockcount /*+ 1*/) : (m->basicblocks + m->basicblockindex[p]);
2678 p = m->exceptiontable[i].handlerpc;
2679 m->exceptiontable[i].handler = m->basicblocks + m->basicblockindex[p];
2685 /* everything's ok */
2689 #if defined(ENABLE_VERIFIER)
2691 throw_unexpected_end_of_bytecode:
2692 exceptions_throw_verifyerror(m, "Unexpected end of bytecode");
2695 throw_invalid_bytecode_index:
2696 exceptions_throw_verifyerror(m, "Illegal target of branch instruction");
2699 throw_illegal_local_variable_number:
2700 exceptions_throw_verifyerror(m, "Illegal local variable number");
2703 #endif /* ENABLE_VERIFIER */
2708 * These are local overrides for various environment variables in Emacs.
2709 * Please do not remove this and leave it at the end of the file, where
2710 * Emacs will automagically detect them.
2711 * ---------------------------------------------------------------------
2714 * indent-tabs-mode: t
2718 * vim:noexpandtab:sw=4:ts=4: