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 5370 2006-09-06 13:46:37Z christian $
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 /*** macro for checking the length of the bytecode ***/
149 #if defined(ENABLE_VERIFIER)
150 #define CHECK_END_OF_BYTECODE(neededlength) \
152 if ((neededlength) > m->jcodelength) \
153 goto throw_unexpected_end_of_bytecode; \
155 #else /* !ENABLE_VERIFIER */
156 #define CHECK_END_OF_BYTECODE(neededlength)
157 #endif /* ENABLE_VERIFIER */
159 bool new_parse(jitdata *jd)
161 methodinfo *m; /* method being parsed */
164 int p; /* java instruction counter */
165 int nextp; /* start of next java instruction */
166 int opcode; /* java opcode */
167 int i; /* temporary for different uses (ctrs) */
168 int ipc = 0; /* intermediate instruction counter */
169 int b_count = 0; /* basic block counter */
170 int s_count = 0; /* stack element counter */
171 bool blockend = false; /* true if basic block end has been reached */
172 bool iswide = false; /* true if last instruction was a wide */
173 instruction *iptr; /* current ptr into instruction array */
174 u1 *instructionstart; /* 1 for pcs which are valid instr. starts */
175 constant_classref *cr;
176 constant_classref *compr;
178 builtintable_entry *bte;
181 unresolved_method *um;
182 resolve_result_t result;
190 int *local_map; /* local pointer to renaming structore */
191 /* is assigned to rd->local_map at the end */
193 /* get required compiler data */
200 /* allocate buffers for local variable renaming */
201 local_map = DMNEW(int, cd->maxlocals * 5);
202 for (i = 0; i < cd->maxlocals; i++) {
203 local_map[i * 5 + 0] = 0;
204 local_map[i * 5 + 1] = 0;
205 local_map[i * 5 + 2] = 0;
206 local_map[i * 5 + 3] = 0;
207 local_map[i * 5 + 4] = 0;
211 /* allocate instruction array and block index table */
213 /* 1 additional for end ipc */
214 jd->new_basicblockindex = DMNEW(s4, m->jcodelength + 1);
215 memset(jd->new_basicblockindex, 0, sizeof(s4) * (m->jcodelength + 1));
217 instructionstart = DMNEW(u1, m->jcodelength + 1);
218 memset(instructionstart, 0, sizeof(u1) * (m->jcodelength + 1));
220 /* IMPORTANT: We assume that parsing creates at most one instruction per */
221 /* byte of original bytecode! */
223 iptr = jd->new_instructions = DMNEW(instruction, m->jcodelength);
225 /* compute branch targets of exception table */
227 if (!new_fillextable(jd, m,
228 &(cd->exceptiontable[cd->exceptiontablelength-1]),
230 m->exceptiontablelength,
236 s_count = 1 + m->exceptiontablelength; /* initialize stack element counter */
238 #if defined(ENABLE_THREADS)
239 if (checksync && (m->flags & ACC_SYNCHRONIZED))
240 jd->isleafmethod = false;
243 /* setup line number info */
248 if (m->linenumbercount == 0) {
252 linepcchange = m->linenumbers[0].start_pc;
255 /*** LOOP OVER ALL BYTECODE INSTRUCTIONS **********************************/
257 for (p = 0; p < m->jcodelength; p = nextp) {
259 /* mark this position as a valid instruction start */
261 instructionstart[p] = 1;
263 /* change the current line number, if necessary */
265 /* XXX rewrite this using pointer arithmetic */
267 if (linepcchange == p) {
268 if (m->linenumbercount > lineindex) {
270 currentline = m->linenumbers[lineindex].line_number;
272 if (lineindex < m->linenumbercount) {
273 linepcchange = m->linenumbers[lineindex].start_pc;
274 if (linepcchange == p)
275 goto next_linenumber;
280 /* fetch next opcode */
282 opcode = SUCK_BE_U1(m->jcode + p);
284 /* store intermediate instruction count (bit 0 mark block starts) */
286 jd->new_basicblockindex[p] |= (ipc << 1);
288 /* some compilers put a JAVA_NOP after a blockend instruction */
290 if (blockend && (opcode != JAVA_NOP)) {
291 /* start new block */
297 /* compute next instruction start */
299 nextp = p + jcommandsize[opcode];
301 CHECK_END_OF_BYTECODE(nextp);
303 /* add stack elements produced by this instruction */
305 s_count += stackreq[opcode];
307 /* translate this bytecode instruction */
314 /* pushing constants onto the stack ***********************************/
317 OP_LOADCONST_I(SUCK_BE_S1(m->jcode + p + 1));
321 OP_LOADCONST_I(SUCK_BE_S2(m->jcode + p + 1));
325 i = SUCK_BE_U1(m->jcode + p + 1);
326 goto pushconstantitem;
330 i = SUCK_BE_U2(m->jcode + p + 1);
334 #if defined(ENABLE_VERIFIER)
335 if (i >= m->class->cpcount) {
336 exceptions_throw_verifyerror(m,
337 "Attempt to access constant outside range");
342 switch (m->class->cptags[i]) {
343 case CONSTANT_Integer:
344 OP_LOADCONST_I(((constant_integer *) (m->class->cpinfos[i]))->value);
347 OP_LOADCONST_L(((constant_long *) (m->class->cpinfos[i]))->value);
350 OP_LOADCONST_F(((constant_float *) (m->class->cpinfos[i]))->value);
352 case CONSTANT_Double:
353 OP_LOADCONST_D(((constant_double *) (m->class->cpinfos[i]))->value);
355 case CONSTANT_String:
356 OP_LOADCONST_STRING(literalstring_new((utf *) (m->class->cpinfos[i])));
359 cr = (constant_classref *) (m->class->cpinfos[i]);
361 if (!resolve_classref(m, cr, resolveLazy, true,
365 /* if not resolved, c == NULL */
367 OP_LOADCONST_CLASSINFO_OR_CLASSREF(c, cr, 0 /* no extra flags */);
371 #if defined(ENABLE_VERIFIER)
373 exceptions_throw_verifyerror(m,
374 "Invalid constant type to push");
380 case JAVA_ACONST_NULL:
391 OP_LOADCONST_I(opcode - JAVA_ICONST_0);
396 OP_LOADCONST_L(opcode - JAVA_LCONST_0);
402 OP_LOADCONST_F(opcode - JAVA_FCONST_0);
407 OP_LOADCONST_D(opcode - JAVA_DCONST_0);
410 /* local variable access instructions *********************************/
415 if (iswide == false) {
416 i = SUCK_BE_U1(m->jcode + p + 1);
419 i = SUCK_BE_U2(m->jcode + p + 1);
423 OP_LOAD_ONEWORD(opcode, i, opcode - JAVA_ILOAD);
428 if (iswide == false) {
429 i = SUCK_BE_U1(m->jcode + p + 1);
432 i = SUCK_BE_U2(m->jcode + p + 1);
436 OP_LOAD_TWOWORD(opcode, i, opcode - JAVA_ILOAD);
443 OP_LOAD_ONEWORD(ICMD_ILOAD, opcode - JAVA_ILOAD_0, TYPE_INT);
450 OP_LOAD_TWOWORD(ICMD_LLOAD, opcode - JAVA_LLOAD_0, TYPE_LNG);
457 OP_LOAD_ONEWORD(ICMD_FLOAD, opcode - JAVA_FLOAD_0, TYPE_FLT);
464 OP_LOAD_TWOWORD(ICMD_DLOAD, opcode - JAVA_DLOAD_0, TYPE_DBL);
471 OP_LOAD_ONEWORD(ICMD_ALOAD, opcode - JAVA_ALOAD_0, TYPE_ADR);
477 if (iswide == false) {
478 i = SUCK_BE_U1(m->jcode + p + 1);
481 i = SUCK_BE_U2(m->jcode + p + 1);
485 OP_STORE_ONEWORD(opcode, i, opcode - JAVA_ISTORE);
490 if (iswide == false) {
491 i = SUCK_BE_U1(m->jcode + p + 1);
494 i = SUCK_BE_U2(m->jcode + p + 1);
498 OP_STORE_TWOWORD(opcode, i, opcode - JAVA_ISTORE);
505 OP_STORE_ONEWORD(ICMD_ISTORE, opcode - JAVA_ISTORE_0, TYPE_INT);
512 OP_STORE_TWOWORD(ICMD_LSTORE, opcode - JAVA_LSTORE_0, TYPE_LNG);
519 OP_STORE_ONEWORD(ICMD_FSTORE, opcode - JAVA_FSTORE_0, TYPE_FLT);
526 OP_STORE_TWOWORD(ICMD_DSTORE, opcode - JAVA_DSTORE_0, TYPE_DBL);
533 OP_STORE_ONEWORD(ICMD_ASTORE, opcode - JAVA_ASTORE_0, TYPE_ADR);
540 if (iswide == false) {
541 i = SUCK_BE_U1(m->jcode + p + 1);
542 v = SUCK_BE_S1(m->jcode + p + 2);
546 i = SUCK_BE_U2(m->jcode + p + 1);
547 v = SUCK_BE_S2(m->jcode + p + 3);
552 LOCALTYPE_USED(i, TYPE_INT);
553 OP_LOCALINDEX_I(opcode, i, v);
557 /* wider index for loading, storing and incrementing ******************/
564 /* managing arrays ****************************************************/
567 switch (SUCK_BE_S1(m->jcode + p + 1)) {
569 bte = builtintable_get_internal(BUILTIN_newarray_boolean);
572 bte = builtintable_get_internal(BUILTIN_newarray_char);
575 bte = builtintable_get_internal(BUILTIN_newarray_float);
578 bte = builtintable_get_internal(BUILTIN_newarray_double);
581 bte = builtintable_get_internal(BUILTIN_newarray_byte);
584 bte = builtintable_get_internal(BUILTIN_newarray_short);
587 bte = builtintable_get_internal(BUILTIN_newarray_int);
590 bte = builtintable_get_internal(BUILTIN_newarray_long);
592 #if defined(ENABLE_VERIFIER)
594 exceptions_throw_verifyerror(m, "Invalid array-type to create");
598 OP_BUILTIN_CHECK_EXCEPTION(bte);
602 i = SUCK_BE_U2(m->jcode + p + 1);
603 compr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
607 if (!(cr = class_get_classref_multiarray_of(1, compr)))
610 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
613 OP_LOADCONST_CLASSINFO_OR_CLASSREF(c, cr, INS_FLAG_NOCHECK);
614 bte = builtintable_get_internal(BUILTIN_newarray);
615 OP_BUILTIN_CHECK_EXCEPTION(bte);
619 case JAVA_MULTIANEWARRAY:
620 jd->isleafmethod = false;
621 i = SUCK_BE_U2(m->jcode + p + 1);
623 s4 v = SUCK_BE_U1(m->jcode + p + 3);
625 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
629 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
632 /* if unresolved, c == NULL */
634 iptr->s1.argcount = v;
635 OP_S3_CLASSINFO_OR_CLASSREF(opcode, c, cr, 0 /* flags */);
639 /* control flow instructions ******************************************/
658 i = p + SUCK_BE_S2(m->jcode + p + 1);
659 CHECK_BYTECODE_INDEX(i);
662 OP_INSINDEX(opcode, i);
666 i = p + SUCK_BE_S4(m->jcode + p + 1);
667 CHECK_BYTECODE_INDEX(i);
670 OP_INSINDEX(opcode, i);
674 i = p + SUCK_BE_S2(m->jcode + p + 1);
676 CHECK_BYTECODE_INDEX(i);
679 OP_PREPARE_ZEROFLAGS(JAVA_JSR);
680 iptr->sx.s23.s3.jsrtarget.insindex = i;
685 i = p + SUCK_BE_S4(m->jcode + p + 1);
689 if (iswide == false) {
690 i = SUCK_BE_U1(m->jcode + p + 1);
693 i = SUCK_BE_U2(m->jcode + p + 1);
699 OP_LOAD_ONEWORD(opcode, i, TYPE_ADR);
709 /* XXX ARETURN will need a flag in the typechecker */
715 /* XXX ATHROW will need a flag in the typechecker */
720 /* table jumps ********************************************************/
722 case JAVA_LOOKUPSWITCH:
725 lookup_target_t *lookup;
726 #if defined(ENABLE_VERIFIER)
730 nextp = ALIGN((p + 1), 4);
732 CHECK_END_OF_BYTECODE(nextp + 8);
734 OP_PREPARE_ZEROFLAGS(opcode);
738 j = p + SUCK_BE_S4(m->jcode + nextp);
739 iptr->sx.s23.s3.lookupdefault.insindex = j;
741 CHECK_BYTECODE_INDEX(j);
744 /* number of pairs */
746 num = SUCK_BE_U4(m->jcode + nextp);
747 iptr->sx.s23.s2.lookupcount = num;
750 /* allocate the intermediate code table */
752 lookup = DMNEW(lookup_target_t, num);
753 iptr->dst.lookup = lookup;
755 /* iterate over the lookup table */
757 CHECK_END_OF_BYTECODE(nextp + 8 * num);
759 for (i = 0; i < num; i++) {
762 j = SUCK_BE_S4(m->jcode + nextp);
767 #if defined(ENABLE_VERIFIER)
768 /* check if the lookup table is sorted correctly */
770 if (i && (j <= prevvalue)) {
771 exceptions_throw_verifyerror(m, "Unsorted lookup switch");
778 j = p + SUCK_BE_S4(m->jcode + nextp);
779 lookup->target.insindex = j;
782 CHECK_BYTECODE_INDEX(j);
791 case JAVA_TABLESWITCH:
795 branch_target_t *table;
798 nextp = ALIGN((p + 1), 4);
800 CHECK_END_OF_BYTECODE(nextp + 12);
802 OP_PREPARE_ZEROFLAGS(opcode);
806 deftarget = p + SUCK_BE_S4(m->jcode + nextp);
808 CHECK_BYTECODE_INDEX(deftarget);
809 MARK_BASICBLOCK(deftarget);
813 j = SUCK_BE_S4(m->jcode + nextp);
814 iptr->sx.s23.s2.tablelow = j;
819 num = SUCK_BE_S4(m->jcode + nextp);
820 iptr->sx.s23.s3.tablehigh = num;
823 /* calculate the number of table entries */
827 #if defined(ENABLE_VERIFIER)
829 exceptions_throw_verifyerror(m,
830 "invalid TABLESWITCH: upper bound < lower bound");
834 /* create the intermediate code table */
835 /* the first entry is the default target */
837 table = MNEW(branch_target_t, 1 + num);
838 iptr->dst.table = table;
839 (table++)->insindex = deftarget;
841 /* iterate over the target table */
843 CHECK_END_OF_BYTECODE(nextp + 4 * num);
845 for (i = 0; i < num; i++) {
846 j = p + SUCK_BE_S4(m->jcode + nextp);
847 (table++)->insindex = j;
849 CHECK_BYTECODE_INDEX(j);
858 /* load and store of object fields ************************************/
862 jd->isleafmethod = false;
871 unresolved_field *uf;
873 i = SUCK_BE_U2(m->jcode + p + 1);
874 fr = class_getconstant(m->class, i, CONSTANT_Fieldref);
878 OP_PREPARE_ZEROFLAGS(opcode);
879 iptr->sx.s23.s3.fmiref = fr;
881 /* only with -noverify, otherwise the typechecker does this */
883 #if defined(ENABLE_VERIFIER)
884 if (!JITDATA_HAS_FLAG_VERIFY(jd)) {
886 result = new_resolve_field_lazy(iptr, m);
887 if (result == resolveFailed)
890 if (result != resolveSucceeded) {
891 uf = new_create_unresolved_field(m->class, m, iptr);
896 /* store the unresolved_field pointer */
898 iptr->sx.s23.s3.uf = uf;
899 iptr->flags.bits = INS_FLAG_UNRESOLVED;
901 #if defined(ENABLE_VERIFIER)
909 /* method invocation **************************************************/
911 case JAVA_INVOKESTATIC:
912 i = SUCK_BE_U2(m->jcode + p + 1);
913 mr = class_getconstant(m->class, i, CONSTANT_Methodref);
917 md = mr->parseddesc.md;
920 if (!descriptor_params_from_paramtypes(md, ACC_STATIC))
925 case JAVA_INVOKEINTERFACE:
926 i = SUCK_BE_U2(m->jcode + p + 1);
928 mr = class_getconstant(m->class, i,
929 CONSTANT_InterfaceMethodref);
931 goto invoke_nonstatic_method;
933 case JAVA_INVOKESPECIAL:
934 case JAVA_INVOKEVIRTUAL:
935 i = SUCK_BE_U2(m->jcode + p + 1);
936 mr = class_getconstant(m->class, i, CONSTANT_Methodref);
938 invoke_nonstatic_method:
942 md = mr->parseddesc.md;
945 if (!descriptor_params_from_paramtypes(md, 0))
949 jd->isleafmethod = false;
951 OP_PREPARE_ZEROFLAGS(opcode);
952 iptr->sx.s23.s3.fmiref = mr;
954 /* only with -noverify, otherwise the typechecker does this */
956 #if defined(ENABLE_VERIFIER)
957 if (!JITDATA_HAS_FLAG_VERIFY(jd)) {
959 result = new_resolve_method_lazy(iptr, m);
960 if (result == resolveFailed)
963 if (result != resolveSucceeded) {
964 um = new_create_unresolved_method(m->class, m, iptr);
969 /* store the unresolved_method pointer */
971 iptr->sx.s23.s3.um = um;
972 iptr->flags.bits = INS_FLAG_UNRESOLVED;
974 #if defined(ENABLE_VERIFIER)
980 /* instructions taking class arguments ********************************/
983 i = SUCK_BE_U2(m->jcode + p + 1);
984 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
988 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
991 OP_LOADCONST_CLASSINFO_OR_CLASSREF(c, cr, INS_FLAG_NOCHECK);
992 bte = builtintable_get_internal(BUILTIN_new);
993 OP_BUILTIN_CHECK_EXCEPTION(bte);
998 i = SUCK_BE_U2(m->jcode + p + 1);
999 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
1003 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
1006 if (cr->name->text[0] == '[') {
1007 /* array type cast-check */
1008 flags = INS_FLAG_ARRAY;
1009 jd->isleafmethod = false;
1012 /* object type cast-check */
1015 OP_S3_CLASSINFO_OR_CLASSREF(opcode, c, cr, flags);
1018 case JAVA_INSTANCEOF:
1019 i = SUCK_BE_U2(m->jcode + p + 1);
1020 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
1024 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
1027 if (cr->name->text[0] == '[') {
1028 /* array type cast-check */
1029 OP_LOADCONST_CLASSINFO_OR_CLASSREF(c, cr, INS_FLAG_NOCHECK);
1030 bte = builtintable_get_internal(BUILTIN_arrayinstanceof);
1031 OP_BUILTIN_NO_EXCEPTION(bte);
1035 /* object type cast-check */
1036 OP_S3_CLASSINFO_OR_CLASSREF(opcode, c, cr, 0 /* flags*/);
1040 /* synchronization instructions ***************************************/
1042 case JAVA_MONITORENTER:
1043 #if defined(ENABLE_THREADS)
1045 bte = builtintable_get_internal(LOCK_monitor_enter);
1046 OP_BUILTIN_CHECK_EXCEPTION(bte);
1051 OP(ICMD_CHECKNULL_POP);
1055 case JAVA_MONITOREXIT:
1056 #if defined(ENABLE_THREADS)
1058 bte = builtintable_get_internal(LOCK_monitor_exit);
1059 OP_BUILTIN_CHECK_EXCEPTION(bte);
1064 OP(ICMD_CHECKNULL_POP);
1068 /* arithmetic instructions that may become builtin functions **********/
1071 #if !SUPPORT_DIVISION
1072 bte = builtintable_get_internal(BUILTIN_idiv);
1073 OP_BUILTIN_ARITHMETIC(opcode, bte);
1080 #if !SUPPORT_DIVISION
1081 bte = builtintable_get_internal(BUILTIN_irem);
1082 OP_BUILTIN_ARITHMETIC(opcode, bte);
1089 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1090 bte = builtintable_get_internal(BUILTIN_ldiv);
1091 OP_BUILTIN_ARITHMETIC(opcode, bte);
1098 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1099 bte = builtintable_get_internal(BUILTIN_lrem);
1100 OP_BUILTIN_ARITHMETIC(opcode, bte);
1107 #if defined(__I386__)
1110 bte = builtintable_get_internal(BUILTIN_frem);
1111 OP_BUILTIN_NO_EXCEPTION(bte);
1116 #if defined(__I386__)
1119 bte = builtintable_get_internal(BUILTIN_drem);
1120 OP_BUILTIN_NO_EXCEPTION(bte);
1125 #if defined(__ALPHA__)
1127 bte = builtintable_get_internal(BUILTIN_f2i);
1128 OP_BUILTIN_NO_EXCEPTION(bte);
1138 #if defined(__ALPHA__)
1140 bte = builtintable_get_internal(BUILTIN_f2l);
1141 OP_BUILTIN_NO_EXCEPTION(bte);
1151 #if defined(__ALPHA__)
1153 bte = builtintable_get_internal(BUILTIN_d2i);
1154 OP_BUILTIN_NO_EXCEPTION(bte);
1164 #if defined(__ALPHA__)
1166 bte = builtintable_get_internal(BUILTIN_d2l);
1167 OP_BUILTIN_NO_EXCEPTION(bte);
1176 /* invalid opcodes ****************************************************/
1178 /* check for invalid opcodes if the verifier is enabled */
1179 #if defined(ENABLE_VERIFIER)
1180 case JAVA_BREAKPOINT:
1181 exceptions_throw_verifyerror(m, "Quick instructions shouldn't appear, yet.");
1184 case 186: /* unused opcode */
1238 exceptions_throw_verifyerror(m, "Illegal opcode %d at instr %d\n",
1242 #endif /* defined(ENABLE_VERIFIER) */
1244 /* opcodes that don't require translation *****************************/
1247 /* straight-forward translation to ICMD */
1253 /* verifier checks ****************************************************/
1255 #if defined(ENABLE_VERIFIER)
1256 /* If WIDE was used correctly, iswide should have been reset by now. */
1258 exceptions_throw_verifyerror(m,
1259 "Illegal instruction: WIDE before incompatible opcode");
1262 #endif /* defined(ENABLE_VERIFIER) */
1266 /*** END OF LOOP **********************************************************/
1268 /* assert that we did not write more ICMDs than allocated */
1270 assert(ipc == (iptr - jd->new_instructions));
1271 assert(ipc <= m->jcodelength);
1273 /*** verifier checks ******************************************************/
1275 #if defined(ENABLE_VERIFIER)
1276 if (p != m->jcodelength) {
1277 exceptions_throw_verifyerror(m,
1278 "Command-sequence crosses code-boundary");
1283 exceptions_throw_verifyerror(m, "Falling off the end of the code");
1286 #endif /* defined(ENABLE_VERIFIER) */
1288 /*** setup the methodinfo, allocate stack and basic blocks ****************/
1290 /* adjust block count if target 0 is not first intermediate instruction */
1292 if (!jd->new_basicblockindex[0] || (jd->new_basicblockindex[0] > 1))
1295 /* copy local to method variables */
1297 jd->new_instructioncount = ipc;
1298 jd->new_basicblockcount = b_count;
1299 jd->new_stackcount = s_count + jd->new_basicblockcount * m->maxstack; /* in-stacks */
1301 /* allocate stack table */
1303 jd->new_stack = DMNEW(stackelement, jd->new_stackcount);
1305 /* build basic block list */
1307 bptr = jd->new_basicblocks = DMNEW(basicblock, b_count + 1); /* one more for end ipc */
1309 /* zero out all basic block structures */
1311 MZERO(bptr, basicblock, b_count + 1);
1314 jd->new_c_debug_nr = 0;
1316 /* additional block if target 0 is not first intermediate instruction */
1318 if (!jd->new_basicblockindex[0] || (jd->new_basicblockindex[0] > 1)) {
1319 BASICBLOCK_INIT(bptr, m);
1321 bptr->iinstr = jd->new_instructions;
1322 /* bptr->icount is set when the next block is allocated */
1326 bptr[-1].next = bptr;
1329 /* allocate blocks */
1331 for (p = 0; p < m->jcodelength; p++) {
1332 if (jd->new_basicblockindex[p] & 1) {
1333 /* Check if this block starts at the beginning of an */
1335 #if defined(ENABLE_VERIFIER)
1336 if (!instructionstart[p]) {
1337 exceptions_throw_verifyerror(m,
1338 "Branch into middle of instruction");
1343 /* allocate the block */
1345 BASICBLOCK_INIT(bptr, m);
1347 bptr->iinstr = jd->new_instructions + (jd->new_basicblockindex[p] >> 1);
1349 bptr[-1].icount = bptr->iinstr - bptr[-1].iinstr;
1351 /* bptr->icount is set when the next block is allocated */
1353 jd->new_basicblockindex[p] = b_count;
1357 bptr[-1].next = bptr;
1361 /* set instruction count of last real block */
1364 bptr[-1].icount = (jd->new_instructions + jd->new_instructioncount) - bptr[-1].iinstr;
1367 /* allocate additional block at end */
1369 BASICBLOCK_INIT(bptr,m);
1371 /* set basicblock pointers in exception table */
1373 if (cd->exceptiontablelength > 0) {
1374 cd->exceptiontable[cd->exceptiontablelength - 1].down = NULL;
1377 for (i = 0; i < cd->exceptiontablelength; ++i) {
1378 p = cd->exceptiontable[i].startpc;
1379 cd->exceptiontable[i].start = jd->new_basicblocks + jd->new_basicblockindex[p];
1381 p = cd->exceptiontable[i].endpc;
1382 cd->exceptiontable[i].end = (p == m->jcodelength) ? (jd->new_basicblocks + jd->new_basicblockcount /*+ 1*/) : (jd->new_basicblocks + jd->new_basicblockindex[p]);
1384 p = cd->exceptiontable[i].handlerpc;
1385 cd->exceptiontable[i].handler = jd->new_basicblocks + jd->new_basicblockindex[p];
1388 /* XXX activate this if you want to try inlining */
1390 for (i = 0; i < m->exceptiontablelength; ++i) {
1391 p = m->exceptiontable[i].startpc;
1392 m->exceptiontable[i].start = jd->new_basicblocks + jd->new_basicblockindex[p];
1394 p = m->exceptiontable[i].endpc;
1395 m->exceptiontable[i].end = (p == m->jcodelength) ? (jd->new_basicblocks + jd->new_basicblockcount /*+ 1*/) : (jd->new_basicblocks + jd->new_basicblockindex[p]);
1397 p = m->exceptiontable[i].handlerpc;
1398 m->exceptiontable[i].handler = jd->new_basicblocks + jd->new_basicblockindex[p];
1402 #if defined(NEW_VAR)
1403 jd->local_map = local_map;
1405 /* calculate local variable renaming */
1415 /* iterate over local_map[0..m->maxlocals*5] and set all existing */
1416 /* index,type pairs (localmap[index*5+type]==1) to an unique value */
1417 /* -> == new local var index */
1418 for(i = 0; i < (m->maxlocals * 5); i++, mapptr++) {
1420 *mapptr = nlocals++;
1422 *mapptr = LOCAL_UNUSED;
1425 jd->localcount = nlocals;
1426 /* if dropped varindices for temp stackslots get reused(?max 2* */
1427 /* m->maxstack elements for stack), nlocals + s_count would be */
1429 jd->varcount = nlocals + s_count +
1430 jd->new_basicblockcount * m->maxstack; /* out-stacks */
1432 jd->var_top = nlocals;
1433 jd->var = DMNEW(varinfo, jd->varcount);
1437 /* everything's ok */
1441 /*** goto labels for throwing verifier exceptions *************************/
1443 #if defined(ENABLE_VERIFIER)
1445 throw_unexpected_end_of_bytecode:
1446 exceptions_throw_verifyerror(m, "Unexpected end of bytecode");
1449 throw_invalid_bytecode_index:
1450 exceptions_throw_verifyerror(m, "Illegal target of branch instruction");
1453 throw_illegal_local_variable_number:
1454 exceptions_throw_verifyerror(m, "Illegal local variable number");
1457 #endif /* ENABLE_VERIFIER */
1462 * These are local overrides for various environment variables in Emacs.
1463 * Please do not remove this and leave it at the end of the file, where
1464 * Emacs will automagically detect them.
1465 * ---------------------------------------------------------------------
1468 * indent-tabs-mode: t
1472 * vim:noexpandtab:sw=4:ts=4: